Skip to content

Commit 58860f4

Browse files
sigurdmcommit-bot@chromium.org
authored andcommitted
Improve handling of disable-dartdev-analytics
This is second try of https://dart-review.googlesource.com/c/sdk/+/171284 that was reverted to to faulty logic in main_options. Some other refactorings are piggy-backed along. TestProject.runSync no longer takes a 'command' argument. It was anyway often not an argument. Also stop the messy handling of pub arguments. It is no longer needed. BUG: #44135 Change-Id: I49abf5810d9ea262409ba9d93f0471037cb8a753 TEST=The VM change is tested via all the pkg/dartdev/test/command/* tests that invoke dart with the --no-analytics flag. TEST=Furthermore manual test that the --no-analytics flag is passed to dartdev. Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/174261 Reviewed-by: Jonas Jensen <[email protected]> Commit-Queue: Sigurd Meldgaard <[email protected]>
1 parent deca91c commit 58860f4

24 files changed

+296
-383
lines changed

pkg/dartdev/lib/dartdev.dart

Lines changed: 99 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -32,129 +32,34 @@ import 'src/vm_interop_handler.dart';
3232
/// analytics logic, it has been moved here.
3333
Future<void> runDartdev(List<String> args, SendPort port) async {
3434
VmInteropHandler.initialize(port);
35-
36-
int result;
37-
38-
// The exit code for the dartdev process; null indicates that it has not been
39-
// set yet. The value is set in the catch and finally blocks below.
40-
int exitCode;
41-
42-
// Any caught non-UsageExceptions when running the sub command.
43-
Object exception;
44-
StackTrace stackTrace;
45-
46-
// The Analytics instance used to report information back to Google Analytics;
47-
// see lib/src/analytics.dart.
48-
final analytics = createAnalyticsInstance(
49-
args.contains('--disable-dartdev-analytics'),
50-
);
51-
52-
// If we have not printed the analyticsNoticeOnFirstRunMessage to stdout,
53-
// the user is on a terminal, and the machine is not a bot, then print the
54-
// disclosure and set analytics.disclosureShownOnTerminal to true.
55-
if (analytics is DartdevAnalytics &&
56-
!analytics.disclosureShownOnTerminal &&
57-
io.stdout.hasTerminal &&
58-
!isBot()) {
59-
print(analyticsNoticeOnFirstRunMessage);
60-
analytics.disclosureShownOnTerminal = true;
35+
if (args.contains('run')) {
36+
// These flags have a format that can't be handled by package:args, so while
37+
// they are valid flags we'll assume the VM has verified them by this point.
38+
args = args
39+
.where(
40+
(element) => !(element.contains('--observe') ||
41+
element.contains('--enable-vm-service')),
42+
)
43+
.toList();
6144
}
6245

63-
// When `--disable-analytics` or `--enable-analytics` are called we perform
64-
// the respective intention and print any notices to standard out and exit.
65-
if (args.contains('--disable-analytics')) {
66-
// This block also potentially catches the case of (disableAnalytics &&
67-
// enableAnalytics), in which we favor the disabling of analytics.
68-
analytics.enabled = false;
69-
70-
// Alert the user that analytics has been disabled.
71-
print(analyticsDisabledNoticeMessage);
72-
VmInteropHandler.exit(0);
73-
return;
74-
} else if (args.contains('--enable-analytics')) {
75-
analytics.enabled = true;
76-
77-
// Alert the user again that anonymous data will be collected.
78-
print(analyticsNoticeOnFirstRunMessage);
79-
VmInteropHandler.exit(0);
80-
return;
81-
}
46+
// Finally, call the runner to execute the command; see DartdevRunner.
8247

48+
final runner = DartdevRunner(args);
49+
var exitCode = 1;
8350
try {
84-
final runner = DartdevRunner(args, analytics);
85-
86-
// Run can't be called with the '--disable-dartdev-analytics' flag; remove
87-
// it if it is contained in args.
88-
if (args.contains('--disable-dartdev-analytics')) {
89-
args = List.from(args)..remove('--disable-dartdev-analytics');
90-
}
91-
92-
if (args.contains('run')) {
93-
// These flags have a format that can't be handled by package:args, so while
94-
// they are valid flags we'll assume the VM has verified them by this point.
95-
args = args
96-
.where(
97-
(element) => !(element.contains('--observe') ||
98-
element.contains('--enable-vm-service')),
99-
)
100-
.toList();
101-
}
102-
103-
// If ... help pub ... is in the args list, remove 'help', and add '--help'
104-
// to the end of the list. This will make it possible to use the help
105-
// command to access subcommands of pub such as `dart help pub publish`; see
106-
// https://github.com/dart-lang/sdk/issues/42965.
107-
if (PubUtils.shouldModifyArgs(args, runner.commands.keys.toList())) {
108-
args = PubUtils.modifyArgs(args);
109-
}
110-
111-
// Finally, call the runner to execute the command; see DartdevRunner.
112-
result = await runner.run(args);
113-
} catch (e, st) {
114-
if (e is UsageException) {
115-
io.stderr.writeln('$e');
116-
exitCode = 64;
117-
} else {
118-
// Set the exception and stack trace only for non-UsageException cases:
119-
exception = e;
120-
stackTrace = st;
121-
io.stderr.writeln('$e');
122-
io.stderr.writeln('$st');
123-
exitCode = 1;
124-
}
51+
exitCode = await runner.run(args);
52+
} on UsageException catch (e) {
53+
// TODO(sigurdm): It is unclear when a UsageException gets to here, and
54+
// when it is in DartdevRunner.runCommand.
55+
io.stderr.writeln('$e');
56+
exitCode = 64;
12557
} finally {
126-
// Set the exitCode, if it wasn't set in the catch block above.
127-
exitCode ??= result ?? 0;
128-
129-
// Send analytics before exiting
130-
if (analytics.enabled) {
131-
// And now send the exceptions and events to Google Analytics:
132-
if (exception != null) {
133-
unawaited(
134-
analytics.sendException(
135-
'${exception.runtimeType}\n${sanitizeStacktrace(stackTrace)}',
136-
fatal: true),
137-
);
138-
}
139-
140-
await analytics.waitForLastPing(
141-
timeout: const Duration(milliseconds: 200));
142-
}
143-
144-
// Set the enabled flag in the analytics object to true. Note: this will not
145-
// enable the analytics unless the disclosure was shown (terminal detected),
146-
// and the machine is not detected to be a bot.
147-
if (analytics.firstRun) {
148-
analytics.enabled = true;
149-
}
150-
analytics.close();
15158
VmInteropHandler.exit(exitCode);
15259
}
15360
}
15461

15562
class DartdevRunner extends CommandRunner<int> {
156-
final Analytics analytics;
157-
15863
@override
15964
final ArgParser argParser = ArgParser(
16065
usageLineLength: dartdevUsageLineLength,
@@ -164,8 +69,7 @@ class DartdevRunner extends CommandRunner<int> {
16469
static const String dartdevDescription =
16570
'A command-line utility for Dart development';
16671

167-
DartdevRunner(List<String> args, this.analytics)
168-
: super('dart', '$dartdevDescription.') {
72+
DartdevRunner(List<String> args) : super('dart', '$dartdevDescription.') {
16973
final bool verbose = args.contains('-v') || args.contains('--verbose');
17074

17175
argParser.addFlag('verbose',
@@ -180,12 +84,9 @@ class DartdevRunner extends CommandRunner<int> {
18084
argParser.addFlag('diagnostics',
18185
negatable: false, help: 'Show tool diagnostic output.', hide: !verbose);
18286

183-
// A hidden flag to disable analytics on this run, this constructor can be
184-
// called with this flag, but should be removed before run() is called as
185-
// the flag has not been added to all sub-commands.
18687
argParser.addFlag(
187-
'disable-dartdev-analytics',
188-
negatable: false,
88+
'analytics',
89+
negatable: true,
18990
help: 'Disable anonymous analytics for this `dart *` run',
19091
hide: true,
19192
);
@@ -212,7 +113,38 @@ class DartdevRunner extends CommandRunner<int> {
212113
@override
213114
Future<int> runCommand(ArgResults topLevelResults) async {
214115
final stopwatch = Stopwatch()..start();
215-
assert(!topLevelResults.arguments.contains('--disable-dartdev-analytics'));
116+
// The Analytics instance used to report information back to Google Analytics;
117+
// see lib/src/analytics.dart.
118+
final analytics = createAnalyticsInstance(!topLevelResults['analytics']);
119+
120+
// If we have not printed the analyticsNoticeOnFirstRunMessage to stdout,
121+
// the user is on a terminal, and the machine is not a bot, then print the
122+
// disclosure and set analytics.disclosureShownOnTerminal to true.
123+
if (analytics is DartdevAnalytics &&
124+
!analytics.disclosureShownOnTerminal &&
125+
io.stdout.hasTerminal &&
126+
!isBot()) {
127+
print(analyticsNoticeOnFirstRunMessage);
128+
analytics.disclosureShownOnTerminal = true;
129+
}
130+
131+
// When `--disable-analytics` or `--enable-analytics` are called we perform
132+
// the respective intention and print any notices to standard out and exit.
133+
if (topLevelResults['disable-analytics']) {
134+
// This block also potentially catches the case of (disableAnalytics &&
135+
// enableAnalytics), in which we favor the disabling of analytics.
136+
analytics.enabled = false;
137+
138+
// Alert the user that analytics has been disabled.
139+
print(analyticsDisabledNoticeMessage);
140+
return 0;
141+
} else if (topLevelResults['enable-analytics']) {
142+
analytics.enabled = true;
143+
144+
// Alert the user again that anonymous data will be collected.
145+
print(analyticsNoticeOnFirstRunMessage);
146+
return 0;
147+
}
216148

217149
if (topLevelResults.command == null &&
218150
topLevelResults.arguments.isNotEmpty) {
@@ -222,14 +154,12 @@ class DartdevRunner extends CommandRunner<int> {
222154
io.stderr.writeln(
223155
"Error when reading '$firstArg': No such file or directory.");
224156
// This is the exit code used by the frontend.
225-
VmInteropHandler.exit(254);
157+
return 254;
226158
}
227159
}
228160

229-
isDiagnostics = topLevelResults['diagnostics'];
230-
231161
final Ansi ansi = Ansi(Ansi.terminalSupportsAnsi);
232-
log = isDiagnostics
162+
log = topLevelResults['diagnostics']
233163
? Logger.verbose(ansi: ansi)
234164
: Logger.standard(ansi: ansi);
235165

@@ -247,8 +177,15 @@ class DartdevRunner extends CommandRunner<int> {
247177
analytics.sendScreenView(path),
248178
);
249179

180+
// The exit code for the dartdev process; null indicates that it has not been
181+
// set yet. The value is set in the catch and finally blocks below.
182+
int exitCode;
183+
184+
// Any caught non-UsageExceptions when running the sub command.
185+
Object exception;
186+
StackTrace stackTrace;
250187
try {
251-
final exitCode = await super.runCommand(topLevelResults);
188+
exitCode = await super.runCommand(topLevelResults);
252189

253190
if (path != null && analytics.enabled) {
254191
// Send the event to analytics
@@ -268,8 +205,16 @@ class DartdevRunner extends CommandRunner<int> {
268205
),
269206
);
270207
}
271-
272-
return exitCode;
208+
} on UsageException catch (e) {
209+
io.stderr.writeln('$e');
210+
exitCode = 64;
211+
} catch (e, st) {
212+
// Set the exception and stack trace only for non-UsageException cases:
213+
exception = e;
214+
stackTrace = st;
215+
io.stderr.writeln('$e');
216+
io.stderr.writeln('$st');
217+
exitCode = 1;
273218
} finally {
274219
stopwatch.stop();
275220
if (analytics.enabled) {
@@ -281,6 +226,32 @@ class DartdevRunner extends CommandRunner<int> {
281226
),
282227
);
283228
}
229+
// Set the exitCode, if it wasn't set in the catch block above.
230+
exitCode ??= 0;
231+
232+
// Send analytics before exiting
233+
if (analytics.enabled) {
234+
// And now send the exceptions and events to Google Analytics:
235+
if (exception != null) {
236+
unawaited(
237+
analytics.sendException(
238+
'${exception.runtimeType}\n${sanitizeStacktrace(stackTrace)}',
239+
fatal: true),
240+
);
241+
}
242+
243+
await analytics.waitForLastPing(
244+
timeout: const Duration(milliseconds: 200));
245+
}
246+
247+
// Set the enabled flag in the analytics object to true. Note: this will not
248+
// enable the analytics unless the disclosure was shown (terminal detected),
249+
// and the machine is not detected to be a bot.
250+
if (analytics.firstRun) {
251+
analytics.enabled = true;
252+
}
253+
analytics.close();
254+
return exitCode;
284255
}
285256
}
286257
}

pkg/dartdev/lib/src/analytics.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Analytics createAnalyticsInstance(bool disableAnalytics) {
5757
}
5858

5959
if (disableAnalytics) {
60-
// Dartdev tests pass a hidden 'disable-dartdev-analytics' flag which is
60+
// Dartdev tests pass a hidden 'no-analytics' flag which is
6161
// handled here.
6262
//
6363
// Also, stdout.hasTerminal is checked; if there is no terminal we infer

pkg/dartdev/lib/src/utils.dart

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,6 @@ String trimEnd(String s, String suffix) {
3838
return s;
3939
}
4040

41-
/// Static util methods used in dartdev to potentially modify the order of the
42-
/// arguments passed into dartdev.
43-
class PubUtils {
44-
/// If [doModifyArgs] returns true, then this method returns a modified copy
45-
/// of the argument list, 'help' is removed from the interior of the list, and
46-
/// '--help' is added to the end of the list of arguments. This method returns
47-
/// a modified copy of the list, the list itself is not modified.
48-
static List<String> modifyArgs(List<String> args) => List.from(args)
49-
..remove('help')
50-
..add('--help');
51-
52-
/// If ... help pub ..., and no other verb (such as 'analyze') appears before
53-
/// the ... help pub ... in the argument list, then return true.
54-
static bool shouldModifyArgs(List<String> args, List<String> allCmds) =>
55-
args != null &&
56-
allCmds != null &&
57-
args.isNotEmpty &&
58-
allCmds.isNotEmpty &&
59-
args.firstWhere((arg) => allCmds.contains(arg), orElse: () => '') ==
60-
'help' &&
61-
args.contains('help') &&
62-
args.contains('pub') &&
63-
args.indexOf('help') + 1 == args.indexOf('pub');
64-
}
65-
6641
extension FileSystemEntityExtension on FileSystemEntity {
6742
String get name => p.basename(path);
6843

0 commit comments

Comments
 (0)