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.driver; | 5 library analyzer_cli.src.driver; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io' as io; | 9 import 'dart:io' as io; |
10 | 10 |
(...skipping 20 matching lines...) Expand all Loading... | |
31 import 'package:analyzer/src/generated/source.dart'; | 31 import 'package:analyzer/src/generated/source.dart'; |
32 import 'package:analyzer/src/generated/source_io.dart'; | 32 import 'package:analyzer/src/generated/source_io.dart'; |
33 import 'package:analyzer/src/generated/utilities_general.dart' | 33 import 'package:analyzer/src/generated/utilities_general.dart' |
34 show PerformanceTag; | 34 show PerformanceTag; |
35 import 'package:analyzer/src/lint/registry.dart'; | 35 import 'package:analyzer/src/lint/registry.dart'; |
36 import 'package:analyzer/src/source/source_resource.dart'; | 36 import 'package:analyzer/src/source/source_resource.dart'; |
37 import 'package:analyzer/src/summary/idl.dart'; | 37 import 'package:analyzer/src/summary/idl.dart'; |
38 import 'package:analyzer/src/summary/package_bundle_reader.dart'; | 38 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
39 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk; | 39 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk; |
40 import 'package:analyzer/src/task/options.dart'; | 40 import 'package:analyzer/src/task/options.dart'; |
41 import 'package:analyzer_cli/src/analyzer_impl.dart'; | |
42 import 'package:analyzer_cli/src/build_mode.dart'; | |
43 import 'package:analyzer_cli/src/error_formatter.dart'; | |
44 import 'package:analyzer_cli/src/options.dart'; | |
45 import 'package:analyzer_cli/src/perf_report.dart'; | |
46 import 'package:analyzer_cli/starter.dart'; | |
47 import 'package:linter/src/rules.dart' as linter; | 41 import 'package:linter/src/rules.dart' as linter; |
48 import 'package:package_config/discovery.dart' as pkg_discovery; | 42 import 'package:package_config/discovery.dart' as pkg_discovery; |
49 import 'package:package_config/packages.dart' show Packages; | 43 import 'package:package_config/packages.dart' show Packages; |
50 import 'package:package_config/packages_file.dart' as pkgfile show parse; | 44 import 'package:package_config/packages_file.dart' as pkgfile show parse; |
51 import 'package:package_config/src/packages_impl.dart' show MapPackages; | 45 import 'package:package_config/src/packages_impl.dart' show MapPackages; |
52 import 'package:path/path.dart' as path; | 46 import 'package:path/path.dart' as path; |
53 import 'package:plugin/manager.dart'; | 47 import 'package:plugin/manager.dart'; |
54 import 'package:plugin/plugin.dart'; | 48 import 'package:plugin/plugin.dart'; |
55 import 'package:yaml/yaml.dart'; | 49 import 'package:yaml/yaml.dart'; |
56 | 50 |
51 import '../starter.dart' show CommandLineStarter; | |
52 import 'analyzer_impl.dart'; | |
53 import 'build_mode.dart'; | |
54 import 'error_formatter.dart'; | |
55 import 'options.dart'; | |
56 import 'perf_report.dart'; | |
57 | |
57 /// Shared IO sink for standard error reporting. | 58 /// Shared IO sink for standard error reporting. |
58 /// | 59 /// |
59 /// *Visible for testing.* | 60 /// *Visible for testing.* |
60 StringSink errorSink = io.stderr; | 61 StringSink errorSink = io.stderr; |
61 | 62 |
62 /// Shared IO sink for standard out reporting. | 63 /// Shared IO sink for standard out reporting. |
63 /// | 64 /// |
64 /// *Visible for testing.* | 65 /// *Visible for testing.* |
65 StringSink outSink = io.stdout; | 66 StringSink outSink = io.stdout; |
66 | 67 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 io.exitCode = severity.ordinal; | 153 io.exitCode = severity.ordinal; |
153 } | 154 } |
154 } | 155 } |
155 | 156 |
156 if (_context != null) { | 157 if (_context != null) { |
157 _analyzedFileCount += _context.sources.length; | 158 _analyzedFileCount += _context.sources.length; |
158 } | 159 } |
159 | 160 |
160 if (options.perfReport != null) { | 161 if (options.perfReport != null) { |
161 String json = makePerfReport( | 162 String json = makePerfReport( |
162 startTime, currentTimeMillis(), options, _analyzedFileCount, stats); | 163 startTime, currentTimeMillis, options, _analyzedFileCount, stats); |
163 new io.File(options.perfReport).writeAsStringSync(json); | 164 new io.File(options.perfReport).writeAsStringSync(json); |
164 } | 165 } |
165 } | 166 } |
166 | 167 |
167 Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async { | 168 Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async { |
168 PerformanceTag previous = _analyzeAllTag.makeCurrent(); | 169 PerformanceTag previous = _analyzeAllTag.makeCurrent(); |
169 try { | 170 try { |
170 return await _analyzeAllImpl(options); | 171 return await _analyzeAllImpl(options); |
171 } finally { | 172 } finally { |
172 previous.makeCurrent(); | 173 previous.makeCurrent(); |
173 } | 174 } |
174 } | 175 } |
175 | 176 |
176 /// Perform analysis according to the given [options]. | 177 /// Perform analysis according to the given [options]. |
177 Future<ErrorSeverity> _analyzeAllImpl(CommandLineOptions options) async { | 178 Future<ErrorSeverity> _analyzeAllImpl(CommandLineOptions options) async { |
178 if (!options.machineFormat) { | 179 if (!options.machineFormat) { |
179 outSink.writeln("Analyzing ${options.sourceFiles}..."); | 180 List<String> fileNames = options.sourceFiles.map((String file) { |
181 file = path.normalize(file); | |
182 if (file == '.') { | |
183 file = path.basename(path.current); | |
184 } else if (file == '..') { | |
185 file = path.basename(path.normalize(path.absolute(file))); | |
186 } | |
187 return file; | |
188 }).toList(); | |
189 | |
190 outSink.writeln("Analyzing ${fileNames.join(', ')}..."); | |
180 } | 191 } |
181 | 192 |
182 // Create a context, or re-use the previous one. | 193 // Create a context, or re-use the previous one. |
183 try { | 194 try { |
184 _createAnalysisContext(options); | 195 _createAnalysisContext(options); |
185 } on _DriverError catch (error) { | 196 } on _DriverError catch (error) { |
186 outSink.writeln(error.msg); | 197 outSink.writeln(error.msg); |
187 return ErrorSeverity.ERROR; | 198 return ErrorSeverity.ERROR; |
188 } | 199 } |
189 | 200 |
190 // Add all the files to be analyzed en masse to the context. Skip any | 201 // Add all the files to be analyzed en masse to the context. Skip any |
191 // files that were added earlier (whether explicitly or implicitly) to | 202 // files that were added earlier (whether explicitly or implicitly) to |
192 // avoid causing those files to be unnecessarily re-read. | 203 // avoid causing those files to be unnecessarily re-read. |
193 Set<Source> knownSources = context.sources.toSet(); | 204 Set<Source> knownSources = context.sources.toSet(); |
194 List<Source> sourcesToAnalyze = <Source>[]; | 205 Set<Source> sourcesToAnalyze = new Set<Source>(); |
195 ChangeSet changeSet = new ChangeSet(); | 206 ChangeSet changeSet = new ChangeSet(); |
196 for (String sourcePath in options.sourceFiles) { | 207 for (String sourcePath in options.sourceFiles) { |
197 sourcePath = sourcePath.trim(); | 208 sourcePath = sourcePath.trim(); |
198 | 209 |
199 // Collect files for analysis. | 210 // Collect files for analysis. |
200 // Note that these files will all be analyzed in the same context. | 211 // Note that these files will all be analyzed in the same context. |
201 // This should be updated when the ContextManager re-work is complete | 212 // This should be updated when the ContextManager re-work is complete |
202 // (See: https://github.com/dart-lang/sdk/issues/24133) | 213 // (See: https://github.com/dart-lang/sdk/issues/24133) |
203 Iterable<io.File> files = _collectFiles(sourcePath); | 214 Iterable<io.File> files = _collectFiles(sourcePath); |
204 if (files.isEmpty) { | 215 if (files.isEmpty) { |
205 errorSink.writeln('No dart files found at: $sourcePath'); | 216 errorSink.writeln('No dart files found at: $sourcePath'); |
206 io.exitCode = ErrorSeverity.ERROR.ordinal; | 217 io.exitCode = ErrorSeverity.ERROR.ordinal; |
207 return ErrorSeverity.ERROR; | 218 return ErrorSeverity.ERROR; |
208 } | 219 } |
209 | 220 |
210 for (io.File file in files) { | 221 for (io.File file in files) { |
211 Source source = _computeLibrarySource(file.absolute.path); | 222 Source source = _computeLibrarySource(file.absolute.path); |
212 if (!knownSources.contains(source)) { | 223 if (!knownSources.contains(source)) { |
213 changeSet.addedSource(source); | 224 changeSet.addedSource(source); |
214 } | 225 } |
215 sourcesToAnalyze.add(source); | 226 sourcesToAnalyze.add(source); |
216 } | 227 } |
217 | 228 |
218 if (analysisDriver != null) { | 229 files.forEach((file) { |
Brian Wilkerson
2017/02/19 22:52:17
It looks like this CL is also removing the non-dri
devoncarew
2017/02/21 04:30:47
No - it's unintentional. I had a fair amount of ch
| |
219 files.forEach((file) { | 230 analysisDriver.addFile(file.path); |
220 analysisDriver.addFile(file.path); | 231 }); |
221 }); | |
222 } else { | |
223 context.applyChanges(changeSet); | |
224 } | |
225 } | 232 } |
226 | 233 |
227 // Analyze the libraries. | 234 // Analyze the libraries. |
228 ErrorSeverity allResult = ErrorSeverity.NONE; | 235 ErrorSeverity allResult = ErrorSeverity.NONE; |
229 var libUris = <Uri>[]; | 236 List<Uri> libUris = <Uri>[]; |
230 var parts = <Source>[]; | 237 Set<Source> partSources = new Set<Source>(); |
238 | |
231 for (Source source in sourcesToAnalyze) { | 239 for (Source source in sourcesToAnalyze) { |
232 SourceKind sourceKind = analysisDriver != null | 240 SourceKind sourceKind = analysisDriver != null |
233 ? await analysisDriver.getSourceKind(source.fullName) | 241 ? await analysisDriver.getSourceKind(source.fullName) |
234 : context.computeKindOf(source); | 242 : context.computeKindOf(source); |
235 if (sourceKind == SourceKind.PART) { | 243 if (sourceKind == SourceKind.PART) { |
236 parts.add(source); | 244 partSources.add(source); |
237 continue; | 245 continue; |
238 } | 246 } |
247 // TODO(devoncarew): Analyzing each source individually causes errors to | |
248 // be reported multiple times (#25697). | |
239 ErrorSeverity status = await _runAnalyzer(source, options); | 249 ErrorSeverity status = await _runAnalyzer(source, options); |
240 allResult = allResult.max(status); | 250 allResult = allResult.max(status); |
241 libUris.add(source.uri); | 251 libUris.add(source.uri); |
242 } | 252 } |
243 | 253 |
244 // Check that each part has a corresponding source in the input list. | 254 // Check that each part has a corresponding source in the input list. |
245 for (Source part in parts) { | 255 for (Source partSource in partSources) { |
246 bool found = false; | 256 bool found = false; |
247 if (analysisDriver != null) { | 257 if (analysisDriver != null) { |
248 var partFile = analysisDriver.fsState.getFileForPath(part.fullName); | 258 var partFile = |
259 analysisDriver.fsState.getFileForPath(partSource.fullName); | |
249 if (libUris.contains(partFile.library?.uri)) { | 260 if (libUris.contains(partFile.library?.uri)) { |
250 found = true; | 261 found = true; |
251 } | 262 } |
252 } else { | 263 } else { |
253 for (var lib in context.getLibrariesContaining(part)) { | 264 for (var lib in context.getLibrariesContaining(partSource)) { |
254 if (libUris.contains(lib.uri)) { | 265 if (libUris.contains(lib.uri)) { |
255 found = true; | 266 found = true; |
256 } | 267 } |
257 } | 268 } |
258 } | 269 } |
259 if (!found) { | 270 if (!found) { |
260 errorSink.writeln("${part.fullName} is a part and cannot be analyzed."); | 271 errorSink.writeln( |
272 "${partSource.fullName} is a part and cannot be analyzed."); | |
261 errorSink.writeln("Please pass in a library that contains this part."); | 273 errorSink.writeln("Please pass in a library that contains this part."); |
262 io.exitCode = ErrorSeverity.ERROR.ordinal; | 274 io.exitCode = ErrorSeverity.ERROR.ordinal; |
263 allResult = allResult.max(ErrorSeverity.ERROR); | 275 allResult = allResult.max(ErrorSeverity.ERROR); |
264 } | 276 } |
265 } | 277 } |
266 | 278 |
267 if (!options.machineFormat) { | 279 if (!options.machineFormat) { |
268 stats.print(outSink); | 280 stats.print(outSink); |
269 } | 281 } |
270 | 282 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
461 if (packageUriResolver != null) { | 473 if (packageUriResolver != null) { |
462 resolvers.add(packageUriResolver); | 474 resolvers.add(packageUriResolver); |
463 } | 475 } |
464 | 476 |
465 // Finally files. | 477 // Finally files. |
466 resolvers.add(new file_system.ResourceUriResolver(resourceProvider)); | 478 resolvers.add(new file_system.ResourceUriResolver(resourceProvider)); |
467 | 479 |
468 return new SourceFactory(resolvers, packageInfo.packages); | 480 return new SourceFactory(resolvers, packageInfo.packages); |
469 } | 481 } |
470 | 482 |
483 // TODO(devoncarew): This needs to respect analysis_options excludes. | |
484 | |
471 /// Collect all analyzable files at [filePath], recursively if it's a | 485 /// Collect all analyzable files at [filePath], recursively if it's a |
472 /// directory, ignoring links. | 486 /// directory, ignoring links. |
473 Iterable<io.File> _collectFiles(String filePath) { | 487 Iterable<io.File> _collectFiles(String filePath) { |
474 List<io.File> files = <io.File>[]; | 488 List<io.File> files = <io.File>[]; |
475 io.File file = new io.File(filePath); | 489 io.File file = new io.File(filePath); |
476 if (file.existsSync()) { | 490 if (file.existsSync()) { |
477 files.add(file); | 491 files.add(file); |
478 } else { | 492 } else { |
479 io.Directory directory = new io.Directory(filePath); | 493 io.Directory directory = new io.Directory(filePath); |
480 if (directory.existsSync()) { | 494 if (directory.existsSync()) { |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
681 | 695 |
682 ExtensionManager manager = new ExtensionManager(); | 696 ExtensionManager manager = new ExtensionManager(); |
683 manager.processPlugins(plugins); | 697 manager.processPlugins(plugins); |
684 | 698 |
685 linter.registerLintRules(); | 699 linter.registerLintRules(); |
686 } | 700 } |
687 | 701 |
688 /// Analyze a single source. | 702 /// Analyze a single source. |
689 Future<ErrorSeverity> _runAnalyzer( | 703 Future<ErrorSeverity> _runAnalyzer( |
690 Source source, CommandLineOptions options) async { | 704 Source source, CommandLineOptions options) async { |
691 int startTime = currentTimeMillis(); | 705 int startTime = currentTimeMillis; |
692 AnalyzerImpl analyzer = new AnalyzerImpl(_context.analysisOptions, _context, | 706 AnalyzerImpl analyzer = new AnalyzerImpl(_context.analysisOptions, _context, |
693 analysisDriver, source, options, stats, startTime); | 707 analysisDriver, source, options, stats, startTime); |
694 ErrorSeverity errorSeverity = await analyzer.analyze(); | 708 ErrorSeverity errorSeverity = await analyzer.analyze(); |
695 if (errorSeverity == ErrorSeverity.ERROR) { | 709 if (errorSeverity == ErrorSeverity.ERROR) { |
696 io.exitCode = errorSeverity.ordinal; | 710 io.exitCode = errorSeverity.ordinal; |
697 } | 711 } |
698 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { | 712 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { |
699 io.exitCode = errorSeverity.ordinal; | 713 io.exitCode = errorSeverity.ordinal; |
700 } | 714 } |
701 return errorSeverity; | 715 return errorSeverity; |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
945 for (var package in packages) { | 959 for (var package in packages) { |
946 var packageName = path.basename(package.path); | 960 var packageName = path.basename(package.path); |
947 var realPath = package.resolveSymbolicLinksSync(); | 961 var realPath = package.resolveSymbolicLinksSync(); |
948 result[packageName] = [ | 962 result[packageName] = [ |
949 PhysicalResourceProvider.INSTANCE.getFolder(realPath) | 963 PhysicalResourceProvider.INSTANCE.getFolder(realPath) |
950 ]; | 964 ]; |
951 } | 965 } |
952 return result; | 966 return result; |
953 } | 967 } |
954 } | 968 } |
OLD | NEW |