diff options
author | 2018-02-15 07:58:03 -0800 | |
---|---|---|
committer | 2018-02-15 07:59:54 -0800 | |
commit | 229ca182e86c3743070841139c67d76598272c2c (patch) | |
tree | 02d93725b2bab2cb7afaa66703dbb7f0756980bb | |
parent | c0f7a2801e1d65cb533a658f82b486beacb480bf (diff) |
Remove unused LineNumberTable.HashLine class.
RELNOTES: None.
PiperOrigin-RevId: 185838543
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java | 355 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java | 35 |
2 files changed, 82 insertions, 308 deletions
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 9edf92777e..49e793a5b5 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 @@ -14,320 +14,129 @@ 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; import java.io.Serializable; -import java.nio.CharBuffer; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * A table to keep track of line numbers in source files. The client creates a LineNumberTable for * 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 { +@AutoCodec +@Immutable +public class LineNumberTable implements Serializable { public static final ObjectCodec<LineNumberTable> CODEC = new LineNumberTable_AutoCodec(); - /** - * Returns the (line, column) pair for the specified offset. - */ - abstract LineAndColumn getLineAndColumn(int offset); + /** A mapping from line number (line >= 1) to character offset into the file. */ + private final int[] linestart; - /** - * Returns the (start, end) offset pair for a specified line, not including - * newline chars. - */ - abstract Pair<Integer, Integer> getOffsetsForLine(int line); + private final PathFragment path; + private final int bufferLength; - /** - * Returns the path corresponding to the given offset. - */ - abstract PathFragment getPath(int offset); - - static LineNumberTable create(char[] buffer, PathFragment path) { - // If #line appears within a BUILD file, we assume it has been preprocessed - // 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()) - ? HashLine.create(buffer, path) - : new Regular(buffer, path); + public LineNumberTable(char[] buffer, PathFragment path) { + this(computeLinestart(buffer), path, buffer.length); } - /** 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. - */ - private final int[] linestart; - private final PathFragment path; - private final int bufferLength; + @AutoCodec.Instantiator + LineNumberTable(int[] linestart, PathFragment path, int bufferLength) { + this.linestart = linestart; + this.path = path; + this.bufferLength = bufferLength; + } - public Regular(char[] buffer, PathFragment path) { - this(computeLinestart(buffer), path, buffer.length); - } + static LineNumberTable create(char[] buffer, PathFragment path) { + return new LineNumberTable(buffer, path); + } - @AutoCodec.Instantiator - Regular(int[] linestart, PathFragment path, int bufferLength) { - this.linestart = linestart; - this.path = path; - this.bufferLength = bufferLength; + private int getLineAt(int offset) { + if (offset < 0) { + throw new IllegalStateException("Illegal position: " + offset); } - - private int getLineAt(int offset) { - if (offset < 0) { - throw new IllegalStateException("Illegal position: " + offset); - } - int lowBoundary = 1; - int highBoundary = linestart.length - 1; - while (true) { - if ((highBoundary - lowBoundary) <= 1) { - if (linestart[highBoundary] > offset) { - return lowBoundary; - } else { - return highBoundary; - } - } - int medium = lowBoundary + ((highBoundary - lowBoundary) >> 1); - if (linestart[medium] > offset) { - highBoundary = medium; + int lowBoundary = 1; + int highBoundary = linestart.length - 1; + while (true) { + if ((highBoundary - lowBoundary) <= 1) { + if (linestart[highBoundary] > offset) { + return lowBoundary; } else { - lowBoundary = medium; - } - } - } - - @Override - LineAndColumn getLineAndColumn(int offset) { - int line = getLineAt(offset); - int column = offset - linestart[line] + 1; - return new LineAndColumn(line, column); - } - - @Override - PathFragment getPath(int offset) { - return path; - } - - @Override - Pair<Integer, Integer> getOffsetsForLine(int line) { - if (line <= 0 || line >= linestart.length) { - throw new IllegalArgumentException("Illegal line: " + line); - } - return Pair.of(linestart[line], line < linestart.length - 1 - ? linestart[line + 1] - : bufferLength); - } - - - @Override - public int hashCode() { - return Objects.hash(Arrays.hashCode(linestart), path, bufferLength); - } - - @Override - public boolean equals(Object other) { - if (other == null || !other.getClass().equals(getClass())) { - return false; - } - Regular that = (Regular) other; - return this.bufferLength == that.bufferLength - && 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++; + return highBoundary; } } - 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; - } + int medium = lowBoundary + ((highBoundary - lowBoundary) >> 1); + if (linestart[medium] > offset) { + highBoundary = medium; + } else { + lowBoundary = medium; } - return linestart; } } - /** - * 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(); - - private final int offset; - private final int line; - private final PathFragment path; - - SingleHashLine(int offset, int line, PathFragment path) { - this.offset = offset; - 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 = - new Ordering<SingleHashLine>() { - - @Override - public int compare(SingleHashLine o1, SingleHashLine o2) { - return Integer.compare(o1.offset, o2.offset); - } - }; - - private static final Pattern pattern = Pattern.compile("\n#line ([0-9]+) \"([^\"\\n]+)\""); - - private final ImmutableList<SingleHashLine> table; - private final PathFragment defaultPath; - private final int bufferLength; - - public static HashLine create(char[] buffer, PathFragment defaultPath) { - CharSequence bufString = CharBuffer.wrap(buffer); - Matcher m = pattern.matcher(bufString); - List<SingleHashLine> unorderedTable = new ArrayList<>(); - Map<String, PathFragment> pathCache = new HashMap<>(); - while (m.find()) { - String pathString = m.group(2); - PathFragment pathFragment = pathCache.computeIfAbsent(pathString, defaultPath::getRelative); - unorderedTable.add(new SingleHashLine( - m.start(0) + 1, //offset (+1 to skip \n in pattern) - Integer.parseInt(m.group(1)), // line number - pathFragment)); // filename is an absolute path - } - return new HashLine( - hashOrdering.immutableSortedCopy(unorderedTable), - Preconditions.checkNotNull(defaultPath), - buffer.length); - } + LineAndColumn getLineAndColumn(int offset) { + int line = getLineAt(offset); + int column = offset - linestart[line] + 1; + return new LineAndColumn(line, column); + } - @AutoCodec.Instantiator - HashLine(ImmutableList<SingleHashLine> table, PathFragment defaultPath, int bufferLength) { - this.table = table; - this.defaultPath = defaultPath; - this.bufferLength = bufferLength; - } + PathFragment getPath(int offset) { + return path; + } - private SingleHashLine getHashLine(int offset) { - if (offset < 0) { - throw new IllegalStateException("Illegal position: " + offset); - } - int binarySearchIndex = - Collections.binarySearch(table, new SingleHashLine(offset, -1, null), hashOrdering); - if (binarySearchIndex >= 0) { - // An exact match in the binary search. Return it. - return table.get(binarySearchIndex); - } else if (binarySearchIndex < -1) { - // See docs at Collections#binarySearch. Our index is -(insertionPoint + 1). To get to the - // nearest existing value in the original list, we must subtract 2. - return table.get(-binarySearchIndex - 2); - } else { - return null; - } + Pair<Integer, Integer> getOffsetsForLine(int line) { + if (line <= 0 || line >= linestart.length) { + throw new IllegalArgumentException("Illegal line: " + line); } + return Pair.of( + linestart[line], line < linestart.length - 1 ? linestart[line + 1] : bufferLength); + } - @Override - LineAndColumn getLineAndColumn(int offset) { - SingleHashLine hashLine = getHashLine(offset); - return hashLine == null ? new LineAndColumn(-1, 1) : new LineAndColumn(hashLine.line, 1); - } + @Override + public int hashCode() { + return Objects.hash(Arrays.hashCode(linestart), path, bufferLength); + } - @Override - PathFragment getPath(int offset) { - SingleHashLine hashLine = getHashLine(offset); - return hashLine == null ? defaultPath : hashLine.path; + @Override + public boolean equals(Object other) { + if (other == null || !other.getClass().equals(getClass())) { + return false; } + LineNumberTable that = (LineNumberTable) other; + return this.bufferLength == that.bufferLength + && Arrays.equals(this.linestart, that.linestart) + && Objects.equals(this.path, that.path); + } - /** - * Returns 0, 0 for an unknown line - */ - @Override - Pair<Integer, Integer> getOffsetsForLine(int line) { - for (int ii = 0, len = table.size(); ii < len; ii++) { - if (table.get(ii).line == line) { - return Pair.of(table.get(ii).offset, ii < len - 1 - ? table.get(ii + 1).offset - : bufferLength); - } + 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++; } - return Pair.of(0, 0); } - - @Override - public int hashCode() { - return Objects.hash(table, defaultPath, bufferLength); - } - - @Override - public boolean equals(Object other) { - if (other == null || !other.getClass().equals(getClass())) { - return false; + 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; } - HashLine that = (HashLine) other; - return this.bufferLength == that.bufferLength - && this.defaultPath.equals(that.defaultPath) - && this.table.equals(that.table); } + return linestart; } } diff --git a/src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java b/src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java index 5397b93549..df45f896d6 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/LineNumberTableTest.java @@ -85,41 +85,6 @@ public class LineNumberTableTest { } @Test - public void testHashLine() { - String data = "#\n" - + "#line 67 \"/foo\"\n" - + "cc_binary(name='a',\n" - + " srcs=[])\n" - + "#line 23 \"/ba.r\"\n" - + "vardef(x,y)\n"; - - LineNumberTable table = create(data); - - // Note: no attempt is made to return accurate column information. - assertThat(table.getLineAndColumn(data.indexOf("cc_binary"))) - .isEqualTo(new LineAndColumn(67, 1)); - assertThat(table.getLineAndColumn(data.indexOf("name='a'"))) - .isEqualTo(new LineAndColumn(67, 1)); - assertThat(table.getPath(0).toString()).isEqualTo("/fake/file"); - // Note: newlines ignored; "srcs" is still (intentionally) considered to be - // on L67. Consider the alternative, and assume that rule 'a' is 50 lines - // when pretty-printed: the last line of 'a' would be reported as line 67 + - // 50, which may be in a part of the original BUILD file that has nothing - // to do with this rule. In other words, the size of rules before and - // after pretty printing are essentially unrelated. - assertThat(table.getLineAndColumn(data.indexOf("srcs"))).isEqualTo(new LineAndColumn(67, 1)); - assertThat(table.getPath(data.indexOf("srcs")).toString()).isEqualTo("/foo"); - assertThat(table.getOffsetsForLine(67)).isEqualTo(Pair.of(2, 57)); - - assertThat(table.getLineAndColumn(data.indexOf("vardef"))).isEqualTo(new LineAndColumn(23, 1)); - assertThat(table.getLineAndColumn(data.indexOf("x,y"))).isEqualTo(new LineAndColumn(23, 1)); - assertThat(table.getPath(data.indexOf("x,y")).toString()).isEqualTo("/ba.r"); - assertThat(table.getOffsetsForLine(23)).isEqualTo(Pair.of(57, 86)); - - assertThat(table.getOffsetsForLine(42)).isEqualTo(Pair.of(0, 0)); - } - - @Test public void testCodec() throws Exception { ObjectCodecTester.newBuilder(LineNumberTable.CODEC) .addSubjects( |