aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax
diff options
context:
space:
mode:
authorGravatar shahan <shahan@google.com>2018-01-16 18:21:16 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-01-16 18:22:48 -0800
commit7ac7b63c658509fd335db6f0149da8e2786c488a (patch)
tree04bf7c852fc0137ace91ce568c7a4a268396ed79 /src/main/java/com/google/devtools/build/lib/syntax
parent6f95124c3453006149eac955d7620540c7d6bda4 (diff)
Codec for Location.
* Moves SingletonCodec to third_party. PiperOrigin-RevId: 182143153
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Lexer.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java123
2 files changed, 92 insertions, 46 deletions
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 10ff03e100..7e3b731d6f 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
@@ -23,6 +23,8 @@ import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
+import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.HashMap;
@@ -157,19 +159,21 @@ public final class Lexer {
}
Location createLocation(int start, int end) {
- return new LexerLocation(locationInfo, start, end);
+ return new LexerLocation(locationInfo.lineNumberTable, start, end);
}
// Don't use an inner class as we don't want to close over the Lexer, only
// the LocationInfo.
+ @AutoCodec
@Immutable
- private static final class LexerLocation extends Location {
+ static final class LexerLocation extends Location {
+ public static final ObjectCodec<LexerLocation> CODEC = new Lexer_LexerLocation_AutoCodec();
private final LineNumberTable lineNumberTable;
- LexerLocation(LocationInfo locationInfo, int start, int end) {
- super(start, end);
- this.lineNumberTable = locationInfo.lineNumberTable;
+ LexerLocation(LineNumberTable lineNumberTable, int startOffset, int endOffset) {
+ super(startOffset, endOffset);
+ this.lineNumberTable = lineNumberTable;
}
@Override
@@ -192,7 +196,6 @@ public final class Lexer {
return lineNumberTable.getLineAndColumn(endOffset);
}
-
@Override
public int hashCode() {
return Objects.hash(lineNumberTable, internalHashCode());
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
index 1e20e4577a..4706fa2f3b 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
@@ -15,9 +15,12 @@
package com.google.devtools.build.lib.syntax;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location.LineAndColumn;
+import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.StringUtilities;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -38,7 +41,9 @@ import java.util.regex.Pattern;
* their buffer using {@link #create}. The client can then ask for the line and column given a
* position using ({@link #getLineAndColumn(int)}).
*/
+@AutoCodec(strategy = AutoCodec.Strategy.POLYMORPHIC)
public abstract class LineNumberTable implements Serializable {
+ public static final ObjectCodec<LineNumberTable> CODEC = new LineNumberTable_AutoCodec();
/**
* Returns the (line, column) pair for the specified offset.
@@ -61,16 +66,15 @@ public abstract class LineNumberTable implements Serializable {
// by gconfig2blaze. We ignore all actual newlines and compute the logical
// LNT based only on the presence of #line markers.
return StringUtilities.containsSubarray(buffer, "\n#line ".toCharArray())
- ? new HashLine(buffer, path)
+ ? HashLine.create(buffer, path)
: new Regular(buffer, path);
}
- /**
- * Line number table implementation for regular source files. Records
- * offsets of newlines.
- */
+ /** Line number table implementation for regular source files. Records offsets of newlines. */
+ @AutoCodec
@Immutable
public static class Regular extends LineNumberTable {
+ public static final ObjectCodec<Regular> CODEC = new LineNumberTable_Regular_AutoCodec();
/**
* A mapping from line number (line >= 1) to character offset into the file.
@@ -80,32 +84,14 @@ public abstract class LineNumberTable implements Serializable {
private final int bufferLength;
public Regular(char[] buffer, PathFragment path) {
- // Compute the size.
- int size = 2;
- for (int i = 0; i < buffer.length; i++) {
- if (buffer[i] == '\n') {
- size++;
- }
- }
- linestart = new int[size];
-
- int index = 0;
- linestart[index++] = 0; // The 0th line does not exist - so we fill something in
- // to make sure the start pos for the 1st line ends up at
- // linestart[1]. Using 0 is useful for tables that are
- // completely empty.
- linestart[index++] = 0; // The first line ("line 1") starts at offset 0.
+ this(computeLinestart(buffer), path, buffer.length);
+ }
- // Scan the buffer and record the offset of each line start. Doing this
- // once upfront is faster than checking each char as it is pulled from
- // the buffer.
- for (int i = 0; i < buffer.length; i++) {
- if (buffer[i] == '\n') {
- linestart[index++] = i + 1;
- }
- }
- this.bufferLength = buffer.length;
+ @AutoCodec.Constructor
+ Regular(int[] linestart, PathFragment path, int bufferLength) {
+ this.linestart = linestart;
this.path = path;
+ this.bufferLength = bufferLength;
}
private int getLineAt(int offset) {
@@ -169,19 +155,51 @@ public abstract class LineNumberTable implements Serializable {
&& Arrays.equals(this.linestart, that.linestart)
&& Objects.equals(this.path, that.path);
}
+
+ private static int[] computeLinestart(char[] buffer) {
+ // Compute the size.
+ int size = 2;
+ for (int i = 0; i < buffer.length; i++) {
+ if (buffer[i] == '\n') {
+ size++;
+ }
+ }
+ int[] linestart = new int[size];
+
+ int index = 0;
+ linestart[index++] = 0; // The 0th line does not exist - so we fill something in
+ // to make sure the start pos for the 1st line ends up at
+ // linestart[1]. Using 0 is useful for tables that are
+ // completely empty.
+ linestart[index++] = 0; // The first line ("line 1") starts at offset 0.
+
+ // Scan the buffer and record the offset of each line start. Doing this
+ // once upfront is faster than checking each char as it is pulled from
+ // the buffer.
+ for (int i = 0; i < buffer.length; i++) {
+ if (buffer[i] == '\n') {
+ linestart[index++] = i + 1;
+ }
+ }
+ return linestart;
+ }
}
/**
- * Line number table implementation for source files that have been
- * preprocessed. Ignores newlines and uses only #line directives.
+ * Line number table implementation for source files that have been preprocessed. Ignores newlines
+ * and uses only #line directives.
*/
+ @AutoCodec
@Immutable
public static class HashLine extends LineNumberTable {
+ public static final ObjectCodec<HashLine> CODEC = new LineNumberTable_HashLine_AutoCodec();
+
+ /** Represents a "#line" directive */
+ @AutoCodec
+ static class SingleHashLine implements Serializable {
+ public static final ObjectCodec<SingleHashLine> CODEC =
+ new LineNumberTable_HashLine_SingleHashLine_AutoCodec();
- /**
- * Represents a "#line" directive
- */
- private static class SingleHashLine implements Serializable {
private final int offset;
private final int line;
private final PathFragment path;
@@ -191,6 +209,23 @@ public abstract class LineNumberTable implements Serializable {
this.line = line;
this.path = path;
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(offset, line, path);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof SingleHashLine)) {
+ return false;
+ }
+ SingleHashLine that = (SingleHashLine) obj;
+ return offset == that.offset && line == that.line && Objects.equals(path, that.path);
+ }
}
private static final Ordering<SingleHashLine> hashOrdering =
@@ -204,11 +239,11 @@ public abstract class LineNumberTable implements Serializable {
private static final Pattern pattern = Pattern.compile("\n#line ([0-9]+) \"([^\"\\n]+)\"");
- private final List<SingleHashLine> table;
+ private final ImmutableList<SingleHashLine> table;
private final PathFragment defaultPath;
private final int bufferLength;
- public HashLine(char[] buffer, PathFragment defaultPath) {
+ public static HashLine create(char[] buffer, PathFragment defaultPath) {
CharSequence bufString = CharBuffer.wrap(buffer);
Matcher m = pattern.matcher(bufString);
List<SingleHashLine> unorderedTable = new ArrayList<>();
@@ -221,9 +256,17 @@ public abstract class LineNumberTable implements Serializable {
Integer.parseInt(m.group(1)), // line number
pathFragment)); // filename is an absolute path
}
- this.table = hashOrdering.immutableSortedCopy(unorderedTable);
- this.bufferLength = buffer.length;
- this.defaultPath = Preconditions.checkNotNull(defaultPath);
+ return new HashLine(
+ hashOrdering.immutableSortedCopy(unorderedTable),
+ Preconditions.checkNotNull(defaultPath),
+ buffer.length);
+ }
+
+ @AutoCodec.Constructor
+ HashLine(ImmutableList<SingleHashLine> table, PathFragment defaultPath, int bufferLength) {
+ this.table = table;
+ this.defaultPath = defaultPath;
+ this.bufferLength = bufferLength;
}
private SingleHashLine getHashLine(int offset) {