| 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 |