Line data Source code
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
3 : // BSD-style license that can be found in the LICENSE file.
4 :
5 : import 'location.dart';
6 : import 'span_mixin.dart';
7 :
8 : /// A class that describes a segment of source text.
9 : abstract class SourceSpan implements Comparable<SourceSpan> {
10 : /// The start location of this span.
11 : final SourceLocation start;
12 :
13 : /// The end location of this span, exclusive.
14 : final SourceLocation end;
15 :
16 : /// The source text for this span.
17 : final String text;
18 :
19 : /// The URL of the source (typically a file) of this span.
20 : ///
21 : /// This may be null, indicating that the source URL is unknown or
22 : /// unavailable.
23 : final Uri sourceUrl;
24 :
25 : /// The length of this span, in characters.
26 : final int length;
27 :
28 : /// Creates a new span from [start] to [end] (exclusive) containing [text].
29 : ///
30 : /// [start] and [end] must have the same source URL and [start] must come
31 : /// before [end]. [text] must have a number of characters equal to the
32 : /// distance between [start] and [end].
33 : factory SourceSpan(SourceLocation start, SourceLocation end, String text) =>
34 0 : new SourceSpanBase(start, end, text);
35 :
36 : /// Creates a new span that's the union of [this] and [other].
37 : ///
38 : /// The two spans must have the same source URL and may not be disjoint.
39 : /// [text] is computed by combining [this.text] and [other.text].
40 : SourceSpan union(SourceSpan other);
41 :
42 : /// Compares two spans.
43 : ///
44 : /// [other] must have the same source URL as [this]. This orders spans by
45 : /// [start] then [length].
46 : int compareTo(SourceSpan other);
47 :
48 : /// Formats [message] in a human-friendly way associated with this span.
49 : ///
50 : /// [color] may either be a [String], a [bool], or `null`. If it's a string,
51 : /// it indicates an ANSII terminal color escape that should be used to
52 : /// highlight the span's text. If it's `true`, it indicates that the text
53 : /// should be highlighted using the default color. If it's `false` or `null`,
54 : /// it indicates that the text shouldn't be highlighted.
55 : String message(String message, {color});
56 :
57 : /// Prints the text associated with this span in a user-friendly way.
58 : ///
59 : /// This is identical to [message], except that it doesn't print the file
60 : /// name, line number, column number, or message. If [length] is 0 and this
61 : /// isn't a [SourceSpanWithContext], returns an empty string.
62 : ///
63 : /// [color] may either be a [String], a [bool], or `null`. If it's a string,
64 : /// it indicates an ANSII terminal color escape that should be used to
65 : /// highlight the span's text. If it's `true`, it indicates that the text
66 : /// should be highlighted using the default color. If it's `false` or `null`,
67 : /// it indicates that the text shouldn't be highlighted.
68 : String highlight({color});
69 : }
70 :
71 : /// A base class for source spans with [start], [end], and [text] known at
72 : /// construction time.
73 : class SourceSpanBase extends SourceSpanMixin {
74 : final SourceLocation start;
75 : final SourceLocation end;
76 : final String text;
77 :
78 0 : SourceSpanBase(this.start, this.end, this.text) {
79 0 : if (end.sourceUrl != start.sourceUrl) {
80 0 : throw new ArgumentError("Source URLs \"${start.sourceUrl}\" and "
81 0 : " \"${end.sourceUrl}\" don't match.");
82 0 : } else if (end.offset < start.offset) {
83 0 : throw new ArgumentError('End $end must come after start $start.');
84 0 : } else if (text.length != start.distance(end)) {
85 0 : throw new ArgumentError('Text "$text" must be ${start.distance(end)} '
86 0 : 'characters long.');
87 : }
88 : }
89 : }
|