aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/events/Location.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/events/Location.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/events/Location.java215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/events/Location.java b/src/main/java/com/google/devtools/build/lib/events/Location.java
new file mode 100644
index 0000000000..39508d17e7
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/events/Location.java
@@ -0,0 +1,215 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.events;
+
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.io.Serializable;
+
+/**
+ * A Location is a range of characters within a file.
+ *
+ * The start and end locations may be the same, in which case the Location
+ * denotes a point in the file, not a range. The path may be null, indicating
+ * an unknown file.
+ *
+ * Implementations of Location should be optimised for speed of construction,
+ * not speed of attribute access, as far more Locations are created during
+ * parsing than are ever used to display error messages.
+ */
+public abstract class Location implements Serializable {
+
+ @Immutable
+ private static final class LocationWithPathAndStartColumn extends Location {
+ private final PathFragment path;
+ private final LineAndColumn startLineAndColumn;
+
+ private LocationWithPathAndStartColumn(Path path, int startOffSet, int endOffSet,
+ LineAndColumn startLineAndColumn) {
+ super(startOffSet, endOffSet);
+ this.path = path != null ? path.asFragment() : null;
+ this.startLineAndColumn = startLineAndColumn;
+ }
+
+ @Override
+ public PathFragment getPath() { return path; }
+
+ @Override
+ public LineAndColumn getStartLineAndColumn() {
+ return startLineAndColumn;
+ }
+ }
+
+ protected final int startOffset;
+ protected final int endOffset;
+
+ /**
+ * Returns a Location with a given Path, start and end offset and start line and column info.
+ */
+ public static Location fromPathAndStartColumn(Path path, int startOffSet, int endOffSet,
+ LineAndColumn startLineAndColumn) {
+ return new LocationWithPathAndStartColumn(path, startOffSet, endOffSet, startLineAndColumn);
+ }
+
+ /**
+ * Returns a Location relating to file 'path', but not to any specific part
+ * region within the file. Try to use a more specific location if possible.
+ */
+ public static Location fromFile(Path path) {
+ return fromFileAndOffsets(path, 0, 0);
+ }
+
+ /**
+ * Returns a Location relating to the subset of file 'path', starting at
+ * 'startOffset' and ending at 'endOffset'.
+ */
+ public static Location fromFileAndOffsets(final Path path,
+ int startOffset,
+ int endOffset) {
+ return new LocationWithPathAndStartColumn(path, startOffset, endOffset, null);
+ }
+
+ protected Location(int startOffset, int endOffset) {
+ this.startOffset = startOffset;
+ this.endOffset = endOffset;
+ }
+
+ /**
+ * Returns the start offset relative to the beginning of the file the object
+ * resides in.
+ */
+ public final int getStartOffset() {
+ return startOffset;
+ }
+
+ /**
+ * Returns the end offset relative to the beginning of the file the object
+ * resides in.
+ *
+ * <p>The end offset is one position past the actual end position, making this method
+ * behave in a compatible fashion with {@link String#substring(int, int)}.
+ *
+ * <p>To compute the length of this location, use {@code getEndOffset() - getStartOffset()}.
+ */
+ public final int getEndOffset() {
+ return endOffset;
+ }
+
+ /**
+ * Returns the path of the file to which the start/end offsets refer. May be
+ * null if the file name information is not available.
+ *
+ * This method is intentionally abstract, as a space optimisation. Some
+ * subclass instances implement sharing of common data (e.g. tables for
+ * convering offsets into line numbers) and this enables them to share the
+ * Path value in the same way.
+ */
+ public abstract PathFragment getPath();
+
+ /**
+ * Returns a (line, column) pair corresponding to the position denoted by
+ * getStartOffset. Returns null if this information is not available.
+ */
+ public LineAndColumn getStartLineAndColumn() {
+ return null;
+ }
+
+ /**
+ * Returns a (line, column) pair corresponding to the position denoted by
+ * getEndOffset. Returns null if this information is not available.
+ */
+ public LineAndColumn getEndLineAndColumn() {
+ return null;
+ }
+
+ /**
+ * A default implementation of toString() that formats the location in the
+ * following ways based on the amount of information available:
+ * <pre>
+ * "foo.cc:23:2"
+ * "23:2"
+ * "foo.cc:char offsets 123--456"
+ * "char offsets 123--456"
+ * </pre>
+ */
+ public String print() {
+ StringBuilder buf = new StringBuilder();
+ if (getPath() != null) {
+ buf.append(getPath()).append(':');
+ }
+ LineAndColumn start = getStartLineAndColumn();
+ if (start == null) {
+ if (getStartOffset() == 0 && getEndOffset() == 0) {
+ buf.append("1"); // i.e. line 1 (special case: no information at all)
+ } else {
+ buf.append("char offsets ").
+ append(getStartOffset()).append("--").append(getEndOffset());
+ }
+ } else {
+ buf.append(start.getLine()).append(':').append(start.getColumn());
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Prints the object in a sort of reasonable way. This should never be used in user-visible
+ * places, only for debugging and testing.
+ */
+ @Override
+ public String toString() {
+ return print();
+ }
+
+ /**
+ * A value class that describes the line and column of an offset in a file.
+ */
+ @Immutable
+ public static final class LineAndColumn {
+ private final int line;
+ private final int column;
+
+ public LineAndColumn(int line, int column) {
+ this.line = line;
+ this.column = column;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+ public int getColumn() {
+ return column;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof LineAndColumn)) {
+ return false;
+ }
+ LineAndColumn lac = (LineAndColumn) o;
+ return lac.line == line && lac.column == column;
+ }
+
+ @Override
+ public int hashCode() {
+ return line * 81 + column;
+ }
+ }
+}