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