diff options
author | 2018-01-16 18:21:16 -0800 | |
---|---|---|
committer | 2018-01-16 18:22:48 -0800 | |
commit | 7ac7b63c658509fd335db6f0149da8e2786c488a (patch) | |
tree | 04bf7c852fc0137ace91ce568c7a4a268396ed79 /src/main/java/com/google/devtools/build/lib/syntax | |
parent | 6f95124c3453006149eac955d7620540c7d6bda4 (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.java | 15 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java | 123 |
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) { |