Unverified Commit 88f38110 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Turn on avoid_dynamic_calls lint, except packages/flutter tests, make appropriate changes. (#84476)

This adds avoid_dynamic_calls to the list of lints, and fixes all instances where it was violated.

Importantly, this lint is NOT turned on for flutter/packages/test, because those changes are happening in another PR: #84478
parent acd68cf4
...@@ -61,7 +61,7 @@ linter: ...@@ -61,7 +61,7 @@ linter:
# - avoid_catching_errors # we do this commonly # - avoid_catching_errors # we do this commonly
- avoid_classes_with_only_static_members - avoid_classes_with_only_static_members
# - avoid_double_and_int_checks # only useful when targeting JS runtime # - avoid_double_and_int_checks # only useful when targeting JS runtime
# - avoid_dynamic_calls # not yet tested - avoid_dynamic_calls
- avoid_empty_else - avoid_empty_else
- avoid_equals_and_hash_code_on_mutable_classes - avoid_equals_and_hash_code_on_mutable_classes
- avoid_escaping_inner_quotes - avoid_escaping_inner_quotes
......
...@@ -595,7 +595,7 @@ class ArchivePublisher { ...@@ -595,7 +595,7 @@ class ArchivePublisher {
if (!jsonData.containsKey('current_release')) { if (!jsonData.containsKey('current_release')) {
jsonData['current_release'] = <String, String>{}; jsonData['current_release'] = <String, String>{};
} }
jsonData['current_release'][branchName] = revision; (jsonData['current_release'] as Map<String, dynamic>)[branchName] = revision;
if (!jsonData.containsKey('releases')) { if (!jsonData.containsKey('releases')) {
jsonData['releases'] = <Map<String, dynamic>>[]; jsonData['releases'] = <Map<String, dynamic>>[];
} }
......
...@@ -1059,7 +1059,7 @@ Future<void> _ensureChromeDriverIsRunning() async { ...@@ -1059,7 +1059,7 @@ Future<void> _ensureChromeDriverIsRunning() async {
final HttpClientResponse response = await request.close(); final HttpClientResponse response = await request.close();
final Map<String, dynamic> webDriverStatus = json.decode(await response.transform(utf8.decoder).join('')) as Map<String, dynamic>; final Map<String, dynamic> webDriverStatus = json.decode(await response.transform(utf8.decoder).join('')) as Map<String, dynamic>;
client.close(); client.close();
final bool webDriverReady = webDriverStatus['value']['ready'] as bool; final bool webDriverReady = (webDriverStatus['value'] as Map<String, dynamic>)['ready'] as bool;
if (!webDriverReady) { if (!webDriverReady) {
throw Exception('WebDriver not available.'); throw Exception('WebDriver not available.');
} }
......
...@@ -394,7 +394,7 @@ void main() { ...@@ -394,7 +394,7 @@ void main() {
// Make sure the new entry is first (and hopefully it takes less than a // Make sure the new entry is first (and hopefully it takes less than a
// minute to go from publishArchive above to this line!). // minute to go from publishArchive above to this line!).
expect( expect(
DateTime.now().difference(DateTime.parse(releases[0]['release_date'] as String)), DateTime.now().difference(DateTime.parse((releases[0] as Map<String, dynamic>)['release_date'] as String)),
lessThan(const Duration(minutes: 1)), lessThan(const Duration(minutes: 1)),
); );
const JsonEncoder encoder = JsonEncoder.withIndent(' '); const JsonEncoder encoder = JsonEncoder.withIndent(' ');
......
...@@ -255,7 +255,7 @@ class ArchiveUnpublisher { ...@@ -255,7 +255,7 @@ class ArchiveUnpublisher {
}); });
jsonData['releases'] = releases; jsonData['releases'] = releases;
for (final Channel channel in channels) { for (final Channel channel in channels) {
if (!revisionsBeingRemoved.contains(jsonData['current_release'][getChannelName(channel)])) { if (!revisionsBeingRemoved.contains((jsonData['current_release'] as Map<String, dynamic>)[getChannelName(channel)])) {
// Don't replace the current release if it's not one of the revisions we're removing. // Don't replace the current release if it's not one of the revisions we're removing.
continue; continue;
} }
...@@ -263,7 +263,7 @@ class ArchiveUnpublisher { ...@@ -263,7 +263,7 @@ class ArchiveUnpublisher {
if (replacementRelease == null) { if (replacementRelease == null) {
throw UnpublishException('Unable to find previous release for channel ${getChannelName(channel)}.'); throw UnpublishException('Unable to find previous release for channel ${getChannelName(channel)}.');
} }
jsonData['current_release'][getChannelName(channel)] = replacementRelease['hash']; (jsonData['current_release'] as Map<String, dynamic>)[getChannelName(channel)] = replacementRelease['hash'];
print( print(
'${confirmed ? 'Reverting' : 'Would revert'} current ${getChannelName(channel)} ' '${confirmed ? 'Reverting' : 'Would revert'} current ${getChannelName(channel)} '
'${getPublishedPlatform(platform)} release to ${replacementRelease['hash']} (version ${replacementRelease['version']}).' '${getPublishedPlatform(platform)} release to ${replacementRelease['hash']} (version ${replacementRelease['version']}).'
......
...@@ -31,7 +31,7 @@ Future<void> main() async { ...@@ -31,7 +31,7 @@ Future<void> main() async {
final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = <String, dynamic>{};
for (final String key in withSemantics.benchmarkScoreKeys) { for (final String key in withSemantics.benchmarkScoreKeys) {
final String deltaKey = 'delta_$key'; final String deltaKey = 'delta_$key';
data[deltaKey] = withSemantics.data[key] - withoutSemantics.data[key]; data[deltaKey] = (withSemantics.data[key] as num) - (withoutSemantics.data[key] as num);
data['semantics_$key'] = withSemantics.data[key]; data['semantics_$key'] = withSemantics.data[key];
data[key] = withoutSemantics.data[key]; data[key] = withoutSemantics.data[key];
benchmarkScoreKeys.add(deltaKey); benchmarkScoreKeys.add(deltaKey);
......
...@@ -273,7 +273,7 @@ Future<Uri> _getRemoteDebuggerUrl(Uri base) async { ...@@ -273,7 +273,7 @@ Future<Uri> _getRemoteDebuggerUrl(Uri base) async {
if (jsonObject == null || jsonObject.isEmpty) { if (jsonObject == null || jsonObject.isEmpty) {
return base; return base;
} }
return base.resolve(jsonObject.first['webSocketDebuggerUrl'] as String); return base.resolve((jsonObject.first as Map<String, dynamic>)['webSocketDebuggerUrl'] as String);
} }
/// Summarizes a Blink trace down to a few interesting values. /// Summarizes a Blink trace down to a few interesting values.
......
...@@ -104,11 +104,12 @@ Manifest _validateAndParseManifest(YamlMap manifestYaml) { ...@@ -104,11 +104,12 @@ Manifest _validateAndParseManifest(YamlMap manifestYaml) {
List<ManifestTask> _validateAndParseTasks(dynamic tasksYaml) { List<ManifestTask> _validateAndParseTasks(dynamic tasksYaml) {
_checkType(tasksYaml is YamlMap, tasksYaml, 'Value of "tasks"', 'dictionary'); _checkType(tasksYaml is YamlMap, tasksYaml, 'Value of "tasks"', 'dictionary');
final List<dynamic> sortedKeys = (tasksYaml as YamlMap).keys.toList()..sort(); final List<String> sortedKeys = (tasksYaml as YamlMap).keys.toList().cast<String>()..sort();
return sortedKeys.map<ManifestTask>((dynamic taskName) => _validateAndParseTask(taskName, tasksYaml[taskName])).toList(); // ignore: avoid_dynamic_calls
return sortedKeys.map<ManifestTask>((String taskName) => _validateAndParseTask(taskName, tasksYaml[taskName])).toList();
} }
ManifestTask _validateAndParseTask(dynamic taskName, dynamic taskYaml) { ManifestTask _validateAndParseTask(String taskName, dynamic taskYaml) {
_checkType(taskName is String, taskName, 'Task name', 'string'); _checkType(taskName is String, taskName, 'Task name', 'string');
_checkType(taskYaml is YamlMap, taskYaml, 'Value of task "$taskName"', 'dictionary'); _checkType(taskYaml is YamlMap, taskYaml, 'Value of task "$taskName"', 'dictionary');
_checkKeys(taskYaml as YamlMap, 'Value of task "$taskName"', const <String>[ _checkKeys(taskYaml as YamlMap, 'Value of task "$taskName"', const <String>[
...@@ -119,27 +120,32 @@ ManifestTask _validateAndParseTask(dynamic taskName, dynamic taskYaml) { ...@@ -119,27 +120,32 @@ ManifestTask _validateAndParseTask(dynamic taskName, dynamic taskYaml) {
'timeout_in_minutes', 'timeout_in_minutes',
'on_luci', 'on_luci',
]); ]);
// ignore: avoid_dynamic_calls
final dynamic isFlaky = taskYaml['flaky']; final dynamic isFlaky = taskYaml['flaky'];
if (isFlaky != null) { if (isFlaky != null) {
_checkType(isFlaky is bool, isFlaky, 'flaky', 'boolean'); _checkType(isFlaky is bool, isFlaky, 'flaky', 'boolean');
} }
// ignore: avoid_dynamic_calls
final dynamic timeoutInMinutes = taskYaml['timeout_in_minutes']; final dynamic timeoutInMinutes = taskYaml['timeout_in_minutes'];
if (timeoutInMinutes != null) { if (timeoutInMinutes != null) {
_checkType(timeoutInMinutes is int, timeoutInMinutes, 'timeout_in_minutes', 'integer'); _checkType(timeoutInMinutes is int, timeoutInMinutes, 'timeout_in_minutes', 'integer');
} }
final List<dynamic> capabilities = _validateAndParseCapabilities(taskName as String, taskYaml['required_agent_capabilities']); // ignore: avoid_dynamic_calls
final List<dynamic> capabilities = _validateAndParseCapabilities(taskName, taskYaml['required_agent_capabilities']);
// ignore: avoid_dynamic_calls
final dynamic onLuci = taskYaml['on_luci']; final dynamic onLuci = taskYaml['on_luci'];
if (onLuci != null) { if (onLuci != null) {
_checkType(onLuci is bool, onLuci, 'on_luci', 'boolean'); _checkType(onLuci is bool, onLuci, 'on_luci', 'boolean');
} }
return ManifestTask._( return ManifestTask._(
name: taskName as String, name: taskName,
// ignore: avoid_dynamic_calls
description: taskYaml['description'] as String, description: taskYaml['description'] as String,
// ignore: avoid_dynamic_calls
stage: taskYaml['stage'] as String, stage: taskYaml['stage'] as String,
requiredAgentCapabilities: capabilities as List<String>, requiredAgentCapabilities: capabilities as List<String>,
isFlaky: isFlaky as bool ?? false, isFlaky: isFlaky as bool ?? false,
...@@ -150,8 +156,9 @@ ManifestTask _validateAndParseTask(dynamic taskName, dynamic taskYaml) { ...@@ -150,8 +156,9 @@ ManifestTask _validateAndParseTask(dynamic taskName, dynamic taskYaml) {
List<String> _validateAndParseCapabilities(String taskName, dynamic capabilitiesYaml) { List<String> _validateAndParseCapabilities(String taskName, dynamic capabilitiesYaml) {
_checkType(capabilitiesYaml is List, capabilitiesYaml, 'required_agent_capabilities', 'list'); _checkType(capabilitiesYaml is List, capabilitiesYaml, 'required_agent_capabilities', 'list');
for (int i = 0; i < (capabilitiesYaml as List<dynamic>).length; i++) { final List<dynamic> capabilities = capabilitiesYaml as List<dynamic>;
final dynamic capability = capabilitiesYaml[i]; for (int i = 0; i < capabilities.length; i++) {
final dynamic capability = capabilities[i];
_checkType(capability is String, capability, 'required_agent_capabilities[$i]', 'string'); _checkType(capability is String, capability, 'required_agent_capabilities[$i]', 'string');
} }
return (capabilitiesYaml as List<dynamic>).cast<String>(); return (capabilitiesYaml as List<dynamic>).cast<String>();
......
...@@ -31,7 +31,7 @@ class TaskResult { ...@@ -31,7 +31,7 @@ class TaskResult {
'result data ${prettyJson.convert(data)}'; 'result data ${prettyJson.convert(data)}';
} else if (data[key] is! num) { } else if (data[key] is! num) {
throw 'Invalid benchmark score for key "$key". It is expected to be a num ' throw 'Invalid benchmark score for key "$key". It is expected to be a num '
'but was ${data[key].runtimeType}: ${prettyJson.convert(data[key])}'; 'but was ${(data[key] as Object).runtimeType}: ${prettyJson.convert(data[key])}';
} }
} }
} }
......
...@@ -151,24 +151,43 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map<String, String> env ...@@ -151,24 +151,43 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map<String, String> env
return TaskResult.success( return TaskResult.success(
<String, dynamic> { <String, dynamic> {
// ignore: avoid_dynamic_calls
'hotReloadInitialDevFSSyncMilliseconds': smallReloadData['hotReloadInitialDevFSSyncMilliseconds'][0], 'hotReloadInitialDevFSSyncMilliseconds': smallReloadData['hotReloadInitialDevFSSyncMilliseconds'][0],
// ignore: avoid_dynamic_calls
'hotRestartMillisecondsToFrame': smallReloadData['hotRestartMillisecondsToFrame'][0], 'hotRestartMillisecondsToFrame': smallReloadData['hotRestartMillisecondsToFrame'][0],
// ignore: avoid_dynamic_calls
'hotReloadMillisecondsToFrame' : smallReloadData['hotReloadMillisecondsToFrame'][0], 'hotReloadMillisecondsToFrame' : smallReloadData['hotReloadMillisecondsToFrame'][0],
// ignore: avoid_dynamic_calls
'hotReloadDevFSSyncMilliseconds': smallReloadData['hotReloadDevFSSyncMilliseconds'][0], 'hotReloadDevFSSyncMilliseconds': smallReloadData['hotReloadDevFSSyncMilliseconds'][0],
// ignore: avoid_dynamic_calls
'hotReloadFlutterReassembleMilliseconds': smallReloadData['hotReloadFlutterReassembleMilliseconds'][0], 'hotReloadFlutterReassembleMilliseconds': smallReloadData['hotReloadFlutterReassembleMilliseconds'][0],
// ignore: avoid_dynamic_calls
'hotReloadVMReloadMilliseconds': smallReloadData['hotReloadVMReloadMilliseconds'][0], 'hotReloadVMReloadMilliseconds': smallReloadData['hotReloadVMReloadMilliseconds'][0],
// ignore: avoid_dynamic_calls
'hotReloadMillisecondsToFrameAfterChange' : smallReloadData['hotReloadMillisecondsToFrame'][1], 'hotReloadMillisecondsToFrameAfterChange' : smallReloadData['hotReloadMillisecondsToFrame'][1],
// ignore: avoid_dynamic_calls
'hotReloadDevFSSyncMillisecondsAfterChange': smallReloadData['hotReloadDevFSSyncMilliseconds'][1], 'hotReloadDevFSSyncMillisecondsAfterChange': smallReloadData['hotReloadDevFSSyncMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadFlutterReassembleMillisecondsAfterChange': smallReloadData['hotReloadFlutterReassembleMilliseconds'][1], 'hotReloadFlutterReassembleMillisecondsAfterChange': smallReloadData['hotReloadFlutterReassembleMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadVMReloadMillisecondsAfterChange': smallReloadData['hotReloadVMReloadMilliseconds'][1], 'hotReloadVMReloadMillisecondsAfterChange': smallReloadData['hotReloadVMReloadMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadInitialDevFSSyncAfterRelaunchMilliseconds' : freshRestartReloadsData['hotReloadInitialDevFSSyncMilliseconds'][0], 'hotReloadInitialDevFSSyncAfterRelaunchMilliseconds' : freshRestartReloadsData['hotReloadInitialDevFSSyncMilliseconds'][0],
// ignore: avoid_dynamic_calls
'hotReloadMillisecondsToFrameAfterMediumChange' : mediumReloadData['hotReloadMillisecondsToFrame'][1], 'hotReloadMillisecondsToFrameAfterMediumChange' : mediumReloadData['hotReloadMillisecondsToFrame'][1],
// ignore: avoid_dynamic_calls
'hotReloadDevFSSyncMillisecondsAfterMediumChange': mediumReloadData['hotReloadDevFSSyncMilliseconds'][1], 'hotReloadDevFSSyncMillisecondsAfterMediumChange': mediumReloadData['hotReloadDevFSSyncMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadFlutterReassembleMillisecondsAfterMediumChange': mediumReloadData['hotReloadFlutterReassembleMilliseconds'][1], 'hotReloadFlutterReassembleMillisecondsAfterMediumChange': mediumReloadData['hotReloadFlutterReassembleMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadVMReloadMillisecondsAfterMediumChange': mediumReloadData['hotReloadVMReloadMilliseconds'][1], 'hotReloadVMReloadMillisecondsAfterMediumChange': mediumReloadData['hotReloadVMReloadMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadMillisecondsToFrameAfterLargeChange' : largeReloadData['hotReloadMillisecondsToFrame'][1], 'hotReloadMillisecondsToFrameAfterLargeChange' : largeReloadData['hotReloadMillisecondsToFrame'][1],
// ignore: avoid_dynamic_calls
'hotReloadDevFSSyncMillisecondsAfterLargeChange': largeReloadData['hotReloadDevFSSyncMilliseconds'][1], 'hotReloadDevFSSyncMillisecondsAfterLargeChange': largeReloadData['hotReloadDevFSSyncMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadFlutterReassembleMillisecondsAfterLargeChange': largeReloadData['hotReloadFlutterReassembleMilliseconds'][1], 'hotReloadFlutterReassembleMillisecondsAfterLargeChange': largeReloadData['hotReloadFlutterReassembleMilliseconds'][1],
// ignore: avoid_dynamic_calls
'hotReloadVMReloadMillisecondsAfterLargeChange': largeReloadData['hotReloadVMReloadMilliseconds'][1], 'hotReloadVMReloadMillisecondsAfterLargeChange': largeReloadData['hotReloadVMReloadMilliseconds'][1],
}, },
benchmarkScoreKeys: <String>[ benchmarkScoreKeys: <String>[
......
...@@ -421,13 +421,15 @@ TaskFunction createsScrollSmoothnessPerfTest() { ...@@ -421,13 +421,15 @@ TaskFunction createsScrollSmoothnessPerfTest() {
final Map<String, dynamic> result = <String, dynamic>{}; final Map<String, dynamic> result = <String, dynamic>{};
void addResult(dynamic data, String suffix) { void addResult(dynamic data, String suffix) {
assert(data is Map<String, dynamic>); assert(data is Map<String, dynamic>);
const List<String> metricKeys = <String>[ if (data is Map<String, dynamic>) {
'janky_count', const List<String> metricKeys = <String>[
'average_abs_jerk', 'janky_count',
'dropped_frame_count', 'average_abs_jerk',
]; 'dropped_frame_count',
for (final String key in metricKeys) { ];
result[key+suffix] = data[key]; for (final String key in metricKeys) {
result[key + suffix] = data[key];
}
} }
} }
addResult(data['resample on with 90Hz input'], '_with_resampler_90Hz'); addResult(data['resample on with 90Hz input'], '_with_resampler_90Hz');
...@@ -1472,15 +1474,15 @@ class DevToolsMemoryTest { ...@@ -1472,15 +1474,15 @@ class DevToolsMemoryTest {
final Map<String, dynamic> data = json.decode( final Map<String, dynamic> data = json.decode(
file('$project/$_kJsonFileName').readAsStringSync(), file('$project/$_kJsonFileName').readAsStringSync(),
) as Map<String, dynamic>; ) as Map<String, dynamic>;
final List<dynamic> samples = data['samples']['data'] as List<dynamic>; final List<Map<String, dynamic>> samples = (data['samples'] as Map<String, dynamic>)['data'] as List<Map<String, dynamic>>;
int maxRss = 0; int maxRss = 0;
int maxAdbTotal = 0; int maxAdbTotal = 0;
for (final dynamic sample in samples) { for (final Map<String, dynamic> sample in samples) {
if (sample['rss'] != null) { if (sample['rss'] != null) {
maxRss = math.max(maxRss, sample['rss'] as int); maxRss = math.max(maxRss, sample['rss'] as int);
} }
if (sample['adb_memoryInfo'] != null) { if (sample['adb_memoryInfo'] != null) {
maxAdbTotal = math.max(maxAdbTotal, sample['adb_memoryInfo']['Total'] as int); maxAdbTotal = math.max(maxAdbTotal, (sample['adb_memoryInfo'] as Map<String, dynamic>)['Total'] as int);
} }
} }
......
...@@ -69,7 +69,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async { ...@@ -69,7 +69,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
final BlinkTraceSummary traceSummary = BlinkTraceSummary.fromJson(latestPerformanceTrace); final BlinkTraceSummary traceSummary = BlinkTraceSummary.fromJson(latestPerformanceTrace);
profile['totalUiFrame.average'] = traceSummary.averageTotalUIFrameTime.inMicroseconds; profile['totalUiFrame.average'] = traceSummary.averageTotalUIFrameTime.inMicroseconds;
profile['scoreKeys'] ??= <dynamic>[]; // using dynamic for consistency with JSON profile['scoreKeys'] ??= <dynamic>[]; // using dynamic for consistency with JSON
profile['scoreKeys'].add('totalUiFrame.average'); (profile['scoreKeys'] as List<dynamic>).add('totalUiFrame.average');
latestPerformanceTrace = null; latestPerformanceTrace = null;
} }
collectedProfiles.add(profile); collectedProfiles.add(profile);
......
...@@ -46,7 +46,7 @@ class _ColorPickerSwatch extends StatelessWidget { ...@@ -46,7 +46,7 @@ class _ColorPickerSwatch extends StatelessWidget {
final Color color; final Color color;
final bool selected; final bool selected;
final Function? onTap; final VoidCallback? onTap;
@override @override
Widget build (BuildContext context) { Widget build (BuildContext context) {
......
...@@ -42,7 +42,7 @@ Future<void> saveDurationsHistogram(List<Map<String, dynamic>> events, String ou ...@@ -42,7 +42,7 @@ Future<void> saveDurationsHistogram(List<Map<String, dynamic>> events, String ou
frameStart = timestamp; frameStart = timestamp;
} else { } else {
assert(phase == 'E'); assert(phase == 'E');
final String routeName = startEvent['args']['to'] as String; final String routeName = (startEvent['args'] as Map<String, dynamic>)['to'] as String;
durations[routeName] ??= <int>[]; durations[routeName] ??= <int>[];
durations[routeName]!.add(timestamp - frameStart!); durations[routeName]!.add(timestamp - frameStart!);
startEvent = null; startEvent = null;
...@@ -79,7 +79,7 @@ Future<void> saveDurationsHistogram(List<Map<String, dynamic>> events, String ou ...@@ -79,7 +79,7 @@ Future<void> saveDurationsHistogram(List<Map<String, dynamic>> events, String ou
continue; continue;
final String routeName = eventName == 'Start Transition' final String routeName = eventName == 'Start Transition'
? eventIter.current['args']['to'] as String ? (eventIter.current['args'] as Map<String, dynamic>)['to'] as String
: ''; : '';
if (eventName == lastEventName && routeName == lastRouteName) { if (eventName == lastEventName && routeName == lastRouteName) {
......
...@@ -440,18 +440,18 @@ class LogicalKeyEntry { ...@@ -440,18 +440,18 @@ class LogicalKeyEntry {
LogicalKeyEntry.fromJsonMapEntry(Map<String, dynamic> map) LogicalKeyEntry.fromJsonMapEntry(Map<String, dynamic> map)
: value = map['value'] as int, : value = map['value'] as int,
name = map['name'] as String, name = map['name'] as String,
webNames = _toNonEmptyArray<String>(map['names']['web']), webNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['web']),
macOSKeyCodeNames = _toNonEmptyArray<String>(map['names']['macos']), macOSKeyCodeNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['macos']),
macOSKeyCodeValues = _toNonEmptyArray<int>(map['values']?['macos']), macOSKeyCodeValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['macos']),
iOSKeyCodeNames = _toNonEmptyArray<String>(map['names']['ios']), iOSKeyCodeNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['ios']),
iOSKeyCodeValues = _toNonEmptyArray<int>(map['values']?['ios']), iOSKeyCodeValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['ios']),
gtkNames = _toNonEmptyArray<String>(map['names']['gtk']), gtkNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['gtk']),
gtkValues = _toNonEmptyArray<int>(map['values']?['gtk']), gtkValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['gtk']),
windowsNames = _toNonEmptyArray<String>(map['names']['windows']), windowsNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['windows']),
windowsValues = _toNonEmptyArray<int>(map['values']?['windows']), windowsValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['windows']),
androidNames = _toNonEmptyArray<String>(map['names']['android']), androidNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['android']),
androidValues = _toNonEmptyArray<int>(map['values']?['android']), androidValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['android']),
fuchsiaValues = _toNonEmptyArray<int>(map['values']?['fuchsia']), fuchsiaValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['fuchsia']),
keyLabel = map['keyLabel'] as String?; keyLabel = map['keyLabel'] as String?;
final int value; final int value;
......
...@@ -275,17 +275,20 @@ class PhysicalKeyEntry { ...@@ -275,17 +275,20 @@ class PhysicalKeyEntry {
/// Populates the key from a JSON map. /// Populates the key from a JSON map.
factory PhysicalKeyEntry.fromJsonMapEntry(Map<String, dynamic> map) { factory PhysicalKeyEntry.fromJsonMapEntry(Map<String, dynamic> map) {
final Map<String, dynamic> names = map['names'] as Map<String, dynamic>;
final Map<String, dynamic> scanCodes = map['scanCodes'] as Map<String, dynamic>;
final Map<String, dynamic>? keyCodes = map['keyCodes'] as Map<String, dynamic>?;
return PhysicalKeyEntry( return PhysicalKeyEntry(
name: map['names']['name'] as String, name: names['name'] as String,
chromiumCode: map['names']['chromium'] as String?, chromiumCode: names['chromium'] as String?,
usbHidCode: map['scanCodes']['usb'] as int, usbHidCode: scanCodes['usb'] as int,
androidScanCodes: (map['scanCodes']['android'] as List<dynamic>?)?.cast<int>() ?? <int>[], androidScanCodes: (scanCodes['android'] as List<dynamic>?)?.cast<int>() ?? <int>[],
linuxScanCode: map['scanCodes']['linux'] as int?, linuxScanCode: scanCodes['linux'] as int?,
xKbScanCode: map['scanCodes']['xkb'] as int?, xKbScanCode: scanCodes['xkb'] as int?,
windowsScanCode: map['scanCodes']['windows'] as int?, windowsScanCode: scanCodes['windows'] as int?,
macOSScanCode: map['scanCodes']['macos'] as int?, macOSScanCode: scanCodes['macos'] as int?,
iOSScanCode: map['scanCodes']['ios'] as int?, iOSScanCode: scanCodes['ios'] as int?,
glfwKeyCodes: (map['keyCodes']?['glfw'] as List<dynamic>?)?.cast<int>() ?? <int>[], glfwKeyCodes: (keyCodes?['glfw'] as List<dynamic>?)?.cast<int>() ?? <int>[],
); );
} }
......
...@@ -221,7 +221,7 @@ class _ChainedEvaluation<T> extends Animatable<T> { ...@@ -221,7 +221,7 @@ class _ChainedEvaluation<T> extends Animatable<T> {
/// If `T` is not nullable, then [begin] and [end] must both be set to /// If `T` is not nullable, then [begin] and [end] must both be set to
/// non-null values before using [lerp] or [transform], otherwise they /// non-null values before using [lerp] or [transform], otherwise they
/// will throw. /// will throw.
class Tween<T extends dynamic> extends Animatable<T> { class Tween<T extends Object?> extends Animatable<T> {
/// Creates a tween. /// Creates a tween.
/// ///
/// The [begin] and [end] properties must be non-null before the tween is /// The [begin] and [end] properties must be non-null before the tween is
...@@ -261,7 +261,8 @@ class Tween<T extends dynamic> extends Animatable<T> { ...@@ -261,7 +261,8 @@ class Tween<T extends dynamic> extends Animatable<T> {
// that do not conform to the Tween requirements. // that do not conform to the Tween requirements.
dynamic result; dynamic result;
try { try {
result = begin + (end - begin) * t; // ignore: avoid_dynamic_calls
result = (begin as dynamic) + ((end as dynamic) - (begin as dynamic)) * t;
result as T; result as T;
return true; return true;
} on NoSuchMethodError { } on NoSuchMethodError {
...@@ -301,7 +302,8 @@ class Tween<T extends dynamic> extends Animatable<T> { ...@@ -301,7 +302,8 @@ class Tween<T extends dynamic> extends Animatable<T> {
]); ]);
} }
}()); }());
return begin + (end - begin) * t as T; // ignore: avoid_dynamic_calls
return (begin as dynamic) + ((end as dynamic) - (begin as dynamic)) * t as T;
} }
/// Returns the interpolated value for the current value of the given animation. /// Returns the interpolated value for the current value of the given animation.
...@@ -330,7 +332,7 @@ class Tween<T extends dynamic> extends Animatable<T> { ...@@ -330,7 +332,7 @@ class Tween<T extends dynamic> extends Animatable<T> {
} }
/// A [Tween] that evaluates its [parent] in reverse. /// A [Tween] that evaluates its [parent] in reverse.
class ReverseTween<T> extends Tween<T> { class ReverseTween<T extends Object?> extends Tween<T> {
/// Construct a [Tween] that evaluates its [parent] in reverse. /// Construct a [Tween] that evaluates its [parent] in reverse.
ReverseTween(this.parent) ReverseTween(this.parent)
: assert(parent != null), : assert(parent != null),
......
...@@ -35,13 +35,15 @@ Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, { St ...@@ -35,13 +35,15 @@ Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, { St
final Completer<R> result = Completer<R>(); final Completer<R> result = Completer<R>();
errorPort.listen((dynamic errorData) { errorPort.listen((dynamic errorData) {
assert(errorData is List<dynamic>); assert(errorData is List<dynamic>);
assert(errorData.length == 2); if (errorData is List<dynamic>) {
final Exception exception = Exception(errorData[0]); assert(errorData.length == 2);
final StackTrace stack = StackTrace.fromString(errorData[1] as String); final Exception exception = Exception(errorData[0]);
if (result.isCompleted) { final StackTrace stack = StackTrace.fromString(errorData[1] as String);
Zone.current.handleUncaughtError(exception, stack); if (result.isCompleted) {
} else { Zone.current.handleUncaughtError(exception, stack);
result.completeError(exception, stack); } else {
result.completeError(exception, stack);
}
} }
}); });
exitPort.listen((dynamic exitData) { exitPort.listen((dynamic exitData) {
......
...@@ -86,7 +86,7 @@ class NetworkImage ...@@ -86,7 +86,7 @@ class NetworkImage
final Uri resolved = Uri.base.resolve(key.url); final Uri resolved = Uri.base.resolve(key.url);
// This API only exists in the web engine implementation and is not // This API only exists in the web engine implementation and is not
// contained in the analyzer summary for Flutter. // contained in the analyzer summary for Flutter.
return ui.webOnlyInstantiateImageCodecFromUrl(// ignore: undefined_function return ui.webOnlyInstantiateImageCodecFromUrl(// ignore: undefined_function, avoid_dynamic_calls
resolved, resolved,
chunkCallback: (int bytes, int total) { chunkCallback: (int bytes, int total) {
chunkEvents.add(ImageChunkEvent(cumulativeBytesLoaded: bytes, expectedTotalBytes: total)); chunkEvents.add(ImageChunkEvent(cumulativeBytesLoaded: bytes, expectedTotalBytes: total));
......
...@@ -517,7 +517,7 @@ class ImageCache { ...@@ -517,7 +517,7 @@ class ImageCache {
image.dispose(); image.dispose();
_cache.remove(key); _cache.remove(key);
if (!kReleaseMode) { if (!kReleaseMode) {
finishArgs['evictedKeys'].add(key.toString()); (finishArgs['evictedKeys'] as List<String>).add(key.toString());
} }
} }
if (!kReleaseMode) { if (!kReleaseMode) {
......
...@@ -1369,8 +1369,10 @@ class TextInput { ...@@ -1369,8 +1369,10 @@ class TextInput {
_currentConnection!._client.performAction(_toTextInputAction(args[1] as String)); _currentConnection!._client.performAction(_toTextInputAction(args[1] as String));
break; break;
case 'TextInputClient.performPrivateCommand': case 'TextInputClient.performPrivateCommand':
final Map<String, dynamic> firstArg = args[1] as Map<String, dynamic>;
_currentConnection!._client.performPrivateCommand( _currentConnection!._client.performPrivateCommand(
args[1]['action'] as String, args[1]['data'] as Map<String, dynamic>, firstArg['action'] as String,
firstArg['data'] as Map<String, dynamic>,
); );
break; break;
case 'TextInputClient.updateFloatingCursor': case 'TextInputClient.updateFloatingCursor':
......
...@@ -6395,7 +6395,7 @@ FlutterErrorDetails _debugReportException( ...@@ -6395,7 +6395,7 @@ FlutterErrorDetails _debugReportException(
/// * [RenderObjectElement.updateChildren], which discusses why this class is /// * [RenderObjectElement.updateChildren], which discusses why this class is
/// used as slot values for the children of a [MultiChildRenderObjectElement]. /// used as slot values for the children of a [MultiChildRenderObjectElement].
@immutable @immutable
class IndexedSlot<T> { class IndexedSlot<T extends Element?> {
/// Creates an [IndexedSlot] with the provided [index] and slot [value]. /// Creates an [IndexedSlot] with the provided [index] and slot [value].
const IndexedSlot(this.index, this.value); const IndexedSlot(this.index, this.value);
......
...@@ -306,6 +306,9 @@ class _GlowingOverscrollIndicatorState extends State<GlowingOverscrollIndicator> ...@@ -306,6 +306,9 @@ class _GlowingOverscrollIndicatorState extends State<GlowingOverscrollIndicator>
} }
} }
} else if (notification is ScrollEndNotification || notification is ScrollUpdateNotification) { } else if (notification is ScrollEndNotification || notification is ScrollUpdateNotification) {
// Using dynamic here to avoid layer violations of importing
// drag_details.dart from gestures.
// ignore: avoid_dynamic_calls
if ((notification as dynamic).dragDetails != null) { if ((notification as dynamic).dragDetails != null) {
_leadingController!.scrollEnd(); _leadingController!.scrollEnd();
_trailingController!.scrollEnd(); _trailingController!.scrollEnd();
......
include: ../analysis_options.yaml
linter:
rules:
# Turn off for tests, since we often use dynamic as a method to obtain a
# reference to a private state object or renderer in tests.
avoid_dynamic_calls: false
...@@ -209,7 +209,9 @@ class FakeAndroidPlatformViewsController { ...@@ -209,7 +209,9 @@ class FakeAndroidPlatformViewsController {
Future<dynamic> _dispose(MethodCall call) { Future<dynamic> _dispose(MethodCall call) {
assert(call.arguments is Map); assert(call.arguments is Map);
// ignore: avoid_dynamic_calls
final int id = call.arguments['id'] as int; final int id = call.arguments['id'] as int;
// ignore: avoid_dynamic_calls
final bool hybrid = call.arguments['hybrid'] as bool; final bool hybrid = call.arguments['hybrid'] as bool;
if (hybrid && !_views[id]!.hybrid!) { if (hybrid && !_views[id]!.hybrid!) {
......
...@@ -156,12 +156,12 @@ class WebFlutterDriver extends FlutterDriver { ...@@ -156,12 +156,12 @@ class WebFlutterDriver extends FlutterDriver {
final List<Map<String, dynamic>> events = <Map<String, dynamic>>[]; final List<Map<String, dynamic>> events = <Map<String, dynamic>>[];
for (final async_io.LogEntry entry in await _connection.logs.toList()) { for (final async_io.LogEntry entry in await _connection.logs.toList()) {
if (_startTime.isBefore(entry.timestamp)) { if (_startTime.isBefore(entry.timestamp)) {
final Map<String, dynamic> data = jsonDecode(entry.message!)['message'] as Map<String, dynamic>; final Map<String, dynamic> data = (jsonDecode(entry.message!) as Map<String, dynamic>)['message'] as Map<String, dynamic>;
if (data['method'] == 'Tracing.dataCollected') { if (data['method'] == 'Tracing.dataCollected') {
// 'ts' data collected from Chrome is in double format, conversion needed // 'ts' data collected from Chrome is in double format, conversion needed
try { try {
data['params']['ts'] = final Map<String, dynamic> params = data['params'] as Map<String, dynamic>;
double.parse(data['params']['ts'].toString()).toInt(); params['ts'] = double.parse(params['ts'].toString()).toInt();
} on FormatException catch (_) { } on FormatException catch (_) {
// data is corrupted, skip // data is corrupted, skip
continue; continue;
......
...@@ -968,16 +968,16 @@ void main() { ...@@ -968,16 +968,16 @@ void main() {
}); });
} }
/// This function will verify the format of the script // This function will verify the format of the script and return the actual
/// and return the actual script. // script. The script will be in the following format:
/// script will be in the following format:
// window.flutterDriver('[actual script]') // window.flutterDriver('[actual script]')
String? _checkAndEncode(dynamic script) { String _checkAndEncode(dynamic script) {
expect(script, isA<String>()); expect(script, isA<String>());
expect(script.startsWith(_kWebScriptPrefix), isTrue); final String scriptString = script as String;
expect(script.endsWith(_kWebScriptSuffix), isTrue); expect(scriptString.startsWith(_kWebScriptPrefix), isTrue);
expect(scriptString.endsWith(_kWebScriptSuffix), isTrue);
// Strip prefix and suffix // Strip prefix and suffix
return script.substring(_kWebScriptPrefix.length, script.length - 2) as String?; return scriptString.substring(_kWebScriptPrefix.length, script.length - 2);
} }
vms.Response? makeFakeResponse( vms.Response? makeFakeResponse(
...@@ -999,7 +999,7 @@ class FakeFlutterWebConnection extends Fake implements FlutterWebConnection { ...@@ -999,7 +999,7 @@ class FakeFlutterWebConnection extends Fake implements FlutterWebConnection {
@override @override
Future<dynamic> sendCommand(String script, Duration? duration) async { Future<dynamic> sendCommand(String script, Duration? duration) async {
commandLog.add('$script $duration'); commandLog.add('$script $duration');
final Map<String, dynamic> decoded = jsonDecode(_checkAndEncode(script)!) as Map<String, dynamic>; final Map<String, dynamic> decoded = jsonDecode(_checkAndEncode(script)) as Map<String, dynamic>;
final dynamic response = responses[decoded['command']]; final dynamic response = responses[decoded['command']];
assert(response != null, 'Missing ${decoded['command']} in responses.'); assert(response != null, 'Missing ${decoded['command']} in responses.');
return response; return response;
......
...@@ -345,14 +345,18 @@ void main() { ...@@ -345,14 +345,18 @@ void main() {
final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial'))); final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial')));
final dynamic dialPainter = dialPaint.painter; final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>; final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect( expect(
// ignore: avoid_dynamic_calls
primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!), primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels12To11, labels12To11,
); );
// ignore: avoid_dynamic_calls
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>; final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
expect( expect(
// ignore: avoid_dynamic_calls
secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!), secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels12To11, labels12To11,
); );
...@@ -363,14 +367,18 @@ void main() { ...@@ -363,14 +367,18 @@ void main() {
final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial'))); final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial')));
final dynamic dialPainter = dialPaint.painter; final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>; final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect( expect(
// ignore: avoid_dynamic_calls
primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!), primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels00To22TwoDigit, labels00To22TwoDigit,
); );
// ignore: avoid_dynamic_calls
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>; final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
expect( expect(
// ignore: avoid_dynamic_calls
secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!), secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels00To22TwoDigit, labels00To22TwoDigit,
); );
......
...@@ -866,7 +866,7 @@ class _HasGoodToStringDeep extends Matcher { ...@@ -866,7 +866,7 @@ class _HasGoodToStringDeep extends Matcher {
@override @override
bool matches(dynamic object, Map<dynamic, dynamic> matchState) { bool matches(dynamic object, Map<dynamic, dynamic> matchState) {
final List<String> issues = <String>[]; final List<String> issues = <String>[];
String description = object.toStringDeep() as String; String description = object.toStringDeep() as String; // ignore: avoid_dynamic_calls
if (description.endsWith('\n')) { if (description.endsWith('\n')) {
// Trim off trailing \n as the remaining calculations assume // Trim off trailing \n as the remaining calculations assume
// the description does not end with a trailing \n. // the description does not end with a trailing \n.
...@@ -904,7 +904,7 @@ class _HasGoodToStringDeep extends Matcher { ...@@ -904,7 +904,7 @@ class _HasGoodToStringDeep extends Matcher {
const String prefixOtherLines = 'PREFIX_OTHER_LINES_'; const String prefixOtherLines = 'PREFIX_OTHER_LINES_';
final List<String> prefixIssues = <String>[]; final List<String> prefixIssues = <String>[];
String descriptionWithPrefixes = String descriptionWithPrefixes =
object.toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines) as String; object.toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines) as String; // ignore: avoid_dynamic_calls
if (descriptionWithPrefixes.endsWith('\n')) { if (descriptionWithPrefixes.endsWith('\n')) {
// Trim off trailing \n as the remaining calculations assume // Trim off trailing \n as the remaining calculations assume
// the description does not end with a trailing \n. // the description does not end with a trailing \n.
...@@ -1875,7 +1875,7 @@ class _MatchesSemanticsData extends Matcher { ...@@ -1875,7 +1875,7 @@ class _MatchesSemanticsData extends Matcher {
bool allMatched = true; bool allMatched = true;
if (children != null) { if (children != null) {
int i = 0; int i = 0;
node.visitChildren((SemanticsNode child) { (node as SemanticsNode).visitChildren((SemanticsNode child) {
allMatched = children![i].matches(child, matchState) && allMatched; allMatched = children![i].matches(child, matchState) && allMatched;
i += 1; i += 1;
return allMatched; return allMatched;
......
...@@ -119,8 +119,9 @@ class TestTextInput { ...@@ -119,8 +119,9 @@ class TestTextInput {
log.add(methodCall); log.add(methodCall);
switch (methodCall.method) { switch (methodCall.method) {
case 'TextInput.setClient': case 'TextInput.setClient':
_client = methodCall.arguments[0] as int; final List<dynamic> arguments = methodCall.arguments as List<dynamic>;
setClientArgs = methodCall.arguments[1] as Map<String, dynamic>; _client = arguments[0] as int;
setClientArgs = arguments[1] as Map<String, dynamic>;
break; break;
case 'TextInput.updateConfig': case 'TextInput.updateConfig':
setClientArgs = methodCall.arguments as Map<String, dynamic>; setClientArgs = methodCall.arguments as Map<String, dynamic>;
......
...@@ -11,6 +11,7 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -11,6 +11,7 @@ import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
test('TestWindow can handle new methods without breaking', () { test('TestWindow can handle new methods without breaking', () {
final dynamic testWindow = TestWindow(window: ui.window); final dynamic testWindow = TestWindow(window: ui.window);
// ignore: avoid_dynamic_calls
expect(testWindow.someNewProperty, null); expect(testWindow.someNewProperty, null);
}); });
......
...@@ -126,7 +126,7 @@ class MultiRootFileSystem extends ForwardingFileSystem { ...@@ -126,7 +126,7 @@ class MultiRootFileSystem extends ForwardingFileSystem {
} else if (path is FileSystemEntity) { } else if (path is FileSystemEntity) {
uri = path.uri; uri = path.uri;
} else { } else {
throw ArgumentError('Invalid type for "path": ${path?.runtimeType}'); throw ArgumentError('Invalid type for "path": ${(path as Object?)?.runtimeType}');
} }
if (!uri.hasScheme || uri.scheme != _scheme) { if (!uri.hasScheme || uri.scheme != _scheme) {
......
...@@ -15,6 +15,7 @@ import '../../base/file_system.dart'; ...@@ -15,6 +15,7 @@ import '../../base/file_system.dart';
import '../../base/io.dart'; import '../../base/io.dart';
import '../../build_info.dart'; import '../../build_info.dart';
import '../../cache.dart'; import '../../cache.dart';
import '../../convert.dart';
import '../../dart/language_version.dart'; import '../../dart/language_version.dart';
import '../../dart/package_map.dart'; import '../../dart/package_map.dart';
import '../../globals_null_migrated.dart' as globals; import '../../globals_null_migrated.dart' as globals;
...@@ -198,6 +199,16 @@ class Dart2JSTarget extends Target { ...@@ -198,6 +199,16 @@ class Dart2JSTarget extends Target {
'dart2js.d', 'dart2js.d',
]; ];
String _collectOutput(ProcessResult result) {
final String stdout = result.stdout is List<int>
? utf8.decode(result.stdout as List<int>)
: result.stdout as String;
final String stderr = result.stderr is List<int>
? utf8.decode(result.stderr as List<int>)
: result.stderr as String;
return stdout + stderr;
}
@override @override
Future<void> build(Environment environment) async { Future<void> build(Environment environment) async {
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]); final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
...@@ -233,7 +244,7 @@ class Dart2JSTarget extends Target { ...@@ -233,7 +244,7 @@ class Dart2JSTarget extends Target {
environment.buildDir.childFile('main.dart').path, // dartfile environment.buildDir.childFile('main.dart').path, // dartfile
]); ]);
if (kernelResult.exitCode != 0) { if (kernelResult.exitCode != 0) {
throw Exception(kernelResult.stdout + kernelResult.stderr); throw Exception(_collectOutput(kernelResult));
} }
final String dart2jsOptimization = environment.defines[kDart2jsOptimization]; final String dart2jsOptimization = environment.defines[kDart2jsOptimization];
...@@ -250,7 +261,7 @@ class Dart2JSTarget extends Target { ...@@ -250,7 +261,7 @@ class Dart2JSTarget extends Target {
environment.buildDir.childFile('app.dill').path, // dartfile environment.buildDir.childFile('app.dill').path, // dartfile
]); ]);
if (javaScriptResult.exitCode != 0) { if (javaScriptResult.exitCode != 0) {
throw Exception(javaScriptResult.stdout + javaScriptResult.stderr); throw Exception(_collectOutput(javaScriptResult));
} }
final File dart2jsDeps = environment.buildDir final File dart2jsDeps = environment.buildDir
.childFile('app.dill.deps'); .childFile('app.dill.deps');
......
...@@ -150,7 +150,7 @@ class AnalysisServer { ...@@ -150,7 +150,7 @@ class AnalysisServer {
void _handleStatus(Map<String, dynamic> statusInfo) { void _handleStatus(Map<String, dynamic> statusInfo) {
// {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}} // {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
if (statusInfo['analysis'] != null && !_analyzingController.isClosed) { if (statusInfo['analysis'] != null && !_analyzingController.isClosed) {
final bool isAnalyzing = statusInfo['analysis']['isAnalyzing'] as bool; final bool isAnalyzing = (statusInfo['analysis'] as Map<String, dynamic>)['isAnalyzing'] as bool;
_analyzingController.add(isAnalyzing); _analyzingController.add(isAnalyzing);
} }
} }
...@@ -293,15 +293,16 @@ class WrittenError { ...@@ -293,15 +293,16 @@ class WrittenError {
/// "hasFix":false /// "hasFix":false
/// } /// }
static WrittenError fromJson(Map<String, dynamic> json) { static WrittenError fromJson(Map<String, dynamic> json) {
final Map<String, dynamic> location = json['location'] as Map<String, dynamic>;
return WrittenError._( return WrittenError._(
severity: json['severity'] as String, severity: json['severity'] as String,
type: json['type'] as String, type: json['type'] as String,
message: json['message'] as String, message: json['message'] as String,
code: json['code'] as String, code: json['code'] as String,
file: json['location']['file'] as String, file: location['file'] as String,
startLine: json['location']['startLine'] as int, startLine: location['startLine'] as int,
startColumn: json['location']['startColumn'] as int, startColumn: location['startColumn'] as int,
offset: json['location']['offset'] as int, offset: location['offset'] as int,
); );
} }
......
...@@ -496,10 +496,10 @@ class _DefaultPub implements Pub { ...@@ -496,10 +496,10 @@ class _DefaultPub implements Pub {
// Because [loadPackageConfigWithLogging] succeeded [packageConfigFile] // Because [loadPackageConfigWithLogging] succeeded [packageConfigFile]
// we can rely on the file to exist and be correctly formatted. // we can rely on the file to exist and be correctly formatted.
final dynamic jsonContents = final Map<String, dynamic> jsonContents =
json.decode(packageConfigFile.readAsStringSync()); json.decode(packageConfigFile.readAsStringSync()) as Map<String, dynamic>;
jsonContents['packages'].add(<String, dynamic>{ (jsonContents['packages'] as List<dynamic>).add(<String, dynamic>{
'name': 'flutter_gen', 'name': 'flutter_gen',
'rootUri': 'flutter_gen', 'rootUri': 'flutter_gen',
'languageVersion': '2.12', 'languageVersion': '2.12',
......
...@@ -247,7 +247,7 @@ class FlutterManifest { ...@@ -247,7 +247,7 @@ class FlutterManifest {
DeferredComponent( DeferredComponent(
name: component['name'] as String, name: component['name'] as String,
libraries: component['libraries'] == null ? libraries: component['libraries'] == null ?
<String>[] : component['libraries'].cast<String>() as List<String>, <String>[] : (component['libraries'] as List<dynamic>).cast<String>(),
assets: assetsUri, assets: assetsUri,
) )
); );
...@@ -571,6 +571,7 @@ void _validateFlutter(YamlMap? yaml, List<String> errors) { ...@@ -571,6 +571,7 @@ void _validateFlutter(YamlMap? yaml, List<String> errors) {
void _validateListType<T>(YamlList yamlList, List<String> errors, String context, String typeAlias) { void _validateListType<T>(YamlList yamlList, List<String> errors, String context, String typeAlias) {
for (int i = 0; i < yamlList.length; i++) { for (int i = 0; i < yamlList.length; i++) {
if (yamlList[i] is! T) { if (yamlList[i] is! T) {
// ignore: avoid_dynamic_calls
errors.add('Expected $context to be a list of $typeAlias, but element $i was a ${yamlList[i].runtimeType}'); errors.add('Expected $context to be a list of $typeAlias, but element $i was a ${yamlList[i].runtimeType}');
} }
} }
...@@ -584,6 +585,7 @@ void _validateDeferredComponents(MapEntry<Object?, Object?> kvp, List<String> er ...@@ -584,6 +585,7 @@ void _validateDeferredComponents(MapEntry<Object?, Object?> kvp, List<String> er
for (int i = 0; i < yamlList.length; i++) { for (int i = 0; i < yamlList.length; i++) {
final Object? valueMap = yamlList[i]; final Object? valueMap = yamlList[i];
if (valueMap is! YamlMap) { if (valueMap is! YamlMap) {
// ignore: avoid_dynamic_calls
errors.add('Expected the $i element in "${kvp.key}" to be a map, but got ${yamlList[i]} (${yamlList[i].runtimeType}).'); errors.add('Expected the $i element in "${kvp.key}" to be a map, but got ${yamlList[i]} (${yamlList[i].runtimeType}).');
continue; continue;
} }
......
...@@ -130,7 +130,7 @@ class SimControl { ...@@ -130,7 +130,7 @@ class SimControl {
return <String, Map<String, dynamic>>{}; return <String, Map<String, dynamic>>{};
} }
try { try {
final Object decodeResult = json.decode(results.stdout)[section.name]; final Object decodeResult = (json.decode(results.stdout) as Map<String, dynamic>)[section.name];
if (decodeResult is Map<String, dynamic>) { if (decodeResult is Map<String, dynamic>) {
return decodeResult; return decodeResult;
} }
......
...@@ -269,55 +269,52 @@ class XCDevice { ...@@ -269,55 +269,52 @@ class XCDevice {
final List<IOSDevice> devices = <IOSDevice>[]; final List<IOSDevice> devices = <IOSDevice>[];
for (final dynamic device in allAvailableDevices) { for (final dynamic device in allAvailableDevices) {
if (device is! Map) { if (device is Map<String, dynamic>) {
continue; // Only include iPhone, iPad, iPod, or other iOS devices.
} if (!_isIPhoneOSDevice(device)) {
final Map<String, dynamic> deviceProperties = device as Map<String, dynamic>; continue;
}
// Only include iPhone, iPad, iPod, or other iOS devices. final Map<String, dynamic> errorProperties = _errorProperties(device);
if (!_isIPhoneOSDevice(deviceProperties)) { if (errorProperties != null) {
continue; final String errorMessage = _parseErrorMessage(errorProperties);
} if (errorMessage.contains('not paired')) {
UsageEvent('device', 'ios-trust-failure', flutterUsage: globals.flutterUsage).send();
}
_logger.printTrace(errorMessage);
final Map<String, dynamic> errorProperties = _errorProperties(deviceProperties); final int code = _errorCode(errorProperties);
if (errorProperties != null) {
final String errorMessage = _parseErrorMessage(errorProperties); // Temporary error -10: iPhone is busy: Preparing debugger support for iPhone.
if (errorMessage.contains('not paired')) { // Sometimes the app launch will fail on these devices until Xcode is done setting up the device.
UsageEvent('device', 'ios-trust-failure', flutterUsage: globals.flutterUsage).send(); // Other times this is a false positive and the app will successfully launch despite the error.
if (code != -10) {
continue;
}
} }
_logger.printTrace(errorMessage);
final int code = _errorCode(errorProperties); final IOSDeviceInterface interface = _interfaceType(device);
// Temporary error -10: iPhone is busy: Preparing debugger support for iPhone. // Only support USB devices, skip "network" interface (Xcode > Window > Devices and Simulators > Connect via network).
// Sometimes the app launch will fail on these devices until Xcode is done setting up the device. // TODO(jmagman): Remove this check once wirelessly detected devices can be observed and attached, https://github.com/flutter/flutter/issues/15072.
// Other times this is a false positive and the app will successfully launch despite the error. if (interface != IOSDeviceInterface.usb) {
if (code != -10) {
continue; continue;
} }
}
final IOSDeviceInterface interface = _interfaceType(deviceProperties);
// Only support USB devices, skip "network" interface (Xcode > Window > Devices and Simulators > Connect via network). devices.add(IOSDevice(
// TODO(jmagman): Remove this check once wirelessly detected devices can be observed and attached, https://github.com/flutter/flutter/issues/15072. device['identifier'] as String,
if (interface != IOSDeviceInterface.usb) { name: device['name'] as String,
continue; cpuArchitecture: _cpuArchitecture(device),
interfaceType: interface,
sdkVersion: _sdkVersion(device),
iProxy: _iProxy,
fileSystem: globals.fs,
logger: _logger,
iosDeploy: _iosDeploy,
iMobileDevice: _iMobileDevice,
platform: globals.platform,
));
} }
devices.add(IOSDevice(
device['identifier'] as String,
name: device['name'] as String,
cpuArchitecture: _cpuArchitecture(deviceProperties),
interfaceType: interface,
sdkVersion: _sdkVersion(deviceProperties),
iProxy: _iProxy,
fileSystem: globals.fs,
logger: _logger,
iosDeploy: _iosDeploy,
iMobileDevice: _iMobileDevice,
platform: globals.platform,
));
} }
return devices; return devices;
} }
......
...@@ -89,13 +89,12 @@ class Plugin { ...@@ -89,13 +89,12 @@ class Plugin {
factory Plugin._fromMultiPlatformYaml( factory Plugin._fromMultiPlatformYaml(
String name, String name,
String path, String path,
dynamic pluginYaml, YamlMap pluginYaml,
List<String> dependencies, List<String> dependencies,
FileSystem fileSystem, FileSystem fileSystem,
bool isDirectDependency, bool isDirectDependency,
) { ) {
assert (pluginYaml != null && pluginYaml['platforms'] != null, assert (pluginYaml['platforms'] != null, 'Invalid multi-platform plugin specification $name.');
'Invalid multi-platform plugin specification $name.');
final YamlMap platformsYaml = pluginYaml['platforms'] as YamlMap; final YamlMap platformsYaml = pluginYaml['platforms'] as YamlMap;
assert (_validateMultiPlatformYaml(platformsYaml).isEmpty, assert (_validateMultiPlatformYaml(platformsYaml).isEmpty,
...@@ -190,7 +189,7 @@ class Plugin { ...@@ -190,7 +189,7 @@ class Plugin {
bool isDirectDependency, bool isDirectDependency,
) { ) {
final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{}; final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{};
final String pluginClass = pluginYaml['pluginClass'] as String; final String pluginClass = (pluginYaml as Map<dynamic, dynamic>)['pluginClass'] as String;
if (pluginYaml != null && pluginClass != null) { if (pluginYaml != null && pluginClass != null) {
final String androidPackage = pluginYaml['androidPackage'] as String; final String androidPackage = pluginYaml['androidPackage'] as String;
if (androidPackage != null) { if (androidPackage != null) {
......
...@@ -177,8 +177,8 @@ class _BufferedStreamController<T> { ...@@ -177,8 +177,8 @@ class _BufferedStreamController<T> {
_streamControllerInstance.add(event); _streamControllerInstance.add(event);
} else { } else {
_streamControllerInstance.addError( _streamControllerInstance.addError(
event.first as Object, (event as Iterable<dynamic>).first as Object,
event.last as StackTrace, (event as Iterable<dynamic>).last as StackTrace,
); );
} }
} }
......
...@@ -1118,8 +1118,9 @@ Future<OperationResult> _defaultReloadSourcesHelper( ...@@ -1118,8 +1118,9 @@ Future<OperationResult> _defaultReloadSourcesHelper(
// refactored, we'll probably need to send one hot reload/restart event // refactored, we'll probably need to send one hot reload/restart event
// per device to analytics. // per device to analytics.
firstReloadDetails.addAll(castStringKeyedMap(reloadReport.json['details'])); firstReloadDetails.addAll(castStringKeyedMap(reloadReport.json['details']));
final int loadedLibraryCount = reloadReport.json['details']['loadedLibraryCount'] as int; final Map<String, dynamic> details = reloadReport.json['details'] as Map<String, dynamic>;
final int finalLibraryCount = reloadReport.json['details']['finalLibraryCount'] as int; final int loadedLibraryCount = details['loadedLibraryCount'] as int;
final int finalLibraryCount = details['finalLibraryCount'] as int;
globals.printTrace('reloaded $loadedLibraryCount of $finalLibraryCount libraries'); globals.printTrace('reloaded $loadedLibraryCount of $finalLibraryCount libraries');
// reloadMessage = 'Reloaded $loadedLibraryCount of $finalLibraryCount libraries'; // reloadMessage = 'Reloaded $loadedLibraryCount of $finalLibraryCount libraries';
// Record time it took for the VM to reload the sources. // Record time it took for the VM to reload the sources.
......
...@@ -737,21 +737,24 @@ class BrowserManager { ...@@ -737,21 +737,24 @@ class BrowserManager {
/// The callback for handling messages received from the host page. /// The callback for handling messages received from the host page.
void _onMessage(dynamic message) { void _onMessage(dynamic message) {
switch (message['command'] as String) { assert(message is Map<String, dynamic>);
case 'ping': if (message is Map<String, dynamic>) {
break; switch (message['command'] as String) {
case 'restart': case 'ping':
_onRestartController.add(null); break;
break; case 'restart':
case 'resume': _onRestartController.add(null);
if (_pauseCompleter != null) { break;
_pauseCompleter.complete(); case 'resume':
} if (_pauseCompleter != null) {
break; _pauseCompleter.complete();
default: }
break;
default:
// Unreachable. // Unreachable.
assert(false); assert(false);
break; break;
}
} }
} }
......
...@@ -56,7 +56,7 @@ class VisualStudio { ...@@ -56,7 +56,7 @@ class VisualStudio {
if (_bestVisualStudioDetails[_catalogKey] == null) { if (_bestVisualStudioDetails[_catalogKey] == null) {
return null; return null;
} }
return _bestVisualStudioDetails[_catalogKey][_catalogDisplayVersionKey] as String?; return (_bestVisualStudioDetails[_catalogKey] as Map<String, dynamic>)[_catalogDisplayVersionKey] as String?;
} }
/// The directory where Visual Studio is installed. /// The directory where Visual Studio is installed.
......
...@@ -52,13 +52,14 @@ void main() { ...@@ -52,13 +52,14 @@ void main() {
expect(testLogger.statusText, isNotEmpty); expect(testLogger.statusText, isNotEmpty);
final dynamic jsonObject = json.decode(testLogger.statusText); final dynamic jsonObject = json.decode(testLogger.statusText);
expect(jsonObject, isMap); expect(jsonObject, const TypeMatcher<Map<String, dynamic>>());
if (jsonObject is Map<String, dynamic>) {
expect(jsonObject.containsKey('android-studio-dir'), true); expect(jsonObject.containsKey('android-studio-dir'), true);
expect(jsonObject['android-studio-dir'], isNotNull); expect(jsonObject['android-studio-dir'], isNotNull);
expect(jsonObject.containsKey('android-sdk'), true); expect(jsonObject.containsKey('android-sdk'), true);
expect(jsonObject['android-sdk'], isNotNull); expect(jsonObject['android-sdk'], isNotNull);
}
verifyNoAnalytics(); verifyNoAnalytics();
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
AndroidStudio: () => fakeAndroidStudio, AndroidStudio: () => fakeAndroidStudio,
......
...@@ -93,7 +93,7 @@ void main() { ...@@ -93,7 +93,7 @@ void main() {
expect(response['id'], 0); expect(response['id'], 0);
expect(response['result'], isNotEmpty); expect(response['result'], isNotEmpty);
expect(response['result']['platforms'], <String>{'macos'}); expect((response['result'] as Map<String, dynamic>)['platforms'], <String>{'macos'});
await responses.close(); await responses.close();
await commands.close(); await commands.close();
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
...@@ -111,7 +111,7 @@ void main() { ...@@ -111,7 +111,7 @@ void main() {
); );
globals.printError('daemon.logMessage test'); globals.printError('daemon.logMessage test');
final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> map) { final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> map) {
return map['event'] == 'daemon.logMessage' && map['params']['level'] == 'error'; return map['event'] == 'daemon.logMessage' && (map['params'] as Map<String, dynamic>)['level'] == 'error';
}); });
expect(response['id'], isNull); expect(response['id'], isNull);
expect(response['event'], 'daemon.logMessage'); expect(response['event'], 'daemon.logMessage');
...@@ -347,7 +347,7 @@ void main() { ...@@ -347,7 +347,7 @@ void main() {
unawaited(output.stream unawaited(output.stream
.firstWhere((Map<String, dynamic> request) => request['method'] == 'app.exposeUrl') .firstWhere((Map<String, dynamic> request) => request['method'] == 'app.exposeUrl')
.then((Map<String, dynamic> request) { .then((Map<String, dynamic> request) {
expect(request['params']['url'], equals(originalUrl)); expect((request['params'] as Map<String, dynamic>)['url'], equals(originalUrl));
input.add(<String, dynamic>{'id': request['id'], 'result': <String, dynamic>{'url': mappedUrl}}); input.add(<String, dynamic>{'id': request['id'], 'result': <String, dynamic>{'url': mappedUrl}});
}) })
); );
...@@ -370,9 +370,10 @@ void main() { ...@@ -370,9 +370,10 @@ void main() {
commands.add(<String, dynamic>{'id': 0, 'method': 'devtools.serve'}); commands.add(<String, dynamic>{'id': 0, 'method': 'devtools.serve'});
final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> response) => response['id'] == 0); final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> response) => response['id'] == 0);
expect(response['result'], isNotEmpty); final Map<String, dynamic> result = response['result'] as Map<String, dynamic>;
expect(response['result']['host'], '127.0.0.1'); expect(result, isNotEmpty);
expect(response['result']['port'], 1234); expect(result['host'], '127.0.0.1');
expect(result['port'], 1234);
await responses.close(); await responses.close();
await commands.close(); await commands.close();
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
...@@ -390,9 +391,10 @@ void main() { ...@@ -390,9 +391,10 @@ void main() {
commands.add(<String, dynamic>{'id': 0, 'method': 'devtools.serve'}); commands.add(<String, dynamic>{'id': 0, 'method': 'devtools.serve'});
final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> response) => response['id'] == 0); final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> response) => response['id'] == 0);
expect(response['result'], isNotEmpty); final Map<String, dynamic> result = response['result'] as Map<String, dynamic>;
expect(response['result']['host'], null); expect(result, isNotEmpty);
expect(response['result']['port'], null); expect(result['host'], null);
expect(result['port'], null);
await responses.close(); await responses.close();
await commands.close(); await commands.close();
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
......
...@@ -28,6 +28,7 @@ import 'package:process/process.dart'; ...@@ -28,6 +28,7 @@ import 'package:process/process.dart';
import 'package:pub_semver/pub_semver.dart'; import 'package:pub_semver/pub_semver.dart';
import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:yaml/yaml.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
...@@ -482,8 +483,9 @@ void main() { ...@@ -482,8 +483,9 @@ void main() {
// Expect the dependency on flutter_web_plugins exists // Expect the dependency on flutter_web_plugins exists
expect(pubspec.dependencies, contains('flutter_web_plugins')); expect(pubspec.dependencies, contains('flutter_web_plugins'));
// The platform is correctly registered // The platform is correctly registered
expect(pubspec.flutter['plugin']['platforms']['web']['pluginClass'], 'FlutterProjectWeb'); final YamlMap web = ((pubspec.flutter['plugin'] as YamlMap)['platforms'] as YamlMap)['web'] as YamlMap;
expect(pubspec.flutter['plugin']['platforms']['web']['fileName'], 'flutter_project_web.dart'); expect(web['pluginClass'], 'FlutterProjectWeb');
expect(web['fileName'], 'flutter_project_web.dart');
expect(logger.errorText, isNot(contains(_kNoPlatformsMessage))); expect(logger.errorText, isNot(contains(_kNoPlatformsMessage)));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
......
...@@ -90,47 +90,54 @@ void main() { ...@@ -90,47 +90,54 @@ void main() {
); );
expect(result['type'], 'apk'); expect(result['type'], 'apk');
final List<dynamic> resultChildren = result['children'] as List<dynamic>;
final Map<String, dynamic> androidManifestMap = result['children'][0] as Map<String, dynamic>; final Map<String, dynamic> androidManifestMap = resultChildren[0] as Map<String, dynamic>;
expect(androidManifestMap['n'], 'AndroidManifest.xml'); expect(androidManifestMap['n'], 'AndroidManifest.xml');
expect(androidManifestMap['value'], 6); expect(androidManifestMap['value'], 6);
final Map<String, dynamic> metaInfMap = result['children'][1] as Map<String, dynamic>; final Map<String, Object?> metaInfMap = resultChildren[1] as Map<String, Object?>;
final List<Map<String, Object?>> metaInfMapChildren = metaInfMap['children']! as List<Map<String, Object?>>;
expect(metaInfMap['n'], 'META-INF'); expect(metaInfMap['n'], 'META-INF');
expect(metaInfMap['value'], 10); expect(metaInfMap['value'], 10);
final Map<String, dynamic> certRsaMap = metaInfMap['children'][0] as Map<String, dynamic>; final Map<String, dynamic> certRsaMap = metaInfMapChildren[0];
expect(certRsaMap['n'], 'CERT.RSA'); expect(certRsaMap['n'], 'CERT.RSA');
expect(certRsaMap['value'], 5); expect(certRsaMap['value'], 5);
final Map<String, dynamic> certSfMap = metaInfMap['children'][1] as Map<String, dynamic>; final Map<String, dynamic> certSfMap = metaInfMapChildren[1];
expect(certSfMap['n'], 'CERT.SF'); expect(certSfMap['n'], 'CERT.SF');
expect(certSfMap['value'], 5); expect(certSfMap['value'], 5);
final Map<String, dynamic> libMap = result['children'][2] as Map<String, dynamic>; final Map<String, Object?> libMap = resultChildren[2] as Map<String, Object?>;
final List<Map<String, Object?>> libMapChildren = libMap['children']! as List<Map<String, Object?>>;
expect(libMap['n'], 'lib'); expect(libMap['n'], 'lib');
expect(libMap['value'], 12); expect(libMap['value'], 12);
final Map<String, dynamic> arm64Map = libMap['children'][0] as Map<String, dynamic>; final Map<String, Object?> arm64Map = libMapChildren[0];
final List<Map<String, Object?>> arn64MapChildren = arm64Map['children']! as List<Map<String, Object?>>;
expect(arm64Map['n'], 'arm64-v8a'); expect(arm64Map['n'], 'arm64-v8a');
expect(arm64Map['value'], 12); expect(arm64Map['value'], 12);
final Map<String, dynamic> libAppMap = arm64Map['children'][0] as Map<String, dynamic>; final Map<String, Object?> libAppMap = arn64MapChildren[0];
final List<dynamic> libAppMapChildren = libAppMap['children']! as List<dynamic>;
expect(libAppMap['n'], 'libxyzzyapp.so (Dart AOT)'); expect(libAppMap['n'], 'libxyzzyapp.so (Dart AOT)');
expect(libAppMap['value'], 6); expect(libAppMap['value'], 6);
expect(libAppMap['children'].length, 3); expect(libAppMapChildren.length, 3);
final Map<String, dynamic> internalMap = libAppMap['children'][0] as Map<String, dynamic>; final Map<String, Object?> internalMap = libAppMapChildren[0] as Map<String, Object?>;
final Map<String, dynamic> skipMap = internalMap['children'][0] as Map<String, dynamic>; final List<dynamic> internalMapChildren = internalMap['children']! as List<dynamic>;
final Map<String, Object?> skipMap = internalMapChildren[0] as Map<String, Object?>;
expect(skipMap['n'], 'skip'); expect(skipMap['n'], 'skip');
expect(skipMap['value'], 2400); expect(skipMap['value'], 2400);
final Map<String, dynamic> subListIterableMap = internalMap['children'][1] as Map<String, dynamic>; final Map<String, Object?> subListIterableMap = internalMapChildren[1] as Map<String, Object?>;
expect(subListIterableMap['n'], 'new SubListIterable.'); expect(subListIterableMap['n'], 'new SubListIterable.');
expect(subListIterableMap['value'], 3560); expect(subListIterableMap['value'], 3560);
final Map<String, dynamic> coreMap = libAppMap['children'][1] as Map<String, dynamic>; final Map<String, Object?> coreMap = libAppMapChildren[1] as Map<String, Object?>;
final Map<String, dynamic> rangeErrorMap = coreMap['children'][0] as Map<String, dynamic>; final List<dynamic> coreMapChildren = coreMap['children']! as List<dynamic>;
final Map<String, Object?> rangeErrorMap = coreMapChildren[0] as Map<String, Object?>;
expect(rangeErrorMap['n'], 'new RangeError.range'); expect(rangeErrorMap['n'], 'new RangeError.range');
expect(rangeErrorMap['value'], 3920); expect(rangeErrorMap['value'], 3920);
final Map<String, dynamic> stubsMap = libAppMap['children'][2] as Map<String, dynamic>; final Map<String, Object?> stubsMap = libAppMapChildren[2] as Map<String, Object?>;
final Map<String, dynamic> allocateMap = stubsMap['children'][0] as Map<String, dynamic>; final List<dynamic> stubsMapChildren = stubsMap['children']! as List<dynamic>;
final Map<String, Object?> allocateMap = stubsMapChildren[0] as Map<String, Object?>;
expect(allocateMap['n'], 'Allocate ArgumentError'); expect(allocateMap['n'], 'Allocate ArgumentError');
expect(allocateMap['value'], 4650); expect(allocateMap['value'], 4650);
final Map<String, dynamic> libFlutterMap = arm64Map['children'][1] as Map<String, dynamic>; final Map<String, Object?> libFlutterMap = arn64MapChildren[1];
expect(libFlutterMap['n'], 'libflutter.so (Flutter Engine)'); expect(libFlutterMap['n'], 'libflutter.so (Flutter Engine)');
expect(libFlutterMap['value'], 6); expect(libFlutterMap['value'], 6);
......
...@@ -104,9 +104,10 @@ void main() { ...@@ -104,9 +104,10 @@ void main() {
final Fingerprint fingerprint = Fingerprint.fromBuildInputs(const <String>['a.dart', 'b.dart'], fileSystem); final Fingerprint fingerprint = Fingerprint.fromBuildInputs(const <String>['a.dart', 'b.dart'], fileSystem);
final Map<String, dynamic>? jsonObject = castStringKeyedMap(json.decode(fingerprint.toJson())); final Map<String, dynamic>? jsonObject = castStringKeyedMap(json.decode(fingerprint.toJson()));
expect(jsonObject!['files'], hasLength(2)); final Map<String, dynamic> files = jsonObject!['files'] as Map<String, dynamic>;
expect(jsonObject['files']['a.dart'], '8a21a15fad560b799f6731d436c1b698'); expect(files, hasLength(2));
expect(jsonObject['files']['b.dart'], '6f144e08b58cd0925328610fad7ac07c'); expect(files['a.dart'], '8a21a15fad560b799f6731d436c1b698');
expect(files['b.dart'], '6f144e08b58cd0925328610fad7ac07c');
}); });
}); });
...@@ -124,10 +125,11 @@ void main() { ...@@ -124,10 +125,11 @@ void main() {
}); });
final Fingerprint fingerprint = Fingerprint.fromJson(jsonString); final Fingerprint fingerprint = Fingerprint.fromJson(jsonString);
final Map<String, dynamic>? content = castStringKeyedMap(json.decode(fingerprint.toJson())); final Map<String, dynamic>? content = castStringKeyedMap(json.decode(fingerprint.toJson()));
final Map<String, dynamic> files = content!['files'] as Map<String, dynamic>;
expect(content, hasLength(1)); expect(content, hasLength(1));
expect(content!['files'], hasLength(2)); expect(files, hasLength(2));
expect(content['files']['a.dart'], '8a21a15fad560b799f6731d436c1b698'); expect(files['a.dart'], '8a21a15fad560b799f6731d436c1b698');
expect(content['files']['b.dart'], '6f144e08b58cd0925328610fad7ac07c'); expect(files['b.dart'], '6f144e08b58cd0925328610fad7ac07c');
}); });
testWithoutContext('treats missing properties and files entries as if empty', () { testWithoutContext('treats missing properties and files entries as if empty', () {
final String jsonString = json.encode(<String, dynamic>{}); final String jsonString = json.encode(<String, dynamic>{});
......
...@@ -284,7 +284,7 @@ void main() { ...@@ -284,7 +284,7 @@ void main() {
version: 1.0.0+3 version: 1.0.0+3
''', logger: BufferLogger.test()); ''', logger: BufferLogger.test());
final FlutterProject project = FlutterProject(fileSystem.systemTempDirectory,manifest,manifest); final FlutterProject project = FlutterProject(fileSystem.systemTempDirectory,manifest,manifest);
final dynamic versionInfo = jsonDecode(project.getVersionInfo()); final Map<String, dynamic> versionInfo = jsonDecode(project.getVersionInfo()) as Map<String, dynamic>;
expect(versionInfo['app_name'],'test'); expect(versionInfo['app_name'],'test');
expect(versionInfo['version'],'1.0.0'); expect(versionInfo['version'],'1.0.0');
expect(versionInfo['build_number'],'3'); expect(versionInfo['build_number'],'3');
......
...@@ -81,7 +81,7 @@ void main() { ...@@ -81,7 +81,7 @@ void main() {
]); ]);
// contains all of the experiments in features.dart // contains all of the experiments in features.dart
expect(result.stdout.split('\n'), containsAll(<Matcher>[ expect((result.stdout as String).split('\n'), containsAll(<Matcher>[
for (final Feature feature in allFeatures) for (final Feature feature in allFeatures)
contains(feature.configSetting), contains(feature.configSetting),
])); ]));
......
...@@ -35,8 +35,8 @@ void main() { ...@@ -35,8 +35,8 @@ void main() {
.childDirectory('.dart_tool') .childDirectory('.dart_tool')
.childFile('package_config.json') .childFile('package_config.json')
.readAsStringSync()); .readAsStringSync());
final dynamic collection = jsonContent['packages'] final Map<String, dynamic> collection = ((jsonContent as Map<String, dynamic>)['packages'] as Iterable<dynamic>)
.firstWhere((dynamic e) => e['name'] == 'collection'); .firstWhere((dynamic entry) => (entry as Map<String, dynamic>)['name'] == 'collection') as Map<String, dynamic>;
expect( expect(
Uri.parse(collection['rootUri'] as String).isAbsolute, Uri.parse(collection['rootUri'] as String).isAbsolute,
isTrue, isTrue,
......
...@@ -190,6 +190,6 @@ bool _isHotReloadCompletionEvent(Map<String, dynamic> event) { ...@@ -190,6 +190,6 @@ bool _isHotReloadCompletionEvent(Map<String, dynamic> event) {
return event != null && return event != null &&
event['event'] == 'app.progress' && event['event'] == 'app.progress' &&
event['params'] != null && event['params'] != null &&
event['params']['progressId'] == 'hot.reload' && (event['params'] as Map<String, dynamic>)['progressId'] == 'hot.reload' &&
event['params']['finished'] == true; (event['params'] as Map<String, dynamic>)['finished'] == true;
} }
...@@ -387,11 +387,14 @@ abstract class FlutterTestDriver { ...@@ -387,11 +387,14 @@ abstract class FlutterTestDriver {
await subscription.cancel(); await subscription.cancel();
final StringBuffer error = StringBuffer(); final StringBuffer error = StringBuffer();
error.write('Received app.stop event while waiting for $interestingOccurrence\n\n$_errorBuffer'); error.write('Received app.stop event while waiting for $interestingOccurrence\n\n$_errorBuffer');
if (json['params'] != null && json['params']['error'] != null) { if (json['params'] != null) {
error.write('${json['params']['error']}\n\n'); final Map<String, dynamic> params = json['params'] as Map<String, dynamic>;
} if (params['error'] != null) {
if (json['params'] != null && json['params']['trace'] != null) { error.write('${params['error']}\n\n');
error.write('${json['params']['trace']}\n\n'); }
if (json['params'] != null && params['trace'] != null) {
error.write('${params['trace']}\n\n');
}
} }
response.completeError(Exception(error.toString())); response.completeError(Exception(error.toString()));
} }
...@@ -563,7 +566,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -563,7 +566,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
// _process.kill() (`flutter` is a shell script so _process itself is a // _process.kill() (`flutter` is a shell script so _process itself is a
// shell, not the flutter tool's Dart process). // shell, not the flutter tool's Dart process).
final Map<String, dynamic> connected = await _waitFor(event: 'daemon.connected'); final Map<String, dynamic> connected = await _waitFor(event: 'daemon.connected');
_processPid = connected['params']['pid'] as int; _processPid = (connected['params'] as Map<String, dynamic>)['pid'] as int;
// Set this up now, but we don't wait it yet. We want to make sure we don't // Set this up now, but we don't wait it yet. We want to make sure we don't
// miss it while waiting for debugPort below. // miss it while waiting for debugPort below.
...@@ -571,7 +574,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -571,7 +574,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
if (withDebugger) { if (withDebugger) {
final Map<String, dynamic> debugPort = await _waitFor(event: 'app.debugPort', timeout: appStartTimeout); final Map<String, dynamic> debugPort = await _waitFor(event: 'app.debugPort', timeout: appStartTimeout);
final String wsUriString = debugPort['params']['wsUri'] as String; final String wsUriString = (debugPort['params'] as Map<String, dynamic>)['wsUri'] as String;
_vmServiceWsUri = Uri.parse(wsUriString); _vmServiceWsUri = Uri.parse(wsUriString);
await connectToVmService(pauseOnExceptions: pauseOnExceptions); await connectToVmService(pauseOnExceptions: pauseOnExceptions);
if (!startPaused) { if (!startPaused) {
...@@ -588,7 +591,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -588,7 +591,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
// Now await the started event; if it had already happened the future will // Now await the started event; if it had already happened the future will
// have already completed. // have already completed.
_currentRunningAppId = (await started)['params']['appId'] as String; _currentRunningAppId = ((await started)['params'] as Map<String, dynamic>)['appId'] as String;
prematureExitGuard.complete(); prematureExitGuard.complete();
} on Exception catch (error, stackTrace) { } on Exception catch (error, stackTrace) {
prematureExitGuard.completeError(Exception(error.toString()), stackTrace); prematureExitGuard.completeError(Exception(error.toString()), stackTrace);
...@@ -618,10 +621,10 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -618,10 +621,10 @@ class FlutterRunTestDriver extends FlutterTestDriver {
} }
_debugPrint('Performing ${ pause ? "paused " : "" }${ fullRestart ? "hot restart" : "hot reload" }...'); _debugPrint('Performing ${ pause ? "paused " : "" }${ fullRestart ? "hot restart" : "hot reload" }...');
final dynamic hotReloadResponse = await _sendRequest( final Map<String, dynamic> hotReloadResponse = await _sendRequest(
'app.restart', 'app.restart',
<String, dynamic>{'appId': _currentRunningAppId, 'fullRestart': fullRestart, 'pause': pause, 'debounce': debounce, 'debounceDurationOverrideMs': debounceDurationOverrideMs}, <String, dynamic>{'appId': _currentRunningAppId, 'fullRestart': fullRestart, 'pause': pause, 'debounce': debounce, 'debounceDurationOverrideMs': debounceDurationOverrideMs},
); ) as Map<String, dynamic>;
_debugPrint('${fullRestart ? "Hot restart" : "Hot reload"} complete.'); _debugPrint('${fullRestart ? "Hot restart" : "Hot reload"} complete.');
if (hotReloadResponse == null || hotReloadResponse['code'] != 0) { if (hotReloadResponse == null || hotReloadResponse['code'] != 0) {
...@@ -760,8 +763,9 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -760,8 +763,9 @@ class FlutterTestTestDriver extends FlutterTestDriver {
_processPid = version['pid'] as int; _processPid = version['pid'] as int;
if (withDebugger) { if (withDebugger) {
final Map<String, dynamic> startedProcess = await _waitFor(event: 'test.startedProcess', timeout: appStartTimeout); final Map<String, dynamic> startedProcessParams =
final String vmServiceHttpString = startedProcess['params']['observatoryUri'] as String; (await _waitFor(event: 'test.startedProcess', timeout: appStartTimeout))['params'] as Map<String, dynamic>;
final String vmServiceHttpString = startedProcessParams['observatoryUri'] as String;
_vmServiceWsUri = Uri.parse(vmServiceHttpString).replace(scheme: 'ws', path: '/ws'); _vmServiceWsUri = Uri.parse(vmServiceHttpString).replace(scheme: 'ws', path: '/ws');
await connectToVmService(pauseOnExceptions: pauseOnExceptions); await connectToVmService(pauseOnExceptions: pauseOnExceptions);
// Allow us to run code before we start, eg. to set up breakpoints. // Allow us to run code before we start, eg. to set up breakpoints.
...@@ -824,7 +828,7 @@ Stream<String> transformToLines(Stream<List<int>> byteStream) { ...@@ -824,7 +828,7 @@ Stream<String> transformToLines(Stream<List<int>> byteStream) {
Map<String, dynamic> parseFlutterResponse(String line) { Map<String, dynamic> parseFlutterResponse(String line) {
if (line.startsWith('[') && line.endsWith(']') && line.length > 2) { if (line.startsWith('[') && line.endsWith(']') && line.length > 2) {
try { try {
final Map<String, dynamic> response = castStringKeyedMap(json.decode(line)[0]); final Map<String, dynamic> response = castStringKeyedMap((json.decode(line) as List<dynamic>)[0]);
return response; return response;
} on FormatException { } on FormatException {
// Not valid JSON, so likely some other output that was surrounded by [brackets] // Not valid JSON, so likely some other output that was surrounded by [brackets]
......
...@@ -19,18 +19,19 @@ void validatePubspecForPlugin({ ...@@ -19,18 +19,19 @@ void validatePubspecForPlugin({
}) { }) {
final FlutterManifest manifest = final FlutterManifest manifest =
FlutterManifest.createFromPath('$projectDir/pubspec.yaml', fileSystem: globals.fs, logger: globals.logger)!; FlutterManifest.createFromPath('$projectDir/pubspec.yaml', fileSystem: globals.fs, logger: globals.logger)!;
final YamlMap platformsMap = YamlMap.wrap(manifest.supportedPlatforms!); final YamlMap platformMaps = YamlMap.wrap(manifest.supportedPlatforms!);
for (final String platform in expectedPlatforms) { for (final String platform in expectedPlatforms) {
expect(platformsMap[platform], isNotNull); expect(platformMaps[platform], isNotNull);
expect(platformsMap[platform]['pluginClass'], pluginClass); final YamlMap platformMap = platformMaps[platform]! as YamlMap;
expect(platformMap['pluginClass'], pluginClass);
if (platform == 'android') { if (platform == 'android') {
expect(platformsMap[platform]['package'], androidIdentifier); expect(platformMap['package'], androidIdentifier);
} }
if (platform == 'web') { if (platform == 'web') {
expect(platformsMap[platform]['fileName'], webFileName); expect(platformMap['fileName'], webFileName);
} }
} }
for (final String platform in unexpectedPlatforms) { for (final String platform in unexpectedPlatforms) {
expect(platformsMap[platform], isNull); expect(platformMaps[platform], isNull);
} }
} }
...@@ -62,7 +62,7 @@ class Registrar extends BinaryMessenger { ...@@ -62,7 +62,7 @@ class Registrar extends BinaryMessenger {
/// compiling for the web. /// compiling for the web.
void registerMessageHandler() { void registerMessageHandler() {
// The `ui.webOnlySetPluginHandler` function below is only defined in the Web dart:ui. // The `ui.webOnlySetPluginHandler` function below is only defined in the Web dart:ui.
// ignore: undefined_function // ignore: undefined_function, avoid_dynamic_calls
ui.webOnlySetPluginHandler(handleFrameworkMessage); ui.webOnlySetPluginHandler(handleFrameworkMessage);
} }
......
...@@ -9,10 +9,13 @@ import 'package:flutter_driver/flutter_driver.dart'; ...@@ -9,10 +9,13 @@ import 'package:flutter_driver/flutter_driver.dart';
import 'common.dart'; import 'common.dart';
/// A callback to use with [integrationDriver].
typedef ScreenshotCallback = Future<bool> Function(String name, List<int> image);
/// Example Integration Test which can also run WebDriver command depending on /// Example Integration Test which can also run WebDriver command depending on
/// the requests coming from the test methods. /// the requests coming from the test methods.
Future<void> integrationDriver( Future<void> integrationDriver(
{FlutterDriver? driver, Function? onScreenshot}) async { {FlutterDriver? driver, ScreenshotCallback? onScreenshot}) async {
driver ??= await FlutterDriver.connect(); driver ??= await FlutterDriver.connect();
// Test states that it's waiting on web driver commands. // Test states that it's waiting on web driver commands.
// [DriverTestMessage] is converted to string since json format causes an // [DriverTestMessage] is converted to string since json format causes an
...@@ -28,11 +31,12 @@ Future<void> integrationDriver( ...@@ -28,11 +31,12 @@ Future<void> integrationDriver(
response.data!['web_driver_command'] != '${WebDriverCommandType.noop}') { response.data!['web_driver_command'] != '${WebDriverCommandType.noop}') {
final String? webDriverCommand = response.data!['web_driver_command'] as String?; final String? webDriverCommand = response.data!['web_driver_command'] as String?;
if (webDriverCommand == '${WebDriverCommandType.screenshot}') { if (webDriverCommand == '${WebDriverCommandType.screenshot}') {
assert(onScreenshot != null, 'screenshot command requires an onScreenshot callback');
// Use `driver.screenshot()` method to get a screenshot of the web page. // Use `driver.screenshot()` method to get a screenshot of the web page.
final List<int> screenshotImage = await driver.screenshot(); final List<int> screenshotImage = await driver.screenshot();
final String? screenshotName = response.data!['screenshot_name'] as String?; final String screenshotName = response.data!['screenshot_name']! as String;
final bool screenshotSuccess = await onScreenshot!(screenshotName, screenshotImage) as bool; final bool screenshotSuccess = await onScreenshot!(screenshotName, screenshotImage);
if (screenshotSuccess) { if (screenshotSuccess) {
jsonResponse = await driver.requestData(DriverTestMessage.complete().toString()); jsonResponse = await driver.requestData(DriverTestMessage.complete().toString());
} else { } else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment