| Index: pkg/analyzer_cli/lib/src/driver.dart
|
| diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
|
| index d8aacada4fbe24c7b9aa927a07db9906ae6e2511..43cbee1daca1d5211f4301681b339663caf59293 100644
|
| --- a/pkg/analyzer_cli/lib/src/driver.dart
|
| +++ b/pkg/analyzer_cli/lib/src/driver.dart
|
| @@ -42,6 +42,7 @@ import 'package:analyzer_cli/starter.dart' show CommandLineStarter;
|
| import 'package:front_end/src/base/performace_logger.dart';
|
| import 'package:front_end/src/incremental/byte_store.dart';
|
| import 'package:linter/src/rules.dart' as linter;
|
| +import 'package:meta/meta.dart';
|
| import 'package:package_config/discovery.dart' as pkg_discovery;
|
| import 'package:package_config/packages.dart' show Packages;
|
| import 'package:package_config/packages_file.dart' as pkgfile show parse;
|
| @@ -49,16 +50,16 @@ import 'package:package_config/src/packages_impl.dart' show MapPackages;
|
| import 'package:path/path.dart' as path;
|
| import 'package:plugin/manager.dart';
|
| import 'package:plugin/plugin.dart';
|
| +import 'package:telemetry/crash_reporting.dart';
|
| +import 'package:telemetry/telemetry.dart' as telemetry;
|
| import 'package:yaml/yaml.dart';
|
|
|
| /// Shared IO sink for standard error reporting.
|
| -///
|
| -/// *Visible for testing.*
|
| +@visibleForTesting
|
| StringSink errorSink = io.stderr;
|
|
|
| /// Shared IO sink for standard out reporting.
|
| -///
|
| -/// *Visible for testing.*
|
| +@visibleForTesting
|
| StringSink outSink = io.stdout;
|
|
|
| /// Test this option map to see if it specifies lint rules.
|
| @@ -67,6 +68,26 @@ bool containsLintRuleEntry(Map<String, YamlNode> options) {
|
| return linterNode is YamlMap && linterNode.containsKey('rules');
|
| }
|
|
|
| +telemetry.Analytics _analytics;
|
| +
|
| +const _analyticsID = 'UA-26406144-28';
|
| +
|
| +/// The analytics instance for analyzer-cli.
|
| +telemetry.Analytics get analytics => (_analytics ??=
|
| + telemetry.createAnalyticsInstance(_analyticsID, 'analyzer-cli'));
|
| +
|
| +/// Make sure that we create an analytics instance that doesn't send for this
|
| +/// session.
|
| +void disableAnalyticsForSession() {
|
| + _analytics = telemetry.createAnalyticsInstance(_analyticsID, 'analyzer-cli',
|
| + disableForSession: true);
|
| +}
|
| +
|
| +@visibleForTesting
|
| +void setAnalytics(telemetry.Analytics replacementAnalytics) {
|
| + _analytics = replacementAnalytics;
|
| +}
|
| +
|
| class Driver implements CommandLineStarter {
|
| static final PerformanceTag _analyzeAllTag =
|
| new PerformanceTag("Driver._analyzeAll");
|
| @@ -109,9 +130,24 @@ class Driver implements CommandLineStarter {
|
| /// Collected analysis statistics.
|
| final AnalysisStats stats = new AnalysisStats();
|
|
|
| - /// This Driver's current analysis context.
|
| + CrashReportSender _crashReportSender;
|
| +
|
| + // TODO(devoncarew): Replace with the real crash product ID.
|
| + /// The crash reporting instance for analyzer-cli.
|
| + CrashReportSender get crashReportSender => (_crashReportSender ??=
|
| + new CrashReportSender('Dart_analyzer_cli', analytics));
|
| +
|
| + /// Create a new Driver instance.
|
| ///
|
| - /// *Visible for testing.*
|
| + /// [isTesting] is true if we're running in a test environment.
|
| + Driver({bool isTesting: false}) {
|
| + if (isTesting) {
|
| + disableAnalyticsForSession();
|
| + }
|
| + }
|
| +
|
| + /// This Driver's current analysis context.
|
| + @visibleForTesting
|
| AnalysisContext get context => _context;
|
|
|
| @override
|
| @@ -133,6 +169,15 @@ class Driver implements CommandLineStarter {
|
| // Parse commandline options.
|
| CommandLineOptions options = CommandLineOptions.parse(args);
|
|
|
| + if (options.batchMode || options.buildMode) {
|
| + disableAnalyticsForSession();
|
| + }
|
| +
|
| + // Ping analytics with our initial call.
|
| + analytics.sendScreenView('home');
|
| +
|
| + var timer = analytics.startTimer('analyze');
|
| +
|
| // Do analysis.
|
| if (options.buildMode) {
|
| ErrorSeverity severity = _buildModeAnalyze(options);
|
| @@ -140,7 +185,7 @@ class Driver implements CommandLineStarter {
|
| if (_shouldBeFatal(severity, options)) {
|
| io.exitCode = severity.ordinal;
|
| }
|
| - } else if (options.shouldBatch) {
|
| + } else if (options.batchMode) {
|
| BatchRunner batchRunner = new BatchRunner(outSink, errorSink);
|
| batchRunner.runAsBatch(args, (List<String> args) async {
|
| CommandLineOptions options = CommandLineOptions.parse(args);
|
| @@ -158,17 +203,30 @@ class Driver implements CommandLineStarter {
|
| _analyzedFileCount += _context.sources.length;
|
| }
|
|
|
| + // Send how long analysis took.
|
| + timer.finish();
|
| +
|
| + // Send how many files were analyzed.
|
| + analytics.sendEvent('analyze', 'fileCount', value: _analyzedFileCount);
|
| +
|
| if (options.perfReport != null) {
|
| String json = makePerfReport(
|
| startTime, currentTimeMillis, options, _analyzedFileCount, stats);
|
| new io.File(options.perfReport).writeAsStringSync(json);
|
| }
|
| +
|
| + // Wait a brief time for any analytics calls to finish.
|
| + await analytics.waitForLastPing(timeout: new Duration(milliseconds: 200));
|
| + analytics.close();
|
| }
|
|
|
| Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async {
|
| PerformanceTag previous = _analyzeAllTag.makeCurrent();
|
| try {
|
| return await _analyzeAllImpl(options);
|
| + } catch (e, st) {
|
| + crashReportSender.sendReport(e, stackTrace: st);
|
| + rethrow;
|
| } finally {
|
| previous.makeCurrent();
|
| }
|
| @@ -321,7 +379,7 @@ class Driver implements CommandLineStarter {
|
| /// [AnalyzeFunctionBodiesPredicate] that implements this policy.
|
| AnalyzeFunctionBodiesPredicate _chooseDietParsingPolicy(
|
| CommandLineOptions options) {
|
| - if (options.shouldBatch) {
|
| + if (options.batchMode) {
|
| // As analyzer is currently implemented, once a file has been diet
|
| // parsed, it can't easily be un-diet parsed without creating a brand new
|
| // context and losing caching. In batch mode, we can't predict which
|
|
|