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

Migrate project.dart and all dependencies to null safety (#83817)

parent 2c645e4c
...@@ -12,6 +12,7 @@ import 'package:flutter_tools/src/base/io.dart'; ...@@ -12,6 +12,7 @@ import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/depfile.dart'; import 'package:flutter_tools/src/build_system/depfile.dart';
import 'package:flutter_tools/src/bundle.dart'; import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart'; import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/devfs.dart';
......
...@@ -2,16 +2,12 @@ ...@@ -2,16 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../project.dart'; import '../project.dart';
/// The builder in the current context. /// The builder in the current context.
AndroidBuilder get androidBuilder { AndroidBuilder? get androidBuilder {
return context.get<AndroidBuilder>(); return context.get<AndroidBuilder>();
} }
...@@ -19,25 +15,25 @@ abstract class AndroidBuilder { ...@@ -19,25 +15,25 @@ abstract class AndroidBuilder {
const AndroidBuilder(); const AndroidBuilder();
/// Builds an AAR artifact. /// Builds an AAR artifact.
Future<void> buildAar({ Future<void> buildAar({
@required FlutterProject project, required FlutterProject project,
@required Set<AndroidBuildInfo> androidBuildInfo, required Set<AndroidBuildInfo> androidBuildInfo,
@required String target, required String target,
@required String outputDirectoryPath, String? outputDirectoryPath,
@required String buildNumber, required String buildNumber,
}); });
/// Builds an APK artifact. /// Builds an APK artifact.
Future<void> buildApk({ Future<void> buildApk({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
}); });
/// Builds an App Bundle artifact. /// Builds an App Bundle artifact.
Future<void> buildAab({ Future<void> buildAab({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
bool validateDeferredComponents = true, bool validateDeferredComponents = true,
bool deferredComponentsEnabled = false, bool deferredComponentsEnabled = false,
}); });
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -126,7 +124,7 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) { ...@@ -126,7 +124,7 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) {
final String newSettingsRelativeFile = fileSystem.path.relative(newSettingsFile.path); final String newSettingsRelativeFile = fileSystem.path.relative(newSettingsFile.path);
final Status status = logger.startProgress('✏️ Creating `$newSettingsRelativeFile`...'); final Status status = logger.startProgress('✏️ Creating `$newSettingsRelativeFile`...');
final String flutterRoot = fileSystem.path.absolute(Cache.flutterRoot); final String flutterRoot = fileSystem.path.absolute(Cache.flutterRoot!);
final File legacySettingsDotGradleFiles = fileSystem.file(fileSystem.path.join(flutterRoot, 'packages','flutter_tools', final File legacySettingsDotGradleFiles = fileSystem.file(fileSystem.path.join(flutterRoot, 'packages','flutter_tools',
'gradle', 'settings.gradle.legacy_versions')); 'gradle', 'settings.gradle.legacy_versions'));
assert(legacySettingsDotGradleFiles.existsSync()); assert(legacySettingsDotGradleFiles.existsSync());
...@@ -161,13 +159,13 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) { ...@@ -161,13 +159,13 @@ void createSettingsAarGradle(Directory androidDirectory, Logger logger) {
/// An implementation of the [AndroidBuilder] that delegates to gradle. /// An implementation of the [AndroidBuilder] that delegates to gradle.
class AndroidGradleBuilder implements AndroidBuilder { class AndroidGradleBuilder implements AndroidBuilder {
AndroidGradleBuilder({ AndroidGradleBuilder({
@required Logger logger, required Logger logger,
@required ProcessManager processManager, required ProcessManager processManager,
@required FileSystem fileSystem, required FileSystem fileSystem,
@required Artifacts artifacts, required Artifacts artifacts,
@required Usage usage, required Usage usage,
@required GradleUtils gradleUtils, required GradleUtils gradleUtils,
@required Platform platform, required Platform platform,
}) : _logger = logger, }) : _logger = logger,
_fileSystem = fileSystem, _fileSystem = fileSystem,
_artifacts = artifacts, _artifacts = artifacts,
...@@ -187,11 +185,11 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -187,11 +185,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
/// Builds the AAR and POM files for the current Flutter module or plugin. /// Builds the AAR and POM files for the current Flutter module or plugin.
@override @override
Future<void> buildAar({ Future<void> buildAar({
@required FlutterProject project, required FlutterProject project,
@required Set<AndroidBuildInfo> androidBuildInfo, required Set<AndroidBuildInfo> androidBuildInfo,
@required String target, required String target,
String outputDirectoryPath, String? outputDirectoryPath,
@required String buildNumber, required String buildNumber,
}) async { }) async {
Directory outputDirectory = Directory outputDirectory =
_fileSystem.directory(outputDirectoryPath ?? project.android.buildDirectory); _fileSystem.directory(outputDirectoryPath ?? project.android.buildDirectory);
...@@ -224,9 +222,9 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -224,9 +222,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
/// Builds the APK. /// Builds the APK.
@override @override
Future<void> buildApk({ Future<void> buildApk({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
}) async { }) async {
await buildGradleApp( await buildGradleApp(
project: project, project: project,
...@@ -240,9 +238,9 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -240,9 +238,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
/// Builds the App Bundle. /// Builds the App Bundle.
@override @override
Future<void> buildAab({ Future<void> buildAab({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
bool validateDeferredComponents = true, bool validateDeferredComponents = true,
bool deferredComponentsEnabled = false, bool deferredComponentsEnabled = false,
}) async { }) async {
...@@ -269,11 +267,11 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -269,11 +267,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
/// * [retries] is the max number of build retries in case one of the [GradleHandledError] handler /// * [retries] is the max number of build retries in case one of the [GradleHandledError] handler
/// returns [GradleBuildStatus.retry] or [GradleBuildStatus.retryWithAarPlugins]. /// returns [GradleBuildStatus.retry] or [GradleBuildStatus.retryWithAarPlugins].
Future<void> buildGradleApp({ Future<void> buildGradleApp({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
@required bool isBuildingBundle, required bool isBuildingBundle,
@required List<GradleHandledError> localGradleErrors, required List<GradleHandledError> localGradleErrors,
bool shouldBuildPluginAsAar = false, bool shouldBuildPluginAsAar = false,
bool validateDeferredComponents = true, bool validateDeferredComponents = true,
bool deferredComponentsEnabled = false, bool deferredComponentsEnabled = false,
...@@ -361,7 +359,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -361,7 +359,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
if (target != null) { if (target != null) {
command.add('-Ptarget=$target'); command.add('-Ptarget=$target');
} }
final List<DeferredComponent> deferredComponents = project.manifest.deferredComponents; final List<DeferredComponent>? deferredComponents = project.manifest.deferredComponents;
if (deferredComponents != null) { if (deferredComponents != null) {
if (deferredComponentsEnabled) { if (deferredComponentsEnabled) {
command.add('-Pdeferred-components=true'); command.add('-Pdeferred-components=true');
...@@ -406,9 +404,9 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -406,9 +404,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
} }
command.add(assembleTask); command.add(assembleTask);
GradleHandledError detectedGradleError; GradleHandledError? detectedGradleError;
String detectedGradleErrorLine; String? detectedGradleErrorLine;
String consumeLog(String line) { String? consumeLog(String line) {
// This message was removed from first-party plugins, // This message was removed from first-party plugins,
// but older plugin versions still display this message. // but older plugin versions still display this message.
if (androidXPluginWarningRegex.hasMatch(line)) { if (androidXPluginWarningRegex.hasMatch(line)) {
...@@ -441,7 +439,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -441,7 +439,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: <String, String>{ environment: <String, String>{
if (javaPath != null) if (javaPath != null)
'JAVA_HOME': javaPath, 'JAVA_HOME': javaPath!,
}, },
mapFunction: consumeLog, mapFunction: consumeLog,
); );
...@@ -466,15 +464,15 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -466,15 +464,15 @@ class AndroidGradleBuilder implements AndroidBuilder {
exitCode: exitCode, exitCode: exitCode,
); );
} else { } else {
final GradleBuildStatus status = await detectedGradleError.handler( final GradleBuildStatus status = await detectedGradleError!.handler(
line: detectedGradleErrorLine, line: detectedGradleErrorLine!,
project: project, project: project,
usesAndroidX: usesAndroidX, usesAndroidX: usesAndroidX,
shouldBuildPluginAsAar: shouldBuildPluginAsAar, shouldBuildPluginAsAar: shouldBuildPluginAsAar,
); );
if (retries >= 1) { if (retries >= 1) {
final String successEventLabel = 'gradle-${detectedGradleError.eventLabel}-success'; final String successEventLabel = 'gradle-${detectedGradleError!.eventLabel}-success';
switch (status) { switch (status) {
case GradleBuildStatus.retry: case GradleBuildStatus.retry:
await buildGradleApp( await buildGradleApp(
...@@ -504,7 +502,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -504,7 +502,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
// noop. // noop.
} }
} }
BuildEvent('gradle-${detectedGradleError.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send(); BuildEvent('gradle-${detectedGradleError?.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send();
throwToolExit( throwToolExit(
'Gradle task $assembleTask failed with exit code $exitCode', 'Gradle task $assembleTask failed with exit code $exitCode',
exitCode: exitCode, exitCode: exitCode,
...@@ -580,7 +578,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -580,7 +578,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
.childFile('snapshot.$archName.json'); .childFile('snapshot.$archName.json');
final File precompilerTrace = _fileSystem.directory(buildInfo.codeSizeDirectory) final File precompilerTrace = _fileSystem.directory(buildInfo.codeSizeDirectory)
.childFile('trace.$archName.json'); .childFile('trace.$archName.json');
final Map<String, Object> output = await sizeAnalyzer.analyzeZipSizeAndAotSnapshot( final Map<String, Object?> output = await sizeAnalyzer.analyzeZipSizeAndAotSnapshot(
zipFile: zipFile, zipFile: zipFile,
aotSnapshot: aotSnapshot, aotSnapshot: aotSnapshot,
precompilerTrace: precompilerTrace, precompilerTrace: precompilerTrace,
...@@ -616,11 +614,11 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -616,11 +614,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
/// * [outputDir] is the destination of the artifacts, /// * [outputDir] is the destination of the artifacts,
/// * [buildNumber] is the build number of the output aar, /// * [buildNumber] is the build number of the output aar,
Future<void> buildGradleAar({ Future<void> buildGradleAar({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
@required Directory outputDirectory, required Directory outputDirectory,
@required String buildNumber, required String buildNumber,
}) async { }) async {
assert(project != null); assert(project != null);
assert(target != null); assert(target != null);
...@@ -638,7 +636,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -638,7 +636,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
"Running Gradle task '$aarTask'...", "Running Gradle task '$aarTask'...",
); );
final String flutterRoot = _fileSystem.path.absolute(Cache.flutterRoot); final String flutterRoot = _fileSystem.path.absolute(Cache.flutterRoot!);
final String initScript = _fileSystem.path.join( final String initScript = _fileSystem.path.join(
flutterRoot, flutterRoot,
'packages', 'packages',
...@@ -721,7 +719,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -721,7 +719,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: <String, String>{ environment: <String, String>{
if (javaPath != null) if (javaPath != null)
'JAVA_HOME': javaPath, 'JAVA_HOME': javaPath!,
}, },
); );
} finally { } finally {
...@@ -757,7 +755,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -757,7 +755,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
Future<void> buildPluginsAsAar( Future<void> buildPluginsAsAar(
FlutterProject flutterProject, FlutterProject flutterProject,
AndroidBuildInfo androidBuildInfo, { AndroidBuildInfo androidBuildInfo, {
@required Directory buildDirectory, required Directory buildDirectory,
}) async { }) async {
final File flutterPluginFile = flutterProject.flutterPluginsFile; final File flutterPluginFile = flutterProject.flutterPluginsFile;
if (!flutterPluginFile.existsSync()) { if (!flutterPluginFile.existsSync()) {
...@@ -806,12 +804,12 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -806,12 +804,12 @@ class AndroidGradleBuilder implements AndroidBuilder {
/// Prints how to consume the AAR from a host app. /// Prints how to consume the AAR from a host app.
void printHowToConsumeAar({ void printHowToConsumeAar({
@required Set<String> buildModes, required Set<String> buildModes,
String androidPackage = 'unknown', String? androidPackage = 'unknown',
@required Directory repoDirectory, required Directory repoDirectory,
@required Logger logger, required Logger logger,
@required FileSystem fileSystem, required FileSystem fileSystem,
String buildNumber, String? buildNumber,
}) { }) {
assert(buildModes != null && buildModes.isNotEmpty); assert(buildModes != null && buildModes.isNotEmpty);
assert(repoDirectory != null); assert(repoDirectory != null);
...@@ -919,7 +917,7 @@ Iterable<String> findApkFilesModule( ...@@ -919,7 +917,7 @@ Iterable<String> findApkFilesModule(
if (apkFile.existsSync()) { if (apkFile.existsSync()) {
return <File>[apkFile]; return <File>[apkFile];
} }
final String flavor = buildInfo.flavor; final String? flavor = buildInfo.flavor;
if (flavor != null) { if (flavor != null) {
// Android Studio Gradle plugin v3 adds flavor to path. // Android Studio Gradle plugin v3 adds flavor to path.
apkFile = apkDirectory apkFile = apkDirectory
...@@ -954,7 +952,7 @@ Iterable<String> listApkPaths( ...@@ -954,7 +952,7 @@ Iterable<String> listApkPaths(
final String buildType = camelCase(androidBuildInfo.buildInfo.modeName); final String buildType = camelCase(androidBuildInfo.buildInfo.modeName);
final List<String> apkPartialName = <String>[ final List<String> apkPartialName = <String>[
if (androidBuildInfo.buildInfo.flavor?.isNotEmpty ?? false) if (androidBuildInfo.buildInfo.flavor?.isNotEmpty ?? false)
androidBuildInfo.buildInfo.lowerCasedFlavor, androidBuildInfo.buildInfo.lowerCasedFlavor!,
'$buildType.apk', '$buildType.apk',
]; ];
if (androidBuildInfo.splitPerAbi) { if (androidBuildInfo.splitPerAbi) {
...@@ -1013,15 +1011,14 @@ File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger, ...@@ -1013,15 +1011,14 @@ File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger,
logger: logger, logger: logger,
usage: usage, usage: usage,
); );
return null;
} }
/// Throws a [ToolExit] exception and logs the event. /// Throws a [ToolExit] exception and logs the event.
void _exitWithExpectedFileNotFound({ Never _exitWithExpectedFileNotFound({
@required FlutterProject project, required FlutterProject project,
@required String fileExtension, required String fileExtension,
@required Logger logger, required Logger logger,
@required Usage usage, required Usage usage,
}) { }) {
assert(project != null); assert(project != null);
assert(fileExtension != null); assert(fileExtension != null);
...@@ -1090,9 +1087,9 @@ String _getLocalArtifactVersion(String pomPath, FileSystem fileSystem) { ...@@ -1090,9 +1087,9 @@ String _getLocalArtifactVersion(String pomPath, FileSystem fileSystem) {
/// This method generates symlinks in the temp directory to the engine artifacts /// This method generates symlinks in the temp directory to the engine artifacts
/// following the convention specified on https://maven.apache.org/pom.html#Repositories /// following the convention specified on https://maven.apache.org/pom.html#Repositories
Directory _getLocalEngineRepo({ Directory _getLocalEngineRepo({
@required String engineOutPath, required String engineOutPath,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required FileSystem fileSystem, required FileSystem fileSystem,
}) { }) {
assert(engineOutPath != null); assert(engineOutPath != null);
assert(androidBuildInfo != null); assert(androidBuildInfo != null);
......
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import '../base/error_handling_io.dart'; import '../base/error_handling_io.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../globals.dart' as globals; import '../globals_null_migrated.dart' as globals;
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import 'android_studio.dart'; import 'android_studio.dart';
...@@ -18,8 +17,8 @@ typedef GradleErrorTest = bool Function(String); ...@@ -18,8 +17,8 @@ typedef GradleErrorTest = bool Function(String);
/// A Gradle error handled by the tool. /// A Gradle error handled by the tool.
class GradleHandledError { class GradleHandledError {
const GradleHandledError({ const GradleHandledError({
@required this.test, required this.test,
@required this.handler, required this.handler,
this.eventLabel, this.eventLabel,
}); });
...@@ -29,16 +28,16 @@ class GradleHandledError { ...@@ -29,16 +28,16 @@ class GradleHandledError {
/// The handler function. /// The handler function.
final Future<GradleBuildStatus> Function({ final Future<GradleBuildStatus> Function({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) handler; }) handler;
/// The [BuildEvent] label is named gradle-[eventLabel]. /// The [BuildEvent] label is named gradle-[eventLabel].
/// If not empty, the build event is logged along with /// If not empty, the build event is logged along with
/// additional metadata such as the attempt number. /// additional metadata such as the attempt number.
final String eventLabel; final String? eventLabel;
} }
/// The status of the Gradle build. /// The status of the Gradle build.
...@@ -85,10 +84,10 @@ final GradleHandledError permissionDeniedErrorHandler = GradleHandledError( ...@@ -85,10 +84,10 @@ final GradleHandledError permissionDeniedErrorHandler = GradleHandledError(
'Permission denied', 'Permission denied',
]), ]),
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
globals.printStatus('${globals.logger.terminal.warningMark} Gradle does not have execution permission.', emphasis: true); globals.printStatus('${globals.logger.terminal.warningMark} Gradle does not have execution permission.', emphasis: true);
globals.printStatus( globals.printStatus(
...@@ -122,17 +121,17 @@ final GradleHandledError networkErrorHandler = GradleHandledError( ...@@ -122,17 +121,17 @@ final GradleHandledError networkErrorHandler = GradleHandledError(
'Gateway Time-out' 'Gateway Time-out'
]), ]),
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
globals.printError( globals.printError(
'${globals.logger.terminal.warningMark} Gradle threw an error while downloading artifacts from the network. ' '${globals.logger.terminal.warningMark} Gradle threw an error while downloading artifacts from the network. '
'Retrying to download...' 'Retrying to download...'
); );
try { try {
final String homeDir = globals.platform.environment['HOME']; final String? homeDir = globals.platform.environment['HOME'];
if (homeDir != null) { if (homeDir != null) {
final Directory directory = globals.fs.directory(globals.fs.path.join(homeDir, '.gradle')); final Directory directory = globals.fs.directory(globals.fs.path.join(homeDir, '.gradle'));
ErrorHandlingFileSystem.deleteIfExists(directory, recursive: true); ErrorHandlingFileSystem.deleteIfExists(directory, recursive: true);
...@@ -152,10 +151,10 @@ final GradleHandledError r8FailureHandler = GradleHandledError( ...@@ -152,10 +151,10 @@ final GradleHandledError r8FailureHandler = GradleHandledError(
'com.android.tools.r8', 'com.android.tools.r8',
]), ]),
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
globals.printStatus('${globals.logger.terminal.warningMark} The shrinker may have failed to optimize the Java bytecode.', emphasis: true); globals.printStatus('${globals.logger.terminal.warningMark} The shrinker may have failed to optimize the Java bytecode.', emphasis: true);
globals.printStatus('To disable the shrinker, pass the `--no-shrink` flag to this command.', indent: 4); globals.printStatus('To disable the shrinker, pass the `--no-shrink` flag to this command.', indent: 4);
...@@ -191,10 +190,10 @@ final GradleHandledError androidXFailureHandler = GradleHandledError( ...@@ -191,10 +190,10 @@ final GradleHandledError androidXFailureHandler = GradleHandledError(
_androidXFailureRegex.hasMatch(line); _androidXFailureRegex.hasMatch(line);
}, },
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
final bool hasPlugins = project.flutterPluginsFile.existsSync(); final bool hasPlugins = project.flutterPluginsFile.existsSync();
if (!hasPlugins) { if (!hasPlugins) {
...@@ -259,21 +258,21 @@ final GradleHandledError licenseNotAcceptedHandler = GradleHandledError( ...@@ -259,21 +258,21 @@ final GradleHandledError licenseNotAcceptedHandler = GradleHandledError(
'You have not accepted the license agreements of the following SDK components', 'You have not accepted the license agreements of the following SDK components',
]), ]),
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
const String licenseNotAcceptedMatcher = const String licenseNotAcceptedMatcher =
r'You have not accepted the license agreements of the following SDK components:\s*\[(.+)\]'; r'You have not accepted the license agreements of the following SDK components:\s*\[(.+)\]';
final RegExp licenseFailure = RegExp(licenseNotAcceptedMatcher, multiLine: true); final RegExp licenseFailure = RegExp(licenseNotAcceptedMatcher, multiLine: true);
assert(licenseFailure != null); assert(licenseFailure != null);
final Match licenseMatch = licenseFailure.firstMatch(line); final Match? licenseMatch = licenseFailure.firstMatch(line);
globals.printStatus( globals.printStatus(
'${globals.logger.terminal.warningMark} Unable to download needed Android SDK components, as the ' '${globals.logger.terminal.warningMark} Unable to download needed Android SDK components, as the '
'following licenses have not been accepted:\n' 'following licenses have not been accepted:\n'
'${licenseMatch.group(1)}\n\n' '${licenseMatch?.group(1)}\n\n'
'To resolve this, please run the following command in a Terminal:\n' 'To resolve this, please run the following command in a Terminal:\n'
'flutter doctor --android-licenses' 'flutter doctor --android-licenses'
); );
...@@ -293,14 +292,14 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError( ...@@ -293,14 +292,14 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
return _undefinedTaskPattern.hasMatch(line); return _undefinedTaskPattern.hasMatch(line);
}, },
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
final RunResult tasksRunResult = await globals.processUtils.run( final RunResult tasksRunResult = await globals.processUtils.run(
<String>[ <String>[
globals.gradleUtils.getExecutable(project), globals.gradleUtils!.getExecutable(project),
'app:tasks' , 'app:tasks' ,
'--all', '--all',
'--console=auto', '--console=auto',
...@@ -309,15 +308,15 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError( ...@@ -309,15 +308,15 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
environment: <String, String>{ environment: <String, String>{
if (javaPath != null) if (javaPath != null)
'JAVA_HOME': javaPath, 'JAVA_HOME': javaPath!,
}, },
); );
// Extract build types and product flavors. // Extract build types and product flavors.
final Set<String> variants = <String>{}; final Set<String> variants = <String>{};
for (final String task in tasksRunResult.stdout.split('\n')) { for (final String task in tasksRunResult.stdout.split('\n')) {
final Match match = _assembleTaskPattern.matchAsPrefix(task); final Match? match = _assembleTaskPattern.matchAsPrefix(task);
if (match != null) { if (match != null) {
final String variant = match.group(1).toLowerCase(); final String variant = match.group(1)!.toLowerCase();
if (!variant.endsWith('test')) { if (!variant.endsWith('test')) {
variants.add(variant); variants.add(variant);
} }
...@@ -366,32 +365,32 @@ final GradleHandledError minSdkVersion = GradleHandledError( ...@@ -366,32 +365,32 @@ final GradleHandledError minSdkVersion = GradleHandledError(
return _minSdkVersionPattern.hasMatch(line); return _minSdkVersionPattern.hasMatch(line);
}, },
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
final File gradleFile = project.directory final File gradleFile = project.directory
.childDirectory('android') .childDirectory('android')
.childDirectory('app') .childDirectory('app')
.childFile('build.gradle'); .childFile('build.gradle');
final Match minSdkVersionMatch = _minSdkVersionPattern.firstMatch(line); final Match? minSdkVersionMatch = _minSdkVersionPattern.firstMatch(line);
assert(minSdkVersionMatch.groupCount == 3); assert(minSdkVersionMatch?.groupCount == 3);
final String bold = globals.logger.terminal.bolden( final String bold = globals.logger.terminal.bolden(
'Fix this issue by adding the following to the file ${gradleFile.path}:\n' 'Fix this issue by adding the following to the file ${gradleFile.path}:\n'
'android {\n' 'android {\n'
' defaultConfig {\n' ' defaultConfig {\n'
' minSdkVersion ${minSdkVersionMatch.group(2)}\n' ' minSdkVersion ${minSdkVersionMatch?.group(2)}\n'
' }\n' ' }\n'
'}\n' '}\n'
); );
globals.printStatus( globals.printStatus(
'\n' '\n'
'The plugin ${minSdkVersionMatch.group(3)} requires a higher Android SDK version.\n' 'The plugin ${minSdkVersionMatch?.group(3)} requires a higher Android SDK version.\n'
'$bold\n' '$bold\n'
"Note that your app won't be available to users running Android SDKs below ${minSdkVersionMatch.group(2)}.\n" "Note that your app won't be available to users running Android SDKs below ${minSdkVersionMatch?.group(2)}.\n"
'Alternatively, try to find a version of this plugin that supports these lower versions of the Android SDK.' 'Alternatively, try to find a version of this plugin that supports these lower versions of the Android SDK.'
); );
return GradleBuildStatus.exit; return GradleBuildStatus.exit;
...@@ -407,10 +406,10 @@ final GradleHandledError transformInputIssue = GradleHandledError( ...@@ -407,10 +406,10 @@ final GradleHandledError transformInputIssue = GradleHandledError(
return line.contains('https://issuetracker.google.com/issues/158753935'); return line.contains('https://issuetracker.google.com/issues/158753935');
}, },
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
final File gradleFile = project.directory final File gradleFile = project.directory
.childDirectory('android') .childDirectory('android')
...@@ -441,10 +440,10 @@ final GradleHandledError lockFileDepMissing = GradleHandledError( ...@@ -441,10 +440,10 @@ final GradleHandledError lockFileDepMissing = GradleHandledError(
return line.contains('which is not part of the dependency lock state'); return line.contains('which is not part of the dependency lock state');
}, },
handler: ({ handler: ({
@required String line, required String line,
@required FlutterProject project, required FlutterProject project,
@required bool usesAndroidX, required bool usesAndroidX,
@required bool shouldBuildPluginAsAar, required bool shouldBuildPluginAsAar,
}) async { }) async {
final File gradleFile = project.directory final File gradleFile = project.directory
.childDirectory('android') .childDirectory('android')
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import '../base/common.dart'; import '../base/common.dart';
...@@ -29,11 +27,11 @@ final RegExp _androidPluginRegExp = RegExp(r'com\.android\.tools\.build:gradle:( ...@@ -29,11 +27,11 @@ final RegExp _androidPluginRegExp = RegExp(r'com\.android\.tools\.build:gradle:(
/// or constructing a Gradle project. /// or constructing a Gradle project.
class GradleUtils { class GradleUtils {
GradleUtils({ GradleUtils({
@required Platform platform, required Platform platform,
@required Logger logger, required Logger logger,
@required FileSystem fileSystem, required FileSystem fileSystem,
@required Cache cache, required Cache cache,
@required OperatingSystemUtils operatingSystemUtils, required OperatingSystemUtils operatingSystemUtils,
}) : _platform = platform, }) : _platform = platform,
_logger = logger, _logger = logger,
_cache = cache, _cache = cache,
...@@ -120,22 +118,22 @@ String getGradleVersionForAndroidPlugin(Directory directory, Logger logger) { ...@@ -120,22 +118,22 @@ String getGradleVersionForAndroidPlugin(Directory directory, Logger logger) {
logger.printTrace("$buildFile doesn't provide an AGP version, assuming AGP version: $_defaultGradleVersion"); logger.printTrace("$buildFile doesn't provide an AGP version, assuming AGP version: $_defaultGradleVersion");
return _defaultGradleVersion; return _defaultGradleVersion;
} }
final String androidPluginVersion = pluginMatches.first.group(1); final String? androidPluginVersion = pluginMatches.first.group(1);
logger.printTrace('$buildFile provides AGP version: $androidPluginVersion'); logger.printTrace('$buildFile provides AGP version: $androidPluginVersion');
return getGradleVersionFor(androidPluginVersion); return getGradleVersionFor(androidPluginVersion ?? 'unknown');
} }
/// Returns true if [targetVersion] is within the range [min] and [max] inclusive. /// Returns true if [targetVersion] is within the range [min] and [max] inclusive.
bool _isWithinVersionRange( bool _isWithinVersionRange(
String targetVersion, { String targetVersion, {
@required String min, required String min,
@required String max, required String max,
}) { }) {
assert(min != null); assert(min != null);
assert(max != null); assert(max != null);
final Version parsedTargetVersion = Version.parse(targetVersion); final Version? parsedTargetVersion = Version.parse(targetVersion);
final Version minVersion = Version.parse(min); final Version? minVersion = Version.parse(min);
final Version maxVersion = Version.parse(max); final Version? maxVersion = Version.parse(max);
return minVersion != null && return minVersion != null &&
maxVersion != null && maxVersion != null &&
parsedTargetVersion != null && parsedTargetVersion != null &&
...@@ -193,8 +191,8 @@ String getGradleVersionFor(String androidPluginVersion) { ...@@ -193,8 +191,8 @@ String getGradleVersionFor(String androidPluginVersion) {
/// If [requireAndroidSdk] is true (the default) and no Android SDK is found, /// If [requireAndroidSdk] is true (the default) and no Android SDK is found,
/// this will fail with a [ToolExit]. /// this will fail with a [ToolExit].
void updateLocalProperties({ void updateLocalProperties({
@required FlutterProject project, required FlutterProject project,
BuildInfo buildInfo, BuildInfo? buildInfo,
bool requireAndroidSdk = true, bool requireAndroidSdk = true,
}) { }) {
if (requireAndroidSdk && globals.androidSdk == null) { if (requireAndroidSdk && globals.androidSdk == null) {
...@@ -211,7 +209,7 @@ void updateLocalProperties({ ...@@ -211,7 +209,7 @@ void updateLocalProperties({
changed = true; changed = true;
} }
void changeIfNecessary(String key, String value) { void changeIfNecessary(String key, String? value) {
if (settings.values[key] == value) { if (settings.values[key] == value) {
return; return;
} }
...@@ -223,21 +221,21 @@ void updateLocalProperties({ ...@@ -223,21 +221,21 @@ void updateLocalProperties({
changed = true; changed = true;
} }
final AndroidSdk androidSdk = globals.androidSdk; final AndroidSdk? androidSdk = globals.androidSdk;
if (androidSdk != null) { if (androidSdk != null) {
changeIfNecessary('sdk.dir', globals.fsUtils.escapePath(androidSdk.directory.path)); changeIfNecessary('sdk.dir', globals.fsUtils.escapePath(androidSdk.directory.path));
} }
changeIfNecessary('flutter.sdk', globals.fsUtils.escapePath(Cache.flutterRoot)); changeIfNecessary('flutter.sdk', globals.fsUtils.escapePath(Cache.flutterRoot!));
if (buildInfo != null) { if (buildInfo != null) {
changeIfNecessary('flutter.buildMode', buildInfo.modeName); changeIfNecessary('flutter.buildMode', buildInfo.modeName);
final String buildName = validatedBuildNameForPlatform( final String? buildName = validatedBuildNameForPlatform(
TargetPlatform.android_arm, TargetPlatform.android_arm,
buildInfo.buildName ?? project.manifest.buildName, buildInfo.buildName ?? project.manifest.buildName,
globals.logger, globals.logger,
); );
changeIfNecessary('flutter.versionName', buildName); changeIfNecessary('flutter.versionName', buildName);
final String buildNumber = validatedBuildNumberForPlatform( final String? buildNumber = validatedBuildNumberForPlatform(
TargetPlatform.android_arm, TargetPlatform.android_arm,
buildInfo.buildNumber ?? project.manifest.buildNumber, buildInfo.buildNumber ?? project.manifest.buildNumber,
globals.logger, globals.logger,
...@@ -255,7 +253,7 @@ void updateLocalProperties({ ...@@ -255,7 +253,7 @@ void updateLocalProperties({
/// Writes the path to the Android SDK, if known. /// Writes the path to the Android SDK, if known.
void writeLocalProperties(File properties) { void writeLocalProperties(File properties) {
final SettingsFile settings = SettingsFile(); final SettingsFile settings = SettingsFile();
final AndroidSdk androidSdk = globals.androidSdk; final AndroidSdk? androidSdk = globals.androidSdk;
if (androidSdk != null) { if (androidSdk != null) {
settings.values['sdk.dir'] = globals.fsUtils.escapePath(androidSdk.directory.path); settings.values['sdk.dir'] = globals.fsUtils.escapePath(androidSdk.directory.path);
} }
......
...@@ -2,35 +2,21 @@ ...@@ -2,35 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:convert/convert.dart'; import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:meta/meta.dart';
import 'package:pool/pool.dart';
import 'asset.dart';
import 'base/common.dart';
import 'base/config.dart'; import 'base/config.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/logger.dart';
import 'build_info.dart'; import 'build_info.dart';
import 'build_system/build_system.dart';
import 'build_system/depfile.dart';
import 'build_system/targets/common.dart';
import 'cache.dart';
import 'convert.dart'; import 'convert.dart';
import 'devfs.dart';
import 'globals_null_migrated.dart' as globals; import 'globals_null_migrated.dart' as globals;
import 'project.dart';
String get defaultMainPath => globals.fs.path.join('lib', 'main.dart'); String get defaultMainPath => globals.fs.path.join('lib', 'main.dart');
const String defaultAssetBasePath = '.';
const String defaultManifestPath = 'pubspec.yaml'; const String defaultManifestPath = 'pubspec.yaml';
String get defaultDepfilePath => globals.fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d'); String get defaultDepfilePath => globals.fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
String getDefaultApplicationKernelPath({ String getDefaultApplicationKernelPath({
@required bool trackWidgetCreation, required bool trackWidgetCreation,
}) { }) {
return getKernelPathForTransformerOptions( return getKernelPathForTransformerOptions(
globals.fs.path.join(getBuildDirectory(), 'app.dill'), globals.fs.path.join(getBuildDirectory(), 'app.dill'),
...@@ -39,15 +25,15 @@ String getDefaultApplicationKernelPath({ ...@@ -39,15 +25,15 @@ String getDefaultApplicationKernelPath({
} }
String getDefaultCachedKernelPath({ String getDefaultCachedKernelPath({
@required bool trackWidgetCreation, required bool trackWidgetCreation,
@required List<String> dartDefines, required List<String> dartDefines,
@required List<String> extraFrontEndOptions, List<String> extraFrontEndOptions = const <String>[],
FileSystem fileSystem, FileSystem? fileSystem,
Config config, Config? config,
}) { }) {
final StringBuffer buffer = StringBuffer(); final StringBuffer buffer = StringBuffer();
buffer.writeAll(dartDefines); buffer.writeAll(dartDefines);
buffer.writeAll(extraFrontEndOptions ?? <String>[]); buffer.writeAll(extraFrontEndOptions);
String buildPrefix = ''; String buildPrefix = '';
if (buffer.isNotEmpty) { if (buffer.isNotEmpty) {
final String output = buffer.toString(); final String output = buffer.toString();
...@@ -65,7 +51,7 @@ String getDefaultCachedKernelPath({ ...@@ -65,7 +51,7 @@ String getDefaultCachedKernelPath({
String getKernelPathForTransformerOptions( String getKernelPathForTransformerOptions(
String path, { String path, {
@required bool trackWidgetCreation, required bool trackWidgetCreation,
}) { }) {
if (trackWidgetCreation) { if (trackWidgetCreation) {
path += '.track.dill'; path += '.track.dill';
...@@ -74,151 +60,3 @@ String getKernelPathForTransformerOptions( ...@@ -74,151 +60,3 @@ String getKernelPathForTransformerOptions(
} }
const String defaultPrivateKeyPath = 'privatekey.der'; const String defaultPrivateKeyPath = 'privatekey.der';
/// Provides a `build` method that builds the bundle.
class BundleBuilder {
/// Builds the bundle for the given target platform.
///
/// The default `mainPath` is `lib/main.dart`.
/// The default `manifestPath` is `pubspec.yaml`
Future<void> build({
@required TargetPlatform platform,
@required BuildInfo buildInfo,
FlutterProject project,
String mainPath,
String manifestPath = defaultManifestPath,
String applicationKernelFilePath,
String depfilePath,
String assetDirPath,
@visibleForTesting BuildSystem buildSystem
}) async {
project ??= FlutterProject.current();
mainPath ??= defaultMainPath;
depfilePath ??= defaultDepfilePath;
assetDirPath ??= getAssetBuildDirectory();
buildSystem ??= globals.buildSystem;
// If the precompiled flag was not passed, force us into debug mode.
final Environment environment = Environment(
projectDir: project.directory,
outputDir: globals.fs.directory(assetDirPath),
buildDir: project.dartTool.childDirectory('flutter_build'),
cacheDir: globals.cache.getRoot(),
flutterRootDir: globals.fs.directory(Cache.flutterRoot),
engineVersion: globals.artifacts.isLocalEngine
? null
: globals.flutterVersion.engineRevision,
defines: <String, String>{
// used by the KernelSnapshot target
kTargetPlatform: getNameForTargetPlatform(platform),
kTargetFile: mainPath,
kDeferredComponents: 'false',
...buildInfo.toBuildSystemEnvironment(),
},
artifacts: globals.artifacts,
fileSystem: globals.fs,
logger: globals.logger,
processManager: globals.processManager,
platform: globals.platform,
generateDartPluginRegistry: true,
);
final Target target = buildInfo.mode == BuildMode.debug
? const CopyFlutterBundle()
: const ReleaseCopyFlutterBundle();
final BuildResult result = await buildSystem.build(target, environment);
if (!result.success) {
for (final ExceptionMeasurement measurement in result.exceptions.values) {
globals.printError('Target ${measurement.target} failed: ${measurement.exception}',
stackTrace: measurement.fatal
? measurement.stackTrace
: null,
);
}
throwToolExit('Failed to build bundle.');
}
if (depfilePath != null) {
final Depfile depfile = Depfile(result.inputFiles, result.outputFiles);
final File outputDepfile = globals.fs.file(depfilePath);
if (!outputDepfile.parent.existsSync()) {
outputDepfile.parent.createSync(recursive: true);
}
final DepfileService depfileService = DepfileService(
fileSystem: globals.fs,
logger: globals.logger,
);
depfileService.writeToFile(depfile, outputDepfile);
}
// Work around for flutter_tester placing kernel artifacts in odd places.
if (applicationKernelFilePath != null) {
final File outputDill = globals.fs.directory(assetDirPath).childFile('kernel_blob.bin');
if (outputDill.existsSync()) {
outputDill.copySync(applicationKernelFilePath);
}
}
return;
}
}
Future<AssetBundle> buildAssets({
String manifestPath,
String assetDirPath,
@required String packagesPath,
TargetPlatform targetPlatform,
}) async {
assetDirPath ??= getAssetBuildDirectory();
packagesPath ??= globals.fs.path.absolute(packagesPath);
// Build the asset bundle.
final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
final int result = await assetBundle.build(
manifestPath: manifestPath,
assetDirPath: assetDirPath,
packagesPath: packagesPath,
targetPlatform: targetPlatform,
);
if (result != 0) {
return null;
}
return assetBundle;
}
Future<void> writeBundle(
Directory bundleDir,
Map<String, DevFSContent> assetEntries,
{ Logger loggerOverride }
) async {
loggerOverride ??= globals.logger;
if (bundleDir.existsSync()) {
try {
bundleDir.deleteSync(recursive: true);
} on FileSystemException catch (err) {
loggerOverride.printError(
'Failed to clean up asset directory ${bundleDir.path}: $err\n'
'To clean build artifacts, use the command "flutter clean".'
);
}
}
bundleDir.createSync(recursive: true);
// Limit number of open files to avoid running out of file descriptors.
final Pool pool = Pool(64);
await Future.wait<void>(
assetEntries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
final PoolResource resource = await pool.request();
try {
// This will result in strange looking files, for example files with `/`
// on Windows or files that end up getting URI encoded such as `#.ext`
// to `%23.ext`. However, we have to keep it this way since the
// platform channels in the framework will URI encode these values,
// and the native APIs will look for files this way.
final File file = globals.fs.file(globals.fs.path.join(bundleDir.path, entry.key));
file.parent.createSync(recursive: true);
await file.writeAsBytes(await entry.value.contentsAsBytes());
} finally {
resource.release();
}
}));
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// 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' hide defaultManifestPath;
import 'base/common.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'build_info.dart';
import 'build_system/build_system.dart';
import 'build_system/depfile.dart';
import 'build_system/targets/common.dart';
import 'bundle.dart';
import 'cache.dart';
import 'devfs.dart';
import 'globals_null_migrated.dart' as globals;
import 'project.dart';
/// Provides a `build` method that builds the bundle.
class BundleBuilder {
/// Builds the bundle for the given target platform.
///
/// The default `mainPath` is `lib/main.dart`.
/// The default `manifestPath` is `pubspec.yaml`
Future<void> build({
@required TargetPlatform platform,
@required BuildInfo buildInfo,
FlutterProject project,
String mainPath,
String manifestPath = defaultManifestPath,
String applicationKernelFilePath,
String depfilePath,
String assetDirPath,
@visibleForTesting BuildSystem buildSystem
}) async {
project ??= FlutterProject.current();
mainPath ??= defaultMainPath;
depfilePath ??= defaultDepfilePath;
assetDirPath ??= getAssetBuildDirectory();
buildSystem ??= globals.buildSystem;
// If the precompiled flag was not passed, force us into debug mode.
final Environment environment = Environment(
projectDir: project.directory,
outputDir: globals.fs.directory(assetDirPath),
buildDir: project.dartTool.childDirectory('flutter_build'),
cacheDir: globals.cache.getRoot(),
flutterRootDir: globals.fs.directory(Cache.flutterRoot),
engineVersion: globals.artifacts.isLocalEngine
? null
: globals.flutterVersion.engineRevision,
defines: <String, String>{
// used by the KernelSnapshot target
kTargetPlatform: getNameForTargetPlatform(platform),
kTargetFile: mainPath,
kDeferredComponents: 'false',
...buildInfo.toBuildSystemEnvironment(),
},
artifacts: globals.artifacts,
fileSystem: globals.fs,
logger: globals.logger,
processManager: globals.processManager,
platform: globals.platform,
generateDartPluginRegistry: true,
);
final Target target = buildInfo.mode == BuildMode.debug
? const CopyFlutterBundle()
: const ReleaseCopyFlutterBundle();
final BuildResult result = await buildSystem.build(target, environment);
if (!result.success) {
for (final ExceptionMeasurement measurement in result.exceptions.values) {
globals.printError('Target ${measurement.target} failed: ${measurement.exception}',
stackTrace: measurement.fatal
? measurement.stackTrace
: null,
);
}
throwToolExit('Failed to build bundle.');
}
if (depfilePath != null) {
final Depfile depfile = Depfile(result.inputFiles, result.outputFiles);
final File outputDepfile = globals.fs.file(depfilePath);
if (!outputDepfile.parent.existsSync()) {
outputDepfile.parent.createSync(recursive: true);
}
final DepfileService depfileService = DepfileService(
fileSystem: globals.fs,
logger: globals.logger,
);
depfileService.writeToFile(depfile, outputDepfile);
}
// Work around for flutter_tester placing kernel artifacts in odd places.
if (applicationKernelFilePath != null) {
final File outputDill = globals.fs.directory(assetDirPath).childFile('kernel_blob.bin');
if (outputDill.existsSync()) {
outputDill.copySync(applicationKernelFilePath);
}
}
return;
}
}
Future<AssetBundle> buildAssets({
String manifestPath,
String assetDirPath,
@required String packagesPath,
TargetPlatform targetPlatform,
}) async {
assetDirPath ??= getAssetBuildDirectory();
packagesPath ??= globals.fs.path.absolute(packagesPath);
// Build the asset bundle.
final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
final int result = await assetBundle.build(
manifestPath: manifestPath,
assetDirPath: assetDirPath,
packagesPath: packagesPath,
targetPlatform: targetPlatform,
);
if (result != 0) {
return null;
}
return assetBundle;
}
Future<void> writeBundle(
Directory bundleDir,
Map<String, DevFSContent> assetEntries,
{ Logger loggerOverride }
) async {
loggerOverride ??= globals.logger;
if (bundleDir.existsSync()) {
try {
bundleDir.deleteSync(recursive: true);
} on FileSystemException catch (err) {
loggerOverride.printError(
'Failed to clean up asset directory ${bundleDir.path}: $err\n'
'To clean build artifacts, use the command "flutter clean".'
);
}
}
bundleDir.createSync(recursive: true);
// Limit number of open files to avoid running out of file descriptors.
final Pool pool = Pool(64);
await Future.wait<void>(
assetEntries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
final PoolResource resource = await pool.request();
try {
// This will result in strange looking files, for example files with `/`
// on Windows or files that end up getting URI encoded such as `#.ext`
// to `%23.ext`. However, we have to keep it this way since the
// platform channels in the framework will URI encode these values,
// and the native APIs will look for files this way.
final File file = globals.fs.file(globals.fs.path.join(bundleDir.path, entry.key));
file.parent.createSync(recursive: true);
await file.writeAsBytes(await entry.value.contentsAsBytes());
} finally {
resource.release();
}
}));
}
...@@ -2,21 +2,19 @@ ...@@ -2,21 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'project.dart'; import 'project.dart';
/// Extracts the `BINARY_NAME` from a project's CMake file. /// Extracts the `BINARY_NAME` from a project's CMake file.
/// ///
/// Returns `null` if it cannot be found. /// Returns `null` if it cannot be found.
String getCmakeExecutableName(CmakeBasedProject project) { String? getCmakeExecutableName(CmakeBasedProject project) {
if (!project.cmakeFile.existsSync()) { if (!project.cmakeFile.existsSync()) {
return null; return null;
} }
final RegExp nameSetPattern = RegExp(r'^\s*set\(BINARY_NAME\s*"(.*)"\s*\)\s*$'); final RegExp nameSetPattern = RegExp(r'^\s*set\(BINARY_NAME\s*"(.*)"\s*\)\s*$');
for (final String line in project.cmakeFile.readAsLinesSync()) { for (final String line in project.cmakeFile.readAsLinesSync()) {
final RegExpMatch match = nameSetPattern.firstMatch(line); final RegExpMatch? match = nameSetPattern.firstMatch(line);
if (match != null) { if (match != null) {
return match.group(1); return match.group(1);
} }
...@@ -27,13 +25,13 @@ String getCmakeExecutableName(CmakeBasedProject project) { ...@@ -27,13 +25,13 @@ String getCmakeExecutableName(CmakeBasedProject project) {
/// Extracts the `PACKAGE_GUID` from a project's CMake file. /// Extracts the `PACKAGE_GUID` from a project's CMake file.
/// ///
/// Returns `null` if it cannot be found. /// Returns `null` if it cannot be found.
String getCmakePackageGuid(File cmakeFile) { String? getCmakePackageGuid(File cmakeFile) {
if (!cmakeFile.existsSync()) { if (!cmakeFile.existsSync()) {
return null; return null;
} }
final RegExp nameSetPattern = RegExp(r'^\s*set\(PACKAGE_GUID\s*"(.*)"\s*\)\s*$'); final RegExp nameSetPattern = RegExp(r'^\s*set\(PACKAGE_GUID\s*"(.*)"\s*\)\s*$');
for (final String line in cmakeFile.readAsLinesSync()) { for (final String line in cmakeFile.readAsLinesSync()) {
final RegExpMatch match = nameSetPattern.firstMatch(line); final RegExpMatch? match = nameSetPattern.firstMatch(line);
if (match != null) { if (match != null) {
return match.group(1); return match.group(1);
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
import '../base/common.dart'; import '../base/common.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle.dart';
import '../bundle_builder.dart';
import '../features.dart'; import '../features.dart';
import '../globals_null_migrated.dart' as globals; import '../globals_null_migrated.dart' as globals;
import '../project.dart'; import '../project.dart';
......
...@@ -12,7 +12,7 @@ import '../asset.dart'; ...@@ -12,7 +12,7 @@ import '../asset.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle_builder.dart';
import '../devfs.dart'; import '../devfs.dart';
import '../device.dart'; import '../device.dart';
import '../globals_null_migrated.dart' as globals; import '../globals_null_migrated.dart' as globals;
......
...@@ -18,6 +18,7 @@ import '../base/process.dart'; ...@@ -18,6 +18,7 @@ import '../base/process.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle.dart';
import '../bundle_builder.dart';
import '../convert.dart'; import '../convert.dart';
import '../device.dart'; import '../device.dart';
import '../device_port_forwarder.dart'; import '../device_port_forwarder.dart';
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart'; import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as path; // flutter_ignore: package_path_import import 'package:path/path.dart' as path; // flutter_ignore: package_path_import
...@@ -22,25 +20,25 @@ import 'convert.dart'; ...@@ -22,25 +20,25 @@ import 'convert.dart';
import 'dart/language_version.dart'; import 'dart/language_version.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'features.dart'; import 'features.dart';
import 'globals.dart' as globals; import 'globals_null_migrated.dart' as globals;
import 'platform_plugins.dart'; import 'platform_plugins.dart';
import 'plugins.dart'; import 'plugins.dart';
import 'project.dart'; import 'project.dart';
void _renderTemplateToFile(String template, dynamic context, File file, TemplateRenderer templateRenderer) { void _renderTemplateToFile(String template, Object? context, File file, TemplateRenderer templateRenderer) {
final String renderedTemplate = templateRenderer final String renderedTemplate = templateRenderer
.renderString(template, context, htmlEscapeValues: false); .renderString(template, context, htmlEscapeValues: false);
file.createSync(recursive: true); file.createSync(recursive: true);
file.writeAsStringSync(renderedTemplate); file.writeAsStringSync(renderedTemplate);
} }
Plugin _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependencies, {FileSystem fileSystem}) { Plugin? _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependencies, {FileSystem? fileSystem}) {
final FileSystem fs = fileSystem ?? globals.fs; final FileSystem fs = fileSystem ?? globals.fs;
final File pubspecFile = fs.file(packageRoot.resolve('pubspec.yaml')); final File pubspecFile = fs.file(packageRoot.resolve('pubspec.yaml'));
if (!pubspecFile.existsSync()) { if (!pubspecFile.existsSync()) {
return null; return null;
} }
dynamic pubspec; Object? pubspec;
try { try {
pubspec = loadYaml(pubspecFile.readAsStringSync()); pubspec = loadYaml(pubspecFile.readAsStringSync());
...@@ -48,20 +46,20 @@ Plugin _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependenc ...@@ -48,20 +46,20 @@ Plugin _pluginFromPackage(String name, Uri packageRoot, Set<String> appDependenc
globals.printTrace('Failed to parse plugin manifest for $name: $err'); globals.printTrace('Failed to parse plugin manifest for $name: $err');
// Do nothing, potentially not a plugin. // Do nothing, potentially not a plugin.
} }
if (pubspec == null) { if (pubspec == null || pubspec is! YamlMap) {
return null; return null;
} }
final dynamic flutterConfig = pubspec['flutter']; final Object? flutterConfig = pubspec['flutter'];
if (flutterConfig == null || !(flutterConfig.containsKey('plugin') as bool)) { if (flutterConfig == null || flutterConfig is! YamlMap || !flutterConfig.containsKey('plugin')) {
return null; return null;
} }
final String packageRootPath = fs.path.fromUri(packageRoot); final String packageRootPath = fs.path.fromUri(packageRoot);
final YamlMap dependencies = pubspec['dependencies'] as YamlMap; final YamlMap? dependencies = pubspec['dependencies'] as YamlMap?;
globals.printTrace('Found plugin $name at $packageRootPath'); globals.printTrace('Found plugin $name at $packageRootPath');
return Plugin.fromYaml( return Plugin.fromYaml(
name, name,
packageRootPath, packageRootPath,
flutterConfig['plugin'] as YamlMap, flutterConfig['plugin'] as YamlMap?,
dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()], dependencies == null ? <String>[] : <String>[...dependencies.keys.cast<String>()],
fileSystem: fs, fileSystem: fs,
appDependencies: appDependencies, appDependencies: appDependencies,
...@@ -82,7 +80,7 @@ Future<List<Plugin>> findPlugins(FlutterProject project, { bool throwOnError = t ...@@ -82,7 +80,7 @@ Future<List<Plugin>> findPlugins(FlutterProject project, { bool throwOnError = t
); );
for (final Package package in packageConfig.packages) { for (final Package package in packageConfig.packages) {
final Uri packageRoot = package.packageUriRoot.resolve('..'); final Uri packageRoot = package.packageUriRoot.resolve('..');
final Plugin plugin = _pluginFromPackage( final Plugin? plugin = _pluginFromPackage(
package.name, package.name,
packageRoot, packageRoot,
project.manifest.dependencies, project.manifest.dependencies,
...@@ -102,15 +100,15 @@ const String _kFlutterPluginsPathKey = 'path'; ...@@ -102,15 +100,15 @@ const String _kFlutterPluginsPathKey = 'path';
const String _kFlutterPluginsDependenciesKey = 'dependencies'; const String _kFlutterPluginsDependenciesKey = 'dependencies';
/// Filters [plugins] to those supported by [platformKey]. /// Filters [plugins] to those supported by [platformKey].
List<Map<String, dynamic>> _filterPluginsByPlatform(List<Plugin> plugins, String platformKey) { List<Map<String, Object>> _filterPluginsByPlatform(List<Plugin> plugins, String platformKey) {
final Iterable<Plugin> platformPlugins = plugins.where((Plugin p) { final Iterable<Plugin> platformPlugins = plugins.where((Plugin p) {
return p.platforms.containsKey(platformKey); return p.platforms.containsKey(platformKey);
}); });
final Set<String> pluginNames = platformPlugins.map((Plugin plugin) => plugin.name).toSet(); final Set<String> pluginNames = platformPlugins.map((Plugin plugin) => plugin.name).toSet();
final List<Map<String, dynamic>> pluginInfo = <Map<String, dynamic>>[]; final List<Map<String, Object>> pluginInfo = <Map<String, Object>>[];
for (final Plugin plugin in platformPlugins) { for (final Plugin plugin in platformPlugins) {
pluginInfo.add(<String, dynamic>{ pluginInfo.add(<String, Object>{
_kFlutterPluginsNameKey: plugin.name, _kFlutterPluginsNameKey: plugin.name,
_kFlutterPluginsPathKey: globals.fsUtils.escapePath(plugin.path), _kFlutterPluginsPathKey: globals.fsUtils.escapePath(plugin.path),
_kFlutterPluginsDependenciesKey: <String>[...plugin.dependencies.where(pluginNames.contains)], _kFlutterPluginsDependenciesKey: <String>[...plugin.dependencies.where(pluginNames.contains)],
...@@ -179,7 +177,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) { ...@@ -179,7 +177,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
final String windowsKey = project.windows.pluginConfigKey; final String windowsKey = project.windows.pluginConfigKey;
final String webKey = project.web.pluginConfigKey; final String webKey = project.web.pluginConfigKey;
final Map<String, dynamic> pluginsMap = <String, dynamic>{}; final Map<String, Object> pluginsMap = <String, Object>{};
pluginsMap[iosKey] = _filterPluginsByPlatform(plugins, iosKey); pluginsMap[iosKey] = _filterPluginsByPlatform(plugins, iosKey);
pluginsMap[androidKey] = _filterPluginsByPlatform(plugins, androidKey); pluginsMap[androidKey] = _filterPluginsByPlatform(plugins, androidKey);
pluginsMap[macosKey] = _filterPluginsByPlatform(plugins, macosKey); pluginsMap[macosKey] = _filterPluginsByPlatform(plugins, macosKey);
...@@ -187,7 +185,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) { ...@@ -187,7 +185,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
pluginsMap[windowsKey] = _filterPluginsByPlatform(plugins, windowsKey); pluginsMap[windowsKey] = _filterPluginsByPlatform(plugins, windowsKey);
pluginsMap[webKey] = _filterPluginsByPlatform(plugins, webKey); pluginsMap[webKey] = _filterPluginsByPlatform(plugins, webKey);
final Map<String, dynamic> result = <String, dynamic> {}; final Map<String, Object> result = <String, Object> {};
result['info'] = 'This is a generated file; do not edit or check into version control.'; result['info'] = 'This is a generated file; do not edit or check into version control.';
result[_kFlutterPluginsPluginListKey] = pluginsMap; result[_kFlutterPluginsPluginListKey] = pluginsMap;
...@@ -200,7 +198,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) { ...@@ -200,7 +198,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
// Only notify if the plugins list has changed. [date_created] will always be different, // Only notify if the plugins list has changed. [date_created] will always be different,
// [version] is not relevant for this check. // [version] is not relevant for this check.
final String oldPluginsFileStringContent = _readFileContent(pluginsFile); final String? oldPluginsFileStringContent = _readFileContent(pluginsFile);
bool pluginsChanged = true; bool pluginsChanged = true;
if (oldPluginsFileStringContent != null) { if (oldPluginsFileStringContent != null) {
pluginsChanged = oldPluginsFileStringContent.contains(pluginsMap.toString()); pluginsChanged = oldPluginsFileStringContent.contains(pluginsMap.toString());
...@@ -211,12 +209,12 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) { ...@@ -211,12 +209,12 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
return pluginsChanged; return pluginsChanged;
} }
List<dynamic> _createPluginLegacyDependencyGraph(List<Plugin> plugins) { List<Object?> _createPluginLegacyDependencyGraph(List<Plugin> plugins) {
final List<dynamic> directAppDependencies = <dynamic>[]; final List<Object> directAppDependencies = <Object>[];
final Set<String> pluginNames = plugins.map((Plugin plugin) => plugin.name).toSet(); final Set<String> pluginNames = plugins.map((Plugin plugin) => plugin.name).toSet();
for (final Plugin plugin in plugins) { for (final Plugin plugin in plugins) {
directAppDependencies.add(<String, dynamic>{ directAppDependencies.add(<String, Object>{
'name': plugin.name, 'name': plugin.name,
// Extract the plugin dependencies which happen to be plugins. // Extract the plugin dependencies which happen to be plugins.
'dependencies': <String>[...plugin.dependencies.where(pluginNames.contains)], 'dependencies': <String>[...plugin.dependencies.where(pluginNames.contains)],
...@@ -245,7 +243,7 @@ bool _writeFlutterPluginsListLegacy(FlutterProject project, List<Plugin> plugins ...@@ -245,7 +243,7 @@ bool _writeFlutterPluginsListLegacy(FlutterProject project, List<Plugin> plugins
for (final Plugin plugin in plugins) { for (final Plugin plugin in plugins) {
flutterPluginsBuffer.write('${plugin.name}=${globals.fsUtils.escapePath(plugin.path)}\n'); flutterPluginsBuffer.write('${plugin.name}=${globals.fsUtils.escapePath(plugin.path)}\n');
} }
final String oldPluginFileContent = _readFileContent(pluginsFile); final String? oldPluginFileContent = _readFileContent(pluginsFile);
final String pluginFileContent = flutterPluginsBuffer.toString(); final String pluginFileContent = flutterPluginsBuffer.toString();
pluginsFile.writeAsStringSync(pluginFileContent, flush: true); pluginsFile.writeAsStringSync(pluginFileContent, flush: true);
...@@ -253,7 +251,7 @@ bool _writeFlutterPluginsListLegacy(FlutterProject project, List<Plugin> plugins ...@@ -253,7 +251,7 @@ bool _writeFlutterPluginsListLegacy(FlutterProject project, List<Plugin> plugins
} }
/// Returns the contents of [File] or [null] if that file does not exist. /// Returns the contents of [File] or [null] if that file does not exist.
String _readFileContent(File file) { String? _readFileContent(File file) {
return file.existsSync() ? file.readAsStringSync() : null; return file.existsSync() ? file.readAsStringSync() : null;
} }
...@@ -335,10 +333,10 @@ public final class GeneratedPluginRegistrant { ...@@ -335,10 +333,10 @@ public final class GeneratedPluginRegistrant {
} }
'''; ''';
List<Map<String, dynamic>> _extractPlatformMaps(List<Plugin> plugins, String type) { List<Map<String, Object?>> _extractPlatformMaps(List<Plugin> plugins, String type) {
final List<Map<String, dynamic>> pluginConfigs = <Map<String, dynamic>>[]; final List<Map<String, Object?>> pluginConfigs = <Map<String, Object?>>[];
for (final Plugin p in plugins) { for (final Plugin p in plugins) {
final PluginPlatform platformPlugin = p.platforms[type]; final PluginPlatform? platformPlugin = p.platforms[type];
if (platformPlugin != null) { if (platformPlugin != null) {
pluginConfigs.add(platformPlugin.toMap()); pluginConfigs.add(platformPlugin.toMap());
} }
...@@ -355,10 +353,10 @@ AndroidEmbeddingVersion _getAndroidEmbeddingVersion(FlutterProject project) { ...@@ -355,10 +353,10 @@ AndroidEmbeddingVersion _getAndroidEmbeddingVersion(FlutterProject project) {
} }
Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin> plugins) async { Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
final List<Map<String, dynamic>> androidPlugins = final List<Map<String, Object?>> androidPlugins =
_extractPlatformMaps(plugins, AndroidPlugin.kConfigKey); _extractPlatformMaps(plugins, AndroidPlugin.kConfigKey);
final Map<String, dynamic> templateContext = <String, dynamic>{ final Map<String, Object> templateContext = <String, Object>{
'plugins': androidPlugins, 'plugins': androidPlugins,
'androidX': isAppUsingAndroidX(project.android.hostAppGradleRoot), 'androidX': isAppUsingAndroidX(project.android.hostAppGradleRoot),
}; };
...@@ -382,8 +380,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin> ...@@ -382,8 +380,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
templateContext['needsShim'] = false; templateContext['needsShim'] = false;
// If a plugin is using an embedding version older than 2.0 and the app is using 2.0, // If a plugin is using an embedding version older than 2.0 and the app is using 2.0,
// then add shim for the old plugins. // then add shim for the old plugins.
for (final Map<String, dynamic> plugin in androidPlugins) { for (final Map<String, Object?> plugin in androidPlugins) {
if (plugin['supportsEmbeddingV1'] as bool && !(plugin['supportsEmbeddingV2'] as bool)) { final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) == true;
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) == true;
if (supportsEmbeddingV1 && !supportsEmbeddingV2) {
templateContext['needsShim'] = true; templateContext['needsShim'] = true;
if (project.isModule) { if (project.isModule) {
globals.printStatus( globals.printStatus(
...@@ -401,8 +401,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin> ...@@ -401,8 +401,10 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
break; break;
case AndroidEmbeddingVersion.v1: case AndroidEmbeddingVersion.v1:
default: default:
for (final Map<String, dynamic> plugin in androidPlugins) { for (final Map<String, Object?> plugin in androidPlugins) {
if (!(plugin['supportsEmbeddingV1'] as bool) && plugin['supportsEmbeddingV2'] as bool) { final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) == true;
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) == true;
if (!supportsEmbeddingV1 && supportsEmbeddingV2) {
throwToolExit( throwToolExit(
'The plugin `${plugin['name']}` requires your app to be migrated to ' 'The plugin `${plugin['name']}` requires your app to be migrated to '
'the Android embedding v2. Follow the steps on https://flutter.dev/go/android-project-migration ' 'the Android embedding v2. Follow the steps on https://flutter.dev/go/android-project-migration '
...@@ -711,8 +713,8 @@ void main(List<String> args) { ...@@ -711,8 +713,8 @@ void main(List<String> args) {
'''; ''';
Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async { Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
final List<Map<String, dynamic>> iosPlugins = _extractPlatformMaps(plugins, IOSPlugin.kConfigKey); final List<Map<String, Object?>> iosPlugins = _extractPlatformMaps(plugins, IOSPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{ final Map<String, Object> context = <String, Object>{
'os': 'ios', 'os': 'ios',
'deploymentTarget': '9.0', 'deploymentTarget': '9.0',
'framework': 'Flutter', 'framework': 'Flutter',
...@@ -761,8 +763,8 @@ String _cmakeRelativePluginSymlinkDirectoryPath(CmakeBasedProject project) { ...@@ -761,8 +763,8 @@ String _cmakeRelativePluginSymlinkDirectoryPath(CmakeBasedProject project) {
Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins) async { Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins) async {
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, LinuxPlugin.kConfigKey); final List<Plugin>nativePlugins = _filterNativePlugins(plugins, LinuxPlugin.kConfigKey);
final List<Map<String, dynamic>> linuxPlugins = _extractPlatformMaps(nativePlugins, LinuxPlugin.kConfigKey); final List<Map<String, Object?>> linuxPlugins = _extractPlatformMaps(nativePlugins, LinuxPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{ final Map<String, Object> context = <String, Object>{
'os': 'linux', 'os': 'linux',
'plugins': linuxPlugins, 'plugins': linuxPlugins,
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.linux), 'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.linux),
...@@ -771,7 +773,7 @@ Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins ...@@ -771,7 +773,7 @@ Future<void> _writeLinuxPluginFiles(FlutterProject project, List<Plugin> plugins
await _writePluginCmakefile(project.linux.generatedPluginCmakeFile, context, globals.templateRenderer); await _writePluginCmakefile(project.linux.generatedPluginCmakeFile, context, globals.templateRenderer);
} }
Future<void> _writeLinuxPluginRegistrant(Directory destination, Map<String, dynamic> templateContext) async { Future<void> _writeLinuxPluginRegistrant(Directory destination, Map<String, Object> templateContext) async {
_renderTemplateToFile( _renderTemplateToFile(
_linuxPluginRegistryHeaderTemplate, _linuxPluginRegistryHeaderTemplate,
templateContext, templateContext,
...@@ -786,7 +788,7 @@ Future<void> _writeLinuxPluginRegistrant(Directory destination, Map<String, dyna ...@@ -786,7 +788,7 @@ Future<void> _writeLinuxPluginRegistrant(Directory destination, Map<String, dyna
); );
} }
Future<void> _writePluginCmakefile(File destinationFile, Map<String, dynamic> templateContext, TemplateRenderer templateRenderer) async { Future<void> _writePluginCmakefile(File destinationFile, Map<String, Object> templateContext, TemplateRenderer templateRenderer) async {
_renderTemplateToFile( _renderTemplateToFile(
_pluginCmakefileTemplate, _pluginCmakefileTemplate,
templateContext, templateContext,
...@@ -797,8 +799,8 @@ Future<void> _writePluginCmakefile(File destinationFile, Map<String, dynamic> te ...@@ -797,8 +799,8 @@ Future<void> _writePluginCmakefile(File destinationFile, Map<String, dynamic> te
Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async { Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, MacOSPlugin.kConfigKey); final List<Plugin>nativePlugins = _filterNativePlugins(plugins, MacOSPlugin.kConfigKey);
final List<Map<String, dynamic>> macosPlugins = _extractPlatformMaps(nativePlugins, MacOSPlugin.kConfigKey); final List<Map<String, Object?>> macosPlugins = _extractPlatformMaps(nativePlugins, MacOSPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{ final Map<String, Object> context = <String, Object>{
'os': 'macos', 'os': 'macos',
'framework': 'FlutterMacOS', 'framework': 'FlutterMacOS',
'plugins': macosPlugins, 'plugins': macosPlugins,
...@@ -814,7 +816,7 @@ Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> pl ...@@ -814,7 +816,7 @@ Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> pl
/// Filters out Dart-only plugins, which shouldn't be added to the native generated registrants. /// Filters out Dart-only plugins, which shouldn't be added to the native generated registrants.
List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) { List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
return plugins.where((Plugin element) { return plugins.where((Plugin element) {
final PluginPlatform plugin = element.platforms[platformKey]; final PluginPlatform? plugin = element.platforms[platformKey];
if (plugin == null) { if (plugin == null) {
return false; return false;
} }
...@@ -830,7 +832,7 @@ List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) { ...@@ -830,7 +832,7 @@ List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
/// Returns only the plugins with the given platform variant. /// Returns only the plugins with the given platform variant.
List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, PluginPlatformVariant variant) { List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, PluginPlatformVariant variant) {
return plugins.where((Plugin element) { return plugins.where((Plugin element) {
final PluginPlatform platformPlugin = element.platforms[platformKey]; final PluginPlatform? platformPlugin = element.platforms[platformKey];
if (platformPlugin == null) { if (platformPlugin == null) {
return false; return false;
} }
...@@ -844,8 +846,8 @@ List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, P ...@@ -844,8 +846,8 @@ List<Plugin> _filterPluginsByVariant(List<Plugin> plugins, String platformKey, P
Future<void> writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async { Future<void> writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async {
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey); final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
final List<Plugin> win32Plugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.win32); final List<Plugin> win32Plugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.win32);
final List<Map<String, dynamic>> pluginInfo = _extractPlatformMaps(win32Plugins, WindowsPlugin.kConfigKey); final List<Map<String, Object?>> pluginInfo = _extractPlatformMaps(win32Plugins, WindowsPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{ final Map<String, Object> context = <String, Object>{
'os': 'windows', 'os': 'windows',
'plugins': pluginInfo, 'plugins': pluginInfo,
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windows), 'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windows),
...@@ -860,8 +862,8 @@ Future<void> writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugin ...@@ -860,8 +862,8 @@ Future<void> writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugin
Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async { Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plugins, TemplateRenderer templateRenderer) async {
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey); final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
final List<Plugin> uwpPlugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.winuwp); final List<Plugin> uwpPlugins = _filterPluginsByVariant(nativePlugins, WindowsPlugin.kConfigKey, PluginPlatformVariant.winuwp);
final List<Map<String, dynamic>> pluginInfo = _extractPlatformMaps(uwpPlugins, WindowsPlugin.kConfigKey); final List<Map<String, Object?>> pluginInfo = _extractPlatformMaps(uwpPlugins, WindowsPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{ final Map<String, Object> context = <String, Object>{
'os': 'windows', 'os': 'windows',
'plugins': pluginInfo, 'plugins': pluginInfo,
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windowsUwp), 'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windowsUwp),
...@@ -870,7 +872,7 @@ Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plu ...@@ -870,7 +872,7 @@ Future<void> writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plu
await _writePluginCmakefile(project.windowsUwp.generatedPluginCmakeFile, context, templateRenderer); await _writePluginCmakefile(project.windowsUwp.generatedPluginCmakeFile, context, templateRenderer);
} }
Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, dynamic> templateContext, TemplateRenderer templateRenderer) async { Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, Object> templateContext, TemplateRenderer templateRenderer) async {
_renderTemplateToFile( _renderTemplateToFile(
_cppPluginRegistryHeaderTemplate, _cppPluginRegistryHeaderTemplate,
templateContext, templateContext,
...@@ -886,13 +888,13 @@ Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, dynami ...@@ -886,13 +888,13 @@ Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, dynami
} }
Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plugins) async { Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
final List<Map<String, dynamic>> webPlugins = _extractPlatformMaps(plugins, WebPlugin.kConfigKey); final List<Map<String, Object?>> webPlugins = _extractPlatformMaps(plugins, WebPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{ final Map<String, Object> context = <String, Object>{
'plugins': webPlugins, 'plugins': webPlugins,
}; };
final File pluginFile = project.web.libDirectory.childFile('generated_plugin_registrant.dart'); final File pluginFile = project.web.libDirectory.childFile('generated_plugin_registrant.dart');
if (webPlugins.isEmpty) { if (webPlugins.isEmpty) {
return ErrorHandlingFileSystem.deleteIfExists(pluginFile); ErrorHandlingFileSystem.deleteIfExists(pluginFile);
} else { } else {
_renderTemplateToFile( _renderTemplateToFile(
_dartPluginRegistryTemplate, _dartPluginRegistryTemplate,
...@@ -911,34 +913,34 @@ Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plug ...@@ -911,34 +913,34 @@ Future<void> _writeWebPluginRegistrant(FlutterProject project, List<Plugin> plug
/// ///
/// This uses [project.flutterPluginsDependenciesFile], so it should only be /// This uses [project.flutterPluginsDependenciesFile], so it should only be
/// run after refreshPluginList has been run since the last plugin change. /// run after refreshPluginList has been run since the last plugin change.
void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleForTesting FeatureFlags featureFlagsOverride}) { void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleForTesting FeatureFlags? featureFlagsOverride}) {
final FeatureFlags localFeatureFlags = featureFlagsOverride ?? featureFlags; final FeatureFlags localFeatureFlags = featureFlagsOverride ?? featureFlags;
Map<String, dynamic> platformPlugins; Map<String, Object?>? platformPlugins;
final String pluginFileContent = _readFileContent(project.flutterPluginsDependenciesFile); final String? pluginFileContent = _readFileContent(project.flutterPluginsDependenciesFile);
if (pluginFileContent != null) { if (pluginFileContent != null) {
final Map<String, dynamic> pluginInfo = json.decode(pluginFileContent) as Map<String, dynamic>; final Map<String, Object?>? pluginInfo = json.decode(pluginFileContent) as Map<String, Object?>?;
platformPlugins = pluginInfo[_kFlutterPluginsPluginListKey] as Map<String, dynamic>; platformPlugins = pluginInfo?[_kFlutterPluginsPluginListKey] as Map<String, Object?>?;
} }
platformPlugins ??= <String, dynamic>{}; platformPlugins ??= <String, Object?>{};
if (localFeatureFlags.isWindowsEnabled && project.windows.existsSync()) { if (localFeatureFlags.isWindowsEnabled && project.windows.existsSync()) {
_createPlatformPluginSymlinks( _createPlatformPluginSymlinks(
project.windows.pluginSymlinkDirectory, project.windows.pluginSymlinkDirectory,
platformPlugins[project.windows.pluginConfigKey] as List<dynamic>, platformPlugins[project.windows.pluginConfigKey] as List<Object?>?,
force: force, force: force,
); );
} }
if (localFeatureFlags.isLinuxEnabled && project.linux.existsSync()) { if (localFeatureFlags.isLinuxEnabled && project.linux.existsSync()) {
_createPlatformPluginSymlinks( _createPlatformPluginSymlinks(
project.linux.pluginSymlinkDirectory, project.linux.pluginSymlinkDirectory,
platformPlugins[project.linux.pluginConfigKey] as List<dynamic>, platformPlugins[project.linux.pluginConfigKey] as List<Object?>?,
force: force, force: force,
); );
} }
if (localFeatureFlags.isWindowsUwpEnabled && project.windowsUwp.existsSync()) { if (localFeatureFlags.isWindowsUwpEnabled && project.windowsUwp.existsSync()) {
_createPlatformPluginSymlinks( _createPlatformPluginSymlinks(
project.windowsUwp.pluginSymlinkDirectory, project.windowsUwp.pluginSymlinkDirectory,
platformPlugins[project.windows.pluginConfigKey] as List<dynamic>, platformPlugins[project.windows.pluginConfigKey] as List<Object?>?,
force: force, force: force,
); );
} }
...@@ -948,12 +950,12 @@ void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleF ...@@ -948,12 +950,12 @@ void createPluginSymlinks(FlutterProject project, {bool force = false, @visibleF
/// failure cases. /// failure cases.
@visibleForTesting @visibleForTesting
void handleSymlinkException(FileSystemException e, { void handleSymlinkException(FileSystemException e, {
@required Platform platform, required Platform platform,
@required OperatingSystemUtils os, required OperatingSystemUtils os,
}) { }) {
if (platform.isWindows && (e.osError?.errorCode ?? 0) == 1314) { if (platform.isWindows && (e.osError?.errorCode ?? 0) == 1314) {
final String versionString = RegExp(r'[\d.]+').firstMatch(os.name)?.group(0); final String? versionString = RegExp(r'[\d.]+').firstMatch(os.name)?.group(0);
final Version version = Version.parse(versionString); final Version? version = Version.parse(versionString);
// Windows 10 14972 is the oldest version that allows creating symlinks // Windows 10 14972 is the oldest version that allows creating symlinks
// just by enabling developer mode; before that it requires running the // just by enabling developer mode; before that it requires running the
// terminal as Administrator. // terminal as Administrator.
...@@ -970,7 +972,7 @@ void handleSymlinkException(FileSystemException e, { ...@@ -970,7 +972,7 @@ void handleSymlinkException(FileSystemException e, {
/// Creates [symlinkDirectory] containing symlinks to each plugin listed in [platformPlugins]. /// Creates [symlinkDirectory] containing symlinks to each plugin listed in [platformPlugins].
/// ///
/// If [force] is true, the directory will be created only if missing. /// If [force] is true, the directory will be created only if missing.
void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<dynamic> platformPlugins, {bool force = false}) { void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<Object?>? platformPlugins, {bool force = false}) {
if (force && symlinkDirectory.existsSync()) { if (force && symlinkDirectory.existsSync()) {
// Start fresh to avoid stale links. // Start fresh to avoid stale links.
symlinkDirectory.deleteSync(recursive: true); symlinkDirectory.deleteSync(recursive: true);
...@@ -979,9 +981,9 @@ void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<dynamic> pla ...@@ -979,9 +981,9 @@ void _createPlatformPluginSymlinks(Directory symlinkDirectory, List<dynamic> pla
if (platformPlugins == null) { if (platformPlugins == null) {
return; return;
} }
for (final Map<String, dynamic> pluginInfo in platformPlugins.cast<Map<String, dynamic>>()) { for (final Map<String, Object?> pluginInfo in platformPlugins.cast<Map<String, Object?>>()) {
final String name = pluginInfo[_kFlutterPluginsNameKey] as String; final String name = pluginInfo[_kFlutterPluginsNameKey]! as String;
final String path = pluginInfo[_kFlutterPluginsPathKey] as String; final String path = pluginInfo[_kFlutterPluginsPathKey]! as String;
final Link link = symlinkDirectory.childLink(name); final Link link = symlinkDirectory.childLink(name);
if (link.existsSync()) { if (link.existsSync()) {
continue; continue;
...@@ -1015,10 +1017,10 @@ Future<void> refreshPluginsList( ...@@ -1015,10 +1017,10 @@ Future<void> refreshPluginsList(
if (changed || legacyChanged) { if (changed || legacyChanged) {
createPluginSymlinks(project, force: true); createPluginSymlinks(project, force: true);
if (iosPlatform) { if (iosPlatform) {
globals.cocoaPods.invalidatePodInstallOutput(project.ios); globals.cocoaPods?.invalidatePodInstallOutput(project.ios);
} }
if (macOSPlatform) { if (macOSPlatform) {
globals.cocoaPods.invalidatePodInstallOutput(project.macos); globals.cocoaPods?.invalidatePodInstallOutput(project.macos);
} }
} }
} }
...@@ -1064,12 +1066,12 @@ Future<void> injectPlugins( ...@@ -1064,12 +1066,12 @@ Future<void> injectPlugins(
]; ];
for (final XcodeBasedProject subproject in darwinProjects) { for (final XcodeBasedProject subproject in darwinProjects) {
if (plugins.isNotEmpty) { if (plugins.isNotEmpty) {
await globals.cocoaPods.setupPodfile(subproject); await globals.cocoaPods?.setupPodfile(subproject);
} }
/// The user may have a custom maintained Podfile that they're running `pod install` /// The user may have a custom maintained Podfile that they're running `pod install`
/// on themselves. /// on themselves.
else if (subproject.podfile.existsSync() && subproject.podfileLock.existsSync()) { else if (subproject.podfile.existsSync() && subproject.podfileLock.existsSync()) {
globals.cocoaPods.addPodsDependencyToFlutterXcconfig(subproject); globals.cocoaPods?.addPodsDependencyToFlutterXcconfig(subproject);
} }
} }
} }
...@@ -1119,9 +1121,9 @@ List<PluginInterfaceResolution> resolvePlatformImplementation( ...@@ -1119,9 +1121,9 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
continue; continue;
} }
// The plugin doesn't implement an interface, verify that it has a default implementation. // The plugin doesn't implement an interface, verify that it has a default implementation.
final String implementsPackage = plugin.implementsPackage; final String? implementsPackage = plugin.implementsPackage;
if (implementsPackage == null || implementsPackage.isEmpty) { if (implementsPackage == null || implementsPackage.isEmpty) {
final String defaultImplementation = plugin.defaultPackagePlatforms[platform]; final String? defaultImplementation = plugin.defaultPackagePlatforms[platform];
if (defaultImplementation == null) { if (defaultImplementation == null) {
if (throwOnPluginPubspecError) { if (throwOnPluginPubspecError) {
globals.printError( globals.printError(
...@@ -1153,7 +1155,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation( ...@@ -1153,7 +1155,7 @@ List<PluginInterfaceResolution> resolvePlatformImplementation(
} }
final String resolutionKey = '$platform/$implementsPackage'; final String resolutionKey = '$platform/$implementsPackage';
if (directDependencyResolutions.containsKey(resolutionKey)) { if (directDependencyResolutions.containsKey(resolutionKey)) {
final PluginInterfaceResolution currResolution = directDependencyResolutions[resolutionKey]; final PluginInterfaceResolution? currResolution = directDependencyResolutions[resolutionKey];
if (currResolution != null && currResolution.plugin.isDirectDependency) { if (currResolution != null && currResolution.plugin.isDirectDependency) {
if (plugin.isDirectDependency) { if (plugin.isDirectDependency) {
if (throwOnPluginPubspecError) { if (throwOnPluginPubspecError) {
...@@ -1223,14 +1225,14 @@ Future<void> generateMainDartWithPluginRegistrant( ...@@ -1223,14 +1225,14 @@ Future<void> generateMainDartWithPluginRegistrant(
final LanguageVersion entrypointVersion = determineLanguageVersion( final LanguageVersion entrypointVersion = determineLanguageVersion(
mainFile, mainFile,
packageConfig.packageOf(mainFile.absolute.uri), packageConfig.packageOf(mainFile.absolute.uri),
Cache.flutterRoot, Cache.flutterRoot!,
); );
final Map<String, dynamic> templateContext = <String, dynamic>{ final Map<String, Object> templateContext = <String, Object>{
'mainEntrypoint': currentMainUri, 'mainEntrypoint': currentMainUri,
'dartLanguageVersion': entrypointVersion.toString(), 'dartLanguageVersion': entrypointVersion.toString(),
LinuxPlugin.kConfigKey: <dynamic>[], LinuxPlugin.kConfigKey: <Object?>[],
MacOSPlugin.kConfigKey: <dynamic>[], MacOSPlugin.kConfigKey: <Object?>[],
WindowsPlugin.kConfigKey: <dynamic>[], WindowsPlugin.kConfigKey: <Object?>[],
}; };
if (resolutions.isEmpty) { if (resolutions.isEmpty) {
try { try {
...@@ -1248,7 +1250,7 @@ Future<void> generateMainDartWithPluginRegistrant( ...@@ -1248,7 +1250,7 @@ Future<void> generateMainDartWithPluginRegistrant(
} }
for (final PluginInterfaceResolution resolution in resolutions) { for (final PluginInterfaceResolution resolution in resolutions) {
assert(templateContext.containsKey(resolution.platform)); assert(templateContext.containsKey(resolution.platform));
(templateContext[resolution.platform] as List<dynamic>).add(resolution.toMap()); (templateContext[resolution.platform] as List<Object?>?)?.add(resolution.toMap());
} }
try { try {
_renderTemplateToFile( _renderTemplateToFile(
......
...@@ -13,7 +13,7 @@ import '../base/file_system.dart'; ...@@ -13,7 +13,7 @@ import '../base/file_system.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle_builder.dart';
import '../convert.dart'; import '../convert.dart';
import '../devfs.dart'; import '../devfs.dart';
import '../globals_null_migrated.dart' as globals; import '../globals_null_migrated.dart' as globals;
......
...@@ -4,17 +4,13 @@ ...@@ -4,17 +4,13 @@
// @dart = 2.8 // @dart = 2.8
import 'android/gradle_utils.dart';
import 'base/context.dart'; import 'base/context.dart';
import 'device.dart'; import 'device.dart';
import 'doctor.dart'; import 'doctor.dart';
import 'fuchsia/fuchsia_sdk.dart'; import 'fuchsia/fuchsia_sdk.dart';
import 'globals_null_migrated.dart' as globals;
import 'ios/simulators.dart'; import 'ios/simulators.dart';
import 'macos/cocoapods.dart';
import 'macos/cocoapods_validator.dart'; import 'macos/cocoapods_validator.dart';
import 'macos/xcdevice.dart'; import 'macos/xcdevice.dart';
import 'project.dart';
import 'reporting/crash_reporting.dart'; import 'reporting/crash_reporting.dart';
import 'runner/local_engine.dart'; import 'runner/local_engine.dart';
...@@ -24,22 +20,10 @@ CrashReporter get crashReporter => context.get<CrashReporter>(); ...@@ -24,22 +20,10 @@ CrashReporter get crashReporter => context.get<CrashReporter>();
Doctor get doctor => context.get<Doctor>(); Doctor get doctor => context.get<Doctor>();
DeviceManager get deviceManager => context.get<DeviceManager>(); DeviceManager get deviceManager => context.get<DeviceManager>();
FlutterProjectFactory get projectFactory {
return context.get<FlutterProjectFactory>() ?? FlutterProjectFactory(
logger: globals.logger,
fileSystem: globals.fs,
);
}
CocoaPodsValidator get cocoapodsValidator => context.get<CocoaPodsValidator>(); CocoaPodsValidator get cocoapodsValidator => context.get<CocoaPodsValidator>();
LocalEngineLocator get localEngineLocator => context.get<LocalEngineLocator>(); LocalEngineLocator get localEngineLocator => context.get<LocalEngineLocator>();
CocoaPods get cocoaPods => context.get<CocoaPods>();
FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>(); FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>(); IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>();
XCDevice get xcdevice => context.get<XCDevice>(); XCDevice get xcdevice => context.get<XCDevice>();
/// Gradle utils in the current [AppContext].
GradleUtils get gradleUtils => context.get<GradleUtils>();
...@@ -6,6 +6,7 @@ import 'package:process/process.dart'; ...@@ -6,6 +6,7 @@ import 'package:process/process.dart';
import 'android/android_sdk.dart'; import 'android/android_sdk.dart';
import 'android/android_studio.dart'; import 'android/android_studio.dart';
import 'android/gradle_utils.dart';
import 'artifacts.dart'; import 'artifacts.dart';
import 'base/bot_detector.dart'; import 'base/bot_detector.dart';
import 'base/config.dart'; import 'base/config.dart';
...@@ -28,8 +29,10 @@ import 'cache.dart'; ...@@ -28,8 +29,10 @@ import 'cache.dart';
import 'ios/ios_workflow.dart'; import 'ios/ios_workflow.dart';
import 'ios/plist_parser.dart'; import 'ios/plist_parser.dart';
import 'ios/xcodeproj.dart'; import 'ios/xcodeproj.dart';
import 'macos/cocoapods.dart';
import 'macos/xcode.dart'; import 'macos/xcode.dart';
import 'persistent_tool_state.dart'; import 'persistent_tool_state.dart';
import 'project.dart';
import 'reporting/reporting.dart'; import 'reporting/reporting.dart';
import 'version.dart'; import 'version.dart';
...@@ -196,3 +199,15 @@ LocalFileSystem get localFileSystem => _instance ??= LocalFileSystem( ...@@ -196,3 +199,15 @@ LocalFileSystem get localFileSystem => _instance ??= LocalFileSystem(
Signals.defaultExitSignals, Signals.defaultExitSignals,
shutdownHooks, shutdownHooks,
); );
/// Gradle utils in the current [AppContext].
GradleUtils? get gradleUtils => context.get<GradleUtils>();
CocoaPods? get cocoaPods => context.get<CocoaPods>();
FlutterProjectFactory get projectFactory {
return context.get<FlutterProjectFactory>() ?? FlutterProjectFactory(
logger: logger,
fileSystem: fs,
);
}
...@@ -2,10 +2,6 @@ ...@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../build_info.dart'; import '../build_info.dart';
...@@ -33,11 +29,11 @@ String flutterMacOSFrameworkDir(BuildMode mode, FileSystem fileSystem, ...@@ -33,11 +29,11 @@ String flutterMacOSFrameworkDir(BuildMode mode, FileSystem fileSystem,
/// targetOverride: Optional parameter, if null or unspecified the default value /// targetOverride: Optional parameter, if null or unspecified the default value
/// from xcode_backend.sh is used 'lib/main.dart'. /// from xcode_backend.sh is used 'lib/main.dart'.
Future<void> updateGeneratedXcodeProperties({ Future<void> updateGeneratedXcodeProperties({
@required FlutterProject project, required FlutterProject project,
@required BuildInfo buildInfo, required BuildInfo buildInfo,
String targetOverride, String? targetOverride,
bool useMacOSConfig = false, bool useMacOSConfig = false,
String buildDirOverride, String? buildDirOverride,
}) async { }) async {
final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines( final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines(
project: project, project: project,
...@@ -64,8 +60,8 @@ Future<void> updateGeneratedXcodeProperties({ ...@@ -64,8 +60,8 @@ Future<void> updateGeneratedXcodeProperties({
/// for Xcode targets that need them. /// for Xcode targets that need them.
/// See [XcodeBasedProject.generatedXcodePropertiesFile]. /// See [XcodeBasedProject.generatedXcodePropertiesFile].
void _updateGeneratedXcodePropertiesFile({ void _updateGeneratedXcodePropertiesFile({
@required FlutterProject project, required FlutterProject project,
@required List<String> xcodeBuildSettings, required List<String> xcodeBuildSettings,
bool useMacOSConfig = false, bool useMacOSConfig = false,
}) { }) {
final StringBuffer localsBuffer = StringBuffer(); final StringBuffer localsBuffer = StringBuffer();
...@@ -84,8 +80,8 @@ void _updateGeneratedXcodePropertiesFile({ ...@@ -84,8 +80,8 @@ void _updateGeneratedXcodePropertiesFile({
/// as flags for Flutter tools. /// as flags for Flutter tools.
/// See [XcodeBasedProject.generatedEnvironmentVariableExportScript]. /// See [XcodeBasedProject.generatedEnvironmentVariableExportScript].
void _updateGeneratedEnvironmentVariablesScript({ void _updateGeneratedEnvironmentVariablesScript({
@required FlutterProject project, required FlutterProject project,
@required List<String> xcodeBuildSettings, required List<String> xcodeBuildSettings,
bool useMacOSConfig = false, bool useMacOSConfig = false,
}) { }) {
final StringBuffer localsBuffer = StringBuffer(); final StringBuffer localsBuffer = StringBuffer();
...@@ -107,21 +103,21 @@ void _updateGeneratedEnvironmentVariablesScript({ ...@@ -107,21 +103,21 @@ void _updateGeneratedEnvironmentVariablesScript({
} }
/// Build name parsed and validated from build info and manifest. Used for CFBundleShortVersionString. /// Build name parsed and validated from build info and manifest. Used for CFBundleShortVersionString.
String parsedBuildName({ String? parsedBuildName({
@required FlutterManifest manifest, required FlutterManifest manifest,
BuildInfo buildInfo, BuildInfo? buildInfo,
}) { }) {
final String buildNameToParse = buildInfo?.buildName ?? manifest.buildName; final String? buildNameToParse = buildInfo?.buildName ?? manifest.buildName;
return validatedBuildNameForPlatform(TargetPlatform.ios, buildNameToParse, globals.logger); return validatedBuildNameForPlatform(TargetPlatform.ios, buildNameToParse, globals.logger);
} }
/// Build number parsed and validated from build info and manifest. Used for CFBundleVersion. /// Build number parsed and validated from build info and manifest. Used for CFBundleVersion.
String parsedBuildNumber({ String? parsedBuildNumber({
@required FlutterManifest manifest, required FlutterManifest manifest,
BuildInfo buildInfo, BuildInfo? buildInfo,
}) { }) {
String buildNumberToParse = buildInfo?.buildNumber ?? manifest.buildNumber; String? buildNumberToParse = buildInfo?.buildNumber ?? manifest.buildNumber;
final String buildNumber = validatedBuildNumberForPlatform( final String? buildNumber = validatedBuildNumberForPlatform(
TargetPlatform.ios, TargetPlatform.ios,
buildNumberToParse, buildNumberToParse,
globals.logger, globals.logger,
...@@ -141,15 +137,15 @@ String parsedBuildNumber({ ...@@ -141,15 +137,15 @@ String parsedBuildNumber({
/// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build' /// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build'
List<String> _xcodeBuildSettingsLines({ List<String> _xcodeBuildSettingsLines({
@required FlutterProject project, required FlutterProject project,
@required BuildInfo buildInfo, required BuildInfo buildInfo,
String targetOverride, String? targetOverride,
bool useMacOSConfig = false, bool useMacOSConfig = false,
String buildDirOverride, String? buildDirOverride,
}) { }) {
final List<String> xcodeBuildSettings = <String>[]; final List<String> xcodeBuildSettings = <String>[];
final String flutterRoot = globals.fs.path.normalize(Cache.flutterRoot); final String flutterRoot = globals.fs.path.normalize(Cache.flutterRoot!);
xcodeBuildSettings.add('FLUTTER_ROOT=$flutterRoot'); xcodeBuildSettings.add('FLUTTER_ROOT=$flutterRoot');
// This holds because requiresProjectRoot is true for this command // This holds because requiresProjectRoot is true for this command
...@@ -173,7 +169,7 @@ List<String> _xcodeBuildSettingsLines({ ...@@ -173,7 +169,7 @@ List<String> _xcodeBuildSettingsLines({
final String buildNumber = parsedBuildNumber(manifest: project.manifest, buildInfo: buildInfo) ?? '1'; final String buildNumber = parsedBuildNumber(manifest: project.manifest, buildInfo: buildInfo) ?? '1';
xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber'); xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber');
final Artifacts artifacts = globals.artifacts; final Artifacts? artifacts = globals.artifacts;
if (artifacts is LocalEngineArtifacts) { if (artifacts is LocalEngineArtifacts) {
final LocalEngineArtifacts localEngineArtifacts = artifacts; final LocalEngineArtifacts localEngineArtifacts = artifacts;
final String engineOutPath = localEngineArtifacts.engineOutPath; final String engineOutPath = localEngineArtifacts.engineOutPath;
......
...@@ -29,7 +29,7 @@ import '../base/net.dart'; ...@@ -29,7 +29,7 @@ import '../base/net.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../build_system/targets/web.dart'; import '../build_system/targets/web.dart';
import '../bundle.dart'; import '../bundle_builder.dart';
import '../cache.dart'; import '../cache.dart';
import '../compile.dart'; import '../compile.dart';
import '../convert.dart'; import '../convert.dart';
......
...@@ -2,10 +2,7 @@ ...@@ -2,10 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../base/common.dart'; import '../base/common.dart';
...@@ -85,12 +82,12 @@ const Version cocoaPodsRecommendedVersion = Version.withText(1, 10, 0, '1.10.0') ...@@ -85,12 +82,12 @@ const Version cocoaPodsRecommendedVersion = Version.withText(1, 10, 0, '1.10.0')
/// installing iOS/macOS dependencies. /// installing iOS/macOS dependencies.
class CocoaPods { class CocoaPods {
CocoaPods({ CocoaPods({
@required FileSystem fileSystem, required FileSystem fileSystem,
@required ProcessManager processManager, required ProcessManager processManager,
@required XcodeProjectInterpreter xcodeProjectInterpreter, required XcodeProjectInterpreter xcodeProjectInterpreter,
@required Logger logger, required Logger logger,
@required Platform platform, required Platform platform,
@required Usage usage, required Usage usage,
}) : _fileSystem = fileSystem, }) : _fileSystem = fileSystem,
_processManager = processManager, _processManager = processManager,
_xcodeProjectInterpreter = xcodeProjectInterpreter, _xcodeProjectInterpreter = xcodeProjectInterpreter,
...@@ -112,33 +109,33 @@ class CocoaPods { ...@@ -112,33 +109,33 @@ class CocoaPods {
final Logger _logger; final Logger _logger;
final Usage _usage; final Usage _usage;
Future<String> _versionText; Future<String?>? _versionText;
Future<bool> get isInstalled => Future<bool> get isInstalled =>
_processUtils.exitsHappy(<String>['which', 'pod']); _processUtils.exitsHappy(<String>['which', 'pod']);
Future<String> get cocoaPodsVersionText { Future<String?> get cocoaPodsVersionText {
_versionText ??= _processUtils.run( _versionText ??= _processUtils.run(
<String>['pod', '--version'], <String>['pod', '--version'],
environment: <String, String>{ environment: <String, String>{
'LANG': 'en_US.UTF-8', 'LANG': 'en_US.UTF-8',
}, },
).then<String>((RunResult result) { ).then<String?>((RunResult result) {
return result.exitCode == 0 ? result.stdout.trim() : null; return result.exitCode == 0 ? result.stdout.trim() : null;
}, onError: (dynamic _) => null); }, onError: (dynamic _) => null);
return _versionText; return _versionText!;
} }
Future<CocoaPodsStatus> get evaluateCocoaPodsInstallation async { Future<CocoaPodsStatus> get evaluateCocoaPodsInstallation async {
if (!(await isInstalled)) { if (!(await isInstalled)) {
return CocoaPodsStatus.notInstalled; return CocoaPodsStatus.notInstalled;
} }
final String versionText = await cocoaPodsVersionText; final String? versionText = await cocoaPodsVersionText;
if (versionText == null) { if (versionText == null) {
return CocoaPodsStatus.brokenInstall; return CocoaPodsStatus.brokenInstall;
} }
try { try {
final Version installedVersion = Version.parse(versionText); final Version? installedVersion = Version.parse(versionText);
if (installedVersion == null) { if (installedVersion == null) {
return CocoaPodsStatus.unknownVersion; return CocoaPodsStatus.unknownVersion;
} }
...@@ -155,8 +152,8 @@ class CocoaPods { ...@@ -155,8 +152,8 @@ class CocoaPods {
} }
Future<bool> processPods({ Future<bool> processPods({
@required XcodeBasedProject xcodeProject, required XcodeBasedProject xcodeProject,
@required BuildMode buildMode, required BuildMode buildMode,
bool dependenciesChanged = true, bool dependenciesChanged = true,
}) async { }) async {
if (!xcodeProject.podfile.existsSync()) { if (!xcodeProject.podfile.existsSync()) {
...@@ -253,7 +250,7 @@ class CocoaPods { ...@@ -253,7 +250,7 @@ class CocoaPods {
podfileTemplateName = isSwift ? 'Podfile-ios-swift' : 'Podfile-ios-objc'; podfileTemplateName = isSwift ? 'Podfile-ios-swift' : 'Podfile-ios-objc';
} }
final File podfileTemplate = _fileSystem.file(_fileSystem.path.join( final File podfileTemplate = _fileSystem.file(_fileSystem.path.join(
Cache.flutterRoot, Cache.flutterRoot!,
'packages', 'packages',
'flutter_tools', 'flutter_tools',
'templates', 'templates',
...@@ -391,7 +388,7 @@ class CocoaPods { ...@@ -391,7 +388,7 @@ class CocoaPods {
// //
// Warn the user if they are still symlinking to the framework. // Warn the user if they are still symlinking to the framework.
final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join( final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join(
(xcodeProject as IosProject).symlinks.path, xcodeProject.symlinks.path,
'flutter', 'flutter',
)); ));
if (flutterSymlink.existsSync()) { if (flutterSymlink.existsSync()) {
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:xml/xml.dart'; import 'package:xml/xml.dart';
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
...@@ -20,7 +18,7 @@ import 'cmake.dart'; ...@@ -20,7 +18,7 @@ import 'cmake.dart';
import 'features.dart'; import 'features.dart';
import 'flutter_manifest.dart'; import 'flutter_manifest.dart';
import 'flutter_plugins.dart'; import 'flutter_plugins.dart';
import 'globals.dart' as globals; import 'globals_null_migrated.dart' as globals;
import 'ios/plist_parser.dart'; import 'ios/plist_parser.dart';
import 'ios/xcode_build_settings.dart' as xcode; import 'ios/xcode_build_settings.dart' as xcode;
import 'ios/xcodeproj.dart'; import 'ios/xcodeproj.dart';
...@@ -29,8 +27,8 @@ import 'template.dart'; ...@@ -29,8 +27,8 @@ import 'template.dart';
class FlutterProjectFactory { class FlutterProjectFactory {
FlutterProjectFactory({ FlutterProjectFactory({
@required Logger logger, required Logger logger,
@required FileSystem fileSystem, required FileSystem fileSystem,
}) : _logger = logger, }) : _logger = logger,
_fileSystem = fileSystem; _fileSystem = fileSystem;
...@@ -89,7 +87,7 @@ class FlutterProject { ...@@ -89,7 +87,7 @@ class FlutterProject {
/// Create a [FlutterProject] and bypass the project caching. /// Create a [FlutterProject] and bypass the project caching.
@visibleForTesting @visibleForTesting
static FlutterProject fromDirectoryTest(Directory directory, [Logger logger]) { static FlutterProject fromDirectoryTest(Directory directory, [Logger? logger]) {
final FileSystem fileSystem = directory.fileSystem; final FileSystem fileSystem = directory.fileSystem;
logger ??= BufferLogger.test(); logger ??= BufferLogger.test();
final FlutterManifest manifest = FlutterProject._readManifest( final FlutterManifest manifest = FlutterProject._readManifest(
...@@ -126,14 +124,14 @@ class FlutterProject { ...@@ -126,14 +124,14 @@ class FlutterProject {
// Don't require iOS build info, this method is only // Don't require iOS build info, this method is only
// used during create as best-effort, use the // used during create as best-effort, use the
// default target bundle identifier. // default target bundle identifier.
final String bundleIdentifier = await ios.productBundleIdentifier(null); final String? bundleIdentifier = await ios.productBundleIdentifier(null);
if (bundleIdentifier != null) { if (bundleIdentifier != null) {
candidates.add(bundleIdentifier); candidates.add(bundleIdentifier);
} }
} }
if (android.existsSync()) { if (android.existsSync()) {
final String applicationId = android.applicationId; final String? applicationId = android.applicationId;
final String group = android.group; final String? group = android.group;
candidates.addAll(<String>[ candidates.addAll(<String>[
if (applicationId != null) if (applicationId != null)
applicationId, applicationId,
...@@ -142,21 +140,21 @@ class FlutterProject { ...@@ -142,21 +140,21 @@ class FlutterProject {
]); ]);
} }
if (example.android.existsSync()) { if (example.android.existsSync()) {
final String applicationId = example.android.applicationId; final String? applicationId = example.android.applicationId;
if (applicationId != null) { if (applicationId != null) {
candidates.add(applicationId); candidates.add(applicationId);
} }
} }
if (example.ios.existsSync()) { if (example.ios.existsSync()) {
final String bundleIdentifier = await example.ios.productBundleIdentifier(null); final String? bundleIdentifier = await example.ios.productBundleIdentifier(null);
if (bundleIdentifier != null) { if (bundleIdentifier != null) {
candidates.add(bundleIdentifier); candidates.add(bundleIdentifier);
} }
} }
return Set<String>.of(candidates.map<String>(_organizationNameFromPackageName).whereType<String>()); return Set<String>.of(candidates.map<String?>(_organizationNameFromPackageName).whereType<String>());
} }
String _organizationNameFromPackageName(String packageName) { String? _organizationNameFromPackageName(String packageName) {
if (packageName != null && 0 <= packageName.lastIndexOf('.')) { if (packageName != null && 0 <= packageName.lastIndexOf('.')) {
return packageName.substring(0, packageName.lastIndexOf('.')); return packageName.substring(0, packageName.lastIndexOf('.'));
} }
...@@ -164,35 +162,35 @@ class FlutterProject { ...@@ -164,35 +162,35 @@ class FlutterProject {
} }
/// The iOS sub project of this project. /// The iOS sub project of this project.
IosProject _ios; IosProject? _ios;
IosProject get ios => _ios ??= IosProject.fromFlutter(this); IosProject get ios => _ios ??= IosProject.fromFlutter(this);
/// The Android sub project of this project. /// The Android sub project of this project.
AndroidProject _android; AndroidProject? _android;
AndroidProject get android => _android ??= AndroidProject._(this); AndroidProject get android => _android ??= AndroidProject._(this);
/// The web sub project of this project. /// The web sub project of this project.
WebProject _web; WebProject? _web;
WebProject get web => _web ??= WebProject._(this); WebProject get web => _web ??= WebProject._(this);
/// The MacOS sub project of this project. /// The MacOS sub project of this project.
MacOSProject _macos; MacOSProject? _macos;
MacOSProject get macos => _macos ??= MacOSProject._(this); MacOSProject get macos => _macos ??= MacOSProject._(this);
/// The Linux sub project of this project. /// The Linux sub project of this project.
LinuxProject _linux; LinuxProject? _linux;
LinuxProject get linux => _linux ??= LinuxProject._(this); LinuxProject get linux => _linux ??= LinuxProject._(this);
/// The Windows sub project of this project. /// The Windows sub project of this project.
WindowsProject _windows; WindowsProject? _windows;
WindowsProject get windows => _windows ??= WindowsProject._(this); WindowsProject get windows => _windows ??= WindowsProject._(this);
/// The Windows UWP sub project of this project. /// The Windows UWP sub project of this project.
WindowsUwpProject _windowUwp; WindowsUwpProject? _windowUwp;
WindowsUwpProject get windowsUwp => _windowUwp ??= WindowsUwpProject._(this); WindowsUwpProject get windowsUwp => _windowUwp ??= WindowsUwpProject._(this);
/// The Fuchsia sub project of this project. /// The Fuchsia sub project of this project.
FuchsiaProject _fuchsia; FuchsiaProject? _fuchsia;
FuchsiaProject get fuchsia => _fuchsia ??= FuchsiaProject._(this); FuchsiaProject get fuchsia => _fuchsia ??= FuchsiaProject._(this);
/// The `pubspec.yaml` file of this project. /// The `pubspec.yaml` file of this project.
...@@ -256,10 +254,10 @@ class FlutterProject { ...@@ -256,10 +254,10 @@ class FlutterProject {
/// Completes with an empty [FlutterManifest], if the file does not exist. /// Completes with an empty [FlutterManifest], if the file does not exist.
/// Completes with a ToolExit on validation error. /// Completes with a ToolExit on validation error.
static FlutterManifest _readManifest(String path, { static FlutterManifest _readManifest(String path, {
@required Logger logger, required Logger logger,
@required FileSystem fileSystem, required FileSystem fileSystem,
}) { }) {
FlutterManifest manifest; FlutterManifest? manifest;
try { try {
manifest = FlutterManifest.createFromPath( manifest = FlutterManifest.createFromPath(
path, path,
...@@ -350,8 +348,8 @@ class FlutterProject { ...@@ -350,8 +348,8 @@ class FlutterProject {
/// Returns a json encoded string containing the [appName], [version], and [buildNumber] that is used to generate version.json /// Returns a json encoded string containing the [appName], [version], and [buildNumber] that is used to generate version.json
String getVersionInfo() { String getVersionInfo() {
final String buildName = manifest.buildName; final String? buildName = manifest.buildName;
final String buildNumber = manifest.buildNumber; final String? buildNumber = manifest.buildNumber;
final Map<String, String> versionFileJson = <String, String>{ final Map<String, String> versionFileJson = <String, String>{
'app_name': manifest.appName, 'app_name': manifest.appName,
if (buildName != null) if (buildName != null)
...@@ -534,16 +532,16 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -534,16 +532,16 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
/// The product bundle identifier of the host app, or null if not set or if /// The product bundle identifier of the host app, or null if not set or if
/// iOS tooling needed to read it is not installed. /// iOS tooling needed to read it is not installed.
Future<String> productBundleIdentifier(BuildInfo buildInfo) async { Future<String?> productBundleIdentifier(BuildInfo? buildInfo) async {
if (!existsSync()) { if (!existsSync()) {
return null; return null;
} }
return _productBundleIdentifier ??= await _parseProductBundleIdentifier(buildInfo); return _productBundleIdentifier ??= await _parseProductBundleIdentifier(buildInfo);
} }
String _productBundleIdentifier; String? _productBundleIdentifier;
Future<String> _parseProductBundleIdentifier(BuildInfo buildInfo) async { Future<String?> _parseProductBundleIdentifier(BuildInfo? buildInfo) async {
String fromPlist; String? fromPlist;
final File defaultInfoPlist = defaultHostInfoPlist; final File defaultInfoPlist = defaultHostInfoPlist;
// Users can change the location of the Info.plist. // Users can change the location of the Info.plist.
// Try parsing the default, first. // Try parsing the default, first.
...@@ -561,7 +559,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -561,7 +559,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
return fromPlist; return fromPlist;
} }
} }
final Map<String, String> allBuildSettings = await buildSettingsForBuildInfo(buildInfo); final Map<String, String>? allBuildSettings = await buildSettingsForBuildInfo(buildInfo);
if (allBuildSettings != null) { if (allBuildSettings != null) {
if (fromPlist != null) { if (fromPlist != null) {
// Perform variable substitution using build settings. // Perform variable substitution using build settings.
...@@ -576,7 +574,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -576,7 +574,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
// or companion watchOS projects. However, on non-macOS platforms this is // or companion watchOS projects. However, on non-macOS platforms this is
// only used for display purposes and to regenerate organization names, so // only used for display purposes and to regenerate organization names, so
// best-effort is probably fine. // best-effort is probably fine.
final String fromPbxproj = _firstMatchInFile(xcodeProjectInfoFile, _productBundleIdPattern)?.group(2); final String? fromPbxproj = _firstMatchInFile(xcodeProjectInfoFile, _productBundleIdPattern)?.group(2);
if (fromPbxproj != null && (fromPlist == null || fromPlist == _productBundleIdVariable)) { if (fromPbxproj != null && (fromPlist == null || fromPlist == _productBundleIdVariable)) {
return fromPbxproj; return fromPbxproj;
} }
...@@ -585,22 +583,22 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -585,22 +583,22 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
} }
/// The bundle name of the host app, `My App.app`. /// The bundle name of the host app, `My App.app`.
Future<String> hostAppBundleName(BuildInfo buildInfo) async { Future<String?> hostAppBundleName(BuildInfo buildInfo) async {
if (!existsSync()) { if (!existsSync()) {
return null; return null;
} }
return _hostAppBundleName ??= await _parseHostAppBundleName(buildInfo); return _hostAppBundleName ??= await _parseHostAppBundleName(buildInfo);
} }
String _hostAppBundleName; String? _hostAppBundleName;
Future<String> _parseHostAppBundleName(BuildInfo buildInfo) async { Future<String> _parseHostAppBundleName(BuildInfo buildInfo) async {
// The product name and bundle name are derived from the display name, which the user // The product name and bundle name are derived from the display name, which the user
// is instructed to change in Xcode as part of deploying to the App Store. // is instructed to change in Xcode as part of deploying to the App Store.
// https://flutter.dev/docs/deployment/ios#review-xcode-project-settings // https://flutter.dev/docs/deployment/ios#review-xcode-project-settings
// The only source of truth for the name is Xcode's interpretation of the build settings. // The only source of truth for the name is Xcode's interpretation of the build settings.
String productName; String? productName;
if (globals.xcodeProjectInterpreter.isInstalled) { if (globals.xcodeProjectInterpreter?.isInstalled == true) {
final Map<String, String> xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo); final Map<String, String>? xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo);
if (xcodeBuildSettings != null) { if (xcodeBuildSettings != null) {
productName = xcodeBuildSettings['FULL_PRODUCT_NAME']; productName = xcodeBuildSettings['FULL_PRODUCT_NAME'];
} }
...@@ -614,27 +612,28 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -614,27 +612,28 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
/// The build settings for the host app of this project, as a detached map. /// The build settings for the host app of this project, as a detached map.
/// ///
/// Returns null, if iOS tooling is unavailable. /// Returns null, if iOS tooling is unavailable.
Future<Map<String, String>> buildSettingsForBuildInfo(BuildInfo buildInfo, { EnvironmentType environmentType = EnvironmentType.physical }) async { Future<Map<String, String>?> buildSettingsForBuildInfo(BuildInfo? buildInfo, { EnvironmentType environmentType = EnvironmentType.physical }) async {
if (!existsSync()) { if (!existsSync()) {
return null; return null;
} }
final XcodeProjectInfo info = await projectInfo(); final XcodeProjectInfo? info = await projectInfo();
if (info == null) { if (info == null) {
return null; return null;
} }
final String scheme = info.schemeFor(buildInfo); final String? scheme = info.schemeFor(buildInfo);
if (scheme == null) { if (scheme == null) {
info.reportFlavorNotFoundAndExit(); info.reportFlavorNotFoundAndExit();
} }
final String configuration = (await projectInfo()).buildConfigurationFor( final String? configuration = (await projectInfo())?.buildConfigurationFor(
buildInfo, buildInfo,
scheme, scheme,
); );
final XcodeProjectBuildContext buildContext = XcodeProjectBuildContext(environmentType: environmentType, scheme: scheme, configuration: configuration); final XcodeProjectBuildContext buildContext = XcodeProjectBuildContext(environmentType: environmentType, scheme: scheme, configuration: configuration);
if (_buildSettingsByBuildContext[buildContext] == null) { final Map<String, String>? currentBuildSettings = _buildSettingsByBuildContext[buildContext];
final Map<String, String> calculatedBuildSettings = await _xcodeProjectBuildSettings(buildContext); if (currentBuildSettings == null) {
final Map<String, String>? calculatedBuildSettings = await _xcodeProjectBuildSettings(buildContext);
if (calculatedBuildSettings != null) { if (calculatedBuildSettings != null) {
_buildSettingsByBuildContext[buildContext] = calculatedBuildSettings; _buildSettingsByBuildContext[buildContext] = calculatedBuildSettings;
} }
...@@ -644,17 +643,17 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -644,17 +643,17 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
final Map<XcodeProjectBuildContext, Map<String, String>> _buildSettingsByBuildContext = <XcodeProjectBuildContext, Map<String, String>>{}; final Map<XcodeProjectBuildContext, Map<String, String>> _buildSettingsByBuildContext = <XcodeProjectBuildContext, Map<String, String>>{};
Future<XcodeProjectInfo> projectInfo() async { Future<XcodeProjectInfo?> projectInfo() async {
final XcodeProjectInterpreter xcodeProjectInterpreter = globals.xcodeProjectInterpreter; final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
if (!xcodeProject.existsSync() || xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) { if (!xcodeProject.existsSync() || xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
return null; return null;
} }
return _projectInfo ??= await xcodeProjectInterpreter.getInfo(hostAppRoot.path); return _projectInfo ??= await xcodeProjectInterpreter.getInfo(hostAppRoot.path);
} }
XcodeProjectInfo _projectInfo; XcodeProjectInfo? _projectInfo;
Future<Map<String, String>> _xcodeProjectBuildSettings(XcodeProjectBuildContext buildContext) async { Future<Map<String, String>?> _xcodeProjectBuildSettings(XcodeProjectBuildContext buildContext) async {
final XcodeProjectInterpreter xcodeProjectInterpreter = globals.xcodeProjectInterpreter; final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
if (xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) { if (xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
return null; return null;
} }
...@@ -680,7 +679,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -680,7 +679,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
/// Check if one the [targets] of the project is a watchOS companion app target. /// Check if one the [targets] of the project is a watchOS companion app target.
Future<bool> containsWatchCompanion(List<String> targets, BuildInfo buildInfo) async { Future<bool> containsWatchCompanion(List<String> targets, BuildInfo buildInfo) async {
final String bundleIdentifier = await productBundleIdentifier(buildInfo); final String? bundleIdentifier = await productBundleIdentifier(buildInfo);
// A bundle identifier is required for a companion app. // A bundle identifier is required for a companion app.
if (bundleIdentifier == null) { if (bundleIdentifier == null) {
return false; return false;
...@@ -748,7 +747,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -748,7 +747,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
// However, cocoapods will run before that script and requires something // However, cocoapods will run before that script and requires something
// to be in this location. // to be in this location.
final Directory framework = globals.fs.directory( final Directory framework = globals.fs.directory(
globals.artifacts.getArtifactPath( globals.artifacts?.getArtifactPath(
Artifact.flutterXcframework, Artifact.flutterXcframework,
platform: TargetPlatform.ios, platform: TargetPlatform.ios,
mode: mode, mode: mode,
...@@ -876,7 +875,7 @@ class AndroidProject extends FlutterProjectPlatform { ...@@ -876,7 +875,7 @@ class AndroidProject extends FlutterProjectPlatform {
/// Returns true if the current version of the Gradle plugin is supported. /// Returns true if the current version of the Gradle plugin is supported.
bool get isSupportedVersion => _isSupportedVersion ??= _computeSupportedVersion(); bool get isSupportedVersion => _isSupportedVersion ??= _computeSupportedVersion();
bool _isSupportedVersion; bool? _isSupportedVersion;
bool _computeSupportedVersion() { bool _computeSupportedVersion() {
final FileSystem fileSystem = hostAppGradleRoot.fileSystem; final FileSystem fileSystem = hostAppGradleRoot.fileSystem;
...@@ -927,12 +926,12 @@ class AndroidProject extends FlutterProjectPlatform { ...@@ -927,12 +926,12 @@ class AndroidProject extends FlutterProjectPlatform {
return hostAppGradleRoot.childFile('build.gradle').existsSync(); return hostAppGradleRoot.childFile('build.gradle').existsSync();
} }
String get applicationId { String? get applicationId {
final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle'); final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle');
return _firstMatchInFile(gradleFile, _applicationIdPattern)?.group(1); return _firstMatchInFile(gradleFile, _applicationIdPattern)?.group(1);
} }
String get group { String? get group {
final File gradleFile = hostAppGradleRoot.childFile('build.gradle'); final File gradleFile = hostAppGradleRoot.childFile('build.gradle');
return _firstMatchInFile(gradleFile, _groupPattern)?.group(1); return _firstMatchInFile(gradleFile, _groupPattern)?.group(1);
} }
...@@ -993,7 +992,7 @@ to migrate your project. ...@@ -993,7 +992,7 @@ to migrate your project.
'library_new_embedding', 'library_new_embedding',
), ephemeralDirectory); ), ephemeralDirectory);
await _overwriteFromTemplate(globals.fs.path.join('module', 'android', 'gradle'), ephemeralDirectory); await _overwriteFromTemplate(globals.fs.path.join('module', 'android', 'gradle'), ephemeralDirectory);
globals.gradleUtils.injectGradleWrapperIfNeeded(ephemeralDirectory); globals.gradleUtils?.injectGradleWrapperIfNeeded(ephemeralDirectory);
} }
Future<void> _overwriteFromTemplate(String path, Directory target) async { Future<void> _overwriteFromTemplate(String path, Directory target) async {
...@@ -1038,9 +1037,9 @@ to migrate your project. ...@@ -1038,9 +1037,9 @@ to migrate your project.
'Please ensure that you have read permission to this file and try again.'); 'Please ensure that you have read permission to this file and try again.');
} }
for (final XmlElement metaData in document.findAllElements('meta-data')) { for (final XmlElement metaData in document.findAllElements('meta-data')) {
final String name = metaData.getAttribute('android:name'); final String? name = metaData.getAttribute('android:name');
if (name == 'flutterEmbedding') { if (name == 'flutterEmbedding') {
final String embeddingVersionString = metaData.getAttribute('android:value'); final String? embeddingVersionString = metaData.getAttribute('android:value');
if (embeddingVersionString == '1') { if (embeddingVersionString == '1') {
return AndroidEmbeddingVersion.v1; return AndroidEmbeddingVersion.v1;
} }
...@@ -1102,12 +1101,12 @@ void _deleteIfExistsSync(Directory directory) { ...@@ -1102,12 +1101,12 @@ void _deleteIfExistsSync(Directory directory) {
/// Returns the first line-based match for [regExp] in [file]. /// Returns the first line-based match for [regExp] in [file].
/// ///
/// Assumes UTF8 encoding. /// Assumes UTF8 encoding.
Match _firstMatchInFile(File file, RegExp regExp) { Match? _firstMatchInFile(File file, RegExp regExp) {
if (!file.existsSync()) { if (!file.existsSync()) {
return null; return null;
} }
for (final String line in file.readAsLinesSync()) { for (final String line in file.readAsLinesSync()) {
final Match match = regExp.firstMatch(line); final Match? match = regExp.firstMatch(line);
if (match != null) { if (match != null) {
return match; return match;
} }
...@@ -1254,20 +1253,20 @@ class WindowsUwpProject extends WindowsProject { ...@@ -1254,20 +1253,20 @@ class WindowsUwpProject extends WindowsProject {
File get runnerCmakeFile => _editableDirectory.childDirectory('runner_uwp').childFile('CMakeLists.txt'); File get runnerCmakeFile => _editableDirectory.childDirectory('runner_uwp').childFile('CMakeLists.txt');
/// Eventually this will be used to check if the user's unstable project needs to be regenerated. /// Eventually this will be used to check if the user's unstable project needs to be regenerated.
int get projectVersion => int.tryParse(_editableDirectory.childFile('project_version').readAsStringSync()); int? get projectVersion => int.tryParse(_editableDirectory.childFile('project_version').readAsStringSync());
/// Retrieve the GUID of the UWP package. /// Retrieve the GUID of the UWP package.
String get packageGuid => _packageGuid ??= getCmakePackageGuid(runnerCmakeFile); String? get packageGuid => _packageGuid ??= getCmakePackageGuid(runnerCmakeFile);
String _packageGuid; String? _packageGuid;
File get appManifest => _editableDirectory.childDirectory('runner_uwp').childFile('appxmanifest.in'); File get appManifest => _editableDirectory.childDirectory('runner_uwp').childFile('appxmanifest.in');
String get packageVersion => _packageVersion ??= parseAppVersion(this); String? get packageVersion => _packageVersion ??= parseAppVersion(this);
String _packageVersion; String? _packageVersion;
} }
@visibleForTesting @visibleForTesting
String parseAppVersion(WindowsUwpProject project) { String? parseAppVersion(WindowsUwpProject project) {
final File appManifestFile = project.appManifest; final File appManifestFile = project.appManifest;
if (!appManifestFile.existsSync()) { if (!appManifestFile.existsSync()) {
return null; return null;
...@@ -1329,7 +1328,7 @@ class LinuxProject extends FlutterProjectPlatform implements CmakeBasedProject { ...@@ -1329,7 +1328,7 @@ class LinuxProject extends FlutterProjectPlatform implements CmakeBasedProject {
Future<void> ensureReadyForPlatformSpecificTooling() async {} Future<void> ensureReadyForPlatformSpecificTooling() async {}
String get applicationId { String? get applicationId {
return _firstMatchInFile(cmakeFile, _applicationIdPattern)?.group(1); return _firstMatchInFile(cmakeFile, _applicationIdPattern)?.group(1);
} }
} }
...@@ -1340,13 +1339,13 @@ class FuchsiaProject { ...@@ -1340,13 +1339,13 @@ class FuchsiaProject {
final FlutterProject project; final FlutterProject project;
Directory _editableHostAppDirectory; Directory? _editableHostAppDirectory;
Directory get editableHostAppDirectory => Directory get editableHostAppDirectory =>
_editableHostAppDirectory ??= project.directory.childDirectory('fuchsia'); _editableHostAppDirectory ??= project.directory.childDirectory('fuchsia');
bool existsSync() => editableHostAppDirectory.existsSync(); bool existsSync() => editableHostAppDirectory.existsSync();
Directory _meta; Directory? _meta;
Directory get meta => Directory get meta =>
_meta ??= editableHostAppDirectory.childDirectory('meta'); _meta ??= editableHostAppDirectory.childDirectory('meta');
} }
...@@ -18,6 +18,7 @@ import '../base/logger.dart'; ...@@ -18,6 +18,7 @@ import '../base/logger.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle.dart';
import '../bundle_builder.dart';
import '../desktop_device.dart'; import '../desktop_device.dart';
import '../devfs.dart'; import '../devfs.dart';
import '../device.dart'; import '../device.dart';
......
...@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/base/file_system.dart'; ...@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart'; 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/build_system.dart';
import 'package:flutter_tools/src/bundle.dart'; import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build_bundle.dart'; import 'package:flutter_tools/src/commands/build_bundle.dart';
import 'package:flutter_tools/src/features.dart'; import 'package:flutter_tools/src/features.dart';
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/gradle.dart'; import 'package:flutter_tools/src/android/gradle.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
...@@ -15,7 +13,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart'; ...@@ -15,7 +13,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart';
import '../../src/common.dart'; import '../../src/common.dart';
void main() { void main() {
FileSystem fileSystem; late FileSystem fileSystem;
setUp(() { setUp(() {
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/gradle_utils.dart'; import 'package:flutter_tools/src/android/gradle_utils.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
...@@ -17,9 +15,9 @@ import '../../src/fakes.dart'; ...@@ -17,9 +15,9 @@ import '../../src/fakes.dart';
void main() { void main() {
group('injectGradleWrapperIfNeeded', () { group('injectGradleWrapperIfNeeded', () {
MemoryFileSystem fileSystem; late MemoryFileSystem fileSystem;
Directory gradleWrapperDirectory; late Directory gradleWrapperDirectory;
GradleUtils gradleUtils; late GradleUtils gradleUtils;
setUp(() { setUp(() {
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
......
...@@ -2,13 +2,10 @@ ...@@ -2,13 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/platform_plugins.dart'; import 'package:flutter_tools/src/platform_plugins.dart';
import '../src/common.dart'; import '../src/common.dart';
void main() { void main() {
......
...@@ -11,7 +11,7 @@ import 'package:file/memory.dart'; ...@@ -11,7 +11,7 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/asset.dart'; import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/bundle.dart'; import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals; import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
......
...@@ -8,7 +8,7 @@ import 'package:file/memory.dart'; ...@@ -8,7 +8,7 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart'; 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/build_system.dart';
import 'package:flutter_tools/src/bundle.dart'; import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals; import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
......
...@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/logger.dart'; ...@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart'; 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/build_system.dart';
import 'package:flutter_tools/src/bundle.dart'; import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/custom_devices/custom_device.dart'; import 'package:flutter_tools/src/custom_devices/custom_device.dart';
import 'package:flutter_tools/src/custom_devices/custom_device_config.dart'; import 'package:flutter_tools/src/custom_devices/custom_device_config.dart';
......
...@@ -2,39 +2,35 @@ ...@@ -2,39 +2,35 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_tools/src/android/android_builder.dart'; import 'package:flutter_tools/src/android/android_builder.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals; import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
import 'package:meta/meta.dart';
/// A fake implementation of [AndroidBuilder]. /// A fake implementation of [AndroidBuilder].
class FakeAndroidBuilder implements AndroidBuilder { class FakeAndroidBuilder implements AndroidBuilder {
@override @override
Future<void> buildAar({ Future<void> buildAar({
@required FlutterProject project, required FlutterProject project,
@required Set<AndroidBuildInfo> androidBuildInfo, required Set<AndroidBuildInfo> androidBuildInfo,
@required String target, required String target,
@required String outputDirectoryPath, String? outputDirectoryPath,
@required String buildNumber, required String buildNumber,
}) async {} }) async {}
@override @override
Future<void> buildApk({ Future<void> buildApk({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
}) async {} }) async {}
@override @override
Future<void> buildAab({ Future<void> buildAab({
@required FlutterProject project, required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo, required AndroidBuildInfo androidBuildInfo,
@required String target, required String target,
bool validateDeferredComponents = true, bool validateDeferredComponents = true,
bool deferredComponentsEnabled = false, bool deferredComponentsEnabled = false,
}) async {} }) async {}
......
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