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 |