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

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

Issue 1230903002: fixes #6, refactor to use AnalysisError/Listener throughout dev_compiler (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 5 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/src/info.dart ('k') | lib/src/summary.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) 2015, the Dart project authors. Please see the AUTHORS file 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 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 /// Summarizes the information produced by the checker. 5 /// Summarizes the information produced by the checker.
6 library dev_compiler.src.report; 6 library dev_compiler.src.report;
7 7
8 import 'dart:math' show max; 8 import 'dart:math' show max;
9 9
10 import 'package:analyzer/src/generated/ast.dart' show AstNode, CompilationUnit;
11 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; 10 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
12 import 'package:analyzer/src/generated/source.dart' show Source; 11 import 'package:analyzer/src/generated/error.dart';
13 import 'package:logging/logging.dart'; 12 import 'package:logging/logging.dart';
14 import 'package:path/path.dart' as path; 13 import 'package:path/path.dart' as path;
15 import 'package:source_span/source_span.dart'; 14 import 'package:source_span/source_span.dart';
16 15
17 import 'info.dart';
18 import 'utils.dart'; 16 import 'utils.dart';
19 import 'summary.dart'; 17 import 'summary.dart';
20 18
21 /// A message (error or warning) produced by the dev_compiler and it's location 19 final _checkerLogger = new Logger('dev_compiler.checker');
22 /// information.
23 ///
24 /// Currently the location information includes only the offsets within a file
25 /// where the error occurs. This is used in the context of a [CheckerReporter],
26 /// where the current file is being tracked.
27 class Message {
28 // Message description.
29 final String message;
30 20
31 /// Log level. This is a placeholder for severity. 21 SourceSpanWithContext _toSpan(AnalysisContext context, AnalysisError error) {
32 final Level level; 22 var source = error.source;
23 var lineInfo = context.computeLineInfo(source);
24 var content = context.getContents(source).data;
25 var start = error.offset;
26 var end = start + error.length;
27 return createSpanHelper(lineInfo, start, end, source, content);
28 }
29 /// Simple reporter that logs checker messages as they are seen.
30 class LogReporter implements AnalysisErrorListener {
31 final AnalysisContext _context;
32 final bool useColors;
33 33
34 /// Offset where the error message begins in the tracked source file. 34 LogReporter(this._context, {this.useColors: false});
35 final int begin;
36 35
37 /// Offset where the error message ends in the tracked source file. 36 void onError(AnalysisError error) {
38 final int end; 37 var level = _severityToLevel[error.errorCode.errorSeverity];
39 38
40 const Message(this.message, this.level, this.begin, this.end); 39 // Upgrade analyzer warnings to errors.
40 // TODO(jmesserly: reconcile this...
41 if (!error.errorCode.name.startsWith('dev_compiler.') &&
42 level == Level.WARNING) {
43 level = Level.SEVERE;
44 }
45
46 var color = useColors ? colorOf(level.name) : null;
47
48 // TODO(jmesserly): figure out what to do with the error's name.
49 var text = '[${errorCodeName(error.errorCode)}] ' + error.message;
50 text = _toSpan(_context, error).message(text, color: color);
51
52 // TODO(jmesserly): just print these instead of sending through logger?
53 _checkerLogger.log(level, text);
54 }
41 } 55 }
42 56
43 // Interface used to report error messages from the checker. 57 // TODO(jmesserly): remove log levels, instead just use severity.
44 abstract class CheckerReporter { 58 const _severityToLevel = const {
45 void log(Message message); 59 ErrorSeverity.ERROR: Level.SEVERE,
46 } 60 ErrorSeverity.WARNING: Level.WARNING,
47 61 ErrorSeverity.INFO: Level.INFO
48 // Interface used to report error messages from the compiler. 62 };
49 abstract class CompilerReporter extends CheckerReporter {
50 final AnalysisContext _context;
51 CompilationUnit _unit;
52 Source _unitSource;
53
54 CompilerReporter(this._context);
55
56 /// Called when starting to process a library.
57 void enterLibrary(Uri uri);
58 void leaveLibrary();
59
60 /// Called when starting to process an HTML source file.
61 void enterHtml(Uri uri);
62 void leaveHtml();
63
64 /// Called when starting to process a source. All subsequent log entries must
65 /// belong to this source until the next call to enterSource.
66 void enterCompilationUnit(CompilationUnit unit, [Source source]) {
67 _unit = unit;
68 _unitSource = source;
69 }
70 void leaveCompilationUnit() {
71 _unit = null;
72 _unitSource = null;
73 }
74
75 // Called in server-mode.
76 void clearLibrary(Uri uri);
77 void clearHtml(Uri uri);
78 void clearAll();
79
80 SourceSpanWithContext _createSpan(int start, int end) =>
81 createSpan(_context, _unit, start, end, _unitSource);
82 }
83
84 final _checkerLogger = new Logger('dev_compiler.checker');
85
86 /// Simple reporter that logs checker messages as they are seen.
87 class LogReporter extends CompilerReporter {
88 final bool useColors;
89 Source _current;
90
91 LogReporter(AnalysisContext context, {this.useColors: false})
92 : super(context);
93
94 void enterLibrary(Uri uri) {}
95 void leaveLibrary() {}
96
97 void enterHtml(Uri uri) {}
98 void leaveHtml() {}
99
100 void log(Message message) {
101 if (message is StaticInfo) {
102 assert(message.node.root == _unit);
103 }
104 // TODO(sigmund): convert to use span information from AST (issue #73)
105 final span = _createSpan(message.begin, message.end);
106 final level = message.level;
107 final color = useColors ? colorOf(level.name) : null;
108 final text = '[${message.runtimeType}] ${message.message}';
109 _checkerLogger.log(level, span.message(text, color: color));
110 }
111
112 void clearLibrary(Uri uri) {}
113 void clearHtml(Uri uri) {}
114 void clearAll() {}
115 }
116 63
117 /// A reporter that gathers all the information in a [GlobalSummary]. 64 /// A reporter that gathers all the information in a [GlobalSummary].
118 class SummaryReporter extends CompilerReporter { 65 class SummaryReporter implements AnalysisErrorListener {
119 GlobalSummary result = new GlobalSummary(); 66 GlobalSummary result = new GlobalSummary();
120 IndividualSummary _current;
121 final Level _level; 67 final Level _level;
68 final AnalysisContext _context;
122 69
123 SummaryReporter(AnalysisContext context, [this._level = Level.ALL]) 70 SummaryReporter(this._context, [this._level = Level.ALL]);
124 : super(context);
125 71
126 void enterLibrary(Uri uri) { 72 IndividualSummary _getIndividualSummary(Uri uri) {
73 if (uri.path.endsWith('.html')) {
74 return result.loose.putIfAbsent('$uri', () => new HtmlSummary('$uri'));
75 }
76
127 var container; 77 var container;
128 if (uri.scheme == 'package') { 78 if (uri.scheme == 'package') {
129 var pname = path.split(uri.path)[0]; 79 var pname = path.split(uri.path)[0];
130 result.packages.putIfAbsent(pname, () => new PackageSummary(pname)); 80 result.packages.putIfAbsent(pname, () => new PackageSummary(pname));
131 container = result.packages[pname].libraries; 81 container = result.packages[pname].libraries;
132 } else if (uri.scheme == 'dart') { 82 } else if (uri.scheme == 'dart') {
133 container = result.system; 83 container = result.system;
134 } else { 84 } else {
135 container = result.loose; 85 container = result.loose;
136 } 86 }
137 _current = container.putIfAbsent('$uri', () => new LibrarySummary('$uri')); 87 return container.putIfAbsent('$uri', () => new LibrarySummary('$uri'));
138 } 88 }
139 89
140 void leaveLibrary() { 90 void onError(AnalysisError error) {
141 _current = null; 91 // Only summarize messages per configured logging level
142 } 92 var code = error.errorCode;
93 if (_severityToLevel[code.errorSeverity] < _level) return;
143 94
144 void enterHtml(Uri uri) { 95 var span = _toSpan(_context, error);
145 _current = result.loose.putIfAbsent('$uri', () => new HtmlSummary('$uri')); 96 var summary = _getIndividualSummary(error.source.uri);
146 } 97 if (summary is LibrarySummary) {
147 98 summary.countSourceLines(_context, error.source);
148 void leaveHtml() {
149 _current = null;
150 }
151
152 @override
153 void enterCompilationUnit(CompilationUnit unit, [Source source]) {
154 super.enterCompilationUnit(unit, source);
155 if (_current is LibrarySummary) {
156 int lines = _unit.lineInfo.getLocation(_unit.endToken.end).lineNumber;
157 (_current as LibrarySummary).lines += lines;
158 } 99 }
159 } 100 summary.messages.add(new MessageSummary(
160 101 errorCodeName(code), code.errorSeverity.displayName, span, error.message ));
161 void log(Message message) {
162 // Only summarize messages per configured logging level
163 if (message.level < _level) return;
164 final span = _createSpan(message.begin, message.end);
165 _current.messages.add(new MessageSummary('${message.runtimeType}',
166 message.level.name.toLowerCase(), span, message.message));
167 } 102 }
168 103
169 void clearLibrary(Uri uri) { 104 void clearLibrary(Uri uri) {
170 enterLibrary(uri); 105 (_getIndividualSummary(uri) as LibrarySummary).clear();
171 _current.messages.clear();
172 (_current as LibrarySummary).lines = 0;
173 leaveLibrary();
174 } 106 }
175 107
176 void clearHtml(Uri uri) { 108 void clearHtml(Uri uri) {
177 HtmlSummary htmlSummary = result.loose['$uri']; 109 HtmlSummary htmlSummary = result.loose['$uri'];
178 if (htmlSummary != null) htmlSummary.messages.clear(); 110 if (htmlSummary != null) htmlSummary.messages.clear();
179 } 111 }
180
181 clearAll() {
182 result = new GlobalSummary();
183 }
184 } 112 }
185 113
186 /// Produces a string representation of the summary. 114 /// Produces a string representation of the summary.
187 String summaryToString(GlobalSummary summary) { 115 String summaryToString(GlobalSummary summary) {
188 var counter = new _Counter(); 116 var counter = new _Counter();
189 summary.accept(counter); 117 summary.accept(counter);
190 118
191 var table = new _Table(); 119 var table = new _Table();
192 // Declare columns and add header 120 // Declare columns and add header
193 table.declareColumn('package'); 121 table.declareColumn('package');
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 300
373 visitMessage(MessageSummary message) { 301 visitMessage(MessageSummary message) {
374 var kind = message.kind; 302 var kind = message.kind;
375 errorCount.putIfAbsent(currentPackage, () => <String, int>{}); 303 errorCount.putIfAbsent(currentPackage, () => <String, int>{});
376 errorCount[currentPackage].putIfAbsent(kind, () => 0); 304 errorCount[currentPackage].putIfAbsent(kind, () => 0);
377 errorCount[currentPackage][kind]++; 305 errorCount[currentPackage][kind]++;
378 totals.putIfAbsent(kind, () => 0); 306 totals.putIfAbsent(kind, () => 0);
379 totals[kind]++; 307 totals[kind]++;
380 } 308 }
381 } 309 }
OLDNEW
« no previous file with comments | « lib/src/info.dart ('k') | lib/src/summary.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698