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..5cb1983464d25255fe038e6b64eca11bcb4aa9ea 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,73 @@ 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 nextLine = lineStarts[index + 1] - 1; |
| + String result = cachedText.substring(lineStarts[index], nextLine); |
| + if (result.endsWith("\r")) { |
| + // Support for Windows text files. |
| + result = result.substring(0, result.length - 1); |
|
asgerf
2017/04/03 09:55:25
The 'nextLine' variable does not actually refer to
ahe
2017/04/03 14:57:08
Done.
|
| + } |
| + return result; |
| + } |
| + // 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 1 and " |
|
asgerf
2017/04/03 09:55:25
between 1 and -> between 0 and
ahe
2017/04/03 14:57:08
Done.
|
| + "${lineStarts.length}."); |
| + |
| + 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. |