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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 /// The plugins that are defined outside the `analyzer_cli` package. | 73 /// The plugins that are defined outside the `analyzer_cli` package. |
74 List<Plugin> _userDefinedPlugins = <Plugin>[]; | 74 List<Plugin> _userDefinedPlugins = <Plugin>[]; |
75 | 75 |
76 /// Indicates whether the analyzer is running in batch mode. | 76 /// Indicates whether the analyzer is running in batch mode. |
77 bool _isBatch; | 77 bool _isBatch; |
78 | 78 |
79 /// The context that was most recently created by a call to [_analyzeAll], or | 79 /// The context that was most recently created by a call to [_analyzeAll], or |
80 /// `null` if [_analyzeAll] hasn't been called yet. | 80 /// `null` if [_analyzeAll] hasn't been called yet. |
81 AnalysisContext _context; | 81 AnalysisContext _context; |
82 | 82 |
| 83 /// The total number of source files loaded by an AnalysisContext. |
| 84 int _analyzedFileCount = 0; |
| 85 |
83 /// If [_context] is not `null`, the [CommandLineOptions] that guided its | 86 /// If [_context] is not `null`, the [CommandLineOptions] that guided its |
84 /// creation. | 87 /// creation. |
85 CommandLineOptions _previousOptions; | 88 CommandLineOptions _previousOptions; |
86 | 89 |
87 @override | 90 @override |
88 EmbeddedResolverProvider embeddedUriResolverProvider; | 91 EmbeddedResolverProvider embeddedUriResolverProvider; |
89 | 92 |
90 @override | 93 @override |
91 ResolverProvider packageResolverProvider; | 94 ResolverProvider packageResolverProvider; |
92 | 95 |
93 /// Collected analysis statistics. | 96 /// Collected analysis statistics. |
94 final AnalysisStats stats = new AnalysisStats(); | 97 final AnalysisStats stats = new AnalysisStats(); |
95 | 98 |
96 /// This Driver's current analysis context. | 99 /// This Driver's current analysis context. |
97 /// | 100 /// |
98 /// *Visible for testing.* | 101 /// *Visible for testing.* |
99 AnalysisContext get context => _context; | 102 AnalysisContext get context => _context; |
100 | 103 |
101 @override | 104 @override |
102 void set userDefinedPlugins(List<Plugin> plugins) { | 105 void set userDefinedPlugins(List<Plugin> plugins) { |
103 _userDefinedPlugins = plugins ?? <Plugin>[]; | 106 _userDefinedPlugins = plugins ?? <Plugin>[]; |
104 } | 107 } |
105 | 108 |
106 @override | 109 @override |
107 void start(List<String> args) { | 110 void start(List<String> args) { |
| 111 if (_context != null) { |
| 112 throw new StateError("start() can only be called once"); |
| 113 } |
108 int startTime = new DateTime.now().millisecondsSinceEpoch; | 114 int startTime = new DateTime.now().millisecondsSinceEpoch; |
109 | 115 |
110 StringUtilities.INTERNER = new MappedInterner(); | 116 StringUtilities.INTERNER = new MappedInterner(); |
111 | 117 |
112 _processPlugins(); | 118 _processPlugins(); |
113 | 119 |
114 // Parse commandline options. | 120 // Parse commandline options. |
115 CommandLineOptions options = CommandLineOptions.parse(args); | 121 CommandLineOptions options = CommandLineOptions.parse(args); |
116 | 122 |
117 // Cache options of interest to inform analysis. | 123 // Cache options of interest to inform analysis. |
(...skipping 12 matching lines...) Expand all Loading... |
130 return _analyzeAll(options); | 136 return _analyzeAll(options); |
131 }); | 137 }); |
132 } else { | 138 } else { |
133 ErrorSeverity severity = _analyzeAll(options); | 139 ErrorSeverity severity = _analyzeAll(options); |
134 // In case of error propagate exit code. | 140 // In case of error propagate exit code. |
135 if (severity == ErrorSeverity.ERROR) { | 141 if (severity == ErrorSeverity.ERROR) { |
136 exitCode = severity.ordinal; | 142 exitCode = severity.ordinal; |
137 } | 143 } |
138 } | 144 } |
139 | 145 |
| 146 if (_context != null) { |
| 147 _analyzedFileCount += _context.sources.length; |
| 148 } |
| 149 |
140 if (options.perfReport != null) { | 150 if (options.perfReport != null) { |
141 String json = makePerfReport(startTime, currentTimeMillis(), options); | 151 String json = makePerfReport( |
| 152 startTime, currentTimeMillis(), options, _analyzedFileCount, stats); |
142 new File(options.perfReport).writeAsStringSync(json); | 153 new File(options.perfReport).writeAsStringSync(json); |
143 } | 154 } |
144 } | 155 } |
145 | 156 |
146 ErrorSeverity _analyzeAll(CommandLineOptions options) { | 157 ErrorSeverity _analyzeAll(CommandLineOptions options) { |
147 return _analyzeAllTag.makeCurrentWhile(() { | 158 return _analyzeAllTag.makeCurrentWhile(() { |
148 return _analyzeAllImpl(options); | 159 return _analyzeAllImpl(options); |
149 }); | 160 }); |
150 } | 161 } |
151 | 162 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 if (options.disableHints != _previousOptions.disableHints) { | 271 if (options.disableHints != _previousOptions.disableHints) { |
261 return false; | 272 return false; |
262 } | 273 } |
263 if (options.enableStrictCallChecks != | 274 if (options.enableStrictCallChecks != |
264 _previousOptions.enableStrictCallChecks) { | 275 _previousOptions.enableStrictCallChecks) { |
265 return false; | 276 return false; |
266 } | 277 } |
267 if (options.showPackageWarnings != _previousOptions.showPackageWarnings) { | 278 if (options.showPackageWarnings != _previousOptions.showPackageWarnings) { |
268 return false; | 279 return false; |
269 } | 280 } |
| 281 if (options.showPackageWarningsPrefix != |
| 282 _previousOptions.showPackageWarningsPrefix) { |
| 283 return false; |
| 284 } |
270 if (options.showSdkWarnings != _previousOptions.showSdkWarnings) { | 285 if (options.showSdkWarnings != _previousOptions.showSdkWarnings) { |
271 return false; | 286 return false; |
272 } | 287 } |
273 if (options.lints != _previousOptions.lints) { | 288 if (options.lints != _previousOptions.lints) { |
274 return false; | 289 return false; |
275 } | 290 } |
276 if (options.strongMode != _previousOptions.strongMode) { | 291 if (options.strongMode != _previousOptions.strongMode) { |
277 return false; | 292 return false; |
278 } | 293 } |
279 if (options.enableSuperMixins != _previousOptions.enableSuperMixins) { | 294 if (options.enableSuperMixins != _previousOptions.enableSuperMixins) { |
(...skipping 13 matching lines...) Expand all Loading... |
293 CommandLineOptions options) { | 308 CommandLineOptions options) { |
294 if (_isBatch) { | 309 if (_isBatch) { |
295 // As analyzer is currently implemented, once a file has been diet | 310 // As analyzer is currently implemented, once a file has been diet |
296 // parsed, it can't easily be un-diet parsed without creating a brand new | 311 // parsed, it can't easily be un-diet parsed without creating a brand new |
297 // context and losing caching. In batch mode, we can't predict which | 312 // context and losing caching. In batch mode, we can't predict which |
298 // files we'll need to generate errors and warnings for in the future, so | 313 // files we'll need to generate errors and warnings for in the future, so |
299 // we can't safely diet parse anything. | 314 // we can't safely diet parse anything. |
300 return (Source source) => true; | 315 return (Source source) => true; |
301 } | 316 } |
302 | 317 |
303 // Determine the set of packages requiring a full parse. Use null to | |
304 // represent the case where all packages require a full parse. | |
305 Set<String> packagesRequiringFullParse; | |
306 if (options.showPackageWarnings) { | |
307 // We are showing warnings from all packages so all packages require a | |
308 // full parse. | |
309 packagesRequiringFullParse = null; | |
310 } else { | |
311 // We aren't showing warnings for dependent packages, but we may still | |
312 // need to show warnings for "self" packages, so we need to do a full | |
313 // parse in any package containing files mentioned on the command line. | |
314 // TODO(paulberry): implement this. As a temporary workaround, we're | |
315 // fully parsing all packages. | |
316 packagesRequiringFullParse = null; | |
317 } | |
318 return (Source source) { | 318 return (Source source) { |
319 if (options.sourceFiles.contains(source.fullName)) { | 319 if (options.sourceFiles.contains(source.fullName)) { |
320 return true; | 320 return true; |
321 } else if (source.uri.scheme == 'dart') { | 321 } else if (source.uri.scheme == 'dart') { |
322 return options.showSdkWarnings; | 322 return options.showSdkWarnings; |
323 } else if (source.uri.scheme == 'package') { | |
324 if (packagesRequiringFullParse == null) { | |
325 return true; | |
326 } else if (source.uri.pathSegments.length == 0) { | |
327 // We should never see a URI like this, but fully parse it to be | |
328 // safe. | |
329 return true; | |
330 } else { | |
331 return packagesRequiringFullParse | |
332 .contains(source.uri.pathSegments[0]); | |
333 } | |
334 } else { | 323 } else { |
| 324 // TODO(paulberry): diet parse 'package:' imports when we don't want |
| 325 // diagnostics. (Full parse is still needed for "self" packages.) |
335 return true; | 326 return true; |
336 } | 327 } |
337 }; | 328 }; |
338 } | 329 } |
339 | 330 |
340 /// Decide on the appropriate method for resolving URIs based on the given | 331 /// Decide on the appropriate method for resolving URIs based on the given |
341 /// [options] and [customUrlMappings] settings, and return a | 332 /// [options] and [customUrlMappings] settings, and return a |
342 /// [SourceFactory] that has been configured accordingly. | 333 /// [SourceFactory] that has been configured accordingly. |
343 SourceFactory _chooseUriResolutionPolicy( | 334 SourceFactory _chooseUriResolutionPolicy( |
344 CommandLineOptions options, EmbedderYamlLocator yamlLocator) { | 335 CommandLineOptions options, EmbedderYamlLocator yamlLocator) { |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 } | 492 } |
502 | 493 |
503 /// Create an analysis context that is prepared to analyze sources according | 494 /// Create an analysis context that is prepared to analyze sources according |
504 /// to the given [options], and store it in [_context]. | 495 /// to the given [options], and store it in [_context]. |
505 void _createAnalysisContext(CommandLineOptions options) { | 496 void _createAnalysisContext(CommandLineOptions options) { |
506 if (_canContextBeReused(options)) { | 497 if (_canContextBeReused(options)) { |
507 return; | 498 return; |
508 } | 499 } |
509 _previousOptions = options; | 500 _previousOptions = options; |
510 | 501 |
| 502 // Save stats from previous context before clobbering it. |
| 503 if (_context != null) { |
| 504 _analyzedFileCount += _context.sources.length; |
| 505 } |
| 506 |
511 // Create a context. | 507 // Create a context. |
512 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); | 508 _context = AnalysisEngine.instance.createAnalysisContext(); |
513 _context = context; | |
514 | 509 |
515 // Choose a package resolution policy and a diet parsing policy based on | 510 // Choose a package resolution policy and a diet parsing policy based on |
516 // the command-line options. | 511 // the command-line options. |
517 SourceFactory sourceFactory = _chooseUriResolutionPolicy( | 512 SourceFactory sourceFactory = _chooseUriResolutionPolicy( |
518 options, (context as InternalAnalysisContext).embedderYamlLocator); | 513 options, (_context as InternalAnalysisContext).embedderYamlLocator); |
519 AnalyzeFunctionBodiesPredicate dietParsingPolicy = | 514 AnalyzeFunctionBodiesPredicate dietParsingPolicy = |
520 _chooseDietParsingPolicy(options); | 515 _chooseDietParsingPolicy(options); |
521 | 516 |
522 context.sourceFactory = sourceFactory; | 517 _context.sourceFactory = sourceFactory; |
523 | 518 |
524 setAnalysisContextOptions(_context, options, | 519 setAnalysisContextOptions(_context, options, |
525 (AnalysisOptionsImpl contextOptions) { | 520 (AnalysisOptionsImpl contextOptions) { |
526 contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy; | 521 contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy; |
527 }); | 522 }); |
528 } | 523 } |
529 | 524 |
530 /// Return discovered packagespec, or `null` if none is found. | 525 /// Return discovered packagespec, or `null` if none is found. |
531 Packages _discoverPackagespec(Uri root) { | 526 Packages _discoverPackagespec(Uri root) { |
532 try { | 527 try { |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
777 for (var package in packages) { | 772 for (var package in packages) { |
778 var packageName = path.basename(package.path); | 773 var packageName = path.basename(package.path); |
779 var realPath = package.resolveSymbolicLinksSync(); | 774 var realPath = package.resolveSymbolicLinksSync(); |
780 result[packageName] = [ | 775 result[packageName] = [ |
781 PhysicalResourceProvider.INSTANCE.getFolder(realPath) | 776 PhysicalResourceProvider.INSTANCE.getFolder(realPath) |
782 ]; | 777 ]; |
783 } | 778 } |
784 return result; | 779 return result; |
785 } | 780 } |
786 } | 781 } |
OLD | NEW |