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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:io' as io; | 6 import 'dart:io' as io; |
7 | 7 |
8 import 'package:analyzer/error/error.dart'; | 8 import 'package:analyzer/error/error.dart'; |
9 import 'package:analyzer/file_system/file_system.dart' as file_system; | 9 import 'package:analyzer/file_system/file_system.dart' as file_system; |
10 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
64 /// Test this option map to see if it specifies lint rules. | 64 /// Test this option map to see if it specifies lint rules. |
65 bool containsLintRuleEntry(Map<String, YamlNode> options) { | 65 bool containsLintRuleEntry(Map<String, YamlNode> options) { |
66 var linterNode = options['linter']; | 66 var linterNode = options['linter']; |
67 return linterNode is YamlMap && linterNode.containsKey('rules'); | 67 return linterNode is YamlMap && linterNode.containsKey('rules'); |
68 } | 68 } |
69 | 69 |
70 class Driver implements CommandLineStarter { | 70 class Driver implements CommandLineStarter { |
71 static final PerformanceTag _analyzeAllTag = | 71 static final PerformanceTag _analyzeAllTag = |
72 new PerformanceTag("Driver._analyzeAll"); | 72 new PerformanceTag("Driver._analyzeAll"); |
73 | 73 |
74 /// Cache of [AnalysisOptionsImpl] objects that correspond to directories | |
75 /// with analyzed files, used to reduce searching for `analysis_options.yaml` | |
76 /// files. | |
77 static Map<String, AnalysisOptionsImpl> _directoryToAnalysisOptions = {}; | |
78 | |
74 static ByteStore analysisDriverMemoryByteStore = new MemoryByteStore(); | 79 static ByteStore analysisDriverMemoryByteStore = new MemoryByteStore(); |
75 | 80 |
76 /// The plugins that are defined outside the `analyzer_cli` package. | 81 /// The plugins that are defined outside the `analyzer_cli` package. |
77 List<Plugin> _userDefinedPlugins = <Plugin>[]; | 82 List<Plugin> _userDefinedPlugins = <Plugin>[]; |
78 | 83 |
79 /// The context that was most recently created by a call to [_analyzeAll], or | 84 /// The context that was most recently created by a call to [_analyzeAll], or |
80 /// `null` if [_analyzeAll] hasn't been called yet. | 85 /// `null` if [_analyzeAll] hasn't been called yet. |
81 InternalAnalysisContext _context; | 86 InternalAnalysisContext _context; |
82 | 87 |
83 AnalysisDriver analysisDriver; | 88 AnalysisDriver analysisDriver; |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 if (options.buildModePersistentWorker) { | 309 if (options.buildModePersistentWorker) { |
305 new AnalyzerWorkerLoop.std(resourceProvider, | 310 new AnalyzerWorkerLoop.std(resourceProvider, |
306 dartSdkPath: options.dartSdkPath) | 311 dartSdkPath: options.dartSdkPath) |
307 .run(); | 312 .run(); |
308 } else { | 313 } else { |
309 return new BuildMode(resourceProvider, options, stats).analyze(); | 314 return new BuildMode(resourceProvider, options, stats).analyze(); |
310 } | 315 } |
311 }); | 316 }); |
312 } | 317 } |
313 | 318 |
314 /// Determine whether the context created during a previous call to | |
315 /// [_analyzeAll] can be re-used in order to analyze using [options]. | |
316 bool _canContextBeReused( | |
317 CommandLineOptions options, AnalysisOptionsImpl other) { | |
318 // TODO(paulberry): add a command-line option that disables context re-use. | |
319 if (_context == null) { | |
320 return false; | |
321 } | |
322 | |
323 // Check command line options. | |
324 if (options.packageRootPath != _previousOptions.packageRootPath) { | |
325 return false; | |
326 } | |
327 if (options.packageConfigPath != _previousOptions.packageConfigPath) { | |
328 return false; | |
329 } | |
330 if (!_equalMaps( | |
331 options.definedVariables, _previousOptions.definedVariables)) { | |
332 return false; | |
333 } | |
334 if (options.log != _previousOptions.log) { | |
335 return false; | |
336 } | |
337 if (options.disableHints != _previousOptions.disableHints) { | |
338 return false; | |
339 } | |
340 if (options.enableStrictCallChecks != | |
341 _previousOptions.enableStrictCallChecks) { | |
342 return false; | |
343 } | |
344 if (options.enableAssertInitializer != | |
345 _previousOptions.enableAssertInitializer) { | |
346 return false; | |
347 } | |
348 if (options.showPackageWarnings != _previousOptions.showPackageWarnings) { | |
349 return false; | |
350 } | |
351 if (options.showPackageWarningsPrefix != | |
352 _previousOptions.showPackageWarningsPrefix) { | |
353 return false; | |
354 } | |
355 if (options.showSdkWarnings != _previousOptions.showSdkWarnings) { | |
356 return false; | |
357 } | |
358 if (options.lints != _previousOptions.lints) { | |
359 return false; | |
360 } | |
361 if (options.strongMode != _previousOptions.strongMode) { | |
362 return false; | |
363 } | |
364 if (options.enableSuperMixins != _previousOptions.enableSuperMixins) { | |
365 return false; | |
366 } | |
367 if (!_equalLists( | |
368 options.buildSummaryInputs, _previousOptions.buildSummaryInputs)) { | |
369 return false; | |
370 } | |
371 if (options.disableCacheFlushing != _previousOptions.disableCacheFlushing) { | |
372 return false; | |
373 } | |
374 | |
375 // Check analysis options. | |
376 var c = _context.analysisOptions; | |
377 if (!(other.enableAssertInitializer == c.enableAssertInitializer && | |
378 other.enableStrictCallChecks == c.enableStrictCallChecks && | |
379 other.enableLazyAssignmentOperators == | |
380 c.enableLazyAssignmentOperators && | |
381 other.enableSuperMixins == c.enableSuperMixins && | |
382 other.enableTiming == c.enableTiming && | |
383 other.generateImplicitErrors == c.generateImplicitErrors && | |
384 other.generateSdkErrors == c.generateSdkErrors && | |
385 other.hint == c.hint && | |
386 other.lint == c.lint && | |
387 AnalysisOptionsImpl.compareLints(other.lintRules, c.lintRules) && | |
388 other.preserveComments == c.preserveComments && | |
389 other.strongMode == c.strongMode)) { | |
390 return false; | |
391 } | |
392 | |
393 return true; | |
394 } | |
395 | |
396 /// Decide on the appropriate policy for which files need to be fully parsed | 319 /// Decide on the appropriate policy for which files need to be fully parsed |
397 /// and which files need to be diet parsed, based on [options], and return an | 320 /// and which files need to be diet parsed, based on [options], and return an |
398 /// [AnalyzeFunctionBodiesPredicate] that implements this policy. | 321 /// [AnalyzeFunctionBodiesPredicate] that implements this policy. |
399 AnalyzeFunctionBodiesPredicate _chooseDietParsingPolicy( | 322 AnalyzeFunctionBodiesPredicate _chooseDietParsingPolicy( |
400 CommandLineOptions options) { | 323 CommandLineOptions options) { |
401 if (options.shouldBatch) { | 324 if (options.shouldBatch) { |
402 // As analyzer is currently implemented, once a file has been diet | 325 // As analyzer is currently implemented, once a file has been diet |
403 // parsed, it can't easily be un-diet parsed without creating a brand new | 326 // parsed, it can't easily be un-diet parsed without creating a brand new |
404 // context and losing caching. In batch mode, we can't predict which | 327 // context and losing caching. In batch mode, we can't predict which |
405 // files we'll need to generate errors and warnings for in the future, so | 328 // files we'll need to generate errors and warnings for in the future, so |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 if (packageUriResolver != null) { | 437 if (packageUriResolver != null) { |
515 resolvers.add(packageUriResolver); | 438 resolvers.add(packageUriResolver); |
516 } | 439 } |
517 | 440 |
518 // Finally files. | 441 // Finally files. |
519 resolvers.add(new file_system.ResourceUriResolver(resourceProvider)); | 442 resolvers.add(new file_system.ResourceUriResolver(resourceProvider)); |
520 | 443 |
521 return new SourceFactory(resolvers, packageInfo.packages); | 444 return new SourceFactory(resolvers, packageInfo.packages); |
522 } | 445 } |
523 | 446 |
524 // TODO(devoncarew): This needs to respect analysis_options excludes. | |
525 | |
526 /// Collect all analyzable files at [filePath], recursively if it's a | 447 /// Collect all analyzable files at [filePath], recursively if it's a |
527 /// directory, ignoring links. | 448 /// directory, ignoring links. |
528 Iterable<io.File> _collectFiles(String filePath) { | 449 Iterable<io.File> _collectFiles(String filePath) { |
529 List<io.File> files = <io.File>[]; | 450 List<io.File> files = <io.File>[]; |
530 io.File file = new io.File(filePath); | 451 io.File file = new io.File(filePath); |
531 if (file.existsSync()) { | 452 if (file.existsSync()) { |
532 files.add(file); | 453 files.add(file); |
533 } else { | 454 } else { |
534 io.Directory directory = new io.Directory(filePath); | 455 io.Directory directory = new io.Directory(filePath); |
535 if (directory.existsSync()) { | 456 if (directory.existsSync()) { |
536 for (io.FileSystemEntity entry | 457 for (io.FileSystemEntity entry |
537 in directory.listSync(recursive: true, followLinks: false)) { | 458 in directory.listSync(recursive: true, followLinks: false)) { |
538 String relative = path.relative(entry.path, from: directory.path); | 459 String relative = path.relative(entry.path, from: directory.path); |
539 if (AnalysisEngine.isDartFileName(entry.path) && | 460 if (AnalysisEngine.isDartFileName(entry.path) && |
540 !_isInHiddenDir(relative)) { | 461 !_isInHiddenDir(relative)) { |
541 files.add(entry); | 462 files.add(entry); |
542 } | 463 } |
543 } | 464 } |
544 } | 465 } |
545 } | 466 } |
546 return files; | 467 return files; |
547 } | 468 } |
548 | 469 |
470 // TODO(devoncarew): This needs to respect analysis_options excludes. | |
Brian Wilkerson
2017/06/27 19:11:02
The comment moved. I'm not sure what it was suppos
| |
471 | |
549 /// Convert the given [sourcePath] (which may be relative to the current | 472 /// Convert the given [sourcePath] (which may be relative to the current |
550 /// working directory) to a [Source] object that can be fed to the analysis | 473 /// working directory) to a [Source] object that can be fed to the analysis |
551 /// context. | 474 /// context. |
552 Source _computeLibrarySource(String sourcePath) { | 475 Source _computeLibrarySource(String sourcePath) { |
553 sourcePath = _normalizeSourcePath(sourcePath); | 476 sourcePath = _normalizeSourcePath(sourcePath); |
554 File sourceFile = resourceProvider.getFile(sourcePath); | 477 File sourceFile = resourceProvider.getFile(sourcePath); |
555 Source source = sdk.fromFileUri(sourceFile.toUri()); | 478 Source source = sdk.fromFileUri(sourceFile.toUri()); |
556 if (source != null) { | 479 if (source != null) { |
557 return source; | 480 return source; |
558 } | 481 } |
559 source = new FileSource(sourceFile, sourceFile.toUri()); | 482 source = new FileSource(sourceFile, sourceFile.toUri()); |
560 Uri uri = _context.sourceFactory.restoreUri(source); | 483 Uri uri = _context.sourceFactory.restoreUri(source); |
561 if (uri == null) { | 484 if (uri == null) { |
562 return source; | 485 return source; |
563 } | 486 } |
564 return new FileSource(sourceFile, uri); | 487 return new FileSource(sourceFile, uri); |
565 } | 488 } |
566 | 489 |
567 /// Create an analysis context that is prepared to analyze sources according | 490 /// Create an analysis context that is prepared to analyze sources according |
568 /// to the given [options], and store it in [_context]. | 491 /// to the given [options], and store it in [_context]. |
569 void _createAnalysisContext(CommandLineOptions options) { | 492 void _createAnalysisContext(CommandLineOptions options) { |
493 // If not the same command-line options, clear cached information. | |
494 if (!_equalCommandLineOptions(_previousOptions, options)) { | |
495 _previousOptions = options; | |
496 _directoryToAnalysisOptions.clear(); | |
497 _context = null; | |
498 analysisDriver = null; | |
499 } | |
500 | |
570 AnalysisOptionsImpl analysisOptions = | 501 AnalysisOptionsImpl analysisOptions = |
571 createAnalysisOptionsForCommandLineOptions(resourceProvider, options); | 502 createAnalysisOptionsForCommandLineOptions(resourceProvider, options); |
572 analysisOptions.analyzeFunctionBodiesPredicate = | 503 analysisOptions.analyzeFunctionBodiesPredicate = |
573 _chooseDietParsingPolicy(options); | 504 _chooseDietParsingPolicy(options); |
574 | 505 |
575 if (_canContextBeReused(options, analysisOptions)) { | 506 // If we have the analysis driver, and the new analysis options are the |
507 // same, we can reuse this analysis driver. | |
508 if (_context != null && | |
509 _equalAnalysisOptions(_context.analysisOptions, analysisOptions)) { | |
576 return; | 510 return; |
577 } | 511 } |
578 | 512 |
579 _previousOptions = options; | |
580 | |
581 // Save stats from previous context before clobbering it. | 513 // Save stats from previous context before clobbering it. |
582 if (_context != null) { | 514 if (_context != null) { |
583 _analyzedFileCount += _context.sources.length; | 515 _analyzedFileCount += _context.sources.length; |
584 } | 516 } |
585 | 517 |
586 // Find package info. | 518 // Find package info. |
587 _PackageInfo packageInfo = _findPackages(options); | 519 _PackageInfo packageInfo = _findPackages(options); |
588 | 520 |
589 // Process embedders. | 521 // Process embedders. |
590 Map<file_system.Folder, YamlMap> embedderMap = | 522 Map<file_system.Folder, YamlMap> embedderMap = |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
653 if (packages != Packages.noPackages) { | 585 if (packages != Packages.noPackages) { |
654 return packages; | 586 return packages; |
655 } | 587 } |
656 } catch (_) { | 588 } catch (_) { |
657 // Ignore and fall through to null. | 589 // Ignore and fall through to null. |
658 } | 590 } |
659 | 591 |
660 return null; | 592 return null; |
661 } | 593 } |
662 | 594 |
595 /// Return whether [a] and [b] options are equal for the purpose of | |
596 /// command line analysis. | |
597 bool _equalAnalysisOptions(AnalysisOptionsImpl a, AnalysisOptions b) { | |
598 return a.enableAssertInitializer == b.enableAssertInitializer && | |
599 a.enableStrictCallChecks == b.enableStrictCallChecks && | |
600 a.enableLazyAssignmentOperators == b.enableLazyAssignmentOperators && | |
601 a.enableSuperMixins == b.enableSuperMixins && | |
602 a.enableTiming == b.enableTiming && | |
603 a.generateImplicitErrors == b.generateImplicitErrors && | |
604 a.generateSdkErrors == b.generateSdkErrors && | |
605 a.hint == b.hint && | |
606 a.lint == b.lint && | |
607 AnalysisOptionsImpl.compareLints(a.lintRules, b.lintRules) && | |
608 a.preserveComments == b.preserveComments && | |
609 a.strongMode == b.strongMode; | |
610 } | |
611 | |
663 _PackageInfo _findPackages(CommandLineOptions options) { | 612 _PackageInfo _findPackages(CommandLineOptions options) { |
664 if (packageResolverProvider != null) { | 613 if (packageResolverProvider != null) { |
665 // The resolver provider will do all the work later. | 614 // The resolver provider will do all the work later. |
666 return new _PackageInfo(null, null); | 615 return new _PackageInfo(null, null); |
667 } | 616 } |
668 | 617 |
669 Packages packages; | 618 Packages packages; |
670 Map<String, List<file_system.Folder>> packageMap; | 619 Map<String, List<file_system.Folder>> packageMap; |
671 | 620 |
672 if (options.packageConfigPath != null) { | 621 if (options.packageConfigPath != null) { |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
798 contextRoot = options.sourceFiles[0]; | 747 contextRoot = options.sourceFiles[0]; |
799 if (!path.isAbsolute(contextRoot)) { | 748 if (!path.isAbsolute(contextRoot)) { |
800 contextRoot = path.absolute(contextRoot); | 749 contextRoot = path.absolute(contextRoot); |
801 } | 750 } |
802 } | 751 } |
803 | 752 |
804 void verbosePrint(String text) { | 753 void verbosePrint(String text) { |
805 outSink.writeln(text); | 754 outSink.writeln(text); |
806 } | 755 } |
807 | 756 |
808 AnalysisOptionsImpl contextOptions = new ContextBuilder( | 757 // Prepare the directory which is, or contains, the context root. |
809 resourceProvider, null, null, | 758 String contextRootDirectory; |
759 if (resourceProvider.getFolder(contextRoot).exists) { | |
760 contextRootDirectory = contextRoot; | |
761 } else { | |
762 contextRootDirectory = resourceProvider.pathContext.dirname(contextRoot); | |
763 } | |
764 | |
765 // Check if there is the options object for the content directory. | |
766 AnalysisOptionsImpl contextOptions = | |
767 _directoryToAnalysisOptions[contextRootDirectory]; | |
768 if (contextOptions != null) { | |
769 return contextOptions; | |
770 } | |
771 | |
772 contextOptions = new ContextBuilder(resourceProvider, null, null, | |
810 options: options.contextBuilderOptions) | 773 options: options.contextBuilderOptions) |
811 .getAnalysisOptions(contextRoot, | 774 .getAnalysisOptions(contextRoot, |
812 verbosePrint: options.verbose ? verbosePrint : null); | 775 verbosePrint: options.verbose ? verbosePrint : null); |
813 | 776 |
814 contextOptions.trackCacheDependencies = false; | 777 contextOptions.trackCacheDependencies = false; |
815 contextOptions.disableCacheFlushing = options.disableCacheFlushing; | 778 contextOptions.disableCacheFlushing = options.disableCacheFlushing; |
816 contextOptions.hint = !options.disableHints; | 779 contextOptions.hint = !options.disableHints; |
817 contextOptions.generateImplicitErrors = options.showPackageWarnings; | 780 contextOptions.generateImplicitErrors = options.showPackageWarnings; |
818 contextOptions.generateSdkErrors = options.showSdkWarnings; | 781 contextOptions.generateSdkErrors = options.showSdkWarnings; |
819 if (options.enableAssertInitializer != null) { | 782 if (options.enableAssertInitializer != null) { |
820 contextOptions.enableAssertInitializer = options.enableAssertInitializer; | 783 contextOptions.enableAssertInitializer = options.enableAssertInitializer; |
821 } | 784 } |
822 | 785 |
786 _directoryToAnalysisOptions[contextRootDirectory] = contextOptions; | |
823 return contextOptions; | 787 return contextOptions; |
824 } | 788 } |
825 | 789 |
826 static void setAnalysisContextOptions( | 790 static void setAnalysisContextOptions( |
827 file_system.ResourceProvider resourceProvider, | 791 file_system.ResourceProvider resourceProvider, |
828 AnalysisContext context, | 792 AnalysisContext context, |
829 CommandLineOptions options, | 793 CommandLineOptions options, |
830 void configureContextOptions(AnalysisOptionsImpl contextOptions)) { | 794 void configureContextOptions(AnalysisOptionsImpl contextOptions)) { |
831 AnalysisOptionsImpl analysisOptions = | 795 AnalysisOptionsImpl analysisOptions = |
832 createAnalysisOptionsForCommandLineOptions(resourceProvider, options); | 796 createAnalysisOptionsForCommandLineOptions(resourceProvider, options); |
(...skipping 12 matching lines...) Expand all Loading... | |
845 } | 809 } |
846 | 810 |
847 if (options.log) { | 811 if (options.log) { |
848 AnalysisEngine.instance.logger = new StdLogger(); | 812 AnalysisEngine.instance.logger = new StdLogger(); |
849 } | 813 } |
850 | 814 |
851 // Set context options. | 815 // Set context options. |
852 context.analysisOptions = analysisOptions; | 816 context.analysisOptions = analysisOptions; |
853 } | 817 } |
854 | 818 |
819 /// Return whether the [newOptions] are equal to the [previous]. | |
820 static bool _equalCommandLineOptions( | |
821 CommandLineOptions previous, CommandLineOptions newOptions) { | |
822 if (previous == null || newOptions == null) { | |
823 return false; | |
824 } | |
825 if (newOptions.packageRootPath != previous.packageRootPath) { | |
826 return false; | |
827 } | |
828 if (newOptions.packageConfigPath != previous.packageConfigPath) { | |
829 return false; | |
830 } | |
831 if (!_equalMaps(newOptions.definedVariables, previous.definedVariables)) { | |
832 return false; | |
833 } | |
834 if (newOptions.log != previous.log) { | |
835 return false; | |
836 } | |
837 if (newOptions.disableHints != previous.disableHints) { | |
838 return false; | |
839 } | |
840 if (newOptions.enableStrictCallChecks != previous.enableStrictCallChecks) { | |
841 return false; | |
842 } | |
843 if (newOptions.enableAssertInitializer != | |
844 previous.enableAssertInitializer) { | |
845 return false; | |
846 } | |
847 if (newOptions.showPackageWarnings != previous.showPackageWarnings) { | |
848 return false; | |
849 } | |
850 if (newOptions.showPackageWarningsPrefix != | |
851 previous.showPackageWarningsPrefix) { | |
852 return false; | |
853 } | |
854 if (newOptions.showSdkWarnings != previous.showSdkWarnings) { | |
855 return false; | |
856 } | |
857 if (newOptions.lints != previous.lints) { | |
858 return false; | |
859 } | |
860 if (newOptions.strongMode != previous.strongMode) { | |
861 return false; | |
862 } | |
863 if (newOptions.enableSuperMixins != previous.enableSuperMixins) { | |
864 return false; | |
865 } | |
866 if (!_equalLists( | |
867 newOptions.buildSummaryInputs, previous.buildSummaryInputs)) { | |
868 return false; | |
869 } | |
870 if (newOptions.disableCacheFlushing != previous.disableCacheFlushing) { | |
871 return false; | |
872 } | |
873 return true; | |
874 } | |
875 | |
855 /// Perform a deep comparison of two string lists. | 876 /// Perform a deep comparison of two string lists. |
856 static bool _equalLists(List<String> l1, List<String> l2) { | 877 static bool _equalLists(List<String> l1, List<String> l2) { |
857 if (l1.length != l2.length) { | 878 if (l1.length != l2.length) { |
858 return false; | 879 return false; |
859 } | 880 } |
860 for (int i = 0; i < l1.length; i++) { | 881 for (int i = 0; i < l1.length; i++) { |
861 if (l1[i] != l2[i]) { | 882 if (l1[i] != l2[i]) { |
862 return false; | 883 return false; |
863 } | 884 } |
864 } | 885 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
912 for (var package in packages) { | 933 for (var package in packages) { |
913 var packageName = path.basename(package.path); | 934 var packageName = path.basename(package.path); |
914 var realPath = package.resolveSymbolicLinksSync(); | 935 var realPath = package.resolveSymbolicLinksSync(); |
915 result[packageName] = [ | 936 result[packageName] = [ |
916 PhysicalResourceProvider.INSTANCE.getFolder(realPath) | 937 PhysicalResourceProvider.INSTANCE.getFolder(realPath) |
917 ]; | 938 ]; |
918 } | 939 } |
919 return result; | 940 return result; |
920 } | 941 } |
921 } | 942 } |
OLD | NEW |