diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart index aa3e9b4898..ec18de191c 100644 --- a/packages/flutter_tools/lib/src/flutter_manifest.dart +++ b/packages/flutter_tools/lib/src/flutter_manifest.dart @@ -40,16 +40,16 @@ class FlutterManifest { /// Returns null on missing or invalid manifest @visibleForTesting static FlutterManifest createFromString(String manifest, { @required Logger logger }) { - return _createFromYaml(loadYaml(manifest) as YamlMap, logger); + return _createFromYaml(manifest != null ? loadYaml(manifest) : null, logger); } - static FlutterManifest _createFromYaml(YamlMap yamlDocument, Logger logger) { - final FlutterManifest pubspec = FlutterManifest._(logger); + static FlutterManifest _createFromYaml(dynamic yamlDocument, Logger logger) { if (yamlDocument != null && !_validate(yamlDocument, logger)) { return null; } - final Map yamlMap = yamlDocument; + final FlutterManifest pubspec = FlutterManifest._(logger); + final Map yamlMap = yamlDocument as YamlMap; if (yamlMap != null) { pubspec._descriptor = yamlMap.cast(); } else { @@ -332,32 +332,36 @@ String buildSchemaPath(FileSystem fileSystem) { /// This method should be kept in sync with the schema in /// `$FLUTTER_ROOT/packages/flutter_tools/schema/pubspec_yaml.json`, /// but avoid introducing dependencies on packages for simple validation. -bool _validate(YamlMap manifest, Logger logger) { +bool _validate(dynamic manifest, Logger logger) { final List errors = []; - 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) { - case 'name': - if (kvp.value is! String) { - errors.add('Expected "${kvp.key}" to be a string, but got ${kvp.value}.'); - } - break; - case 'flutter': - if (kvp.value == null) { - continue; - } - 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); - } - break; - default: + if (manifest is! YamlMap) { + errors.add('Expected YAML map'); + } else { + for (final MapEntry kvp in (manifest as YamlMap).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) { + case 'name': + if (kvp.value is! String) { + errors.add('Expected "${kvp.key}" to be a string, but got ${kvp.value}.'); + } + break; + case 'flutter': + if (kvp.value == null) { + continue; + } + 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); + } + break; + default: // additionalProperties are allowed. - break; + 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 ace5077ae2..4d11c5ee79 100644 --- a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart +++ b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart @@ -32,6 +32,16 @@ void main() { expect(flutterManifest.assets, isEmpty); }); + testWithoutContext('FlutterManifest is null when the pubspec.yaml file is not a map', () async { + final BufferLogger logger = BufferLogger.test(); + expect(FlutterManifest.createFromString( + 'Not a map', + logger: logger, + ), isNull); + + expect(logger.errorText, contains('Expected YAML map')); + }); + testWithoutContext('FlutterManifest has no fonts or assets when the "flutter" section is empty', () async { const String manifest = ''' name: test