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

Side by Side Diff: pkg/source_maps/lib/span.dart

Issue 18083030: Fixes source map bug: getLocationMessage was incorrect on file segments (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 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
« no previous file with comments | « no previous file | pkg/source_maps/test/span_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /// Dart classes representing the souce spans and source files. 5 /// Dart classes representing the souce spans and source files.
6 library source_maps.span; 6 library source_maps.span;
7 7
8 import 'dart:utf' show stringToCodepoints; 8 import 'dart:utf' show stringToCodepoints;
9 import 'dart:math' show min; 9 import 'dart:math' show min, max;
10 10
11 import 'src/utils.dart'; 11 import 'src/utils.dart';
12 12
13 /// A simple class that describe a segment of source text. 13 /// A simple class that describe a segment of source text.
14 abstract class Span implements Comparable { 14 abstract class Span implements Comparable {
15 /// The start location of this span. 15 /// The start location of this span.
16 final Location start; 16 final Location start;
17 17
18 /// The end location of this span, exclusive. 18 /// The end location of this span, exclusive.
19 final Location end; 19 final Location end;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 } 209 }
210 210
211 /// Returns a span in this [SourceFile] with the given offsets. 211 /// Returns a span in this [SourceFile] with the given offsets.
212 Span span(int start, [int end, bool isIdentifier = false]) => 212 Span span(int start, [int end, bool isIdentifier = false]) =>
213 new FileSpan(this, start, end, isIdentifier); 213 new FileSpan(this, start, end, isIdentifier);
214 214
215 /// Returns a location in this [SourceFile] with the given offset. 215 /// Returns a location in this [SourceFile] with the given offset.
216 Location location(int offset) => new FileLocation(this, offset); 216 Location location(int offset) => new FileLocation(this, offset);
217 217
218 /// Gets the 0-based line corresponding to an offset. 218 /// Gets the 0-based line corresponding to an offset.
219 int getLine(int offset) { 219 int getLine(int offset) => binarySearch(_lineStarts, (o) => o > offset) - 1;
220 return binarySearch(_lineStarts, (o) => o > offset) - 1;
221 }
222 220
223 /// Gets the 0-based column corresponding to an offset. 221 /// Gets the 0-based column corresponding to an offset.
224 int getColumn(int line, int offset) { 222 int getColumn(int line, int offset) => offset - _lineStarts[line];
225 return offset - _lineStarts[line];
226 }
227 223
228 /// Get the offset for a given line and column 224 /// Get the offset for a given line and column
229 int getOffset(int line, int column) { 225 int getOffset(int line, int column) =>
230 return _lineStarts[min(line, _lineStarts.length - 1)] + column; 226 _lineStarts[max(min(line, _lineStarts.length - 1), 0)] + column;
231 }
232 227
233 /// Gets the text at the given offsets. 228 /// Gets the text at the given offsets.
234 String getText(int start, [int end]) { 229 String getText(int start, [int end]) =>
235 return new String.fromCharCodes(_decodedChars.sublist(start, end)); 230 new String.fromCharCodes(_decodedChars.sublist(max(start, 0), end));
236 }
237 231
238 /// Create a pretty string representation from a span. 232 /// Create a pretty string representation from a span.
239 String getLocationMessage(String message, int start, int end, 233 String getLocationMessage(String message, int start, int end,
240 {bool useColors: false, String color}) { 234 {bool useColors: false, String color}) {
241 // TODO(jmesserly): it would be more useful to pass in an object that 235 // TODO(jmesserly): it would be more useful to pass in an object that
242 // controls how the errors are printed. This method is a bit too smart. 236 // controls how the errors are printed. This method is a bit too smart.
243 var line = getLine(start); 237 var line = getLine(start);
244 var column = getColumn(line, start); 238 var column = getColumn(line, start);
245 239
246 var src = url == null ? '' : url; 240 var src = url == null ? '' : url;
247 var msg = '$src:${line + 1}:${column + 1}: $message'; 241 var msg = '$src:${line + 1}:${column + 1}: $message';
248 242
249 if (_decodedChars == null) { 243 if (_decodedChars == null) {
250 // We don't have any text to include, so exit. 244 // We don't have any text to include, so exit.
251 return msg; 245 return msg;
252 } 246 }
253 247
254 var buf = new StringBuffer(msg); 248 var buf = new StringBuffer(msg);
255 buf.write('\n'); 249 buf.write('\n');
256 var textLine;
257 250
258 // +1 for 0-indexing, +1 again to avoid the last line 251 // +1 for 0-indexing, +1 again to avoid the last line
259 if ((line + 2) < _lineStarts.length) { 252 var textLine = getText(getOffset(line, 0), getOffset(line + 1, 0));
260 textLine = getText(_lineStarts[line], _lineStarts[line + 1]);
261 } else {
262 textLine = getText(_lineStarts[line]);
263 textLine = '$textLine\n';
264 }
265 253
254
255 column = min(column, textLine.length - 1);
266 int toColumn = min(column + end - start, textLine.length); 256 int toColumn = min(column + end - start, textLine.length);
267 if (useColors) { 257 if (useColors) {
268 if (color == null) { 258 if (color == null) {
269 color = _RED_COLOR; 259 color = _RED_COLOR;
270 } 260 }
271 buf.write(textLine.substring(0, column)); 261 buf.write(textLine.substring(0, column));
272 buf.write(color); 262 buf.write(color);
273 buf.write(textLine.substring(column, toColumn)); 263 buf.write(textLine.substring(column, toColumn));
274 buf.write(_NO_COLOR); 264 buf.write(_NO_COLOR);
275 buf.write(textLine.substring(toColumn)); 265 buf.write(textLine.substring(toColumn));
(...skipping 18 matching lines...) Expand all
294 /// A convenience type to treat a code segment as if it were a separate 284 /// A convenience type to treat a code segment as if it were a separate
295 /// [SourceFile]. A [SourceFileSegment] shifts all locations by an offset, which 285 /// [SourceFile]. A [SourceFileSegment] shifts all locations by an offset, which
296 /// allows you to set source-map locations based on the locations relative to 286 /// allows you to set source-map locations based on the locations relative to
297 /// the start of the segment, but that get translated to absolute locations in 287 /// the start of the segment, but that get translated to absolute locations in
298 /// the original source file. 288 /// the original source file.
299 class SourceFileSegment extends SourceFile { 289 class SourceFileSegment extends SourceFile {
300 final int _baseOffset; 290 final int _baseOffset;
301 final int _baseLine; 291 final int _baseLine;
302 final int _baseColumn; 292 final int _baseColumn;
303 293
294 // TODO(sigmund): consider providing an end-offset to correctly truncate
295 // values passed the end of the segment.
304 SourceFileSegment(String url, String textSegment, Location startOffset) 296 SourceFileSegment(String url, String textSegment, Location startOffset)
305 : _baseOffset = startOffset.offset, 297 : _baseOffset = startOffset.offset,
306 _baseLine = startOffset.line, 298 _baseLine = startOffset.line,
307 _baseColumn = startOffset.column, 299 _baseColumn = startOffset.column,
308 super.text(url, textSegment); 300 super.text(url, textSegment);
309 301
302 /// Craete a span, where [start] is relative to this segment's base offset.
303 /// The returned span stores the real offset on the file, so that error
304 /// messages are reported at the real location.
310 Span span(int start, [int end, bool isIdentifier = false]) => 305 Span span(int start, [int end, bool isIdentifier = false]) =>
311 super.span(start + _baseOffset, 306 super.span(start + _baseOffset,
312 end == null ? null : end + _baseOffset, isIdentifier); 307 end == null ? null : end + _baseOffset, isIdentifier);
313 308
309 /// Create a location, where [offset] relative to this segment's base offset.
310 /// The returned span stores the real offset on the file, so that error
311 /// messages are reported at the real location.
314 Location location(int offset) => super.location(offset + _baseOffset); 312 Location location(int offset) => super.location(offset + _baseOffset);
315 313
314 /// Return the line on the underlying file associated with the [offset] of the
315 /// underlying file. This API operates on the real offsets from the original
Jennifer Messerly 2013/07/03 21:58:22 "method" instead of "API"? same below
Siggi Cherem (dart-lang) 2013/07/03 22:24:54 Done.
316 /// file, so that error messages can be reported accurately.
316 int getLine(int offset) => 317 int getLine(int offset) =>
317 super.getLine(offset - _baseOffset) + _baseLine; 318 super.getLine(max(offset - _baseOffset, 0)) + _baseLine;
318 319
320 /// Return the column on the underlying file associated with [line] and
321 /// [offset], where [line] is absolute from the beginning of the underlying
322 /// file. This API operates on the real offsets from the original file, so
323 /// that error messages can be reported accurately.
319 int getColumn(int line, int offset) { 324 int getColumn(int line, int offset) {
320 var col = super.getColumn(line - _baseLine, offset - _baseOffset); 325 var col = super.getColumn(line - _baseLine, max(offset - _baseOffset, 0));
321 return line == _baseLine ? col + _baseColumn : col; 326 return line == _baseLine ? col + _baseColumn : col;
322 } 327 }
323 328
329 /// Return the offset associated with a line and column. As above, this API
Jennifer Messerly 2013/07/03 21:58:22 perhaps worth avoiding the term "above" in a doc c
Siggi Cherem (dart-lang) 2013/07/03 22:24:54 Done.
330 /// operates on the real offsets from the original file, so that error
331 /// messages can be reported accurately.
324 int getOffset(int line, int column) => 332 int getOffset(int line, int column) =>
325 super.getOffset(line - _baseLine, 333 super.getOffset(line - _baseLine,
326 line == _baseLine ? column - _baseColumn : column) + _baseOffset; 334 line == _baseLine ? column - _baseColumn : column) + _baseOffset;
327 335
336 /// Retrieve the text associated with the specified range. As above, this API
337 /// operates on the real offsets from the original file, so that error
338 /// messages can be reported accurately.
328 String getText(int start, [int end]) => 339 String getText(int start, [int end]) =>
329 super.getText(start - _baseOffset, end - _baseOffset); 340 super.getText(start - _baseOffset,
341 end == null ? null : end - _baseOffset);
330 } 342 }
OLDNEW
« no previous file with comments | « no previous file | pkg/source_maps/test/span_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698