OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.io.source_file; | 5 library dart2js.io.source_file; |
6 | 6 |
7 import 'dart:math'; | 7 import 'dart:math'; |
8 import 'dart:convert' show UTF8; | 8 import 'dart:convert' show UTF8; |
9 import 'dart:typed_data' show Uint8List; | 9 import 'dart:typed_data' show Uint8List; |
10 | 10 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 } | 108 } |
109 | 109 |
110 /** | 110 /** |
111 * Returns the column number for the offset [position] in the string | 111 * Returns the column number for the offset [position] in the string |
112 * representation of this source file. | 112 * representation of this source file. |
113 */ | 113 */ |
114 int getColumn(int line, int position) { | 114 int getColumn(int line, int position) { |
115 return position - lineStarts[line]; | 115 return position - lineStarts[line]; |
116 } | 116 } |
117 | 117 |
| 118 /// Returns the offset for 0-based [line] and [column] numbers. |
| 119 int getOffset(int line, int column) => lineStarts[line] + column; |
| 120 |
118 String slowSubstring(int start, int end); | 121 String slowSubstring(int start, int end); |
119 | 122 |
120 /** | 123 /** |
121 * Create a pretty string representation for [message] from a character | 124 * Create a pretty string representation for [message] from a character |
122 * range `[start, end]` in this file. | 125 * range `[start, end]` in this file. |
123 * | 126 * |
124 * If [includeSourceLine] is `true` the first source line code line that | 127 * If [includeSourceLine] is `true` the first source line code line that |
125 * contains the range will be included as well as marker characters ('^') | 128 * contains the range will be included as well as marker characters ('^') |
126 * underlining the range. | 129 * underlining the range. |
127 * | 130 * |
(...skipping 10 matching lines...) Expand all Loading... |
138 var column = getColumn(line, start); | 141 var column = getColumn(line, start); |
139 | 142 |
140 var buf = new StringBuffer('${filename}:'); | 143 var buf = new StringBuffer('${filename}:'); |
141 if (start != end || start != 0) { | 144 if (start != end || start != 0) { |
142 // Line/column info is relevant. | 145 // Line/column info is relevant. |
143 buf.write('${line + 1}:${column + 1}:'); | 146 buf.write('${line + 1}:${column + 1}:'); |
144 } | 147 } |
145 buf.write('\n$message\n'); | 148 buf.write('\n$message\n'); |
146 | 149 |
147 if (start != end && includeSourceLine) { | 150 if (start != end && includeSourceLine) { |
148 String textLine; | 151 String textLine = getLineText(line); |
149 // +1 for 0-indexing, +1 again to avoid the last line of the file | |
150 if ((line + 2) < lineStarts.length) { | |
151 textLine = slowSubstring(lineStarts[line], lineStarts[line+1]); | |
152 } else { | |
153 textLine = '${slowSubstring(lineStarts[line], length)}\n'; | |
154 } | |
155 | 152 |
156 int toColumn = min(column + (end-start), textLine.length); | 153 int toColumn = min(column + (end-start), textLine.length); |
157 buf.write(textLine.substring(0, column)); | 154 buf.write(textLine.substring(0, column)); |
158 buf.write(colorize(textLine.substring(column, toColumn))); | 155 buf.write(colorize(textLine.substring(column, toColumn))); |
159 buf.write(textLine.substring(toColumn)); | 156 buf.write(textLine.substring(toColumn)); |
160 | 157 |
161 int i = 0; | 158 int i = 0; |
162 for (; i < column; i++) { | 159 for (; i < column; i++) { |
163 buf.write(' '); | 160 buf.write(' '); |
164 } | 161 } |
165 | 162 |
166 for (; i < toColumn; i++) { | 163 for (; i < toColumn; i++) { |
167 buf.write(colorize('^')); | 164 buf.write(colorize('^')); |
168 } | 165 } |
169 } | 166 } |
170 | 167 |
171 return buf.toString(); | 168 return buf.toString(); |
172 } | 169 } |
| 170 |
| 171 int get lines => lineStarts.length - 1; |
| 172 |
| 173 /// Returns the text of line at the 0-based [index] within this source file. |
| 174 String getLineText(int index) { |
| 175 // +1 for 0-indexing, +1 again to avoid the last line of the file |
| 176 if ((index + 2) < lineStarts.length) { |
| 177 return slowSubstring(lineStarts[index], lineStarts[index+1]); |
| 178 } else if ((index + 1) < lineStarts.length) { |
| 179 return '${slowSubstring(lineStarts[index], length)}\n'; |
| 180 } else { |
| 181 throw new ArgumentError("Line index $index is out of bounds."); |
| 182 } |
| 183 } |
173 } | 184 } |
174 | 185 |
175 List<int> _zeroTerminateIfNecessary(List<int> bytes) { | 186 List<int> _zeroTerminateIfNecessary(List<int> bytes) { |
176 if (bytes.length > 0 && bytes.last == 0) return bytes; | 187 if (bytes.length > 0 && bytes.last == 0) return bytes; |
177 List<int> result = new Uint8List(bytes.length + 1); | 188 List<int> result = new Uint8List(bytes.length + 1); |
178 result.setRange(0, bytes.length, bytes); | 189 result.setRange(0, bytes.length, bytes); |
179 result[result.length - 1] = 0; | 190 result[result.length - 1] = 0; |
180 return result; | 191 return result; |
181 } | 192 } |
182 | 193 |
(...skipping 22 matching lines...) Expand all Loading... |
205 | 216 |
206 String slowSubstring(int start, int end) { | 217 String slowSubstring(int start, int end) { |
207 // TODO(lry): to make this faster, the scanner could record the UTF-8 slack | 218 // TODO(lry): to make this faster, the scanner could record the UTF-8 slack |
208 // for all positions of the source text. We could use [:content.sublist:]. | 219 // for all positions of the source text. We could use [:content.sublist:]. |
209 return slowText().substring(start, end); | 220 return slowText().substring(start, end); |
210 } | 221 } |
211 | 222 |
212 int get length { | 223 int get length { |
213 if (lengthCache == -1) { | 224 if (lengthCache == -1) { |
214 // During scanning the length is not yet assigned, so we use a slow path. | 225 // During scanning the length is not yet assigned, so we use a slow path. |
215 length = slowText().length; | 226 lengthCache = slowText().length; |
216 } | 227 } |
217 return lengthCache; | 228 return lengthCache; |
218 } | 229 } |
219 set length(int v) => lengthCache = v; | 230 set length(int v) => lengthCache = v; |
220 int lengthCache = -1; | 231 int lengthCache = -1; |
221 } | 232 } |
222 | 233 |
223 class CachingUtf8BytesSourceFile extends Utf8BytesSourceFile { | 234 class CachingUtf8BytesSourceFile extends Utf8BytesSourceFile { |
224 String cachedText; | 235 String cachedText; |
225 final String filename; | 236 final String filename; |
(...skipping 26 matching lines...) Expand all Loading... |
252 set length(int v) { } | 263 set length(int v) { } |
253 | 264 |
254 String slowText() => text; | 265 String slowText() => text; |
255 | 266 |
256 List<int> slowUtf8ZeroTerminatedBytes() { | 267 List<int> slowUtf8ZeroTerminatedBytes() { |
257 return _zeroTerminateIfNecessary(UTF8.encode(text)); | 268 return _zeroTerminateIfNecessary(UTF8.encode(text)); |
258 } | 269 } |
259 | 270 |
260 String slowSubstring(int start, int end) => text.substring(start, end); | 271 String slowSubstring(int start, int end) => text.substring(start, end); |
261 } | 272 } |
OLD | NEW |