Migrate reporting library to null safety (#80320)
This commit is contained in:
parent
2bc7939a9c
commit
16c73829a6
@ -16,7 +16,7 @@ import '../base/utils.dart';
|
|||||||
import '../base/version.dart';
|
import '../base/version.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../reporting/reporting.dart';
|
import '../reporting/reporting.dart';
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import '../base/os.dart';
|
|||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
import '../features.dart';
|
import '../features.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../linux/build_linux.dart';
|
import '../linux/build_linux.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
||||||
|
@ -11,7 +11,7 @@ import '../base/common.dart';
|
|||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
import '../features.dart';
|
import '../features.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../macos/build_macos.dart';
|
import '../macos/build_macos.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
||||||
|
@ -11,7 +11,7 @@ import '../base/common.dart';
|
|||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
import '../features.dart';
|
import '../features.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
||||||
import '../windows/build_windows.dart';
|
import '../windows/build_windows.dart';
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
import '../features.dart';
|
import '../features.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../reporting/reporting.dart';
|
import '../reporting/reporting.dart';
|
||||||
import '../runner/flutter_command.dart';
|
import '../runner/flutter_command.dart';
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import '../base/process.dart';
|
|||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
import '../device.dart';
|
import '../device.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../resident_runner.dart';
|
import '../resident_runner.dart';
|
||||||
import '../web/web_runner.dart';
|
import '../web/web_runner.dart';
|
||||||
|
@ -21,7 +21,6 @@ import 'macos/xcdevice.dart';
|
|||||||
import 'macos/xcode.dart';
|
import 'macos/xcode.dart';
|
||||||
import 'project.dart';
|
import 'project.dart';
|
||||||
import 'reporting/crash_reporting.dart';
|
import 'reporting/crash_reporting.dart';
|
||||||
import 'reporting/reporting.dart';
|
|
||||||
import 'runner/local_engine.dart';
|
import 'runner/local_engine.dart';
|
||||||
|
|
||||||
export 'globals_null_migrated.dart';
|
export 'globals_null_migrated.dart';
|
||||||
@ -30,7 +29,6 @@ Artifacts get artifacts => context.get<Artifacts>();
|
|||||||
BuildSystem get buildSystem => context.get<BuildSystem>();
|
BuildSystem get buildSystem => context.get<BuildSystem>();
|
||||||
CrashReporter get crashReporter => context.get<CrashReporter>();
|
CrashReporter get crashReporter => context.get<CrashReporter>();
|
||||||
Doctor get doctor => context.get<Doctor>();
|
Doctor get doctor => context.get<Doctor>();
|
||||||
Usage get flutterUsage => context.get<Usage>();
|
|
||||||
DeviceManager get deviceManager => context.get<DeviceManager>();
|
DeviceManager get deviceManager => context.get<DeviceManager>();
|
||||||
|
|
||||||
FlutterProjectFactory get projectFactory {
|
FlutterProjectFactory get projectFactory {
|
||||||
|
@ -25,6 +25,7 @@ import 'base/user_messages.dart';
|
|||||||
import 'cache.dart';
|
import 'cache.dart';
|
||||||
import 'ios/plist_parser.dart';
|
import 'ios/plist_parser.dart';
|
||||||
import 'persistent_tool_state.dart';
|
import 'persistent_tool_state.dart';
|
||||||
|
import 'reporting/reporting.dart';
|
||||||
import 'version.dart';
|
import 'version.dart';
|
||||||
|
|
||||||
Cache get cache => context.get<Cache>()!;
|
Cache get cache => context.get<Cache>()!;
|
||||||
@ -36,6 +37,7 @@ Signals get signals => context.get<Signals>() ?? LocalSignals.instance;
|
|||||||
AndroidStudio? get androidStudio => context.get<AndroidStudio>();
|
AndroidStudio? get androidStudio => context.get<AndroidStudio>();
|
||||||
AndroidSdk? get androidSdk => context.get<AndroidSdk>();
|
AndroidSdk? get androidSdk => context.get<AndroidSdk>();
|
||||||
FlutterVersion get flutterVersion => context.get<FlutterVersion>()!;
|
FlutterVersion get flutterVersion => context.get<FlutterVersion>()!;
|
||||||
|
Usage get flutterUsage => context.get<Usage>()!;
|
||||||
|
|
||||||
PersistentToolState? get persistentToolState => PersistentToolState.instance;
|
PersistentToolState? get persistentToolState => PersistentToolState.instance;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import '../build_info.dart';
|
|||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
import '../device.dart';
|
import '../device.dart';
|
||||||
import '../device_port_forwarder.dart';
|
import '../device_port_forwarder.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../macos/xcdevice.dart';
|
import '../macos/xcdevice.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../protocol_discovery.dart';
|
import '../protocol_discovery.dart';
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
part of reporting;
|
part of reporting;
|
||||||
|
|
||||||
class DisabledUsage implements Usage {
|
class DisabledUsage implements Usage {
|
||||||
@ -20,28 +18,28 @@ class DisabledUsage implements Usage {
|
|||||||
set enabled(bool value) { }
|
set enabled(bool value) { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get clientId => null;
|
String get clientId => '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendCommand(String command, { Map<String, String> parameters }) { }
|
void sendCommand(String command, { Map<String, String>? parameters }) { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendEvent(
|
void sendEvent(
|
||||||
String category,
|
String category,
|
||||||
String parameter, {
|
String parameter, {
|
||||||
String label,
|
String? label,
|
||||||
int value,
|
int? value,
|
||||||
Map<String, String> parameters,
|
Map<String, String>? parameters,
|
||||||
}) { }
|
}) { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendTiming(String category, String variableName, Duration duration, { String label }) { }
|
void sendTiming(String category, String variableName, Duration duration, { String? label }) { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendException(dynamic exception) { }
|
void sendException(dynamic exception) { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<Map<String, dynamic>> get onSend => null;
|
Stream<Map<String, dynamic>> get onSend => const Stream<Map<String, dynamic>>.empty();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> ensureAnalyticsSent() => Future<void>.value();
|
Future<void> ensureAnalyticsSent() => Future<void>.value();
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
part of reporting;
|
part of reporting;
|
||||||
|
|
||||||
/// A generic usage even that does not involve custom dimensions.
|
/// A generic usage even that does not involve custom dimensions.
|
||||||
@ -14,13 +12,13 @@ class UsageEvent {
|
|||||||
UsageEvent(this.category, this.parameter, {
|
UsageEvent(this.category, this.parameter, {
|
||||||
this.label,
|
this.label,
|
||||||
this.value,
|
this.value,
|
||||||
@required this.flutterUsage,
|
required this.flutterUsage,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String category;
|
final String category;
|
||||||
final String parameter;
|
final String parameter;
|
||||||
final String label;
|
final String? label;
|
||||||
final int value;
|
final int? value;
|
||||||
final Usage flutterUsage;
|
final Usage flutterUsage;
|
||||||
|
|
||||||
void send() {
|
void send() {
|
||||||
@ -37,11 +35,11 @@ class UsageEvent {
|
|||||||
/// sync/transfer "overhead" of updating this number of source files.
|
/// sync/transfer "overhead" of updating this number of source files.
|
||||||
class HotEvent extends UsageEvent {
|
class HotEvent extends UsageEvent {
|
||||||
HotEvent(String parameter, {
|
HotEvent(String parameter, {
|
||||||
@required this.targetPlatform,
|
required this.targetPlatform,
|
||||||
@required this.sdkName,
|
required this.sdkName,
|
||||||
@required this.emulator,
|
required this.emulator,
|
||||||
@required this.fullRestart,
|
required this.fullRestart,
|
||||||
@required this.fastReassemble,
|
required this.fastReassemble,
|
||||||
this.reason,
|
this.reason,
|
||||||
this.finalLibraryCount,
|
this.finalLibraryCount,
|
||||||
this.syncedLibraryCount,
|
this.syncedLibraryCount,
|
||||||
@ -53,20 +51,20 @@ class HotEvent extends UsageEvent {
|
|||||||
this.overallTimeInMs,
|
this.overallTimeInMs,
|
||||||
}) : super('hot', parameter, flutterUsage: globals.flutterUsage);
|
}) : super('hot', parameter, flutterUsage: globals.flutterUsage);
|
||||||
|
|
||||||
final String reason;
|
final String? reason;
|
||||||
final String targetPlatform;
|
final String targetPlatform;
|
||||||
final String sdkName;
|
final String sdkName;
|
||||||
final bool emulator;
|
final bool emulator;
|
||||||
final bool fullRestart;
|
final bool fullRestart;
|
||||||
final bool fastReassemble;
|
final bool fastReassemble;
|
||||||
final int finalLibraryCount;
|
final int? finalLibraryCount;
|
||||||
final int syncedLibraryCount;
|
final int? syncedLibraryCount;
|
||||||
final int syncedClassesCount;
|
final int? syncedClassesCount;
|
||||||
final int syncedProceduresCount;
|
final int? syncedProceduresCount;
|
||||||
final int syncedBytes;
|
final int? syncedBytes;
|
||||||
final int invalidatedSourcesCount;
|
final int? invalidatedSourcesCount;
|
||||||
final int transferTimeInMs;
|
final int? transferTimeInMs;
|
||||||
final int overallTimeInMs;
|
final int? overallTimeInMs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void send() {
|
void send() {
|
||||||
@ -76,7 +74,7 @@ class HotEvent extends UsageEvent {
|
|||||||
CustomDimensions.hotEventEmulator: emulator.toString(),
|
CustomDimensions.hotEventEmulator: emulator.toString(),
|
||||||
CustomDimensions.hotEventFullRestart: fullRestart.toString(),
|
CustomDimensions.hotEventFullRestart: fullRestart.toString(),
|
||||||
if (reason != null)
|
if (reason != null)
|
||||||
CustomDimensions.hotEventReason: reason,
|
CustomDimensions.hotEventReason: reason!,
|
||||||
if (finalLibraryCount != null)
|
if (finalLibraryCount != null)
|
||||||
CustomDimensions.hotEventFinalLibraryCount: finalLibraryCount.toString(),
|
CustomDimensions.hotEventFinalLibraryCount: finalLibraryCount.toString(),
|
||||||
if (syncedLibraryCount != null)
|
if (syncedLibraryCount != null)
|
||||||
@ -103,9 +101,9 @@ class HotEvent extends UsageEvent {
|
|||||||
/// An event that reports the result of a [DoctorValidator]
|
/// An event that reports the result of a [DoctorValidator]
|
||||||
class DoctorResultEvent extends UsageEvent {
|
class DoctorResultEvent extends UsageEvent {
|
||||||
DoctorResultEvent({
|
DoctorResultEvent({
|
||||||
@required this.validator,
|
required this.validator,
|
||||||
@required this.result,
|
required this.result,
|
||||||
Usage flutterUsage,
|
Usage? flutterUsage,
|
||||||
}) : super(
|
}) : super(
|
||||||
'doctor-result',
|
'doctor-result',
|
||||||
'${validator.runtimeType}',
|
'${validator.runtimeType}',
|
||||||
@ -139,20 +137,20 @@ class DoctorResultEvent extends UsageEvent {
|
|||||||
/// An event that reports on the result of a pub invocation.
|
/// An event that reports on the result of a pub invocation.
|
||||||
class PubResultEvent extends UsageEvent {
|
class PubResultEvent extends UsageEvent {
|
||||||
PubResultEvent({
|
PubResultEvent({
|
||||||
@required String context,
|
required String context,
|
||||||
@required String result,
|
required String result,
|
||||||
@required Usage usage,
|
required Usage usage,
|
||||||
}) : super('pub-result', context, label: result, flutterUsage: usage);
|
}) : super('pub-result', context, label: result, flutterUsage: usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An event that reports something about a build.
|
/// An event that reports something about a build.
|
||||||
class BuildEvent extends UsageEvent {
|
class BuildEvent extends UsageEvent {
|
||||||
BuildEvent(String label, {
|
BuildEvent(String label, {
|
||||||
String command,
|
String? command,
|
||||||
String settings,
|
String? settings,
|
||||||
String eventError,
|
String? eventError,
|
||||||
@required Usage flutterUsage,
|
required Usage flutterUsage,
|
||||||
@required String type,
|
required String type,
|
||||||
}) : _command = command,
|
}) : _command = command,
|
||||||
_settings = settings,
|
_settings = settings,
|
||||||
_eventError = eventError,
|
_eventError = eventError,
|
||||||
@ -165,19 +163,19 @@ class BuildEvent extends UsageEvent {
|
|||||||
flutterUsage: flutterUsage,
|
flutterUsage: flutterUsage,
|
||||||
);
|
);
|
||||||
|
|
||||||
final String _command;
|
final String? _command;
|
||||||
final String _settings;
|
final String? _settings;
|
||||||
final String _eventError;
|
final String? _eventError;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void send() {
|
void send() {
|
||||||
final Map<String, String> parameters = _useCdKeys(<CustomDimensions, String>{
|
final Map<String, String> parameters = _useCdKeys(<CustomDimensions, String>{
|
||||||
if (_command != null)
|
if (_command != null)
|
||||||
CustomDimensions.buildEventCommand: _command,
|
CustomDimensions.buildEventCommand: _command!,
|
||||||
if (_settings != null)
|
if (_settings != null)
|
||||||
CustomDimensions.buildEventSettings: _settings,
|
CustomDimensions.buildEventSettings: _settings!,
|
||||||
if (_eventError != null)
|
if (_eventError != null)
|
||||||
CustomDimensions.buildEventError: _eventError,
|
CustomDimensions.buildEventError: _eventError!,
|
||||||
});
|
});
|
||||||
flutterUsage.sendEvent(
|
flutterUsage.sendEvent(
|
||||||
category,
|
category,
|
||||||
@ -226,7 +224,7 @@ class CommandResultEvent extends UsageEvent {
|
|||||||
class AnalyticsConfigEvent extends UsageEvent {
|
class AnalyticsConfigEvent extends UsageEvent {
|
||||||
AnalyticsConfigEvent({
|
AnalyticsConfigEvent({
|
||||||
/// Whether analytics reporting is being enabled (true) or disabled (false).
|
/// Whether analytics reporting is being enabled (true) or disabled (false).
|
||||||
@required bool enabled,
|
required bool enabled,
|
||||||
}) : super(
|
}) : super(
|
||||||
'analytics',
|
'analytics',
|
||||||
'enabled',
|
'enabled',
|
||||||
@ -238,11 +236,11 @@ class AnalyticsConfigEvent extends UsageEvent {
|
|||||||
/// An event that reports when the code size measurement is run via `--analyze-size`.
|
/// An event that reports when the code size measurement is run via `--analyze-size`.
|
||||||
class CodeSizeEvent extends UsageEvent {
|
class CodeSizeEvent extends UsageEvent {
|
||||||
CodeSizeEvent(String platform, {
|
CodeSizeEvent(String platform, {
|
||||||
@required Usage flutterUsage,
|
required Usage flutterUsage,
|
||||||
}) : super(
|
}) : super(
|
||||||
'code-size-analysis',
|
'code-size-analysis',
|
||||||
platform,
|
platform,
|
||||||
flutterUsage: flutterUsage ?? globals.flutterUsage,
|
flutterUsage: flutterUsage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,14 +277,15 @@ class NullSafetyAnalysisEvent implements UsageEvent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int migrated = 0;
|
int migrated = 0;
|
||||||
LanguageVersion languageVersion;
|
LanguageVersion? languageVersion;
|
||||||
for (final Package package in packageConfig.packages) {
|
for (final Package package in packageConfig.packages) {
|
||||||
|
final LanguageVersion? packageLanguageVersion = package.languageVersion;
|
||||||
if (package.name == currentPackage) {
|
if (package.name == currentPackage) {
|
||||||
languageVersion = package.languageVersion;
|
languageVersion = packageLanguageVersion;
|
||||||
}
|
}
|
||||||
if (package.languageVersion != null &&
|
if (packageLanguageVersion != null &&
|
||||||
package.languageVersion.major >= nullSafeVersion.major &&
|
packageLanguageVersion.major >= nullSafeVersion.major &&
|
||||||
package.languageVersion.minor >= nullSafeVersion.minor) {
|
packageLanguageVersion.minor >= nullSafeVersion.minor) {
|
||||||
migrated += 1;
|
migrated += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
library reporting;
|
library reporting;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
@ -20,7 +18,7 @@ import '../build_info.dart';
|
|||||||
import '../dart/language_version.dart';
|
import '../dart/language_version.dart';
|
||||||
import '../doctor_validator.dart';
|
import '../doctor_validator.dart';
|
||||||
import '../features.dart';
|
import '../features.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals_null_migrated.dart' as globals;
|
||||||
import '../version.dart';
|
import '../version.dart';
|
||||||
import 'first_run.dart';
|
import 'first_run.dart';
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
part of reporting;
|
part of reporting;
|
||||||
|
|
||||||
const String _kFlutterUA = 'UA-67589403-6';
|
const String _kFlutterUA = 'UA-67589403-6';
|
||||||
@ -77,24 +75,27 @@ abstract class Usage {
|
|||||||
/// [logFile] are used for testing.
|
/// [logFile] are used for testing.
|
||||||
factory Usage({
|
factory Usage({
|
||||||
String settingsName = 'flutter',
|
String settingsName = 'flutter',
|
||||||
String versionOverride,
|
String? versionOverride,
|
||||||
String configDirOverride,
|
String? configDirOverride,
|
||||||
String logFile,
|
String? logFile,
|
||||||
AnalyticsFactory analyticsIOFactory,
|
AnalyticsFactory? analyticsIOFactory,
|
||||||
FirstRunMessenger firstRunMessenger,
|
FirstRunMessenger? firstRunMessenger,
|
||||||
@required bool runningOnBot,
|
required bool runningOnBot,
|
||||||
}) => _DefaultUsage(settingsName: settingsName,
|
}) =>
|
||||||
versionOverride: versionOverride,
|
_DefaultUsage.initialize(
|
||||||
configDirOverride: configDirOverride,
|
settingsName: settingsName,
|
||||||
logFile: logFile,
|
versionOverride: versionOverride,
|
||||||
analyticsIOFactory: analyticsIOFactory,
|
configDirOverride: configDirOverride,
|
||||||
runningOnBot: runningOnBot,
|
logFile: logFile,
|
||||||
firstRunMessenger: firstRunMessenger);
|
analyticsIOFactory: analyticsIOFactory,
|
||||||
|
runningOnBot: runningOnBot,
|
||||||
|
firstRunMessenger: firstRunMessenger,
|
||||||
|
);
|
||||||
|
|
||||||
/// Uses the global [Usage] instance to send a 'command' to analytics.
|
/// Uses the global [Usage] instance to send a 'command' to analytics.
|
||||||
static void command(String command, {
|
static void command(String command, {
|
||||||
Map<CustomDimensions, Object> parameters,
|
Map<CustomDimensions, Object>? parameters,
|
||||||
}) => globals.flutterUsage.sendCommand(command, parameters: _useCdKeys(parameters));
|
}) => globals.flutterUsage.sendCommand(command, parameters: parameters == null ? null : _useCdKeys(parameters));
|
||||||
|
|
||||||
/// Whether analytics reporting should be suppressed.
|
/// Whether analytics reporting should be suppressed.
|
||||||
bool get suppressAnalytics;
|
bool get suppressAnalytics;
|
||||||
@ -118,7 +119,7 @@ abstract class Usage {
|
|||||||
/// keys are well-defined in [CustomDimensions] above.
|
/// keys are well-defined in [CustomDimensions] above.
|
||||||
void sendCommand(
|
void sendCommand(
|
||||||
String command, {
|
String command, {
|
||||||
Map<String, String> parameters,
|
Map<String, String>? parameters,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Sends an 'event' to the underlying analytics implementation.
|
/// Sends an 'event' to the underlying analytics implementation.
|
||||||
@ -130,9 +131,9 @@ abstract class Usage {
|
|||||||
void sendEvent(
|
void sendEvent(
|
||||||
String category,
|
String category,
|
||||||
String parameter, {
|
String parameter, {
|
||||||
String label,
|
String? label,
|
||||||
int value,
|
int? value,
|
||||||
Map<String, String> parameters,
|
Map<String, String>? parameters,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Sends timing information to the underlying analytics implementation.
|
/// Sends timing information to the underlying analytics implementation.
|
||||||
@ -140,7 +141,7 @@ abstract class Usage {
|
|||||||
String category,
|
String category,
|
||||||
String variableName,
|
String variableName,
|
||||||
Duration duration, {
|
Duration duration, {
|
||||||
String label,
|
String? label,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Sends an exception to the underlying analytics implementation.
|
/// Sends an exception to the underlying analytics implementation.
|
||||||
@ -164,15 +165,15 @@ typedef AnalyticsFactory = Analytics Function(
|
|||||||
String applicationName,
|
String applicationName,
|
||||||
String applicationVersion, {
|
String applicationVersion, {
|
||||||
String analyticsUrl,
|
String analyticsUrl,
|
||||||
Directory documentDirectory,
|
Directory? documentDirectory,
|
||||||
});
|
});
|
||||||
|
|
||||||
Analytics _defaultAnalyticsIOFactory(
|
Analytics _defaultAnalyticsIOFactory(
|
||||||
String trackingId,
|
String trackingId,
|
||||||
String applicationName,
|
String applicationName,
|
||||||
String applicationVersion, {
|
String applicationVersion, {
|
||||||
String analyticsUrl,
|
String? analyticsUrl,
|
||||||
Directory documentDirectory,
|
Directory? documentDirectory,
|
||||||
}) {
|
}) {
|
||||||
return AnalyticsIO(
|
return AnalyticsIO(
|
||||||
trackingId,
|
trackingId,
|
||||||
@ -184,24 +185,34 @@ Analytics _defaultAnalyticsIOFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DefaultUsage implements Usage {
|
class _DefaultUsage implements Usage {
|
||||||
_DefaultUsage({
|
_DefaultUsage._({
|
||||||
|
required bool suppressAnalytics,
|
||||||
|
required Analytics analytics,
|
||||||
|
required this.firstRunMessenger,
|
||||||
|
required SystemClock clock,
|
||||||
|
}) : _suppressAnalytics = suppressAnalytics,
|
||||||
|
_analytics = analytics,
|
||||||
|
_clock = clock;
|
||||||
|
|
||||||
|
static _DefaultUsage initialize({
|
||||||
String settingsName = 'flutter',
|
String settingsName = 'flutter',
|
||||||
String versionOverride,
|
String? versionOverride,
|
||||||
String configDirOverride,
|
String? configDirOverride,
|
||||||
String logFile,
|
String? logFile,
|
||||||
AnalyticsFactory analyticsIOFactory,
|
AnalyticsFactory? analyticsIOFactory,
|
||||||
@required this.firstRunMessenger,
|
required FirstRunMessenger? firstRunMessenger,
|
||||||
@required bool runningOnBot,
|
required bool runningOnBot,
|
||||||
}) {
|
}) {
|
||||||
final FlutterVersion flutterVersion = globals.flutterVersion;
|
final FlutterVersion flutterVersion = globals.flutterVersion;
|
||||||
final String version = versionOverride ?? flutterVersion.getVersionString(redactUnknownBranches: true);
|
final String version = versionOverride ?? flutterVersion.getVersionString(redactUnknownBranches: true);
|
||||||
final bool suppressEnvFlag = globals.platform.environment['FLUTTER_SUPPRESS_ANALYTICS'] == 'true';
|
final bool suppressEnvFlag = globals.platform.environment['FLUTTER_SUPPRESS_ANALYTICS'] == 'true';
|
||||||
final String logFilePath = logFile ?? globals.platform.environment['FLUTTER_ANALYTICS_LOG_FILE'];
|
final String? logFilePath = logFile ?? globals.platform.environment['FLUTTER_ANALYTICS_LOG_FILE'];
|
||||||
final bool usingLogFile = logFilePath != null && logFilePath.isNotEmpty;
|
final bool usingLogFile = logFilePath != null && logFilePath.isNotEmpty;
|
||||||
|
|
||||||
analyticsIOFactory ??= _defaultAnalyticsIOFactory;
|
final AnalyticsFactory analyticsFactory = analyticsIOFactory ?? _defaultAnalyticsIOFactory;
|
||||||
_clock = globals.systemClock;
|
bool suppressAnalytics = false;
|
||||||
|
bool skipAnalyticsSessionSetup = false;
|
||||||
|
Analytics? setupAnalytics;
|
||||||
if (// To support testing, only allow other signals to suppress analytics
|
if (// To support testing, only allow other signals to suppress analytics
|
||||||
// when analytics are not being shunted to a file.
|
// when analytics are not being shunted to a file.
|
||||||
!usingLogFile && (
|
!usingLogFile && (
|
||||||
@ -213,73 +224,81 @@ class _DefaultUsage implements Usage {
|
|||||||
runningOnBot ||
|
runningOnBot ||
|
||||||
// Ignore when suppressed by FLUTTER_SUPPRESS_ANALYTICS.
|
// Ignore when suppressed by FLUTTER_SUPPRESS_ANALYTICS.
|
||||||
suppressEnvFlag
|
suppressEnvFlag
|
||||||
)) {
|
)) {
|
||||||
// If we think we're running on a CI system, suppress sending analytics.
|
// If we think we're running on a CI system, suppress sending analytics.
|
||||||
suppressAnalytics = true;
|
suppressAnalytics = true;
|
||||||
_analytics = AnalyticsMock();
|
setupAnalytics = AnalyticsMock();
|
||||||
return;
|
skipAnalyticsSessionSetup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usingLogFile) {
|
if (usingLogFile) {
|
||||||
_analytics = LogToFileAnalytics(logFilePath);
|
setupAnalytics ??= LogToFileAnalytics(logFilePath);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ErrorHandlingFileSystem.noExitOnFailure(() {
|
ErrorHandlingFileSystem.noExitOnFailure(() {
|
||||||
_analytics = analyticsIOFactory(
|
setupAnalytics = analyticsFactory(
|
||||||
_kFlutterUA,
|
_kFlutterUA,
|
||||||
settingsName,
|
settingsName,
|
||||||
version,
|
version,
|
||||||
documentDirectory: configDirOverride != null
|
documentDirectory: configDirOverride != null
|
||||||
? globals.fs.directory(configDirOverride)
|
? globals.fs.directory(configDirOverride)
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
globals.printTrace('Failed to initialize analytics reporting: $e');
|
globals.printTrace('Failed to initialize analytics reporting: $e');
|
||||||
suppressAnalytics = true;
|
suppressAnalytics = true;
|
||||||
_analytics = AnalyticsMock();
|
setupAnalytics ??= AnalyticsMock();
|
||||||
return;
|
skipAnalyticsSessionSetup = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(_analytics != null);
|
|
||||||
|
|
||||||
// Report a more detailed OS version string than package:usage does by default.
|
final Analytics analytics = setupAnalytics!;
|
||||||
_analytics.setSessionValue(
|
if (!skipAnalyticsSessionSetup) {
|
||||||
cdKey(CustomDimensions.sessionHostOsDetails),
|
// Report a more detailed OS version string than package:usage does by default.
|
||||||
globals.os.name,
|
analytics.setSessionValue(
|
||||||
);
|
cdKey(CustomDimensions.sessionHostOsDetails),
|
||||||
// Send the branch name as the "channel".
|
globals.os.name,
|
||||||
_analytics.setSessionValue(
|
);
|
||||||
cdKey(CustomDimensions.sessionChannelName),
|
// Send the branch name as the "channel".
|
||||||
flutterVersion.getBranchName(redactUnknownBranches: true),
|
analytics.setSessionValue(
|
||||||
);
|
cdKey(CustomDimensions.sessionChannelName),
|
||||||
// For each flutter experimental feature, record a session value in a comma
|
flutterVersion.getBranchName(redactUnknownBranches: true),
|
||||||
// separated list.
|
);
|
||||||
final String enabledFeatures = allFeatures
|
// For each flutter experimental feature, record a session value in a comma
|
||||||
.where((Feature feature) {
|
// separated list.
|
||||||
return feature.configSetting != null &&
|
final String enabledFeatures = allFeatures
|
||||||
globals.config.getValue(feature.configSetting) == true;
|
.where((Feature feature) {
|
||||||
|
final String? configSetting = feature.configSetting;
|
||||||
|
return configSetting != null && globals.config.getValue(configSetting) == true;
|
||||||
})
|
})
|
||||||
.map((Feature feature) => feature.configSetting)
|
.map((Feature feature) => feature.configSetting)
|
||||||
.join(',');
|
.join(',');
|
||||||
_analytics.setSessionValue(
|
analytics.setSessionValue(
|
||||||
cdKey(CustomDimensions.enabledFlutterFeatures),
|
cdKey(CustomDimensions.enabledFlutterFeatures),
|
||||||
enabledFeatures,
|
enabledFeatures,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Record the host as the application installer ID - the context that flutter_tools is running in.
|
// Record the host as the application installer ID - the context that flutter_tools is running in.
|
||||||
if (globals.platform.environment.containsKey('FLUTTER_HOST')) {
|
if (globals.platform.environment.containsKey('FLUTTER_HOST')) {
|
||||||
_analytics.setSessionValue('aiid', globals.platform.environment['FLUTTER_HOST']);
|
analytics.setSessionValue('aiid', globals.platform.environment['FLUTTER_HOST']);
|
||||||
|
}
|
||||||
|
analytics.analyticsOpt = AnalyticsOpt.optOut;
|
||||||
}
|
}
|
||||||
_analytics.analyticsOpt = AnalyticsOpt.optOut;
|
|
||||||
|
return _DefaultUsage._(
|
||||||
|
suppressAnalytics: suppressAnalytics,
|
||||||
|
analytics: analytics,
|
||||||
|
firstRunMessenger: firstRunMessenger,
|
||||||
|
clock: globals.systemClock,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Analytics _analytics;
|
final Analytics _analytics;
|
||||||
final FirstRunMessenger firstRunMessenger;
|
final FirstRunMessenger? firstRunMessenger;
|
||||||
|
|
||||||
bool _printedWelcome = false;
|
bool _printedWelcome = false;
|
||||||
bool _suppressAnalytics = false;
|
bool _suppressAnalytics = false;
|
||||||
SystemClock _clock;
|
final SystemClock _clock;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get suppressAnalytics => _suppressAnalytics || _analytics.firstRun;
|
bool get suppressAnalytics => _suppressAnalytics || _analytics.firstRun;
|
||||||
@ -301,7 +320,7 @@ class _DefaultUsage implements Usage {
|
|||||||
String get clientId => _analytics.clientId;
|
String get clientId => _analytics.clientId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendCommand(String command, { Map<String, String> parameters }) {
|
void sendCommand(String command, { Map<String, String>? parameters }) {
|
||||||
if (suppressAnalytics) {
|
if (suppressAnalytics) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -317,9 +336,9 @@ class _DefaultUsage implements Usage {
|
|||||||
void sendEvent(
|
void sendEvent(
|
||||||
String category,
|
String category,
|
||||||
String parameter, {
|
String parameter, {
|
||||||
String label,
|
String? label,
|
||||||
int value,
|
int? value,
|
||||||
Map<String, String> parameters,
|
Map<String, String>? parameters,
|
||||||
}) {
|
}) {
|
||||||
if (suppressAnalytics) {
|
if (suppressAnalytics) {
|
||||||
return;
|
return;
|
||||||
@ -344,7 +363,7 @@ class _DefaultUsage implements Usage {
|
|||||||
String category,
|
String category,
|
||||||
String variableName,
|
String variableName,
|
||||||
Duration duration, {
|
Duration duration, {
|
||||||
String label,
|
String? label,
|
||||||
}) {
|
}) {
|
||||||
if (suppressAnalytics) {
|
if (suppressAnalytics) {
|
||||||
return;
|
return;
|
||||||
@ -384,11 +403,12 @@ class _DefaultUsage implements Usage {
|
|||||||
}
|
}
|
||||||
// Display the welcome message if this is the first run of the tool or if
|
// Display the welcome message if this is the first run of the tool or if
|
||||||
// the license terms have changed since it was last displayed.
|
// the license terms have changed since it was last displayed.
|
||||||
if (firstRunMessenger != null && firstRunMessenger.shouldDisplayLicenseTerms() ?? true) {
|
final FirstRunMessenger? messenger = firstRunMessenger;
|
||||||
|
if (messenger != null && messenger.shouldDisplayLicenseTerms()) {
|
||||||
globals.printStatus('');
|
globals.printStatus('');
|
||||||
globals.printStatus(firstRunMessenger.licenseTerms, emphasis: true);
|
globals.printStatus(messenger.licenseTerms, emphasis: true);
|
||||||
_printedWelcome = true;
|
_printedWelcome = true;
|
||||||
firstRunMessenger.confirmLicenseTermsDisplayed();
|
messenger.confirmLicenseTermsDisplayed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,7 +432,7 @@ class LogToFileAnalytics extends AnalyticsMock {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> sendScreenView(String viewName, {
|
Future<void> sendScreenView(String viewName, {
|
||||||
Map<String, String> parameters,
|
Map<String, String>? parameters,
|
||||||
}) {
|
}) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return Future<void>.value(null);
|
return Future<void>.value(null);
|
||||||
@ -427,7 +447,7 @@ class LogToFileAnalytics extends AnalyticsMock {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> sendEvent(String category, String action,
|
Future<void> sendEvent(String category, String action,
|
||||||
{String label, int value, Map<String, String> parameters}) {
|
{String? label, int? value, Map<String, String>? parameters}) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return Future<void>.value(null);
|
return Future<void>.value(null);
|
||||||
}
|
}
|
||||||
@ -441,7 +461,7 @@ class LogToFileAnalytics extends AnalyticsMock {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> sendTiming(String variableName, int time,
|
Future<void> sendTiming(String variableName, int time,
|
||||||
{String category, String label}) {
|
{String? category, String? label}) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return Future<void>.value(null);
|
return Future<void>.value(null);
|
||||||
}
|
}
|
||||||
@ -496,12 +516,12 @@ class TestUsage implements Usage {
|
|||||||
void printWelcome() { }
|
void printWelcome() { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendCommand(String command, {Map<String, String> parameters}) {
|
void sendCommand(String command, {Map<String, String>? parameters}) {
|
||||||
commands.add(TestUsageCommand(command, parameters: parameters));
|
commands.add(TestUsageCommand(command, parameters: parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendEvent(String category, String parameter, {String label, int value, Map<String, String> parameters}) {
|
void sendEvent(String category, String parameter, {String? label, int? value, Map<String, String>? parameters}) {
|
||||||
events.add(TestUsageEvent(category, parameter, label: label, value: value, parameters: parameters));
|
events.add(TestUsageEvent(category, parameter, label: label, value: value, parameters: parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,7 +531,7 @@ class TestUsage implements Usage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void sendTiming(String category, String variableName, Duration duration, {String label}) {
|
void sendTiming(String category, String variableName, Duration duration, {String? label}) {
|
||||||
timings.add(TestTimingEvent(category, variableName, duration, label: label));
|
timings.add(TestTimingEvent(category, variableName, duration, label: label));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -522,7 +542,7 @@ class TestUsageCommand {
|
|||||||
const TestUsageCommand(this.command, {this.parameters});
|
const TestUsageCommand(this.command, {this.parameters});
|
||||||
|
|
||||||
final String command;
|
final String command;
|
||||||
final Map<String, String> parameters;
|
final Map<String, String>? parameters;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
@ -545,9 +565,9 @@ class TestUsageEvent {
|
|||||||
|
|
||||||
final String category;
|
final String category;
|
||||||
final String parameter;
|
final String parameter;
|
||||||
final String label;
|
final String? label;
|
||||||
final int value;
|
final int? value;
|
||||||
final Map<String, String> parameters;
|
final Map<String, String>? parameters;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
@ -578,7 +598,7 @@ class TestTimingEvent {
|
|||||||
final String category;
|
final String category;
|
||||||
final String variableName;
|
final String variableName;
|
||||||
final Duration duration;
|
final Duration duration;
|
||||||
final String label;
|
final String? label;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
@ -599,7 +619,7 @@ class TestTimingEvent {
|
|||||||
String toString() => 'TestTimingEvent($category, $variableName, $duration, label:$label)';
|
String toString() => 'TestTimingEvent($category, $variableName, $duration, label:$label)';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mapsEqual(Map<dynamic, dynamic> a, Map<dynamic, dynamic> b) {
|
bool _mapsEqual(Map<dynamic, dynamic>? a, Map<dynamic, dynamic>? b) {
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import 'dart/package_map.dart';
|
|||||||
import 'devfs.dart';
|
import 'devfs.dart';
|
||||||
import 'device.dart';
|
import 'device.dart';
|
||||||
import 'features.dart';
|
import 'features.dart';
|
||||||
import 'globals.dart' as globals;
|
import 'globals_null_migrated.dart' as globals;
|
||||||
import 'reporting/reporting.dart';
|
import 'reporting/reporting.dart';
|
||||||
import 'resident_devtools_handler.dart';
|
import 'resident_devtools_handler.dart';
|
||||||
import 'resident_runner.dart';
|
import 'resident_runner.dart';
|
||||||
|
@ -18,7 +18,7 @@ import 'package:flutter_tools/src/cache.dart';
|
|||||||
import 'package:flutter_tools/src/commands/packages.dart';
|
import 'package:flutter_tools/src/commands/packages.dart';
|
||||||
import 'package:flutter_tools/src/dart/pub.dart';
|
import 'package:flutter_tools/src/dart/pub.dart';
|
||||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||||
|
|
||||||
import '../../src/common.dart';
|
import '../../src/common.dart';
|
||||||
import '../../src/context.dart';
|
import '../../src/context.dart';
|
||||||
|
@ -17,7 +17,7 @@ import 'package:flutter_tools/src/commands/config.dart';
|
|||||||
import 'package:flutter_tools/src/commands/doctor.dart';
|
import 'package:flutter_tools/src/commands/doctor.dart';
|
||||||
import 'package:flutter_tools/src/doctor.dart';
|
import 'package:flutter_tools/src/doctor.dart';
|
||||||
import 'package:flutter_tools/src/features.dart';
|
import 'package:flutter_tools/src/features.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||||
import 'package:flutter_tools/src/version.dart';
|
import 'package:flutter_tools/src/version.dart';
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/doctor_validator.dart';
|
import 'package:flutter_tools/src/doctor_validator.dart';
|
||||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
|
@ -15,7 +15,7 @@ import 'package:flutter_tools/src/isolated/devfs_web.dart';
|
|||||||
import 'package:flutter_tools/src/isolated/resident_web_runner.dart';
|
import 'package:flutter_tools/src/isolated/resident_web_runner.dart';
|
||||||
import 'package:flutter_tools/src/build_system/build_system.dart';
|
import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||||
import 'package:flutter_tools/src/device.dart';
|
import 'package:flutter_tools/src/device.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||||
import 'package:flutter_tools/src/project.dart';
|
import 'package:flutter_tools/src/project.dart';
|
||||||
import 'package:flutter_tools/src/resident_runner.dart';
|
import 'package:flutter_tools/src/resident_runner.dart';
|
||||||
import 'package:flutter_tools/src/web/chrome.dart';
|
import 'package:flutter_tools/src/web/chrome.dart';
|
||||||
|
@ -21,7 +21,7 @@ import 'package:flutter_tools/src/isolated/resident_web_runner.dart';
|
|||||||
import 'package:flutter_tools/src/compile.dart';
|
import 'package:flutter_tools/src/compile.dart';
|
||||||
import 'package:flutter_tools/src/devfs.dart';
|
import 'package:flutter_tools/src/devfs.dart';
|
||||||
import 'package:flutter_tools/src/device.dart';
|
import 'package:flutter_tools/src/device.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||||
import 'package:flutter_tools/src/project.dart';
|
import 'package:flutter_tools/src/project.dart';
|
||||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
import 'package:flutter_tools/src/resident_runner.dart';
|
import 'package:flutter_tools/src/resident_runner.dart';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user