Chromium Code Reviews| 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. |