mirror of
https://github.com/lightbend/config.git
synced 2025-01-28 21:20:07 +08:00
start fixing Token hierarchy by factoring origin() up to base class
This commit is contained in:
parent
7d13a00f7d
commit
81a4fe63f9
@ -69,7 +69,7 @@ final class Parser {
|
||||
}
|
||||
|
||||
if (Tokens.isProblem(t)) {
|
||||
ConfigOrigin origin = Tokens.getProblemOrigin(t);
|
||||
ConfigOrigin origin = t.origin();
|
||||
String message = Tokens.getProblemMessage(t);
|
||||
Throwable cause = Tokens.getProblemCause(t);
|
||||
boolean suggestQuotes = Tokens.getProblemSuggestQuotes(t);
|
||||
@ -102,7 +102,7 @@ final class Parser {
|
||||
while (Tokens.isNewline(t)) {
|
||||
// line number tokens have the line that was _ended_ by the
|
||||
// newline, so we have to add one.
|
||||
lineNumber = Tokens.getLineNumber(t) + 1;
|
||||
lineNumber = t.lineNumber() + 1;
|
||||
t = nextToken();
|
||||
}
|
||||
return t;
|
||||
@ -129,7 +129,7 @@ final class Parser {
|
||||
while (true) {
|
||||
if (Tokens.isNewline(t)) {
|
||||
// newline number is the line just ended, so add one
|
||||
lineNumber = Tokens.getLineNumber(t) + 1;
|
||||
lineNumber = t.lineNumber() + 1;
|
||||
sawSeparatorOrNewline = true;
|
||||
// we want to continue to also eat
|
||||
// a comma if there is one.
|
||||
@ -190,11 +190,11 @@ final class Parser {
|
||||
} else if (Tokens.isUnquotedText(valueToken)) {
|
||||
String text = Tokens.getUnquotedText(valueToken);
|
||||
if (firstOrigin == null)
|
||||
firstOrigin = Tokens.getUnquotedTextOrigin(valueToken);
|
||||
firstOrigin = valueToken.origin();
|
||||
sb.append(text);
|
||||
} else if (Tokens.isSubstitution(valueToken)) {
|
||||
if (firstOrigin == null)
|
||||
firstOrigin = Tokens.getSubstitutionOrigin(valueToken);
|
||||
firstOrigin = valueToken.origin();
|
||||
|
||||
if (sb.length() > 0) {
|
||||
// save string so far
|
||||
@ -204,8 +204,7 @@ final class Parser {
|
||||
// now save substitution
|
||||
List<Token> expression = Tokens
|
||||
.getSubstitutionPathExpression(valueToken);
|
||||
Path path = parsePathExpression(expression.iterator(),
|
||||
Tokens.getSubstitutionOrigin(valueToken));
|
||||
Path path = parsePathExpression(expression.iterator(), valueToken.origin());
|
||||
boolean optional = Tokens.getSubstitutionOptional(valueToken);
|
||||
|
||||
minimized.add(new SubstitutionExpression(path, optional));
|
||||
|
@ -3,24 +3,51 @@
|
||||
*/
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import com.typesafe.config.ConfigException;
|
||||
import com.typesafe.config.ConfigOrigin;
|
||||
|
||||
class Token {
|
||||
final private TokenType tokenType;
|
||||
final private String debugString;
|
||||
final private ConfigOrigin origin;
|
||||
|
||||
Token(TokenType tokenType) {
|
||||
this(tokenType, null);
|
||||
Token(TokenType tokenType, ConfigOrigin origin) {
|
||||
this(tokenType, origin, null);
|
||||
}
|
||||
|
||||
Token(TokenType tokenType, String debugString) {
|
||||
Token(TokenType tokenType, ConfigOrigin origin, String debugString) {
|
||||
this.tokenType = tokenType;
|
||||
this.origin = origin;
|
||||
this.debugString = debugString;
|
||||
}
|
||||
|
||||
// this is used for singleton tokens like COMMA or OPEN_CURLY
|
||||
static Token newWithoutOrigin(TokenType tokenType, String debugString) {
|
||||
return new Token(tokenType, null, debugString);
|
||||
}
|
||||
|
||||
public TokenType tokenType() {
|
||||
final TokenType tokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
// this is final because we don't always use the origin() accessor,
|
||||
// and we don't because it throws if origin is null
|
||||
final ConfigOrigin origin() {
|
||||
// code is only supposed to call origin() on token types that are
|
||||
// expected to have an origin.
|
||||
if (origin == null)
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"tried to get origin from token that doesn't have one: " + this);
|
||||
return origin;
|
||||
}
|
||||
|
||||
final int lineNumber() {
|
||||
if (origin != null)
|
||||
return origin.lineNumber();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (debugString != null)
|
||||
@ -36,6 +63,7 @@ class Token {
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof Token) {
|
||||
// origin is deliberately left out
|
||||
return canEqual(other)
|
||||
&& this.tokenType == ((Token) other).tokenType;
|
||||
} else {
|
||||
@ -45,6 +73,7 @@ class Token {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// origin is deliberately left out
|
||||
return tokenType.hashCode();
|
||||
}
|
||||
}
|
||||
|
@ -479,8 +479,9 @@ final class Tokenizer {
|
||||
return Tokens.END;
|
||||
} else if (c == '\n') {
|
||||
// newline tokens have the just-ended line number
|
||||
Token line = Tokens.newLine(lineOrigin()); // uses lineNumber
|
||||
lineNumber += 1;
|
||||
return Tokens.newLine(lineNumber - 1);
|
||||
return line;
|
||||
} else {
|
||||
Token t = null;
|
||||
switch (c) {
|
||||
|
@ -16,7 +16,7 @@ final class Tokens {
|
||||
final private AbstractConfigValue value;
|
||||
|
||||
Value(AbstractConfigValue value) {
|
||||
super(TokenType.VALUE);
|
||||
super(TokenType.VALUE, value.origin());
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ -46,20 +46,13 @@ final class Tokens {
|
||||
}
|
||||
|
||||
static private class Line extends Token {
|
||||
final private int lineNumber;
|
||||
|
||||
Line(int lineNumber) {
|
||||
super(TokenType.NEWLINE);
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
int lineNumber() {
|
||||
return lineNumber;
|
||||
Line(ConfigOrigin origin) {
|
||||
super(TokenType.NEWLINE, origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "'\n'@" + lineNumber;
|
||||
return "'\n'@" + lineNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -69,31 +62,24 @@ final class Tokens {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return super.equals(other)
|
||||
&& ((Line) other).lineNumber == lineNumber;
|
||||
return super.equals(other) && ((Line) other).lineNumber() == lineNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 41 * (41 + super.hashCode()) + lineNumber;
|
||||
return 41 * (41 + super.hashCode()) + lineNumber();
|
||||
}
|
||||
}
|
||||
|
||||
// This is not a Value, because it requires special processing
|
||||
static private class UnquotedText extends Token {
|
||||
final private ConfigOrigin origin;
|
||||
final private String value;
|
||||
|
||||
UnquotedText(ConfigOrigin origin, String s) {
|
||||
super(TokenType.UNQUOTED_TEXT);
|
||||
this.origin = origin;
|
||||
super(TokenType.UNQUOTED_TEXT, origin);
|
||||
this.value = s;
|
||||
}
|
||||
|
||||
ConfigOrigin origin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
String value() {
|
||||
return value;
|
||||
}
|
||||
@ -121,7 +107,6 @@ final class Tokens {
|
||||
}
|
||||
|
||||
static private class Problem extends Token {
|
||||
final private ConfigOrigin origin;
|
||||
final private String what;
|
||||
final private String message;
|
||||
final private boolean suggestQuotes;
|
||||
@ -129,18 +114,13 @@ final class Tokens {
|
||||
|
||||
Problem(ConfigOrigin origin, String what, String message, boolean suggestQuotes,
|
||||
Throwable cause) {
|
||||
super(TokenType.PROBLEM);
|
||||
this.origin = origin;
|
||||
super(TokenType.PROBLEM, origin);
|
||||
this.what = what;
|
||||
this.message = message;
|
||||
this.suggestQuotes = suggestQuotes;
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
ConfigOrigin origin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
String message() {
|
||||
return message;
|
||||
}
|
||||
@ -189,21 +169,15 @@ final class Tokens {
|
||||
|
||||
// This is not a Value, because it requires special processing
|
||||
static private class Substitution extends Token {
|
||||
final private ConfigOrigin origin;
|
||||
final private boolean optional;
|
||||
final private List<Token> value;
|
||||
|
||||
Substitution(ConfigOrigin origin, boolean optional, List<Token> expression) {
|
||||
super(TokenType.SUBSTITUTION);
|
||||
this.origin = origin;
|
||||
super(TokenType.SUBSTITUTION, origin);
|
||||
this.optional = optional;
|
||||
this.value = expression;
|
||||
}
|
||||
|
||||
ConfigOrigin origin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
boolean optional() {
|
||||
return optional;
|
||||
}
|
||||
@ -259,27 +233,10 @@ final class Tokens {
|
||||
return token instanceof Line;
|
||||
}
|
||||
|
||||
static int getLineNumber(Token token) {
|
||||
if (token instanceof Line) {
|
||||
return ((Line) token).lineNumber();
|
||||
} else {
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"tried to get line number from non-newline " + token);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isProblem(Token token) {
|
||||
return token instanceof Problem;
|
||||
}
|
||||
|
||||
static ConfigOrigin getProblemOrigin(Token token) {
|
||||
if (token instanceof Problem) {
|
||||
return ((Problem) token).origin();
|
||||
} else {
|
||||
throw new ConfigException.BugOrBroken("tried to get problem origin from " + token);
|
||||
}
|
||||
}
|
||||
|
||||
static String getProblemMessage(Token token) {
|
||||
if (token instanceof Problem) {
|
||||
return ((Problem) token).message();
|
||||
@ -318,15 +275,6 @@ final class Tokens {
|
||||
}
|
||||
}
|
||||
|
||||
static ConfigOrigin getUnquotedTextOrigin(Token token) {
|
||||
if (token instanceof UnquotedText) {
|
||||
return ((UnquotedText) token).origin();
|
||||
} else {
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"tried to get unquoted text from " + token);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isSubstitution(Token token) {
|
||||
return token instanceof Substitution;
|
||||
}
|
||||
@ -340,15 +288,6 @@ final class Tokens {
|
||||
}
|
||||
}
|
||||
|
||||
static ConfigOrigin getSubstitutionOrigin(Token token) {
|
||||
if (token instanceof Substitution) {
|
||||
return ((Substitution) token).origin();
|
||||
} else {
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"tried to get substitution origin from " + token);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean getSubstitutionOptional(Token token) {
|
||||
if (token instanceof Substitution) {
|
||||
return ((Substitution) token).optional();
|
||||
@ -358,18 +297,18 @@ final class Tokens {
|
||||
}
|
||||
}
|
||||
|
||||
final static Token START = new Token(TokenType.START, "start of file");
|
||||
final static Token END = new Token(TokenType.END, "end of file");
|
||||
final static Token COMMA = new Token(TokenType.COMMA, "','");
|
||||
final static Token EQUALS = new Token(TokenType.EQUALS, "'='");
|
||||
final static Token COLON = new Token(TokenType.COLON, "':'");
|
||||
final static Token OPEN_CURLY = new Token(TokenType.OPEN_CURLY, "'{'");
|
||||
final static Token CLOSE_CURLY = new Token(TokenType.CLOSE_CURLY, "'}'");
|
||||
final static Token OPEN_SQUARE = new Token(TokenType.OPEN_SQUARE, "'['");
|
||||
final static Token CLOSE_SQUARE = new Token(TokenType.CLOSE_SQUARE, "']'");
|
||||
final static Token START = Token.newWithoutOrigin(TokenType.START, "start of file");
|
||||
final static Token END = Token.newWithoutOrigin(TokenType.END, "end of file");
|
||||
final static Token COMMA = Token.newWithoutOrigin(TokenType.COMMA, "','");
|
||||
final static Token EQUALS = Token.newWithoutOrigin(TokenType.EQUALS, "'='");
|
||||
final static Token COLON = Token.newWithoutOrigin(TokenType.COLON, "':'");
|
||||
final static Token OPEN_CURLY = Token.newWithoutOrigin(TokenType.OPEN_CURLY, "'{'");
|
||||
final static Token CLOSE_CURLY = Token.newWithoutOrigin(TokenType.CLOSE_CURLY, "'}'");
|
||||
final static Token OPEN_SQUARE = Token.newWithoutOrigin(TokenType.OPEN_SQUARE, "'['");
|
||||
final static Token CLOSE_SQUARE = Token.newWithoutOrigin(TokenType.CLOSE_SQUARE, "']'");
|
||||
|
||||
static Token newLine(int lineNumberJustEnded) {
|
||||
return new Line(lineNumberJustEnded);
|
||||
static Token newLine(ConfigOrigin origin) {
|
||||
return new Line(origin);
|
||||
}
|
||||
|
||||
static Token newProblem(ConfigOrigin origin, String what, String message,
|
||||
|
@ -388,6 +388,7 @@ abstract trait TestUtils {
|
||||
def tokenDouble(d: Double) = Tokens.newDouble(fakeOrigin(), d, null)
|
||||
def tokenInt(i: Int) = Tokens.newInt(fakeOrigin(), i, null)
|
||||
def tokenLong(l: Long) = Tokens.newLong(fakeOrigin(), l, null)
|
||||
def tokenLine(line: Int) = Tokens.newLine(fakeOrigin.setLineNumber(line))
|
||||
|
||||
private def tokenMaybeOptionalSubstitution(optional: Boolean, expression: Token*) = {
|
||||
val l = new java.util.ArrayList[Token]
|
||||
|
@ -50,8 +50,8 @@ class TokenTest extends TestUtils {
|
||||
checkEqualObjects(tokenNull, tokenNull)
|
||||
|
||||
// newline
|
||||
checkEqualObjects(Tokens.newLine(10), Tokens.newLine(10))
|
||||
checkNotEqualObjects(Tokens.newLine(10), Tokens.newLine(11))
|
||||
checkEqualObjects(tokenLine(10), tokenLine(10))
|
||||
checkNotEqualObjects(tokenLine(10), tokenLine(11))
|
||||
|
||||
// different types are not equal
|
||||
checkNotEqualObjects(tokenTrue, tokenInt(1))
|
||||
@ -71,7 +71,7 @@ class TokenTest extends TestUtils {
|
||||
tokenUnquoted("foo").toString()
|
||||
tokenString("bar").toString()
|
||||
tokenKeySubstitution("a").toString()
|
||||
Tokens.newLine(10).toString()
|
||||
tokenLine(10).toString()
|
||||
Tokens.START.toString()
|
||||
Tokens.END.toString()
|
||||
Tokens.COLON.toString()
|
||||
|
@ -23,7 +23,7 @@ class TokenizerTest extends TestUtils {
|
||||
|
||||
@Test
|
||||
def tokenizeNewlines() {
|
||||
assertEquals(List(Tokens.START, Tokens.newLine(1), Tokens.newLine(2), Tokens.END),
|
||||
assertEquals(List(Tokens.START, tokenLine(1), tokenLine(2), Tokens.END),
|
||||
tokenizeAsList("\n\n"))
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ class TokenizerTest extends TestUtils {
|
||||
tokenTrue, tokenDouble(3.14), tokenFalse,
|
||||
tokenLong(42), tokenNull, tokenSubstitution(tokenUnquoted("a.b")),
|
||||
tokenOptionalSubstitution(tokenUnquoted("x.y")),
|
||||
tokenKeySubstitution("c.d"), Tokens.newLine(1), Tokens.END)
|
||||
tokenKeySubstitution("c.d"), tokenLine(1), Tokens.END)
|
||||
assertEquals(expected, tokenizeAsList(""",:=}{]["foo"true3.14false42null${a.b}${?x.y}${"c.d"}""" + "\n"))
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ class TokenizerTest extends TestUtils {
|
||||
tokenUnquoted(" "), tokenSubstitution(tokenUnquoted("a.b")), tokenUnquoted(" "),
|
||||
tokenOptionalSubstitution(tokenUnquoted("x.y")), tokenUnquoted(" "),
|
||||
tokenKeySubstitution("c.d"),
|
||||
Tokens.newLine(1), Tokens.END)
|
||||
tokenLine(1), Tokens.END)
|
||||
assertEquals(expected, tokenizeAsList(""" , : = } { ] [ "foo" 42 true 3.14 false null ${a.b} ${?x.y} ${"c.d"} """ + "\n "))
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ class TokenizerTest extends TestUtils {
|
||||
tokenUnquoted(" "), tokenSubstitution(tokenUnquoted("a.b")), tokenUnquoted(" "),
|
||||
tokenOptionalSubstitution(tokenUnquoted("x.y")), tokenUnquoted(" "),
|
||||
tokenKeySubstitution("c.d"),
|
||||
Tokens.newLine(1), Tokens.END)
|
||||
tokenLine(1), Tokens.END)
|
||||
assertEquals(expected, tokenizeAsList(""" , : = } { ] [ "foo" 42 true 3.14 false null ${a.b} ${?x.y} ${"c.d"} """ + "\n "))
|
||||
}
|
||||
|
||||
@ -113,14 +113,14 @@ class TokenizerTest extends TestUtils {
|
||||
|
||||
@Test
|
||||
def tokenizeUnquotedTextTrimsSpaces() {
|
||||
val expected = List(Tokens.START, tokenUnquoted("foo"), Tokens.newLine(1), Tokens.END)
|
||||
val expected = List(Tokens.START, tokenUnquoted("foo"), tokenLine(1), Tokens.END)
|
||||
assertEquals(expected, tokenizeAsList(" foo \n"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def tokenizeUnquotedTextKeepsInternalSpaces() {
|
||||
val expected = List(Tokens.START, tokenUnquoted("foo"), tokenUnquoted(" "), tokenUnquoted("bar"),
|
||||
tokenUnquoted(" "), tokenUnquoted("baz"), Tokens.newLine(1), Tokens.END)
|
||||
tokenUnquoted(" "), tokenUnquoted("baz"), tokenLine(1), Tokens.END)
|
||||
assertEquals(expected, tokenizeAsList(" foo bar baz \n"))
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ class TokenizerTest extends TestUtils {
|
||||
def tokenizeMixedUnquotedQuoted() {
|
||||
val expected = List(Tokens.START, tokenUnquoted("foo"),
|
||||
tokenString("bar"), tokenUnquoted("baz"),
|
||||
Tokens.newLine(1), Tokens.END)
|
||||
tokenLine(1), Tokens.END)
|
||||
assertEquals(expected, tokenizeAsList(" foo\"bar\"baz \n"))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user