mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
Move async from member access to construction (#20035)
This commit is contained in:
parent
eda03e2586
commit
b280074815
|
@ -375,14 +375,15 @@ class AndroidDevice extends Device {
|
|||
|
||||
if (!prebuiltApplication) {
|
||||
printTrace('Building APK');
|
||||
final FlutterProject project = await FlutterProject.current();
|
||||
await buildApk(
|
||||
project: new FlutterProject(fs.currentDirectory),
|
||||
project: project,
|
||||
target: mainPath,
|
||||
buildInfo: buildInfo,
|
||||
);
|
||||
// Package has been built, so we can get the updated application ID and
|
||||
// activity name from the .apk.
|
||||
package = await AndroidApk.fromAndroidProject(new FlutterProject(fs.currentDirectory).android);
|
||||
package = await AndroidApk.fromAndroidProject(project.android);
|
||||
}
|
||||
|
||||
printTrace("Stopping app '${package.name}' on $name.");
|
||||
|
|
|
@ -90,7 +90,7 @@ Future<GradleProject> _gradleProject() async {
|
|||
// Note: Dependencies are resolved and possibly downloaded as a side-effect
|
||||
// of calculating the app properties using Gradle. This may take minutes.
|
||||
Future<GradleProject> _readGradleProject() async {
|
||||
final FlutterProject flutterProject = new FlutterProject(fs.currentDirectory);
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
final String gradle = await _ensureGradle(flutterProject);
|
||||
await updateLocalProperties(project: flutterProject);
|
||||
final Status status = logger.startProgress('Resolving dependencies...', expectSlowOperation: true);
|
||||
|
@ -214,7 +214,7 @@ Future<void> updateLocalProperties({
|
|||
throwToolExit('Unable to locate Android SDK. Please run `flutter doctor` for more details.');
|
||||
}
|
||||
|
||||
final File localProperties = await project.androidLocalPropertiesFile;
|
||||
final File localProperties = project.androidLocalPropertiesFile;
|
||||
bool changed = false;
|
||||
|
||||
SettingsFile settings;
|
||||
|
@ -232,7 +232,7 @@ Future<void> updateLocalProperties({
|
|||
}
|
||||
}
|
||||
|
||||
final FlutterManifest manifest = await project.manifest;
|
||||
final FlutterManifest manifest = project.manifest;
|
||||
|
||||
if (androidSdk != null)
|
||||
changeIfNecessary('sdk.dir', escapePath(androidSdk.directory));
|
||||
|
|
|
@ -314,7 +314,7 @@ Future<ApplicationPackage> getApplicationPackageForPlatform(
|
|||
case TargetPlatform.android_x64:
|
||||
case TargetPlatform.android_x86:
|
||||
return applicationBinary == null
|
||||
? await AndroidApk.fromAndroidProject(new FlutterProject(fs.currentDirectory).android)
|
||||
? await AndroidApk.fromAndroidProject((await FlutterProject.current()).android)
|
||||
: new AndroidApk.fromApk(applicationBinary);
|
||||
case TargetPlatform.ios:
|
||||
return applicationBinary == null
|
||||
|
@ -344,7 +344,7 @@ class ApplicationPackageStore {
|
|||
case TargetPlatform.android_arm64:
|
||||
case TargetPlatform.android_x64:
|
||||
case TargetPlatform.android_x86:
|
||||
android ??= await AndroidApk.fromAndroidProject(new FlutterProject(fs.currentDirectory).android);
|
||||
android ??= await AndroidApk.fromAndroidProject((await FlutterProject.current()).android);
|
||||
return android;
|
||||
case TargetPlatform.ios:
|
||||
iOS ??= new IOSApp.fromCurrentDirectory();
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import '../android/apk.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../project.dart';
|
||||
import 'build.dart';
|
||||
|
||||
|
@ -46,6 +45,10 @@ class BuildApkCommand extends BuildSubCommand {
|
|||
@override
|
||||
Future<Null> runCommand() async {
|
||||
await super.runCommand();
|
||||
await buildApk(project: new FlutterProject(fs.currentDirectory),target: targetFile, buildInfo: getBuildInfo());
|
||||
await buildApk(
|
||||
project: await FlutterProject.current(),
|
||||
target: targetFile,
|
||||
buildInfo: getBuildInfo(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,7 +135,8 @@ class CreateCommand extends FlutterCommand {
|
|||
dirPath = fs.path.dirname(dirPath);
|
||||
String organization = argResults['org'];
|
||||
if (!argResults.wasParsed('org')) {
|
||||
final Set<String> existingOrganizations = await new FlutterProject(projectDir).organizationNames();
|
||||
final FlutterProject project = await FlutterProject.fromDirectory(projectDir);
|
||||
final Set<String> existingOrganizations = await project.organizationNames();
|
||||
if (existingOrganizations.length == 1) {
|
||||
organization = existingOrganizations.first;
|
||||
} else if (1 < existingOrganizations.length) {
|
||||
|
@ -167,20 +168,20 @@ class CreateCommand extends FlutterCommand {
|
|||
);
|
||||
|
||||
printStatus('Creating project ${fs.path.relative(dirPath)}...');
|
||||
final Directory directory = fs.directory(dirPath);
|
||||
int generatedFileCount = 0;
|
||||
final FlutterProject project = new FlutterProject.fromPath(dirPath);
|
||||
switch (template) {
|
||||
case 'app':
|
||||
generatedFileCount += await _generateApp(project, templateContext);
|
||||
generatedFileCount += await _generateApp(directory, templateContext);
|
||||
break;
|
||||
case 'module':
|
||||
generatedFileCount += await _generateModule(project, templateContext);
|
||||
generatedFileCount += await _generateModule(directory, templateContext);
|
||||
break;
|
||||
case 'package':
|
||||
generatedFileCount += await _generatePackage(project, templateContext);
|
||||
generatedFileCount += await _generatePackage(directory, templateContext);
|
||||
break;
|
||||
case 'plugin':
|
||||
generatedFileCount += await _generatePlugin(project, templateContext);
|
||||
generatedFileCount += await _generatePlugin(directory, templateContext);
|
||||
break;
|
||||
}
|
||||
printStatus('Wrote $generatedFileCount files.');
|
||||
|
@ -193,6 +194,7 @@ class CreateCommand extends FlutterCommand {
|
|||
printStatus('Your module code is in lib/main.dart in the $relativePath directory.');
|
||||
} else {
|
||||
// Run doctor; tell the user the next steps.
|
||||
final FlutterProject project = await FlutterProject.fromPath(dirPath);
|
||||
final FlutterProject app = project.hasExampleApp ? project.example : project;
|
||||
final String relativeAppPath = fs.path.relative(app.directory.path);
|
||||
final String relativePluginPath = fs.path.relative(dirPath);
|
||||
|
@ -233,57 +235,57 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
|
|||
}
|
||||
}
|
||||
|
||||
Future<int> _generateModule(FlutterProject project, Map<String, dynamic> templateContext) async {
|
||||
Future<int> _generateModule(Directory directory, Map<String, dynamic> templateContext) async {
|
||||
int generatedCount = 0;
|
||||
final String description = argResults.wasParsed('description')
|
||||
? argResults['description']
|
||||
: 'A new flutter module project.';
|
||||
templateContext['description'] = description;
|
||||
generatedCount += _renderTemplate(fs.path.join('module', 'common'), project.directory, templateContext);
|
||||
generatedCount += _renderTemplate(fs.path.join('module', 'common'), directory, templateContext);
|
||||
if (argResults['pub']) {
|
||||
await pubGet(
|
||||
context: PubContext.create,
|
||||
directory: project.directory.path,
|
||||
directory: directory.path,
|
||||
offline: argResults['offline'],
|
||||
);
|
||||
final FlutterProject project = await FlutterProject.fromDirectory(directory);
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
}
|
||||
return generatedCount;
|
||||
}
|
||||
|
||||
Future<int> _generatePackage(FlutterProject project, Map<String, dynamic> templateContext) async {
|
||||
Future<int> _generatePackage(Directory directory, Map<String, dynamic> templateContext) async {
|
||||
int generatedCount = 0;
|
||||
final String description = argResults.wasParsed('description')
|
||||
? argResults['description']
|
||||
: 'A new flutter package project.';
|
||||
templateContext['description'] = description;
|
||||
generatedCount += _renderTemplate('package', project.directory, templateContext);
|
||||
|
||||
generatedCount += _renderTemplate('package', directory, templateContext);
|
||||
if (argResults['pub']) {
|
||||
await pubGet(
|
||||
context: PubContext.createPackage,
|
||||
directory: project.directory.path,
|
||||
directory: directory.path,
|
||||
offline: argResults['offline'],
|
||||
);
|
||||
}
|
||||
return generatedCount;
|
||||
}
|
||||
|
||||
Future<int> _generatePlugin(FlutterProject project, Map<String, dynamic> templateContext) async {
|
||||
Future<int> _generatePlugin(Directory directory, Map<String, dynamic> templateContext) async {
|
||||
int generatedCount = 0;
|
||||
final String description = argResults.wasParsed('description')
|
||||
? argResults['description']
|
||||
: 'A new flutter plugin project.';
|
||||
templateContext['description'] = description;
|
||||
generatedCount += _renderTemplate('plugin', project.directory, templateContext);
|
||||
|
||||
generatedCount += _renderTemplate('plugin', directory, templateContext);
|
||||
if (argResults['pub']) {
|
||||
await pubGet(
|
||||
context: PubContext.createPlugin,
|
||||
directory: project.directory.path,
|
||||
directory: directory.path,
|
||||
offline: argResults['offline'],
|
||||
);
|
||||
}
|
||||
final FlutterProject project = await FlutterProject.fromDirectory(directory);
|
||||
if (android_sdk.androidSdk != null)
|
||||
await gradle.updateLocalProperties(project: project);
|
||||
|
||||
|
@ -298,22 +300,23 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
|
|||
templateContext['pluginProjectName'] = projectName;
|
||||
templateContext['androidPluginIdentifier'] = androidPluginIdentifier;
|
||||
|
||||
generatedCount += await _generateApp(project.example, templateContext);
|
||||
generatedCount += await _generateApp(project.example.directory, templateContext);
|
||||
return generatedCount;
|
||||
}
|
||||
|
||||
Future<int> _generateApp(FlutterProject project, Map<String, dynamic> templateContext) async {
|
||||
Future<int> _generateApp(Directory directory, Map<String, dynamic> templateContext) async {
|
||||
int generatedCount = 0;
|
||||
generatedCount += _renderTemplate('create', project.directory, templateContext);
|
||||
generatedCount += _renderTemplate('create', directory, templateContext);
|
||||
final FlutterProject project = await FlutterProject.fromDirectory(directory);
|
||||
generatedCount += _injectGradleWrapper(project);
|
||||
|
||||
if (argResults['with-driver-test']) {
|
||||
final Directory testDirectory = project.directory.childDirectory('test_driver');
|
||||
final Directory testDirectory = directory.childDirectory('test_driver');
|
||||
generatedCount += _renderTemplate('driver', testDirectory, templateContext);
|
||||
}
|
||||
|
||||
if (argResults['pub']) {
|
||||
await pubGet(context: PubContext.create, directory: project.directory.path, offline: argResults['offline']);
|
||||
await pubGet(context: PubContext.create, directory: directory.path, offline: argResults['offline']);
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import '../base/file_system.dart';
|
||||
import '../globals.dart';
|
||||
import '../plugins.dart';
|
||||
import '../project.dart';
|
||||
|
@ -26,7 +25,7 @@ class InjectPluginsCommand extends FlutterCommand {
|
|||
|
||||
@override
|
||||
Future<Null> runCommand() async {
|
||||
final FlutterProject project = new FlutterProject(fs.currentDirectory);
|
||||
final FlutterProject project = await FlutterProject.current();
|
||||
await injectPlugins(project);
|
||||
final bool result = hasPlugins(project);
|
||||
if (result) {
|
||||
|
|
|
@ -80,7 +80,7 @@ class PackagesGetCommand extends FlutterCommand {
|
|||
}
|
||||
|
||||
await _runPubGet(target);
|
||||
final FlutterProject rootProject = new FlutterProject.fromPath(target);
|
||||
final FlutterProject rootProject = await FlutterProject.fromPath(target);
|
||||
await rootProject.ensureReadyForPlatformSpecificTooling();
|
||||
|
||||
// Get/upgrade packages in example app as well
|
||||
|
|
|
@ -20,6 +20,14 @@ final RegExp _versionPattern = new RegExp(r'^(\d+)(\.(\d+)(\.(\d+))?)?(\+(\d+))?
|
|||
class FlutterManifest {
|
||||
FlutterManifest._();
|
||||
|
||||
/// Returns an empty manifest.
|
||||
static FlutterManifest empty() {
|
||||
final FlutterManifest manifest = new FlutterManifest._();
|
||||
manifest._descriptor = <String, dynamic>{};
|
||||
manifest._flutterDescriptor = <String, dynamic>{};
|
||||
return manifest;
|
||||
}
|
||||
|
||||
/// Returns null on invalid manifest. Returns empty manifest on missing file.
|
||||
static Future<FlutterManifest> createFromPath(String path) async {
|
||||
if (path == null || !fs.isFileSync(path))
|
||||
|
|
|
@ -233,7 +233,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||
final Directory appDirectory = fs.directory(app.appDirectory);
|
||||
await _addServicesToBundle(appDirectory);
|
||||
|
||||
final FlutterProject project = new FlutterProject(fs.currentDirectory);
|
||||
final FlutterProject project = await FlutterProject.current();
|
||||
await updateGeneratedXcodeProperties(
|
||||
project: project,
|
||||
targetOverride: targetOverride,
|
||||
|
|
|
@ -32,9 +32,9 @@ String flutterFrameworkDir(BuildMode mode) {
|
|||
/// if project is an iOS project and such files are out of date or do not
|
||||
/// already exist.
|
||||
Future<void> generateXcodeProperties({FlutterProject project}) async {
|
||||
if ((await project.manifest).isModule ||
|
||||
if (project.manifest.isModule ||
|
||||
project.ios.directory.existsSync()) {
|
||||
if (!Cache.instance.fileOlderThanToolsStamp(await project.generatedXcodePropertiesFile)) {
|
||||
if (!Cache.instance.fileOlderThanToolsStamp(project.generatedXcodePropertiesFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ Future<void> updateGeneratedXcodeProperties({
|
|||
|
||||
localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
|
||||
|
||||
final FlutterManifest manifest = await project.manifest;
|
||||
final FlutterManifest manifest = project.manifest;
|
||||
if (!manifest.isModule) {
|
||||
// For module projects we do not want to write the FLUTTER_FRAMEWORK_DIR
|
||||
// explicitly. Rather we rely on the xcode backend script and the Podfile
|
||||
|
@ -119,7 +119,7 @@ Future<void> updateGeneratedXcodeProperties({
|
|||
localsBuffer.writeln('TRACK_WIDGET_CREATION=true');
|
||||
}
|
||||
|
||||
final File generatedXcodePropertiesFile = await project.generatedXcodePropertiesFile;
|
||||
final File generatedXcodePropertiesFile = project.generatedXcodePropertiesFile;
|
||||
generatedXcodePropertiesFile.createSync(recursive: true);
|
||||
generatedXcodePropertiesFile.writeAsStringSync(localsBuffer.toString());
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
|
|||
};
|
||||
|
||||
final String javaSourcePath = fs.path.join(
|
||||
(await project.androidPluginRegistrantHost).path,
|
||||
project.androidPluginRegistrantHost.path,
|
||||
'src',
|
||||
'main',
|
||||
'java',
|
||||
|
@ -247,8 +247,8 @@ Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plug
|
|||
'plugins': iosPlugins,
|
||||
};
|
||||
|
||||
final String registryDirectory = (await project.iosPluginRegistrantHost).path;
|
||||
if ((await project.manifest).isModule) {
|
||||
final String registryDirectory = project.iosPluginRegistrantHost.path;
|
||||
if (project.manifest.isModule) {
|
||||
final String registryClassesDirectory = fs.path.join(registryDirectory, 'Classes');
|
||||
_renderTemplateToFile(
|
||||
_iosPluginRegistrantPodspecTemplate,
|
||||
|
|
|
@ -15,20 +15,39 @@ import 'plugins.dart';
|
|||
import 'template.dart';
|
||||
|
||||
/// Represents the contents of a Flutter project at the specified [directory].
|
||||
///
|
||||
/// Instances should be treated as immutable snapshots, to be replaced by new
|
||||
/// instances on changes to `pubspec.yaml` files.
|
||||
class FlutterProject {
|
||||
FlutterProject._(this.directory, this.manifest, this._exampleManifest);
|
||||
|
||||
FlutterProject(this.directory);
|
||||
FlutterProject.fromPath(String projectPath) : directory = fs.directory(projectPath);
|
||||
/// Returns a future that completes with a FlutterProject view of the given directory.
|
||||
static Future<FlutterProject> fromDirectory(Directory directory) async {
|
||||
final FlutterManifest manifest = await FlutterManifest.createFromPath(
|
||||
directory.childFile(bundle.defaultManifestPath).path,
|
||||
);
|
||||
final Directory exampleDirectory = directory.childDirectory('example');
|
||||
final FlutterManifest exampleManifest = await FlutterManifest.createFromPath(
|
||||
exampleDirectory.childFile(bundle.defaultManifestPath).path,
|
||||
);
|
||||
return new FlutterProject._(directory, manifest, exampleManifest);
|
||||
}
|
||||
|
||||
/// Returns a future that completes with a FlutterProject view of the current directory.
|
||||
static Future<FlutterProject> current() => fromDirectory(fs.currentDirectory);
|
||||
|
||||
/// Returns a future that completes with a FlutterProject view of the given directory.
|
||||
static Future<FlutterProject> fromPath(String path) => fromDirectory(fs.directory(path));
|
||||
|
||||
/// The location of this project.
|
||||
final Directory directory;
|
||||
|
||||
Future<FlutterManifest> get manifest {
|
||||
return _manifest ??= FlutterManifest.createFromPath(
|
||||
directory.childFile(bundle.defaultManifestPath).path,
|
||||
);
|
||||
}
|
||||
Future<FlutterManifest> _manifest;
|
||||
/// The manifest of this project, or null, if `pubspec.yaml` is invalid.
|
||||
final FlutterManifest manifest;
|
||||
|
||||
/// The manifest of the example sub-project of this project, or null, if
|
||||
/// `example/pubspec.yaml` is invalid.
|
||||
final FlutterManifest _exampleManifest;
|
||||
|
||||
/// Asynchronously returns the organization names found in this project as
|
||||
/// part of iOS product bundle identifier, Android application ID, or
|
||||
|
@ -41,10 +60,9 @@ class FlutterProject {
|
|||
example.android.applicationId(),
|
||||
example.ios.productBundleIdentifier(),
|
||||
]);
|
||||
return new Set<String>.from(
|
||||
candidates.map(_organizationNameFromPackageName)
|
||||
.where((String name) => name != null)
|
||||
);
|
||||
return new Set<String>.from(candidates
|
||||
.map(_organizationNameFromPackageName)
|
||||
.where((String name) => name != null));
|
||||
}
|
||||
|
||||
String _organizationNameFromPackageName(String packageName) {
|
||||
|
@ -66,75 +84,52 @@ class FlutterProject {
|
|||
/// The generated IosModule sub project of this module project.
|
||||
IosModuleProject get iosModule => new IosModuleProject(directory.childDirectory('.ios'));
|
||||
|
||||
Future<File> get androidLocalPropertiesFile {
|
||||
return _androidLocalPropertiesFile ??= manifest.then<File>((FlutterManifest manifest) {
|
||||
return directory.childDirectory(manifest.isModule ? '.android' : 'android')
|
||||
.childFile('local.properties');
|
||||
});
|
||||
File get androidLocalPropertiesFile {
|
||||
return directory
|
||||
.childDirectory(manifest.isModule ? '.android' : 'android')
|
||||
.childFile('local.properties');
|
||||
}
|
||||
Future<File> _androidLocalPropertiesFile;
|
||||
|
||||
Future<File> get generatedXcodePropertiesFile {
|
||||
return _generatedXcodeProperties ??= manifest.then<File>((FlutterManifest manifest) {
|
||||
return directory.childDirectory(manifest.isModule ? '.ios' : 'ios')
|
||||
.childDirectory('Flutter')
|
||||
.childFile('Generated.xcconfig');
|
||||
});
|
||||
File get generatedXcodePropertiesFile {
|
||||
return directory
|
||||
.childDirectory(manifest.isModule ? '.ios' : 'ios')
|
||||
.childDirectory('Flutter')
|
||||
.childFile('Generated.xcconfig');
|
||||
}
|
||||
Future<File> _generatedXcodeProperties;
|
||||
|
||||
File get flutterPluginsFile {
|
||||
return _flutterPluginsFile ??= directory.childFile('.flutter-plugins');
|
||||
File get flutterPluginsFile => directory.childFile('.flutter-plugins');
|
||||
|
||||
Directory get androidPluginRegistrantHost {
|
||||
return manifest.isModule
|
||||
? directory.childDirectory('.android').childDirectory('Flutter')
|
||||
: directory.childDirectory('android').childDirectory('app');
|
||||
}
|
||||
File _flutterPluginsFile;
|
||||
|
||||
Future<Directory> get androidPluginRegistrantHost async {
|
||||
return _androidPluginRegistrantHost ??= manifest.then((FlutterManifest manifest) {
|
||||
if (manifest.isModule) {
|
||||
return directory.childDirectory('.android').childDirectory('Flutter');
|
||||
} else {
|
||||
return directory.childDirectory('android').childDirectory('app');
|
||||
}
|
||||
});
|
||||
Directory get iosPluginRegistrantHost {
|
||||
// In a module create the GeneratedPluginRegistrant as a pod to be included
|
||||
// from a hosting app.
|
||||
// For a non-module create the GeneratedPluginRegistrant as source files
|
||||
// directly in the iOS project.
|
||||
return manifest.isModule
|
||||
? directory.childDirectory('.ios').childDirectory('Flutter').childDirectory('FlutterPluginRegistrant')
|
||||
: directory.childDirectory('ios').childDirectory('Runner');
|
||||
}
|
||||
Future<Directory> _androidPluginRegistrantHost;
|
||||
|
||||
Future<Directory> get iosPluginRegistrantHost async {
|
||||
return _iosPluginRegistrantHost ??= manifest.then((FlutterManifest manifest) {
|
||||
if (manifest.isModule) {
|
||||
// In a module create the GeneratedPluginRegistrant as a pod to be included
|
||||
// from a hosting app.
|
||||
return directory
|
||||
.childDirectory('.ios')
|
||||
.childDirectory('Flutter')
|
||||
.childDirectory('FlutterPluginRegistrant');
|
||||
} else {
|
||||
// For a non-module create the GeneratedPluginRegistrant as source files
|
||||
// directly in the iOS project.
|
||||
return directory.childDirectory('ios').childDirectory('Runner');
|
||||
}
|
||||
});
|
||||
}
|
||||
Future<Directory> _iosPluginRegistrantHost;
|
||||
/// The example sub-project of this project.
|
||||
FlutterProject get example => new FlutterProject._(_exampleDirectory, _exampleManifest, FlutterManifest.empty());
|
||||
|
||||
/// Returns true if this project has an example application
|
||||
/// True, if this project has an example application
|
||||
bool get hasExampleApp => _exampleDirectory.childFile('pubspec.yaml').existsSync();
|
||||
|
||||
/// The example sub project of this (package or plugin) project.
|
||||
FlutterProject get example => new FlutterProject(_exampleDirectory);
|
||||
|
||||
/// The directory that will contain the example if an example exists.
|
||||
Directory get _exampleDirectory => directory.childDirectory('example');
|
||||
|
||||
/// Generates project files necessary to make Gradle builds work on Android
|
||||
/// and CocoaPods+Xcode work on iOS, for app and module projects only.
|
||||
///
|
||||
/// Returns the number of files written.
|
||||
Future<void> ensureReadyForPlatformSpecificTooling() async {
|
||||
if (!directory.existsSync() || hasExampleApp) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
final FlutterManifest manifest = await this.manifest;
|
||||
if (manifest.isModule) {
|
||||
await androidModule.ensureReadyForPlatformSpecificTooling(this);
|
||||
await iosModule.ensureReadyForPlatformSpecificTooling();
|
||||
|
@ -152,9 +147,7 @@ class IosProject {
|
|||
final Directory directory;
|
||||
|
||||
/// The xcode config file for [mode].
|
||||
File xcodeConfigFor(String mode) {
|
||||
return directory.childDirectory('Flutter').childFile('$mode.xcconfig');
|
||||
}
|
||||
File xcodeConfigFor(String mode) => directory.childDirectory('Flutter').childFile('$mode.xcconfig');
|
||||
|
||||
/// The 'Podfile'.
|
||||
File get podfile => directory.childFile('Podfile');
|
||||
|
@ -198,23 +191,16 @@ class AndroidProject {
|
|||
AndroidProject(this.directory);
|
||||
|
||||
File get gradleManifestFile {
|
||||
return _gradleManifestFile ??= isUsingGradle()
|
||||
return isUsingGradle()
|
||||
? fs.file(fs.path.join(directory.path, 'app', 'src', 'main', 'AndroidManifest.xml'))
|
||||
: directory.childFile('AndroidManifest.xml');
|
||||
}
|
||||
File _gradleManifestFile;
|
||||
|
||||
|
||||
File get gradleAppOutV1File {
|
||||
return _gradleAppOutV1File ??= gradleAppOutV1Directory.childFile('app-debug.apk');
|
||||
}
|
||||
File _gradleAppOutV1File;
|
||||
File get gradleAppOutV1File => gradleAppOutV1Directory.childFile('app-debug.apk');
|
||||
|
||||
Directory get gradleAppOutV1Directory {
|
||||
return _gradleAppOutV1Directory ??= fs.directory(fs.path.join(directory.path, 'app', 'build', 'outputs', 'apk'));
|
||||
return fs.directory(fs.path.join(directory.path, 'app', 'build', 'outputs', 'apk'));
|
||||
}
|
||||
Directory _gradleAppOutV1Directory;
|
||||
|
||||
|
||||
bool isUsingGradle() {
|
||||
return directory.childFile('build.gradle').existsSync();
|
||||
|
@ -233,8 +219,7 @@ class AndroidProject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents the contents of the .android-generated/ folder of a Flutter module
|
||||
/// project.
|
||||
/// Represents the contents of the .android/ folder of a Flutter module project.
|
||||
class AndroidModuleProject {
|
||||
AndroidModuleProject(this.directory);
|
||||
|
||||
|
@ -243,9 +228,13 @@ class AndroidModuleProject {
|
|||
Future<void> ensureReadyForPlatformSpecificTooling(FlutterProject project) async {
|
||||
if (_shouldRegenerate()) {
|
||||
final Template template = new Template.fromName(fs.path.join('module', 'android'));
|
||||
template.render(directory, <String, dynamic>{
|
||||
'androidIdentifier': (await project.manifest).moduleDescriptor['androidPackage'],
|
||||
}, printStatusWhenWriting: false);
|
||||
template.render(
|
||||
directory,
|
||||
<String, dynamic>{
|
||||
'androidIdentifier': project.manifest.moduleDescriptor['androidPackage'],
|
||||
},
|
||||
printStatusWhenWriting: false,
|
||||
);
|
||||
gradle.injectGradleWrapper(directory);
|
||||
}
|
||||
await gradle.updateLocalProperties(project: project, requireAndroidSdk: false);
|
||||
|
|
|
@ -276,7 +276,7 @@ class FlutterDevice {
|
|||
|
||||
if (package == null) {
|
||||
String message = 'No application found for $targetPlatform.';
|
||||
final String hint = getMissingPackageHintForPlatform(targetPlatform);
|
||||
final String hint = await getMissingPackageHintForPlatform(targetPlatform);
|
||||
if (hint != null)
|
||||
message += '\n$hint';
|
||||
printError(message);
|
||||
|
@ -335,7 +335,7 @@ class FlutterDevice {
|
|||
|
||||
if (package == null) {
|
||||
String message = 'No application found for $targetPlatform.';
|
||||
final String hint = getMissingPackageHintForPlatform(targetPlatform);
|
||||
final String hint = await getMissingPackageHintForPlatform(targetPlatform);
|
||||
if (hint != null)
|
||||
message += '\n$hint';
|
||||
printError(message);
|
||||
|
@ -898,13 +898,13 @@ String findMainDartFile([String target]) {
|
|||
return targetPath;
|
||||
}
|
||||
|
||||
String getMissingPackageHintForPlatform(TargetPlatform platform) {
|
||||
Future<String> getMissingPackageHintForPlatform(TargetPlatform platform) async {
|
||||
switch (platform) {
|
||||
case TargetPlatform.android_arm:
|
||||
case TargetPlatform.android_arm64:
|
||||
case TargetPlatform.android_x64:
|
||||
case TargetPlatform.android_x86:
|
||||
final FlutterProject project = new FlutterProject(fs.currentDirectory);
|
||||
final FlutterProject project = await FlutterProject.current();
|
||||
final String manifestPath = fs.path.relative(project.android.gradleManifestFile.path);
|
||||
return 'Is your project missing an $manifestPath?\nConsider running "flutter create ." to create one.';
|
||||
case TargetPlatform.ios:
|
||||
|
|
|
@ -332,7 +332,8 @@ abstract class FlutterCommand extends Command<Null> {
|
|||
|
||||
if (shouldRunPub) {
|
||||
await pubGet(context: PubContext.getVerifyContext(name));
|
||||
await new FlutterProject(fs.currentDirectory).ensureReadyForPlatformSpecificTooling();
|
||||
final FlutterProject project = await FlutterProject.current();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
}
|
||||
|
||||
setupApplicationPackages();
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:flutter_tools/src/android/gradle.dart';
|
|||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/flutter_manifest.dart';
|
||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
|
@ -21,6 +22,7 @@ import '../src/common.dart';
|
|||
import '../src/context.dart';
|
||||
|
||||
void main() {
|
||||
Cache.flutterRoot = getFlutterRoot();
|
||||
group('gradle build', () {
|
||||
test('do not crash if there is no Android SDK', () async {
|
||||
Exception shouldBeToolExit;
|
||||
|
@ -32,7 +34,7 @@ void main() {
|
|||
// This test is written to fail if our bots get Android SDKs in the future: shouldBeToolExit
|
||||
// will be null and our expectation would fail. That would remind us to make these tests
|
||||
// hermetic before adding Android SDKs to the bots.
|
||||
await updateLocalProperties(project: new FlutterProject(fs.currentDirectory));
|
||||
await updateLocalProperties(project: await FlutterProject.current());
|
||||
} on Exception catch (e) {
|
||||
shouldBeToolExit = e;
|
||||
}
|
||||
|
@ -190,7 +192,7 @@ someOtherProperty: someOtherValue
|
|||
|
||||
try {
|
||||
await updateLocalProperties(
|
||||
project: new FlutterProject.fromPath('path/to/project'),
|
||||
project: await FlutterProject.fromPath('path/to/project'),
|
||||
buildInfo: buildInfo,
|
||||
);
|
||||
|
||||
|
|
|
@ -344,8 +344,9 @@ void main() {
|
|||
);
|
||||
projectDir.childDirectory('ios').deleteSync(recursive: true);
|
||||
await _createProject(projectDir, <String>['--no-pub'], <String>[]);
|
||||
final FlutterProject project = await FlutterProject.fromDirectory(projectDir);
|
||||
expect(
|
||||
await new FlutterProject(projectDir).ios.productBundleIdentifier(),
|
||||
await project.ios.productBundleIdentifier(),
|
||||
'com.bar.foo.flutterProject',
|
||||
);
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
@ -370,8 +371,9 @@ void main() {
|
|||
'android/src/main/java/com/example/flutterproject/FlutterProjectPlugin.java',
|
||||
],
|
||||
);
|
||||
final FlutterProject project = await FlutterProject.fromDirectory(projectDir);
|
||||
expect(
|
||||
await new FlutterProject(projectDir).example.ios.productBundleIdentifier(),
|
||||
await project.example.ios.productBundleIdentifier(),
|
||||
'com.bar.foo.flutterProjectExample',
|
||||
);
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
|
|
@ -40,12 +40,12 @@ void main() {
|
|||
resultOfPodVersion = () async => exitsHappy(versionText);
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
setUp(() async {
|
||||
Cache.flutterRoot = 'flutter';
|
||||
fs = new MemoryFileSystem();
|
||||
mockProcessManager = new MockProcessManager();
|
||||
mockXcodeProjectInterpreter = new MockXcodeProjectInterpreter();
|
||||
projectUnderTest = new FlutterProject(fs.directory('project'));
|
||||
projectUnderTest = await FlutterProject.fromDirectory(fs.directory('project'));
|
||||
projectUnderTest.ios.directory.createSync(recursive: true);
|
||||
cocoaPodsUnderTest = new CocoaPods();
|
||||
pretendPodVersionIs('1.5.0');
|
||||
|
@ -138,7 +138,7 @@ void main() {
|
|||
'SWIFT_VERSION': '4.0',
|
||||
});
|
||||
|
||||
final FlutterProject project = new FlutterProject.fromPath('project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('project');
|
||||
cocoaPodsUnderTest.setupPodfile(project.ios);
|
||||
|
||||
expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Swift podfile template');
|
||||
|
@ -150,7 +150,7 @@ void main() {
|
|||
testUsingContext('does not recreate Podfile when already present', () async {
|
||||
projectUnderTest.ios.podfile..createSync()..writeAsStringSync('Existing Podfile');
|
||||
|
||||
final FlutterProject project = new FlutterProject.fromPath('project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('project');
|
||||
cocoaPodsUnderTest.setupPodfile(project.ios);
|
||||
|
||||
expect(projectUnderTest.ios.podfile.readAsStringSync(), 'Existing Podfile');
|
||||
|
@ -161,7 +161,7 @@ void main() {
|
|||
testUsingContext('does not create Podfile when we cannot interpret Xcode projects', () async {
|
||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
||||
|
||||
final FlutterProject project = new FlutterProject.fromPath('project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('project');
|
||||
cocoaPodsUnderTest.setupPodfile(project.ios);
|
||||
|
||||
expect(projectUnderTest.ios.podfile.existsSync(), false);
|
||||
|
@ -179,7 +179,7 @@ void main() {
|
|||
..createSync(recursive: true)
|
||||
..writeAsStringSync('Existing release config');
|
||||
|
||||
final FlutterProject project = new FlutterProject.fromPath('project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('project');
|
||||
cocoaPodsUnderTest.setupPodfile(project.ios);
|
||||
|
||||
final String debugContents = projectUnderTest.ios.xcodeConfigFor('Debug').readAsStringSync();
|
||||
|
|
|
@ -289,7 +289,7 @@ Information about project "Runner":
|
|||
previewDart2: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
final FlutterProject project = new FlutterProject.fromPath('path/to/project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('path/to/project');
|
||||
await updateGeneratedXcodeProperties(
|
||||
project: project,
|
||||
buildInfo: buildInfo,
|
||||
|
@ -311,7 +311,7 @@ Information about project "Runner":
|
|||
trackWidgetCreation: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
final FlutterProject project = new FlutterProject.fromPath('path/to/project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('path/to/project');
|
||||
await updateGeneratedXcodeProperties(
|
||||
project: project,
|
||||
buildInfo: buildInfo,
|
||||
|
@ -332,7 +332,7 @@ Information about project "Runner":
|
|||
previewDart2: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
final FlutterProject project = new FlutterProject.fromPath('path/to/project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('path/to/project');
|
||||
await updateGeneratedXcodeProperties(
|
||||
project: project,
|
||||
buildInfo: buildInfo,
|
||||
|
@ -354,7 +354,7 @@ Information about project "Runner":
|
|||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
|
||||
final FlutterProject project = new FlutterProject.fromPath('path/to/project');
|
||||
final FlutterProject project = await FlutterProject.fromPath('path/to/project');
|
||||
await updateGeneratedXcodeProperties(
|
||||
project: project,
|
||||
buildInfo: buildInfo,
|
||||
|
@ -405,7 +405,7 @@ Information about project "Runner":
|
|||
writeSchemaFile(fs, schemaData);
|
||||
|
||||
await updateGeneratedXcodeProperties(
|
||||
project: new FlutterProject.fromPath('path/to/project'),
|
||||
project: await FlutterProject.fromPath('path/to/project'),
|
||||
buildInfo: buildInfo,
|
||||
previewDart2: false,
|
||||
);
|
||||
|
|
|
@ -13,83 +13,83 @@ import 'src/context.dart';
|
|||
|
||||
void main() {
|
||||
group('Project', () {
|
||||
testInMemory('knows location', () {
|
||||
testInMemory('knows location', () async {
|
||||
final Directory directory = fs.directory('myproject');
|
||||
expect(
|
||||
new FlutterProject(directory).directory.absolute.path,
|
||||
(await FlutterProject.fromDirectory(directory)).directory.absolute.path,
|
||||
directory.absolute.path,
|
||||
);
|
||||
expect(
|
||||
new FlutterProject.fromPath(directory.path).directory.absolute.path,
|
||||
(await FlutterProject.fromPath(directory.path)).directory.absolute.path,
|
||||
directory.absolute.path,
|
||||
);
|
||||
});
|
||||
group('ensure ready for platform-specific tooling', () {
|
||||
testInMemory('does nothing, if project is not created', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.directory.existsSync(), isFalse);
|
||||
});
|
||||
testInMemory('does nothing in plugin or package root project', () async {
|
||||
final FlutterProject project = aPluginProject();
|
||||
final FlutterProject project = await aPluginProject();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isFalse);
|
||||
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isFalse);
|
||||
});
|
||||
testInMemory('injects plugins', () async {
|
||||
final FlutterProject project = aProjectWithIos();
|
||||
final FlutterProject project = await aProjectWithIos();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isTrue);
|
||||
});
|
||||
testInMemory('generates Xcode configuration', () async {
|
||||
final FlutterProject project = aProjectWithIos();
|
||||
final FlutterProject project = await aProjectWithIos();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isTrue);
|
||||
});
|
||||
});
|
||||
group('organization names set', () {
|
||||
testInMemory('is empty, if project not created', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
expect(await project.organizationNames(), isEmpty);
|
||||
});
|
||||
testInMemory('is empty, if no platform folders exist', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
project.directory.createSync();
|
||||
expect(await project.organizationNames(), isEmpty);
|
||||
});
|
||||
testInMemory('is populated from iOS bundle identifier', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
addIosWithBundleId(project.directory, 'io.flutter.someProject');
|
||||
expect(await project.organizationNames(), <String>['io.flutter']);
|
||||
});
|
||||
testInMemory('is populated from Android application ID', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
addAndroidWithApplicationId(project.directory, 'io.flutter.someproject');
|
||||
expect(await project.organizationNames(), <String>['io.flutter']);
|
||||
});
|
||||
testInMemory('is populated from iOS bundle identifier in plugin example', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
addIosWithBundleId(project.example.directory, 'io.flutter.someProject');
|
||||
expect(await project.organizationNames(), <String>['io.flutter']);
|
||||
});
|
||||
testInMemory('is populated from Android application ID in plugin example', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
addAndroidWithApplicationId(project.example.directory, 'io.flutter.someproject');
|
||||
expect(await project.organizationNames(), <String>['io.flutter']);
|
||||
});
|
||||
testInMemory('is populated from Android group in plugin', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
addAndroidWithGroup(project.directory, 'io.flutter.someproject');
|
||||
expect(await project.organizationNames(), <String>['io.flutter']);
|
||||
});
|
||||
testInMemory('is singleton, if sources agree', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
addIosWithBundleId(project.directory, 'io.flutter.someProject');
|
||||
addAndroidWithApplicationId(project.directory, 'io.flutter.someproject');
|
||||
expect(await project.organizationNames(), <String>['io.flutter']);
|
||||
});
|
||||
testInMemory('is non-singleton, if sources disagree', () async {
|
||||
final FlutterProject project = someProject();
|
||||
final FlutterProject project = await someProject();
|
||||
addIosWithBundleId(project.directory, 'io.flutter.someProject');
|
||||
addAndroidWithApplicationId(project.directory, 'io.clutter.someproject');
|
||||
expect(
|
||||
|
@ -101,22 +101,22 @@ void main() {
|
|||
});
|
||||
}
|
||||
|
||||
FlutterProject someProject() => new FlutterProject.fromPath('some_project');
|
||||
Future<FlutterProject> someProject() => FlutterProject.fromPath('some_project');
|
||||
|
||||
FlutterProject aProjectWithIos() {
|
||||
Future<FlutterProject> aProjectWithIos() {
|
||||
final Directory directory = fs.directory('ios_project');
|
||||
directory.childFile('pubspec.yaml').createSync(recursive: true);
|
||||
directory.childFile('.packages').createSync(recursive: true);
|
||||
directory.childDirectory('ios').createSync(recursive: true);
|
||||
return new FlutterProject(directory);
|
||||
return FlutterProject.fromDirectory(directory);
|
||||
}
|
||||
|
||||
FlutterProject aPluginProject() {
|
||||
Future<FlutterProject> aPluginProject() {
|
||||
final Directory directory = fs.directory('plugin_project/example');
|
||||
directory.childFile('pubspec.yaml').createSync(recursive: true);
|
||||
directory.childFile('.packages').createSync(recursive: true);
|
||||
directory.childDirectory('ios').createSync(recursive: true);
|
||||
return new FlutterProject(directory.parent);
|
||||
return FlutterProject.fromDirectory(directory.parent);
|
||||
}
|
||||
|
||||
void testInMemory(String description, Future<Null> testMethod()) {
|
||||
|
|
Loading…
Reference in a new issue