| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, 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 library error_formatter; | |
| 6 | |
| 7 import 'package:analyzer/src/analyzer_impl.dart'; | |
| 8 | |
| 9 import '../options.dart'; | |
| 10 import 'generated/engine.dart'; | |
| 11 import 'generated/error.dart'; | |
| 12 import 'generated/source_io.dart'; | |
| 13 | |
| 14 /// Allows any [AnalysisError]. | |
| 15 bool _anyError(AnalysisError error) => true; | |
| 16 | |
| 17 /// Returns `true` if [AnalysisError] should be printed. | |
| 18 typedef bool _ErrorFilter(AnalysisError error); | |
| 19 | |
| 20 /** | |
| 21 * Helper for formatting [AnalysisError]s. | |
| 22 * The two format options are a user consumable format and a machine consumable
format. | |
| 23 */ | |
| 24 class ErrorFormatter { | |
| 25 final StringSink out; | |
| 26 final CommandLineOptions options; | |
| 27 final _ErrorFilter errorFilter; | |
| 28 | |
| 29 ErrorFormatter(this.out, this.options, [this.errorFilter = _anyError]); | |
| 30 | |
| 31 void formatError( | |
| 32 Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) { | |
| 33 Source source = error.source; | |
| 34 LineInfo_Location location = errorToLine[error].getLocation(error.offset); | |
| 35 int length = error.length; | |
| 36 ErrorSeverity severity = | |
| 37 AnalyzerImpl.computeSeverity(error, options.enableTypeChecks); | |
| 38 if (options.machineFormat) { | |
| 39 if (severity == ErrorSeverity.WARNING && options.warningsAreFatal) { | |
| 40 severity = ErrorSeverity.ERROR; | |
| 41 } | |
| 42 out.write(severity); | |
| 43 out.write('|'); | |
| 44 out.write(error.errorCode.type); | |
| 45 out.write('|'); | |
| 46 out.write(error.errorCode.name); | |
| 47 out.write('|'); | |
| 48 out.write(escapePipe(source.fullName)); | |
| 49 out.write('|'); | |
| 50 out.write(location.lineNumber); | |
| 51 out.write('|'); | |
| 52 out.write(location.columnNumber); | |
| 53 out.write('|'); | |
| 54 out.write(length); | |
| 55 out.write('|'); | |
| 56 out.write(escapePipe(error.message)); | |
| 57 } else { | |
| 58 String errorType = severity.displayName; | |
| 59 if (error.errorCode.type == ErrorType.HINT || | |
| 60 error.errorCode.type == ErrorType.LINT) { | |
| 61 errorType = error.errorCode.type.displayName; | |
| 62 } | |
| 63 // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2) | |
| 64 out.write('[$errorType] ${error.message} '); | |
| 65 out.write('(${source.fullName}'); | |
| 66 out.write(', line ${location.lineNumber}, col ${location.columnNumber})'); | |
| 67 } | |
| 68 out.writeln(); | |
| 69 } | |
| 70 | |
| 71 void formatErrors(List<AnalysisErrorInfo> errorInfos) { | |
| 72 var errors = new List<AnalysisError>(); | |
| 73 var errorToLine = new Map<AnalysisError, LineInfo>(); | |
| 74 for (AnalysisErrorInfo errorInfo in errorInfos) { | |
| 75 for (AnalysisError error in errorInfo.errors) { | |
| 76 if (errorFilter(error)) { | |
| 77 errors.add(error); | |
| 78 errorToLine[error] = errorInfo.lineInfo; | |
| 79 } | |
| 80 } | |
| 81 } | |
| 82 // sort errors | |
| 83 errors.sort((AnalysisError error1, AnalysisError error2) { | |
| 84 // severity | |
| 85 ErrorSeverity severity1 = | |
| 86 AnalyzerImpl.computeSeverity(error1, options.enableTypeChecks); | |
| 87 ErrorSeverity severity2 = | |
| 88 AnalyzerImpl.computeSeverity(error2, options.enableTypeChecks); | |
| 89 int compare = severity2.compareTo(severity1); | |
| 90 if (compare != 0) { | |
| 91 return compare; | |
| 92 } | |
| 93 // path | |
| 94 compare = Comparable.compare(error1.source.fullName.toLowerCase(), | |
| 95 error2.source.fullName.toLowerCase()); | |
| 96 if (compare != 0) { | |
| 97 return compare; | |
| 98 } | |
| 99 // offset | |
| 100 return error1.offset - error2.offset; | |
| 101 }); | |
| 102 // format errors | |
| 103 int errorCount = 0; | |
| 104 int warnCount = 0; | |
| 105 int hintCount = 0; | |
| 106 int lintCount = 0; | |
| 107 for (AnalysisError error in errors) { | |
| 108 ErrorSeverity severity = | |
| 109 AnalyzerImpl.computeSeverity(error, options.enableTypeChecks); | |
| 110 if (severity == ErrorSeverity.ERROR) { | |
| 111 errorCount++; | |
| 112 } else if (severity == ErrorSeverity.WARNING) { | |
| 113 if (options.warningsAreFatal) { | |
| 114 errorCount++; | |
| 115 } else { | |
| 116 if (error.errorCode.type == ErrorType.HINT) { | |
| 117 hintCount++; | |
| 118 } else { | |
| 119 warnCount++; | |
| 120 } | |
| 121 } | |
| 122 } else if (error.errorCode.type == ErrorType.LINT) { | |
| 123 lintCount++; | |
| 124 } | |
| 125 formatError(errorToLine, error); | |
| 126 } | |
| 127 // print statistics | |
| 128 if (!options.machineFormat) { | |
| 129 var hasErrors = errorCount != 0; | |
| 130 var hasWarns = warnCount != 0; | |
| 131 var hasHints = hintCount != 0; | |
| 132 var hasLints = lintCount != 0; | |
| 133 bool hasContent = false; | |
| 134 if (hasErrors) { | |
| 135 out.write(errorCount); | |
| 136 out.write(' '); | |
| 137 out.write(pluralize("error", errorCount)); | |
| 138 hasContent = true; | |
| 139 } | |
| 140 if (hasWarns) { | |
| 141 if (hasContent) { | |
| 142 if (!hasHints && !hasLints) { | |
| 143 out.write(' and '); | |
| 144 } else { | |
| 145 out.write(", "); | |
| 146 } | |
| 147 } | |
| 148 out.write(warnCount); | |
| 149 out.write(' '); | |
| 150 out.write(pluralize("warning", warnCount)); | |
| 151 hasContent = true; | |
| 152 } | |
| 153 if (hasHints) { | |
| 154 if (hasContent) { | |
| 155 if (!hasLints) { | |
| 156 out.write(' and '); | |
| 157 } else { | |
| 158 out.write(", "); | |
| 159 } | |
| 160 } | |
| 161 out.write(hintCount); | |
| 162 out.write(' '); | |
| 163 out.write(pluralize("hint", hintCount)); | |
| 164 hasContent = true; | |
| 165 } | |
| 166 if (hasLints) { | |
| 167 if (hasContent) { | |
| 168 out.write(" and "); | |
| 169 } | |
| 170 out.write(lintCount); | |
| 171 out.write(' '); | |
| 172 out.write(pluralize("lint", lintCount)); | |
| 173 hasContent = true; | |
| 174 } | |
| 175 if (hasContent) { | |
| 176 out.writeln(" found."); | |
| 177 } else { | |
| 178 out.writeln("No issues found"); | |
| 179 } | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 static String escapePipe(String input) { | |
| 184 var result = new StringBuffer(); | |
| 185 for (var c in input.codeUnits) { | |
| 186 if (c == '\\' || c == '|') { | |
| 187 result.write('\\'); | |
| 188 } | |
| 189 result.writeCharCode(c); | |
| 190 } | |
| 191 return result.toString(); | |
| 192 } | |
| 193 | |
| 194 static String pluralize(String word, int count) { | |
| 195 if (count == 1) { | |
| 196 return word; | |
| 197 } else { | |
| 198 return word + "s"; | |
| 199 } | |
| 200 } | |
| 201 } | |
| OLD | NEW |