OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:analyzer/analyzer.dart' |
| 6 show AnalysisError, ErrorSeverity, StaticWarningCode; |
| 7 import 'package:analyzer/source/error_processor.dart' show ErrorProcessor; |
5 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; | 8 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
6 import 'package:analyzer/src/generated/error.dart'; | |
7 import 'package:logging/logging.dart'; | |
8 import 'package:path/path.dart' as path; | 9 import 'package:path/path.dart' as path; |
9 import 'package:analyzer/source/error_processor.dart'; | |
10 | 10 |
11 final _checkerLogger = new Logger('dev_compiler.checker'); | 11 // TODO(jmesserly): this code was taken from analyzer_cli. |
| 12 // It really should be in some common place so we can share it. |
| 13 // TODO(jmesserly): this shouldn't depend on `context` but we need it to compute |
| 14 // `errorSeverity` due to some APIs that need fixing. |
| 15 void sortErrors(AnalysisContext context, List<AnalysisError> errors) { |
| 16 errors.sort((AnalysisError error1, AnalysisError error2) { |
| 17 // severity |
| 18 var severity1 = errorSeverity(context, error1); |
| 19 var severity2 = errorSeverity(context, error2); |
| 20 int compare = severity2.compareTo(severity1); |
| 21 if (compare != 0) return compare; |
12 | 22 |
13 /// Collects errors, and then sorts them and sends them | 23 // path |
14 class ErrorCollector implements AnalysisErrorListener { | 24 compare = Comparable.compare(error1.source.fullName.toLowerCase(), |
15 final AnalysisContext _context; | 25 error2.source.fullName.toLowerCase()); |
16 final AnalysisErrorListener listener; | 26 if (compare != 0) return compare; |
17 final List<AnalysisError> _errors = []; | |
18 | 27 |
19 ErrorCollector(this._context, this.listener); | 28 // offset |
| 29 compare = error1.offset - error2.offset; |
| 30 if (compare != 0) return compare; |
20 | 31 |
21 /// Flushes errors to the log. Until this is called, errors are buffered. | 32 // compare message, in worst case. |
22 void flush() { | 33 return error1.message.compareTo(error2.message); |
23 // TODO(jmesserly): this code was taken from analyzer_cli. | 34 }); |
24 // sort errors | 35 } |
25 _errors.sort((AnalysisError error1, AnalysisError error2) { | |
26 // severity | |
27 var severity1 = errorSeverity(_context, error1); | |
28 var severity2 = errorSeverity(_context, error2); | |
29 int compare = severity2.compareTo(severity1); | |
30 if (compare != 0) return compare; | |
31 | 36 |
32 // path | 37 // TODO(jmesserly): this was from analyzer_cli, we should factor it differently. |
33 compare = Comparable.compare(error1.source.fullName.toLowerCase(), | 38 String formatError(AnalysisContext context, AnalysisError error) { |
34 error2.source.fullName.toLowerCase()); | 39 var severity = errorSeverity(context, error); |
35 if (compare != 0) return compare; | 40 // Skip hints, some like TODOs are not useful. |
| 41 if (severity.ordinal <= ErrorSeverity.INFO.ordinal) return null; |
36 | 42 |
37 // offset | 43 var lineInfo = context.computeLineInfo(error.source); |
38 compare = error1.offset - error2.offset; | 44 var location = lineInfo.getLocation(error.offset); |
39 if (compare != 0) return compare; | |
40 | 45 |
41 // compare message, in worst case. | 46 // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2) |
42 return error1.message.compareTo(error2.message); | 47 return (new StringBuffer() |
43 }); | 48 ..write('[${severity.displayName}] ') |
44 | 49 ..write(error.message) |
45 _errors.forEach(listener.onError); | 50 ..write(' (${path.prettyUri(error.source.uri)}') |
46 _errors.clear(); | 51 ..write(', line ${location.lineNumber}, col ${location.columnNumber})')) |
47 } | 52 .toString(); |
48 | |
49 void onError(AnalysisError error) { | |
50 _errors.add(error); | |
51 } | |
52 } | 53 } |
53 | 54 |
54 ErrorSeverity errorSeverity(AnalysisContext context, AnalysisError error) { | 55 ErrorSeverity errorSeverity(AnalysisContext context, AnalysisError error) { |
55 var code = error.errorCode; | 56 var code = error.errorCode; |
56 if (code is StaticWarningCode) { | 57 if (code is StaticWarningCode) { |
57 // TODO(jmesserly): many more warnings need to be promoted for soundness. | 58 // TODO(jmesserly): many more warnings need to be promoted for soundness. |
58 // Also code generation will blow up finding null types/elements for many | 59 // Also code generation will blow up finding null types/elements for many |
59 // of these, or we rely on them to produce valid optimizations. | 60 // of these, or we rely on them to produce valid optimizations. |
60 switch (code.name) { | 61 switch (code.name) { |
61 case 'AMBIGUOUS_IMPORT': | 62 case 'AMBIGUOUS_IMPORT': |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 // analyzer_cli and server use. | 174 // analyzer_cli and server use. |
174 // | 175 // |
175 // Among the issues with ErrorProcessor.getProcessor: | 176 // Among the issues with ErrorProcessor.getProcessor: |
176 // * it needs to be called per-error, so it's a performance trap. | 177 // * it needs to be called per-error, so it's a performance trap. |
177 // * it can return null | 178 // * it can return null |
178 // * using AnalysisError directly is now suspect, it's a correctness trap | 179 // * using AnalysisError directly is now suspect, it's a correctness trap |
179 // * it requires an AnalysisContext | 180 // * it requires an AnalysisContext |
180 return ErrorProcessor.getProcessor(context, error)?.severity ?? | 181 return ErrorProcessor.getProcessor(context, error)?.severity ?? |
181 error.errorCode.errorSeverity; | 182 error.errorCode.errorSeverity; |
182 } | 183 } |
183 | |
184 /// Simple reporter that logs checker messages as they are seen. | |
185 class LogReporter implements AnalysisErrorListener { | |
186 final AnalysisContext _context; | |
187 final bool useColors; | |
188 final List<AnalysisError> _errors = []; | |
189 | |
190 LogReporter(this._context, {this.useColors: false}); | |
191 | |
192 void onError(AnalysisError error) { | |
193 var level = _severityToLevel[errorSeverity(_context, error)]; | |
194 | |
195 // TODO(jmesserly): figure out what to do with the error's name. | |
196 var lineInfo = _context.computeLineInfo(error.source); | |
197 var location = lineInfo.getLocation(error.offset); | |
198 | |
199 // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2) | |
200 var text = new StringBuffer() | |
201 ..write('[${error.errorCode.name}] ') | |
202 ..write(error.message) | |
203 ..write(' (${path.prettyUri(error.source.uri)}') | |
204 ..write(', line ${location.lineNumber}, col ${location.columnNumber})'); | |
205 | |
206 // TODO(jmesserly): just print these instead of sending through logger? | |
207 _checkerLogger.log(level, text); | |
208 } | |
209 } | |
210 | |
211 // TODO(jmesserly): remove log levels, instead just use severity. | |
212 const _severityToLevel = const { | |
213 ErrorSeverity.ERROR: Level.SEVERE, | |
214 ErrorSeverity.WARNING: Level.WARNING, | |
215 ErrorSeverity.INFO: Level.INFO | |
216 }; | |
OLD | NEW |