Index: pkg/kernel/lib/ast.dart |
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart |
index 0112b5a7286a9cfd651dfbe5f032e6e43bbf8ae5..840dd1bfe3797f5efc18fc432b2cb0daf997a371 100644 |
--- a/pkg/kernel/lib/ast.dart |
+++ b/pkg/kernel/lib/ast.dart |
@@ -50,6 +50,8 @@ |
/// |
library kernel.ast; |
+import 'dart:convert' show UTF8; |
+ |
import 'visitor.dart'; |
export 'visitor.dart'; |
@@ -4107,22 +4109,7 @@ class Program extends TreeNode { |
/// Translates an offset to line and column numbers in the given file. |
Location getLocation(String file, int offset) { |
- List<int> lines = uriToSource[file].lineStarts; |
- int low = 0, high = lines.length - 1; |
- while (low < high) { |
- int mid = high - ((high - low) >> 1); // Get middle, rounding up. |
- int pivot = lines[mid]; |
- if (pivot <= offset) { |
- low = mid; |
- } else { |
- high = mid - 1; |
- } |
- } |
- int lineIndex = low; |
- int lineStart = lines[lineIndex]; |
- int lineNumber = 1 + lineIndex; |
- int columnNumber = 1 + offset - lineStart; |
- return new Location(file, lineNumber, columnNumber); |
+ return uriToSource[file]?.getLocation(file, offset); |
} |
} |
@@ -4228,9 +4215,71 @@ class _ChildReplacer extends Transformer { |
class Source { |
final List<int> lineStarts; |
+ |
final List<int> source; |
+ String cachedText; |
+ |
Source(this.lineStarts, this.source); |
+ |
+ /// Return the text corresponding to [line] which is a 1-based line |
+ /// number. The returned line contains no line separators. |
+ String getTextLine(int line) { |
+ RangeError.checkValueInInterval( |
+ line, |
+ 1, |
+ lineStarts.length, |
+ "line", |
+ "The value of 'line' ($line) must be between 1 and " |
+ "${lineStarts.length}."); |
+ if (source == null) return null; |
+ |
+ cachedText ??= UTF8.decode(source, allowMalformed: true); |
+ // -1 as line numbers start at 1. |
+ int index = line - 1; |
+ if (index + 1 == lineStarts.length) { |
+ // Last line. |
+ return cachedText.substring(lineStarts[index]); |
+ } else if (index < lineStarts.length) { |
+ // We subtract 1 from the next line for two reasons: |
+ // 1. If the file isn't terminated by a newline, that index is invalid. |
+ // 2. To remove the newline at the end of the line. |
+ int endOfLine = lineStarts[index + 1] - 1; |
+ if (endOfLine > index && cachedText[endOfLine - 1] == "\r") { |
+ --endOfLine; // Windows line endings. |
+ } |
+ return cachedText.substring(lineStarts[index], endOfLine); |
+ } |
+ // This shouldn't happen: should have been caught by the range check above. |
+ throw "Internal error"; |
+ } |
+ |
+ /// Translates an offset to line and column numbers in the given file. |
+ Location getLocation(String file, int offset) { |
+ RangeError.checkValueInInterval( |
+ offset, |
+ 0, |
+ lineStarts.last, |
+ "offset", |
+ "The value of 'offset' ($offset) must be between 0 and " |
+ "${lineStarts.length}."); |
asgerf
2017/04/04 08:53:05
length -> last
ahe
2017/04/05 11:34:23
Done.
|
+ |
+ int low = 0, high = lineStarts.length - 1; |
+ while (low < high) { |
+ int mid = high - ((high - low) >> 1); // Get middle, rounding up. |
+ int pivot = lineStarts[mid]; |
+ if (pivot <= offset) { |
+ low = mid; |
+ } else { |
+ high = mid - 1; |
+ } |
+ } |
+ int lineIndex = low; |
+ int lineStart = lineStarts[lineIndex]; |
+ int lineNumber = 1 + lineIndex; |
+ int columnNumber = 1 + offset - lineStart; |
+ return new Location(file, lineNumber, columnNumber); |
+ } |
} |
/// Returns the [Reference] object for the given member. |