diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart index fa30fe7a12e..67c38c68366 100644 --- a/packages/flutter_tools/lib/src/flutter_manifest.dart +++ b/packages/flutter_tools/lib/src/flutter_manifest.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:meta/meta.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:yaml/yaml.dart'; @@ -21,20 +19,15 @@ const Set _kValidPluginPlatforms = { /// A wrapper around the `flutter` section in the `pubspec.yaml` file. class FlutterManifest { - FlutterManifest._(this._logger); + FlutterManifest._({required Logger logger}) : _logger = logger; /// Returns an empty manifest. - factory FlutterManifest.empty({ @required Logger logger }) { - final FlutterManifest manifest = FlutterManifest._(logger); - manifest._descriptor = const {}; - manifest._flutterDescriptor = const {}; - return manifest; - } + factory FlutterManifest.empty({ required Logger logger }) = FlutterManifest._; /// Returns null on invalid manifest. Returns empty manifest on missing file. - static FlutterManifest createFromPath(String path, { - @required FileSystem fileSystem, - @required Logger logger, + static FlutterManifest? createFromPath(String path, { + required FileSystem fileSystem, + required Logger logger, }) { if (path == null || !fileSystem.isFileSync(path)) { return _createFromYaml(null, logger); @@ -45,28 +38,24 @@ class FlutterManifest { /// Returns null on missing or invalid manifest. @visibleForTesting - static FlutterManifest createFromString(String manifest, { @required Logger logger }) { + static FlutterManifest? createFromString(String manifest, { required Logger logger }) { return _createFromYaml(manifest != null ? loadYaml(manifest) : null, logger); } - static FlutterManifest _createFromYaml(dynamic yamlDocument, Logger logger) { + static FlutterManifest? _createFromYaml(Object? yamlDocument, Logger logger) { if (yamlDocument != null && !_validate(yamlDocument, logger)) { return null; } - final FlutterManifest pubspec = FlutterManifest._(logger); - final Map yamlMap = yamlDocument as YamlMap; + final FlutterManifest pubspec = FlutterManifest._(logger: logger); + final Map? yamlMap = yamlDocument as YamlMap?; if (yamlMap != null) { - pubspec._descriptor = yamlMap.cast(); - } else { - pubspec._descriptor = {}; + pubspec._descriptor = yamlMap.cast(); } - final Map flutterMap = pubspec._descriptor['flutter'] as Map; + final Map? flutterMap = pubspec._descriptor['flutter'] as Map?; if (flutterMap != null) { - pubspec._flutterDescriptor = flutterMap.cast(); - } else { - pubspec._flutterDescriptor = {}; + pubspec._flutterDescriptor = flutterMap.cast(); } return pubspec; @@ -75,29 +64,29 @@ class FlutterManifest { final Logger _logger; /// A map representation of the entire `pubspec.yaml` file. - Map _descriptor; + Map _descriptor = {}; /// A map representation of the `flutter` section in the `pubspec.yaml` file. - Map _flutterDescriptor; + Map _flutterDescriptor = {}; /// True if the `pubspec.yaml` file does not exist. bool get isEmpty => _descriptor.isEmpty; /// The string value of the top-level `name` property in the `pubspec.yaml` file. - String get appName => _descriptor['name'] as String ?? ''; + String get appName => _descriptor['name'] as String? ?? ''; // Flag to avoid printing multiple invalid version messages. bool _hasShowInvalidVersionMsg = false; /// The version String from the `pubspec.yaml` file. /// Can be null if it isn't set or has a wrong format. - String get appVersion { - final String verStr = _descriptor['version']?.toString(); + String? get appVersion { + final String? verStr = _descriptor['version']?.toString(); if (verStr == null) { return null; } - Version version; + Version? version; try { version = Version.parse(verStr); } on Exception { @@ -111,18 +100,20 @@ class FlutterManifest { /// The build version name from the `pubspec.yaml` file. /// Can be null if version isn't set or has a wrong format. - String get buildName { - if (appVersion != null && appVersion.contains('+')) { - return appVersion.split('+')?.elementAt(0); + String? get buildName { + final String? version = appVersion; + if (version != null && version.contains('+')) { + return version.split('+').elementAt(0); } - return appVersion; + return version; } /// The build version number from the `pubspec.yaml` file. /// Can be null if version isn't set or has a wrong format. - String get buildNumber { - if (appVersion != null && appVersion.contains('+')) { - final String value = appVersion.split('+')?.elementAt(1); + String? get buildNumber { + final String? version = appVersion; + if (version != null && version.contains('+')) { + final String value = version.split('+').elementAt(1); return value; } else { return null; @@ -130,15 +121,16 @@ class FlutterManifest { } bool get usesMaterialDesign { - return _flutterDescriptor['uses-material-design'] as bool ?? false; + return _flutterDescriptor['uses-material-design'] as bool? ?? false; } /// True if this Flutter module should use AndroidX dependencies. /// /// If false the deprecated Android Support library will be used. bool get usesAndroidX { - if (_flutterDescriptor.containsKey('module')) { - return _flutterDescriptor['module']['androidX'] as bool; + final Object? module = _flutterDescriptor['module']; + if (module is YamlMap) { + return module['androidX'] == true; } return false; } @@ -155,9 +147,13 @@ class FlutterManifest { /// licenses: /// - assets/foo_license.txt /// ``` - List get additionalLicenses => _flutterDescriptor.containsKey('licenses') - ? (_flutterDescriptor['licenses'] as YamlList).map((dynamic element) => element.toString()).toList() - : []; + List get additionalLicenses { + final Object? licenses = _flutterDescriptor['licenses']; + if (licenses is YamlList) { + return licenses.map((Object? element) => element.toString()).toList(); + } + return []; + } /// True if this manifest declares a Flutter module project. /// @@ -181,51 +177,60 @@ class FlutterManifest { /// Returns the Android package declared by this manifest in its /// module or plugin descriptor. Returns null, if there is no /// such declaration. - String get androidPackage { + String? get androidPackage { if (isModule) { - return _flutterDescriptor['module']['androidPackage'] as String; + final Object? module = _flutterDescriptor['module']; + if (module is YamlMap) { + return module['androidPackage'] as String?; + } } - if (supportedPlatforms == null) { + final Map? platforms = supportedPlatforms; + if (platforms == null) { // Pre-multi-platform plugin format if (isPlugin) { - final YamlMap plugin = _flutterDescriptor['plugin'] as YamlMap; - return plugin['androidPackage'] as String; + final YamlMap? plugin = _flutterDescriptor['plugin'] as YamlMap?; + return plugin?['androidPackage'] as String?; } return null; } - if (supportedPlatforms.containsKey('android')) { - return supportedPlatforms['android']['package'] as String; + if (platforms.containsKey('android')) { + final Object? android = platforms['android']; + if (android is YamlMap) { + return android['package'] as String?; + } } return null; } /// Returns the deferred components configuration if declared. Returns /// null if no deferred components are declared. - List get deferredComponents => _deferredComponents ??= computeDeferredComponents(); - List _deferredComponents; - List computeDeferredComponents() { + late final List? deferredComponents = computeDeferredComponents(); + List? computeDeferredComponents() { if (!_flutterDescriptor.containsKey('deferred-components')) { return null; } final List components = []; - if (_flutterDescriptor['deferred-components'] == null) { + final Object? deferredComponents = _flutterDescriptor['deferred-components']; + if (deferredComponents is! YamlList) { return components; } - for (final dynamic componentData in _flutterDescriptor['deferred-components']) { - final YamlMap component = componentData as YamlMap; + for (final Object? component in deferredComponents) { + if (component is! YamlMap) { + _logger.printError('Expected deferred component manifest to be a map.'); + continue; + } List assetsUri = []; - final List assets = component['assets'] as List; + final List? assets = component['assets'] as List?; if (assets == null) { assetsUri = const []; } else { - for (final Object asset in assets) { + for (final Object? asset in assets) { if (asset is! String || asset == null || asset == '') { _logger.printError('Deferred component asset manifest contains a null or empty uri.'); continue; } - final String stringAsset = asset as String; try { - assetsUri.add(Uri.parse(stringAsset)); + assetsUri.add(Uri.parse(asset)); } on FormatException { _logger.printError('Asset manifest contains invalid uri: $asset.'); } @@ -245,9 +250,12 @@ class FlutterManifest { /// Returns the iOS bundle identifier declared by this manifest in its /// module descriptor. Returns null if there is no such declaration. - String get iosBundleIdentifier { + String? get iosBundleIdentifier { if (isModule) { - return _flutterDescriptor['module']['iosBundleIdentifier'] as String; + final Object? module = _flutterDescriptor['module']; + if (module is YamlMap) { + return module['iosBundleIdentifier'] as String?; + } } return null; } @@ -255,58 +263,56 @@ class FlutterManifest { /// Gets the supported platforms. This only supports the new `platforms` format. /// /// If the plugin uses the legacy pubspec format, this method returns null. - Map get supportedPlatforms { + Map? get supportedPlatforms { if (isPlugin) { - final YamlMap plugin = _flutterDescriptor['plugin'] as YamlMap; - if (plugin.containsKey('platforms')) { - final YamlMap platformsMap = plugin['platforms'] as YamlMap; - return platformsMap.value.cast(); + final YamlMap? plugin = _flutterDescriptor['plugin'] as YamlMap?; + if (plugin?.containsKey('platforms') == true) { + final YamlMap? platformsMap = plugin!['platforms'] as YamlMap?; + return platformsMap?.value.cast(); } } return null; } /// Like [supportedPlatforms], but only returns the valid platforms that are supported in flutter plugins. - Map get validSupportedPlatforms { - final Map allPlatforms = supportedPlatforms; + Map? get validSupportedPlatforms { + final Map? allPlatforms = supportedPlatforms; if (allPlatforms == null) { return null; } - final Map platforms = {}..addAll(supportedPlatforms); - platforms.removeWhere((String key, dynamic _) => !_kValidPluginPlatforms.contains(key)); + final Map platforms = {}..addAll(allPlatforms); + platforms.removeWhere((String key, Object? _) => !_kValidPluginPlatforms.contains(key)); if (platforms.isEmpty) { return null; } return platforms; } - List> get fontsDescriptor { + List> get fontsDescriptor { return fonts.map((Font font) => font.descriptor).toList(); } - List> get _rawFontsDescriptor { - final List fontList = _flutterDescriptor['fonts'] as List; + List> get _rawFontsDescriptor { + final List? fontList = _flutterDescriptor['fonts'] as List?; return fontList == null - ? const >[] - : fontList.map>(castStringKeyedMap).toList(); + ? const >[] + : fontList.map?>(castStringKeyedMap).whereType>().toList(); } - List get assets => _assets ??= _computeAssets(); - List _assets; + late final List assets = _computeAssets(); List _computeAssets() { - final List assets = _flutterDescriptor['assets'] as List; + final List? assets = _flutterDescriptor['assets'] as List?; if (assets == null) { return const []; } final List results = []; - for (final Object asset in assets) { + for (final Object? asset in assets) { if (asset is! String || asset == null || asset == '') { _logger.printError('Asset manifest contains a null or empty uri.'); continue; } - final String stringAsset = asset as String; try { - results.add(Uri(pathSegments: stringAsset.split('/'))); + results.add(Uri(pathSegments: asset.split('/'))); } on FormatException { _logger.printError('Asset manifest contains invalid uri: $asset.'); } @@ -314,12 +320,7 @@ class FlutterManifest { return results; } - List _fonts; - - List get fonts { - _fonts ??= _extractFonts(); - return _fonts; - } + late final List fonts = _extractFonts(); List _extractFonts() { if (!_flutterDescriptor.containsKey('fonts')) { @@ -327,9 +328,9 @@ class FlutterManifest { } final List fonts = []; - for (final Map fontFamily in _rawFontsDescriptor) { - final YamlList fontFiles = fontFamily['fonts'] as YamlList; - final String familyName = fontFamily['family'] as String; + for (final Map fontFamily in _rawFontsDescriptor) { + final YamlList? fontFiles = fontFamily['fonts'] as YamlList?; + final String? familyName = fontFamily['family'] as String?; if (familyName == null) { _logger.printError('Warning: Missing family name for font.', emphasis: true); continue; @@ -340,8 +341,8 @@ class FlutterManifest { } final List fontAssets = []; - for (final Map fontFile in fontFiles.cast>()) { - final String asset = fontFile['asset'] as String; + for (final Map fontFile in fontFiles.cast>()) { + final String? asset = fontFile['asset'] as String?; if (asset == null) { _logger.printError('Warning: Missing asset in fonts for $familyName', emphasis: true); continue; @@ -349,12 +350,12 @@ class FlutterManifest { fontAssets.add(FontAsset( Uri.parse(asset), - weight: fontFile['weight'] as int, - style: fontFile['style'] as String, + weight: fontFile['weight'] as int?, + style: fontFile['style'] as String?, )); } if (fontAssets.isNotEmpty) { - fonts.add(Font(fontFamily['family'] as String, fontAssets)); + fonts.add(Font(familyName, fontAssets)); } } return fonts; @@ -367,17 +368,16 @@ class FlutterManifest { /// /// This allows generated source code to be imported using a package /// alias. - bool get generateSyntheticPackage => _generateSyntheticPackage ??= _computeGenerateSyntheticPackage(); - bool _generateSyntheticPackage; + late final bool generateSyntheticPackage = _computeGenerateSyntheticPackage(); bool _computeGenerateSyntheticPackage() { if (!_flutterDescriptor.containsKey('generate')) { return false; } - final Object value = _flutterDescriptor['generate']; + final Object? value = _flutterDescriptor['generate']; if (value is! bool) { return false; } - return value as bool; + return value; } } @@ -390,10 +390,10 @@ class Font { final String familyName; final List fontAssets; - Map get descriptor { - return { + Map get descriptor { + return { 'family': familyName, - 'fonts': fontAssets.map>((FontAsset a) => a.descriptor).toList(), + 'fonts': fontAssets.map>((FontAsset a) => a.descriptor).toList(), }; } @@ -406,11 +406,11 @@ class FontAsset { : assert(assetUri != null); final Uri assetUri; - final int weight; - final String style; + final int? weight; + final String? style; - Map get descriptor { - final Map descriptor = {}; + Map get descriptor { + final Map descriptor = {}; if (weight != null) { descriptor['weight'] = weight; } @@ -428,17 +428,17 @@ class FontAsset { } -bool _validate(dynamic manifest, Logger logger) { +bool _validate(Object? manifest, Logger logger) { final List errors = []; if (manifest is! YamlMap) { errors.add('Expected YAML map'); } else { - for (final MapEntry kvp in (manifest as YamlMap).entries) { + for (final MapEntry kvp in manifest.entries) { if (kvp.key is! String) { errors.add('Expected YAML key to be a string, but got ${kvp.key}.'); continue; } - switch (kvp.key as String) { + switch (kvp.key as String?) { case 'name': if (kvp.value is! String) { errors.add('Expected "${kvp.key}" to be a string, but got ${kvp.value}.'); @@ -451,7 +451,7 @@ bool _validate(dynamic manifest, Logger logger) { if (kvp.value is! YamlMap) { errors.add('Expected "${kvp.key}" section to be an object or null, but got ${kvp.value}.'); } else { - _validateFlutter(kvp.value as YamlMap, errors); + _validateFlutter(kvp.value as YamlMap?, errors); } break; default: @@ -470,62 +470,64 @@ bool _validate(dynamic manifest, Logger logger) { return true; } -void _validateFlutter(YamlMap yaml, List errors) { +void _validateFlutter(YamlMap? yaml, List errors) { if (yaml == null || yaml.entries == null) { return; } - for (final MapEntry kvp in yaml.entries) { - if (kvp.key is! String) { - errors.add('Expected YAML key to be a string, but got ${kvp.key} (${kvp.value.runtimeType}).'); + for (final MapEntry kvp in yaml.entries) { + final Object? yamlKey = kvp.key; + final Object? yamlValue = kvp.value; + if (yamlKey is! String) { + errors.add('Expected YAML key to be a string, but got $yamlKey (${yamlValue.runtimeType}).'); continue; } - switch (kvp.key as String) { + switch (yamlKey) { case 'uses-material-design': - if (kvp.value is! bool) { - errors.add('Expected "${kvp.key}" to be a bool, but got ${kvp.value} (${kvp.value.runtimeType}).'); + if (yamlValue is! bool) { + errors.add('Expected "$yamlKey" to be a bool, but got $yamlValue (${yamlValue.runtimeType}).'); } break; case 'assets': - if (kvp.value is! YamlList || kvp.value[0] is! String) { - errors.add('Expected "${kvp.key}" to be a list, but got ${kvp.value} (${kvp.value.runtimeType}).'); + if (yamlValue is! YamlList || yamlValue[0] is! String) { + errors.add('Expected "$yamlKey" to be a list, but got $yamlValue (${yamlValue.runtimeType}).'); } break; case 'fonts': - if (kvp.value is! YamlList || kvp.value[0] is! YamlMap) { - errors.add('Expected "${kvp.key}" to be a list, but got ${kvp.value} (${kvp.value.runtimeType}).'); + if (yamlValue is! YamlList || yamlValue[0] is! YamlMap) { + errors.add('Expected "$yamlKey" to be a list, but got $yamlValue (${yamlValue.runtimeType}).'); } else { - _validateFonts(kvp.value as YamlList, errors); + _validateFonts(yamlValue, errors); } break; case 'licenses': - final dynamic value = kvp.value; - if (value is YamlList) { - _validateListType(value, errors, '"${kvp.key}"', 'files'); + if (yamlValue is YamlList) { + _validateListType(yamlValue, errors, '"$yamlKey"', 'files'); } else { - errors.add('Expected "${kvp.key}" to be a list of files, but got $value (${value.runtimeType})'); + errors.add('Expected "$yamlKey" to be a list of files, but got $yamlValue (${yamlValue.runtimeType})'); } break; case 'module': - if (kvp.value is! YamlMap) { - errors.add('Expected "${kvp.key}" to be an object, but got ${kvp.value} (${kvp.value.runtimeType}).'); + if (yamlValue is! YamlMap) { + errors.add('Expected "$yamlKey" to be an object, but got $yamlValue (${yamlValue.runtimeType}).'); + break; } - if (kvp.value['androidX'] != null && kvp.value['androidX'] is! bool) { + if (yamlValue['androidX'] != null && yamlValue['androidX'] is! bool) { errors.add('The "androidX" value must be a bool if set.'); } - if (kvp.value['androidPackage'] != null && kvp.value['androidPackage'] is! String) { + if (yamlValue['androidPackage'] != null && yamlValue['androidPackage'] is! String) { errors.add('The "androidPackage" value must be a string if set.'); } - if (kvp.value['iosBundleIdentifier'] != null && kvp.value['iosBundleIdentifier'] is! String) { + if (yamlValue['iosBundleIdentifier'] != null && yamlValue['iosBundleIdentifier'] is! String) { errors.add('The "iosBundleIdentifier" section must be a string if set.'); } break; case 'plugin': - if (kvp.value is! YamlMap || kvp.value == null) { - errors.add('Expected "${kvp.key}" to be an object, but got ${kvp.value} (${kvp.value.runtimeType}).'); + if (yamlValue is! YamlMap || yamlValue == null) { + errors.add('Expected "$yamlKey" to be an object, but got $yamlValue (${yamlValue.runtimeType}).'); break; } - final List pluginErrors = Plugin.validatePluginYaml(kvp.value as YamlMap); + final List pluginErrors = Plugin.validatePluginYaml(yamlValue); errors.addAll(pluginErrors); break; case 'generate': @@ -534,7 +536,7 @@ void _validateFlutter(YamlMap yaml, List errors) { _validateDeferredComponents(kvp, errors); break; default: - errors.add('Unexpected child "${kvp.key}" found under "flutter".'); + errors.add('Unexpected child "$yamlKey" found under "flutter".'); break; } } @@ -548,30 +550,34 @@ void _validateListType(YamlList yamlList, List errors, String context } } -void _validateDeferredComponents(MapEntry kvp, List errors) { - if (kvp.value != null && (kvp.value is! YamlList || kvp.value[0] is! YamlMap)) { - errors.add('Expected "${kvp.key}" to be a list, but got ${kvp.value} (${kvp.value.runtimeType}).'); - } else if (kvp.value != null) { - for (int i = 0; i < (kvp.value as YamlList).length; i++) { - if (kvp.value[i] is! YamlMap) { - errors.add('Expected the $i element in "${kvp.key}" to be a map, but got ${kvp.value[i]} (${kvp.value[i].runtimeType}).'); +void _validateDeferredComponents(MapEntry kvp, List errors) { + final Object? yamlList = kvp.value; + if (yamlList != null && (yamlList is! YamlList || yamlList[0] is! YamlMap)) { + errors.add('Expected "${kvp.key}" to be a list, but got $yamlList (${yamlList.runtimeType}).'); + } else if (yamlList is YamlList) { + for (int i = 0; i < yamlList.length; i++) { + final Object? valueMap = yamlList[i]; + if (valueMap is! YamlMap) { + errors.add('Expected the $i element in "${kvp.key}" to be a map, but got ${yamlList[i]} (${yamlList[i].runtimeType}).'); continue; } - if (!(kvp.value[i] as YamlMap).containsKey('name') || kvp.value[i]['name'] is! String) { + if (!valueMap.containsKey('name') || valueMap['name'] is! String) { errors.add('Expected the $i element in "${kvp.key}" to have required key "name" of type String'); } - if ((kvp.value[i] as YamlMap).containsKey('libraries')) { - if (kvp.value[i]['libraries'] is! YamlList) { - errors.add('Expected "libraries" key in the $i element of "${kvp.key}" to be a list, but got ${kvp.value[i]['libraries']} (${kvp.value[i]['libraries'].runtimeType}).'); + if (valueMap.containsKey('libraries')) { + final Object? libraries = valueMap['libraries']; + if (libraries is! YamlList) { + errors.add('Expected "libraries" key in the $i element of "${kvp.key}" to be a list, but got $libraries (${libraries.runtimeType}).'); } else { - _validateListType(kvp.value[i]['libraries'] as YamlList, errors, '"libraries" key in the $i element of "${kvp.key}"', 'dart library Strings'); + _validateListType(libraries, errors, '"libraries" key in the $i element of "${kvp.key}"', 'dart library Strings'); } } - if ((kvp.value[i] as YamlMap).containsKey('assets')) { - if (kvp.value[i]['assets'] is! YamlList) { - errors.add('Expected "assets" key in the $i element of "${kvp.key}" to be a list, but got ${kvp.value[i]['assets']} (${kvp.value[i]['assets'].runtimeType}).'); + if (valueMap.containsKey('assets')) { + final Object? assets = valueMap['assets']; + if (assets is! YamlList) { + errors.add('Expected "assets" key in the $i element of "${kvp.key}" to be a list, but got $assets (${assets.runtimeType}).'); } else { - _validateListType(kvp.value[i]['assets'] as YamlList, errors, '"assets" key in the $i element of "${kvp.key}"', 'file paths'); + _validateListType(assets, errors, '"assets" key in the $i element of "${kvp.key}"', 'file paths'); } } } @@ -585,13 +591,12 @@ void _validateFonts(YamlList fonts, List errors) { const Set fontWeights = { 100, 200, 300, 400, 500, 600, 700, 800, 900, }; - for (final dynamic fontListEntry in fonts) { - if (fontListEntry is! YamlMap) { - errors.add('Unexpected child "$fontListEntry" found under "fonts". Expected a map.'); + for (final Object? fontMap in fonts) { + if (fontMap is! YamlMap) { + errors.add('Unexpected child "$fontMap" found under "fonts". Expected a map.'); continue; } - final YamlMap fontMap = fontListEntry as YamlMap; - for (final dynamic key in fontMap.keys.where((dynamic key) => key != 'family' && key != 'fonts')) { + for (final Object? key in fontMap.keys.where((Object? key) => key != 'family' && key != 'fonts')) { errors.add('Unexpected child "$key" found under "fonts".'); } if (fontMap['family'] != null && fontMap['family'] is! String) { @@ -603,17 +608,17 @@ void _validateFonts(YamlList fonts, List errors) { errors.add('Expected "fonts" to either be null or a list.'); continue; } - for (final dynamic fontListItem in fontMap['fonts']) { - if (fontListItem is! YamlMap) { + for (final Object? fontMapList in fontMap['fonts']) { + if (fontMapList is! YamlMap) { errors.add('Expected "fonts" to be a list of maps.'); continue; } - final YamlMap fontMapList = fontListItem as YamlMap; - for (final MapEntry kvp in fontMapList.entries) { - if (kvp.key is! String) { - errors.add('Expected "${kvp.key}" under "fonts" to be a string.'); + for (final MapEntry kvp in fontMapList.entries) { + final Object? fontKey = kvp.key; + if (fontKey is! String) { + errors.add('Expected "$fontKey" under "fonts" to be a string.'); } - switch(kvp.key as String) { + switch(fontKey) { case 'asset': if (kvp.value is! String) { errors.add('Expected font asset ${kvp.value} ((${kvp.value.runtimeType})) to be a string.'); @@ -630,7 +635,7 @@ void _validateFonts(YamlList fonts, List errors) { } break; default: - errors.add('Unexpected key ${kvp.key} ((${kvp.value.runtimeType})) under font.'); + errors.add('Unexpected key $fontKey ((${kvp.value.runtimeType})) under font.'); break; } } diff --git a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart index eb2a0712b46..709ab208309 100644 --- a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart +++ b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart @@ -2,17 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:file/file.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/base/deferred_component.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/flutter_manifest.dart'; import '../src/common.dart'; -import '../src/context.dart'; void main() { setUpAll(() { @@ -24,7 +22,7 @@ void main() { final FlutterManifest flutterManifest = FlutterManifest.createFromString( '', logger: logger, - ); + )!; expect(flutterManifest.isEmpty, true); expect(flutterManifest.appName, ''); @@ -56,7 +54,7 @@ dependencies: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest, isNotNull); expect(flutterManifest.isEmpty, false); @@ -80,7 +78,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.usesMaterialDesign, true); }); @@ -98,7 +96,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.generateSyntheticPackage, true); }); @@ -116,7 +114,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.generateSyntheticPackage, false); }); @@ -134,7 +132,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.generateSyntheticPackage, false); }); @@ -155,7 +153,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.assets, [ Uri.parse('a/foo'), @@ -180,7 +178,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fonts, hasLength(1)); expect(flutterManifest.fonts.single, matchesFont( @@ -217,7 +215,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fonts, hasLength(1)); expect(flutterManifest.fonts.single, matchesFont( @@ -257,7 +255,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fonts, hasLength(1)); expect(flutterManifest.fonts.single, matchesFont( @@ -303,7 +301,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fonts, hasLength(2)); expect(flutterManifest.fonts, containsAll([ @@ -365,7 +363,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fontsDescriptor, [ { @@ -411,7 +409,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fonts, hasLength(1)); expect(flutterManifest.fonts, containsAll([ @@ -454,7 +452,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fonts, hasLength(1)); expect(flutterManifest.fonts, containsAll([ @@ -493,7 +491,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.fontsDescriptor, isEmpty); expect(flutterManifest.fonts, isEmpty); @@ -511,7 +509,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isEmpty, false); expect(flutterManifest.isModule, false); @@ -532,7 +530,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isModule, true); expect(flutterManifest.androidPackage, 'com.example'); @@ -550,7 +548,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isPlugin, true); expect(flutterManifest.androidPackage, 'com.example'); @@ -571,7 +569,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isPlugin, true); expect(flutterManifest.androidPackage, 'com.example'); @@ -591,20 +589,20 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isPlugin, true); expect(flutterManifest.androidPackage, isNull); }); - testUsingContext('FlutterManifest handles an invalid plugin declaration', () { + testWithoutContext('FlutterManifest handles an invalid plugin declaration', () { const String manifest = ''' name: test flutter: plugin: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -624,7 +622,7 @@ dependencies: flutter: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -646,7 +644,7 @@ dependencies: flutter: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -668,7 +666,7 @@ dependencies: flutter: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -690,7 +688,7 @@ dependencies: flutter: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -712,7 +710,7 @@ dependencies: flutter: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -733,7 +731,7 @@ dependencies: flutter: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -759,7 +757,7 @@ flutter: -asset: a/bar '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -783,7 +781,7 @@ flutter: - asset '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -807,7 +805,7 @@ flutter: -asset: a/bar '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -832,7 +830,7 @@ flutter: - string '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -857,7 +855,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; final List assets = flutterManifest.assets; expect(logger.errorText, contains('Asset manifest contains a null or empty uri.')); @@ -881,7 +879,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; final List assets = flutterManifest.assets; expect(assets, hasLength(3)); @@ -903,7 +901,7 @@ flutter: - uses-material-design: true '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -932,7 +930,7 @@ flutter: 'pubspec.yaml', fileSystem: fileSystem, logger: logger, - ); + )!; expect(flutterManifest.isEmpty, false); }); @@ -953,7 +951,7 @@ flutter: 'pubspec.yaml', fileSystem: fileSystem, logger: logger, - ); + )!; expect(flutterManifest.isEmpty, false); }); @@ -969,7 +967,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isPlugin, true); expect(flutterManifest.supportedPlatforms, null); @@ -988,7 +986,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isPlugin, true); expect(flutterManifest.validSupportedPlatforms, null); @@ -1009,12 +1007,13 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isPlugin, true); - expect(flutterManifest.validSupportedPlatforms['ios'], + final Map validSupportedPlatforms = flutterManifest.validSupportedPlatforms!; + expect(validSupportedPlatforms['ios'], {'pluginClass': 'SomeClass'}); - expect(flutterManifest.validSupportedPlatforms['some_platform'], + expect(validSupportedPlatforms['some_platform'], isNull); }); @@ -1034,12 +1033,13 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.isPlugin, true); - expect(flutterManifest.supportedPlatforms['ios'], + final Map validSupportedPlatforms = flutterManifest.validSupportedPlatforms!; + expect(validSupportedPlatforms['ios'], {'pluginClass': 'SomeClass'}); - expect(flutterManifest.supportedPlatforms['android'], + expect(validSupportedPlatforms['android'], {'pluginClass': 'SomeClass', 'package': 'com.example'}); }); @@ -1054,7 +1054,7 @@ flutter: - android '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1076,7 +1076,7 @@ flutter: pluginClass: SomeClass '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1100,7 +1100,7 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest.additionalLicenses, ['foo.txt']); }); @@ -1115,7 +1115,7 @@ flutter: licenses: foo.txt '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1136,7 +1136,7 @@ flutter: - bar: fizz '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1163,15 +1163,16 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest, isNotNull); - expect(flutterManifest.deferredComponents.length, 1); - expect(flutterManifest.deferredComponents[0].name, 'component1'); - expect(flutterManifest.deferredComponents[0].libraries.length, 1); - expect(flutterManifest.deferredComponents[0].libraries[0], 'lib1'); - expect(flutterManifest.deferredComponents[0].assets.length, 1); - expect(flutterManifest.deferredComponents[0].assets[0].path, 'path/to/asset.jpg'); + final List deferredComponents = flutterManifest.deferredComponents!; + expect(deferredComponents.length, 1); + expect(deferredComponents[0].name, 'component1'); + expect(deferredComponents[0].libraries.length, 1); + expect(deferredComponents[0].libraries[0], 'lib1'); + expect(deferredComponents[0].assets.length, 1); + expect(deferredComponents[0].assets[0].path, 'path/to/asset.jpg'); }); testWithoutContext('FlutterManifest parses multiple deferred components', () async { @@ -1198,22 +1199,23 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest, isNotNull); - expect(flutterManifest.deferredComponents.length, 2); - expect(flutterManifest.deferredComponents[0].name, 'component1'); - expect(flutterManifest.deferredComponents[0].libraries.length, 1); - expect(flutterManifest.deferredComponents[0].libraries[0], 'lib1'); - expect(flutterManifest.deferredComponents[0].assets.length, 1); - expect(flutterManifest.deferredComponents[0].assets[0].path, 'path/to/asset.jpg'); + final List deferredComponents = flutterManifest.deferredComponents!; + expect(deferredComponents.length, 2); + expect(deferredComponents[0].name, 'component1'); + expect(deferredComponents[0].libraries.length, 1); + expect(deferredComponents[0].libraries[0], 'lib1'); + expect(deferredComponents[0].assets.length, 1); + expect(deferredComponents[0].assets[0].path, 'path/to/asset.jpg'); - expect(flutterManifest.deferredComponents[1].name, 'component2'); - expect(flutterManifest.deferredComponents[1].libraries.length, 2); - expect(flutterManifest.deferredComponents[1].libraries[0], 'lib2'); - expect(flutterManifest.deferredComponents[1].libraries[1], 'lib3'); - expect(flutterManifest.deferredComponents[1].assets.length, 1); - expect(flutterManifest.deferredComponents[1].assets[0].path, 'path/to/asset2.jpg'); + expect(deferredComponents[1].name, 'component2'); + expect(deferredComponents[1].libraries.length, 2); + expect(deferredComponents[1].libraries[0], 'lib2'); + expect(deferredComponents[1].libraries[1], 'lib3'); + expect(deferredComponents[1].assets.length, 1); + expect(deferredComponents[1].assets[0].path, 'path/to/asset2.jpg'); }); testWithoutContext('FlutterManifest parses empty deferred components', () async { @@ -1229,10 +1231,10 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest, isNotNull); - expect(flutterManifest.deferredComponents.length, 0); + expect(flutterManifest.deferredComponents!.length, 0); }); testWithoutContext('FlutterManifest deferred component requires name', () async { @@ -1247,7 +1249,7 @@ flutter: - lib1 '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1266,7 +1268,7 @@ flutter: deferred-components: blah '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1287,7 +1289,7 @@ flutter: libraries: blah '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1309,7 +1311,7 @@ flutter: - not-a-string: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1331,7 +1333,7 @@ flutter: - not-a-string: '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1355,7 +1357,7 @@ flutter: - woo '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1382,7 +1384,7 @@ flutter: - woo '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1403,7 +1405,7 @@ flutter: assets: blah '''; final BufferLogger logger = BufferLogger.test(); - final FlutterManifest flutterManifest = FlutterManifest.createFromString( + final FlutterManifest? flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, ); @@ -1430,23 +1432,24 @@ flutter: final FlutterManifest flutterManifest = FlutterManifest.createFromString( manifest, logger: logger, - ); + )!; expect(flutterManifest, isNotNull); - expect(flutterManifest.deferredComponents.length, 1); - expect(flutterManifest.deferredComponents[0].name, 'component1'); - expect(flutterManifest.deferredComponents[0].libraries.length, 0); - expect(flutterManifest.deferredComponents[0].assets.length, 3); - expect(flutterManifest.deferredComponents[0].assets[0].path, 'path/to/asset1.jpg'); - expect(flutterManifest.deferredComponents[0].assets[1].path, 'path/to/asset2.jpg'); - expect(flutterManifest.deferredComponents[0].assets[2].path, 'path/to/asset3.jpg'); + final List deferredComponents = flutterManifest.deferredComponents!; + expect(deferredComponents.length, 1); + expect(deferredComponents[0].name, 'component1'); + expect(deferredComponents[0].libraries.length, 0); + expect(deferredComponents[0].assets.length, 3); + expect(deferredComponents[0].assets[0].path, 'path/to/asset1.jpg'); + expect(deferredComponents[0].assets[1].path, 'path/to/asset2.jpg'); + expect(deferredComponents[0].assets[2].path, 'path/to/asset3.jpg'); }); } Matcher matchesManifest({ - String appVersion, - String buildName, - String buildNumber, + String? appVersion, + String? buildName, + String? buildNumber, }) { return isA() .having((FlutterManifest manifest) => manifest.appVersion, 'appVersion', appVersion) @@ -1455,9 +1458,9 @@ Matcher matchesManifest({ } Matcher matchesFontAsset({ - Uri assetUri, - int weight, - String style, + required Uri assetUri, + int? weight, + String? style, }) { return isA() .having((FontAsset fontAsset) => fontAsset.assetUri, 'assetUri', assetUri) @@ -1466,9 +1469,9 @@ Matcher matchesFontAsset({ } Matcher matchesFont({ - Map descriptor, - String familyName, - List fontAssets, + required Map descriptor, + required String familyName, + required List fontAssets, }) { return isA() .having((Font font) => font.descriptor, 'descriptor', descriptor)