c3da025eaa
This reverts commit e498ca00dc.
Reason for revert: 2.10 has been branched.
Original change's description:
> [VM] Temporarily disable DDS for 2.10 branch
>
> Change-Id: I32916b8e816e109d4e659e9b05326cd0fffb85d7
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/161764
> Commit-Queue: Ben Konyi <bkonyi@google.com>
> Reviewed-by: Devon Carew <devoncarew@google.com>
TBR=devoncarew@google.com,bkonyi@google.com,asiva@google.com
# Not skipping CQ checks because original CL landed > 1 day ago.
Change-Id: If895b635fc2f66c08d8b1aa28af92c250de3e95a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/162942
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
326 lines
11 KiB
Dart
326 lines
11 KiB
Dart
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:io' as io;
|
|
import 'dart:isolate';
|
|
|
|
import 'package:analyzer/src/dart/analysis/experiments.dart';
|
|
import 'package:args/args.dart';
|
|
import 'package:args/command_runner.dart';
|
|
import 'package:cli_util/cli_logging.dart';
|
|
import 'package:dart_style/src/cli/format_command.dart';
|
|
import 'package:nnbd_migration/migration_cli.dart';
|
|
import 'package:usage/usage.dart';
|
|
|
|
import 'src/analytics.dart';
|
|
import 'src/commands/analyze.dart';
|
|
import 'src/commands/compile.dart';
|
|
import 'src/commands/create.dart';
|
|
import 'src/commands/fix.dart';
|
|
import 'src/commands/pub.dart';
|
|
import 'src/commands/run.dart';
|
|
import 'src/commands/test.dart';
|
|
import 'src/core.dart';
|
|
import 'src/events.dart';
|
|
import 'src/experiments.dart';
|
|
import 'src/sdk.dart';
|
|
import 'src/utils.dart';
|
|
import 'src/vm_interop_handler.dart';
|
|
|
|
/// This is typically called from bin/, but given the length of the method and
|
|
/// analytics logic, it has been moved here. Also note that this method calls
|
|
/// [io.exit(code)] directly.
|
|
Future<void> runDartdev(List<String> args, SendPort port) async {
|
|
VmInteropHandler.initialize(port);
|
|
final stopwatch = Stopwatch();
|
|
int result;
|
|
|
|
// The exit code for the dartdev process, null indicates that it has not yet
|
|
// been set yet. The value is set in the catch and finally blocks below.
|
|
int exitCode;
|
|
|
|
// Any caught non-UsageExceptions when running the sub command
|
|
Object exception;
|
|
StackTrace stackTrace;
|
|
|
|
// The Analytics instance used to report information back to Google Analytics,
|
|
// see lib/src/analytics.dart.
|
|
Analytics analytics =
|
|
createAnalyticsInstance(args.contains('--disable-dartdev-analytics'));
|
|
|
|
// If we have not printed the analyticsNoticeOnFirstRunMessage to stdout,
|
|
// the user is on a terminal, and the machine is not a bot, then print the
|
|
// disclosure and set analytics.disclosureShownOnTerminal to true.
|
|
if (analytics is DartdevAnalytics &&
|
|
!analytics.disclosureShownOnTerminal &&
|
|
io.stdout.hasTerminal &&
|
|
!isBot()) {
|
|
print(analyticsNoticeOnFirstRunMessage);
|
|
analytics.disclosureShownOnTerminal = true;
|
|
}
|
|
|
|
// When `--disable-analytics` or `--enable-analytics` are called we perform
|
|
// the respective intention and print any notices to standard out and exit.
|
|
if (args.contains('--disable-analytics')) {
|
|
// This block also potentially catches the case of (disableAnalytics &&
|
|
// enableAnalytics), in which we favor the disabling of analytics.
|
|
analytics.enabled = false;
|
|
|
|
// Alert the user that analytics have been disabled:
|
|
print(analyticsDisabledNoticeMessage);
|
|
io.exit(0);
|
|
} else if (args.contains('--enable-analytics')) {
|
|
analytics.enabled = true;
|
|
|
|
// Alert the user again that anonymous data will be collected:
|
|
print(analyticsNoticeOnFirstRunMessage);
|
|
io.exit(0);
|
|
}
|
|
|
|
// --launch-dds is provided by the VM if the VM service is to be enabled. In
|
|
// that case, we need to launch DDS as well.
|
|
final launchDdsArg = args.singleWhere(
|
|
(element) => element.startsWith('--launch-dds'),
|
|
orElse: () => null,
|
|
);
|
|
if (launchDdsArg != null) {
|
|
RunCommand.launchDds = true;
|
|
final ddsUrl = (launchDdsArg.split('=')[1]).split(':');
|
|
RunCommand.ddsHost = ddsUrl[0];
|
|
RunCommand.ddsPort = ddsUrl[1];
|
|
}
|
|
|
|
String commandName;
|
|
|
|
try {
|
|
stopwatch.start();
|
|
final runner = DartdevRunner(args);
|
|
|
|
// Run can't be called with the '--disable-dartdev-analytics' flag, remove
|
|
// it if it is contained in args.
|
|
if (args.contains('--disable-dartdev-analytics')) {
|
|
args = List.from(args)..remove('--disable-dartdev-analytics');
|
|
}
|
|
|
|
// Run also can't be called with '--launch-dds', remove it if it's
|
|
// contained in args.
|
|
if (launchDdsArg != null) {
|
|
args = List.from(args)..remove(launchDdsArg);
|
|
}
|
|
|
|
// These flags have a format that can't be handled by package:args, so
|
|
// while they are valid flags we'll assume the VM has verified them by this
|
|
// point.
|
|
args = args
|
|
.where(
|
|
(element) => !(element.contains('--observe') ||
|
|
element.contains('--enable-vm-service')),
|
|
)
|
|
.toList();
|
|
|
|
// If ... help pub ... is in the args list, remove 'help', and add '--help'
|
|
// to the end of the list. This will make it possible to use the help
|
|
// command to access subcommands of pub such as `dart help pub publish`, see
|
|
// https://github.com/dart-lang/sdk/issues/42965
|
|
if (PubUtils.shouldModifyArgs(args, runner.commands.keys.toList())) {
|
|
args = PubUtils.modifyArgs(args);
|
|
}
|
|
|
|
// For the commands format and migrate, dartdev itself sends the
|
|
// sendScreenView notification to analytics, for all other
|
|
// dartdev commands (instances of DartdevCommand) the commands send this
|
|
// to analytics.
|
|
commandName = ArgParserUtils.getCommandStr(args);
|
|
if (analytics.enabled &&
|
|
(commandName == formatCmdName || commandName == migrateCmdName)) {
|
|
// ignore: unawaited_futures
|
|
analytics.sendScreenView(commandName);
|
|
}
|
|
|
|
// Finally, call the runner to execute the command, see DartdevRunner.
|
|
result = await runner.run(args);
|
|
} catch (e, st) {
|
|
if (e is UsageException) {
|
|
io.stderr.writeln('$e');
|
|
exitCode = 64;
|
|
} else {
|
|
// Set the exception and stack trace only for non-UsageException cases:
|
|
exception = e;
|
|
stackTrace = st;
|
|
io.stderr.writeln('$e');
|
|
io.stderr.writeln('$st');
|
|
exitCode = 1;
|
|
}
|
|
} finally {
|
|
stopwatch.stop();
|
|
|
|
// Set the exitCode, if it wasn't set in the catch block above.
|
|
exitCode ??= result ?? 0;
|
|
|
|
// Send analytics before exiting
|
|
if (analytics.enabled) {
|
|
// For commands that are not DartdevCommand instances, we manually create
|
|
// and send the UsageEvent from here:
|
|
if (commandName == formatCmdName) {
|
|
// ignore: unawaited_futures
|
|
FormatUsageEvent(
|
|
exitCode: exitCode,
|
|
args: args,
|
|
).send(analyticsInstance);
|
|
} else if (commandName == migrateCmdName) {
|
|
// ignore: unawaited_futures
|
|
MigrateUsageEvent(
|
|
exitCode: exitCode,
|
|
args: args,
|
|
).send(analyticsInstance);
|
|
}
|
|
|
|
// ignore: unawaited_futures
|
|
analytics.sendTiming(commandName, stopwatch.elapsedMilliseconds,
|
|
category: 'commands');
|
|
|
|
// And now send the exceptions and events to Google Analytics:
|
|
if (exception != null) {
|
|
// ignore: unawaited_futures
|
|
analytics.sendException(
|
|
'${exception.runtimeType}\n${sanitizeStacktrace(stackTrace)}',
|
|
fatal: true);
|
|
}
|
|
|
|
await analytics.waitForLastPing(
|
|
timeout: const Duration(milliseconds: 200));
|
|
}
|
|
|
|
// Set the enabled flag in the analytics object to true. Note: this will not
|
|
// enable the analytics unless the disclosure was shown (terminal
|
|
// detected), and the machine is not detected to be a bot.
|
|
if (analytics.firstRun) {
|
|
analytics.enabled = true;
|
|
}
|
|
analytics.close();
|
|
VmInteropHandler.exit(exitCode);
|
|
}
|
|
}
|
|
|
|
class DartdevRunner<int> extends CommandRunner {
|
|
@override
|
|
final ArgParser argParser =
|
|
ArgParser(usageLineLength: dartdevUsageLineLength);
|
|
|
|
static const String dartdevDescription =
|
|
'A command-line utility for Dart development';
|
|
|
|
DartdevRunner(List<String> args) : super('dart', '$dartdevDescription.') {
|
|
final bool verbose = args.contains('-v') || args.contains('--verbose');
|
|
|
|
argParser.addFlag('verbose',
|
|
abbr: 'v', negatable: false, help: 'Show additional command output.');
|
|
argParser.addFlag('version',
|
|
negatable: false, help: 'Print the Dart SDK version.');
|
|
argParser.addFlag('enable-analytics',
|
|
negatable: false, help: 'Enable anonymous analytics.');
|
|
argParser.addFlag('disable-analytics',
|
|
negatable: false, help: 'Disable anonymous analytics.');
|
|
|
|
addExperimentalFlags(argParser, verbose);
|
|
|
|
argParser.addFlag('diagnostics',
|
|
negatable: false, help: 'Show tool diagnostic output.', hide: !verbose);
|
|
|
|
// A hidden flag to disable analytics on this run, this constructor can be
|
|
// called with this flag, but should be removed before run() is called as
|
|
// the flag has not been added to all sub-commands.
|
|
argParser.addFlag(
|
|
'disable-dartdev-analytics',
|
|
negatable: false,
|
|
help: 'Disable anonymous analytics for this `dart *` run',
|
|
hide: true,
|
|
);
|
|
|
|
// Another hidden flag used by the VM to indicate that DDS should be
|
|
// launched. Should be removed for all commands other than `run`.
|
|
argParser.addFlag('launch-dds',
|
|
negatable: false, hide: true, help: 'Launch DDS.');
|
|
|
|
addCommand(AnalyzeCommand());
|
|
addCommand(CreateCommand(verbose: verbose));
|
|
addCommand(CompileCommand());
|
|
addCommand(FixCommand());
|
|
addCommand(FormatCommand(verbose: verbose));
|
|
addCommand(MigrateCommand(
|
|
verbose: verbose,
|
|
hidden: Runtime.runtime.stableChannel,
|
|
));
|
|
addCommand(PubCommand());
|
|
addCommand(RunCommand(verbose: verbose));
|
|
addCommand(TestCommand());
|
|
}
|
|
|
|
@override
|
|
String get usageFooter =>
|
|
'See https://dart.dev/tools/dart-tool for detailed documentation.';
|
|
|
|
@override
|
|
String get invocation =>
|
|
'dart [<vm-flags>] <command|dart-file> [<arguments>]';
|
|
|
|
void addExperimentalFlags(ArgParser argParser, bool verbose) {
|
|
List<ExperimentalFeature> features = experimentalFeatures;
|
|
|
|
Map<String, String> allowedHelp = {};
|
|
for (ExperimentalFeature feature in features) {
|
|
String suffix =
|
|
feature.isEnabledByDefault ? ' (no-op - enabled by default)' : '';
|
|
allowedHelp[feature.enableString] = '${feature.documentation}$suffix';
|
|
}
|
|
|
|
argParser.addMultiOption(
|
|
experimentFlagName,
|
|
valueHelp: 'experiment',
|
|
allowedHelp: verbose ? allowedHelp : null,
|
|
help: 'Enable one or more experimental features '
|
|
'(see dart.dev/go/experiments).',
|
|
hide: !verbose,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<int> runCommand(ArgResults topLevelResults) async {
|
|
assert(!topLevelResults.arguments.contains('--disable-dartdev-analytics'));
|
|
|
|
if (topLevelResults.command == null &&
|
|
topLevelResults.arguments.isNotEmpty) {
|
|
final firstArg = topLevelResults.arguments.first;
|
|
// If we make it this far, it means the VM couldn't find the file on disk.
|
|
if (firstArg.endsWith('.dart')) {
|
|
io.stderr.writeln(
|
|
"Error when reading '$firstArg': No such file or directory.");
|
|
// This is the exit code used by the frontend.
|
|
VmInteropHandler.exit(254);
|
|
}
|
|
}
|
|
|
|
isDiagnostics = topLevelResults['diagnostics'];
|
|
|
|
final Ansi ansi = Ansi(Ansi.terminalSupportsAnsi);
|
|
log = isDiagnostics
|
|
? Logger.verbose(ansi: ansi)
|
|
: Logger.standard(ansi: ansi);
|
|
|
|
if (topLevelResults.wasParsed(experimentFlagName)) {
|
|
List<String> experimentIds = topLevelResults[experimentFlagName];
|
|
for (ExperimentalFeature feature in experimentalFeatures) {
|
|
// We allow default true flags, but complain when they are passed in.
|
|
if (feature.isEnabledByDefault &&
|
|
experimentIds.contains(feature.enableString)) {
|
|
print("'${feature.enableString}' is now enabled by default; this "
|
|
'flag is no longer required.');
|
|
}
|
|
}
|
|
}
|
|
|
|
return await super.runCommand(topLevelResults);
|
|
}
|
|
}
|