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

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

Issue 421723004: Remove support for the old Span classes from source_maps. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes Created 6 years, 4 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 | « pkg/source_maps/lib/source_maps.dart ('k') | pkg/source_maps/lib/src/source_map_span.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// Dart classes representing the souce spans and source files.
6 library source_maps.span;
7
8 import 'dart:math' show min, max;
9
10 import 'package:path/path.dart' as p;
11
12 import 'src/utils.dart';
13
14 /// A simple class that describe a segment of source text.
15 @Deprecated("Use the source_span package instead.")
16 abstract class Span implements Comparable {
17 /// The start location of this span.
18 final Location start;
19
20 /// The end location of this span, exclusive.
21 final Location end;
22
23 /// Url of the source (typically a file) containing this span.
24 String get sourceUrl => start.sourceUrl;
25
26 /// The length of this span, in characters.
27 int get length => end.offset - start.offset;
28
29 /// The source text for this span, if available.
30 String get text;
31
32 /// Whether [text] corresponds to an identifier symbol.
33 final bool isIdentifier;
34
35 Span(this.start, this.end, bool isIdentifier)
36 : isIdentifier = isIdentifier != null ? isIdentifier : false {
37 _checkRange();
38 }
39
40 /// Creates a new span that is the union of two existing spans [start] and
41 /// [end]. Note that the resulting span might contain some positions that were
42 /// not in either of the original spans if [start] and [end] are disjoint.
43 Span.union(Span start, Span end)
44 : start = start.start, end = end.end, isIdentifier = false {
45 _checkRange();
46 }
47
48 void _checkRange() {
49 if (start.offset < 0) throw new ArgumentError('start $start must be >= 0');
50 if (end.offset < start.offset) {
51 throw new ArgumentError('end $end must be >= start $start');
52 }
53 }
54
55 /// Compares two spans. If the spans are not in the same source, this method
56 /// generates an error.
57 int compareTo(Span other) {
58 int d = start.compareTo(other.start);
59 return d == 0 ? end.compareTo(other.end) : d;
60 }
61
62 /// Gets the location in standard printed form `filename:line:column`, where
63 /// line and column are adjusted by 1 to match the convention in editors.
64 String get formatLocation => start.formatString;
65
66 String getLocationMessage(String message,
67 {bool useColors: false, String color}) {
68 var source = start.sourceUrl == null ? '' :
69 ' of ${p.prettyUri(start.sourceUrl)}';
70 return 'line ${start.line + 1}, column ${start.column + 1}$source: ' +
71 message;
72 }
73
74 bool operator ==(Span other) =>
75 sourceUrl == other.sourceUrl && start == other.start && end == other.end;
76
77 int get hashCode => sourceUrl.hashCode + start.offset + (31 * length);
78
79 String toString() => '<$runtimeType: $start $end $formatLocation $text>';
80 }
81
82 /// A location in the source text
83 @Deprecated("Use the source_span package instead.")
84 abstract class Location implements Comparable {
85 /// Url of the source containing this span.
86 String get sourceUrl;
87
88 /// The offset of this location, 0-based.
89 final int offset;
90
91 /// The 0-based line in the source of this location.
92 int get line;
93
94 /// The 0-based column in the source of this location.
95 int get column;
96
97 Location(this.offset);
98
99 /// Compares two locations. If the locations are not in the same source, this
100 /// method generates an error.
101 int compareTo(Location other) {
102 if (sourceUrl != other.sourceUrl) {
103 throw new ArgumentError('can only compare locations of the same source');
104 }
105 return offset - other.offset;
106 }
107
108 bool operator ==(Location other) =>
109 sourceUrl == other.sourceUrl && offset == other.offset;
110
111 int get hashCode => sourceUrl.hashCode + offset;
112
113 String toString() => '(Location $offset)';
114 String get formatString => '$sourceUrl:${line + 1}:${column + 1}';
115 }
116
117 /// Implementation of [Location] with fixed values given at allocation time.
118 @Deprecated("Use the source_span package instead.")
119 class FixedLocation extends Location {
120 final String sourceUrl;
121 final int line;
122 final int column;
123
124 FixedLocation(int offset, this.sourceUrl, this.line, this.column)
125 : super(offset);
126 }
127
128 /// Implementation of [Span] where all the values are given at allocation time.
129 @Deprecated("Use the source_span package instead.")
130 class FixedSpan extends Span {
131 /// The source text for this span, if available.
132 final String text;
133
134 /// Creates a span which starts and end in the same line.
135 FixedSpan(String sourceUrl, int start, int line, int column,
136 {String text: '', bool isIdentifier: false})
137 : text = text, super(new FixedLocation(start, sourceUrl, line, column),
138 new FixedLocation(start + text.length, sourceUrl, line,
139 column + text.length),
140 isIdentifier);
141 }
142
143 /// [Location] with values computed from an underling [SourceFile].
144 @Deprecated("Use the source_span package instead.")
145 class FileLocation extends Location {
146 /// The source file containing this location.
147 final SourceFile file;
148
149 String get sourceUrl => file.url;
150 int get line => file.getLine(offset);
151 int get column => file.getColumn(line, offset);
152
153 FileLocation(this.file, int offset): super(offset);
154 }
155
156 /// [Span] where values are computed from an underling [SourceFile].
157 @Deprecated("Use the source_span package instead.")
158 class FileSpan extends Span {
159 /// The source file containing this span.
160 final SourceFile file;
161
162 /// The source text for this span, if available.
163 String get text => file.getText(start.offset, end.offset);
164
165 factory FileSpan(SourceFile file, int start,
166 [int end, bool isIdentifier = false]) {
167 var startLoc = new FileLocation(file, start);
168 var endLoc = end == null ? startLoc : new FileLocation(file, end);
169 return new FileSpan.locations(startLoc, endLoc, isIdentifier);
170 }
171
172 FileSpan.locations(FileLocation start, FileLocation end,
173 bool isIdentifier)
174 : file = start.file, super(start, end, isIdentifier);
175
176 /// Creates a new span that is the union of two existing spans [start] and
177 /// [end]. Note that the resulting span might contain some positions that were
178 /// not in either of the original spans if [start] and [end] are disjoint.
179 FileSpan.union(FileSpan start, FileSpan end)
180 : file = start.file, super.union(start, end) {
181 if (start.file != end.file) {
182 throw new ArgumentError('start and end must be from the same file');
183 }
184 }
185
186 String getLocationMessage(String message,
187 {bool useColors: false, String color}) {
188 return file.getLocationMessage(message, start.offset, end.offset,
189 useColors: useColors, color: color);
190 }
191 }
192
193 // Constants to determine end-of-lines.
194 const int _LF = 10;
195 const int _CR = 13;
196
197 // Color constants used for generating messages.
198 const String _RED_COLOR = '\u001b[31m';
199 const String _NO_COLOR = '\u001b[0m';
200
201 /// Stores information about a source file, to permit computation of the line
202 /// and column. Also contains a nice default error message highlighting the code
203 /// location.
204 @Deprecated("Use the source_span package instead.")
205 class SourceFile {
206 /// Url where the source file is located.
207 final String url;
208 final List<int> _lineStarts;
209 final List<int> _decodedChars;
210
211 SourceFile(this.url, this._lineStarts, this._decodedChars);
212
213 SourceFile.text(this.url, String text)
214 : _lineStarts = <int>[0],
215 _decodedChars = text.runes.toList() {
216 for (int i = 0; i < _decodedChars.length; i++) {
217 var c = _decodedChars[i];
218 if (c == _CR) {
219 // Return not followed by newline is treated as a newline
220 int j = i + 1;
221 if (j >= _decodedChars.length || _decodedChars[j] != _LF) {
222 c = _LF;
223 }
224 }
225 if (c == _LF) _lineStarts.add(i + 1);
226 }
227 }
228
229 /// Returns a span in this [SourceFile] with the given offsets.
230 Span span(int start, [int end, bool isIdentifier = false]) =>
231 new FileSpan(this, start, end, isIdentifier);
232
233 /// Returns a location in this [SourceFile] with the given offset.
234 Location location(int offset) => new FileLocation(this, offset);
235
236 /// Gets the 0-based line corresponding to an offset.
237 int getLine(int offset) => binarySearch(_lineStarts, (o) => o > offset) - 1;
238
239 /// Gets the 0-based column corresponding to an offset.
240 int getColumn(int line, int offset) {
241 if (line < 0 || line >= _lineStarts.length) return 0;
242 return offset - _lineStarts[line];
243 }
244
245 /// Get the offset for a given line and column
246 int getOffset(int line, int column) {
247 if (line < 0) return getOffset(0, 0);
248 if (line < _lineStarts.length) {
249 return _lineStarts[line] + column;
250 } else {
251 return _decodedChars.length;
252 }
253 }
254
255 /// Gets the text at the given offsets.
256 String getText(int start, [int end]) =>
257 new String.fromCharCodes(_decodedChars.sublist(max(start, 0), end));
258
259 /// Create a pretty string representation from a span.
260 String getLocationMessage(String message, int start, int end,
261 {bool useColors: false, String color}) {
262 // TODO(jmesserly): it would be more useful to pass in an object that
263 // controls how the errors are printed. This method is a bit too smart.
264 var line = getLine(start);
265 var column = getColumn(line, start);
266
267 var source = url == null ? '' : ' of ${p.prettyUri(url)}';
268 var msg = 'line ${line + 1}, column ${column + 1}$source: $message';
269
270 if (_decodedChars == null) {
271 // We don't have any text to include, so exit.
272 return msg;
273 }
274
275 var buf = new StringBuffer(msg);
276 buf.write('\n');
277
278 // +1 for 0-indexing, +1 again to avoid the last line
279 var textLine = getText(getOffset(line, 0), getOffset(line + 1, 0));
280
281 column = min(column, textLine.length - 1);
282 int toColumn = min(column + end - start, textLine.length);
283 if (useColors) {
284 if (color == null) {
285 color = _RED_COLOR;
286 }
287 buf.write(textLine.substring(0, column));
288 buf.write(color);
289 buf.write(textLine.substring(column, toColumn));
290 buf.write(_NO_COLOR);
291 buf.write(textLine.substring(toColumn));
292 } else {
293 buf.write(textLine);
294 if (textLine != '' && !textLine.endsWith('\n')) buf.write('\n');
295 }
296
297 int i = 0;
298 for (; i < column; i++) {
299 buf.write(' ');
300 }
301
302 if (useColors) buf.write(color);
303 for (; i < toColumn; i++) {
304 buf.write('^');
305 }
306 if (useColors) buf.write(_NO_COLOR);
307 return buf.toString();
308 }
309 }
310
311 /// A convenience type to treat a code segment as if it were a separate
312 /// [SourceFile]. A [SourceFileSegment] shifts all locations by an offset, which
313 /// allows you to set source-map locations based on the locations relative to
314 /// the start of the segment, but that get translated to absolute locations in
315 /// the original source file.
316 @Deprecated("Use the source_span package instead.")
317 class SourceFileSegment extends SourceFile {
318 final int _baseOffset;
319 final int _baseLine;
320 final int _baseColumn;
321 final int _maxOffset;
322
323 SourceFileSegment(String url, String textSegment, Location startOffset)
324 : _baseOffset = startOffset.offset,
325 _baseLine = startOffset.line,
326 _baseColumn = startOffset.column,
327 _maxOffset = startOffset.offset + textSegment.length,
328 super.text(url, textSegment);
329
330 /// Craete a span, where [start] is relative to this segment's base offset.
331 /// The returned span stores the real offset on the file, so that error
332 /// messages are reported at the real location.
333 Span span(int start, [int end, bool isIdentifier = false]) =>
334 super.span(start + _baseOffset,
335 end == null ? null : end + _baseOffset, isIdentifier);
336
337 /// Create a location, where [offset] relative to this segment's base offset.
338 /// The returned span stores the real offset on the file, so that error
339 /// messages are reported at the real location.
340 Location location(int offset) => super.location(offset + _baseOffset);
341
342 /// Return the line on the underlying file associated with the [offset] of the
343 /// underlying file. This method operates on the real offsets from the
344 /// original file, so that error messages can be reported accurately. When the
345 /// requested offset is past the length of the segment, this returns the line
346 /// number after the end of the segment (total lines + 1).
347 int getLine(int offset) {
348 var res = super.getLine(max(offset - _baseOffset, 0)) + _baseLine;
349 return (offset > _maxOffset) ? res + 1 : res;
350 }
351
352 /// Return the column on the underlying file associated with [line] and
353 /// [offset], where [line] is absolute from the beginning of the underlying
354 /// file. This method operates on the real offsets from the original file, so
355 /// that error messages can be reported accurately.
356 int getColumn(int line, int offset) {
357 var col = super.getColumn(line - _baseLine, max(offset - _baseOffset, 0));
358 return line == _baseLine ? col + _baseColumn : col;
359 }
360
361 /// Return the offset associated with a line and column. This method operates
362 /// on the real offsets from the original file, so that error messages can be
363 /// reported accurately.
364 int getOffset(int line, int column) =>
365 super.getOffset(line - _baseLine,
366 line == _baseLine ? column - _baseColumn : column) + _baseOffset;
367
368 /// Retrieve the text associated with the specified range. This method
369 /// operates on the real offsets from the original file, so that error
370 /// messages can be reported accurately.
371 String getText(int start, [int end]) =>
372 super.getText(start - _baseOffset, end == null ? null : end - _baseOffset);
373 }
374
375 /// A class for exceptions that have source span information attached.
376 @Deprecated("Use the source_span package instead.")
377 class SpanException implements Exception {
378 /// A message describing the exception.
379 final String message;
380
381 /// The span associated with this exception.
382 ///
383 /// This may be `null` if the source location can't be determined.
384 final Span span;
385
386 SpanException(this.message, this.span);
387
388 String toString({bool useColors: false, String color}) {
389 if (span == null) return message;
390 return "Error on " + span.getLocationMessage(message,
391 useColors: useColors, color: color);
392 }
393 }
394
395 /// A [SpanException] that's also a [FormatException].
396 @Deprecated("Use the source_span package instead.")
397 class SpanFormatException extends SpanException implements FormatException {
398 final source;
399
400 SpanFormatException(String message, Span span, [this.source])
401 : super(message, span);
402
403 int get offset => span == null ? null : span.start.offset;
404 }
OLDNEW
« no previous file with comments | « pkg/source_maps/lib/source_maps.dart ('k') | pkg/source_maps/lib/src/source_map_span.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698