Index: pkg/kernel/lib/ast.dart |
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart |
index 0112b5a7286a9cfd651dfbe5f032e6e43bbf8ae5..9d00c1ec9eafc850511d80bc809db61a7ce9b441 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,63 @@ 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) { |
+ _rangeCheck(line, 1, lineStarts.length, "line"); |
+ 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) { |
+ _rangeCheck(offset, 0, lineStarts.last, "offset"); |
+ 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); |
+ } |
+} |
+ |
+void _rangeCheck(int value, int min, int max, String name) { |
+ RangeError.checkValueInInterval(value, min, max, name, |
+ "The value of '$name' ($value) must be between $min and $max."); |
sra1
2017/05/04 05:44:39
Please remove this interpolation.
It is expensive
|
} |
/// Returns the [Reference] object for the given member. |