Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/source_file.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/source_file.dart b/sdk/lib/_internal/compiler/implementation/source_file.dart |
| index 3e7d2b8a37856e63a45226e3e3e9f077f2fff207..25f2afbf708d06b196bb3dabfe3901c778f9cbcd 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/source_file.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/source_file.dart |
| @@ -5,42 +5,83 @@ |
| library source_file; |
| import 'dart:math'; |
| +import 'dart:convert' show UTF8; |
| /** |
| - * Represents a file of source code. |
| + * Represents a file of source code. The content can be either a [String] or |
| + * a UTF-8 encoded [List<int>] of bytes. |
| */ |
| -class SourceFile { |
| +abstract class SourceFile { |
| /** The name of the file. */ |
| final String filename; |
| - /** The text content of the file. */ |
| - final String text; |
| + SourceFile(this.filename); |
| + |
| + /** The text content of the file represented as a String. */ |
| + String slowText(); |
| - List<int> _lineStarts; |
| + /** The content of the file represented as a UTF-8 encoded [List<int>]. */ |
| + List<int> slowUtf8Bytes(); |
| - SourceFile(this.filename, this.text); |
| + /** |
| + * The length of the string representation of this source file, i.e., |
| + * equivalent to [:slowText().length:], but faster. |
| + */ |
| + int get length; |
| + /** |
| + * Sets the string length of this source file. For source files based on UTF-8 |
| + * byte arrays, the string length is computed and assigned by the scanner. |
| + */ |
| + set length(v); |
|
ngeoffray
2013/10/18 10:19:37
int v?
lukas
2013/10/24 16:48:36
Done.
|
| + |
| + /** |
| + * A map from line numbers to offsets in the string text representation of |
| + * this source file. |
| + */ |
| List<int> get lineStarts { |
| - if (_lineStarts == null) { |
| - var starts = [0]; |
| - var index = 0; |
| - while (index < text.length) { |
| - index = text.indexOf('\n', index) + 1; |
| - if (index <= 0) break; |
| - starts.add(index); |
| - } |
| - starts.add(text.length + 1); |
| - _lineStarts = starts; |
| + if (lineStartsCache == null) { |
| + // When reporting errors during scanning, the line numbers are not yet |
| + // available and need to be computed using this slow path. |
| + lineStartsCache = lineStartsFromString(slowText()); |
| } |
| - return _lineStarts; |
| + return lineStartsCache; |
| } |
| + /** |
| + * Sets the line numbers map for this source file. This map is computed and |
| + * assigned by the scanner, avoiding a separate traversal of the source file. |
| + * |
| + * The map contains one additional entry at the end of the file, as if the |
| + * source file had one more empty line at the end. This simplifies the binary |
| + * search in [getLine]. |
| + */ |
| + set lineStarts(v) => lineStartsCache = v; |
|
ngeoffray
2013/10/18 10:19:37
v -> List<int> v.
lukas
2013/10/24 16:48:36
Done.
|
| + |
| + List<int> lineStartsCache; |
| + |
| + List<int> lineStartsFromString(String text) { |
| + var starts = [0]; |
| + var index = 0; |
| + while (index < text.length) { |
| + index = text.indexOf('\n', index) + 1; |
| + if (index <= 0) break; |
| + starts.add(index); |
| + } |
| + starts.add(text.length + 1); // One additional line start at the end. |
| + return starts; |
| + } |
| + |
| + /** |
| + * Returns the line number for the offset [position] in the string |
| + * representation of this source file. |
| + */ |
| int getLine(int position) { |
| List<int> starts = lineStarts; |
| if (position < 0 || starts.last <= position) { |
| throw 'bad position #$position in file $filename with ' |
| - 'length ${text.length}.'; |
| + 'length ${length}.'; |
| } |
| int first = 0; |
| int count = starts.length; |
| @@ -58,10 +99,16 @@ class SourceFile { |
| return first; |
| } |
| + /** |
| + * Returns the column number for the offset [position] in the string |
| + * representation of this source file. |
| + */ |
| int getColumn(int line, int position) { |
| return position - lineStarts[line]; |
| } |
| + String slowSubstring(int start, int end); |
| + |
| /** |
| * Create a pretty string representation from a character position |
| * in the file. |
| @@ -75,12 +122,12 @@ class SourceFile { |
| '${filename}:${line + 1}:${column + 1}: $message'); |
| if (includeText) { |
| buf.write('\n'); |
| - var textLine; |
| + String textLine; |
| // +1 for 0-indexing, +1 again to avoid the last line of the file |
| - if ((line + 2) < _lineStarts.length) { |
| - textLine = text.substring(_lineStarts[line], _lineStarts[line+1]); |
| + if ((line + 2) < lineStarts.length) { |
| + textLine = slowSubstring(lineStarts[line], lineStarts[line+1]); |
| } else { |
| - textLine = '${text.substring(_lineStarts[line])}\n'; |
| + textLine = '${slowSubstring(lineStarts[line], length)}\n'; |
| } |
| int toColumn = min(column + (end-start), textLine.length); |
| @@ -101,3 +148,47 @@ class SourceFile { |
| return buf.toString(); |
| } |
| } |
| + |
| +class Utf8BytesSourceFile extends SourceFile { |
| + |
| + /** The UTF-8 encoded content of the source file. */ |
| + final List<int> content; |
| + |
| + Utf8BytesSourceFile(String filename, this.content) : super(filename); |
| + |
| + String slowText() => UTF8.decode(content); |
| + |
| + List<int> slowUtf8Bytes() => content; |
| + |
| + String slowSubstring(int start, int end) { |
| + // TODO(lry): to make this faster, the scanner could record the UTF-8 slack |
| + // for all positions of the source text. We could use [:content.sublist:]. |
| + return slowText().substring(start, end); |
| + } |
| + |
| + int get length { |
| + if (lengthCache == -1) { |
| + // During scanning the length is not yet assigned, so we use a slow path. |
| + length = slowText().length; |
| + } |
| + return lengthCache; |
| + } |
| + set length(v) => lengthCache = v; |
|
ngeoffray
2013/10/18 10:19:37
int v
lukas
2013/10/24 16:48:36
Done.
|
| + int lengthCache = -1; |
| +} |
| + |
| +class StringSourceFile extends SourceFile { |
| + |
| + final String text; |
| + |
| + StringSourceFile(String filename, this.text) : super(filename); |
| + |
| + int get length => text.length; |
| + set length(v) { } |
|
ngeoffray
2013/10/18 10:19:37
int v
lukas
2013/10/24 16:48:36
Done.
|
| + |
| + String slowText() => text; |
| + |
| + List<int> slowUtf8Bytes() => UTF8.encode(text); |
| + |
| + String slowSubstring(int start, int end) => text.substring(start, end); |
| +} |