Unverified Commit 0ff9e8a9 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Rename 'application' back to 'module', and make 'app' the default again for templates. (#22888)

We decided that redefining the default for templates was premature. We're going to go back to having "module" in experimental land again, and we'll try again when we have the feature set fully baked.

This keeps the writing of the .metadata files, and writing the template type to them, because that was a good improvement, and there are still a bunch of added tests that improve our coverage.
parent e58e4732
...@@ -9,7 +9,7 @@ import 'package:flutter_devicelab/framework/framework.dart'; ...@@ -9,7 +9,7 @@ import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/utils.dart'; import 'package:flutter_devicelab/framework/utils.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
/// Tests that the Flutter application project template works and supports /// Tests that the Flutter module project template works and supports
/// adding Flutter to an existing Android app. /// adding Flutter to an existing Android app.
Future<void> main() async { Future<void> main() async {
await task(() async { await task(() async {
...@@ -21,15 +21,15 @@ Future<void> main() async { ...@@ -21,15 +21,15 @@ Future<void> main() async {
return TaskResult.failure('Could not find Java'); return TaskResult.failure('Could not find Java');
print('\nUsing JAVA_HOME=$javaHome'); print('\nUsing JAVA_HOME=$javaHome');
section('Create Flutter application project'); section('Create Flutter module project');
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_application_test.'); final Directory tempDir = Directory.systemTemp.createTempSync('flutter_module_test.');
final Directory projectDir = Directory(path.join(tempDir.path, 'hello')); final Directory projectDir = Directory(path.join(tempDir.path, 'hello'));
try { try {
await inDirectory(tempDir, () async { await inDirectory(tempDir, () async {
await flutter( await flutter(
'create', 'create',
options: <String>['--org', 'io.flutter.devicelab', '--template=application', 'hello'], options: <String>['--org', 'io.flutter.devicelab', '--template=module', 'hello'],
); );
}); });
...@@ -49,7 +49,7 @@ Future<void> main() async { ...@@ -49,7 +49,7 @@ Future<void> main() async {
); );
}); });
section('Build Flutter application library archive'); section('Build Flutter module library archive');
await inDirectory(Directory(path.join(projectDir.path, '.android')), () async { await inDirectory(Directory(path.join(projectDir.path, '.android')), () async {
await exec( await exec(
......
...@@ -10,20 +10,20 @@ import 'package:flutter_devicelab/framework/ios.dart'; ...@@ -10,20 +10,20 @@ import 'package:flutter_devicelab/framework/ios.dart';
import 'package:flutter_devicelab/framework/utils.dart'; import 'package:flutter_devicelab/framework/utils.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
/// Tests that the Flutter application project template works and supports /// Tests that the Flutter module project template works and supports
/// adding Flutter to an existing iOS app. /// adding Flutter to an existing iOS app.
Future<void> main() async { Future<void> main() async {
await task(() async { await task(() async {
section('Create Flutter application project'); section('Create Flutter module project');
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_application_test.'); final Directory tempDir = Directory.systemTemp.createTempSync('flutter_module_test.');
final Directory projectDir = Directory(path.join(tempDir.path, 'hello')); final Directory projectDir = Directory(path.join(tempDir.path, 'hello'));
try { try {
await inDirectory(tempDir, () async { await inDirectory(tempDir, () async {
await flutter( await flutter(
'create', 'create',
options: <String>['--org', 'io.flutter.devicelab', '--template=application', 'hello'], options: <String>['--org', 'io.flutter.devicelab', '--template=module', 'hello'],
); );
}); });
await prepareProvisioningCertificates(projectDir.path); await prepareProvisioningCertificates(projectDir.path);
......
...@@ -263,9 +263,9 @@ tasks: ...@@ -263,9 +263,9 @@ tasks:
stage: devicelab stage: devicelab
required_agent_capabilities: ["linux/android"] required_agent_capabilities: ["linux/android"]
application_test: module_test:
description: > description: >
Checks that the application project template works and supports add2app on Android. Checks that the module project template works and supports add2app on Android.
stage: devicelab stage: devicelab
required_agent_capabilities: ["linux/android"] required_agent_capabilities: ["linux/android"]
...@@ -297,9 +297,9 @@ tasks: ...@@ -297,9 +297,9 @@ tasks:
stage: devicelab_ios stage: devicelab_ios
required_agent_capabilities: ["mac/ios"] required_agent_capabilities: ["mac/ios"]
application_test_ios: module_test_ios:
description: > description: >
Checks that the application project template works and supports add2app on iOS. Checks that the module project template works and supports add2app on iOS.
stage: devicelab stage: devicelab
required_agent_capabilities: ["mac/ios"] required_agent_capabilities: ["mac/ios"]
......
...@@ -56,7 +56,7 @@ Future<void> main(List<String> args) async { ...@@ -56,7 +56,7 @@ Future<void> main(List<String> args) async {
ChannelCommand(verboseHelp: verboseHelp), ChannelCommand(verboseHelp: verboseHelp),
CleanCommand(), CleanCommand(),
ConfigCommand(verboseHelp: verboseHelp), ConfigCommand(verboseHelp: verboseHelp),
CreateCommand(verboseHelp: verboseHelp), CreateCommand(),
DaemonCommand(hidden: !verboseHelp), DaemonCommand(hidden: !verboseHelp),
DevicesCommand(), DevicesCommand(),
DoctorCommand(verbose: verbose), DoctorCommand(verbose: verbose),
......
...@@ -25,15 +25,13 @@ import '../template.dart'; ...@@ -25,15 +25,13 @@ import '../template.dart';
import '../version.dart'; import '../version.dart';
enum _ProjectType { enum _ProjectType {
/// This is the legacy "app" module type that was created before the default /// This is the default project with the user-managed host code.
/// was "application". It is kept around to allow users to recreate files that /// It is different than the "module" template in that it exposes and doesn't
/// have been removed in old projects. /// manage the platform code.
app, app,
/// The is the default type of project created. It is an application with /// The is a project that has managed platform host code. It is an application with
/// ephemeral .ios and .android directories that can be updated automatically. /// ephemeral .ios and .android directories that can be updated automatically.
application, module,
/// This is the old name for the [application] style project.
module, // TODO(gspencer): deprecated -- should be removed once IntelliJ no longer uses it.
/// This is a Flutter Dart package project. It doesn't have any native /// This is a Flutter Dart package project. It doesn't have any native
/// components, only Dart. /// components, only Dart.
package, package,
...@@ -43,11 +41,6 @@ enum _ProjectType { ...@@ -43,11 +41,6 @@ enum _ProjectType {
_ProjectType _stringToProjectType(String value) { _ProjectType _stringToProjectType(String value) {
_ProjectType result; _ProjectType result;
// TODO(gspencer): remove module when it is no longer used by IntelliJ plugin.
// Module is just an alias for application.
if (value == 'module') {
value = 'application';
}
for (_ProjectType type in _ProjectType.values) { for (_ProjectType type in _ProjectType.values) {
if (value == getEnumName(type)) { if (value == getEnumName(type)) {
result = type; result = type;
...@@ -58,7 +51,7 @@ _ProjectType _stringToProjectType(String value) { ...@@ -58,7 +51,7 @@ _ProjectType _stringToProjectType(String value) {
} }
class CreateCommand extends FlutterCommand { class CreateCommand extends FlutterCommand {
CreateCommand({bool verboseHelp = false }) { CreateCommand() {
argParser.addFlag('pub', argParser.addFlag('pub',
defaultsTo: true, defaultsTo: true,
help: 'Whether to run "flutter packages get" after the project has been created.' help: 'Whether to run "flutter packages get" after the project has been created.'
...@@ -82,23 +75,13 @@ class CreateCommand extends FlutterCommand { ...@@ -82,23 +75,13 @@ class CreateCommand extends FlutterCommand {
help: 'Specify the type of project to create.', help: 'Specify the type of project to create.',
valueHelp: 'type', valueHelp: 'type',
allowedHelp: <String, String>{ allowedHelp: <String, String>{
getEnumName(_ProjectType.application): '(default) Generate a Flutter application.', getEnumName(_ProjectType.app): '(default) Generate a Flutter application.',
getEnumName(_ProjectType.package): 'Generate a shareable Flutter project containing modular ' getEnumName(_ProjectType.package): 'Generate a shareable Flutter project containing modular '
'Dart code.', 'Dart code.',
getEnumName(_ProjectType.plugin): 'Generate a shareable Flutter project containing an API ' getEnumName(_ProjectType.plugin): 'Generate a shareable Flutter project containing an API '
'in Dart code with a platform-specific implementation for Android, for iOS code, or ' 'in Dart code with a platform-specific implementation for Android, for iOS code, or '
'for both.', 'for both.',
}..addAll(verboseHelp },
? <String, String>{
getEnumName(_ProjectType.app): 'Generate the legacy form of an application project. Use '
'"application" instead, unless you are working with an existing legacy app project. '
'This is not just an alias for the "application" template, it produces different '
'output.',
getEnumName(_ProjectType.module): 'Legacy, deprecated form of an application project. Use '
'"application" instead. This is just an alias for the "application" template, it '
'produces the same output. It will be removed in a future release.',
}
: <String, String>{}),
defaultsTo: null, defaultsTo: null,
); );
argParser.addOption( argParser.addOption(
...@@ -227,7 +210,7 @@ class CreateCommand extends FlutterCommand { ...@@ -227,7 +210,7 @@ class CreateCommand extends FlutterCommand {
} }
} }
} }
template ??= detectedProjectType ?? _ProjectType.application; template ??= detectedProjectType ?? _ProjectType.app;
if (detectedProjectType != null && template != detectedProjectType && metadataExists) { if (detectedProjectType != null && template != detectedProjectType && metadataExists) {
// We can only be definitive that this is the wrong type if the .metadata file // We can only be definitive that this is the wrong type if the .metadata file
// exists and contains a type that doesn't match. // exists and contains a type that doesn't match.
...@@ -235,7 +218,7 @@ class CreateCommand extends FlutterCommand { ...@@ -235,7 +218,7 @@ class CreateCommand extends FlutterCommand {
"existing template type of '${getEnumName(detectedProjectType)}'."); "existing template type of '${getEnumName(detectedProjectType)}'.");
} }
final bool generateApplication = template == _ProjectType.application; final bool generateModule = template == _ProjectType.module;
final bool generatePlugin = template == _ProjectType.plugin; final bool generatePlugin = template == _ProjectType.plugin;
final bool generatePackage = template == _ProjectType.package; final bool generatePackage = template == _ProjectType.package;
...@@ -283,11 +266,10 @@ class CreateCommand extends FlutterCommand { ...@@ -283,11 +266,10 @@ class CreateCommand extends FlutterCommand {
int generatedFileCount = 0; int generatedFileCount = 0;
switch (template) { switch (template) {
case _ProjectType.app: case _ProjectType.app:
generatedFileCount += await _generateLegacyApp(relativeDir, templateContext); generatedFileCount += await _generateApp(relativeDir, templateContext);
break; break;
case _ProjectType.module: case _ProjectType.module:
case _ProjectType.application: generatedFileCount += await _generateModule(relativeDir, templateContext);
generatedFileCount += await _generateApplication(relativeDir, templateContext);
break; break;
case _ProjectType.package: case _ProjectType.package:
generatedFileCount += await _generatePackage(relativeDir, templateContext); generatedFileCount += await _generatePackage(relativeDir, templateContext);
...@@ -305,13 +287,13 @@ class CreateCommand extends FlutterCommand { ...@@ -305,13 +287,13 @@ class CreateCommand extends FlutterCommand {
'${templateContext['projectName']}.dart', '${templateContext['projectName']}.dart',
)); ));
printStatus('Your package code is in $relativeMainPath'); printStatus('Your package code is in $relativeMainPath');
} else if (generateApplication) { } else if (generateModule) {
final String relativeMainPath = fs.path.normalize(fs.path.join( final String relativeMainPath = fs.path.normalize(fs.path.join(
relativeDirPath, relativeDirPath,
'lib', 'lib',
'main.dart', 'main.dart',
)); ));
printStatus('Your application code is in $relativeMainPath.'); printStatus('Your module code is in $relativeMainPath.');
} else { } else {
// Run doctor; tell the user the next steps. // Run doctor; tell the user the next steps.
final FlutterProject project = await FlutterProject.fromPath(projectDirPath); final FlutterProject project = await FlutterProject.fromPath(projectDirPath);
...@@ -359,13 +341,13 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit ...@@ -359,13 +341,13 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
return null; return null;
} }
Future<int> _generateApplication(Directory directory, Map<String, dynamic> templateContext) async { Future<int> _generateModule(Directory directory, Map<String, dynamic> templateContext) async {
int generatedCount = 0; int generatedCount = 0;
final String description = argResults.wasParsed('description') final String description = argResults.wasParsed('description')
? argResults['description'] ? argResults['description']
: 'A new flutter application project.'; : 'A new flutter module project.';
templateContext['description'] = description; templateContext['description'] = description;
generatedCount += _renderTemplate(fs.path.join('application', 'common'), directory, templateContext); generatedCount += _renderTemplate(fs.path.join('module', 'common'), directory, templateContext);
if (argResults['pub']) { if (argResults['pub']) {
await pubGet( await pubGet(
context: PubContext.create, context: PubContext.create,
...@@ -382,7 +364,7 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit ...@@ -382,7 +364,7 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
int generatedCount = 0; int generatedCount = 0;
final String description = argResults.wasParsed('description') final String description = argResults.wasParsed('description')
? argResults['description'] ? argResults['description']
: 'A new flutter package project.'; : 'A new Flutter package project.';
templateContext['description'] = description; templateContext['description'] = description;
generatedCount += _renderTemplate('package', directory, templateContext); generatedCount += _renderTemplate('package', directory, templateContext);
if (argResults['pub']) { if (argResults['pub']) {
...@@ -423,11 +405,11 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit ...@@ -423,11 +405,11 @@ To edit platform code in an IDE see https://flutter.io/developing-packages/#edit
templateContext['pluginProjectName'] = projectName; templateContext['pluginProjectName'] = projectName;
templateContext['androidPluginIdentifier'] = androidPluginIdentifier; templateContext['androidPluginIdentifier'] = androidPluginIdentifier;
generatedCount += await _generateLegacyApp(project.example.directory, templateContext); generatedCount += await _generateApp(project.example.directory, templateContext);
return generatedCount; return generatedCount;
} }
Future<int> _generateLegacyApp(Directory directory, Map<String, dynamic> templateContext) async { Future<int> _generateApp(Directory directory, Map<String, dynamic> templateContext) async {
int generatedCount = 0; int generatedCount = 0;
generatedCount += _renderTemplate('app', directory, templateContext); generatedCount += _renderTemplate('app', directory, templateContext);
final FlutterProject project = await FlutterProject.fromDirectory(directory); final FlutterProject project = await FlutterProject.fromDirectory(directory);
......
...@@ -37,8 +37,8 @@ class MakeHostAppEditableCommand extends FlutterCommand { ...@@ -37,8 +37,8 @@ class MakeHostAppEditableCommand extends FlutterCommand {
Future<void> validateCommand() async { Future<void> validateCommand() async {
await super.validateCommand(); await super.validateCommand();
_project = await FlutterProject.current(); _project = await FlutterProject.current();
if (!_project.isApplication) if (!_project.isModule)
throw ToolExit("Only projects created using 'flutter create -t application' can have their host apps made editable."); throw ToolExit("Only projects created using 'flutter create -t module' can have their host apps made editable.");
} }
@override @override
......
...@@ -110,14 +110,14 @@ class FlutterManifest { ...@@ -110,14 +110,14 @@ class FlutterManifest {
return _flutterDescriptor['uses-material-design'] ?? false; return _flutterDescriptor['uses-material-design'] ?? false;
} }
/// True if this manifest declares a Flutter application project. /// True if this manifest declares a Flutter module project.
/// ///
/// A Flutter project is considered an application when it has a `application:` /// A Flutter project is considered a module when it has a `module:`
/// descriptor. A Flutter application project supports integration into an /// descriptor. A Flutter module project supports integration into an
/// existing host app. /// existing host app, and has managed platform host code.
/// ///
/// Such a project can be created using `flutter create -t application`. /// Such a project can be created using `flutter create -t module`.
bool get isApplication => _flutterDescriptor.containsKey('application'); bool get isModule => _flutterDescriptor.containsKey('module');
/// True if this manifest declares a Flutter plugin project. /// True if this manifest declares a Flutter plugin project.
/// ///
...@@ -130,21 +130,21 @@ class FlutterManifest { ...@@ -130,21 +130,21 @@ class FlutterManifest {
bool get isPlugin => _flutterDescriptor.containsKey('plugin'); bool get isPlugin => _flutterDescriptor.containsKey('plugin');
/// Returns the Android package declared by this manifest in its /// Returns the Android package declared by this manifest in its
/// application or plugin descriptor. Returns null, if there is no /// module or plugin descriptor. Returns null, if there is no
/// such declaration. /// such declaration.
String get androidPackage { String get androidPackage {
if (isApplication) if (isModule)
return _flutterDescriptor['application']['androidPackage']; return _flutterDescriptor['module']['androidPackage'];
if (isPlugin) if (isPlugin)
return _flutterDescriptor['plugin']['androidPackage']; return _flutterDescriptor['plugin']['androidPackage'];
return null; return null;
} }
/// Returns the iOS bundle identifier declared by this manifest in its /// Returns the iOS bundle identifier declared by this manifest in its
/// application descriptor. Returns null, if there is no such declaration. /// module descriptor. Returns null if there is no such declaration.
String get iosBundleIdentifier { String get iosBundleIdentifier {
if (isApplication) if (isModule)
return _flutterDescriptor['application']['iosBundleIdentifier']; return _flutterDescriptor['module']['iosBundleIdentifier'];
return null; return null;
} }
......
...@@ -335,7 +335,7 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -335,7 +335,7 @@ Future<XcodeBuildResult> buildXcodeProject({
buildInfo: buildInfo, buildInfo: buildInfo,
); );
refreshPluginsList(project); refreshPluginsList(project);
if (hasPlugins(project) || (project.isApplication && project.ios.podfile.existsSync())) { if (hasPlugins(project) || (project.isModule && project.ios.podfile.existsSync())) {
// If the Xcode project, Podfile, or Generated.xcconfig have changed since // If the Xcode project, Podfile, or Generated.xcconfig have changed since
// last run, pods should be updated. // last run, pods should be updated.
final Fingerprinter fingerprinter = Fingerprinter( final Fingerprinter fingerprinter = Fingerprinter(
......
...@@ -57,8 +57,8 @@ Future<void> updateGeneratedXcodeProperties({ ...@@ -57,8 +57,8 @@ Future<void> updateGeneratedXcodeProperties({
localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}'); localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
if (!project.isApplication) { if (!project.isModule) {
// For application projects we do not want to write the FLUTTER_FRAMEWORK_DIR // 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 // explicitly. Rather we rely on the xcode backend script and the Podfile
// logic to derive it from FLUTTER_ROOT and FLUTTER_BUILD_MODE. // logic to derive it from FLUTTER_ROOT and FLUTTER_BUILD_MODE.
localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=${flutterFrameworkDir(buildInfo.mode)}'); localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=${flutterFrameworkDir(buildInfo.mode)}');
......
...@@ -248,7 +248,7 @@ Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plug ...@@ -248,7 +248,7 @@ Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plug
}; };
final String registryDirectory = project.ios.pluginRegistrantHost.path; final String registryDirectory = project.ios.pluginRegistrantHost.path;
if (project.isApplication) { if (project.isModule) {
final String registryClassesDirectory = fs.path.join(registryDirectory, 'Classes'); final String registryClassesDirectory = fs.path.join(registryDirectory, 'Classes');
_renderTemplateToFile( _renderTemplateToFile(
_iosPluginRegistrantPodspecTemplate, _iosPluginRegistrantPodspecTemplate,
...@@ -297,7 +297,7 @@ Future<void> injectPlugins(FlutterProject project) async { ...@@ -297,7 +297,7 @@ Future<void> injectPlugins(FlutterProject project) async {
final List<Plugin> plugins = findPlugins(project); final List<Plugin> plugins = findPlugins(project);
await _writeAndroidPluginRegistrant(project, plugins); await _writeAndroidPluginRegistrant(project, plugins);
await _writeIOSPluginRegistrant(project, plugins); await _writeIOSPluginRegistrant(project, plugins);
if (!project.isApplication && project.ios.hostAppRoot.existsSync()) { if (!project.isModule && project.ios.hostAppRoot.existsSync()) {
final CocoaPods cocoaPods = CocoaPods(); final CocoaPods cocoaPods = CocoaPods();
if (plugins.isNotEmpty) if (plugins.isNotEmpty)
cocoaPods.setupPodfile(project.ios); cocoaPods.setupPodfile(project.ios);
......
...@@ -110,10 +110,10 @@ class FlutterProject { ...@@ -110,10 +110,10 @@ class FlutterProject {
FlutterManifest.empty(), FlutterManifest.empty(),
); );
/// True, if this project is a Flutter application. /// True if this project is a Flutter module project.
bool get isApplication => manifest.isApplication; bool get isModule => manifest.isModule;
/// True, if this project has an example application. /// True if this project has an example application.
bool get hasExampleApp => _exampleDirectory(directory).existsSync(); bool get hasExampleApp => _exampleDirectory(directory).existsSync();
/// The directory that will contain the example if an example exists. /// The directory that will contain the example if an example exists.
...@@ -132,7 +132,7 @@ class FlutterProject { ...@@ -132,7 +132,7 @@ class FlutterProject {
} }
/// Generates project files necessary to make Gradle builds work on Android /// Generates project files necessary to make Gradle builds work on Android
/// and CocoaPods+Xcode work on iOS, for app and application projects only. /// and CocoaPods+Xcode work on iOS, for app and module projects only.
Future<void> ensureReadyForPlatformSpecificTooling() async { Future<void> ensureReadyForPlatformSpecificTooling() async {
if (!directory.existsSync() || hasExampleApp) if (!directory.existsSync() || hasExampleApp)
return; return;
...@@ -146,7 +146,7 @@ class FlutterProject { ...@@ -146,7 +146,7 @@ class FlutterProject {
/// Represents the iOS sub-project of a Flutter project. /// Represents the iOS sub-project of a Flutter project.
/// ///
/// Instances will reflect the contents of the `ios/` sub-folder of /// Instances will reflect the contents of the `ios/` sub-folder of
/// Flutter applications and the `.ios/` sub-folder of Flutter applications. /// Flutter applications and the `.ios/` sub-folder of Flutter module projects.
class IosProject { class IosProject {
IosProject._(this.parent); IosProject._(this.parent);
...@@ -162,7 +162,7 @@ class IosProject { ...@@ -162,7 +162,7 @@ class IosProject {
/// This parent folder of `Runner.xcodeproj`. /// This parent folder of `Runner.xcodeproj`.
Directory get hostAppRoot { Directory get hostAppRoot {
if (!isApplication || _editableDirectory.existsSync()) if (!isModule || _editableDirectory.existsSync())
return _editableDirectory; return _editableDirectory;
return _ephemeralDirectory; return _ephemeralDirectory;
} }
...@@ -172,14 +172,14 @@ class IosProject { ...@@ -172,14 +172,14 @@ class IosProject {
/// during build. /// during build.
/// ///
/// This is the same as [hostAppRoot] except when the project is /// This is the same as [hostAppRoot] except when the project is
/// a Flutter application with an editable host app. /// a Flutter module with an editable host app.
Directory get _flutterLibRoot => isApplication ? _ephemeralDirectory : _editableDirectory; Directory get _flutterLibRoot => isModule ? _ephemeralDirectory : _editableDirectory;
/// The bundle name of the host app, `Runner.app`. /// The bundle name of the host app, `Runner.app`.
String get hostAppBundleName => '$_hostAppBundleName.app'; String get hostAppBundleName => '$_hostAppBundleName.app';
/// True, if the parent Flutter project is an application. /// True, if the parent Flutter project is a module project.
bool get isApplication => parent.isApplication; bool get isModule => parent.isModule;
/// The xcode config file for [mode]. /// The xcode config file for [mode].
File xcodeConfigFor(String mode) => _flutterLibRoot.childDirectory('Flutter').childFile('$mode.xcconfig'); File xcodeConfigFor(String mode) => _flutterLibRoot.childDirectory('Flutter').childFile('$mode.xcconfig');
...@@ -264,32 +264,32 @@ class IosProject { ...@@ -264,32 +264,32 @@ class IosProject {
} }
void _regenerateFromTemplateIfNeeded() { void _regenerateFromTemplateIfNeeded() {
if (!isApplication) if (!isModule)
return; return;
final bool pubspecChanged = isOlderThanReference(entity: _ephemeralDirectory, referenceFile: parent.pubspecFile); final bool pubspecChanged = isOlderThanReference(entity: _ephemeralDirectory, referenceFile: parent.pubspecFile);
final bool toolingChanged = Cache.instance.isOlderThanToolsStamp(_ephemeralDirectory); final bool toolingChanged = Cache.instance.isOlderThanToolsStamp(_ephemeralDirectory);
if (!pubspecChanged && !toolingChanged) if (!pubspecChanged && !toolingChanged)
return; return;
_deleteIfExistsSync(_ephemeralDirectory); _deleteIfExistsSync(_ephemeralDirectory);
_overwriteFromTemplate(fs.path.join('application', 'ios', 'library'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'ios', 'library'), _ephemeralDirectory);
// Add ephemeral host app, if a editable host app does not already exist. // Add ephemeral host app, if a editable host app does not already exist.
if (!_editableDirectory.existsSync()) { if (!_editableDirectory.existsSync()) {
_overwriteFromTemplate(fs.path.join('application', 'ios', 'host_app_ephemeral'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'ios', 'host_app_ephemeral'), _ephemeralDirectory);
if (hasPlugins(parent)) { if (hasPlugins(parent)) {
_overwriteFromTemplate(fs.path.join('application', 'ios', 'host_app_ephemeral_cocoapods'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'ios', 'host_app_ephemeral_cocoapods'), _ephemeralDirectory);
} }
} }
} }
Future<void> makeHostAppEditable() async { Future<void> makeHostAppEditable() async {
assert(isApplication); assert(isModule);
if (_editableDirectory.existsSync()) if (_editableDirectory.existsSync())
throwToolExit('iOS host app is already editable. To start fresh, delete the ios/ folder.'); throwToolExit('iOS host app is already editable. To start fresh, delete the ios/ folder.');
_deleteIfExistsSync(_ephemeralDirectory); _deleteIfExistsSync(_ephemeralDirectory);
_overwriteFromTemplate(fs.path.join('application', 'ios', 'library'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'ios', 'library'), _ephemeralDirectory);
_overwriteFromTemplate(fs.path.join('application', 'ios', 'host_app_ephemeral'), _editableDirectory); _overwriteFromTemplate(fs.path.join('module', 'ios', 'host_app_ephemeral'), _editableDirectory);
_overwriteFromTemplate(fs.path.join('application', 'ios', 'host_app_ephemeral_cocoapods'), _editableDirectory); _overwriteFromTemplate(fs.path.join('module', 'ios', 'host_app_ephemeral_cocoapods'), _editableDirectory);
_overwriteFromTemplate(fs.path.join('application', 'ios', 'host_app_editable_cocoapods'), _editableDirectory); _overwriteFromTemplate(fs.path.join('module', 'ios', 'host_app_editable_cocoapods'), _editableDirectory);
await _updateGeneratedXcodeConfigIfNeeded(); await _updateGeneratedXcodeConfigIfNeeded();
await injectPlugins(parent); await injectPlugins(parent);
} }
...@@ -297,7 +297,7 @@ class IosProject { ...@@ -297,7 +297,7 @@ class IosProject {
File get generatedXcodePropertiesFile => _flutterLibRoot.childDirectory('Flutter').childFile('Generated.xcconfig'); File get generatedXcodePropertiesFile => _flutterLibRoot.childDirectory('Flutter').childFile('Generated.xcconfig');
Directory get pluginRegistrantHost { Directory get pluginRegistrantHost {
return isApplication return isModule
? _flutterLibRoot.childDirectory('Flutter').childDirectory('FlutterPluginRegistrant') ? _flutterLibRoot.childDirectory('Flutter').childDirectory('FlutterPluginRegistrant')
: hostAppRoot.childDirectory(_hostAppBundleName); : hostAppRoot.childDirectory(_hostAppBundleName);
} }
...@@ -319,7 +319,7 @@ class IosProject { ...@@ -319,7 +319,7 @@ class IosProject {
/// Represents the Android sub-project of a Flutter project. /// Represents the Android sub-project of a Flutter project.
/// ///
/// Instances will reflect the contents of the `android/` sub-folder of /// Instances will reflect the contents of the `android/` sub-folder of
/// Flutter applications and the `.android/` sub-folder of Flutter applications. /// Flutter applications and the `.android/` sub-folder of Flutter module projects.
class AndroidProject { class AndroidProject {
AndroidProject._(this.parent); AndroidProject._(this.parent);
...@@ -333,21 +333,21 @@ class AndroidProject { ...@@ -333,21 +333,21 @@ class AndroidProject {
/// containing the `app/` subdirectory and the `settings.gradle` file that /// containing the `app/` subdirectory and the `settings.gradle` file that
/// includes it in the overall Gradle project. /// includes it in the overall Gradle project.
Directory get hostAppGradleRoot { Directory get hostAppGradleRoot {
if (!isApplication || _editableHostAppDirectory.existsSync()) if (!isModule || _editableHostAppDirectory.existsSync())
return _editableHostAppDirectory; return _editableHostAppDirectory;
return _ephemeralDirectory; return _ephemeralDirectory;
} }
/// The Gradle root directory of the Android wrapping of Flutter and plugins. /// The Gradle root directory of the Android wrapping of Flutter and plugins.
/// This is the same as [hostAppGradleRoot] except when the project is /// This is the same as [hostAppGradleRoot] except when the project is
/// a Flutter application with an editable host app. /// a Flutter module with an editable host app.
Directory get _flutterLibGradleRoot => isApplication ? _ephemeralDirectory : _editableHostAppDirectory; Directory get _flutterLibGradleRoot => isModule ? _ephemeralDirectory : _editableHostAppDirectory;
Directory get _ephemeralDirectory => parent.directory.childDirectory('.android'); Directory get _ephemeralDirectory => parent.directory.childDirectory('.android');
Directory get _editableHostAppDirectory => parent.directory.childDirectory('android'); Directory get _editableHostAppDirectory => parent.directory.childDirectory('android');
/// True, if the parent Flutter project is an application. /// True if the parent Flutter project is a module.
bool get isApplication => parent.isApplication; bool get isModule => parent.isModule;
File get appManifestFile { File get appManifestFile {
return isUsingGradle return isUsingGradle
...@@ -376,12 +376,12 @@ class AndroidProject { ...@@ -376,12 +376,12 @@ class AndroidProject {
} }
Future<void> ensureReadyForPlatformSpecificTooling() async { Future<void> ensureReadyForPlatformSpecificTooling() async {
if (isApplication && _shouldRegenerateFromTemplate()) { if (isModule && _shouldRegenerateFromTemplate()) {
_regenerateLibrary(); _regenerateLibrary();
// Add ephemeral host app, if an editable host app does not already exist. // Add ephemeral host app, if an editable host app does not already exist.
if (!_editableHostAppDirectory.existsSync()) { if (!_editableHostAppDirectory.existsSync()) {
_overwriteFromTemplate(fs.path.join('application', 'android', 'host_app_common'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'android', 'host_app_common'), _ephemeralDirectory);
_overwriteFromTemplate(fs.path.join('application', 'android', 'host_app_ephemeral'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'android', 'host_app_ephemeral'), _ephemeralDirectory);
} }
} }
if (!hostAppGradleRoot.existsSync()) { if (!hostAppGradleRoot.existsSync()) {
...@@ -396,13 +396,13 @@ class AndroidProject { ...@@ -396,13 +396,13 @@ class AndroidProject {
} }
Future<void> makeHostAppEditable() async { Future<void> makeHostAppEditable() async {
assert(isApplication); assert(isModule);
if (_editableHostAppDirectory.existsSync()) if (_editableHostAppDirectory.existsSync())
throwToolExit('Android host app is already editable. To start fresh, delete the android/ folder.'); throwToolExit('Android host app is already editable. To start fresh, delete the android/ folder.');
_regenerateLibrary(); _regenerateLibrary();
_overwriteFromTemplate(fs.path.join('application', 'android', 'host_app_common'), _editableHostAppDirectory); _overwriteFromTemplate(fs.path.join('module', 'android', 'host_app_common'), _editableHostAppDirectory);
_overwriteFromTemplate(fs.path.join('application', 'android', 'host_app_editable'), _editableHostAppDirectory); _overwriteFromTemplate(fs.path.join('module', 'android', 'host_app_editable'), _editableHostAppDirectory);
_overwriteFromTemplate(fs.path.join('application', 'android', 'gradle'), _editableHostAppDirectory); _overwriteFromTemplate(fs.path.join('module', 'android', 'gradle'), _editableHostAppDirectory);
gradle.injectGradleWrapper(_editableHostAppDirectory); gradle.injectGradleWrapper(_editableHostAppDirectory);
gradle.writeLocalProperties(_editableHostAppDirectory.childFile('local.properties')); gradle.writeLocalProperties(_editableHostAppDirectory.childFile('local.properties'));
await injectPlugins(parent); await injectPlugins(parent);
...@@ -410,12 +410,12 @@ class AndroidProject { ...@@ -410,12 +410,12 @@ class AndroidProject {
File get localPropertiesFile => _flutterLibGradleRoot.childFile('local.properties'); File get localPropertiesFile => _flutterLibGradleRoot.childFile('local.properties');
Directory get pluginRegistrantHost => _flutterLibGradleRoot.childDirectory(isApplication ? 'Flutter' : 'app'); Directory get pluginRegistrantHost => _flutterLibGradleRoot.childDirectory(isModule ? 'Flutter' : 'app');
void _regenerateLibrary() { void _regenerateLibrary() {
_deleteIfExistsSync(_ephemeralDirectory); _deleteIfExistsSync(_ephemeralDirectory);
_overwriteFromTemplate(fs.path.join('application', 'android', 'library'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'android', 'library'), _ephemeralDirectory);
_overwriteFromTemplate(fs.path.join('application', 'android', 'gradle'), _ephemeralDirectory); _overwriteFromTemplate(fs.path.join('module', 'android', 'gradle'), _ephemeralDirectory);
gradle.injectGradleWrapper(_ephemeralDirectory); gradle.injectGradleWrapper(_ephemeralDirectory);
} }
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
} }
} }
}, },
"application": { "module": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
......
...@@ -7,4 +7,4 @@ version: ...@@ -7,4 +7,4 @@ version:
revision: {{flutterRevision}} revision: {{flutterRevision}}
channel: {{flutterChannel}} channel: {{flutterChannel}}
project_type: application project_type: module
...@@ -20,6 +20,6 @@ dev_dependencies: ...@@ -20,6 +20,6 @@ dev_dependencies:
flutter: flutter:
uses-material-design: true uses-material-design: true
application: module:
androidPackage: {{androidIdentifier}} androidPackage: {{androidIdentifier}}
iosBundleIdentifier: {{iosIdentifier}} iosBundleIdentifier: {{iosIdentifier}}
...@@ -45,8 +45,8 @@ void main() { ...@@ -45,8 +45,8 @@ void main() {
tryToDelete(tempDir); tryToDelete(tempDir);
}); });
Future<String> createProjectWithPlugin(String plugin) async { Future<String> createProjectWithPlugin(String plugin, {List<String> arguments}) async {
final String projectPath = await createProject(tempDir); final String projectPath = await createProject(tempDir, arguments: arguments);
final File pubspec = fs.file(fs.path.join(projectPath, 'pubspec.yaml')); final File pubspec = fs.file(fs.path.join(projectPath, 'pubspec.yaml'));
String content = await pubspec.readAsString(); String content = await pubspec.readAsString();
content = content.replaceFirst( content = content.replaceFirst(
...@@ -114,7 +114,7 @@ void main() { ...@@ -114,7 +114,7 @@ void main() {
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java', 'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
]; ];
const List<String> applicationPluginRegistrants = <String>[ const List<String> modulePluginRegistrants = <String>[
'.ios/Flutter/FlutterPluginRegistrant/Classes/GeneratedPluginRegistrant.h', '.ios/Flutter/FlutterPluginRegistrant/Classes/GeneratedPluginRegistrant.h',
'.ios/Flutter/FlutterPluginRegistrant/Classes/GeneratedPluginRegistrant.m', '.ios/Flutter/FlutterPluginRegistrant/Classes/GeneratedPluginRegistrant.m',
'.android/Flutter/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java', '.android/Flutter/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
...@@ -125,7 +125,7 @@ void main() { ...@@ -125,7 +125,7 @@ void main() {
'ios/Podfile', 'ios/Podfile',
]; ];
const List<String> applicationPluginWitnesses = <String>[ const List<String> modulePluginWitnesses = <String>[
'.flutter-plugins', '.flutter-plugins',
'.ios/Podfile', '.ios/Podfile',
]; ];
...@@ -135,7 +135,7 @@ void main() { ...@@ -135,7 +135,7 @@ void main() {
'ios/Flutter/Release.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"', 'ios/Flutter/Release.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"',
}; };
const Map<String, String> applicationPluginContentWitnesses = <String, String>{ const Map<String, String> modulePluginContentWitnesses = <String, String>{
'.ios/Config/Debug.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"', '.ios/Config/Debug.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"',
'.ios/Config/Release.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"', '.ios/Config/Release.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"',
}; };
...@@ -147,13 +147,13 @@ void main() { ...@@ -147,13 +147,13 @@ void main() {
} }
void expectZeroPluginsInjected(String projectPath) { void expectZeroPluginsInjected(String projectPath) {
for (final String registrant in applicationPluginRegistrants) { for (final String registrant in modulePluginRegistrants) {
expectExists(projectPath, registrant); expectExists(projectPath, registrant);
} }
for (final String witness in pluginWitnesses) { for (final String witness in pluginWitnesses) {
expectNotExists(projectPath, witness); expectNotExists(projectPath, witness);
} }
applicationPluginContentWitnesses.forEach((String witness, String content) { modulePluginContentWitnesses.forEach((String witness, String content) {
expectNotContains(projectPath, witness, content); expectNotContains(projectPath, witness, content);
}); });
} }
...@@ -170,14 +170,14 @@ void main() { ...@@ -170,14 +170,14 @@ void main() {
}); });
} }
void expectApplicationPluginInjected(String projectPath) { void expectModulePluginInjected(String projectPath) {
for (final String registrant in applicationPluginRegistrants) { for (final String registrant in modulePluginRegistrants) {
expectExists(projectPath, registrant); expectExists(projectPath, registrant);
} }
for (final String witness in applicationPluginWitnesses) { for (final String witness in modulePluginWitnesses) {
expectExists(projectPath, witness); expectExists(projectPath, witness);
} }
applicationPluginContentWitnesses.forEach((String witness, String content) { modulePluginContentWitnesses.forEach((String witness, String content) {
expectContains(projectPath, witness, content); expectContains(projectPath, witness, content);
}); });
} }
...@@ -185,7 +185,7 @@ void main() { ...@@ -185,7 +185,7 @@ void main() {
void removeGeneratedFiles(String projectPath) { void removeGeneratedFiles(String projectPath) {
final Iterable<String> allFiles = <List<String>>[ final Iterable<String> allFiles = <List<String>>[
pubOutput, pubOutput,
applicationPluginRegistrants, modulePluginRegistrants,
pluginWitnesses, pluginWitnesses,
].expand<String>((List<String> list) => list); ].expand<String>((List<String> list) => list);
for (String path in allFiles) { for (String path in allFiles) {
...@@ -196,7 +196,8 @@ void main() { ...@@ -196,7 +196,8 @@ void main() {
} }
testUsingContext('get fetches packages', () async { testUsingContext('get fetches packages', () async {
final String projectPath = await createProject(tempDir); final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=module']);
removeGeneratedFiles(projectPath); removeGeneratedFiles(projectPath);
await runCommandIn(projectPath, 'get'); await runCommandIn(projectPath, 'get');
...@@ -206,7 +207,8 @@ void main() { ...@@ -206,7 +207,8 @@ void main() {
}, timeout: allowForRemotePubInvocation); }, timeout: allowForRemotePubInvocation);
testUsingContext('get --offline fetches packages', () async { testUsingContext('get --offline fetches packages', () async {
final String projectPath = await createProject(tempDir); final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=module']);
removeGeneratedFiles(projectPath); removeGeneratedFiles(projectPath);
await runCommandIn(projectPath, 'get', args: <String>['--offline']); await runCommandIn(projectPath, 'get', args: <String>['--offline']);
...@@ -216,7 +218,8 @@ void main() { ...@@ -216,7 +218,8 @@ void main() {
}, timeout: allowForCreateFlutterProject); }, timeout: allowForCreateFlutterProject);
testUsingContext('upgrade fetches packages', () async { testUsingContext('upgrade fetches packages', () async {
final String projectPath = await createProject(tempDir); final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=module']);
removeGeneratedFiles(projectPath); removeGeneratedFiles(projectPath);
await runCommandIn(projectPath, 'upgrade'); await runCommandIn(projectPath, 'upgrade');
...@@ -226,13 +229,14 @@ void main() { ...@@ -226,13 +229,14 @@ void main() {
}, timeout: allowForRemotePubInvocation); }, timeout: allowForRemotePubInvocation);
testUsingContext('get fetches packages and injects plugin', () async { testUsingContext('get fetches packages and injects plugin', () async {
final String projectPath = await createProjectWithPlugin('path_provider'); final String projectPath = await createProjectWithPlugin('path_provider',
arguments: <String>['--no-pub', '--template=module']);
removeGeneratedFiles(projectPath); removeGeneratedFiles(projectPath);
await runCommandIn(projectPath, 'get'); await runCommandIn(projectPath, 'get');
expectDependenciesResolved(projectPath); expectDependenciesResolved(projectPath);
expectApplicationPluginInjected(projectPath); expectModulePluginInjected(projectPath);
}, timeout: allowForRemotePubInvocation); }, timeout: allowForRemotePubInvocation);
testUsingContext('get fetches packages and injects plugin in plugin project', () async { testUsingContext('get fetches packages and injects plugin in plugin project', () async {
......
...@@ -355,20 +355,20 @@ flutter: ...@@ -355,20 +355,20 @@ flutter:
'''; ''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest); final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
expect(flutterManifest.isEmpty, false); expect(flutterManifest.isEmpty, false);
expect(flutterManifest.isApplication, false); expect(flutterManifest.isModule, false);
expect(flutterManifest.isPlugin, false); expect(flutterManifest.isPlugin, false);
expect(flutterManifest.androidPackage, null); expect(flutterManifest.androidPackage, null);
}); });
test('allows an application declaration', () async { test('allows a module declaration', () async {
const String manifest = ''' const String manifest = '''
name: test name: test
flutter: flutter:
application: module:
androidPackage: com.example androidPackage: com.example
'''; ''';
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest); final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
expect(flutterManifest.isApplication, true); expect(flutterManifest.isModule, true);
expect(flutterManifest.androidPackage, 'com.example'); expect(flutterManifest.androidPackage, 'com.example');
}); });
......
...@@ -90,20 +90,20 @@ void main() { ...@@ -90,20 +90,20 @@ void main() {
}); });
group('editable Android host app', () { group('editable Android host app', () {
testInMemory('fails on non-application', () async { testInMemory('fails on non-module', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await expectLater( await expectLater(
project.android.makeHostAppEditable(), project.android.makeHostAppEditable(),
throwsA(isInstanceOf<AssertionError>()), throwsA(isInstanceOf<AssertionError>()),
); );
}); });
testInMemory('exits on already editable application', () async { testInMemory('exits on already editable module', () async {
final FlutterProject project = await anApplicationProject(); final FlutterProject project = await aModuleProject();
await project.android.makeHostAppEditable(); await project.android.makeHostAppEditable();
return expectToolExitLater(project.android.makeHostAppEditable(), contains('already editable')); return expectToolExitLater(project.android.makeHostAppEditable(), contains('already editable'));
}); });
testInMemory('creates android/app folder in place of .android/app', () async { testInMemory('creates android/app folder in place of .android/app', () async {
final FlutterProject project = await anApplicationProject(); final FlutterProject project = await aModuleProject();
await project.android.makeHostAppEditable(); await project.android.makeHostAppEditable();
expectNotExists(project.directory.childDirectory('.android').childDirectory('app')); expectNotExists(project.directory.childDirectory('.android').childDirectory('app'));
expect( expect(
...@@ -118,7 +118,7 @@ void main() { ...@@ -118,7 +118,7 @@ void main() {
); );
}); });
testInMemory('retains .android/Flutter folder and references it', () async { testInMemory('retains .android/Flutter folder and references it', () async {
final FlutterProject project = await anApplicationProject(); final FlutterProject project = await aModuleProject();
await project.android.makeHostAppEditable(); await project.android.makeHostAppEditable();
expectExists(project.directory.childDirectory('.android').childDirectory('Flutter')); expectExists(project.directory.childDirectory('.android').childDirectory('Flutter'));
expect( expect(
...@@ -127,7 +127,7 @@ void main() { ...@@ -127,7 +127,7 @@ void main() {
); );
}); });
testInMemory('can be redone after deletion', () async { testInMemory('can be redone after deletion', () async {
final FlutterProject project = await anApplicationProject(); final FlutterProject project = await aModuleProject();
await project.android.makeHostAppEditable(); await project.android.makeHostAppEditable();
project.directory.childDirectory('android').deleteSync(recursive: true); project.directory.childDirectory('android').deleteSync(recursive: true);
await project.android.makeHostAppEditable(); await project.android.makeHostAppEditable();
...@@ -173,15 +173,15 @@ void main() { ...@@ -173,15 +173,15 @@ void main() {
await project.ensureReadyForPlatformSpecificTooling(); await project.ensureReadyForPlatformSpecificTooling();
expectExists(project.android.hostAppGradleRoot.childFile('local.properties')); expectExists(project.android.hostAppGradleRoot.childFile('local.properties'));
}); });
testInMemory('creates Android library in application', () async { testInMemory('creates Android library in module', () async {
final FlutterProject project = await anApplicationProject(); final FlutterProject project = await aModuleProject();
await project.ensureReadyForPlatformSpecificTooling(); await project.ensureReadyForPlatformSpecificTooling();
expectExists(project.android.hostAppGradleRoot.childFile('settings.gradle')); expectExists(project.android.hostAppGradleRoot.childFile('settings.gradle'));
expectExists(project.android.hostAppGradleRoot.childFile('local.properties')); expectExists(project.android.hostAppGradleRoot.childFile('local.properties'));
expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('Flutter'))); expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('Flutter')));
}); });
testInMemory('creates iOS pod in application', () async { testInMemory('creates iOS pod in module', () async {
final FlutterProject project = await anApplicationProject(); final FlutterProject project = await aModuleProject();
await project.ensureReadyForPlatformSpecificTooling(); await project.ensureReadyForPlatformSpecificTooling();
final Directory flutter = project.ios.hostAppRoot.childDirectory('Flutter'); final Directory flutter = project.ios.hostAppRoot.childDirectory('Flutter');
expectExists(flutter.childFile('podhelper.rb')); expectExists(flutter.childFile('podhelper.rb'));
...@@ -194,20 +194,20 @@ void main() { ...@@ -194,20 +194,20 @@ void main() {
}); });
}); });
group('application status', () { group('module status', () {
testInMemory('is known for application', () async { testInMemory('is known for module', () async {
final FlutterProject project = await anApplicationProject(); final FlutterProject project = await aModuleProject();
expect(project.isApplication, isTrue); expect(project.isModule, isTrue);
expect(project.android.isApplication, isTrue); expect(project.android.isModule, isTrue);
expect(project.ios.isApplication, isTrue); expect(project.ios.isModule, isTrue);
expect(project.android.hostAppGradleRoot.basename, '.android'); expect(project.android.hostAppGradleRoot.basename, '.android');
expect(project.ios.hostAppRoot.basename, '.ios'); expect(project.ios.hostAppRoot.basename, '.ios');
}); });
testInMemory('is known for non-application', () async { testInMemory('is known for non-module', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
expect(project.isApplication, isFalse); expect(project.isModule, isFalse);
expect(project.android.isApplication, isFalse); expect(project.android.isModule, isFalse);
expect(project.ios.isApplication, isFalse); expect(project.ios.isModule, isFalse);
expect(project.android.hostAppGradleRoot.basename, 'android'); expect(project.android.hostAppGradleRoot.basename, 'android');
expect(project.ios.hostAppRoot.basename, 'ios'); expect(project.ios.hostAppRoot.basename, 'ios');
}); });
...@@ -351,13 +351,13 @@ flutter: ...@@ -351,13 +351,13 @@ flutter:
return FlutterProject.fromDirectory(directory); return FlutterProject.fromDirectory(directory);
} }
Future<FlutterProject> anApplicationProject() async { Future<FlutterProject> aModuleProject() async {
final Directory directory = fs.directory('application_project'); final Directory directory = fs.directory('module_project');
directory.childFile('.packages').createSync(recursive: true); directory.childFile('.packages').createSync(recursive: true);
directory.childFile('pubspec.yaml').writeAsStringSync(''' directory.childFile('pubspec.yaml').writeAsStringSync('''
name: my_application name: my_module
flutter: flutter:
application: module:
androidPackage: com.example androidPackage: com.example
'''); ''');
return FlutterProject.fromDirectory(directory); return FlutterProject.fromDirectory(directory);
......
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