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.analyzer_impl; | 5 library analyzer_cli.src.analyzer_impl; |
6 | 6 |
| 7 import 'dart:async'; |
7 import 'dart:collection'; | 8 import 'dart:collection'; |
8 import 'dart:io'; | 9 import 'dart:io'; |
9 | 10 |
10 import 'package:analyzer/dart/element/element.dart'; | 11 import 'package:analyzer/dart/element/element.dart'; |
11 import 'package:analyzer/error/error.dart'; | 12 import 'package:analyzer/error/error.dart'; |
12 import 'package:analyzer/exception/exception.dart'; | 13 import 'package:analyzer/exception/exception.dart'; |
13 import 'package:analyzer/source/error_processor.dart'; | 14 import 'package:analyzer/source/error_processor.dart'; |
14 import 'package:analyzer/src/error/codes.dart'; | 15 import 'package:analyzer/src/error/codes.dart'; |
15 import 'package:analyzer/src/generated/engine.dart'; | 16 import 'package:analyzer/src/generated/engine.dart'; |
16 import 'package:analyzer/src/generated/java_io.dart'; | 17 import 'package:analyzer/src/generated/java_io.dart'; |
(...skipping 13 matching lines...) Expand all Loading... |
30 /// Analyzes single library [File]. | 31 /// Analyzes single library [File]. |
31 class AnalyzerImpl { | 32 class AnalyzerImpl { |
32 static final PerformanceTag _prepareErrorsTag = | 33 static final PerformanceTag _prepareErrorsTag = |
33 new PerformanceTag("AnalyzerImpl.prepareErrors"); | 34 new PerformanceTag("AnalyzerImpl.prepareErrors"); |
34 static final PerformanceTag _resolveLibraryTag = | 35 static final PerformanceTag _resolveLibraryTag = |
35 new PerformanceTag("AnalyzerImpl._resolveLibrary"); | 36 new PerformanceTag("AnalyzerImpl._resolveLibrary"); |
36 | 37 |
37 final CommandLineOptions options; | 38 final CommandLineOptions options; |
38 final int startTime; | 39 final int startTime; |
39 | 40 |
| 41 final AnalysisOptions analysisOptions; |
40 final AnalysisContext context; | 42 final AnalysisContext context; |
41 | 43 |
42 /// Accumulated analysis statistics. | 44 /// Accumulated analysis statistics. |
43 final AnalysisStats stats; | 45 final AnalysisStats stats; |
44 | 46 |
45 final Source librarySource; | 47 final Source librarySource; |
46 | 48 |
47 /// All [Source]s references by the analyzed library. | 49 /// All [Source]s references by the analyzed library. |
48 final Set<Source> sources = new Set<Source>(); | 50 final Set<Source> sources = new Set<Source>(); |
49 | 51 |
50 /// All [AnalysisErrorInfo]s in the analyzed library. | 52 /// All [AnalysisErrorInfo]s in the analyzed library. |
51 final List<AnalysisErrorInfo> errorInfos = new List<AnalysisErrorInfo>(); | 53 final List<AnalysisErrorInfo> errorInfos = new List<AnalysisErrorInfo>(); |
52 | 54 |
53 /// [HashMap] between sources and analysis error infos. | 55 /// [HashMap] between sources and analysis error infos. |
54 final HashMap<Source, AnalysisErrorInfo> sourceErrorsMap = | 56 final HashMap<Source, AnalysisErrorInfo> sourceErrorsMap = |
55 new HashMap<Source, AnalysisErrorInfo>(); | 57 new HashMap<Source, AnalysisErrorInfo>(); |
56 | 58 |
57 /// If the file specified on the command line is part of a package, the name | 59 /// If the file specified on the command line is part of a package, the name |
58 /// of that package. Otherwise `null`. This allows us to analyze the file | 60 /// of that package. Otherwise `null`. This allows us to analyze the file |
59 /// specified on the command line as though it is reached via a "package:" | 61 /// specified on the command line as though it is reached via a "package:" |
60 /// URI, but avoid suppressing its output in the event that the user has not | 62 /// URI, but avoid suppressing its output in the event that the user has not |
61 /// specified the "--package-warnings" option. | 63 /// specified the "--package-warnings" option. |
62 String _selfPackageName; | 64 String _selfPackageName; |
63 | 65 |
64 AnalyzerImpl(this.context, this.librarySource, this.options, this.stats, | 66 AnalyzerImpl(this.analysisOptions, this.context, this.librarySource, |
65 this.startTime); | 67 this.options, this.stats, this.startTime); |
66 | 68 |
67 /// Returns the maximal [ErrorSeverity] of the recorded errors. | 69 /// Returns the maximal [ErrorSeverity] of the recorded errors. |
68 ErrorSeverity get maxErrorSeverity { | 70 ErrorSeverity get maxErrorSeverity { |
69 var status = ErrorSeverity.NONE; | 71 var status = ErrorSeverity.NONE; |
70 for (AnalysisErrorInfo errorInfo in errorInfos) { | 72 for (AnalysisErrorInfo errorInfo in errorInfos) { |
71 for (AnalysisError error in errorInfo.errors) { | 73 for (AnalysisError error in errorInfo.errors) { |
72 if (_processError(error) == null) { | 74 if (_processError(error) == null) { |
73 continue; | 75 continue; |
74 } | 76 } |
75 var severity = computeSeverity(error, options); | 77 var severity = computeSeverity(error, options); |
(...skipping 28 matching lines...) Expand all Loading... |
104 } | 106 } |
105 // Add referenced libraries. | 107 // Add referenced libraries. |
106 for (LibraryElement child in library.importedLibraries) { | 108 for (LibraryElement child in library.importedLibraries) { |
107 addLibrarySources(child, libraries, units); | 109 addLibrarySources(child, libraries, units); |
108 } | 110 } |
109 for (LibraryElement child in library.exportedLibraries) { | 111 for (LibraryElement child in library.exportedLibraries) { |
110 addLibrarySources(child, libraries, units); | 112 addLibrarySources(child, libraries, units); |
111 } | 113 } |
112 } | 114 } |
113 | 115 |
114 /// Treats the [sourcePath] as the top level library and analyzes it using a | 116 /// Treats the [sourcePath] as the top level library and analyzes it using |
115 /// synchronous algorithm over the analysis engine. If [printMode] is `0`, | 117 /// the analysis engine. If [printMode] is `0`, then no error or performance |
116 /// then no error or performance information is printed. If [printMode] is `1`
, | 118 /// information is printed. If [printMode] is `1`, then both will be printed. |
117 /// then both will be printed. If [printMode] is `2`, then only performance | 119 /// If [printMode] is `2`, then only performance information will be printed, |
118 /// information will be printed, and it will be marked as being for a cold VM. | 120 /// and it will be marked as being for a cold VM. |
119 ErrorSeverity analyzeSync({int printMode: 1}) { | 121 Future<ErrorSeverity> analyze({int printMode: 1}) async { |
120 setupForAnalysis(); | 122 setupForAnalysis(); |
121 return _analyzeSync(printMode); | 123 return await _analyze(printMode); |
122 } | 124 } |
123 | 125 |
124 /// Fills [errorInfos] using [sources]. | 126 /// Fills [errorInfos] using [sources]. |
125 void prepareErrors() { | 127 Future<Null> prepareErrors() async { |
126 return _prepareErrorsTag.makeCurrentWhile(() { | 128 PerformanceTag previous = _prepareErrorsTag.makeCurrent(); |
| 129 try { |
127 for (Source source in sources) { | 130 for (Source source in sources) { |
128 context.computeErrors(source); | 131 context.computeErrors(source); |
129 errorInfos.add(context.getErrors(source)); | 132 errorInfos.add(context.getErrors(source)); |
130 } | 133 } |
131 }); | 134 } finally { |
| 135 previous.makeCurrent(); |
| 136 } |
132 } | 137 } |
133 | 138 |
134 /// Fills [sources]. | 139 /// Fills [sources]. |
135 void prepareSources(LibraryElement library) { | 140 void prepareSources(LibraryElement library) { |
136 var units = new Set<CompilationUnitElement>(); | 141 var units = new Set<CompilationUnitElement>(); |
137 var libraries = new Set<LibraryElement>(); | 142 var libraries = new Set<LibraryElement>(); |
138 addLibrarySources(library, libraries, units); | 143 addLibrarySources(library, libraries, units); |
139 } | 144 } |
140 | 145 |
141 /// Setup local fields such as the analysis context for analysis. | 146 /// Setup local fields such as the analysis context for analysis. |
142 void setupForAnalysis() { | 147 void setupForAnalysis() { |
143 sources.clear(); | 148 sources.clear(); |
144 errorInfos.clear(); | 149 errorInfos.clear(); |
145 Uri libraryUri = librarySource.uri; | 150 Uri libraryUri = librarySource.uri; |
146 if (libraryUri.scheme == 'package' && libraryUri.pathSegments.length > 0) { | 151 if (libraryUri.scheme == 'package' && libraryUri.pathSegments.length > 0) { |
147 _selfPackageName = libraryUri.pathSegments[0]; | 152 _selfPackageName = libraryUri.pathSegments[0]; |
148 } | 153 } |
149 } | 154 } |
150 | 155 |
151 /// The sync version of analysis. | 156 Future<ErrorSeverity> _analyze(int printMode) async { |
152 ErrorSeverity _analyzeSync(int printMode) { | |
153 // Don't try to analyze parts. | 157 // Don't try to analyze parts. |
154 if (context.computeKindOf(librarySource) == SourceKind.PART) { | 158 if (context.computeKindOf(librarySource) == SourceKind.PART) { |
155 stderr.writeln("Only libraries can be analyzed."); | 159 stderr.writeln("Only libraries can be analyzed."); |
156 stderr.writeln( | 160 stderr.writeln( |
157 "${librarySource.fullName} is a part and can not be analyzed."); | 161 "${librarySource.fullName} is a part and can not be analyzed."); |
158 return ErrorSeverity.ERROR; | 162 return ErrorSeverity.ERROR; |
159 } | 163 } |
160 var libraryElement = _resolveLibrary(); | 164 LibraryElement libraryElement = await _resolveLibrary(); |
161 prepareSources(libraryElement); | 165 prepareSources(libraryElement); |
162 prepareErrors(); | 166 await prepareErrors(); |
163 | 167 |
164 // Print errors and performance numbers. | 168 // Print errors and performance numbers. |
165 if (printMode == 1) { | 169 if (printMode == 1) { |
166 _printErrors(); | 170 _printErrors(); |
167 } else if (printMode == 2) { | 171 } else if (printMode == 2) { |
168 _printColdPerf(); | 172 _printColdPerf(); |
169 } | 173 } |
170 | 174 |
171 // Compute max severity and set exitCode. | 175 // Compute max severity and set exitCode. |
172 ErrorSeverity status = maxErrorSeverity; | 176 ErrorSeverity status = maxErrorSeverity; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 // "cannot have the batch flag and source file" error message. | 237 // "cannot have the batch flag and source file" error message. |
234 StringSink sink = options.machineFormat ? errorSink : outSink; | 238 StringSink sink = options.machineFormat ? errorSink : outSink; |
235 | 239 |
236 // Print errors. | 240 // Print errors. |
237 ErrorFormatter formatter = | 241 ErrorFormatter formatter = |
238 new ErrorFormatter(sink, options, stats, _processError); | 242 new ErrorFormatter(sink, options, stats, _processError); |
239 formatter.formatErrors(errorInfos); | 243 formatter.formatErrors(errorInfos); |
240 } | 244 } |
241 | 245 |
242 ProcessedSeverity _processError(AnalysisError error) => | 246 ProcessedSeverity _processError(AnalysisError error) => |
243 processError(error, options, context); | 247 processError(error, options, analysisOptions); |
244 | 248 |
245 LibraryElement _resolveLibrary() { | 249 Future<LibraryElement> _resolveLibrary() async { |
246 return _resolveLibraryTag.makeCurrentWhile(() { | 250 PerformanceTag previous = _resolveLibraryTag.makeCurrent(); |
| 251 try { |
247 return context.computeLibraryElement(librarySource); | 252 return context.computeLibraryElement(librarySource); |
248 }); | 253 } finally { |
| 254 previous.makeCurrent(); |
| 255 } |
249 } | 256 } |
250 | 257 |
251 /// Compute the severity of the error; however: | 258 /// Compute the severity of the error; however: |
252 /// * if [options.enableTypeChecks] is false, then de-escalate checked-mode | 259 /// * if [options.enableTypeChecks] is false, then de-escalate checked-mode |
253 /// compile time errors to a severity of [ErrorSeverity.INFO]. | 260 /// compile time errors to a severity of [ErrorSeverity.INFO]. |
254 /// * if [options.hintsAreFatal] is true, escalate hints to errors. | 261 /// * if [options.hintsAreFatal] is true, escalate hints to errors. |
255 /// * if [options.lintsAreFatal] is true, escalate lints to errors. | 262 /// * if [options.lintsAreFatal] is true, escalate lints to errors. |
256 static ErrorSeverity computeSeverity( | 263 static ErrorSeverity computeSeverity( |
257 AnalysisError error, CommandLineOptions options, | 264 AnalysisError error, CommandLineOptions options, |
258 [AnalysisContext context]) { | 265 [AnalysisOptions analysisOptions]) { |
259 if (context != null) { | 266 if (analysisOptions != null) { |
260 ErrorProcessor processor = | 267 ErrorProcessor processor = |
261 ErrorProcessor.getProcessor(context.analysisOptions, error); | 268 ErrorProcessor.getProcessor(analysisOptions, error); |
262 // If there is a processor for this error, defer to it. | 269 // If there is a processor for this error, defer to it. |
263 if (processor != null) { | 270 if (processor != null) { |
264 return processor.severity; | 271 return processor.severity; |
265 } | 272 } |
266 } | 273 } |
267 | 274 |
268 if (!options.enableTypeChecks && | 275 if (!options.enableTypeChecks && |
269 error.errorCode.type == ErrorType.CHECKED_MODE_COMPILE_TIME_ERROR) { | 276 error.errorCode.type == ErrorType.CHECKED_MODE_COMPILE_TIME_ERROR) { |
270 return ErrorSeverity.INFO; | 277 return ErrorSeverity.INFO; |
271 } else if (options.hintsAreFatal && error.errorCode is HintCode) { | 278 } else if (options.hintsAreFatal && error.errorCode is HintCode) { |
(...skipping 17 matching lines...) Expand all Loading... |
289 } | 296 } |
290 dir = dir.getParentFile(); | 297 dir = dir.getParentFile(); |
291 } | 298 } |
292 // Not found. | 299 // Not found. |
293 return null; | 300 return null; |
294 } | 301 } |
295 | 302 |
296 /// Check various configuration options to get a desired severity for this | 303 /// Check various configuration options to get a desired severity for this |
297 /// [error] (or `null` if it's to be suppressed). | 304 /// [error] (or `null` if it's to be suppressed). |
298 static ProcessedSeverity processError(AnalysisError error, | 305 static ProcessedSeverity processError(AnalysisError error, |
299 CommandLineOptions options, AnalysisContext context) { | 306 CommandLineOptions options, AnalysisOptions analysisOptions) { |
300 ErrorSeverity severity = computeSeverity(error, options, context); | 307 ErrorSeverity severity = computeSeverity(error, options, analysisOptions); |
301 bool isOverridden = false; | 308 bool isOverridden = false; |
302 | 309 |
303 // Skip TODOs categorically (unless escalated to ERROR or HINT.) | 310 // Skip TODOs categorically (unless escalated to ERROR or HINT.) |
304 // https://github.com/dart-lang/sdk/issues/26215 | 311 // https://github.com/dart-lang/sdk/issues/26215 |
305 if (error.errorCode.type == ErrorType.TODO && | 312 if (error.errorCode.type == ErrorType.TODO && |
306 severity == ErrorSeverity.INFO) { | 313 severity == ErrorSeverity.INFO) { |
307 return null; | 314 return null; |
308 } | 315 } |
309 | 316 |
310 // First check for a filter. | 317 // First check for a filter. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 } | 362 } |
356 | 363 |
357 @override | 364 @override |
358 void logInformation(String message, [CaughtException exception]) { | 365 void logInformation(String message, [CaughtException exception]) { |
359 outSink.writeln(message); | 366 outSink.writeln(message); |
360 if (exception != null) { | 367 if (exception != null) { |
361 outSink.writeln(exception); | 368 outSink.writeln(exception); |
362 } | 369 } |
363 } | 370 } |
364 } | 371 } |
OLD | NEW |