| OLD | NEW |
| 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 /// Defines messages templates and an adapter for TransformLogger to be able | 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 | 6 /// report error messages from transformers and refer to them in a consistent |
| 7 /// manner long term. | 7 /// manner long term. |
| 8 library code_transformers.messages; | 8 library code_transformers.messages; |
| 9 | 9 |
| 10 // Note: this library purposely doesn't depend on dart:io, dart:html, or barback | 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 | 11 // so it can easily be used both in the transformers and in client-side apps |
| 12 // (for example in the log_injector). | 12 // (for example in the log_injector). |
| 13 import 'dart:collection' show LinkedHashMap; | 13 import 'dart:collection' show LinkedHashMap; |
| 14 |
| 14 import 'package:source_span/source_span.dart'; | 15 import 'package:source_span/source_span.dart'; |
| 15 | 16 |
| 16 /// A globally unique identifier for an error message. This identifier should be | 17 /// 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 /// 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 /// message. That allows us to document our error messages and make them |
| 19 /// searchable for prosperity. | 20 /// searchable for prosperity. |
| 20 class MessageId implements Comparable { | 21 class MessageId implements Comparable<MessageId> { |
| 21 /// Name of the package that declares this message. | 22 /// Name of the package that declares this message. |
| 22 final String package; | 23 final String package; |
| 23 | 24 |
| 24 /// Message identifier number, unique within the package. | 25 /// Message identifier number, unique within the package. |
| 25 final int id; | 26 final int id; |
| 26 | 27 |
| 27 const MessageId(this.package, this.id); | 28 const MessageId(this.package, this.id); |
| 28 | 29 |
| 29 static const MessageId NOT_SPECIFIED = const MessageId('unknown', 0); | 30 static const MessageId NOT_SPECIFIED = const MessageId('unknown', 0); |
| 30 | 31 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 41 } | 42 } |
| 42 | 43 |
| 43 /// Creates a new [MessageId] from an encoded value produced via [toJson]. | 44 /// Creates a new [MessageId] from an encoded value produced via [toJson]. |
| 44 factory MessageId.fromJson(data) { | 45 factory MessageId.fromJson(data) { |
| 45 var index = data.lastIndexOf('#'); | 46 var index = data.lastIndexOf('#'); |
| 46 if (index == -1) throw 'Invalid message id: $data'; | 47 if (index == -1) throw 'Invalid message id: $data'; |
| 47 return new MessageId( | 48 return new MessageId( |
| 48 data.substring(0, index), int.parse(data.substring(index + 1))); | 49 data.substring(0, index), int.parse(data.substring(index + 1))); |
| 49 } | 50 } |
| 50 | 51 |
| 51 operator ==(MessageId other) => package == other.package && id == other.id; | 52 operator ==(Object other) => |
| 53 other is MessageId && package == other.package && id == other.id; |
| 54 |
| 52 int get hashCode => 31 * package.hashCode + id; | 55 int get hashCode => 31 * package.hashCode + id; |
| 53 } | 56 } |
| 54 | 57 |
| 55 /// An instance of an error message. These are typically produced from a | 58 /// An instance of an error message. These are typically produced from a |
| 56 /// [MessageTemplate]. | 59 /// [MessageTemplate]. |
| 57 class Message { | 60 class Message { |
| 58 /// A globally unique identifier for this message. | 61 /// A globally unique identifier for this message. |
| 59 final MessageId id; | 62 final MessageId id; |
| 60 | 63 |
| 61 /// A snippet message that is presented to the user. | 64 /// A snippet message that is presented to the user. |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 line: locData['line'], | 160 line: locData['line'], |
| 158 column: locData['column']); | 161 column: locData['column']); |
| 159 span = new SourceSpan(start, end, spanData['text']); | 162 span = new SourceSpan(start, end, spanData['text']); |
| 160 } | 163 } |
| 161 return new BuildLogEntry( | 164 return new BuildLogEntry( |
| 162 new Message.fromJson(data['message']), span, data['level']); | 165 new Message.fromJson(data['message']), span, data['level']); |
| 163 } | 166 } |
| 164 | 167 |
| 165 /// Serializes this log entry to JSON. | 168 /// Serializes this log entry to JSON. |
| 166 Map toJson() { | 169 Map toJson() { |
| 167 var data = {'level': level, 'message': message.toJson(),}; | 170 var data = { |
| 171 'level': level, |
| 172 'message': message.toJson(), |
| 173 }; |
| 168 if (span != null) { | 174 if (span != null) { |
| 169 data['span'] = { | 175 data['span'] = { |
| 170 'start': { | 176 'start': { |
| 171 'url': span.start.sourceUrl.toString(), | 177 'url': span.start.sourceUrl.toString(), |
| 172 'offset': span.start.offset, | 178 'offset': span.start.offset, |
| 173 'line': span.start.line, | 179 'line': span.start.line, |
| 174 'column': span.start.column, | 180 'column': span.start.column, |
| 175 }, | 181 }, |
| 176 'end': { | 182 'end': { |
| 177 'url': span.end.sourceUrl.toString(), | 183 'url': span.end.sourceUrl.toString(), |
| 178 'offset': span.end.offset, | 184 'offset': span.end.offset, |
| 179 'line': span.end.line, | 185 'line': span.end.line, |
| 180 'column': span.end.column, | 186 'column': span.end.column, |
| 181 }, | 187 }, |
| 182 'text': span.text, | 188 'text': span.text, |
| 183 }; | 189 }; |
| 184 } | 190 } |
| 185 return data; | 191 return data; |
| 186 } | 192 } |
| 193 |
| 187 String toString() => '${toJson()}'; | 194 String toString() => '${toJson()}'; |
| 188 } | 195 } |
| 189 | 196 |
| 190 /// A table of entries, that clusters error messages by id. | 197 /// A table of entries, that clusters error messages by id. |
| 191 class LogEntryTable { | 198 class LogEntryTable { |
| 192 final Map<MessageId, List<BuildLogEntry>> entries; | 199 final Map<MessageId, List<BuildLogEntry>> entries; |
| 193 | 200 |
| 194 LogEntryTable() : entries = new LinkedHashMap(); | 201 LogEntryTable() : entries = new LinkedHashMap(); |
| 195 | 202 |
| 196 /// Creates a new [LogEntryTable] from an encoded value produced via [toJson]. | 203 /// Creates a new [LogEntryTable] from an encoded value produced via [toJson]. |
| 197 factory LogEntryTable.fromJson(Map json) { | 204 factory LogEntryTable.fromJson(Map<String, Iterable> json) { |
| 198 var res = new LogEntryTable(); | 205 var res = new LogEntryTable(); |
| 199 for (String key in json.keys) { | 206 for (String key in json.keys) { |
| 200 var id = new MessageId.fromJson(key); | 207 var id = new MessageId.fromJson(key); |
| 201 res.entries[id] = | 208 res.entries[id] = |
| 202 json[key].map((v) => new BuildLogEntry.fromJson(v)).toList(); | 209 json[key].map((v) => new BuildLogEntry.fromJson(v)).toList(); |
| 203 } | 210 } |
| 204 return res; | 211 return res; |
| 205 } | 212 } |
| 206 | 213 |
| 207 /// Serializes this entire table as JSON. | 214 /// Serializes this entire table as JSON. |
| 208 Map toJson() { | 215 Map toJson() { |
| 209 var res = {}; | 216 var res = {}; |
| 210 entries.forEach((key, value) { | 217 entries.forEach((key, value) { |
| 211 res['$key'] = value.map((e) => e.toJson()).toList(); | 218 res['$key'] = value.map((e) => e.toJson()).toList(); |
| 212 }); | 219 }); |
| 213 return res; | 220 return res; |
| 214 } | 221 } |
| 222 |
| 215 String toString() => '${toJson()}'; | 223 String toString() => '${toJson()}'; |
| 216 | 224 |
| 217 void add(BuildLogEntry entry) { | 225 void add(BuildLogEntry entry) { |
| 218 entries.putIfAbsent(entry.message.id, () => []).add(entry); | 226 entries.putIfAbsent(entry.message.id, () => []).add(entry); |
| 219 } | 227 } |
| 228 |
| 220 void addAll(LogEntryTable other) { | 229 void addAll(LogEntryTable other) { |
| 221 for (var key in other.entries.keys) { | 230 for (var key in other.entries.keys) { |
| 222 var values = entries.putIfAbsent(key, () => []); | 231 var values = entries.putIfAbsent(key, () => []); |
| 223 values.addAll(other.entries[key]); | 232 values.addAll(other.entries[key]); |
| 224 } | 233 } |
| 225 } | 234 } |
| 226 } | 235 } |
| OLD | NEW |