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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 /// | 61 /// |
62 /// *Visible for testing.* | 62 /// *Visible for testing.* |
63 StringSink outSink = io.stdout; | 63 StringSink outSink = io.stdout; |
64 | 64 |
65 /// Test this option map to see if it specifies lint rules. | 65 /// Test this option map to see if it specifies lint rules. |
66 bool containsLintRuleEntry(Map<String, YamlNode> options) { | 66 bool containsLintRuleEntry(Map<String, YamlNode> options) { |
67 var linterNode = options['linter']; | 67 var linterNode = options['linter']; |
68 return linterNode is YamlMap && linterNode.containsKey('rules'); | 68 return linterNode is YamlMap && linterNode.containsKey('rules'); |
69 } | 69 } |
70 | 70 |
71 typedef ErrorSeverity _BatchRunnerHandler(List<String> args); | 71 typedef Future<ErrorSeverity> _BatchRunnerHandler(List<String> args); |
72 | 72 |
73 class Driver implements CommandLineStarter { | 73 class Driver implements CommandLineStarter { |
74 static final PerformanceTag _analyzeAllTag = | 74 static final PerformanceTag _analyzeAllTag = |
75 new PerformanceTag("Driver._analyzeAll"); | 75 new PerformanceTag("Driver._analyzeAll"); |
76 | 76 |
77 /// The plugins that are defined outside the `analyzer_cli` package. | 77 /// The plugins that are defined outside the `analyzer_cli` package. |
78 List<Plugin> _userDefinedPlugins = <Plugin>[]; | 78 List<Plugin> _userDefinedPlugins = <Plugin>[]; |
79 | 79 |
80 /// The context that was most recently created by a call to [_analyzeAll], or | 80 /// The context that was most recently created by a call to [_analyzeAll], or |
81 /// `null` if [_analyzeAll] hasn't been called yet. | 81 /// `null` if [_analyzeAll] hasn't been called yet. |
(...skipping 25 matching lines...) Expand all Loading... |
107 /// | 107 /// |
108 /// *Visible for testing.* | 108 /// *Visible for testing.* |
109 AnalysisContext get context => _context; | 109 AnalysisContext get context => _context; |
110 | 110 |
111 @override | 111 @override |
112 void set userDefinedPlugins(List<Plugin> plugins) { | 112 void set userDefinedPlugins(List<Plugin> plugins) { |
113 _userDefinedPlugins = plugins ?? <Plugin>[]; | 113 _userDefinedPlugins = plugins ?? <Plugin>[]; |
114 } | 114 } |
115 | 115 |
116 @override | 116 @override |
117 void start(List<String> args) { | 117 Future<Null> start(List<String> args) async { |
118 if (_context != null) { | 118 if (_context != null) { |
119 throw new StateError("start() can only be called once"); | 119 throw new StateError("start() can only be called once"); |
120 } | 120 } |
121 int startTime = new DateTime.now().millisecondsSinceEpoch; | 121 int startTime = new DateTime.now().millisecondsSinceEpoch; |
122 | 122 |
123 StringUtilities.INTERNER = new MappedInterner(); | 123 StringUtilities.INTERNER = new MappedInterner(); |
124 | 124 |
125 _processPlugins(); | 125 _processPlugins(); |
126 | 126 |
127 // Parse commandline options. | 127 // Parse commandline options. |
128 CommandLineOptions options = CommandLineOptions.parse(args); | 128 CommandLineOptions options = CommandLineOptions.parse(args); |
129 | 129 |
130 // Do analysis. | 130 // Do analysis. |
131 if (options.buildMode) { | 131 if (options.buildMode) { |
132 ErrorSeverity severity = _buildModeAnalyze(options); | 132 ErrorSeverity severity = _buildModeAnalyze(options); |
133 // In case of error propagate exit code. | 133 // In case of error propagate exit code. |
134 if (severity == ErrorSeverity.ERROR) { | 134 if (severity == ErrorSeverity.ERROR) { |
135 io.exitCode = severity.ordinal; | 135 io.exitCode = severity.ordinal; |
136 } | 136 } |
137 } else if (options.shouldBatch) { | 137 } else if (options.shouldBatch) { |
138 _BatchRunner.runAsBatch(args, (List<String> args) { | 138 _BatchRunner.runAsBatch(args, (List<String> args) { |
139 CommandLineOptions options = CommandLineOptions.parse(args); | 139 CommandLineOptions options = CommandLineOptions.parse(args); |
140 return _analyzeAll(options); | 140 return _analyzeAll(options); |
141 }); | 141 }); |
142 } else { | 142 } else { |
143 ErrorSeverity severity = _analyzeAll(options); | 143 ErrorSeverity severity = await _analyzeAll(options); |
144 // In case of error propagate exit code. | 144 // In case of error propagate exit code. |
145 if (severity == ErrorSeverity.ERROR) { | 145 if (severity == ErrorSeverity.ERROR) { |
146 io.exitCode = severity.ordinal; | 146 io.exitCode = severity.ordinal; |
147 } | 147 } |
148 } | 148 } |
149 | 149 |
150 if (_context != null) { | 150 if (_context != null) { |
151 _analyzedFileCount += _context.sources.length; | 151 _analyzedFileCount += _context.sources.length; |
152 } | 152 } |
153 | 153 |
154 if (options.perfReport != null) { | 154 if (options.perfReport != null) { |
155 String json = makePerfReport( | 155 String json = makePerfReport( |
156 startTime, currentTimeMillis(), options, _analyzedFileCount, stats); | 156 startTime, currentTimeMillis(), options, _analyzedFileCount, stats); |
157 new io.File(options.perfReport).writeAsStringSync(json); | 157 new io.File(options.perfReport).writeAsStringSync(json); |
158 } | 158 } |
159 } | 159 } |
160 | 160 |
161 ErrorSeverity _analyzeAll(CommandLineOptions options) { | 161 Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async { |
162 return _analyzeAllTag.makeCurrentWhile(() { | 162 PerformanceTag previous = _analyzeAllTag.makeCurrent(); |
163 return _analyzeAllImpl(options); | 163 try { |
164 }); | 164 return await _analyzeAllImpl(options); |
| 165 } finally { |
| 166 previous.makeCurrent(); |
| 167 } |
165 } | 168 } |
166 | 169 |
167 /// Perform analysis according to the given [options]. | 170 /// Perform analysis according to the given [options]. |
168 ErrorSeverity _analyzeAllImpl(CommandLineOptions options) { | 171 Future<ErrorSeverity> _analyzeAllImpl(CommandLineOptions options) async { |
169 if (!options.machineFormat) { | 172 if (!options.machineFormat) { |
170 outSink.writeln("Analyzing ${options.sourceFiles}..."); | 173 outSink.writeln("Analyzing ${options.sourceFiles}..."); |
171 } | 174 } |
172 | 175 |
173 // Create a context, or re-use the previous one. | 176 // Create a context, or re-use the previous one. |
174 try { | 177 try { |
175 _createAnalysisContext(options); | 178 _createAnalysisContext(options); |
176 } on _DriverError catch (error) { | 179 } on _DriverError catch (error) { |
177 outSink.writeln(error.msg); | 180 outSink.writeln(error.msg); |
178 return ErrorSeverity.ERROR; | 181 return ErrorSeverity.ERROR; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 | 213 |
211 // Analyze the libraries. | 214 // Analyze the libraries. |
212 ErrorSeverity allResult = ErrorSeverity.NONE; | 215 ErrorSeverity allResult = ErrorSeverity.NONE; |
213 var libUris = <Uri>[]; | 216 var libUris = <Uri>[]; |
214 var parts = <Source>[]; | 217 var parts = <Source>[]; |
215 for (Source source in sourcesToAnalyze) { | 218 for (Source source in sourcesToAnalyze) { |
216 if (context.computeKindOf(source) == SourceKind.PART) { | 219 if (context.computeKindOf(source) == SourceKind.PART) { |
217 parts.add(source); | 220 parts.add(source); |
218 continue; | 221 continue; |
219 } | 222 } |
220 ErrorSeverity status = _runAnalyzer(source, options); | 223 ErrorSeverity status = await _runAnalyzer(source, options); |
221 allResult = allResult.max(status); | 224 allResult = allResult.max(status); |
222 libUris.add(source.uri); | 225 libUris.add(source.uri); |
223 } | 226 } |
224 | 227 |
225 // Check that each part has a corresponding source in the input list. | 228 // Check that each part has a corresponding source in the input list. |
226 for (Source part in parts) { | 229 for (Source part in parts) { |
227 bool found = false; | 230 bool found = false; |
228 for (var lib in context.getLibrariesContaining(part)) { | 231 for (var lib in context.getLibrariesContaining(part)) { |
229 if (libUris.contains(lib.uri)) { | 232 if (libUris.contains(lib.uri)) { |
230 found = true; | 233 found = true; |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 | 532 |
530 AnalyzeFunctionBodiesPredicate dietParsingPolicy = | 533 AnalyzeFunctionBodiesPredicate dietParsingPolicy = |
531 _chooseDietParsingPolicy(options); | 534 _chooseDietParsingPolicy(options); |
532 setAnalysisContextOptions( | 535 setAnalysisContextOptions( |
533 resourceProvider, sourceFactory, _context, options, | 536 resourceProvider, sourceFactory, _context, options, |
534 (AnalysisOptionsImpl contextOptions) { | 537 (AnalysisOptionsImpl contextOptions) { |
535 contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy; | 538 contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy; |
536 }); | 539 }); |
537 | 540 |
538 _context.sourceFactory = sourceFactory; | 541 _context.sourceFactory = sourceFactory; |
| 542 |
539 if (sdkBundle != null) { | 543 if (sdkBundle != null) { |
540 _context.resultProvider = | 544 _context.resultProvider = |
541 new InputPackagesResultProvider(_context, summaryDataStore); | 545 new InputPackagesResultProvider(_context, summaryDataStore); |
542 } | 546 } |
543 } | 547 } |
544 | 548 |
545 /// Return discovered packagespec, or `null` if none is found. | 549 /// Return discovered packagespec, or `null` if none is found. |
546 Packages _discoverPackagespec(Uri root) { | 550 Packages _discoverPackagespec(Uri root) { |
547 try { | 551 try { |
548 Packages packages = pkg_discovery.findPackagesFromFile(root); | 552 Packages packages = pkg_discovery.findPackagesFromFile(root); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 plugins.addAll(AnalysisEngine.instance.requiredPlugins); | 630 plugins.addAll(AnalysisEngine.instance.requiredPlugins); |
627 plugins.addAll(_userDefinedPlugins); | 631 plugins.addAll(_userDefinedPlugins); |
628 | 632 |
629 ExtensionManager manager = new ExtensionManager(); | 633 ExtensionManager manager = new ExtensionManager(); |
630 manager.processPlugins(plugins); | 634 manager.processPlugins(plugins); |
631 | 635 |
632 linter.registerLintRules(); | 636 linter.registerLintRules(); |
633 } | 637 } |
634 | 638 |
635 /// Analyze a single source. | 639 /// Analyze a single source. |
636 ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) { | 640 Future<ErrorSeverity> _runAnalyzer( |
| 641 Source source, CommandLineOptions options) async { |
637 int startTime = currentTimeMillis(); | 642 int startTime = currentTimeMillis(); |
638 AnalyzerImpl analyzer = | 643 AnalyzerImpl analyzer = new AnalyzerImpl( |
639 new AnalyzerImpl(_context, source, options, stats, startTime); | 644 _context.analysisOptions, _context, source, options, stats, startTime); |
640 var errorSeverity = analyzer.analyzeSync(); | 645 ErrorSeverity errorSeverity = await analyzer.analyze(); |
641 if (errorSeverity == ErrorSeverity.ERROR) { | 646 if (errorSeverity == ErrorSeverity.ERROR) { |
642 io.exitCode = errorSeverity.ordinal; | 647 io.exitCode = errorSeverity.ordinal; |
643 } | 648 } |
644 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { | 649 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { |
645 io.exitCode = errorSeverity.ordinal; | 650 io.exitCode = errorSeverity.ordinal; |
646 } | 651 } |
647 return errorSeverity; | 652 return errorSeverity; |
648 } | 653 } |
649 | 654 |
650 void _setupSdk(CommandLineOptions options, bool useSummaries) { | 655 void _setupSdk(CommandLineOptions options, bool useSummaries) { |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 static void runAsBatch(List<String> sharedArgs, _BatchRunnerHandler handler) { | 807 static void runAsBatch(List<String> sharedArgs, _BatchRunnerHandler handler) { |
803 outSink.writeln('>>> BATCH START'); | 808 outSink.writeln('>>> BATCH START'); |
804 Stopwatch stopwatch = new Stopwatch(); | 809 Stopwatch stopwatch = new Stopwatch(); |
805 stopwatch.start(); | 810 stopwatch.start(); |
806 int testsFailed = 0; | 811 int testsFailed = 0; |
807 int totalTests = 0; | 812 int totalTests = 0; |
808 ErrorSeverity batchResult = ErrorSeverity.NONE; | 813 ErrorSeverity batchResult = ErrorSeverity.NONE; |
809 // Read line from stdin. | 814 // Read line from stdin. |
810 Stream cmdLine = | 815 Stream cmdLine = |
811 io.stdin.transform(UTF8.decoder).transform(new LineSplitter()); | 816 io.stdin.transform(UTF8.decoder).transform(new LineSplitter()); |
812 cmdLine.listen((String line) { | 817 cmdLine.listen((String line) async { |
813 // Maybe finish. | 818 // Maybe finish. |
814 if (line.isEmpty) { | 819 if (line.isEmpty) { |
815 var time = stopwatch.elapsedMilliseconds; | 820 var time = stopwatch.elapsedMilliseconds; |
816 outSink.writeln( | 821 outSink.writeln( |
817 '>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms')
; | 822 '>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms')
; |
818 io.exitCode = batchResult.ordinal; | 823 io.exitCode = batchResult.ordinal; |
819 } | 824 } |
820 // Prepare arguments. | 825 // Prepare arguments. |
821 var lineArgs = line.split(new RegExp('\\s+')); | 826 var lineArgs = line.split(new RegExp('\\s+')); |
822 var args = new List<String>(); | 827 var args = new List<String>(); |
823 args.addAll(sharedArgs); | 828 args.addAll(sharedArgs); |
824 args.addAll(lineArgs); | 829 args.addAll(lineArgs); |
825 args.remove('-b'); | 830 args.remove('-b'); |
826 args.remove('--batch'); | 831 args.remove('--batch'); |
827 // Analyze single set of arguments. | 832 // Analyze single set of arguments. |
828 try { | 833 try { |
829 totalTests++; | 834 totalTests++; |
830 ErrorSeverity result = handler(args); | 835 ErrorSeverity result = await handler(args); |
831 bool resultPass = result != ErrorSeverity.ERROR; | 836 bool resultPass = result != ErrorSeverity.ERROR; |
832 if (!resultPass) { | 837 if (!resultPass) { |
833 testsFailed++; | 838 testsFailed++; |
834 } | 839 } |
835 batchResult = batchResult.max(result); | 840 batchResult = batchResult.max(result); |
836 // Write stderr end token and flush. | 841 // Write stderr end token and flush. |
837 errorSink.writeln('>>> EOF STDERR'); | 842 errorSink.writeln('>>> EOF STDERR'); |
838 String resultPassString = resultPass ? 'PASS' : 'FAIL'; | 843 String resultPassString = resultPass ? 'PASS' : 'FAIL'; |
839 outSink.writeln( | 844 outSink.writeln( |
840 '>>> TEST $resultPassString ${stopwatch.elapsedMilliseconds}ms'); | 845 '>>> TEST $resultPassString ${stopwatch.elapsedMilliseconds}ms'); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 for (var package in packages) { | 882 for (var package in packages) { |
878 var packageName = path.basename(package.path); | 883 var packageName = path.basename(package.path); |
879 var realPath = package.resolveSymbolicLinksSync(); | 884 var realPath = package.resolveSymbolicLinksSync(); |
880 result[packageName] = [ | 885 result[packageName] = [ |
881 PhysicalResourceProvider.INSTANCE.getFolder(realPath) | 886 PhysicalResourceProvider.INSTANCE.getFolder(realPath) |
882 ]; | 887 ]; |
883 } | 888 } |
884 return result; | 889 return result; |
885 } | 890 } |
886 } | 891 } |
OLD | NEW |