Unverified Commit afbfc1f3 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate assets, common, icon_tree_shaker to null safety (#91309)

parent 79412662
......@@ -634,7 +634,7 @@ String getNameForTargetPlatform(TargetPlatform platform, {DarwinArch? darwinArch
}
}
TargetPlatform? getTargetPlatformForName(String platform) {
TargetPlatform getTargetPlatformForName(String platform) {
switch (platform) {
case 'android':
return TargetPlatform.android;
......@@ -669,8 +669,7 @@ TargetPlatform? getTargetPlatformForName(String platform) {
case 'web-javascript':
return TargetPlatform.web_javascript;
}
assert(platform != null);
return null;
throw Exception('Unsupported platform name "$platform"');
}
AndroidArch getAndroidArchForName(String platform) {
......
......@@ -2,9 +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:pool/pool.dart';
import '../../asset.dart';
......@@ -28,13 +25,13 @@ import 'icon_tree_shaker.dart';
///
/// Returns a [Depfile] containing all assets used in the build.
Future<Depfile> copyAssets(Environment environment, Directory outputDirectory, {
Map<String, DevFSContent> additionalContent,
@required TargetPlatform targetPlatform,
BuildMode buildMode,
Map<String, DevFSContent>? additionalContent,
required TargetPlatform targetPlatform,
BuildMode? buildMode,
}) async {
// Check for an SkSL bundle.
final String shaderBundlePath = environment.defines[kBundleSkSLPath] ?? environment.inputs[kBundleSkSLPath];
final DevFSContent skslBundle = processSkSLBundle(
final String? shaderBundlePath = environment.defines[kBundleSkSLPath] ?? environment.inputs[kBundleSkSLPath];
final DevFSContent? skslBundle = processSkSLBundle(
shaderBundlePath,
engineVersion: environment.engineVersion,
fileSystem: environment.fileSystem,
......@@ -70,7 +67,7 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory, {
final IconTreeShaker iconTreeShaker = IconTreeShaker(
environment,
assetBundle.entries[kFontManifestJson] as DevFSStringContent,
assetBundle.entries[kFontManifestJson] as DevFSStringContent?,
processManager: environment.processManager,
logger: environment.logger,
fileSystem: environment.fileSystem,
......@@ -118,7 +115,7 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory, {
// Copy deferred components assets only for release or profile builds.
// The assets are included in assetBundle.entries as a normal asset when
// building as debug.
if (environment.defines[kDeferredComponents] == 'true') {
if (environment.defines[kDeferredComponents] == 'true' && buildMode != null) {
await Future.wait<void>(
assetBundle.deferredComponentsEntries.entries.map<Future<void>>((MapEntry<String, Map<String, DevFSContent>> componentEntries) async {
final Directory componentOutputDir =
......@@ -185,11 +182,11 @@ const String kSkSLShaderBundlePath = 'io.flutter.shaders.json';
///
/// If the current target platform is different than the platform constructed
/// for the bundle, a warning will be printed.
DevFSContent processSkSLBundle(String bundlePath, {
@required TargetPlatform targetPlatform,
@required FileSystem fileSystem,
@required Logger logger,
@required String engineVersion,
DevFSContent? processSkSLBundle(String? bundlePath, {
required TargetPlatform targetPlatform,
required FileSystem fileSystem,
required Logger logger,
String? engineVersion,
}) {
if (bundlePath == null) {
return null;
......@@ -202,9 +199,9 @@ DevFSContent processSkSLBundle(String bundlePath, {
}
// Step 2: validate top level bundle structure.
Map<String, Object> bundle;
Map<String, Object>? bundle;
try {
final Object rawBundle = json.decode(skSLBundleFile.readAsStringSync());
final Object? rawBundle = json.decode(skSLBundleFile.readAsStringSync());
if (rawBundle is Map<String, Object>) {
bundle = rawBundle;
} else {
......@@ -219,7 +216,7 @@ DevFSContent processSkSLBundle(String bundlePath, {
// * The engine revision the bundle was compiled with
// is the same as the current revision.
// * The target platform is the same (this one is a warning only).
final String bundleEngineRevision = bundle['engineRevision'] as String;
final String? bundleEngineRevision = bundle['engineRevision'] as String?;
if (bundleEngineRevision != engineVersion) {
logger.printError(
'Expected Flutter $bundleEngineRevision, but found $engineVersion\n'
......@@ -229,16 +226,19 @@ DevFSContent processSkSLBundle(String bundlePath, {
throw Exception('SkSL bundle was invalid');
}
final TargetPlatform bundleTargetPlatform = getTargetPlatformForName(
bundle['platform'] as String);
if (bundleTargetPlatform != targetPlatform) {
final String? parsedPlatform = bundle['platform'] as String?;
TargetPlatform? bundleTargetPlatform;
if (parsedPlatform != null) {
bundleTargetPlatform = getTargetPlatformForName(parsedPlatform);
}
if (bundleTargetPlatform == null || bundleTargetPlatform != targetPlatform) {
logger.printError(
'The SkSL bundle was created for $bundleTargetPlatform, but the current '
'platform is $targetPlatform. This may lead to less efficient shader '
'caching.'
);
}
return DevFSStringContent(json.encode(<String, Object>{
return DevFSStringContent(json.encode(<String, Object?>{
'data': bundle['data'],
}));
}
......
......@@ -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:package_config/package_config.dart';
import '../../artifacts.dart';
......@@ -51,10 +49,11 @@ class CopyFlutterBundle extends Target {
@override
Future<void> build(Environment environment) async {
if (environment.defines[kBuildMode] == null) {
final String? buildModeEnvironment = environment.defines[kBuildMode];
if (buildModeEnvironment == null) {
throw MissingDefineException(kBuildMode, 'copy_flutter_bundle');
}
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final BuildMode buildMode = getBuildModeForName(buildModeEnvironment);
environment.outputDir.createSync(recursive: true);
// Only copy the prebuilt runtimes and kernel blob in debug mode.
......@@ -157,13 +156,15 @@ class KernelSnapshot extends Target {
fileSystemRoots: <String>[],
fileSystemScheme: null,
);
if (environment.defines[kBuildMode] == null) {
final String? buildModeEnvironment = environment.defines[kBuildMode];
if (buildModeEnvironment == null) {
throw MissingDefineException(kBuildMode, 'kernel_snapshot');
}
if (environment.defines[kTargetPlatform] == null) {
final String? targetPlatformEnvironment = environment.defines[kTargetPlatform];
if (targetPlatformEnvironment == null) {
throw MissingDefineException(kTargetPlatform, 'kernel_snapshot');
}
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final BuildMode buildMode = getBuildModeForName(buildModeEnvironment);
final String targetFile = environment.defines[kTargetFile] ?? environment.fileSystem.path.join('lib', 'main.dart');
final File packagesFile = environment.projectDir
.childDirectory('.dart_tool')
......@@ -171,12 +172,12 @@ class KernelSnapshot extends Target {
final String targetFileAbsolute = environment.fileSystem.file(targetFile).absolute.path;
// everything besides 'false' is considered to be enabled.
final bool trackWidgetCreation = environment.defines[kTrackWidgetCreation] != 'false';
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
final TargetPlatform targetPlatform = getTargetPlatformForName(targetPlatformEnvironment);
// This configuration is all optional.
final List<String> extraFrontEndOptions = decodeCommaSeparated(environment.defines, kExtraFrontEndOptions);
final List<String> fileSystemRoots = environment.defines[kFileSystemRoots]?.split(',');
final String fileSystemScheme = environment.defines[kFileSystemScheme];
final List<String>? fileSystemRoots = environment.defines[kFileSystemRoots]?.split(',');
final String? fileSystemScheme = environment.defines[kFileSystemScheme];
TargetModel targetModel = TargetModel.flutter;
if (targetPlatform == TargetPlatform.fuchsia_x64 ||
......@@ -202,7 +203,7 @@ class KernelSnapshot extends Target {
logger: environment.logger,
);
final CompilerOutput output = await compiler.compile(
final CompilerOutput? output = await compiler.compile(
sdkRoot: environment.artifacts.getArtifactPath(
Artifact.flutterPatchedSdkPath,
platform: targetPlatform,
......@@ -244,23 +245,25 @@ abstract class AotElfBase extends Target {
reportTimings: false,
fileSystem: environment.fileSystem,
logger: environment.logger,
xcode: globals.xcode,
xcode: globals.xcode!,
processManager: environment.processManager,
artifacts: environment.artifacts,
);
final String outputPath = environment.buildDir.path;
if (environment.defines[kBuildMode] == null) {
final String? buildModeEnvironment = environment.defines[kBuildMode];
if (buildModeEnvironment == null) {
throw MissingDefineException(kBuildMode, 'aot_elf');
}
if (environment.defines[kTargetPlatform] == null) {
final String? targetPlatformEnvironment = environment.defines[kTargetPlatform];
if (targetPlatformEnvironment == null) {
throw MissingDefineException(kTargetPlatform, 'aot_elf');
}
final List<String> extraGenSnapshotOptions = decodeCommaSeparated(environment.defines, kExtraGenSnapshotOptions);
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
final BuildMode buildMode = getBuildModeForName(buildModeEnvironment);
final TargetPlatform targetPlatform = getTargetPlatformForName(targetPlatformEnvironment);
final String? splitDebugInfo = environment.defines[kSplitDebugInfo];
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
final String codeSizeDirectory = environment.defines[kCodeSizeDirectory];
final String? codeSizeDirectory = environment.defines[kCodeSizeDirectory];
if (codeSizeDirectory != null) {
final File codeSizeFile = environment.fileSystem
......
......@@ -2,9 +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:mime/mime.dart' as mime;
import 'package:process/process.dart';
......@@ -18,9 +15,9 @@ import '../../convert.dart';
import '../../devfs.dart';
import '../build_system.dart';
List<Map<String, dynamic>> _getList(dynamic object, String errorMessage) {
if (object is List<dynamic>) {
return object.cast<Map<String, dynamic>>();
List<Map<String, Object?>> _getList(Object? object, String errorMessage) {
if (object is List<Object?>) {
return object.cast<Map<String, Object?>>();
}
throw IconTreeShakerException._(errorMessage);
}
......@@ -39,11 +36,11 @@ class IconTreeShaker {
/// font subsetting has been requested in a debug build mode.
IconTreeShaker(
this._environment,
DevFSStringContent fontManifest, {
@required ProcessManager processManager,
@required Logger logger,
@required FileSystem fileSystem,
@required Artifacts artifacts,
DevFSStringContent? fontManifest, {
required ProcessManager processManager,
required Logger logger,
required FileSystem fileSystem,
required Artifacts artifacts,
}) : assert(_environment != null),
assert(processManager != null),
assert(logger != null),
......@@ -81,9 +78,9 @@ class IconTreeShaker {
];
final Environment _environment;
final String _fontManifest;
Future<void> _iconDataProcessing;
Map<String, _IconTreeShakerData> _iconData;
final String? _fontManifest;
Future<void>? _iconDataProcessing;
Map<String, _IconTreeShakerData>? _iconData;
final ProcessManager _processManager;
final Logger _logger;
......@@ -120,7 +117,7 @@ class IconTreeShaker {
final Set<String> familyKeys = iconData.keys.toSet();
final Map<String, String> fonts = await _parseFontJson(
_fontManifest,
_fontManifest!, // Guarded by `enabled`.
familyKeys,
);
......@@ -137,10 +134,14 @@ class IconTreeShaker {
final Map<String, _IconTreeShakerData> result = <String, _IconTreeShakerData>{};
for (final MapEntry<String, String> entry in fonts.entries) {
final List<int>? codePoints = iconData[entry.key];
if (codePoints == null) {
throw IconTreeShakerException._('Expected to font code points for ${entry.key}, but none were found.');
}
result[entry.value] = _IconTreeShakerData(
family: entry.key,
relativePath: entry.value,
codePoints: iconData[entry.key],
codePoints: codePoints,
);
}
_iconData = result;
......@@ -156,9 +157,9 @@ class IconTreeShaker {
/// If the font-subset subprocess fails, it will [throwToolExit].
/// Otherwise, it will return true.
Future<bool> subsetFont({
@required File input,
@required String outputPath,
@required String relativePath,
required File input,
required String outputPath,
required String relativePath,
}) async {
if (!enabled) {
return false;
......@@ -166,7 +167,7 @@ class IconTreeShaker {
if (input.lengthSync() < 12) {
return false;
}
final String mimeType = mime.lookupMimeType(
final String? mimeType = mime.lookupMimeType(
input.path,
headerBytes: await input.openRead(0, 12).first,
);
......@@ -176,7 +177,7 @@ class IconTreeShaker {
await (_iconDataProcessing ??= _getIconData(_environment));
assert(_iconData != null);
final _IconTreeShakerData iconTreeShakerData = _iconData[relativePath];
final _IconTreeShakerData? iconTreeShakerData = _iconData![relativePath];
if (iconTreeShakerData == null) {
return false;
}
......@@ -220,22 +221,22 @@ class IconTreeShaker {
Set<String> families,
) async {
final Map<String, String> result = <String, String>{};
final List<Map<String, dynamic>> fontList = _getList(
final List<Map<String, Object?>> fontList = _getList(
json.decode(fontManifestData),
'FontManifest.json invalid: expected top level to be a list of objects.',
);
for (final Map<String, dynamic> map in fontList) {
if (map['family'] is! String) {
for (final Map<String, Object?> map in fontList) {
final Object? familyKey = map['family'];
if (familyKey is! String) {
throw IconTreeShakerException._(
'FontManifest.json invalid: expected the family value to be a string, '
'got: ${map['family']}.');
}
final String familyKey = map['family'] as String;
if (!families.contains(familyKey)) {
continue;
}
final List<Map<String, dynamic>> fonts = _getList(
final List<Map<String, Object?>> fonts = _getList(
map['fonts'],
'FontManifest.json invalid: expected "fonts" to be a list of objects.',
);
......@@ -244,12 +245,13 @@ class IconTreeShaker {
'This tool cannot process icon fonts with multiple fonts in a '
'single family.');
}
if (fonts.first['asset'] is! String) {
final Object? asset = fonts.first['asset'];
if (asset is! String) {
throw IconTreeShakerException._(
'FontManifest.json invalid: expected "asset" value to be a string, '
'got: ${map['assets']}.');
}
result[familyKey] = fonts.first['asset'] as String;
result[familyKey] = asset;
}
return result;
}
......@@ -273,19 +275,18 @@ class IconTreeShaker {
if (constFinderProcessResult.exitCode != 0) {
throw IconTreeShakerException._('ConstFinder failure: ${constFinderProcessResult.stderr}');
}
final dynamic jsonDecode = json.decode(constFinderProcessResult.stdout as String);
if (jsonDecode is! Map<String, dynamic>) {
final Object? constFinderMap = json.decode(constFinderProcessResult.stdout as String);
if (constFinderMap is! Map<String, Object?>) {
throw IconTreeShakerException._(
'Invalid ConstFinder output: expected a top level JSON object, '
'got $jsonDecode.');
'got $constFinderMap.');
}
final Map<String, dynamic> constFinderMap = jsonDecode as Map<String, dynamic>;
final _ConstFinderResult constFinderResult = _ConstFinderResult(constFinderMap);
if (constFinderResult.hasNonConstantLocations) {
_logger.printError('This application cannot tree shake icons fonts. '
'It has non-constant instances of IconData at the '
'following locations:', emphasis: true);
for (final Map<String, dynamic> location in constFinderResult.nonConstantLocations) {
for (final Map<String, Object?> location in constFinderResult.nonConstantLocations) {
_logger.printError(
'- ${location['file']}:${location['line']}:${location['column']}',
indent: 2,
......@@ -300,22 +301,24 @@ class IconTreeShaker {
Map<String, List<int>> _parseConstFinderResult(_ConstFinderResult constants) {
final Map<String, List<int>> result = <String, List<int>>{};
for (final Map<String, dynamic> iconDataMap in constants.constantInstances) {
if ((iconDataMap['fontPackage'] ?? '') is! String || // Null is ok here.
iconDataMap['fontFamily'] is! String ||
iconDataMap['codePoint'] is! num) {
for (final Map<String, Object?> iconDataMap in constants.constantInstances) {
final Object? package = iconDataMap['fontPackage'];
final Object? fontFamily = iconDataMap['fontFamily'];
final Object? codePoint = iconDataMap['codePoint'];
if ((package ?? '') is! String || // Null is ok here.
fontFamily is! String ||
codePoint is! num) {
throw IconTreeShakerException._(
'Invalid ConstFinder result. Expected "fontPackage" to be a String, '
'"fontFamily" to be a String, and "codePoint" to be an int, '
'got: $iconDataMap.');
}
final String package = iconDataMap['fontPackage'] as String;
final String family = iconDataMap['fontFamily'] as String;
final String family = fontFamily;
final String key = package == null
? family
: 'packages/$package/$family';
result[key] ??= <int>[];
result[key].add((iconDataMap['codePoint'] as num).round());
result[key]!.add(codePoint.round());
}
return result;
}
......@@ -324,25 +327,17 @@ class IconTreeShaker {
class _ConstFinderResult {
_ConstFinderResult(this.result);
final Map<String, dynamic> result;
final Map<String, Object?> result;
List<Map<String, dynamic>> _constantInstances;
List<Map<String, dynamic>> get constantInstances {
_constantInstances ??= _getList(
result['constantInstances'],
'Invalid ConstFinder output: Expected "constInstances" to be a list of objects.',
);
return _constantInstances;
}
late final List<Map<String, Object?>> constantInstances = _getList(
result['constantInstances'],
'Invalid ConstFinder output: Expected "constInstances" to be a list of objects.',
);
List<Map<String, dynamic>> _nonConstantLocations;
List<Map<String, dynamic>> get nonConstantLocations {
_nonConstantLocations ??= _getList(
result['nonConstantLocations'],
'Invalid ConstFinder output: Expected "nonConstLocations" to be a list of objects',
);
return _nonConstantLocations;
}
late final List<Map<String, Object?>> nonConstantLocations = _getList(
result['nonConstantLocations'],
'Invalid ConstFinder output: Expected "nonConstLocations" to be a list of objects',
);
bool get hasNonConstantLocations => nonConstantLocations.isNotEmpty;
}
......@@ -352,9 +347,9 @@ class _ConstFinderResult {
class _IconTreeShakerData {
/// All parameters are required.
const _IconTreeShakerData({
@required this.family,
@required this.relativePath,
@required this.codePoints,
required this.family,
required this.relativePath,
required this.codePoints,
}) : assert(family != null),
assert(relativePath != null),
assert(codePoints != null);
......
......@@ -196,7 +196,7 @@ class KernelCompiler {
required ProcessManager processManager,
required Artifacts artifacts,
required List<String> fileSystemRoots,
required String fileSystemScheme,
String? fileSystemScheme,
@visibleForTesting StdoutHandler? stdoutHandler,
}) : _logger = logger,
_fileSystem = fileSystem,
......@@ -210,7 +210,7 @@ class KernelCompiler {
final Artifacts _artifacts;
final ProcessManager _processManager;
final Logger _logger;
final String _fileSystemScheme;
final String? _fileSystemScheme;
final List<String> _fileSystemRoots;
final StdoutHandler _stdoutHandler;
......
......@@ -203,7 +203,7 @@ flutter:
fileSystem.file('bundle.sksl').writeAsStringSync(json.encode(
<String, Object>{
'engineRevision': '2',
'platform': 'fuchsia',
'platform': 'fuchsia-arm64',
'data': <String, Object>{}
}
));
......
......@@ -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:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -13,7 +11,6 @@ import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/icon_tree_shaker.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:meta/meta.dart';
import '../../../src/common.dart';
import '../../../src/fake_process_manager.dart';
......@@ -27,16 +24,16 @@ const String outputPath = '/output/fonts/MaterialIcons-Regular.otf';
const String relativePath = 'fonts/MaterialIcons-Regular.otf';
void main() {
BufferLogger logger;
MemoryFileSystem fileSystem;
FakeProcessManager processManager;
Artifacts artifacts;
DevFSStringContent fontManifestContent;
late BufferLogger logger;
late MemoryFileSystem fileSystem;
late FakeProcessManager processManager;
late Artifacts artifacts;
late DevFSStringContent fontManifestContent;
String dartPath;
String constFinderPath;
String fontSubsetPath;
List<String> fontSubsetArgs;
late String dartPath;
late String constFinderPath;
late String fontSubsetPath;
late List<String> fontSubsetArgs;
List<String> _getConstFinderArgs(String appDillPath) => <String>[
dartPath,
......@@ -65,7 +62,7 @@ void main() {
int exitCode = 0,
String stdout = '',
String stderr = '',
@required CompleterIOSink stdinSink,
required CompleterIOSink stdinSink,
}) {
assert(stdinSink != null);
stdinSink.clear();
......
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