| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, 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 /// Summary of error messages produced by a `SummaryReporter`. | |
| 6 | |
| 7 import 'dart:collection' show HashSet; | |
| 8 | |
| 9 import 'package:source_span/source_span.dart'; | |
| 10 | |
| 11 /// Summary information computed by the DDC checker. | |
| 12 abstract class Summary { | |
| 13 Map toJsonMap(); | |
| 14 | |
| 15 void accept(SummaryVisitor visitor); | |
| 16 } | |
| 17 | |
| 18 /// Summary for the entire program. | |
| 19 class GlobalSummary implements Summary { | |
| 20 /// Summary from the system libraries. | |
| 21 final Map<String, LibrarySummary> system = <String, LibrarySummary>{}; | |
| 22 | |
| 23 /// Summary for libraries in packages. | |
| 24 final Map<String, PackageSummary> packages = <String, PackageSummary>{}; | |
| 25 | |
| 26 /// Summary for loose files | |
| 27 // TODO(sigmund): consider inferring the package from the pubspec instead? | |
| 28 final Map<String, IndividualSummary> loose = <String, IndividualSummary>{}; | |
| 29 | |
| 30 GlobalSummary(); | |
| 31 | |
| 32 Map toJsonMap() => { | |
| 33 'system': system.values.map((l) => l.toJsonMap()).toList(), | |
| 34 'packages': packages.values.map((p) => p.toJsonMap()).toList(), | |
| 35 'loose': loose.values | |
| 36 .map((l) => ['${l.runtimeType}', l.toJsonMap()]) | |
| 37 .toList(), | |
| 38 }; | |
| 39 | |
| 40 void accept(SummaryVisitor visitor) => visitor.visitGlobal(this); | |
| 41 | |
| 42 static GlobalSummary parse(Map json) { | |
| 43 var res = new GlobalSummary(); | |
| 44 json['system'].map(LibrarySummary.parse).forEach((l) { | |
| 45 res.system[l.name] = l; | |
| 46 }); | |
| 47 json['packages'].map(PackageSummary.parse).forEach((p) { | |
| 48 res.packages[p.name] = p; | |
| 49 }); | |
| 50 json['loose'].forEach((e) { | |
| 51 var summary = e[0] == 'LibrarySummary' | |
| 52 ? LibrarySummary.parse(e[1]) | |
| 53 : HtmlSummary.parse(e[1]); | |
| 54 res.loose[summary.name] = summary; | |
| 55 }); | |
| 56 return res; | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 /// A summary of a package. | |
| 61 class PackageSummary implements Summary { | |
| 62 final String name; | |
| 63 final Map<String, LibrarySummary> libraries = <String, LibrarySummary>{}; | |
| 64 | |
| 65 PackageSummary(this.name); | |
| 66 | |
| 67 Map toJsonMap() => { | |
| 68 'package_name': name, | |
| 69 'libraries': libraries.values.map((l) => l.toJsonMap()).toList(), | |
| 70 }; | |
| 71 | |
| 72 void accept(SummaryVisitor visitor) => visitor.visitPackage(this); | |
| 73 | |
| 74 static PackageSummary parse(Map json) { | |
| 75 var res = new PackageSummary(json['package_name']); | |
| 76 json['libraries'].map(LibrarySummary.parse).forEach((l) { | |
| 77 res.libraries[l.name] = l; | |
| 78 }); | |
| 79 return res; | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 /// A summary for a library or an html file. | |
| 84 abstract class IndividualSummary extends Summary { | |
| 85 /// Unique name for this library. | |
| 86 String get name; | |
| 87 | |
| 88 List<MessageSummary> get messages; | |
| 89 } | |
| 90 | |
| 91 /// A summary at the level of a library. | |
| 92 class LibrarySummary implements IndividualSummary { | |
| 93 /// Unique name for this library. | |
| 94 final String name; | |
| 95 | |
| 96 /// All messages collected for the library. | |
| 97 final List<MessageSummary> messages; | |
| 98 | |
| 99 /// All parts of this library. Only used for computing _lines. | |
| 100 final _uris = new HashSet<Uri>(); | |
| 101 | |
| 102 int _lines; | |
| 103 | |
| 104 LibrarySummary(this.name, {List<MessageSummary> messages, lines}) | |
| 105 : messages = messages == null ? <MessageSummary>[] : messages, | |
| 106 _lines = lines != null ? lines : 0; | |
| 107 | |
| 108 void clear() { | |
| 109 _uris.clear(); | |
| 110 _lines = 0; | |
| 111 messages.clear(); | |
| 112 } | |
| 113 | |
| 114 /// Total lines of code (including all parts of the library). | |
| 115 int get lines => _lines; | |
| 116 | |
| 117 Map toJsonMap() => { | |
| 118 'library_name': name, | |
| 119 'messages': messages.map((m) => m.toJsonMap()).toList(), | |
| 120 'lines': lines, | |
| 121 }; | |
| 122 | |
| 123 void recordSourceLines(Uri uri, int computeLines()) { | |
| 124 if (_uris.add(uri)) { | |
| 125 _lines += computeLines(); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 void accept(SummaryVisitor visitor) => visitor.visitLibrary(this); | |
| 130 | |
| 131 static LibrarySummary parse(Map json) => | |
| 132 new LibrarySummary(json['library_name'], | |
| 133 messages: new List<MessageSummary>.from( | |
| 134 json['messages'].map(MessageSummary.parse)), | |
| 135 lines: json['lines']); | |
| 136 } | |
| 137 | |
| 138 /// A summary at the level of an HTML file. | |
| 139 class HtmlSummary implements IndividualSummary { | |
| 140 /// Unique name used to identify the HTML file. | |
| 141 final String name; | |
| 142 | |
| 143 /// All messages collected on the file. | |
| 144 final List<MessageSummary> messages; | |
| 145 | |
| 146 HtmlSummary(this.name, [List<MessageSummary> messages]) | |
| 147 : messages = messages == null ? <MessageSummary>[] : messages; | |
| 148 | |
| 149 Map toJsonMap() => | |
| 150 {'name': name, 'messages': messages.map((m) => m.toJsonMap()).toList()}; | |
| 151 | |
| 152 void accept(SummaryVisitor visitor) => visitor.visitHtml(this); | |
| 153 | |
| 154 static HtmlSummary parse(Map json) => new HtmlSummary( | |
| 155 json['name'], | |
| 156 new List<MessageSummary>.from( | |
| 157 json['messages'].map(MessageSummary.parse))); | |
| 158 } | |
| 159 | |
| 160 /// A single message produced by the checker. | |
| 161 class MessageSummary implements Summary { | |
| 162 /// The kind of message, currently the name of the StaticInfo type. | |
| 163 final String kind; | |
| 164 | |
| 165 /// Level (error, warning, etc). | |
| 166 final String level; | |
| 167 | |
| 168 /// Location where the error is reported. | |
| 169 final SourceSpan span; | |
| 170 final String message; | |
| 171 | |
| 172 MessageSummary(this.kind, this.level, this.span, this.message); | |
| 173 | |
| 174 Map toJsonMap() => { | |
| 175 'kind': kind, | |
| 176 'level': level, | |
| 177 'message': message, | |
| 178 'url': '${span.sourceUrl}', | |
| 179 'start': [span.start.offset, span.start.line, span.start.column], | |
| 180 'end': [span.end.offset, span.end.line, span.end.column], | |
| 181 'text': span.text, | |
| 182 'context': span is SourceSpanWithContext | |
| 183 ? (span as SourceSpanWithContext).context | |
| 184 : null, | |
| 185 }; | |
| 186 | |
| 187 void accept(SummaryVisitor visitor) => visitor.visitMessage(this); | |
| 188 | |
| 189 static MessageSummary parse(Map json) { | |
| 190 var start = new SourceLocation(json['start'][0], | |
| 191 sourceUrl: json['url'], | |
| 192 line: json['start'][1], | |
| 193 column: json['start'][2]); | |
| 194 var end = new SourceLocation(json['end'][0], | |
| 195 sourceUrl: json['url'], line: json['end'][1], column: json['end'][2]); | |
| 196 var context = json['context']; | |
| 197 var span = context != null | |
| 198 ? new SourceSpanWithContext(start, end, json['text'], context) | |
| 199 : new SourceSpan(start, end, json['text']); | |
| 200 return new MessageSummary( | |
| 201 json['kind'], json['level'], span, json['message']); | |
| 202 } | |
| 203 } | |
| 204 | |
| 205 /// A visitor of the [Summary] hierarchy. | |
| 206 abstract class SummaryVisitor { | |
| 207 void visitGlobal(GlobalSummary global); | |
| 208 void visitPackage(PackageSummary package); | |
| 209 void visitLibrary(LibrarySummary lib); | |
| 210 void visitHtml(HtmlSummary html); | |
| 211 void visitMessage(MessageSummary message); | |
| 212 } | |
| 213 | |
| 214 /// A recursive [SummaryVisitor] that visits summaries on a top-down fashion. | |
| 215 class RecursiveSummaryVisitor implements SummaryVisitor { | |
| 216 void visitGlobal(GlobalSummary global) { | |
| 217 for (var lib in global.system.values) { | |
| 218 lib.accept(this); | |
| 219 } | |
| 220 for (var package in global.packages.values) { | |
| 221 package.accept(this); | |
| 222 } | |
| 223 for (var libOrHtml in global.loose.values) { | |
| 224 libOrHtml.accept(this); | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 void visitPackage(PackageSummary package) { | |
| 229 for (var lib in package.libraries.values) { | |
| 230 lib.accept(this); | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 void visitLibrary(LibrarySummary lib) { | |
| 235 for (var msg in lib.messages) { | |
| 236 msg.accept(this); | |
| 237 } | |
| 238 } | |
| 239 | |
| 240 void visitHtml(HtmlSummary html) { | |
| 241 for (var msg in html.messages) { | |
| 242 msg.accept(this); | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 void visitMessage(MessageSummary message) {} | |
| 247 } | |
| OLD | NEW |