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'; | 9 import 'dart:io'; |
10 | 10 |
(...skipping 15 matching lines...) Expand all Loading... | |
26 import 'package:analyzer/src/generated/java_engine.dart'; | 26 import 'package:analyzer/src/generated/java_engine.dart'; |
27 import 'package:analyzer/src/generated/java_io.dart'; | 27 import 'package:analyzer/src/generated/java_io.dart'; |
28 import 'package:analyzer/src/generated/sdk_io.dart'; | 28 import 'package:analyzer/src/generated/sdk_io.dart'; |
29 import 'package:analyzer/src/generated/source.dart'; | 29 import 'package:analyzer/src/generated/source.dart'; |
30 import 'package:analyzer/src/generated/source_io.dart'; | 30 import 'package:analyzer/src/generated/source_io.dart'; |
31 import 'package:analyzer/src/generated/utilities_general.dart' | 31 import 'package:analyzer/src/generated/utilities_general.dart' |
32 show PerformanceTag; | 32 show PerformanceTag; |
33 import 'package:analyzer/src/services/lint.dart'; | 33 import 'package:analyzer/src/services/lint.dart'; |
34 import 'package:analyzer/src/task/options.dart'; | 34 import 'package:analyzer/src/task/options.dart'; |
35 import 'package:analyzer_cli/src/analyzer_impl.dart'; | 35 import 'package:analyzer_cli/src/analyzer_impl.dart'; |
36 import 'package:analyzer_cli/src/error_formatter.dart'; | |
36 import 'package:analyzer_cli/src/options.dart'; | 37 import 'package:analyzer_cli/src/options.dart'; |
37 import 'package:analyzer_cli/src/package_analyzer.dart'; | 38 import 'package:analyzer_cli/src/package_analyzer.dart'; |
38 import 'package:analyzer_cli/src/perf_report.dart'; | 39 import 'package:analyzer_cli/src/perf_report.dart'; |
39 import 'package:analyzer_cli/starter.dart'; | 40 import 'package:analyzer_cli/starter.dart'; |
40 import 'package:linter/src/plugin/linter_plugin.dart'; | 41 import 'package:linter/src/plugin/linter_plugin.dart'; |
41 import 'package:package_config/discovery.dart' as pkgDiscovery; | 42 import 'package:package_config/discovery.dart' as pkgDiscovery; |
42 import 'package:package_config/packages.dart' show Packages; | 43 import 'package:package_config/packages.dart' show Packages; |
43 import 'package:package_config/packages_file.dart' as pkgfile show parse; | 44 import 'package:package_config/packages_file.dart' as pkgfile show parse; |
44 import 'package:package_config/src/packages_impl.dart' show MapPackages; | 45 import 'package:package_config/src/packages_impl.dart' show MapPackages; |
45 import 'package:path/path.dart' as path; | 46 import 'package:path/path.dart' as path; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 /// If [_context] is not `null`, the [CommandLineOptions] that guided its | 83 /// If [_context] is not `null`, the [CommandLineOptions] that guided its |
83 /// creation. | 84 /// creation. |
84 CommandLineOptions _previousOptions; | 85 CommandLineOptions _previousOptions; |
85 | 86 |
86 @override | 87 @override |
87 EmbeddedResolverProvider embeddedUriResolverProvider; | 88 EmbeddedResolverProvider embeddedUriResolverProvider; |
88 | 89 |
89 @override | 90 @override |
90 ResolverProvider packageResolverProvider; | 91 ResolverProvider packageResolverProvider; |
91 | 92 |
93 /// Collected analysis statistics. | |
94 final AnalysisStats stats = new AnalysisStats(); | |
95 | |
92 /// This Driver's current analysis context. | 96 /// This Driver's current analysis context. |
93 /// | 97 /// |
94 /// *Visible for testing.* | 98 /// *Visible for testing.* |
95 AnalysisContext get context => _context; | 99 AnalysisContext get context => _context; |
96 | 100 |
97 @override | 101 @override |
98 void set userDefinedPlugins(List<Plugin> plugins) { | 102 void set userDefinedPlugins(List<Plugin> plugins) { |
99 _userDefinedPlugins = plugins == null ? <Plugin>[] : plugins; | 103 _userDefinedPlugins = plugins ?? <Plugin>[]; |
100 } | 104 } |
101 | 105 |
102 @override | 106 @override |
103 void start(List<String> args) { | 107 void start(List<String> args) { |
104 int startTime = new DateTime.now().millisecondsSinceEpoch; | 108 int startTime = new DateTime.now().millisecondsSinceEpoch; |
105 | 109 |
106 StringUtilities.INTERNER = new MappedInterner(); | 110 StringUtilities.INTERNER = new MappedInterner(); |
107 | 111 |
108 _processPlugins(); | 112 _processPlugins(); |
109 | 113 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 try { | 159 try { |
156 _createAnalysisContext(options); | 160 _createAnalysisContext(options); |
157 } on _DriverError catch (error) { | 161 } on _DriverError catch (error) { |
158 outSink.writeln(error.msg); | 162 outSink.writeln(error.msg); |
159 return ErrorSeverity.ERROR; | 163 return ErrorSeverity.ERROR; |
160 } | 164 } |
161 | 165 |
162 // Add all the files to be analyzed en masse to the context. Skip any | 166 // Add all the files to be analyzed en masse to the context. Skip any |
163 // files that were added earlier (whether explicitly or implicitly) to | 167 // files that were added earlier (whether explicitly or implicitly) to |
164 // avoid causing those files to be unnecessarily re-read. | 168 // avoid causing those files to be unnecessarily re-read. |
165 Set<Source> knownSources = _context.sources.toSet(); | 169 Set<Source> knownSources = context.sources.toSet(); |
166 List<Source> sourcesToAnalyze = <Source>[]; | 170 List<Source> sourcesToAnalyze = <Source>[]; |
167 ChangeSet changeSet = new ChangeSet(); | 171 ChangeSet changeSet = new ChangeSet(); |
168 for (String sourcePath in options.sourceFiles) { | 172 for (String sourcePath in options.sourceFiles) { |
169 sourcePath = sourcePath.trim(); | 173 sourcePath = sourcePath.trim(); |
170 // Check that file exists. | 174 |
171 if (!new File(sourcePath).existsSync()) { | 175 // Collect files for analysis. |
172 errorSink.writeln('File not found: $sourcePath'); | 176 // Note that these files will all be analyzed in the same context. |
177 // This should be updated when the ContextManager re-work is complete | |
178 // (See: https://github.com/dart-lang/sdk/issues/24133) | |
179 Iterable<File> files = _collectFiles(sourcePath); | |
180 if (files.isEmpty) { | |
181 errorSink.writeln('No dart files found at: $sourcePath'); | |
173 exitCode = ErrorSeverity.ERROR.ordinal; | 182 exitCode = ErrorSeverity.ERROR.ordinal; |
174 //Fail fast; don't analyze more files | |
175 return ErrorSeverity.ERROR; | 183 return ErrorSeverity.ERROR; |
176 } | 184 } |
177 // Check that file is Dart file. | 185 |
178 if (!AnalysisEngine.isDartFileName(sourcePath)) { | 186 for (File file in files) { |
179 errorSink.writeln('$sourcePath is not a Dart file'); | 187 Source source = _computeLibrarySource(file.absolute.path); |
180 exitCode = ErrorSeverity.ERROR.ordinal; | 188 if (!knownSources.contains(source)) { |
181 // Fail fast; don't analyze more files. | 189 changeSet.addedSource(source); |
182 return ErrorSeverity.ERROR; | 190 } |
191 sourcesToAnalyze.add(source); | |
pquitslund
2016/03/17 18:55:55
FYI: here's the change. The previous version had
| |
183 } | 192 } |
184 Source source = _computeLibrarySource(sourcePath); | |
185 if (!knownSources.contains(source)) { | |
186 changeSet.addedSource(source); | |
187 } | |
188 sourcesToAnalyze.add(source); | |
189 } | 193 } |
190 _context.applyChanges(changeSet); | 194 context.applyChanges(changeSet); |
191 | 195 |
192 // Analyze the libraries. | 196 // Analyze the libraries. |
193 ErrorSeverity allResult = ErrorSeverity.NONE; | 197 ErrorSeverity allResult = ErrorSeverity.NONE; |
194 var libUris = <Uri>[]; | 198 var libUris = <Uri>[]; |
195 var parts = <Source>[]; | 199 var parts = <Source>[]; |
196 for (Source source in sourcesToAnalyze) { | 200 for (Source source in sourcesToAnalyze) { |
197 if (context.computeKindOf(source) == SourceKind.PART) { | 201 if (context.computeKindOf(source) == SourceKind.PART) { |
198 parts.add(source); | 202 parts.add(source); |
199 continue; | 203 continue; |
200 } | 204 } |
(...skipping 11 matching lines...) Expand all Loading... | |
212 } | 216 } |
213 } | 217 } |
214 if (!found) { | 218 if (!found) { |
215 errorSink.writeln("${part.fullName} is a part and cannot be analyzed."); | 219 errorSink.writeln("${part.fullName} is a part and cannot be analyzed."); |
216 errorSink.writeln("Please pass in a library that contains this part."); | 220 errorSink.writeln("Please pass in a library that contains this part."); |
217 exitCode = ErrorSeverity.ERROR.ordinal; | 221 exitCode = ErrorSeverity.ERROR.ordinal; |
218 allResult = allResult.max(ErrorSeverity.ERROR); | 222 allResult = allResult.max(ErrorSeverity.ERROR); |
219 } | 223 } |
220 } | 224 } |
221 | 225 |
226 if (!options.machineFormat) { | |
227 stats.print(outSink); | |
228 } | |
229 | |
222 return allResult; | 230 return allResult; |
223 } | 231 } |
224 | 232 |
225 /// Perform package analysis according to the given [options]. | 233 /// Perform package analysis according to the given [options]. |
226 ErrorSeverity _analyzePackage(CommandLineOptions options) { | 234 ErrorSeverity _analyzePackage(CommandLineOptions options) { |
227 return _analyzeAllTag.makeCurrentWhile(() { | 235 return _analyzeAllTag.makeCurrentWhile(() { |
228 return new PackageAnalyzer(options).analyze(); | 236 return new PackageAnalyzer(options, stats).analyze(); |
229 }); | 237 }); |
230 } | 238 } |
231 | 239 |
232 /// Determine whether the context created during a previous call to | 240 /// Determine whether the context created during a previous call to |
233 /// [_analyzeAll] can be re-used in order to analyze using [options]. | 241 /// [_analyzeAll] can be re-used in order to analyze using [options]. |
234 bool _canContextBeReused(CommandLineOptions options) { | 242 bool _canContextBeReused(CommandLineOptions options) { |
235 // TODO(paulberry): add a command-line option that disables context re-use. | 243 // TODO(paulberry): add a command-line option that disables context re-use. |
236 if (_context == null) { | 244 if (_context == null) { |
237 return false; | 245 return false; |
238 } | 246 } |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 if (packageUriResolver != null) { | 452 if (packageUriResolver != null) { |
445 resolvers.add(packageUriResolver); | 453 resolvers.add(packageUriResolver); |
446 } | 454 } |
447 | 455 |
448 // Finally files. | 456 // Finally files. |
449 resolvers.add(new FileUriResolver()); | 457 resolvers.add(new FileUriResolver()); |
450 | 458 |
451 return new SourceFactory(resolvers, packages); | 459 return new SourceFactory(resolvers, packages); |
452 } | 460 } |
453 | 461 |
462 /// Collect all analyzable files at [filePath], recursively if it's a | |
463 /// directory, ignoring links. | |
464 Iterable<File> _collectFiles(String filePath) { | |
465 List<File> files = <File>[]; | |
466 File file = new File(filePath); | |
467 if (file.existsSync()) { | |
468 files.add(file); | |
469 } else { | |
470 Directory directory = new Directory(filePath); | |
471 if (directory.existsSync()) { | |
472 for (FileSystemEntity entry | |
473 in directory.listSync(recursive: true, followLinks: false)) { | |
474 String relative = path.relative(entry.path, from: directory.path); | |
475 if (AnalysisEngine.isDartFileName(entry.path) && | |
476 !_isInHiddenDir(relative)) { | |
477 files.add(entry); | |
478 } | |
479 } | |
480 } | |
481 } | |
482 return files; | |
483 } | |
484 | |
454 /// Convert the given [sourcePath] (which may be relative to the current | 485 /// Convert the given [sourcePath] (which may be relative to the current |
455 /// working directory) to a [Source] object that can be fed to the analysis | 486 /// working directory) to a [Source] object that can be fed to the analysis |
456 /// context. | 487 /// context. |
457 Source _computeLibrarySource(String sourcePath) { | 488 Source _computeLibrarySource(String sourcePath) { |
458 sourcePath = _normalizeSourcePath(sourcePath); | 489 sourcePath = _normalizeSourcePath(sourcePath); |
459 JavaFile sourceFile = new JavaFile(sourcePath); | 490 JavaFile sourceFile = new JavaFile(sourcePath); |
460 Source source = sdk.fromFileUri(sourceFile.toURI()); | 491 Source source = sdk.fromFileUri(sourceFile.toURI()); |
461 if (source != null) { | 492 if (source != null) { |
462 return source; | 493 return source; |
463 } | 494 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
518 Map<String, List<fileSystem.Folder>> folderMap = | 549 Map<String, List<fileSystem.Folder>> folderMap = |
519 new Map<String, List<fileSystem.Folder>>(); | 550 new Map<String, List<fileSystem.Folder>>(); |
520 packages.asMap().forEach((String packagePath, Uri uri) { | 551 packages.asMap().forEach((String packagePath, Uri uri) { |
521 folderMap[packagePath] = [ | 552 folderMap[packagePath] = [ |
522 PhysicalResourceProvider.INSTANCE.getFolder(path.fromUri(uri)) | 553 PhysicalResourceProvider.INSTANCE.getFolder(path.fromUri(uri)) |
523 ]; | 554 ]; |
524 }); | 555 }); |
525 return folderMap; | 556 return folderMap; |
526 } | 557 } |
527 | 558 |
559 /// Returns `true` if this relative path is a hidden directory. | |
560 bool _isInHiddenDir(String relative) => | |
561 path.split(relative).any((part) => part.startsWith(".")); | |
562 | |
528 void _processPlugins() { | 563 void _processPlugins() { |
529 List<Plugin> plugins = <Plugin>[]; | 564 List<Plugin> plugins = <Plugin>[]; |
530 plugins.addAll(AnalysisEngine.instance.requiredPlugins); | 565 plugins.addAll(AnalysisEngine.instance.requiredPlugins); |
531 plugins.add(AnalysisEngine.instance.commandLinePlugin); | 566 plugins.add(AnalysisEngine.instance.commandLinePlugin); |
532 plugins.add(AnalysisEngine.instance.optionsPlugin); | 567 plugins.add(AnalysisEngine.instance.optionsPlugin); |
533 plugins.add(linterPlugin); | 568 plugins.add(linterPlugin); |
534 plugins.addAll(_userDefinedPlugins); | 569 plugins.addAll(_userDefinedPlugins); |
535 | 570 |
536 ExtensionManager manager = new ExtensionManager(); | 571 ExtensionManager manager = new ExtensionManager(); |
537 manager.processPlugins(plugins); | 572 manager.processPlugins(plugins); |
538 } | 573 } |
539 | 574 |
540 /// Analyze a single source. | 575 /// Analyze a single source. |
541 ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) { | 576 ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) { |
542 int startTime = currentTimeMillis(); | 577 int startTime = currentTimeMillis(); |
543 AnalyzerImpl analyzer = | 578 AnalyzerImpl analyzer = |
544 new AnalyzerImpl(_context, source, options, startTime); | 579 new AnalyzerImpl(_context, source, options, stats, startTime); |
545 var errorSeverity = analyzer.analyzeSync(); | 580 var errorSeverity = analyzer.analyzeSync(); |
546 if (errorSeverity == ErrorSeverity.ERROR) { | 581 if (errorSeverity == ErrorSeverity.ERROR) { |
547 exitCode = errorSeverity.ordinal; | 582 exitCode = errorSeverity.ordinal; |
548 } | 583 } |
549 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { | 584 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { |
550 exitCode = errorSeverity.ordinal; | 585 exitCode = errorSeverity.ordinal; |
551 } | 586 } |
552 return errorSeverity; | 587 return errorSeverity; |
553 } | 588 } |
554 | 589 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
678 Stream cmdLine = | 713 Stream cmdLine = |
679 stdin.transform(UTF8.decoder).transform(new LineSplitter()); | 714 stdin.transform(UTF8.decoder).transform(new LineSplitter()); |
680 cmdLine.listen((String line) { | 715 cmdLine.listen((String line) { |
681 // Maybe finish. | 716 // Maybe finish. |
682 if (line.isEmpty) { | 717 if (line.isEmpty) { |
683 var time = stopwatch.elapsedMilliseconds; | 718 var time = stopwatch.elapsedMilliseconds; |
684 outSink.writeln( | 719 outSink.writeln( |
685 '>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms') ; | 720 '>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms') ; |
686 exitCode = batchResult.ordinal; | 721 exitCode = batchResult.ordinal; |
687 } | 722 } |
688 // Prepare aruments. | 723 // Prepare arguments. |
689 var args; | 724 var args; |
690 { | 725 { |
691 var lineArgs = line.split(new RegExp('\\s+')); | 726 var lineArgs = line.split(new RegExp('\\s+')); |
692 args = new List<String>(); | 727 args = new List<String>(); |
693 args.addAll(sharedArgs); | 728 args.addAll(sharedArgs); |
694 args.addAll(lineArgs); | 729 args.addAll(lineArgs); |
695 args.remove('-b'); | 730 args.remove('-b'); |
696 args.remove('--batch'); | 731 args.remove('--batch'); |
697 } | 732 } |
698 // Analyze single set of arguments. | 733 // Analyze single set of arguments. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 for (var package in packages) { | 777 for (var package in packages) { |
743 var packageName = path.basename(package.path); | 778 var packageName = path.basename(package.path); |
744 var realPath = package.resolveSymbolicLinksSync(); | 779 var realPath = package.resolveSymbolicLinksSync(); |
745 result[packageName] = [ | 780 result[packageName] = [ |
746 PhysicalResourceProvider.INSTANCE.getFolder(realPath) | 781 PhysicalResourceProvider.INSTANCE.getFolder(realPath) |
747 ]; | 782 ]; |
748 } | 783 } |
749 return result; | 784 return result; |
750 } | 785 } |
751 } | 786 } |
OLD | NEW |