bazel syntax: make Node.lnt final; pass LineNumberTable as ctor param
Also:
- make the field package-private (again). Unlike protected, this does not
expose the existence of the field in the Javadoc.
- rename 'LineNumberTable lnt' to 'FileLocations locs'.
- change Comment.text to include the leading # (to match its start-end range).
PiperOrigin-RevId: 305897033
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Argument.java b/src/main/java/com/google/devtools/build/lib/syntax/Argument.java
index 37d2738..b80a2fe 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Argument.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Argument.java
@@ -26,7 +26,8 @@
protected final Expression value;
- Argument(Expression value) {
+ Argument(FileLocations locs, Expression value) {
+ super(locs);
this.value = Preconditions.checkNotNull(value);
}
@@ -47,8 +48,8 @@
/** Syntax node for a positional argument, {@code f(expr)}. */
public static final class Positional extends Argument {
- Positional(Expression value) {
- super(value);
+ Positional(FileLocations locs, Expression value) {
+ super(locs, value);
}
@Override
@@ -65,8 +66,8 @@
final Identifier id;
- Keyword(Identifier id, Expression value) {
- super(value);
+ Keyword(FileLocations locs, Identifier id, Expression value) {
+ super(locs, value);
this.id = id;
}
@@ -89,8 +90,8 @@
public static final class Star extends Argument {
private final int starOffset;
- Star(int starOffset, Expression value) {
- super(value);
+ Star(FileLocations locs, int starOffset, Expression value) {
+ super(locs, value);
this.starOffset = starOffset;
}
@@ -104,8 +105,8 @@
public static final class StarStar extends Argument {
private final int starStarOffset;
- StarStar(int starStarOffset, Expression value) {
- super(value);
+ StarStar(FileLocations locs, int starStarOffset, Expression value) {
+ super(locs, value);
this.starStarOffset = starStarOffset;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/AssignmentStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/AssignmentStatement.java
index 2b56c7c..edefa52 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/AssignmentStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/AssignmentStatement.java
@@ -33,7 +33,9 @@
* {@code (e, ...)}, where x, i, and e are arbitrary expressions. For an augmented assignment, the
* list and tuple forms are disallowed.
*/
- AssignmentStatement(Expression lhs, @Nullable TokenKind op, int opOffset, Expression rhs) {
+ AssignmentStatement(
+ FileLocations locs, Expression lhs, @Nullable TokenKind op, int opOffset, Expression rhs) {
+ super(locs);
this.lhs = lhs;
this.op = op;
this.opOffset = opOffset;
@@ -53,7 +55,7 @@
/** Returns the location of the assignment operator. */
public Location getOperatorLocation() {
- return lnt.getLocation(opOffset);
+ return locs.getLocation(opOffset);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BUILD b/src/main/java/com/google/devtools/build/lib/syntax/BUILD
index 9833bde..972c5b4 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BUILD
@@ -41,6 +41,7 @@
"DotExpression.java",
"Expression.java",
"ExpressionStatement.java",
+ "FileLocations.java",
"FileOptions.java",
"FlowStatement.java",
"ForStatement.java",
@@ -50,7 +51,6 @@
"IndexExpression.java",
"IntegerLiteral.java",
"Lexer.java",
- "LineNumberTable.java",
"ListExpression.java",
"LoadStatement.java",
"Location.java",
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
index aa0de06..066e908 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
@@ -44,7 +44,9 @@
TokenKind.PIPE,
TokenKind.STAR);
- BinaryOperatorExpression(Expression x, TokenKind op, int opOffset, Expression y) {
+ BinaryOperatorExpression(
+ FileLocations locs, Expression x, TokenKind op, int opOffset, Expression y) {
+ super(locs);
this.x = x;
this.op = op;
this.opOffset = opOffset;
@@ -62,7 +64,7 @@
}
public Location getOperatorLocation() {
- return lnt.getLocation(opOffset);
+ return locs.getLocation(opOffset);
}
/** Returns the right operand. */
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/CallExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/CallExpression.java
index 64af972..128bd5f 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/CallExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/CallExpression.java
@@ -28,10 +28,12 @@
private final int numPositionalArgs;
CallExpression(
+ FileLocations locs,
Expression function,
Location lparenLocation,
ImmutableList<Argument> arguments,
int rparenOffset) {
+ super(locs);
this.function = Preconditions.checkNotNull(function);
this.lparenLocation = lparenLocation;
this.arguments = arguments;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Comment.java b/src/main/java/com/google/devtools/build/lib/syntax/Comment.java
index ee7d6a7..2af98f9 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Comment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Comment.java
@@ -20,11 +20,13 @@
private final int offset;
private final String text;
- Comment(int offset, String text) {
+ Comment(FileLocations locs, int offset, String text) {
+ super(locs);
this.offset = offset;
this.text = text;
}
+ /** Returns the text of the comment, including the leading '#' but not the trailing newline. */
public String getText() {
return text;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Comprehension.java b/src/main/java/com/google/devtools/build/lib/syntax/Comprehension.java
index 4549bbc..3444930 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Comprehension.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Comprehension.java
@@ -37,7 +37,11 @@
public final class Comprehension extends Expression {
/** For or If */
- public abstract static class Clause extends Node {}
+ public abstract static class Clause extends Node {
+ Clause(FileLocations locs) {
+ super(locs);
+ }
+ }
/** A for clause in a comprehension, e.g. "for a in b" in the example above. */
public static final class For extends Clause {
@@ -45,7 +49,8 @@
private final Expression vars;
private final Expression iterable;
- For(int forOffset, Expression vars, Expression iterable) {
+ For(FileLocations locs, int forOffset, Expression vars, Expression iterable) {
+ super(locs);
this.forOffset = forOffset;
this.vars = vars;
this.iterable = iterable;
@@ -80,7 +85,8 @@
private final int ifOffset;
private final Expression condition;
- If(int ifOffset, Expression condition) {
+ If(FileLocations locs, int ifOffset, Expression condition) {
+ super(locs);
this.ifOffset = ifOffset;
this.condition = condition;
}
@@ -112,11 +118,13 @@
private final int rbracketOffset;
Comprehension(
+ FileLocations locs,
boolean isDict,
int lbracketOffset,
Node body,
ImmutableList<Clause> clauses,
int rbracketOffset) {
+ super(locs);
this.isDict = isDict;
this.lbracketOffset = lbracketOffset;
this.body = body;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java
index 8085d55..973eedc 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java
@@ -33,7 +33,8 @@
}
/** Constructor for a conditional expression */
- ConditionalExpression(Expression t, Expression cond, Expression f) {
+ ConditionalExpression(FileLocations locs, Expression t, Expression cond, Expression f) {
+ super(locs);
this.t = t;
this.cond = cond;
this.f = f;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/DefStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/DefStatement.java
index d128c0e..342f0ac 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/DefStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/DefStatement.java
@@ -26,11 +26,13 @@
private final ImmutableList<Parameter> parameters;
DefStatement(
+ FileLocations locs,
int defOffset,
Identifier identifier,
ImmutableList<Parameter> parameters,
FunctionSignature signature,
ImmutableList<Statement> body) {
+ super(locs);
this.defOffset = defOffset;
this.identifier = identifier;
this.parameters = Preconditions.checkNotNull(parameters);
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/DictExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/DictExpression.java
index c144d4a7..fdb5346 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/DictExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/DictExpression.java
@@ -26,7 +26,8 @@
private final int colonOffset;
private final Expression value;
- Entry(Expression key, int colonOffset, Expression value) {
+ Entry(FileLocations locs, Expression key, int colonOffset, Expression value) {
+ super(locs);
this.key = key;
this.colonOffset = colonOffset;
this.value = value;
@@ -51,7 +52,7 @@
}
public Location getColonLocation() {
- return lnt.getLocation(colonOffset);
+ return locs.getLocation(colonOffset);
}
@Override
@@ -64,7 +65,8 @@
private final ImmutableList<Entry> entries;
private final int rbraceOffset;
- DictExpression(int lbraceOffset, List<Entry> entries, int rbraceOffset) {
+ DictExpression(FileLocations locs, int lbraceOffset, List<Entry> entries, int rbraceOffset) {
+ super(locs);
this.lbraceOffset = lbraceOffset;
this.entries = ImmutableList.copyOf(entries);
this.rbraceOffset = rbraceOffset;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java
index 65b2048..9e7a541 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/DotExpression.java
@@ -21,7 +21,8 @@
private final int dotOffset;
private final Identifier field;
- DotExpression(Expression object, int dotOffset, Identifier field) {
+ DotExpression(FileLocations locs, Expression object, int dotOffset, Identifier field) {
+ super(locs);
this.object = object;
this.dotOffset = dotOffset;
this.field = field;
@@ -46,7 +47,7 @@
}
public Location getDotLocation() {
- return lnt.getLocation(dotOffset);
+ return locs.getLocation(dotOffset);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Expression.java b/src/main/java/com/google/devtools/build/lib/syntax/Expression.java
index cb1cb3d..2206d79 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Expression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Expression.java
@@ -45,6 +45,10 @@
UNARY_OPERATOR,
}
+ Expression(FileLocations locs) {
+ super(locs);
+ }
+
/**
* Kind of the expression. This is similar to using instanceof, except that it's more efficient
* and can be used in a switch/case.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ExpressionStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/ExpressionStatement.java
index 8e54ff0..32d3b26 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ExpressionStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ExpressionStatement.java
@@ -19,7 +19,8 @@
private final Expression expression;
- ExpressionStatement(Expression expression) {
+ ExpressionStatement(FileLocations locs, Expression expression) {
+ super(locs);
this.expression = expression;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java b/src/main/java/com/google/devtools/build/lib/syntax/FileLocations.java
similarity index 75%
rename from src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
rename to src/main/java/com/google/devtools/build/lib/syntax/FileLocations.java
index 9c89581..5dd1735 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/FileLocations.java
@@ -22,40 +22,32 @@
import java.util.Objects;
/**
- * A LineNumberTable maps each UTF-16 index within a source file to its (file, line, column) triple.
- * An offset is valid if {@code 0 <= offset <= size}.
+ * FileLocations maps each source offset within a file to a Location. An offset is a (UTF-16) char
+ * index such that {@code 0 <= offset <= size}. A Location is a (file, line, column) triple.
*/
@AutoCodec
@Immutable
-// TODO(adonovan): rename to FileLocations.
-final class LineNumberTable {
+final class FileLocations {
- private static final Interner<LineNumberTable> LINE_NUMBER_TABLE_INTERNER =
- BlazeInterners.newWeakInterner();
+ private static final Interner<FileLocations> INTERNER = BlazeInterners.newWeakInterner();
- /** A mapping from line number (line >= 1) to character offset into the file. */
- private final int[] linestart;
-
+ private final int[] linestart; // maps line number (line >= 1) to char offset
private final String file;
private final int size; // size of file in chars
- private LineNumberTable(char[] buffer, String file) {
- this(computeLinestart(buffer), file, buffer.length);
- }
-
- private LineNumberTable(int[] linestart, String file, int size) {
+ private FileLocations(int[] linestart, String file, int size) {
this.linestart = linestart;
this.file = file;
this.size = size;
}
@AutoCodec.Instantiator
- static LineNumberTable createForSerialization(int[] linestart, String file, int size) {
- return LINE_NUMBER_TABLE_INTERNER.intern(new LineNumberTable(linestart, file, size));
+ static FileLocations createForSerialization(int[] linestart, String file, int size) {
+ return INTERNER.intern(new FileLocations(linestart, file, size));
}
- static LineNumberTable create(char[] buffer, String file) {
- return new LineNumberTable(buffer, file);
+ static FileLocations create(char[] buffer, String file) {
+ return new FileLocations(computeLinestart(buffer), file, buffer.length);
}
private int getLineAt(int offset) {
@@ -98,10 +90,10 @@
@Override
public boolean equals(Object other) {
- if (!(other instanceof LineNumberTable)) {
+ if (!(other instanceof FileLocations)) {
return false;
}
- LineNumberTable that = (LineNumberTable) other;
+ FileLocations that = (FileLocations) other;
return this.size == that.size
&& Arrays.equals(this.linestart, that.linestart)
&& this.file.equals(that.file);
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java
index 1637934..4013668 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/FlowStatement.java
@@ -21,7 +21,8 @@
private final int offset;
/** @param kind The label of the statement (break, continue, or pass) */
- FlowStatement(TokenKind kind, int offset) {
+ FlowStatement(FileLocations locs, TokenKind kind, int offset) {
+ super(locs);
this.kind = kind;
this.offset = offset;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ForStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/ForStatement.java
index 9b3fdb9..525379f 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ForStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ForStatement.java
@@ -26,7 +26,13 @@
private final ImmutableList<Statement> block; // non-empty if well formed
/** Constructs a for loop statement. */
- ForStatement(int forOffset, Expression lhs, Expression collection, List<Statement> block) {
+ ForStatement(
+ FileLocations locs,
+ int forOffset,
+ Expression lhs,
+ Expression collection,
+ List<Statement> block) {
+ super(locs);
this.forOffset = forOffset;
this.lhs = Preconditions.checkNotNull(lhs);
this.collection = Preconditions.checkNotNull(collection);
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java b/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java
index 70af64e..a253c9d 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Identifier.java
@@ -33,7 +33,8 @@
// ValidationEnvironment.
@Nullable private ValidationEnvironment.Scope scope;
- Identifier(String name, int nameOffset) {
+ Identifier(FileLocations locs, String name, int nameOffset) {
+ super(locs);
this.name = name;
this.nameOffset = nameOffset;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java
index 5769057..931d12c 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java
@@ -27,7 +27,13 @@
private final ImmutableList<Statement> thenBlock; // non-empty
@Nullable ImmutableList<Statement> elseBlock; // non-empty if non-null; set after construction
- IfStatement(TokenKind token, int ifOffset, Expression condition, List<Statement> thenBlock) {
+ IfStatement(
+ FileLocations locs,
+ TokenKind token,
+ int ifOffset,
+ Expression condition,
+ List<Statement> thenBlock) {
+ super(locs);
this.token = token;
this.ifOffset = ifOffset;
this.condition = condition;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/IndexExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/IndexExpression.java
index c5c9c8c..6baf1b5 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/IndexExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/IndexExpression.java
@@ -26,7 +26,13 @@
private final Expression key;
private final int rbracketOffset;
- IndexExpression(Expression object, int lbracketOffset, Expression key, int rbracketOffset) {
+ IndexExpression(
+ FileLocations locs,
+ Expression object,
+ int lbracketOffset,
+ Expression key,
+ int rbracketOffset) {
+ super(locs);
this.object = object;
this.lbracketOffset = lbracketOffset;
this.key = key;
@@ -52,7 +58,7 @@
}
public Location getLbracketLocation() {
- return lnt.getLocation(lbracketOffset);
+ return locs.getLocation(lbracketOffset);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/IntegerLiteral.java b/src/main/java/com/google/devtools/build/lib/syntax/IntegerLiteral.java
index d5ae4ec..415d8d2 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/IntegerLiteral.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/IntegerLiteral.java
@@ -20,7 +20,8 @@
private final int tokenOffset;
private final int value;
- IntegerLiteral(String raw, int tokenOffset, int value) {
+ IntegerLiteral(FileLocations locs, String raw, int tokenOffset, int value) {
+ super(locs);
this.raw = raw;
this.tokenOffset = tokenOffset;
this.value = value;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
index 9ec6be3..9a87e7a 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
@@ -28,7 +28,7 @@
// --- These fields are accessed directly by the parser: ---
// Mapping from file offsets to Locations.
- final LineNumberTable lnt;
+ final FileLocations locs;
// Information about current token. Updated by nextToken.
// raw and value are defined only for STRING, INT, IDENTIFIER, and COMMENT.
@@ -87,7 +87,7 @@
// Constructs a lexer which tokenizes the parser input.
// Errors are appended to errors.
Lexer(ParserInput input, FileOptions options, List<SyntaxError> errors) {
- this.lnt = LineNumberTable.create(input.getContent(), input.getFile());
+ this.locs = FileLocations.create(input.getContent(), input.getFile());
this.options = options;
this.buffer = input.getContent();
this.pos = 0;
@@ -128,7 +128,7 @@
}
private void error(String message, int pos) {
- errors.add(new SyntaxError(lnt.getLocation(pos), message));
+ errors.add(new SyntaxError(locs.getLocation(pos), message));
}
private void setToken(TokenKind kind, int left, int right) {
@@ -867,8 +867,6 @@
// TODO(adonovan): don't retain comments unconditionally.
private void addComment(int start, int end) {
String content = bufferSlice(start, end);
- Comment c = new Comment(start, content);
- c.lnt = lnt;
- comments.add(c);
+ comments.add(new Comment(locs, start, content));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ListExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/ListExpression.java
index 7a4ef85..7704259 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ListExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ListExpression.java
@@ -29,7 +29,12 @@
private final int rbracketOffset; // -1 => unparenthesized non-empty tuple
ListExpression(
- boolean isTuple, int lbracketOffset, List<Expression> elements, int rbracketOffset) {
+ FileLocations locs,
+ boolean isTuple,
+ int lbracketOffset,
+ List<Expression> elements,
+ int rbracketOffset) {
+ super(locs);
// An unparenthesized tuple must be non-empty.
Preconditions.checkArgument(
!elements.isEmpty() || (lbracketOffset >= 0 && rbracketOffset >= 0));
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/LoadStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/LoadStatement.java
index 765f923..3d5d135 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/LoadStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/LoadStatement.java
@@ -47,7 +47,12 @@
private final int rparenOffset;
LoadStatement(
- int loadOffset, StringLiteral module, ImmutableList<Binding> bindings, int rparenOffset) {
+ FileLocations locs,
+ int loadOffset,
+ StringLiteral module,
+ ImmutableList<Binding> bindings,
+ int rparenOffset) {
+ super(locs);
this.loadOffset = loadOffset;
this.module = module;
this.bindings = bindings;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Node.java b/src/main/java/com/google/devtools/build/lib/syntax/Node.java
index b761590..e89bc1a 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Node.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Node.java
@@ -14,6 +14,8 @@
package com.google.devtools.build.lib.syntax;
+import com.google.common.base.Preconditions;
+
/**
* A Node is a node in a Starlark syntax tree.
*
@@ -59,13 +61,14 @@
// 1.0% Comprehension
// 6 % all others
- // The LNT holds the file name and a compressed mapping from
- // token char offsets to Locations. It is shared by all nodes
- // from the same file. For convenience of the parser, it is
- // set immediately after construction.
- protected LineNumberTable lnt;
+ // The FileLocations table holds the file name and a compressed
+ // mapping from token char offsets to Locations.
+ // It is shared by all nodes from the same file.
+ final FileLocations locs;
- Node() {}
+ Node(FileLocations locs) {
+ this.locs = Preconditions.checkNotNull(locs);
+ }
/**
* Returns the node's start offset, as a char index (zero-based count of UTF-16 codes) from the
@@ -75,7 +78,7 @@
/** Returns the location of the start of this syntax node. */
public final Location getStartLocation() {
- return lnt.getLocation(getStartOffset());
+ return locs.getLocation(getStartOffset());
}
/** Returns the char offset of the source position immediately after this syntax node. */
@@ -83,7 +86,7 @@
/** Returns the location of the source position immediately after this syntax node. */
public final Location getEndLocation() {
- return lnt.getLocation(getEndOffset());
+ return locs.getLocation(getEndOffset());
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/NodePrinter.java b/src/main/java/com/google/devtools/build/lib/syntax/NodePrinter.java
index 934d3b2..ef8d9ae 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/NodePrinter.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/NodePrinter.java
@@ -55,7 +55,6 @@
// of StarlarkFile. So don't bother word-wrapping and just print
// it on a single line.
printIndent();
- buf.append("# ");
buf.append(comment.getText());
} else if (n instanceof Argument) {
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java b/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java
index 21422d5..5c92f0c 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parameter.java
@@ -31,7 +31,8 @@
@Nullable private final Identifier id;
- private Parameter(@Nullable Identifier id) {
+ private Parameter(FileLocations locs, @Nullable Identifier id) {
+ super(locs);
this.id = id;
}
@@ -55,8 +56,8 @@
* depending on its position.
*/
public static final class Mandatory extends Parameter {
- Mandatory(Identifier id) {
- super(id);
+ Mandatory(FileLocations locs, Identifier id) {
+ super(locs, id);
}
@Override
@@ -78,8 +79,8 @@
public final Expression defaultValue;
- Optional(Identifier id, @Nullable Expression defaultValue) {
- super(id);
+ Optional(FileLocations locs, Identifier id, @Nullable Expression defaultValue) {
+ super(locs, id);
this.defaultValue = defaultValue;
}
@@ -109,8 +110,8 @@
public static final class Star extends Parameter {
private final int starOffset;
- Star(int starOffset, @Nullable Identifier id) {
- super(id);
+ Star(FileLocations locs, int starOffset, @Nullable Identifier id) {
+ super(locs, id);
this.starOffset = starOffset;
}
@@ -129,8 +130,8 @@
public static final class StarStar extends Parameter {
private final int starStarOffset;
- StarStar(int starStarOffset, Identifier id) {
- super(id);
+ StarStar(FileLocations locs, int starStarOffset, Identifier id) {
+ super(locs, id);
this.starStarOffset = starStarOffset;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index 62e2e7e..8eb169e 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -33,7 +33,7 @@
/** Combines the parser result into a single value object. */
static final class ParseResult {
// Maps char offsets in the file to Locations.
- final LineNumberTable lnt;
+ final FileLocations locs;
/** The statements (rules, basically) from the parsed file. */
final List<Statement> statements;
@@ -46,11 +46,11 @@
final List<SyntaxError> errors;
ParseResult(
- LineNumberTable lnt,
+ FileLocations locs,
List<Statement> statements,
List<Comment> comments,
List<SyntaxError> errors) {
- this.lnt = lnt;
+ this.locs = locs;
// No need to copy here; when the object is created, the parser instance is just about to go
// out of scope and be garbage collected.
this.statements = Preconditions.checkNotNull(statements);
@@ -97,6 +97,7 @@
private static final boolean DEBUGGING = false;
private final Lexer lexer;
+ private final FileLocations locs;
private final List<SyntaxError> errors;
// TODO(adonovan): opt: compute this by subtraction.
@@ -148,6 +149,7 @@
private Parser(Lexer lexer, List<SyntaxError> errors) {
this.lexer = lexer;
+ this.locs = lexer.locs;
this.errors = errors;
this.token = lexer;
nextToken();
@@ -175,7 +177,7 @@
Profiler.instance().profile(ProfilerTask.STARLARK_PARSER, input.getFile())) {
statements = parser.parseFileInput();
}
- return new ParseResult(lexer.lnt, statements, lexer.getComments(), errors);
+ return new ParseResult(lexer.locs, statements, lexer.getComments(), errors);
}
// stmt = simple_stmt
@@ -228,14 +230,14 @@
List<Expression> elems = new ArrayList<>();
elems.add(e);
parseExprList(elems, /*trailingCommaAllowed=*/ false);
- return setLNT(new ListExpression(/*isTuple=*/ true, -1, elems, -1));
+ return new ListExpression(locs, /*isTuple=*/ true, -1, elems, -1);
}
private void reportError(int offset, String message) {
errorsCount++;
// Limit the number of reported errors to avoid spamming output.
if (errorsCount <= 5) {
- Location location = lexer.lnt.getLocation(offset);
+ Location location = locs.getLocation(offset);
errors.add(new SyntaxError(location, message));
}
}
@@ -367,16 +369,9 @@
// It's tempting to define a dedicated BadExpression type,
// but it is convenient for parseIdent to return an Identifier
// even when it fails.
- return setLNT(new Identifier(lexer.bufferSlice(start, end), start));
+ return new Identifier(locs, lexer.bufferSlice(start, end), start);
}
- // setLNT sets the LineNumberTable associated with a newly created Node.
- // TODO(adonovan): experiment with making this an explicit parameter
- // to all Node subclass constructors.
- private <N extends Node> N setLNT(N n) {
- n.lnt = lexer.lnt;
- return n;
- }
// arg = IDENTIFIER '=' test
// | expr
@@ -389,14 +384,14 @@
if (token.kind == TokenKind.STAR_STAR) {
int starStarOffset = nextToken();
expr = parseTest();
- return setLNT(new Argument.StarStar(starStarOffset, expr));
+ return new Argument.StarStar(locs, starStarOffset, expr);
}
// parse *expr
if (token.kind == TokenKind.STAR) {
int starOffset = nextToken();
expr = parseTest();
- return setLNT(new Argument.Star(starOffset, expr));
+ return new Argument.Star(locs, starOffset, expr);
}
// IDENTIFIER or IDENTIFIER = test
@@ -407,12 +402,12 @@
if (token.kind == TokenKind.EQUALS) {
nextToken();
Expression arg = parseTest();
- return setLNT(new Argument.Keyword(id, arg));
+ return new Argument.Keyword(locs, id, arg);
}
}
// parse a positional argument
- return setLNT(new Argument.Positional(expr));
+ return new Argument.Positional(locs, expr);
}
// arg = IDENTIFIER '=' test
@@ -422,7 +417,7 @@
if (token.kind == TokenKind.STAR_STAR) {
int starStarOffset = nextToken();
Identifier id = parseIdent();
- return setLNT(new Parameter.StarStar(starStarOffset, id));
+ return new Parameter.StarStar(locs, starStarOffset, id);
}
// * or *args
@@ -430,9 +425,9 @@
int starOffset = nextToken();
if (token.kind == TokenKind.IDENTIFIER) {
Identifier id = parseIdent();
- return setLNT(new Parameter.Star(starOffset, id));
+ return new Parameter.Star(locs, starOffset, id);
}
- return setLNT(new Parameter.Star(starOffset, null));
+ return new Parameter.Star(locs, starOffset, null);
}
// name=default
@@ -440,11 +435,11 @@
if (token.kind == TokenKind.EQUALS) {
nextToken(); // TODO: save token pos?
Expression expr = parseTest();
- return setLNT(new Parameter.Optional(id, expr));
+ return new Parameter.Optional(locs, id, expr);
}
// name
- return setLNT(new Parameter.Mandatory(id));
+ return new Parameter.Mandatory(locs, id);
}
// call_suffix = '(' arg_list? ')'
@@ -455,7 +450,7 @@
args = parseArguments(); // (includes optional trailing comma)
}
int rparenOffset = expect(TokenKind.RPAREN);
- return setLNT(new CallExpression(fn, lexer.lnt.getLocation(lparenOffset), args, rparenOffset));
+ return new CallExpression(locs, fn, locs.getLocation(lparenOffset), args, rparenOffset);
}
// Parse a list of call arguments.
@@ -548,7 +543,7 @@
int dotOffset = expect(TokenKind.DOT);
if (token.kind == TokenKind.IDENTIFIER) {
Identifier id = parseIdent();
- return setLNT(new DotExpression(e, dotOffset, id));
+ return new DotExpression(locs, e, dotOffset, id);
}
syntaxError("expected identifier after dot");
@@ -595,14 +590,14 @@
Expression key = parseTest();
int colonOffset = expect(TokenKind.COLON);
Expression value = parseTest();
- return setLNT(new DictExpression.Entry(key, colonOffset, value));
+ return new DictExpression.Entry(locs, key, colonOffset, value);
}
// expr = STRING
private StringLiteral parseStringLiteral() {
Preconditions.checkState(token.kind == TokenKind.STRING);
StringLiteral literal =
- setLNT(new StringLiteral(token.left, intern((String) token.value), token.right));
+ new StringLiteral(locs, token.left, intern((String) token.value), token.right);
nextToken();
if (token.kind == TokenKind.STRING) {
reportError(token.left, "Implicit string concatenation is forbidden, use the + operator");
@@ -623,7 +618,7 @@
case INT:
{
IntegerLiteral literal =
- setLNT(new IntegerLiteral(token.raw, token.left, (Integer) token.value));
+ new IntegerLiteral(locs, token.raw, token.left, (Integer) token.value);
nextToken();
return literal;
}
@@ -647,8 +642,8 @@
// empty tuple: ()
if (token.kind == TokenKind.RPAREN) {
int rparen = nextToken();
- return setLNT(
- new ListExpression(/*isTuple=*/ true, lparenOffset, ImmutableList.of(), rparen));
+ return new ListExpression(
+ locs, /*isTuple=*/ true, lparenOffset, ImmutableList.of(), rparen);
}
Expression e = parseTest();
@@ -666,7 +661,7 @@
elems.add(e);
parseExprList(elems, /*trailingCommaAllowed=*/ true);
int rparenOffset = expect(TokenKind.RPAREN);
- return setLNT(new ListExpression(/*isTuple=*/ true, lparenOffset, elems, rparenOffset));
+ return new ListExpression(locs, /*isTuple=*/ true, lparenOffset, elems, rparenOffset);
}
expect(TokenKind.RPAREN);
@@ -681,7 +676,7 @@
TokenKind op = token.kind;
int offset = nextToken();
Expression x = parsePrimaryWithSuffix();
- return setLNT(new UnaryOperatorExpression(op, offset, x));
+ return new UnaryOperatorExpression(locs, op, offset, x);
}
default:
@@ -725,7 +720,7 @@
// index x[i]
if (token.kind == TokenKind.RBRACKET) {
int rbracketOffset = expect(TokenKind.RBRACKET);
- return setLNT(new IndexExpression(e, lbracketOffset, start, rbracketOffset));
+ return new IndexExpression(locs, e, lbracketOffset, start, rbracketOffset);
}
}
@@ -741,7 +736,7 @@
}
}
int rbracketOffset = expect(TokenKind.RBRACKET);
- return setLNT(new SliceExpression(e, lbracketOffset, start, end, step, rbracketOffset));
+ return new SliceExpression(locs, e, lbracketOffset, start, end, step, rbracketOffset);
}
// Equivalent to 'exprlist' rule in Python grammar.
@@ -764,7 +759,7 @@
}
elems.add(parsePrimaryWithSuffix());
}
- return setLNT(new ListExpression(/*isTuple=*/ true, -1, elems, -1));
+ return new ListExpression(locs, /*isTuple=*/ true, -1, elems, -1);
}
// comprehension_suffix = 'FOR' loop_variables 'IN' expr comprehension_suffix
@@ -780,13 +775,13 @@
// The expression cannot be a ternary expression ('x if y else z') due to
// conflicts in Python grammar ('if' is used by the comprehension).
Expression seq = parseTest(0);
- clauses.add(setLNT(new Comprehension.For(forOffset, vars, seq)));
+ clauses.add(new Comprehension.For(locs, forOffset, vars, seq));
} else if (token.kind == TokenKind.IF) {
int ifOffset = nextToken();
// [x for x in li if 1, 2] # parse error
// [x for x in li if (1, 2)] # ok
Expression cond = parseTest(0);
- clauses.add(setLNT(new Comprehension.If(ifOffset, cond)));
+ clauses.add(new Comprehension.If(locs, ifOffset, cond));
} else if (token.kind == closingBracket) {
break;
} else {
@@ -798,7 +793,7 @@
boolean isDict = closingBracket == TokenKind.RBRACE;
int roffset = expect(closingBracket);
- return setLNT(new Comprehension(isDict, loffset, body, clauses.build(), roffset));
+ return new Comprehension(locs, isDict, loffset, body, clauses.build(), roffset);
}
// list_maker = '[' ']'
@@ -809,9 +804,8 @@
int lbracketOffset = expect(TokenKind.LBRACKET);
if (token.kind == TokenKind.RBRACKET) { // empty List
int rbracketOffset = nextToken();
- return setLNT(
- new ListExpression(
- /*isTuple=*/ false, lbracketOffset, ImmutableList.of(), rbracketOffset));
+ return new ListExpression(
+ locs, /*isTuple=*/ false, lbracketOffset, ImmutableList.of(), rbracketOffset);
}
Expression expression = parseTest();
@@ -820,12 +814,12 @@
// [e], singleton list
{
int rbracketOffset = nextToken();
- return setLNT(
- new ListExpression(
- /*isTuple=*/ false,
- lbracketOffset,
- ImmutableList.of(expression),
- rbracketOffset));
+ return new ListExpression(
+ locs,
+ /*isTuple=*/ false,
+ lbracketOffset,
+ ImmutableList.of(expression),
+ rbracketOffset);
}
case FOR:
@@ -840,8 +834,8 @@
parseExprList(elems, /*trailingCommaAllowed=*/ true);
if (token.kind == TokenKind.RBRACKET) {
int rbracketOffset = nextToken();
- return setLNT(
- new ListExpression(/*isTuple=*/ false, lbracketOffset, elems, rbracketOffset));
+ return new ListExpression(
+ locs, /*isTuple=*/ false, lbracketOffset, elems, rbracketOffset);
}
expect(TokenKind.RBRACKET);
@@ -865,7 +859,7 @@
int lbraceOffset = expect(TokenKind.LBRACE);
if (token.kind == TokenKind.RBRACE) { // empty Dict
int rbraceOffset = nextToken();
- return setLNT(new DictExpression(lbraceOffset, ImmutableList.of(), rbraceOffset));
+ return new DictExpression(locs, lbraceOffset, ImmutableList.of(), rbraceOffset);
}
DictExpression.Entry entry = parseDictEntry();
@@ -882,7 +876,7 @@
}
if (token.kind == TokenKind.RBRACE) {
int rbraceOffset = nextToken();
- return setLNT(new DictExpression(lbraceOffset, entries, rbraceOffset));
+ return new DictExpression(locs, lbraceOffset, entries, rbraceOffset);
}
expect(TokenKind.RBRACE);
@@ -899,7 +893,7 @@
String name = (String) token.value;
int offset = nextToken();
- return setLNT(new Identifier(name, offset));
+ return new Identifier(locs, name, offset);
}
// binop_expression = binop_expression OP binop_expression
@@ -949,13 +943,13 @@
private Expression optimizeBinOpExpression(
Expression x, TokenKind op, int opOffset, Expression y) {
if (op == TokenKind.PLUS && x instanceof StringLiteral && y instanceof StringLiteral) {
- return setLNT(
- new StringLiteral(
- x.getStartOffset(),
- intern(((StringLiteral) x).getValue() + ((StringLiteral) y).getValue()),
- y.getEndOffset()));
+ return new StringLiteral(
+ locs,
+ x.getStartOffset(),
+ intern(((StringLiteral) x).getValue() + ((StringLiteral) y).getValue()),
+ y.getEndOffset());
}
- return setLNT(new BinaryOperatorExpression(x, op, opOffset, y));
+ return new BinaryOperatorExpression(locs, x, op, opOffset, y);
}
// Parses a non-tuple expression ("test" in Python terminology).
@@ -968,7 +962,7 @@
if (token.kind == TokenKind.ELSE) {
nextToken();
Expression elseClause = parseTest();
- return setLNT(new ConditionalExpression(expr, condition, elseClause));
+ return new ConditionalExpression(locs, expr, condition, elseClause);
} else {
reportError(start, "missing else clause in conditional expression or semicolon before if");
return expr; // Try to recover from error: drop the if and the expression after it. Ouch.
@@ -991,7 +985,7 @@
private Expression parseNotExpression(int prec) {
int notOffset = expect(TokenKind.NOT);
Expression x = parseTest(prec);
- return setLNT(new UnaryOperatorExpression(TokenKind.NOT, notOffset, x));
+ return new UnaryOperatorExpression(locs, TokenKind.NOT, notOffset, x);
}
// file_input = ('\n' | stmt)* EOF
@@ -1018,15 +1012,15 @@
expect(TokenKind.LPAREN);
if (token.kind != TokenKind.STRING) {
// error: module is not a string literal.
- StringLiteral module = setLNT(new StringLiteral(token.left, "", token.right));
+ StringLiteral module = new StringLiteral(locs, token.left, "", token.right);
expect(TokenKind.STRING);
- return setLNT(new LoadStatement(loadOffset, module, ImmutableList.of(), token.right));
+ return new LoadStatement(locs, loadOffset, module, ImmutableList.of(), token.right);
}
StringLiteral module = parseStringLiteral();
if (token.kind == TokenKind.RPAREN) {
syntaxError("expected at least one symbol to load");
- return setLNT(new LoadStatement(loadOffset, module, ImmutableList.of(), token.right));
+ return new LoadStatement(locs, loadOffset, module, ImmutableList.of(), token.right);
}
expect(TokenKind.COMMA);
@@ -1043,7 +1037,7 @@
}
int rparen = expect(TokenKind.RPAREN);
- return setLNT(new LoadStatement(loadOffset, module, bindings.build(), rparen));
+ return new LoadStatement(locs, loadOffset, module, bindings.build(), rparen);
}
/**
@@ -1061,7 +1055,7 @@
String name = (String) token.value;
int nameOffset = token.left + (token.kind == TokenKind.STRING ? 1 : 0);
- Identifier local = setLNT(new Identifier(name, nameOffset));
+ Identifier local = new Identifier(locs, name, nameOffset);
Identifier original;
if (token.kind == TokenKind.STRING) {
@@ -1078,7 +1072,7 @@
syntaxError("expected string");
return;
}
- original = setLNT(new Identifier((String) token.value, token.left + 1));
+ original = new Identifier(locs, (String) token.value, token.left + 1);
}
nextToken();
symbols.add(new LoadStatement.Binding(local, original));
@@ -1119,7 +1113,7 @@
|| token.kind == TokenKind.PASS) {
TokenKind kind = token.kind;
int offset = nextToken();
- return setLNT(new FlowStatement(kind, offset));
+ return new FlowStatement(locs, kind, offset);
}
// load
@@ -1135,9 +1129,9 @@
int opOffset = nextToken();
Expression rhs = parseExpression();
// op == null for ordinary assignment. TODO(adonovan): represent as EQUALS.
- return setLNT(new AssignmentStatement(lhs, op, opOffset, rhs));
+ return new AssignmentStatement(locs, lhs, op, opOffset, rhs);
} else {
- return setLNT(new ExpressionStatement(lhs));
+ return new ExpressionStatement(locs, lhs);
}
}
@@ -1147,14 +1141,14 @@
Expression cond = parseTest();
expect(TokenKind.COLON);
List<Statement> body = parseSuite();
- IfStatement ifStmt = setLNT(new IfStatement(TokenKind.IF, ifOffset, cond, body));
+ IfStatement ifStmt = new IfStatement(locs, TokenKind.IF, ifOffset, cond, body);
IfStatement tail = ifStmt;
while (token.kind == TokenKind.ELIF) {
int elifOffset = expect(TokenKind.ELIF);
cond = parseTest();
expect(TokenKind.COLON);
body = parseSuite();
- IfStatement elif = setLNT(new IfStatement(TokenKind.ELIF, elifOffset, cond, body));
+ IfStatement elif = new IfStatement(locs, TokenKind.ELIF, elifOffset, cond, body);
tail.setElseBlock(ImmutableList.of(elif));
tail = elif;
}
@@ -1175,7 +1169,7 @@
Expression collection = parseExpression();
expect(TokenKind.COLON);
List<Statement> block = parseSuite();
- return setLNT(new ForStatement(forOffset, lhs, collection, block));
+ return new ForStatement(locs, forOffset, lhs, collection, block);
}
// def_stmt = DEF IDENTIFIER '(' arguments ')' ':' suite
@@ -1197,7 +1191,7 @@
expect(TokenKind.RPAREN);
expect(TokenKind.COLON);
ImmutableList<Statement> block = ImmutableList.copyOf(parseSuite());
- return setLNT(new DefStatement(defOffset, ident, params, signature, block));
+ return new DefStatement(locs, defOffset, ident, params, signature, block);
}
// Parse a list of function parameters.
@@ -1264,6 +1258,6 @@
if (!STATEMENT_TERMINATOR_SET.contains(token.kind)) {
result = parseExpression();
}
- return setLNT(new ReturnStatement(returnOffset, result));
+ return new ReturnStatement(locs, returnOffset, result);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ReturnStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/ReturnStatement.java
index 3ba54ae..46b6dd4 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ReturnStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ReturnStatement.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.syntax;
-import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
/** A syntax node for return statements. */
@@ -22,7 +21,8 @@
private final int returnOffset;
@Nullable private final Expression result;
- ReturnStatement(int returnOffset, @Nullable Expression result) {
+ ReturnStatement(FileLocations locs, int returnOffset, @Nullable Expression result) {
+ super(locs);
this.returnOffset = returnOffset;
this.result = result;
}
@@ -33,9 +33,7 @@
* compiled representation.
*/
public static ReturnStatement make(Expression expr) {
- ReturnStatement stmt = new ReturnStatement(0, expr);
- stmt.lnt = Preconditions.checkNotNull(expr.lnt);
- return stmt;
+ return new ReturnStatement(expr.locs, 0, expr);
}
// TODO(adonovan): rename to getResult.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java
index d78a850..29f6d70 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java
@@ -26,12 +26,14 @@
private final int rbracketOffset;
SliceExpression(
+ FileLocations locs,
Expression object,
int lbracketOffset,
Expression start,
Expression stop,
Expression step,
int rbracketOffset) {
+ super(locs);
this.object = object;
this.lbracketOffset = lbracketOffset;
this.start = start;
@@ -70,7 +72,7 @@
}
public Location getLbracketLocation() {
- return lnt.getLocation(lbracketOffset);
+ return locs.getLocation(lbracketOffset);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFile.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFile.java
index 237cd19..8850cfd 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFile.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkFile.java
@@ -41,15 +41,17 @@
@Override
public int getEndOffset() {
- return lnt.size();
+ return locs.size();
}
private StarlarkFile(
+ FileLocations locs,
ImmutableList<Statement> statements,
FileOptions options,
ImmutableList<Comment> comments,
List<SyntaxError> errors,
String contentHashCode) {
+ super(locs);
this.statements = statements;
this.options = options;
this.comments = comments;
@@ -60,35 +62,30 @@
// Creates a StarlarkFile from the given effective list of statements,
// which may include the prelude.
private static StarlarkFile create(
- LineNumberTable lnt,
+ FileLocations locs,
ImmutableList<Statement> statements,
FileOptions options,
Parser.ParseResult result,
String contentHashCode) {
- StarlarkFile file =
- new StarlarkFile(
- statements,
- options,
- ImmutableList.copyOf(result.comments),
- result.errors,
- contentHashCode);
- file.lnt = lnt;
- return file;
+ return new StarlarkFile(
+ locs,
+ statements,
+ options,
+ ImmutableList.copyOf(result.comments),
+ result.errors,
+ contentHashCode);
}
/** Extract a subtree containing only statements from i (included) to j (excluded). */
public StarlarkFile subTree(int i, int j) {
- StarlarkFile file =
- new StarlarkFile(
- this.statements.subList(i, j),
- this.options,
- /*comments=*/ ImmutableList.of(),
- errors,
- /*contentHashCode=*/ null);
- file.lnt = this.lnt;
- return file;
+ return new StarlarkFile(
+ this.locs,
+ this.statements.subList(i, j),
+ this.options,
+ /*comments=*/ ImmutableList.of(),
+ errors,
+ /*contentHashCode=*/ null);
}
-
/**
* Returns an unmodifiable view of the list of scanner, parser, and (perhaps) resolver errors
* accumulated in this Starlark file.
@@ -134,7 +131,7 @@
stmts.addAll(prelude);
stmts.addAll(result.statements);
- return create(result.lnt, stmts.build(), options, result, /*contentHashCode=*/ null);
+ return create(result.locs, stmts.build(), options, result, /*contentHashCode=*/ null);
}
// TODO(adonovan): make the digest publicly settable, and delete this.
@@ -142,7 +139,7 @@
throws IOException {
Parser.ParseResult result = Parser.parseFile(input, options);
return create(
- result.lnt,
+ result.locs,
ImmutableList.copyOf(result.statements),
options,
result,
@@ -166,7 +163,7 @@
public static StarlarkFile parse(ParserInput input, FileOptions options) {
Parser.ParseResult result = Parser.parseFile(input, options);
return create(
- result.lnt,
+ result.locs,
ImmutableList.copyOf(result.statements),
options,
result,
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Statement.java b/src/main/java/com/google/devtools/build/lib/syntax/Statement.java
index 27d3123..e3633b4 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Statement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Statement.java
@@ -31,6 +31,10 @@
RETURN,
}
+ Statement(FileLocations locs) {
+ super(locs);
+ }
+
/**
* Kind of the statement. This is similar to using instanceof, except that it's more efficient and
* can be used in a switch/case.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StringLiteral.java b/src/main/java/com/google/devtools/build/lib/syntax/StringLiteral.java
index 8ca6f1c..bbde6a2 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StringLiteral.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StringLiteral.java
@@ -28,7 +28,8 @@
private final String value;
private final int endOffset;
- StringLiteral(int startOffset, String value, int endOffset) {
+ StringLiteral(FileLocations locs, int startOffset, String value, int endOffset) {
+ super(locs);
this.startOffset = startOffset;
this.value = value;
this.endOffset = endOffset;
@@ -40,7 +41,7 @@
}
public Location getLocation() {
- return lnt.getLocation(startOffset);
+ return locs.getLocation(startOffset);
}
@Override
@@ -83,7 +84,7 @@
out.writeInt32NoTag(lit.startOffset);
out.writeInt32NoTag(lit.endOffset);
context.serializeWithAdHocMemoizationStrategy(
- lit.lnt, MemoizationStrategy.MEMOIZE_AFTER, out);
+ lit.locs, MemoizationStrategy.MEMOIZE_AFTER, out);
}
@Override
@@ -93,10 +94,9 @@
context.deserializeWithAdHocMemoizationStrategy(in, MemoizationStrategy.MEMOIZE_AFTER);
int startOffset = in.readInt32();
int endOffset = in.readInt32();
- StringLiteral lit = new StringLiteral(startOffset, value, endOffset);
- lit.lnt =
+ FileLocations locs =
context.deserializeWithAdHocMemoizationStrategy(in, MemoizationStrategy.MEMOIZE_AFTER);
- return lit;
+ return new StringLiteral(locs, startOffset, value, endOffset);
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperatorExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperatorExpression.java
index 59d387a..4b1e9f4 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperatorExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperatorExpression.java
@@ -21,7 +21,8 @@
private final int opOffset;
private final Expression x;
- UnaryOperatorExpression(TokenKind op, int opOffset, Expression x) {
+ UnaryOperatorExpression(FileLocations locs, TokenKind op, int opOffset, Expression x) {
+ super(locs);
this.op = op;
this.opOffset = opOffset;
this.x = x;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
index 8e42109..4eae9f4 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
@@ -90,7 +90,15 @@
String getUndeclaredNameError(String name);
}
- private static final Identifier PREDECLARED = new Identifier("", 0);
+ private static final Identifier PREDECLARED; // sentinel for predeclared names
+
+ static {
+ try {
+ PREDECLARED = (Identifier) Expression.parse(ParserInput.fromLines("PREDECLARED"));
+ } catch (SyntaxError.Exception ex) {
+ throw new IllegalStateException(ex); // can't happen
+ }
+ }
private static class Block {
private final Map<String, Identifier> variables = new HashMap<>();
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java b/src/test/java/com/google/devtools/build/lib/syntax/FileLocationsTest.java
similarity index 84%
rename from src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java
rename to src/test/java/com/google/devtools/build/lib/syntax/FileLocationsTest.java
index 6116743..c672b25 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/FileLocationsTest.java
@@ -19,17 +19,17 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-/** Tests for {@link LineNumberTable}. */
+/** Tests for {@link FileLocations}. */
// TODO(adonovan): express this test in terms of the public API.
@RunWith(JUnit4.class)
-public class LineNumberTableTest {
+public class FileLocationsTest {
- private static LineNumberTable create(String buffer) {
- return LineNumberTable.create(buffer.toCharArray(), "/fake/file");
+ private static FileLocations create(String buffer) {
+ return FileLocations.create(buffer.toCharArray(), "/fake/file");
}
// Asserts that the specified offset results in a line/column pair of the form "1:2".
- private static void checkOffset(LineNumberTable table, int offset, String wantLineCol) {
+ private static void checkOffset(FileLocations table, int offset, String wantLineCol) {
Location loc = table.getLocation(offset);
String got = String.format("%d:%d", loc.line(), loc.column());
if (!got.equals(wantLineCol)) {
@@ -40,20 +40,20 @@
@Test
public void testEmpty() {
- LineNumberTable table = create("");
+ FileLocations table = create("");
checkOffset(table, 0, "1:1");
}
@Test
public void testNewline() {
- LineNumberTable table = create("\n");
+ FileLocations table = create("\n");
checkOffset(table, 0, "1:1");
checkOffset(table, 1, "2:1"); // EOF
}
@Test
public void testOneLiner() {
- LineNumberTable table = create("foo");
+ FileLocations table = create("foo");
checkOffset(table, 0, "1:1");
checkOffset(table, 1, "1:2");
checkOffset(table, 2, "1:3");
@@ -62,7 +62,7 @@
@Test
public void testMultiLiner() {
- LineNumberTable table = create("\ntwo\nthree\n\nfive\n");
+ FileLocations table = create("\ntwo\nthree\n\nfive\n");
// \n
checkOffset(table, 0, "1:1");
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/LexerTest.java b/src/test/java/com/google/devtools/build/lib/syntax/LexerTest.java
index 616a85c..be15a86 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/LexerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/LexerTest.java
@@ -83,8 +83,8 @@
}
/**
- * Lexes the specified input string, and returns a string containing just the
- * linenumbers of each token.
+ * Lexes the specified input string, and returns a string containing just the line numbers of each
+ * token.
*/
private String linenums(String input) {
Lexer lexer = createLexer(input);
@@ -93,7 +93,7 @@
if (buf.length() > 0) {
buf.append(' ');
}
- int line = lexer.lnt.getLocation(tok.left).line();
+ int line = lexer.locs.getLocation(tok.left).line();
buf.append(line);
}
return buf.toString();
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/PrettyPrintTest.java b/src/test/java/com/google/devtools/build/lib/syntax/PrettyPrintTest.java
index 6293505..dfbe0f74 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/PrettyPrintTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/PrettyPrintTest.java
@@ -23,6 +23,7 @@
/** Tests the {@code toString} and pretty printing methods for {@link Node} subclasses. */
@RunWith(JUnit4.class)
+// TODO(adonovan): rename to NodePrinterTest.
public final class PrettyPrintTest {
private static StarlarkFile parseFile(String... lines) throws SyntaxError.Exception {
@@ -393,9 +394,17 @@
@Test
public void comment() throws SyntaxError.Exception {
- Comment node = new Comment(0, "foo");
- assertIndentedPrettyMatches(node, " # foo");
- assertTostringMatches(node, "foo");
+ ParserInput input =
+ ParserInput.fromLines(
+ "# foo", //
+ "expr # bar");
+ Parser.ParseResult r = Parser.parseFile(input, FileOptions.DEFAULT);
+ Comment c0 = r.comments.get(0);
+ assertIndentedPrettyMatches(c0, " # foo");
+ assertTostringMatches(c0, "# foo");
+ Comment c1 = r.comments.get(1);
+ assertIndentedPrettyMatches(c1, " # bar");
+ assertTostringMatches(c1, "# bar");
}
/* Not tested explicitly because they're covered implicitly by tests for other nodes: