| OLD | NEW |
| 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 Loading... |
| 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 } |
| OLD | NEW |