| 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 library analyzer_cli.src.error_formatter; | 5 library analyzer_cli.src.error_formatter; |
| 6 | 6 |
| 7 import 'package:analyzer/src/generated/engine.dart'; | 7 import 'package:analyzer/src/generated/engine.dart'; |
| 8 import 'package:analyzer/src/generated/error.dart'; | 8 import 'package:analyzer/src/generated/error.dart'; |
| 9 import 'package:analyzer/src/generated/source.dart'; | 9 import 'package:analyzer/src/generated/source.dart'; |
| 10 import 'package:analyzer_cli/src/analyzer_impl.dart'; | |
| 11 import 'package:analyzer_cli/src/options.dart'; | 10 import 'package:analyzer_cli/src/options.dart'; |
| 12 | 11 |
| 13 /// Allows any [AnalysisError]. | 12 /// Returns the given error's severity. |
| 14 bool _anyError(AnalysisError error) => true; | 13 ProcessedSeverity _identity(AnalysisError error) => |
| 14 new ProcessedSeverity(error.errorCode.errorSeverity); |
| 15 | 15 |
| 16 /// Returns `true` if [AnalysisError] should be printed. | 16 /// Returns desired severity for the given [error] (or `null` if it's to be |
| 17 typedef bool _ErrorFilter(AnalysisError error); | 17 /// suppressed). |
| 18 typedef ProcessedSeverity _SeverityProcessor(AnalysisError error); |
| 18 | 19 |
| 19 /// Helper for formatting [AnalysisError]s. | 20 /// Helper for formatting [AnalysisError]s. |
| 20 /// The two format options are a user consumable format and a machine consumable
format. | 21 /// The two format options are a user consumable format and a machine consumable |
| 22 /// format. |
| 21 class ErrorFormatter { | 23 class ErrorFormatter { |
| 22 final StringSink out; | 24 final StringSink out; |
| 23 final CommandLineOptions options; | 25 final CommandLineOptions options; |
| 24 final _ErrorFilter errorFilter; | 26 final _SeverityProcessor processSeverity; |
| 25 | 27 |
| 26 ErrorFormatter(this.out, this.options, [this.errorFilter = _anyError]); | 28 ErrorFormatter(this.out, this.options, [this.processSeverity = _identity]); |
| 29 |
| 30 /// Compute the severity for this [error] or `null` if this error should be |
| 31 /// filtered. |
| 32 ErrorSeverity computeSeverity(AnalysisError error) => |
| 33 processSeverity(error)?.severity; |
| 27 | 34 |
| 28 void formatError( | 35 void formatError( |
| 29 Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) { | 36 Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) { |
| 30 Source source = error.source; | 37 Source source = error.source; |
| 31 LineInfo_Location location = errorToLine[error].getLocation(error.offset); | 38 LineInfo_Location location = errorToLine[error].getLocation(error.offset); |
| 32 int length = error.length; | 39 int length = error.length; |
| 33 ErrorSeverity severity = | 40 |
| 34 AnalyzerImpl.computeSeverity(error, options); | 41 ProcessedSeverity processedSeverity = processSeverity(error); |
| 42 ErrorSeverity severity = processedSeverity.severity; |
| 43 |
| 35 if (options.machineFormat) { | 44 if (options.machineFormat) { |
| 36 if (severity == ErrorSeverity.WARNING && options.warningsAreFatal) { | 45 if (!processedSeverity.overridden) { |
| 37 severity = ErrorSeverity.ERROR; | 46 if (severity == ErrorSeverity.WARNING && options.warningsAreFatal) { |
| 47 severity = ErrorSeverity.ERROR; |
| 48 } |
| 38 } | 49 } |
| 39 out.write(severity); | 50 out.write(severity); |
| 40 out.write('|'); | 51 out.write('|'); |
| 41 out.write(error.errorCode.type); | 52 out.write(error.errorCode.type); |
| 42 out.write('|'); | 53 out.write('|'); |
| 43 out.write(error.errorCode.name); | 54 out.write(error.errorCode.name); |
| 44 out.write('|'); | 55 out.write('|'); |
| 45 out.write(escapePipe(source.fullName)); | 56 out.write(escapePipe(source.fullName)); |
| 46 out.write('|'); | 57 out.write('|'); |
| 47 out.write(location.lineNumber); | 58 out.write(location.lineNumber); |
| 48 out.write('|'); | 59 out.write('|'); |
| 49 out.write(location.columnNumber); | 60 out.write(location.columnNumber); |
| 50 out.write('|'); | 61 out.write('|'); |
| 51 out.write(length); | 62 out.write(length); |
| 52 out.write('|'); | 63 out.write('|'); |
| 53 out.write(escapePipe(error.message)); | 64 out.write(escapePipe(error.message)); |
| 54 } else { | 65 } else { |
| 66 // Get display name. |
| 55 String errorType = severity.displayName; | 67 String errorType = severity.displayName; |
| 56 if (error.errorCode.type == ErrorType.HINT || | 68 |
| 57 error.errorCode.type == ErrorType.LINT) { | 69 // Translate INFOs into LINTS and HINTS. |
| 58 errorType = error.errorCode.type.displayName; | 70 if (severity == ErrorSeverity.INFO) { |
| 71 if (error.errorCode.type == ErrorType.HINT || |
| 72 error.errorCode.type == ErrorType.LINT) { |
| 73 errorType = error.errorCode.type.displayName; |
| 74 } |
| 59 } | 75 } |
| 76 |
| 60 // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2) | 77 // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2) |
| 61 out.write('[$errorType] ${error.message} '); | 78 out.write('[$errorType] ${error.message} '); |
| 62 out.write('(${source.fullName}'); | 79 out.write('(${source.fullName}'); |
| 63 out.write(', line ${location.lineNumber}, col ${location.columnNumber})'); | 80 out.write(', line ${location.lineNumber}, col ${location.columnNumber})'); |
| 64 } | 81 } |
| 65 out.writeln(); | 82 out.writeln(); |
| 66 } | 83 } |
| 67 | 84 |
| 68 void formatErrors(List<AnalysisErrorInfo> errorInfos) { | 85 void formatErrors(List<AnalysisErrorInfo> errorInfos) { |
| 69 var errors = new List<AnalysisError>(); | 86 var errors = new List<AnalysisError>(); |
| 70 var errorToLine = new Map<AnalysisError, LineInfo>(); | 87 var errorToLine = new Map<AnalysisError, LineInfo>(); |
| 71 for (AnalysisErrorInfo errorInfo in errorInfos) { | 88 for (AnalysisErrorInfo errorInfo in errorInfos) { |
| 72 for (AnalysisError error in errorInfo.errors) { | 89 for (AnalysisError error in errorInfo.errors) { |
| 73 if (errorFilter(error)) { | 90 if (computeSeverity(error) != null) { |
| 74 errors.add(error); | 91 errors.add(error); |
| 75 errorToLine[error] = errorInfo.lineInfo; | 92 errorToLine[error] = errorInfo.lineInfo; |
| 76 } | 93 } |
| 77 } | 94 } |
| 78 } | 95 } |
| 79 // Sort errors. | 96 // Sort errors. |
| 80 errors.sort((AnalysisError error1, AnalysisError error2) { | 97 errors.sort((AnalysisError error1, AnalysisError error2) { |
| 81 // Severity. | 98 // Severity. |
| 82 ErrorSeverity severity1 = | 99 ErrorSeverity severity1 = computeSeverity(error1); |
| 83 AnalyzerImpl.computeSeverity(error1, options); | 100 ErrorSeverity severity2 = computeSeverity(error2); |
| 84 ErrorSeverity severity2 = | |
| 85 AnalyzerImpl.computeSeverity(error2, options); | |
| 86 int compare = severity2.compareTo(severity1); | 101 int compare = severity2.compareTo(severity1); |
| 87 if (compare != 0) { | 102 if (compare != 0) { |
| 88 return compare; | 103 return compare; |
| 89 } | 104 } |
| 90 // Path. | 105 // Path. |
| 91 compare = Comparable.compare(error1.source.fullName.toLowerCase(), | 106 compare = Comparable.compare(error1.source.fullName.toLowerCase(), |
| 92 error2.source.fullName.toLowerCase()); | 107 error2.source.fullName.toLowerCase()); |
| 93 if (compare != 0) { | 108 if (compare != 0) { |
| 94 return compare; | 109 return compare; |
| 95 } | 110 } |
| 96 // Offset. | 111 // Offset. |
| 97 return error1.offset - error2.offset; | 112 return error1.offset - error2.offset; |
| 98 }); | 113 }); |
| 99 // Format errors. | 114 // Format errors. |
| 100 int errorCount = 0; | 115 int errorCount = 0; |
| 101 int warnCount = 0; | 116 int warnCount = 0; |
| 102 int hintCount = 0; | 117 int hintCount = 0; |
| 103 int lintCount = 0; | 118 int lintCount = 0; |
| 104 for (AnalysisError error in errors) { | 119 for (AnalysisError error in errors) { |
| 105 ErrorSeverity severity = | 120 ProcessedSeverity processedSeverity = processSeverity(error); |
| 106 AnalyzerImpl.computeSeverity(error, options); | 121 ErrorSeverity severity = processedSeverity.severity; |
| 107 if (severity == ErrorSeverity.ERROR) { | 122 if (severity == ErrorSeverity.ERROR) { |
| 108 errorCount++; | 123 errorCount++; |
| 109 } else if (severity == ErrorSeverity.WARNING) { | 124 } else if (severity == ErrorSeverity.WARNING) { |
| 110 if (options.warningsAreFatal) { | 125 /// Only treat a warning as an error if it's not been set by a |
| 126 /// proccesser. |
| 127 if (!processedSeverity.overridden && options.warningsAreFatal) { |
| 111 errorCount++; | 128 errorCount++; |
| 112 } else { | 129 } else { |
| 113 warnCount++; | 130 warnCount++; |
| 114 } | 131 } |
| 115 } else if (error.errorCode.type == ErrorType.HINT) { | 132 } else if (error.errorCode.type == ErrorType.HINT) { |
| 116 hintCount++; | 133 hintCount++; |
| 117 } else if (error.errorCode.type == ErrorType.LINT) { | 134 } else if (error.errorCode.type == ErrorType.LINT) { |
| 118 lintCount++; | 135 lintCount++; |
| 119 } | 136 } |
| 120 formatError(errorToLine, error); | 137 formatError(errorToLine, error); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 204 } |
| 188 | 205 |
| 189 static String pluralize(String word, int count) { | 206 static String pluralize(String word, int count) { |
| 190 if (count == 1) { | 207 if (count == 1) { |
| 191 return word; | 208 return word; |
| 192 } else { | 209 } else { |
| 193 return word + "s"; | 210 return word + "s"; |
| 194 } | 211 } |
| 195 } | 212 } |
| 196 } | 213 } |
| 214 |
| 215 /// A severity with awareness of whether it was overriden by a processor. |
| 216 class ProcessedSeverity { |
| 217 ErrorSeverity severity; |
| 218 bool overridden; |
| 219 ProcessedSeverity(this.severity, [this.overridden = false]); |
| 220 } |
| OLD | NEW |