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

Side by Side Diff: code_transformers/lib/messages/messages.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 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 | « code_transformers/lib/messages/build_logger.dart ('k') | code_transformers/lib/resolver.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) 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 /// Defines messages templates and an adapter for TransformLogger to be able
6 /// report error messages from transformers and refer to them in a consistent
7 /// manner long term.
8 library code_transformers.messages;
9
10 // Note: this library purposely doesn't depend on dart:io, dart:html, or barback
11 // so it can easily be used both in the transformers and in client-side apps
12 // (for example in the log_injector).
13 import 'dart:collection' show LinkedHashMap;
14 import 'package:source_span/source_span.dart';
15
16 /// A globally unique identifier for an error message. This identifier should be
17 /// stable, that is, it should never change after it is asigned to a particular
18 /// message. That allows us to document our error messages and make them
19 /// searchable for prosperity.
20 class MessageId implements Comparable {
21 /// Name of the package that declares this message.
22 final String package;
23
24 /// Message identifier number, unique within the package.
25 final int id;
26
27 const MessageId(this.package, this.id);
28
29 static const MessageId NOT_SPECIFIED = const MessageId('unknown', 0);
30
31 /// Serialize this message. We use a string and not a map to encode ids so
32 /// they can be used as keys in JSON maps.
33 String toJson() => toString();
34
35 toString() => '${package}#$id';
36
37 int compareTo(MessageId other) {
38 var res = package.compareTo(other.package);
39 if (res != 0) return res;
40 return id.compareTo(other.id);
41 }
42
43 /// Creates a new [MessageId] from an encoded value produced via [toJson].
44 factory MessageId.fromJson(data) {
45 var index = data.lastIndexOf('#');
46 if (index == -1) throw 'Invalid message id: $data';
47 return new MessageId(
48 data.substring(0, index), int.parse(data.substring(index + 1)));
49 }
50
51 operator ==(MessageId other) => package == other.package && id == other.id;
52 int get hashCode => 31 * package.hashCode + id;
53 }
54
55 /// An instance of an error message. These are typically produced from a
56 /// [MessageTemplate].
57 class Message {
58 /// A globally unique identifier for this message.
59 final MessageId id;
60
61 /// A snippet message that is presented to the user.
62 final String snippet;
63
64 const Message(this.id, this.snippet);
65
66 const Message.unknown(this.snippet) : id = MessageId.NOT_SPECIFIED;
67
68 /// Serializes this message to JSON.
69 Map toJson() => {'id': id.toJson(), 'snippet': snippet};
70 String toString() => 'id: $id, snippet: $snippet';
71
72 /// Creates a new [Message] from an encoded value produced via [toJson].
73 factory Message.fromJson(data) =>
74 new Message(new MessageId.fromJson(data['id']), data['snippet']);
75 }
76
77 /// Template for a message. Templates can include placeholders to indicate
78 /// values that are different for each instance of the error. Calling [create]
79 /// will generate the actual message, with the placeholders replaced with
80 /// values. If there are no placeholders, an instance of [MessageTemplate] is a
81 /// valid instance of [Message] as well.
82 class MessageTemplate implements Message {
83 /// Unique and stable id for the message.
84 final MessageId id;
85
86 /// Template message with placeholders of the form `%-name-%`.
87 final String snippetTemplate;
88
89 /// This returns the message snippet, only if it the template has no
90 /// placeholders, otherwise this throws an exception. Most messages have no
91 /// placeholder arguments, in those cases, the snippet can be computed
92 /// without specifying any arguments (exactly like calling `create()` with no
93 /// arguments).
94 String get snippet => _createSnippet();
95
96 /// Short description of the error message, typically used as a title of the
97 /// error message in autogenerated documentation. This should be a single
98 /// phrase, and cannot use placeholders.
99 final String description;
100
101 /// Additional details about this error message. These are used to
102 /// automatically generate documentation.
103 final String details;
104
105 const MessageTemplate(
106 this.id, this.snippetTemplate, this.description, this.details);
107
108 static final _placeholderPattern = new RegExp(r"%-(\w*)-%");
109
110 _createSnippet([Map args = const {}, bool fillUnknowns = false]) {
111 var snippet = snippetTemplate.replaceAllMapped(_placeholderPattern, (m) {
112 var arg = m.group(1);
113 var value = args[arg];
114 if (value != null) return '$value';
115 if (fillUnknowns) return '';
116 throw "missing argument $arg, for error message: $snippetTemplate";
117 });
118 return snippet;
119 }
120
121 create([Map args = const {}, bool fillUnknowns = false]) =>
122 new Message(id, _createSnippet(args, fillUnknowns));
123
124 /// Serializes this message to JSON.
125 Map toJson() => create().toJson();
126 String toString() => '${toJson()}';
127 }
128
129 /// Represents an actual log entry for a build error message. Including the
130 /// actual message, its severity level (warning, error, etc), and a source span
131 /// for a code location that is revelant to the message.
132 class BuildLogEntry {
133 /// The actual message.
134 final Message message;
135
136 /// Severity level.
137 final String level;
138
139 /// Location associated with this message, if any.
140 final SourceSpan span;
141
142 BuildLogEntry(this.message, this.span, this.level);
143
144 /// Creates a new [BuildLogEntry] from an encoded value produced via [toJson].
145 factory BuildLogEntry.fromJson(Map data) {
146 var spanData = data['span'];
147 var span = null;
148 if (spanData != null) {
149 var locData = spanData['start'];
150 var start = new SourceLocation(locData['offset'],
151 sourceUrl: Uri.parse(locData['url']),
152 line: locData['line'],
153 column: locData['column']);
154 locData = spanData['end'];
155 var end = new SourceLocation(locData['offset'],
156 sourceUrl: Uri.parse(locData['url']),
157 line: locData['line'],
158 column: locData['column']);
159 span = new SourceSpan(start, end, spanData['text']);
160 }
161 return new BuildLogEntry(
162 new Message.fromJson(data['message']), span, data['level']);
163 }
164
165 /// Serializes this log entry to JSON.
166 Map toJson() {
167 var data = {'level': level, 'message': message.toJson(),};
168 if (span != null) {
169 data['span'] = {
170 'start': {
171 'url': span.start.sourceUrl.toString(),
172 'offset': span.start.offset,
173 'line': span.start.line,
174 'column': span.start.column,
175 },
176 'end': {
177 'url': span.end.sourceUrl.toString(),
178 'offset': span.end.offset,
179 'line': span.end.line,
180 'column': span.end.column,
181 },
182 'text': span.text,
183 };
184 }
185 return data;
186 }
187 String toString() => '${toJson()}';
188 }
189
190 /// A table of entries, that clusters error messages by id.
191 class LogEntryTable {
192 final Map<MessageId, List<BuildLogEntry>> entries;
193
194 LogEntryTable() : entries = new LinkedHashMap();
195
196 /// Creates a new [LogEntryTable] from an encoded value produced via [toJson].
197 factory LogEntryTable.fromJson(Map json) {
198 var res = new LogEntryTable();
199 for (String key in json.keys) {
200 var id = new MessageId.fromJson(key);
201 res.entries[id] =
202 json[key].map((v) => new BuildLogEntry.fromJson(v)).toList();
203 }
204 return res;
205 }
206
207 /// Serializes this entire table as JSON.
208 Map toJson() {
209 var res = {};
210 entries.forEach((key, value) {
211 res['$key'] = value.map((e) => e.toJson()).toList();
212 });
213 return res;
214 }
215 String toString() => '${toJson()}';
216
217 void add(BuildLogEntry entry) {
218 entries.putIfAbsent(entry.message.id, () => []).add(entry);
219 }
220 void addAll(LogEntryTable other) {
221 for (var key in other.entries.keys) {
222 var values = entries.putIfAbsent(key, () => []);
223 values.addAll(other.entries[key]);
224 }
225 }
226 }
OLDNEW
« no previous file with comments | « code_transformers/lib/messages/build_logger.dart ('k') | code_transformers/lib/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698