[SwiftPM] Move the logic for SwiftPM enablement to the platform project (#158213)
In the future, it will be possible for Swift Package Manager to be enabled on one but not all platforms (see https://github.com/flutter/flutter/issues/151567#issuecomment-2455941279). This moves the `usesSwiftPackageManager` property from the platform-agnostic `Project` to the platform-specific `IosProject` and `MacOSProject`. This will allow the `IosProject` and `MacOSProject` to return different values for `usesSwiftPackageManager` in the future. For now, both of these projects will always return the same value. Part of https://github.com/flutter/flutter/issues/151567
This commit is contained in:
parent
5a9c2b4dd1
commit
8a55c941cf
@ -1071,12 +1071,22 @@ Future<void> refreshPluginsList(
|
||||
// Write the legacy plugin files to avoid breaking existing apps.
|
||||
final bool legacyChanged = useImplicitPubspecResolution && _writeFlutterPluginsListLegacy(project, plugins);
|
||||
|
||||
final bool swiftPackageManagerEnabled = !forceCocoaPodsOnly && project.usesSwiftPackageManager;
|
||||
bool swiftPackageManagerEnabledIos = false;
|
||||
bool swiftPackageManagerEnabledMacos = false;
|
||||
if (!forceCocoaPodsOnly) {
|
||||
if (iosPlatform) {
|
||||
swiftPackageManagerEnabledIos = project.ios.usesSwiftPackageManager;
|
||||
}
|
||||
if (macOSPlatform) {
|
||||
swiftPackageManagerEnabledMacos = project.macos.usesSwiftPackageManager;
|
||||
}
|
||||
}
|
||||
|
||||
final bool changed = _writeFlutterPluginsList(
|
||||
project,
|
||||
plugins,
|
||||
swiftPackageManagerEnabledIos: swiftPackageManagerEnabled,
|
||||
swiftPackageManagerEnabledMacos: swiftPackageManagerEnabled,
|
||||
swiftPackageManagerEnabledIos: swiftPackageManagerEnabledIos,
|
||||
swiftPackageManagerEnabledMacos: swiftPackageManagerEnabledMacos,
|
||||
);
|
||||
if (changed || legacyChanged || forceCocoaPodsOnly) {
|
||||
createPluginSymlinks(project, force: true);
|
||||
|
@ -166,7 +166,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
RemoveBitcodeMigration(app.project, globals.logger),
|
||||
XcodeThinBinaryBuildPhaseInputPathsMigration(app.project, globals.logger),
|
||||
UIApplicationMainDeprecationMigration(app.project, globals.logger),
|
||||
if (project.usesSwiftPackageManager && app.project.flutterPluginSwiftPackageManifest.existsSync())
|
||||
if (app.project.usesSwiftPackageManager && app.project.flutterPluginSwiftPackageManifest.existsSync())
|
||||
SwiftPackageManagerIntegrationMigration(
|
||||
app.project,
|
||||
SupportedPlatform.ios,
|
||||
@ -267,7 +267,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
targetOverride: targetOverride,
|
||||
buildInfo: buildInfo,
|
||||
);
|
||||
if (project.usesSwiftPackageManager) {
|
||||
if (app.project.usesSwiftPackageManager) {
|
||||
final String? iosDeploymentTarget = buildSettings['IPHONEOS_DEPLOYMENT_TARGET'];
|
||||
if (iosDeploymentTarget != null) {
|
||||
SwiftPackageManager.updateMinimumDeployment(
|
||||
@ -888,7 +888,7 @@ Future<bool> _handleIssues(
|
||||
logger.printError(missingPlatformInstructions(missingPlatform), emphasis: true);
|
||||
} else if (duplicateModules.isNotEmpty) {
|
||||
final bool usesCocoapods = xcodeProject.podfile.existsSync();
|
||||
final bool usesSwiftPackageManager = project.usesSwiftPackageManager;
|
||||
final bool usesSwiftPackageManager = xcodeProject.usesSwiftPackageManager;
|
||||
if (usesCocoapods && usesSwiftPackageManager) {
|
||||
logger.printError(
|
||||
'Your project uses both CocoaPods and Swift Package Manager, which can '
|
||||
@ -906,7 +906,7 @@ Future<bool> _handleIssues(
|
||||
}
|
||||
} else if (missingModules.isNotEmpty) {
|
||||
final bool usesCocoapods = xcodeProject.podfile.existsSync();
|
||||
final bool usesSwiftPackageManager = project.usesSwiftPackageManager;
|
||||
final bool usesSwiftPackageManager = xcodeProject.usesSwiftPackageManager;
|
||||
if (usesCocoapods && !usesSwiftPackageManager) {
|
||||
final List<String> swiftPackageOnlyPlugins = <String>[];
|
||||
for (final String module in missingModules) {
|
||||
|
@ -91,7 +91,7 @@ Future<void> buildMacOS({
|
||||
FlutterApplicationMigration(flutterProject.macos, globals.logger),
|
||||
NSApplicationMainDeprecationMigration(flutterProject.macos, globals.logger),
|
||||
SecureRestorableStateMigration(flutterProject.macos, globals.logger),
|
||||
if (flutterProject.usesSwiftPackageManager && flutterProject.macos.flutterPluginSwiftPackageManifest.existsSync())
|
||||
if (flutterProject.macos.usesSwiftPackageManager && flutterProject.macos.flutterPluginSwiftPackageManifest.existsSync())
|
||||
SwiftPackageManagerIntegrationMigration(
|
||||
flutterProject.macos,
|
||||
SupportedPlatform.macos,
|
||||
@ -145,7 +145,7 @@ Future<void> buildMacOS({
|
||||
useMacOSConfig: true,
|
||||
);
|
||||
|
||||
if (flutterProject.usesSwiftPackageManager) {
|
||||
if (flutterProject.macos.usesSwiftPackageManager) {
|
||||
final String? macOSDeploymentTarget = buildSettings['MACOSX_DEPLOYMENT_TARGET'];
|
||||
if (macOSDeploymentTarget != null) {
|
||||
SwiftPackageManager.updateMinimumDeployment(
|
||||
|
@ -22,7 +22,7 @@ Future<void> processPodsIfNeeded(
|
||||
|
||||
// When using Swift Package Manager, the Podfile may not exist so if there
|
||||
// isn't a Podfile, skip processing pods.
|
||||
if (project.usesSwiftPackageManager &&
|
||||
if (xcodeProject.usesSwiftPackageManager &&
|
||||
!xcodeProject.podfile.existsSync() &&
|
||||
!forceCocoaPodsOnly) {
|
||||
return;
|
||||
@ -50,7 +50,7 @@ Future<void> processPodsIfNeeded(
|
||||
|
||||
// If forcing the use of only CocoaPods, but the project is using Swift
|
||||
// Package Manager, print a warning that CocoaPods will be used.
|
||||
if (forceCocoaPodsOnly && project.usesSwiftPackageManager) {
|
||||
if (forceCocoaPodsOnly && xcodeProject.usesSwiftPackageManager) {
|
||||
globals.logger.printWarning(
|
||||
'Swift Package Manager does not yet support this command. '
|
||||
'CocoaPods will be used instead.');
|
||||
|
@ -167,7 +167,7 @@ class CocoaPods {
|
||||
}) async {
|
||||
if (!xcodeProject.podfile.existsSync()) {
|
||||
// Swift Package Manager doesn't need Podfile, so don't error.
|
||||
if (xcodeProject.parent.usesSwiftPackageManager) {
|
||||
if (xcodeProject.usesSwiftPackageManager) {
|
||||
return false;
|
||||
}
|
||||
throwToolExit('Podfile missing');
|
||||
|
@ -60,7 +60,7 @@ class DarwinDependencyManagement {
|
||||
final XcodeBasedProject xcodeProject = platform == SupportedPlatform.ios
|
||||
? _project.ios
|
||||
: _project.macos;
|
||||
if (_project.usesSwiftPackageManager) {
|
||||
if (xcodeProject.usesSwiftPackageManager) {
|
||||
await _swiftPackageManager.generatePluginsSwiftPackage(
|
||||
_plugins,
|
||||
platform,
|
||||
@ -89,7 +89,7 @@ class DarwinDependencyManagement {
|
||||
);
|
||||
|
||||
final bool useCocoapods;
|
||||
if (_project.usesSwiftPackageManager) {
|
||||
if (xcodeProject.usesSwiftPackageManager) {
|
||||
useCocoapods = swiftPackageCount < totalCount;
|
||||
} else {
|
||||
// When Swift Package Manager is not enabled, set up Podfile if plugins
|
||||
@ -161,7 +161,7 @@ class DarwinDependencyManagement {
|
||||
// If not using Swift Package Manager and plugin does not have podspec
|
||||
// but does have a Package.swift, throw an error. Otherwise, it'll error
|
||||
// when it builds.
|
||||
if (!_project.usesSwiftPackageManager &&
|
||||
if (!xcodeProject.usesSwiftPackageManager &&
|
||||
!cocoaPodsCompatible &&
|
||||
swiftPackageManagerCompatible) {
|
||||
throwToolExit(
|
||||
@ -175,7 +175,7 @@ class DarwinDependencyManagement {
|
||||
// Only show warnings to remove CocoaPods if the project is using Swift
|
||||
// Package Manager, has already been migrated to have SPM integration, and
|
||||
// all plugins are Swift Packages.
|
||||
if (_project.usesSwiftPackageManager &&
|
||||
if (xcodeProject.usesSwiftPackageManager &&
|
||||
xcodeProject.flutterPluginSwiftPackageInProjectSettings &&
|
||||
pluginCount == swiftPackageCount &&
|
||||
swiftPackageCount != 0) {
|
||||
|
@ -21,7 +21,6 @@ import 'features.dart';
|
||||
import 'flutter_manifest.dart';
|
||||
import 'flutter_plugins.dart';
|
||||
import 'globals.dart' as globals;
|
||||
import 'macos/xcode.dart';
|
||||
import 'platform_plugins.dart';
|
||||
import 'project_validator_result.dart';
|
||||
import 'template.dart';
|
||||
@ -262,24 +261,6 @@ class FlutterProject {
|
||||
/// True if this project has an example application.
|
||||
bool get hasExampleApp => _exampleDirectory(directory).existsSync();
|
||||
|
||||
/// True if this project doesn't have Swift Package Manager disabled in the
|
||||
/// pubspec, has either an iOS or macOS platform implementation, is not a
|
||||
/// module project, Xcode is 15 or greater, and the Swift Package Manager
|
||||
/// feature is enabled.
|
||||
bool get usesSwiftPackageManager {
|
||||
if (!manifest.disabledSwiftPackageManager &&
|
||||
(ios.existsSync() || macos.existsSync()) &&
|
||||
!isModule) {
|
||||
final Xcode? xcode = globals.xcode;
|
||||
final Version? xcodeVersion = xcode?.currentVersion;
|
||||
if (xcodeVersion == null || xcodeVersion.major < 15) {
|
||||
return false;
|
||||
}
|
||||
return featureFlags.isSwiftPackageManagerEnabled;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns a list of platform names that are supported by the project.
|
||||
List<SupportedPlatform> getSupportedPlatforms({bool includeRoot = false}) {
|
||||
return <SupportedPlatform>[
|
||||
|
@ -5,15 +5,18 @@
|
||||
import 'base/error_handling_io.dart';
|
||||
import 'base/file_system.dart';
|
||||
import 'base/utils.dart';
|
||||
import 'base/version.dart';
|
||||
import 'build_info.dart';
|
||||
import 'bundle.dart' as bundle;
|
||||
import 'convert.dart';
|
||||
import 'features.dart';
|
||||
import 'flutter_plugins.dart';
|
||||
import 'globals.dart' as globals;
|
||||
import 'ios/code_signing.dart';
|
||||
import 'ios/plist_parser.dart';
|
||||
import 'ios/xcode_build_settings.dart' as xcode;
|
||||
import 'ios/xcodeproj.dart';
|
||||
import 'macos/xcode.dart';
|
||||
import 'platform_plugins.dart';
|
||||
import 'project.dart';
|
||||
import 'template.dart';
|
||||
@ -147,6 +150,40 @@ abstract class XcodeBasedProject extends FlutterProjectPlatform {
|
||||
.contains('FlutterGeneratedPluginSwiftPackage');
|
||||
}
|
||||
|
||||
/// True if this project doesn't have Swift Package Manager disabled in the
|
||||
/// pubspec, has either an iOS or macOS platform implementation, is not a
|
||||
/// module project, Xcode is 15 or greater, and the Swift Package Manager
|
||||
/// feature is enabled.
|
||||
bool get usesSwiftPackageManager {
|
||||
if (!featureFlags.isSwiftPackageManagerEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The project can disable Swift Package Manager in its pubspec.yaml.
|
||||
if (parent.manifest.disabledSwiftPackageManager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(loic-sharma): Support Swift Package Manager in add-to-app modules.
|
||||
// https://github.com/flutter/flutter/issues/146957
|
||||
if (parent.isModule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!existsSync()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Swift Package Manager requires Xcode 15 or greater.
|
||||
final Xcode? xcode = globals.xcode;
|
||||
final Version? xcodeVersion = xcode?.currentVersion;
|
||||
if (xcodeVersion == null || xcodeVersion.major < 15) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<XcodeProjectInfo?> projectInfo() async {
|
||||
final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
|
||||
if (!xcodeProject.existsSync() || xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
|
||||
|
@ -816,6 +816,7 @@ void createFakePlugins(
|
||||
class FakeIosProject extends Fake implements IosProject {
|
||||
FakeIosProject({
|
||||
required MemoryFileSystem fileSystem,
|
||||
this.usesSwiftPackageManager = false,
|
||||
}) : hostAppRoot = fileSystem.directory('app_name').childDirectory('ios');
|
||||
|
||||
@override
|
||||
@ -832,6 +833,9 @@ class FakeIosProject extends Fake implements IosProject {
|
||||
|
||||
@override
|
||||
File get podfile => hostAppRoot.childFile('Podfile');
|
||||
|
||||
@override
|
||||
final bool usesSwiftPackageManager;
|
||||
}
|
||||
|
||||
class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
@ -841,7 +845,8 @@ class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
this.isModule = false,
|
||||
});
|
||||
|
||||
MemoryFileSystem fileSystem;
|
||||
final MemoryFileSystem fileSystem;
|
||||
final bool usesSwiftPackageManager;
|
||||
|
||||
@override
|
||||
late final Directory directory = fileSystem.directory('app_name');
|
||||
@ -856,10 +861,10 @@ class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
File get flutterPluginsDependenciesFile => directory.childFile('.flutter-plugins-dependencies');
|
||||
|
||||
@override
|
||||
late final IosProject ios = FakeIosProject(fileSystem: fileSystem);
|
||||
|
||||
@override
|
||||
final bool usesSwiftPackageManager;
|
||||
late final IosProject ios = FakeIosProject(
|
||||
fileSystem: fileSystem,
|
||||
usesSwiftPackageManager: usesSwiftPackageManager,
|
||||
);
|
||||
|
||||
@override
|
||||
final bool isModule;
|
||||
|
@ -177,7 +177,7 @@ void main() {
|
||||
'plugin_one',
|
||||
'plugin_two'
|
||||
]);
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
flutterProject.ios.usesSwiftPackageManager = true;
|
||||
flutterProject.ios.podfile.createSync(recursive: true);
|
||||
|
||||
await processPodsIfNeeded(
|
||||
@ -200,7 +200,7 @@ void main() {
|
||||
'plugin_one',
|
||||
'plugin_two'
|
||||
]);
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
flutterProject.ios.usesSwiftPackageManager = true;
|
||||
|
||||
await processPodsIfNeeded(
|
||||
flutterProject.ios,
|
||||
@ -221,7 +221,7 @@ void main() {
|
||||
'plugin_one',
|
||||
'plugin_two'
|
||||
]);
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
flutterProject.ios.usesSwiftPackageManager = true;
|
||||
flutterProject.ios.flutterPluginSwiftPackageManifest.createSync(recursive: true);
|
||||
|
||||
await processPodsIfNeeded(
|
||||
@ -336,7 +336,7 @@ void main() {
|
||||
'plugin_one',
|
||||
'plugin_two'
|
||||
]);
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
flutterProject.macos.usesSwiftPackageManager = true;
|
||||
flutterProject.macos.podfile.createSync(recursive: true);
|
||||
|
||||
await processPodsIfNeeded(
|
||||
@ -359,7 +359,7 @@ void main() {
|
||||
'plugin_one',
|
||||
'plugin_two'
|
||||
]);
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
flutterProject.macos.usesSwiftPackageManager = true;
|
||||
|
||||
await processPodsIfNeeded(
|
||||
flutterProject.macos,
|
||||
@ -380,7 +380,7 @@ void main() {
|
||||
'plugin_one',
|
||||
'plugin_two'
|
||||
]);
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
flutterProject.macos.usesSwiftPackageManager = true;
|
||||
flutterProject.macos.flutterPluginSwiftPackageManifest.createSync(recursive: true);
|
||||
|
||||
await processPodsIfNeeded(
|
||||
@ -420,9 +420,6 @@ class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
@override
|
||||
bool isModule = false;
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager = false;
|
||||
|
||||
@override
|
||||
late FlutterManifest manifest;
|
||||
|
||||
@ -436,10 +433,10 @@ class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
late File flutterPluginsDependenciesFile;
|
||||
|
||||
@override
|
||||
late IosProject ios;
|
||||
late FakeIosProject ios;
|
||||
|
||||
@override
|
||||
late MacOSProject macos;
|
||||
late FakeMacOSProject macos;
|
||||
|
||||
@override
|
||||
late AndroidProject android;
|
||||
@ -489,6 +486,9 @@ class FakeMacOSProject extends Fake implements MacOSProject {
|
||||
.childDirectory('Packages')
|
||||
.childDirectory('FlutterGeneratedPluginSwiftPackage')
|
||||
.childFile('Package.swift');
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager = false;
|
||||
}
|
||||
|
||||
class FakeIosProject extends Fake implements IosProject {
|
||||
@ -527,6 +527,9 @@ class FakeIosProject extends Fake implements IosProject {
|
||||
.childDirectory('Packages')
|
||||
.childDirectory('FlutterGeneratedPluginSwiftPackage')
|
||||
.childFile('Package.swift');
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager = false;
|
||||
}
|
||||
|
||||
class FakeAndroidProject extends Fake implements AndroidProject {
|
||||
|
@ -505,6 +505,7 @@ void main() {
|
||||
class FakeIosProject extends Fake implements IosProject {
|
||||
FakeIosProject({
|
||||
required MemoryFileSystem fileSystem,
|
||||
required this.usesSwiftPackageManager,
|
||||
}) : hostAppRoot = fileSystem.directory('app_name').childDirectory('ios');
|
||||
|
||||
@override
|
||||
@ -530,6 +531,9 @@ class FakeIosProject extends Fake implements IosProject {
|
||||
.contains('FlutterGeneratedPluginSwiftPackage');
|
||||
}
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager;
|
||||
|
||||
@override
|
||||
Directory get managedDirectory => hostAppRoot.childDirectory('Flutter');
|
||||
|
||||
@ -540,6 +544,7 @@ class FakeIosProject extends Fake implements IosProject {
|
||||
class FakeMacOSProject extends Fake implements MacOSProject {
|
||||
FakeMacOSProject({
|
||||
required MemoryFileSystem fileSystem,
|
||||
required this.usesSwiftPackageManager,
|
||||
}) : hostAppRoot = fileSystem.directory('app_name').childDirectory('macos');
|
||||
|
||||
@override
|
||||
@ -565,6 +570,9 @@ class FakeMacOSProject extends Fake implements MacOSProject {
|
||||
.contains('FlutterGeneratedPluginSwiftPackage');
|
||||
}
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager;
|
||||
|
||||
@override
|
||||
Directory get managedDirectory => hostAppRoot.childDirectory('Flutter');
|
||||
|
||||
@ -579,18 +587,21 @@ class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
this.isModule = false,
|
||||
});
|
||||
|
||||
MemoryFileSystem fileSystem;
|
||||
|
||||
|
||||
@override
|
||||
late final IosProject ios = FakeIosProject(fileSystem: fileSystem);
|
||||
|
||||
@override
|
||||
late final MacOSProject macos = FakeMacOSProject(fileSystem: fileSystem);
|
||||
|
||||
@override
|
||||
final MemoryFileSystem fileSystem;
|
||||
final bool usesSwiftPackageManager;
|
||||
|
||||
@override
|
||||
late final FakeIosProject ios = FakeIosProject(
|
||||
fileSystem: fileSystem,
|
||||
usesSwiftPackageManager: usesSwiftPackageManager,
|
||||
);
|
||||
|
||||
@override
|
||||
late final FakeMacOSProject macos = FakeMacOSProject(
|
||||
fileSystem: fileSystem,
|
||||
usesSwiftPackageManager: usesSwiftPackageManager,
|
||||
);
|
||||
|
||||
@override
|
||||
final bool isModule;
|
||||
}
|
||||
|
@ -667,9 +667,15 @@ dependencies:
|
||||
final DateTime dateCreated = DateTime(1970);
|
||||
systemClock.currentTime = dateCreated;
|
||||
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
iosProject.usesSwiftPackageManager = true;
|
||||
macosProject.usesSwiftPackageManager = true;
|
||||
|
||||
await refreshPluginsList(flutterProject, useImplicitPubspecResolution: true);
|
||||
await refreshPluginsList(
|
||||
flutterProject,
|
||||
iosPlatform: true,
|
||||
macOSPlatform: true,
|
||||
useImplicitPubspecResolution: true,
|
||||
);
|
||||
|
||||
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
|
||||
final String pluginsString = flutterProject.flutterPluginsDependenciesFile
|
||||
@ -711,7 +717,8 @@ dependencies:
|
||||
final DateTime dateCreated = DateTime(1970);
|
||||
systemClock.currentTime = dateCreated;
|
||||
|
||||
flutterProject.usesSwiftPackageManager = true;
|
||||
iosProject.usesSwiftPackageManager = true;
|
||||
macosProject.usesSwiftPackageManager = true;
|
||||
|
||||
await refreshPluginsList(flutterProject, forceCocoaPodsOnly: true, useImplicitPubspecResolution: true);
|
||||
|
||||
@ -735,6 +742,55 @@ dependencies:
|
||||
FlutterVersion: () => flutterVersion,
|
||||
});
|
||||
|
||||
testUsingContext(
|
||||
'.flutter-plugins-dependencies can have different swift_package_manager_enabled values for iOS and macoS', () async {
|
||||
createPlugin(
|
||||
name: 'plugin-a',
|
||||
platforms: const <String, _PluginPlatformInfo>{
|
||||
// Native-only; should include native build.
|
||||
'android': _PluginPlatformInfo(pluginClass: 'Foo', androidPackage: 'bar.foo'),
|
||||
// Hybrid native and Dart; should include native build.
|
||||
'ios': _PluginPlatformInfo(pluginClass: 'Foo', dartPluginClass: 'Bar', sharedDarwinSource: true),
|
||||
// Web; should not have the native build key at all since it doesn't apply.
|
||||
'web': _PluginPlatformInfo(pluginClass: 'Foo', fileName: 'lib/foo.dart'),
|
||||
// Dart-only; should not include native build.
|
||||
'windows': _PluginPlatformInfo(dartPluginClass: 'Foo'),
|
||||
});
|
||||
iosProject.testExists = true;
|
||||
|
||||
final DateTime dateCreated = DateTime(1970);
|
||||
systemClock.currentTime = dateCreated;
|
||||
|
||||
iosProject.usesSwiftPackageManager = true;
|
||||
macosProject.usesSwiftPackageManager = false;
|
||||
|
||||
await refreshPluginsList(
|
||||
flutterProject,
|
||||
iosPlatform: true,
|
||||
macOSPlatform: true,
|
||||
useImplicitPubspecResolution: true,
|
||||
);
|
||||
|
||||
expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
|
||||
final String pluginsString = flutterProject.flutterPluginsDependenciesFile
|
||||
.readAsStringSync();
|
||||
final Map<String, dynamic> jsonContent = json.decode(pluginsString) as Map<String, dynamic>;
|
||||
|
||||
final Map<String, dynamic> expectedSwiftPackageManagerEnabled = <String, dynamic>{
|
||||
'ios': true,
|
||||
'macos': false,
|
||||
};
|
||||
expect(
|
||||
jsonContent['swift_package_manager_enabled'],
|
||||
expectedSwiftPackageManagerEnabled,
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
SystemClock: () => systemClock,
|
||||
FlutterVersion: () => flutterVersion,
|
||||
});
|
||||
|
||||
testUsingContext('Changes to the plugin list invalidates the Cocoapod lockfiles', () async {
|
||||
simulatePodInstallRun(iosProject);
|
||||
simulatePodInstallRun(macosProject);
|
||||
@ -2108,9 +2164,6 @@ class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
@override
|
||||
bool isModule = false;
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager = false;
|
||||
|
||||
@override
|
||||
late FlutterManifest manifest;
|
||||
|
||||
@ -2154,6 +2207,9 @@ class FakeMacOSProject extends Fake implements MacOSProject {
|
||||
@override
|
||||
late File podManifestLock;
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager = false;
|
||||
|
||||
@override
|
||||
late Directory managedDirectory;
|
||||
|
||||
@ -2187,6 +2243,9 @@ class FakeIosProject extends Fake implements IosProject {
|
||||
|
||||
@override
|
||||
late File podManifestLock;
|
||||
|
||||
@override
|
||||
bool usesSwiftPackageManager = false;
|
||||
}
|
||||
|
||||
class FakeAndroidProject extends Fake implements AndroidProject {
|
||||
|
@ -375,91 +375,6 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('usesSwiftPackageManager', () {
|
||||
testUsingContext('is true when iOS project exists', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.usesSwiftPackageManager, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is true when macOS project exists', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('macos').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.usesSwiftPackageManager, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when disabled via manifest', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest(disabledSwiftPackageManager: true);
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext("is false when iOS and macOS project don't exist", () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when Xcode is less than 15', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(14, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when Swift Package Manager feature is not enabled', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when project is a module', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest(isModule: true);
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
});
|
||||
|
||||
group('java gradle agp compatibility', () {
|
||||
Future<FlutterProject?> configureGradleAgpForTest({
|
||||
required String gradleV,
|
||||
@ -1896,16 +1811,3 @@ class FakeAndroidSdkWithDir extends Fake implements AndroidSdk {
|
||||
@override
|
||||
Directory get directory => _directory;
|
||||
}
|
||||
|
||||
class FakeFlutterManifest extends Fake implements FlutterManifest {
|
||||
FakeFlutterManifest({
|
||||
this.disabledSwiftPackageManager = false,
|
||||
this.isModule = false,
|
||||
});
|
||||
|
||||
@override
|
||||
bool disabledSwiftPackageManager;
|
||||
|
||||
@override
|
||||
bool isModule;
|
||||
}
|
||||
|
@ -6,13 +6,16 @@ import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/version.dart';
|
||||
import 'package:flutter_tools/src/features.dart';
|
||||
import 'package:flutter_tools/src/flutter_manifest.dart';
|
||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:test/fake.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
|
||||
import '../src/fakes.dart';
|
||||
|
||||
void main() {
|
||||
group('IosProject', () {
|
||||
@ -127,6 +130,79 @@ void main() {
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(),
|
||||
});
|
||||
});
|
||||
|
||||
group('usesSwiftPackageManager', () {
|
||||
testUsingContext('is true when iOS project exists', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.ios.usesSwiftPackageManager, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext("is false when iOS project doesn't exist", () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.ios.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when disabled via manifest', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest(disabledSwiftPackageManager: true);
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.ios.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when Xcode is less than 15', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.ios.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(14, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when Swift Package Manager feature is not enabled', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.ios.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when project is a module', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('ios').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest(isModule: true);
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.ios.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('MacOSProject', () {
|
||||
@ -175,6 +251,80 @@ void main() {
|
||||
'app_name/macos/Flutter/Flutter-Debug.xcconfig',
|
||||
);
|
||||
});
|
||||
|
||||
group('usesSwiftPackageManager', () {
|
||||
testUsingContext('is true when macOS project exists', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('macos').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.macos.usesSwiftPackageManager, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext("is false when macOS project doesn't exist", () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.ios.usesSwiftPackageManager, isFalse);
|
||||
expect(project.macos.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when disabled via manifest', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('macos').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest(disabledSwiftPackageManager: true);
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.macos.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when Xcode is less than 15', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('macos').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.macos.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(14, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when Swift Package Manager feature is not enabled', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('macos').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest();
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.macos.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
|
||||
testUsingContext('is false when project is a module', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||
final Directory projectDirectory = fs.directory('path');
|
||||
projectDirectory.childDirectory('macos').createSync(recursive: true);
|
||||
final FlutterManifest manifest = FakeFlutterManifest(isModule: true);
|
||||
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
|
||||
expect(project.macos.usesSwiftPackageManager, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -196,11 +346,15 @@ class FakeFlutterProject extends Fake implements FlutterProject {
|
||||
class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterpreter {
|
||||
FakeXcodeProjectInterpreter({
|
||||
this.isInstalled = true,
|
||||
this.version,
|
||||
});
|
||||
|
||||
@override
|
||||
final bool isInstalled;
|
||||
|
||||
@override
|
||||
final Version? version;
|
||||
|
||||
@override
|
||||
Future<XcodeProjectInfo?> getInfo(String projectPath, {String? projectFilename}) async {
|
||||
return XcodeProjectInfo(
|
||||
@ -211,3 +365,16 @@ class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterprete
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FakeFlutterManifest extends Fake implements FlutterManifest {
|
||||
FakeFlutterManifest({
|
||||
this.disabledSwiftPackageManager = false,
|
||||
this.isModule = false,
|
||||
});
|
||||
|
||||
@override
|
||||
bool disabledSwiftPackageManager;
|
||||
|
||||
@override
|
||||
bool isModule;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user