Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(809)

Side by Side Diff: pkg/analyzer_cli/lib/src/driver.dart

Issue 1720963003: Initial hermetic package analyzer. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 16 matching lines...) Expand all
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/options.dart'; 36 import 'package:analyzer_cli/src/options.dart';
37 import 'package:analyzer_cli/src/package_analyzer.dart';
37 import 'package:analyzer_cli/src/perf_report.dart'; 38 import 'package:analyzer_cli/src/perf_report.dart';
38 import 'package:analyzer_cli/starter.dart'; 39 import 'package:analyzer_cli/starter.dart';
39 import 'package:linter/src/plugin/linter_plugin.dart'; 40 import 'package:linter/src/plugin/linter_plugin.dart';
40 import 'package:package_config/discovery.dart' as pkgDiscovery; 41 import 'package:package_config/discovery.dart' as pkgDiscovery;
41 import 'package:package_config/packages.dart' show Packages; 42 import 'package:package_config/packages.dart' show Packages;
42 import 'package:package_config/packages_file.dart' as pkgfile show parse; 43 import 'package:package_config/packages_file.dart' as pkgfile show parse;
43 import 'package:package_config/src/packages_impl.dart' show MapPackages; 44 import 'package:package_config/src/packages_impl.dart' show MapPackages;
44 import 'package:path/path.dart' as path; 45 import 'package:path/path.dart' as path;
45 import 'package:plugin/manager.dart'; 46 import 'package:plugin/manager.dart';
46 import 'package:plugin/plugin.dart'; 47 import 'package:plugin/plugin.dart';
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 107
107 _processPlugins(); 108 _processPlugins();
108 109
109 // Parse commandline options. 110 // Parse commandline options.
110 CommandLineOptions options = CommandLineOptions.parse(args); 111 CommandLineOptions options = CommandLineOptions.parse(args);
111 112
112 // Cache options of interest to inform analysis. 113 // Cache options of interest to inform analysis.
113 _setupEnv(options); 114 _setupEnv(options);
114 115
115 // Do analysis. 116 // Do analysis.
116 if (_isBatch) { 117 if (options.packageMode) {
118 ErrorSeverity severity = _analyzePackage(options);
119 // In case of error propagate exit code.
120 if (severity == ErrorSeverity.ERROR) {
121 exitCode = severity.ordinal;
122 }
123 } else if (_isBatch) {
117 _BatchRunner.runAsBatch(args, (List<String> args) { 124 _BatchRunner.runAsBatch(args, (List<String> args) {
118 CommandLineOptions options = CommandLineOptions.parse(args); 125 CommandLineOptions options = CommandLineOptions.parse(args);
119 return _analyzeAll(options); 126 return _analyzeAll(options);
120 }); 127 });
121 } else { 128 } else {
122 ErrorSeverity severity = _analyzeAll(options); 129 ErrorSeverity severity = _analyzeAll(options);
123 // In case of error propagate exit code. 130 // In case of error propagate exit code.
124 if (severity == ErrorSeverity.ERROR) { 131 if (severity == ErrorSeverity.ERROR) {
125 exitCode = severity.ordinal; 132 exitCode = severity.ordinal;
126 } 133 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 errorSink.writeln("${part.fullName} is a part and cannot be analyzed."); 215 errorSink.writeln("${part.fullName} is a part and cannot be analyzed.");
209 errorSink.writeln("Please pass in a library that contains this part."); 216 errorSink.writeln("Please pass in a library that contains this part.");
210 exitCode = ErrorSeverity.ERROR.ordinal; 217 exitCode = ErrorSeverity.ERROR.ordinal;
211 allResult = allResult.max(ErrorSeverity.ERROR); 218 allResult = allResult.max(ErrorSeverity.ERROR);
212 } 219 }
213 } 220 }
214 221
215 return allResult; 222 return allResult;
216 } 223 }
217 224
225 /// Perform package analysis according to the given [options].
226 ErrorSeverity _analyzePackage(CommandLineOptions options) {
227 return _analyzeAllTag.makeCurrentWhile(() {
228 return new PackageAnalyzer(options).analyze();
229 });
230 }
231
218 /// Determine whether the context created during a previous call to 232 /// Determine whether the context created during a previous call to
219 /// [_analyzeAll] can be re-used in order to analyze using [options]. 233 /// [_analyzeAll] can be re-used in order to analyze using [options].
220 bool _canContextBeReused(CommandLineOptions options) { 234 bool _canContextBeReused(CommandLineOptions options) {
221 // TODO(paulberry): add a command-line option that disables context re-use. 235 // TODO(paulberry): add a command-line option that disables context re-use.
222 if (_context == null) { 236 if (_context == null) {
223 return false; 237 return false;
224 } 238 }
225 if (options.packageRootPath != _previousOptions.packageRootPath) { 239 if (options.packageRootPath != _previousOptions.packageRootPath) {
226 return false; 240 return false;
227 } 241 }
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 /// Create an analysis context that is prepared to analyze sources according 468 /// Create an analysis context that is prepared to analyze sources according
455 /// to the given [options], and store it in [_context]. 469 /// to the given [options], and store it in [_context].
456 void _createAnalysisContext(CommandLineOptions options) { 470 void _createAnalysisContext(CommandLineOptions options) {
457 if (_canContextBeReused(options)) { 471 if (_canContextBeReused(options)) {
458 return; 472 return;
459 } 473 }
460 _previousOptions = options; 474 _previousOptions = options;
461 475
462 // Create a context. 476 // Create a context.
463 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); 477 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
478 _context = context;
464 479
465 // Choose a package resolution policy and a diet parsing policy based on 480 // Choose a package resolution policy and a diet parsing policy based on
466 // the command-line options. 481 // the command-line options.
467 SourceFactory sourceFactory = _chooseUriResolutionPolicy( 482 SourceFactory sourceFactory = _chooseUriResolutionPolicy(
468 options, (context as InternalAnalysisContext).embedderYamlLocator); 483 options, (context as InternalAnalysisContext).embedderYamlLocator);
469 AnalyzeFunctionBodiesPredicate dietParsingPolicy = 484 AnalyzeFunctionBodiesPredicate dietParsingPolicy =
470 _chooseDietParsingPolicy(options); 485 _chooseDietParsingPolicy(options);
471 486
472 context.sourceFactory = sourceFactory; 487 context.sourceFactory = sourceFactory;
473 488
474 Map<String, String> definedVariables = options.definedVariables; 489 setAnalysisContextOptions(_context, options,
475 if (!definedVariables.isEmpty) { 490 (AnalysisOptionsImpl contextOptions) {
476 DeclaredVariables declaredVariables = context.declaredVariables; 491 contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy;
477 definedVariables.forEach((String variableName, String value) { 492 });
478 declaredVariables.define(variableName, value);
479 });
480 }
481
482 if (options.log) {
483 AnalysisEngine.instance.logger = new StdLogger();
484 }
485
486 // Set context options.
487 AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
488 contextOptions.hint = !options.disableHints;
489 contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
490 contextOptions.enableSuperMixins = options.enableSuperMixins;
491 contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy;
492 contextOptions.generateImplicitErrors = options.showPackageWarnings;
493 contextOptions.generateSdkErrors = options.showSdkWarnings;
494 contextOptions.lint = options.lints;
495 contextOptions.strongMode = options.strongMode;
496 context.analysisOptions = contextOptions;
497 sourceFactory.dartSdk.context.analysisOptions = contextOptions;
498 _context = context;
499
500 // Process analysis options file (and notify all interested parties).
501 _processAnalysisOptions(options, context);
502 } 493 }
503 494
504 /// Return discovered packagespec, or `null` if none is found. 495 /// Return discovered packagespec, or `null` if none is found.
505 Packages _discoverPackagespec(Uri root) { 496 Packages _discoverPackagespec(Uri root) {
506 try { 497 try {
507 Packages packages = pkgDiscovery.findPackagesFromFile(root); 498 Packages packages = pkgDiscovery.findPackagesFromFile(root);
508 if (packages != Packages.noPackages) { 499 if (packages != Packages.noPackages) {
509 return packages; 500 return packages;
510 } 501 }
511 } catch (_) { 502 } catch (_) {
512 // Ignore and fall through to null. 503 // Ignore and fall through to null.
513 } 504 }
514 505
515 return null; 506 return null;
516 } 507 }
517 508
518 fileSystem.File _getOptionsFile(CommandLineOptions options) {
519 fileSystem.File file;
520 String filePath = options.analysisOptionsFile;
521 if (filePath != null) {
522 file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
523 if (!file.exists) {
524 printAndFail('Options file not found: $filePath',
525 exitCode: ErrorSeverity.ERROR.ordinal);
526 }
527 } else {
528 filePath = AnalysisEngine.ANALYSIS_OPTIONS_FILE;
529 file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
530 }
531 return file;
532 }
533
534 Map<String, List<fileSystem.Folder>> _getPackageMap(Packages packages) { 509 Map<String, List<fileSystem.Folder>> _getPackageMap(Packages packages) {
535 if (packages == null) { 510 if (packages == null) {
536 return null; 511 return null;
537 } 512 }
538 513
539 Map<String, List<fileSystem.Folder>> folderMap = 514 Map<String, List<fileSystem.Folder>> folderMap =
540 new Map<String, List<fileSystem.Folder>>(); 515 new Map<String, List<fileSystem.Folder>>();
541 packages.asMap().forEach((String packagePath, Uri uri) { 516 packages.asMap().forEach((String packagePath, Uri uri) {
542 folderMap[packagePath] = [ 517 folderMap[packagePath] = [
543 PhysicalResourceProvider.INSTANCE.getFolder(path.fromUri(uri)) 518 PhysicalResourceProvider.INSTANCE.getFolder(path.fromUri(uri))
544 ]; 519 ];
545 }); 520 });
546 return folderMap; 521 return folderMap;
547 } 522 }
548 523
549 void _processAnalysisOptions(
550 CommandLineOptions options, AnalysisContext context) {
551 fileSystem.File file = _getOptionsFile(options);
552 List<OptionsProcessor> optionsProcessors =
553 AnalysisEngine.instance.optionsPlugin.optionsProcessors;
554 try {
555 AnalysisOptionsProvider analysisOptionsProvider =
556 new AnalysisOptionsProvider();
557 Map<String, YamlNode> optionMap =
558 analysisOptionsProvider.getOptionsFromFile(file);
559 optionsProcessors.forEach(
560 (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
561
562 // Fill in lint rule defaults in case lints are enabled and rules are
563 // not specified in an options file.
564 if (options.lints && !containsLintRuleEntry(optionMap)) {
565 setLints(context, linterPlugin.contributedRules);
566 }
567
568 // Ask engine to further process options.
569 if (optionMap != null) {
570 configureContextOptions(context, optionMap);
571 }
572 } on Exception catch (e) {
573 optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
574 }
575 }
576
577 void _processPlugins() { 524 void _processPlugins() {
578 List<Plugin> plugins = <Plugin>[]; 525 List<Plugin> plugins = <Plugin>[];
579 plugins.addAll(AnalysisEngine.instance.requiredPlugins); 526 plugins.addAll(AnalysisEngine.instance.requiredPlugins);
580 plugins.add(AnalysisEngine.instance.commandLinePlugin); 527 plugins.add(AnalysisEngine.instance.commandLinePlugin);
581 plugins.add(AnalysisEngine.instance.optionsPlugin); 528 plugins.add(AnalysisEngine.instance.optionsPlugin);
582 plugins.add(linterPlugin); 529 plugins.add(linterPlugin);
583 plugins.addAll(_userDefinedPlugins); 530 plugins.addAll(_userDefinedPlugins);
584 531
585 ExtensionManager manager = new ExtensionManager(); 532 ExtensionManager manager = new ExtensionManager();
586 manager.processPlugins(plugins); 533 manager.processPlugins(plugins);
(...skipping 17 matching lines...) Expand all
604 void _setupEnv(CommandLineOptions options) { 551 void _setupEnv(CommandLineOptions options) {
605 // In batch mode, SDK is specified on the main command line rather than in 552 // In batch mode, SDK is specified on the main command line rather than in
606 // the command lines sent to stdin. So process it before deciding whether 553 // the command lines sent to stdin. So process it before deciding whether
607 // to activate batch mode. 554 // to activate batch mode.
608 if (sdk == null) { 555 if (sdk == null) {
609 sdk = new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath)); 556 sdk = new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath));
610 } 557 }
611 _isBatch = options.shouldBatch; 558 _isBatch = options.shouldBatch;
612 } 559 }
613 560
561 static void setAnalysisContextOptions(
562 AnalysisContext context,
563 CommandLineOptions options,
564 void configureContextOptions(AnalysisOptionsImpl contextOptions)) {
565 Map<String, String> definedVariables = options.definedVariables;
566 if (!definedVariables.isEmpty) {
567 DeclaredVariables declaredVariables = context.declaredVariables;
568 definedVariables.forEach((String variableName, String value) {
569 declaredVariables.define(variableName, value);
570 });
571 }
572
573 if (options.log) {
574 AnalysisEngine.instance.logger = new StdLogger();
575 }
576
577 // Prepare context options.
578 AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
579 contextOptions.hint = !options.disableHints;
580 contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
581 contextOptions.enableSuperMixins = options.enableSuperMixins;
582 contextOptions.generateImplicitErrors = options.showPackageWarnings;
583 contextOptions.generateSdkErrors = options.showSdkWarnings;
584 contextOptions.lint = options.lints;
585 contextOptions.strongMode = options.strongMode;
586 configureContextOptions(contextOptions);
587
588 // Set context options.
589 context.analysisOptions = contextOptions;
590 context.sourceFactory.dartSdk.context.analysisOptions = contextOptions;
591
592 // Process analysis options file (and notify all interested parties).
593 _processAnalysisOptions(context, options);
594 }
595
614 /// Perform a deep comparison of two string maps. 596 /// Perform a deep comparison of two string maps.
615 static bool _equalMaps(Map<String, String> m1, Map<String, String> m2) { 597 static bool _equalMaps(Map<String, String> m1, Map<String, String> m2) {
616 if (m1.length != m2.length) { 598 if (m1.length != m2.length) {
617 return false; 599 return false;
618 } 600 }
619 for (String key in m1.keys) { 601 for (String key in m1.keys) {
620 if (!m2.containsKey(key) || m1[key] != m2[key]) { 602 if (!m2.containsKey(key) || m1[key] != m2[key]) {
621 return false; 603 return false;
622 } 604 }
623 } 605 }
624 return true; 606 return true;
625 } 607 }
626 608
609 static fileSystem.File _getOptionsFile(CommandLineOptions options) {
610 fileSystem.File file;
611 String filePath = options.analysisOptionsFile;
612 if (filePath != null) {
613 file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
614 if (!file.exists) {
615 printAndFail('Options file not found: $filePath',
616 exitCode: ErrorSeverity.ERROR.ordinal);
617 }
618 } else {
619 filePath = AnalysisEngine.ANALYSIS_OPTIONS_FILE;
620 file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
621 }
622 return file;
623 }
624
627 /// Convert [sourcePath] into an absolute path. 625 /// Convert [sourcePath] into an absolute path.
628 static String _normalizeSourcePath(String sourcePath) => 626 static String _normalizeSourcePath(String sourcePath) =>
629 path.normalize(new File(sourcePath).absolute.path); 627 path.normalize(new File(sourcePath).absolute.path);
628
629 static void _processAnalysisOptions(
630 AnalysisContext context, CommandLineOptions options) {
631 fileSystem.File file = _getOptionsFile(options);
632 List<OptionsProcessor> optionsProcessors =
633 AnalysisEngine.instance.optionsPlugin.optionsProcessors;
634 try {
635 AnalysisOptionsProvider analysisOptionsProvider =
636 new AnalysisOptionsProvider();
637 Map<String, YamlNode> optionMap =
638 analysisOptionsProvider.getOptionsFromFile(file);
639 optionsProcessors.forEach(
640 (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
641
642 // Fill in lint rule defaults in case lints are enabled and rules are
643 // not specified in an options file.
644 if (options.lints && !containsLintRuleEntry(optionMap)) {
645 setLints(context, linterPlugin.contributedRules);
646 }
647
648 // Ask engine to further process options.
649 if (optionMap != null) {
650 configureContextOptions(context, optionMap);
651 }
652 } on Exception catch (e) {
653 optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
654 }
655 }
630 } 656 }
631 657
632 /// Provides a framework to read command line options from stdin and feed them 658 /// Provides a framework to read command line options from stdin and feed them
633 /// to a callback. 659 /// to a callback.
634 class _BatchRunner { 660 class _BatchRunner {
635 /// Run the tool in 'batch' mode, receiving command lines through stdin and 661 /// Run the tool in 'batch' mode, receiving command lines through stdin and
636 /// returning pass/fail status through stdout. This feature is intended for 662 /// returning pass/fail status through stdout. This feature is intended for
637 /// use in unit testing. 663 /// use in unit testing.
638 static void runAsBatch(List<String> sharedArgs, _BatchRunnerHandler handler) { 664 static void runAsBatch(List<String> sharedArgs, _BatchRunnerHandler handler) {
639 outSink.writeln('>>> BATCH START'); 665 outSink.writeln('>>> BATCH START');
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 for (var package in packages) { 736 for (var package in packages) {
711 var packageName = path.basename(package.path); 737 var packageName = path.basename(package.path);
712 var realPath = package.resolveSymbolicLinksSync(); 738 var realPath = package.resolveSymbolicLinksSync();
713 result[packageName] = [ 739 result[packageName] = [
714 PhysicalResourceProvider.INSTANCE.getFolder(realPath) 740 PhysicalResourceProvider.INSTANCE.getFolder(realPath)
715 ]; 741 ];
716 } 742 }
717 return result; 743 return result;
718 } 744 }
719 } 745 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698