Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: pkg/compiler/lib/src/source_file.dart

Issue 830703004: Emit to StreamCodeOutput instead of CodeBuffer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library source_file;
6
7 import 'dart:math';
8 import 'dart:convert' show UTF8;
9
10 /// Interface for providing line/column information.
11 abstract class LineColumnProvider {
12 /// Returns the line number (0-based) for [offset].
13 int getLine(int offset);
14
15 /// Returns the column number (0-based) for [offset] at the given [line].
16 int getColumn(int line, int offset);
17 }
18
19 /**
20 * Represents a file of source code. The content can be either a [String] or
21 * a UTF-8 encoded [List<int>] of bytes.
22 */
23 abstract class SourceFile implements LineColumnProvider {
24
25 /** The name of the file. */
26 String get filename;
27
28 /** The text content of the file represented as a String. */
29 String slowText();
30
31 /** The content of the file represented as a UTF-8 encoded [List<int>]. */
32 List<int> slowUtf8Bytes();
33
34 /**
35 * The length of the string representation of this source file, i.e.,
36 * equivalent to [:slowText().length:], but faster.
37 */
38 int get length;
39
40 /**
41 * Sets the string length of this source file. For source files based on UTF-8
42 * byte arrays, the string length is computed and assigned by the scanner.
43 */
44 set length(int v);
45
46 /**
47 * A map from line numbers to offsets in the string text representation of
48 * this source file.
49 */
50 List<int> get lineStarts {
51 if (lineStartsCache == null) {
52 // When reporting errors during scanning, the line numbers are not yet
53 // available and need to be computed using this slow path.
54 lineStartsCache = lineStartsFromString(slowText());
55 }
56 return lineStartsCache;
57 }
58
59 /**
60 * Sets the line numbers map for this source file. This map is computed and
61 * assigned by the scanner, avoiding a separate traversal of the source file.
62 *
63 * The map contains one additional entry at the end of the file, as if the
64 * source file had one more empty line at the end. This simplifies the binary
65 * search in [getLine].
66 */
67 set lineStarts(List<int> v) => lineStartsCache = v;
68
69 List<int> lineStartsCache;
70
71 List<int> lineStartsFromString(String text) {
72 var starts = [0];
73 var index = 0;
74 while (index < text.length) {
75 index = text.indexOf('\n', index) + 1;
76 if (index <= 0) break;
77 starts.add(index);
78 }
79 starts.add(text.length + 1); // One additional line start at the end.
80 return starts;
81 }
82
83 /**
84 * Returns the line number for the offset [position] in the string
85 * representation of this source file.
86 */
87 int getLine(int position) {
88 List<int> starts = lineStarts;
89 if (position < 0 || starts.last <= position) {
90 throw 'bad position #$position in file $filename with '
91 'length ${length}.';
92 }
93 int first = 0;
94 int count = starts.length;
95 while (count > 1) {
96 int step = count ~/ 2;
97 int middle = first + step;
98 int lineStart = starts[middle];
99 if (position < lineStart) {
100 count = step;
101 } else {
102 first = middle;
103 count -= step;
104 }
105 }
106 return first;
107 }
108
109 /**
110 * Returns the column number for the offset [position] in the string
111 * representation of this source file.
112 */
113 int getColumn(int line, int position) {
114 return position - lineStarts[line];
115 }
116
117 String slowSubstring(int start, int end);
118
119 /**
120 * Create a pretty string representation for [message] from a character
121 * range `[start, end]` in this file.
122 *
123 * If [includeSourceLine] is `true` the first source line code line that
124 * contains the range will be included as well as marker characters ('^')
125 * underlining the range.
126 *
127 * Use [colorize] to wrap source code text and marker characters in color
128 * escape codes.
129 */
130 String getLocationMessage(String message, int start, int end,
131 {bool includeSourceLine: true,
132 String colorize(String text)}) {
133 if (colorize == null) {
134 colorize = (text) => text;
135 }
136 var line = getLine(start);
137 var column = getColumn(line, start);
138
139 var buf = new StringBuffer('${filename}:');
140 if (start != end || start != 0) {
141 // Line/column info is relevant.
142 buf.write('${line + 1}:${column + 1}:');
143 }
144 buf.write('\n$message\n');
145
146 if (start != end && includeSourceLine) {
147 String textLine;
148 // +1 for 0-indexing, +1 again to avoid the last line of the file
149 if ((line + 2) < lineStarts.length) {
150 textLine = slowSubstring(lineStarts[line], lineStarts[line+1]);
151 } else {
152 textLine = '${slowSubstring(lineStarts[line], length)}\n';
153 }
154
155 int toColumn = min(column + (end-start), textLine.length);
156 buf.write(textLine.substring(0, column));
157 buf.write(colorize(textLine.substring(column, toColumn)));
158 buf.write(textLine.substring(toColumn));
159
160 int i = 0;
161 for (; i < column; i++) {
162 buf.write(' ');
163 }
164
165 for (; i < toColumn; i++) {
166 buf.write(colorize('^'));
167 }
168 }
169
170 return buf.toString();
171 }
172 }
173
174 class Utf8BytesSourceFile extends SourceFile {
175 final String filename;
176
177 /** The UTF-8 encoded content of the source file. */
178 final List<int> content;
179
180 Utf8BytesSourceFile(this.filename, this.content);
181
182 String slowText() => UTF8.decode(content);
183
184 List<int> slowUtf8Bytes() => content;
185
186 String slowSubstring(int start, int end) {
187 // TODO(lry): to make this faster, the scanner could record the UTF-8 slack
188 // for all positions of the source text. We could use [:content.sublist:].
189 return slowText().substring(start, end);
190 }
191
192 int get length {
193 if (lengthCache == -1) {
194 // During scanning the length is not yet assigned, so we use a slow path.
195 length = slowText().length;
196 }
197 return lengthCache;
198 }
199 set length(int v) => lengthCache = v;
200 int lengthCache = -1;
201 }
202
203 class CachingUtf8BytesSourceFile extends Utf8BytesSourceFile {
204 String cachedText;
205
206 CachingUtf8BytesSourceFile(String filename, List<int> content)
207 : super(filename, content);
208
209 String slowText() {
210 if (cachedText == null) {
211 cachedText = super.slowText();
212 }
213 return cachedText;
214 }
215 }
216
217 class StringSourceFile extends SourceFile {
218 final String filename;
219 final String text;
220
221 StringSourceFile(this.filename, this.text);
222
223 int get length => text.length;
224 set length(int v) { }
225
226 String slowText() => text;
227
228 List<int> slowUtf8Bytes() => UTF8.encode(text);
229
230 String slowSubstring(int start, int end) => text.substring(start, end);
231 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/scanner/scannerlib.dart ('k') | pkg/compiler/lib/src/source_file_provider.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698