Add hidden --no-implicit-pubspec-resolution flag for one stable release. (#157635)

Closes https://github.com/flutter/flutter/issues/157532.

Work towards https://github.com/flutter/flutter/issues/157819.

Because this flag is checked in `FlutterCommand.verifyAndRun`, it seemed cleaner to just make it a global flag - particularly because this flag's longevity is unlikely to be longer than a single stable release.
This commit is contained in:
Matan Lurey 2024-10-30 10:00:32 -07:00 committed by GitHub
parent e10d1dee5d
commit e6c9fce313
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 133 additions and 51 deletions

View File

@ -26,6 +26,7 @@ import '../macos/swift_packages.dart';
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../runner/flutter_command_runner.dart';
import 'create_base.dart'; import 'create_base.dart';
const String kPlatformHelp = const String kPlatformHelp =
@ -458,6 +459,7 @@ class CreateCommand extends CreateBase {
macOSPlatform: includeMacos, macOSPlatform: includeMacos,
windowsPlatform: includeWindows, windowsPlatform: includeWindows,
webPlatform: includeWeb, webPlatform: includeWeb,
writeLegacyPluginsList: boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true),
); );
} }
} }

View File

@ -21,6 +21,7 @@ import '../plugins.dart';
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../runner/flutter_command_runner.dart';
/// The function signature of the [print] function. /// The function signature of the [print] function.
typedef PrintFn = void Function(Object?); typedef PrintFn = void Function(Object?);
@ -383,10 +384,15 @@ class PackagesGetCommand extends FlutterCommand {
if (rootProject != null) { if (rootProject != null) {
// We need to regenerate the platform specific tooling for both the project // We need to regenerate the platform specific tooling for both the project
// itself and example(if present). // itself and example(if present).
await rootProject.regeneratePlatformSpecificTooling(); final bool writeLegacyPluginsList = boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true);
await rootProject.regeneratePlatformSpecificTooling(
writeLegacyPluginsList: writeLegacyPluginsList,
);
if (example && rootProject.hasExampleApp && rootProject.example.pubspecFile.existsSync()) { if (example && rootProject.hasExampleApp && rootProject.example.pubspecFile.existsSync()) {
final FlutterProject exampleProject = rootProject.example; final FlutterProject exampleProject = rootProject.example;
await exampleProject.regeneratePlatformSpecificTooling(); await exampleProject.regeneratePlatformSpecificTooling(
writeLegacyPluginsList: writeLegacyPluginsList,
);
} }
} }

View File

@ -1010,7 +1010,7 @@ Future<void> refreshPluginsList(
bool iosPlatform = false, bool iosPlatform = false,
bool macOSPlatform = false, bool macOSPlatform = false,
bool forceCocoaPodsOnly = false, bool forceCocoaPodsOnly = false,
bool writeLegacyPluginsList = true, required bool writeLegacyPluginsList,
}) async { }) async {
final List<Plugin> plugins = await findPlugins(project); final List<Plugin> plugins = await findPlugins(project);
// Sort the plugins by name to keep ordering stable in generated files. // Sort the plugins by name to keep ordering stable in generated files.

View File

@ -340,6 +340,7 @@ class FlutterProject {
Future<void> regeneratePlatformSpecificTooling({ Future<void> regeneratePlatformSpecificTooling({
DeprecationBehavior deprecationBehavior = DeprecationBehavior.none, DeprecationBehavior deprecationBehavior = DeprecationBehavior.none,
Iterable<String>? allowedPlugins, Iterable<String>? allowedPlugins,
required bool writeLegacyPluginsList,
}) async { }) async {
return ensureReadyForPlatformSpecificTooling( return ensureReadyForPlatformSpecificTooling(
androidPlatform: android.existsSync(), androidPlatform: android.existsSync(),
@ -352,6 +353,7 @@ class FlutterProject {
webPlatform: featureFlags.isWebEnabled && web.existsSync(), webPlatform: featureFlags.isWebEnabled && web.existsSync(),
deprecationBehavior: deprecationBehavior, deprecationBehavior: deprecationBehavior,
allowedPlugins: allowedPlugins, allowedPlugins: allowedPlugins,
writeLegacyPluginsList: writeLegacyPluginsList,
); );
} }
@ -366,11 +368,17 @@ class FlutterProject {
bool webPlatform = false, bool webPlatform = false,
DeprecationBehavior deprecationBehavior = DeprecationBehavior.none, DeprecationBehavior deprecationBehavior = DeprecationBehavior.none,
Iterable<String>? allowedPlugins, Iterable<String>? allowedPlugins,
required bool writeLegacyPluginsList,
}) async { }) async {
if (!directory.existsSync() || isPlugin) { if (!directory.existsSync() || isPlugin) {
return; return;
} }
await refreshPluginsList(this, iosPlatform: iosPlatform, macOSPlatform: macOSPlatform); await refreshPluginsList(
this,
iosPlatform: iosPlatform,
macOSPlatform: macOSPlatform,
writeLegacyPluginsList: writeLegacyPluginsList,
);
if (androidPlatform) { if (androidPlatform) {
await android.ensureReadyForPlatformSpecificTooling(deprecationBehavior: deprecationBehavior); await android.ensureReadyForPlatformSpecificTooling(deprecationBehavior: deprecationBehavior);
} }

View File

@ -1790,7 +1790,10 @@ Run 'flutter -h' (or 'flutter <command> -h') for available flutter commands and
// The preview device does not currently support any plugins. // The preview device does not currently support any plugins.
allowedPlugins = PreviewDevice.supportedPubPlugins; allowedPlugins = PreviewDevice.supportedPubPlugins;
} }
await project.regeneratePlatformSpecificTooling(allowedPlugins: allowedPlugins); await project.regeneratePlatformSpecificTooling(
allowedPlugins: allowedPlugins,
writeLegacyPluginsList: boolArg(FlutterGlobalOptions.kImplicitPubspecResolution, global: true),
);
if (reportNullSafety) { if (reportNullSafety) {
await _sendNullSafetyAnalyticsEvents(project); await _sendNullSafetyAnalyticsEvents(project);
} }

View File

@ -33,6 +33,8 @@ abstract final class FlutterGlobalOptions {
static const String kLocalEngineSrcPathOption = 'local-engine-src-path'; static const String kLocalEngineSrcPathOption = 'local-engine-src-path';
static const String kLocalEngineHostOption = 'local-engine-host'; static const String kLocalEngineHostOption = 'local-engine-host';
static const String kLocalWebSDKOption = 'local-web-sdk'; static const String kLocalWebSDKOption = 'local-web-sdk';
// TODO(matanlurey): Remove one stable after https://github.com/flutter/flutter/issues/157819.
static const String kImplicitPubspecResolution = 'implicit-pubspec-resolution';
static const String kMachineFlag = 'machine'; static const String kMachineFlag = 'machine';
static const String kPackagesOption = 'packages'; static const String kPackagesOption = 'packages';
static const String kPrefixedErrorsFlag = 'prefixed-errors'; static const String kPrefixedErrorsFlag = 'prefixed-errors';
@ -124,6 +126,26 @@ class FlutterCommandRunner extends CommandRunner<void> {
help: 'Print the address of the Dart Tooling Daemon, if one is hosted by the Flutter CLI.', help: 'Print the address of the Dart Tooling Daemon, if one is hosted by the Flutter CLI.',
hide: !verboseHelp, hide: !verboseHelp,
); );
// TODO(matanlurey): Remove after the Q2 2025 stable release; this is intended
// to give application developers a single stable release where the .flutter-plugins
// file is still supported, but is deprecated, and let folks ensure (with CI or local
// testing) that their workflows do not depend on the file.
//
// See https://github.com/flutter/flutter/issues/157532.
argParser.addFlag(FlutterGlobalOptions.kImplicitPubspecResolution,
defaultsTo: true,
help: 'Whether to support (deprecated) implicit pubspec resolution '
'features, each of which are slated for removal in a future stable '
'release. By setting to "true", the following occurs:\n'
' 1. The generation of ".flutter-plugins" (https://flutter.dev/to/flutter-plugins-configuration).\n'
' 2. Including plugins registered as "dev_dependencies" in release mode.\n'
' 3. Flutter localizations are by default output to synthetic "flutter_gen" package.\n'
'\n'
'This flag will become "false" by default, and then features removed.',
hide: !verboseHelp,
);
if (verboseHelp) { if (verboseHelp) {
argParser.addSeparator('Local build selection options (not normally required):'); argParser.addSeparator('Local build selection options (not normally required):');
} }

View File

@ -72,10 +72,11 @@ void main() {
return projectPath; return projectPath;
} }
Future<PackagesCommand> runCommandIn(String projectPath, String verb, { List<String>? args }) async { Future<PackagesCommand> runCommandIn(String projectPath, String verb, { List<String>? args, List<String>? globalArgs }) async {
final PackagesCommand command = PackagesCommand(); final PackagesCommand command = PackagesCommand();
final CommandRunner<void> runner = createTestCommandRunner(command); final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[ await runner.run(<String>[
...?globalArgs,
'packages', 'packages',
verb, verb,
...?args, ...?args,
@ -136,15 +137,21 @@ void main() {
'.android/Flutter/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java', '.android/Flutter/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
]; ];
const List<String> pluginWitnesses = <String>[ List<String> pluginWitnesses({required bool includeLegacyPluginsList}) {
'.flutter-plugins', return <String>[
if (includeLegacyPluginsList) '.flutter-plugins',
'.flutter-plugins-dependencies',
'ios/Podfile', 'ios/Podfile',
]; ];
}
const List<String> modulePluginWitnesses = <String>[ List<String> modulePluginWitnesses({required bool includeLegacyPluginsList}) {
'.flutter-plugins', return <String>[
if (includeLegacyPluginsList) '.flutter-plugins',
'.flutter-plugins-dependencies',
'.ios/Podfile', '.ios/Podfile',
]; ];
}
const Map<String, String> pluginContentWitnesses = <String, String>{ const Map<String, String> pluginContentWitnesses = <String, String>{
'ios/Flutter/Debug.xcconfig': '#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"', 'ios/Flutter/Debug.xcconfig': '#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"',
@ -166,7 +173,10 @@ void main() {
for (final String registrant in modulePluginRegistrants) { for (final String registrant in modulePluginRegistrants) {
expectExists(projectPath, registrant); expectExists(projectPath, registrant);
} }
for (final String witness in pluginWitnesses) { for (final String witness in pluginWitnesses(includeLegacyPluginsList: true)) {
expectNotExists(projectPath, witness);
}
for (final String witness in modulePluginWitnesses(includeLegacyPluginsList: true)) {
expectNotExists(projectPath, witness); expectNotExists(projectPath, witness);
} }
modulePluginContentWitnesses.forEach((String witness, String content) { modulePluginContentWitnesses.forEach((String witness, String content) {
@ -174,23 +184,26 @@ void main() {
}); });
} }
void expectPluginInjected(String projectPath) { void expectPluginInjected(String projectPath, {required bool includeLegacyPluginsList}) {
for (final String registrant in pluginRegistrants) { for (final String registrant in pluginRegistrants) {
expectExists(projectPath, registrant); expectExists(projectPath, registrant);
} }
for (final String witness in pluginWitnesses) { for (final String witness in pluginWitnesses(includeLegacyPluginsList: includeLegacyPluginsList)) {
expectExists(projectPath, witness); expectExists(projectPath, witness);
} }
if (!includeLegacyPluginsList) {
expectNotExists(projectPath, '.flutter-plugins');
}
pluginContentWitnesses.forEach((String witness, String content) { pluginContentWitnesses.forEach((String witness, String content) {
expectContains(projectPath, witness, content); expectContains(projectPath, witness, content);
}); });
} }
void expectModulePluginInjected(String projectPath) { void expectModulePluginInjected(String projectPath, {required bool includeLegacyPluginsList}) {
for (final String registrant in modulePluginRegistrants) { for (final String registrant in modulePluginRegistrants) {
expectExists(projectPath, registrant); expectExists(projectPath, registrant);
} }
for (final String witness in modulePluginWitnesses) { for (final String witness in modulePluginWitnesses(includeLegacyPluginsList: includeLegacyPluginsList)) {
expectExists(projectPath, witness); expectExists(projectPath, witness);
} }
modulePluginContentWitnesses.forEach((String witness, String content) { modulePluginContentWitnesses.forEach((String witness, String content) {
@ -202,7 +215,7 @@ void main() {
final Iterable<String> allFiles = <List<String>>[ final Iterable<String> allFiles = <List<String>>[
pubOutput, pubOutput,
modulePluginRegistrants, modulePluginRegistrants,
pluginWitnesses, pluginWitnesses(includeLegacyPluginsList: true),
].expand<String>((List<String> list) => list); ].expand<String>((List<String> list) => list);
for (final String path in allFiles) { for (final String path in allFiles) {
final File file = globals.fs.file(globals.fs.path.join(projectPath, path)); final File file = globals.fs.file(globals.fs.path.join(projectPath, path));
@ -579,7 +592,7 @@ workspace:
await runCommandIn(projectPath, 'get'); await runCommandIn(projectPath, 'get');
expectDependenciesResolved(projectPath); expectDependenciesResolved(projectPath);
expectModulePluginInjected(projectPath); expectModulePluginInjected(projectPath, includeLegacyPluginsList: true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Stdio: () => mockStdio, Stdio: () => mockStdio,
Pub: () => Pub.test( Pub: () => Pub.test(
@ -609,7 +622,35 @@ workspace:
await runCommandIn(exampleProjectPath, 'get'); await runCommandIn(exampleProjectPath, 'get');
expectDependenciesResolved(exampleProjectPath); expectDependenciesResolved(exampleProjectPath);
expectPluginInjected(exampleProjectPath); expectPluginInjected(exampleProjectPath, includeLegacyPluginsList: true);
}, overrides: <Type, Generator>{
Stdio: () => mockStdio,
Pub: () => Pub.test(
fileSystem: globals.fs,
logger: globals.logger,
processManager: globals.processManager,
usage: globals.flutterUsage,
botDetector: globals.botDetector,
platform: globals.platform,
stdio: mockStdio,
),
});
testUsingContext('get --no-implicit-pubspec-resolution omits ".flutter-plugins"', () async {
final String projectPath = await createProject(
tempDir,
arguments: <String>['--template=plugin', '--no-pub', '--platforms=ios,android'],
);
final String exampleProjectPath = globals.fs.path.join(projectPath, 'example');
removeGeneratedFiles(projectPath);
removeGeneratedFiles(exampleProjectPath);
// Running flutter packages get also resolves the dependencies in the example/ project.
await runCommandIn(projectPath, 'get', globalArgs: <String>['--no-implicit-pubspec-resolution']);
expectDependenciesResolved(projectPath);
expectDependenciesResolved(exampleProjectPath);
expectPluginInjected(exampleProjectPath, includeLegacyPluginsList: false);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Stdio: () => mockStdio, Stdio: () => mockStdio,
Pub: () => Pub.test( Pub: () => Pub.test(

View File

@ -402,7 +402,7 @@ dependencies:
group('refreshPlugins', () { group('refreshPlugins', () {
testUsingContext('Refreshing the plugin list is a no-op when the plugins list stays empty', () async { testUsingContext('Refreshing the plugin list is a no-op when the plugins list stays empty', () async {
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(flutterProject.flutterPluginsFile.existsSync(), false); expect(flutterProject.flutterPluginsFile.existsSync(), false);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false);
@ -415,7 +415,7 @@ dependencies:
flutterProject.flutterPluginsFile.createSync(); flutterProject.flutterPluginsFile.createSync();
flutterProject.flutterPluginsDependenciesFile.createSync(); flutterProject.flutterPluginsDependenciesFile.createSync();
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(flutterProject.flutterPluginsFile.existsSync(), false); expect(flutterProject.flutterPluginsFile.existsSync(), false);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false);
@ -434,7 +434,7 @@ dependencies:
iosProject.testExists = true; iosProject.testExists = true;
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(flutterProject.flutterPluginsFile.existsSync(), true); expect(flutterProject.flutterPluginsFile.existsSync(), true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
@ -473,7 +473,7 @@ dependencies:
final DateTime dateCreated = DateTime(1970); final DateTime dateCreated = DateTime(1970);
systemClock.currentTime = dateCreated; systemClock.currentTime = dateCreated;
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
// Verify .flutter-plugins-dependencies is configured correctly. // Verify .flutter-plugins-dependencies is configured correctly.
expect(flutterProject.flutterPluginsFile.existsSync(), true); expect(flutterProject.flutterPluginsFile.existsSync(), true);
@ -583,7 +583,7 @@ dependencies:
final DateTime dateCreated = DateTime(1970); final DateTime dateCreated = DateTime(1970);
systemClock.currentTime = dateCreated; systemClock.currentTime = dateCreated;
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
final String pluginsString = flutterProject.flutterPluginsDependenciesFile.readAsStringSync(); final String pluginsString = flutterProject.flutterPluginsDependenciesFile.readAsStringSync();
@ -655,7 +655,7 @@ dependencies:
flutterProject.usesSwiftPackageManager = true; flutterProject.usesSwiftPackageManager = true;
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
final String pluginsString = flutterProject.flutterPluginsDependenciesFile final String pluginsString = flutterProject.flutterPluginsDependenciesFile
@ -692,7 +692,7 @@ dependencies:
flutterProject.usesSwiftPackageManager = true; flutterProject.usesSwiftPackageManager = true;
await refreshPluginsList(flutterProject, forceCocoaPodsOnly: true); await refreshPluginsList(flutterProject, forceCocoaPodsOnly: true, writeLegacyPluginsList: true);
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true); expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
final String pluginsString = flutterProject.flutterPluginsDependenciesFile final String pluginsString = flutterProject.flutterPluginsDependenciesFile
@ -714,7 +714,7 @@ dependencies:
iosProject.testExists = true; iosProject.testExists = true;
macosProject.exists = true; macosProject.exists = true;
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true); await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true, writeLegacyPluginsList: true);
expect(iosProject.podManifestLock.existsSync(), false); expect(iosProject.podManifestLock.existsSync(), false);
expect(macosProject.podManifestLock.existsSync(), false); expect(macosProject.podManifestLock.existsSync(), false);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -733,11 +733,11 @@ dependencies:
// Since there was no plugins list, the lock files will be invalidated. // Since there was no plugins list, the lock files will be invalidated.
// The second call is where the plugins list is compared to the existing one, and if there is no change, // The second call is where the plugins list is compared to the existing one, and if there is no change,
// the podfiles shouldn't be invalidated. // the podfiles shouldn't be invalidated.
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true); await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true, writeLegacyPluginsList: true);
simulatePodInstallRun(iosProject); simulatePodInstallRun(iosProject);
simulatePodInstallRun(macosProject); simulatePodInstallRun(macosProject);
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(iosProject.podManifestLock.existsSync(), true); expect(iosProject.podManifestLock.existsSync(), true);
expect(macosProject.podManifestLock.existsSync(), true); expect(macosProject.podManifestLock.existsSync(), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -1508,7 +1508,7 @@ The Flutter Preview device does not support the following plugins from your pubs
linuxProject.exists = true; linuxProject.exists = true;
createFakePlugin(fs); createFakePlugin(fs);
// refreshPluginsList should call createPluginSymlinks. // refreshPluginsList should call createPluginSymlinks.
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(linuxProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true); expect(linuxProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -1521,7 +1521,7 @@ The Flutter Preview device does not support the following plugins from your pubs
windowsProject.exists = true; windowsProject.exists = true;
createFakePlugin(fs); createFakePlugin(fs);
// refreshPluginsList should call createPluginSymlinks. // refreshPluginsList should call createPluginSymlinks.
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
expect(windowsProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true); expect(windowsProject.pluginSymlinkDirectory.childLink('some_plugin').existsSync(), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -1567,7 +1567,7 @@ The Flutter Preview device does not support the following plugins from your pubs
// refreshPluginsList should remove existing links and recreate on changes. // refreshPluginsList should remove existing links and recreate on changes.
createFakePlugin(fs); createFakePlugin(fs);
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
for (final File file in dummyFiles) { for (final File file in dummyFiles) {
expect(file.existsSync(), false); expect(file.existsSync(), false);
@ -1606,7 +1606,7 @@ The Flutter Preview device does not support the following plugins from your pubs
linuxProject.exists = true; linuxProject.exists = true;
windowsProject.exists = true; windowsProject.exists = true;
createFakePlugin(fs); createFakePlugin(fs);
await refreshPluginsList(flutterProject); await refreshPluginsList(flutterProject, writeLegacyPluginsList: true);
final List<Link> links = <Link>[ final List<Link> links = <Link>[
linuxProject.pluginSymlinkDirectory.childLink('some_plugin'), linuxProject.pluginSymlinkDirectory.childLink('some_plugin'),

View File

@ -141,12 +141,12 @@ void main() {
FlutterManifest.empty(logger: logger), FlutterManifest.empty(logger: logger),
FlutterManifest.empty(logger: logger), FlutterManifest.empty(logger: logger),
); );
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectNotExists(project.directory); expectNotExists(project.directory);
}); });
_testInMemory('does nothing in plugin or package root project', () async { _testInMemory('does nothing in plugin or package root project', () async {
final FlutterProject project = await aPluginProject(); final FlutterProject project = await aPluginProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectNotExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h')); expectNotExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h'));
expectNotExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app'))); expectNotExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app')));
expectNotExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig')); expectNotExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig'));
@ -158,7 +158,7 @@ void main() {
// that a project was a plugin, but shouldn't be as this creates false // that a project was a plugin, but shouldn't be as this creates false
// positives. // positives.
project.directory.childDirectory('example').createSync(); project.directory.childDirectory('example').createSync();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h')); expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h'));
expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app'))); expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app')));
expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig')); expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig'));
@ -166,22 +166,22 @@ void main() {
}); });
_testInMemory('injects plugins for iOS', () async { _testInMemory('injects plugins for iOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h')); expectExists(project.ios.hostAppRoot.childDirectory('Runner').childFile('GeneratedPluginRegistrant.h'));
}); });
_testInMemory('generates Xcode configuration for iOS', () async { _testInMemory('generates Xcode configuration for iOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig')); expectExists(project.ios.hostAppRoot.childDirectory('Flutter').childFile('Generated.xcconfig'));
}); });
_testInMemory('injects plugins for Android', () async { _testInMemory('injects plugins for Android', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app'))); expectExists(androidPluginRegistrant(project.android.hostAppGradleRoot.childDirectory('app')));
}); });
_testInMemory('updates local properties for Android', () async { _testInMemory('updates local properties for Android', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.android.hostAppGradleRoot.childFile('local.properties')); expectExists(project.android.hostAppGradleRoot.childFile('local.properties'));
}); });
_testInMemory('checkForDeprecation fails on invalid android app manifest file', () async { _testInMemory('checkForDeprecation fails on invalid android app manifest file', () async {
@ -224,18 +224,18 @@ void main() {
final FlutterProject project = await aPluginProject(); final FlutterProject project = await aPluginProject();
project.example.directory.deleteSync(); project.example.directory.deleteSync();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expect(testLogger.statusText, isNot(contains('https://github.com/flutter/flutter/blob/main/docs/platforms/android/Upgrading-pre-1.12-Android-projects.md'))); expect(testLogger.statusText, isNot(contains('https://github.com/flutter/flutter/blob/main/docs/platforms/android/Upgrading-pre-1.12-Android-projects.md')));
}); });
_testInMemory('updates local properties for Android', () async { _testInMemory('updates local properties for Android', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.android.hostAppGradleRoot.childFile('local.properties')); expectExists(project.android.hostAppGradleRoot.childFile('local.properties'));
}); });
testUsingContext('injects plugins for macOS', () async { testUsingContext('injects plugins for macOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.macos.managedDirectory.createSync(recursive: true); project.macos.managedDirectory.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.macos.pluginRegistrantImplementation); expectExists(project.macos.pluginRegistrantImplementation);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
@ -249,7 +249,7 @@ void main() {
testUsingContext('generates Xcode configuration for macOS', () async { testUsingContext('generates Xcode configuration for macOS', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.macos.managedDirectory.createSync(recursive: true); project.macos.managedDirectory.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.macos.generatedXcodePropertiesFile); expectExists(project.macos.generatedXcodePropertiesFile);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
@ -263,7 +263,7 @@ void main() {
testUsingContext('injects plugins for Linux', () async { testUsingContext('injects plugins for Linux', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.linux.cmakeFile.createSync(recursive: true); project.linux.cmakeFile.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.h')); expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.h'));
expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.cc')); expectExists(project.linux.managedDirectory.childFile('generated_plugin_registrant.cc'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -278,7 +278,7 @@ void main() {
testUsingContext('injects plugins for Windows', () async { testUsingContext('injects plugins for Windows', () async {
final FlutterProject project = await someProject(); final FlutterProject project = await someProject();
project.windows.cmakeFile.createSync(recursive: true); project.windows.cmakeFile.createSync(recursive: true);
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.h')); expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.h'));
expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.cc')); expectExists(project.windows.managedDirectory.childFile('generated_plugin_registrant.cc'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
@ -292,14 +292,14 @@ void main() {
}); });
_testInMemory('creates Android library in module', () async { _testInMemory('creates Android library in module', () async {
final FlutterProject project = await aModuleProject(); final FlutterProject project = await aModuleProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
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 module', () async { _testInMemory('creates iOS pod in module', () async {
final FlutterProject project = await aModuleProject(); final FlutterProject project = await aModuleProject();
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling(writeLegacyPluginsList: true);
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'));
expectExists(flutter.childFile('flutter_export_environment.sh')); expectExists(flutter.childFile('flutter_export_environment.sh'));