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

Side by Side Diff: lib/src/file.dart

Issue 1028813002: Introduce span with line context (Closed) Base URL: git@github.com:dart-lang/source_span.git@master
Patch Set: Created 5 years, 8 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
« no previous file with comments | « lib/source_span.dart ('k') | lib/src/span_mixin.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 source_span.file; 5 library source_span.file;
6 6
7 import 'dart:math' as math; 7 import 'dart:math' as math;
8 import 'dart:typed_data'; 8 import 'dart:typed_data';
9 9
10 import 'package:path/path.dart' as p; 10 import 'package:path/path.dart' as p;
11 11
12 import 'colors.dart' as colors; 12 import 'colors.dart' as colors;
13 import 'location.dart'; 13 import 'location.dart';
14 import 'span.dart'; 14 import 'span.dart';
15 import 'span_mixin.dart'; 15 import 'span_mixin.dart';
16 import 'span_with_context.dart';
16 import 'utils.dart'; 17 import 'utils.dart';
17 18
18 // Constants to determine end-of-lines. 19 // Constants to determine end-of-lines.
19 const int _LF = 10; 20 const int _LF = 10;
20 const int _CR = 13; 21 const int _CR = 13;
21 22
22 /// A class representing a source file. 23 /// A class representing a source file.
23 /// 24 ///
24 /// This doesn't necessarily have to correspond to a file on disk, just a chunk 25 /// This doesn't necessarily have to correspond to a file on disk, just a chunk
25 /// of text usually with a URL associated with it. 26 /// of text usually with a URL associated with it.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 } 177 }
177 178
178 /// A [SourceSpan] within a [SourceFile]. 179 /// A [SourceSpan] within a [SourceFile].
179 /// 180 ///
180 /// Unlike the base [SourceSpan], [FileSpan] lazily computes its line and column 181 /// Unlike the base [SourceSpan], [FileSpan] lazily computes its line and column
181 /// values based on its offset and the contents of [file]. [FileSpan.message] is 182 /// values based on its offset and the contents of [file]. [FileSpan.message] is
182 /// also able to provide more context then [SourceSpan.message], and 183 /// also able to provide more context then [SourceSpan.message], and
183 /// [FileSpan.union] will return a [FileSpan] if possible. 184 /// [FileSpan.union] will return a [FileSpan] if possible.
184 /// 185 ///
185 /// A [FileSpan] can be created using [SourceFile.span]. 186 /// A [FileSpan] can be created using [SourceFile.span].
186 class FileSpan extends SourceSpanMixin { 187 class FileSpan extends SourceSpanMixin implements SourceSpanWithContext {
187 /// The [file] that [this] belongs to. 188 /// The [file] that [this] belongs to.
188 final SourceFile file; 189 final SourceFile file;
189 190
190 /// The offset of the beginning of the span. 191 /// The offset of the beginning of the span.
191 /// 192 ///
192 /// [start] is lazily generated from this to avoid allocating unnecessary 193 /// [start] is lazily generated from this to avoid allocating unnecessary
193 /// objects. 194 /// objects.
194 final int _start; 195 final int _start;
195 196
196 /// The offset of the end of the span. 197 /// The offset of the end of the span.
197 /// 198 ///
198 /// [end] is lazily generated from this to avoid allocating unnecessary 199 /// [end] is lazily generated from this to avoid allocating unnecessary
199 /// objects. 200 /// objects.
200 final int _end; 201 final int _end;
201 202
202 Uri get sourceUrl => file.url; 203 Uri get sourceUrl => file.url;
203 int get length => _end - _start; 204 int get length => _end - _start;
204 FileLocation get start => new FileLocation._(file, _start); 205 FileLocation get start => new FileLocation._(file, _start);
205 FileLocation get end => new FileLocation._(file, _end); 206 FileLocation get end => new FileLocation._(file, _end);
206 String get text => file.getText(_start, _end); 207 String get text => file.getText(_start, _end);
207 208
209 String get context {
210 var line = start.line;
211 return file.getText(file.getOffset(line),
212 line == file.lines - 1 ? null : file.getOffset(line + 1));
213 }
214
208 FileSpan._(this.file, this._start, this._end) { 215 FileSpan._(this.file, this._start, this._end) {
209 if (_end < _start) { 216 if (_end < _start) {
210 throw new ArgumentError('End $_end must come after start $_start.'); 217 throw new ArgumentError('End $_end must come after start $_start.');
211 } else if (_end > file.length) { 218 } else if (_end > file.length) {
212 throw new RangeError("End $_end must not be greater than the number " 219 throw new RangeError("End $_end must not be greater than the number "
213 "of characters in the file, ${file.length}."); 220 "of characters in the file, ${file.length}.");
214 } else if (_start < 0) { 221 } else if (_start < 0) {
215 throw new RangeError("Start may not be negative, was $_start."); 222 throw new RangeError("Start may not be negative, was $_start.");
216 } 223 }
217 } 224 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 FileSpan expand(FileSpan other) { 261 FileSpan expand(FileSpan other) {
255 if (sourceUrl != other.sourceUrl) { 262 if (sourceUrl != other.sourceUrl) {
256 throw new ArgumentError("Source URLs \"${sourceUrl}\" and " 263 throw new ArgumentError("Source URLs \"${sourceUrl}\" and "
257 " \"${other.sourceUrl}\" don't match."); 264 " \"${other.sourceUrl}\" don't match.");
258 } 265 }
259 266
260 var start = math.min(this._start, other._start); 267 var start = math.min(this._start, other._start);
261 var end = math.max(this._end, other._end); 268 var end = math.max(this._end, other._end);
262 return new FileSpan._(file, start, end); 269 return new FileSpan._(file, start, end);
263 } 270 }
264
265 String message(String message, {color}) {
266 if (color == true) color = colors.RED;
267 if (color == false) color = null;
268
269 var line = start.line;
270 var column = start.column;
271
272 var buffer = new StringBuffer();
273 buffer.write('line ${start.line + 1}, column ${start.column + 1}');
274 if (sourceUrl != null) buffer.write(' of ${p.prettyUri(sourceUrl)}');
275 buffer.write(': $message\n');
276
277 var textLine = file.getText(file.getOffset(line),
278 line == file.lines - 1 ? null : file.getOffset(line + 1));
279
280 column = math.min(column, textLine.length - 1);
281 var toColumn =
282 math.min(column + end.offset - start.offset, textLine.length);
283
284 if (color != null) {
285 buffer.write(textLine.substring(0, column));
286 buffer.write(color);
287 buffer.write(textLine.substring(column, toColumn));
288 buffer.write(colors.NONE);
289 buffer.write(textLine.substring(toColumn));
290 } else {
291 buffer.write(textLine);
292 }
293 if (!textLine.endsWith('\n')) buffer.write('\n');
294
295 buffer.write(' ' * column);
296 if (color != null) buffer.write(color);
297 buffer.write('^' * math.max(toColumn - column, 1));
298 if (color != null) buffer.write(colors.NONE);
299 return buffer.toString();
300 }
301 } 271 }
OLDNEW
« no previous file with comments | « lib/source_span.dart ('k') | lib/src/span_mixin.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698