Skip to content

Commit 9895434

Browse files
authored
Give guided message when project is not compatible with SwiftPM (flutter#182394)
Fixes flutter#171921. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent b5afa98 commit 9895434

3 files changed

Lines changed: 109 additions & 21 deletions

File tree

packages/flutter_tools/lib/src/macos/darwin_dependency_management.dart

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,22 @@ class DarwinDependencyManagement {
186186
!xcodeProject.usesSwiftPackageManager &&
187187
!cocoaPodsCompatible &&
188188
swiftPackageManagerCompatible) {
189-
throwToolExit(
190-
'Plugin ${plugin.name} is only Swift Package Manager compatible. Try '
191-
'enabling Swift Package Manager by running '
192-
'"flutter config --enable-swift-package-manager" or remove the '
193-
'plugin as a dependency.',
194-
);
189+
if (xcodeProject.compatibleWithSwiftPackageManager) {
190+
throwToolExit(
191+
'Plugin ${plugin.name} is only compatible with Swift Package Manager. Try '
192+
'enabling Swift Package Manager by running '
193+
'"flutter config --enable-swift-package-manager" or remove the '
194+
'plugin as a dependency.',
195+
);
196+
} else {
197+
throwToolExit(
198+
'Plugin ${plugin.name} is only compatible with Swift Package Manager, but your '
199+
'project does not currently support it. To support Swift Package Manager:\n'
200+
' - Ensure Xcode 15+ is being used '
201+
' - Enable Swift Package Manager feature by running '
202+
'"flutter config --enable-swift-package-manager"',
203+
);
204+
}
195205
}
196206
}
197207

packages/flutter_tools/lib/src/xcode_project.dart

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,11 @@ abstract class XcodeBasedProject extends FlutterProjectPlatform {
181181
);
182182
}
183183

184-
/// True if this project doesn't have Swift Package Manager disabled in the
185-
/// pubspec, has either an iOS or macOS platform implementation, is not a
186-
/// module project, Xcode is 15 or greater, and the Swift Package Manager
187-
/// feature is enabled.
188-
bool get usesSwiftPackageManager {
189-
if (!featureFlags.isSwiftPackageManagerEnabled) {
190-
return false;
191-
}
192-
184+
/// Return true if the project meets the following requirements:
185+
/// - Project is not a module
186+
/// - Xcode project exists
187+
/// - Xcode version is greater or equal to 15
188+
bool get compatibleWithSwiftPackageManager {
193189
// TODO(loic-sharma): Support Swift Package Manager in add-to-app modules.
194190
// https://github.com/flutter/flutter/issues/146957
195191
if (parent.isModule) {
@@ -210,6 +206,11 @@ abstract class XcodeBasedProject extends FlutterProjectPlatform {
210206
return true;
211207
}
212208

209+
/// Return true if the Swift Package Manager feature is enabled and the project is
210+
/// [compatibleWithSwiftPackageManager].
211+
bool get usesSwiftPackageManager =>
212+
featureFlags.isSwiftPackageManagerEnabled && compatibleWithSwiftPackageManager;
213+
213214
Future<XcodeProjectInfo?> projectInfo() async {
214215
final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
215216
if (!xcodeProject.existsSync() ||

packages/flutter_tools/test/general.shard/macos/darwin_dependency_management_test.dart

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,10 @@ void main() {
622622
final cocoaPods = FakeCocoaPods();
623623

624624
final dependencyManagement = DarwinDependencyManagement(
625-
project: FakeFlutterProject(fileSystem: testFileSystem),
625+
project: FakeFlutterProject(
626+
fileSystem: testFileSystem,
627+
compatibleWithSwiftPackageManager: true,
628+
),
626629
plugins: plugins,
627630
cocoapods: cocoaPods,
628631
swiftPackageManager: swiftPackageManager,
@@ -636,7 +639,7 @@ void main() {
636639
() => dependencyManagement.setUp(platform: platform),
637640
throwsToolExit(
638641
message:
639-
'Plugin swift_package_plugin_1 is only Swift Package Manager compatible. Try '
642+
'Plugin swift_package_plugin_1 is only compatible with Swift Package Manager. Try '
640643
'enabling Swift Package Manager by running '
641644
'"flutter config --enable-swift-package-manager" or remove the '
642645
'plugin as a dependency.',
@@ -647,6 +650,56 @@ void main() {
647650
expect(testAnalytics.sentEvents, isEmpty);
648651
});
649652

653+
testWithoutContext(
654+
'with only Swift Package Manager plugins and project does not support',
655+
() async {
656+
final testFileSystem = MemoryFileSystem.test();
657+
final testLogger = BufferLogger.test();
658+
final FakeAnalytics testAnalytics = getInitializedFakeAnalyticsInstance(
659+
fs: testFileSystem,
660+
fakeFlutterVersion: FakeFlutterVersion(),
661+
);
662+
final File swiftPackagePluginPodspec = testFileSystem.file(
663+
'/path/to/cocoapod_plugin_1/darwin/cocoapod_plugin_1/Package.swift',
664+
)..createSync(recursive: true);
665+
final plugins = <Plugin>[
666+
FakePlugin(
667+
name: 'swift_package_plugin_1',
668+
platforms: <String, PluginPlatform>{platform.name: FakePluginPlatform()},
669+
pluginSwiftPackageManifestPath: swiftPackagePluginPodspec.path,
670+
),
671+
];
672+
final swiftPackageManager = FakeSwiftPackageManager(expectedPlugins: plugins);
673+
final cocoaPods = FakeCocoaPods();
674+
675+
final dependencyManagement = DarwinDependencyManagement(
676+
project: FakeFlutterProject(
677+
fileSystem: testFileSystem,
678+
compatibleWithSwiftPackageManager: false,
679+
),
680+
plugins: plugins,
681+
cocoapods: cocoaPods,
682+
swiftPackageManager: swiftPackageManager,
683+
fileSystem: testFileSystem,
684+
featureFlags: TestFeatureFlags(),
685+
logger: testLogger,
686+
analytics: testAnalytics,
687+
platform: FakePlatform(operatingSystem: 'macos'),
688+
);
689+
await expectLater(
690+
() => dependencyManagement.setUp(platform: platform),
691+
throwsToolExit(
692+
message:
693+
'Plugin swift_package_plugin_1 is only compatible with Swift Package '
694+
'Manager, but your project does not currently support it.',
695+
),
696+
);
697+
expect(swiftPackageManager.generated, isFalse);
698+
expect(cocoaPods.podfileSetup, isFalse);
699+
expect(testAnalytics.sentEvents, isEmpty);
700+
},
701+
);
702+
650703
testWithoutContext(
651704
'with only Swift Package Manager plugins does not throw error on non-mac',
652705
() async {
@@ -771,8 +824,12 @@ void main() {
771824
}
772825

773826
class FakeIosProject extends Fake implements IosProject {
774-
FakeIosProject({required MemoryFileSystem fileSystem, required this.usesSwiftPackageManager})
775-
: hostAppRoot = fileSystem.directory('app_name').childDirectory('ios');
827+
FakeIosProject({
828+
required MemoryFileSystem fileSystem,
829+
required this.usesSwiftPackageManager,
830+
bool? compatibleWithSwiftPackageManager,
831+
}) : _compatibleWithSwiftPackageManager = compatibleWithSwiftPackageManager,
832+
hostAppRoot = fileSystem.directory('app_name').childDirectory('ios');
776833

777834
@override
778835
Directory hostAppRoot;
@@ -798,6 +855,12 @@ class FakeIosProject extends Fake implements IosProject {
798855
@override
799856
bool usesSwiftPackageManager;
800857

858+
final bool? _compatibleWithSwiftPackageManager;
859+
860+
@override
861+
bool get compatibleWithSwiftPackageManager =>
862+
_compatibleWithSwiftPackageManager ?? usesSwiftPackageManager;
863+
801864
@override
802865
Directory get managedDirectory => hostAppRoot.childDirectory('Flutter');
803866

@@ -806,8 +869,12 @@ class FakeIosProject extends Fake implements IosProject {
806869
}
807870

808871
class FakeMacOSProject extends Fake implements MacOSProject {
809-
FakeMacOSProject({required MemoryFileSystem fileSystem, required this.usesSwiftPackageManager})
810-
: hostAppRoot = fileSystem.directory('app_name').childDirectory('macos');
872+
FakeMacOSProject({
873+
required MemoryFileSystem fileSystem,
874+
required this.usesSwiftPackageManager,
875+
bool? compatibleWithSwiftPackageManager,
876+
}) : _compatibleWithSwiftPackageManager = compatibleWithSwiftPackageManager,
877+
hostAppRoot = fileSystem.directory('app_name').childDirectory('macos');
811878

812879
@override
813880
Directory hostAppRoot;
@@ -833,6 +900,12 @@ class FakeMacOSProject extends Fake implements MacOSProject {
833900
@override
834901
bool usesSwiftPackageManager;
835902

903+
final bool? _compatibleWithSwiftPackageManager;
904+
905+
@override
906+
bool get compatibleWithSwiftPackageManager =>
907+
_compatibleWithSwiftPackageManager ?? usesSwiftPackageManager;
908+
836909
@override
837910
Directory get managedDirectory => hostAppRoot.childDirectory('Flutter');
838911

@@ -851,21 +924,25 @@ class FakeFlutterProject extends Fake implements FlutterProject {
851924
required this.fileSystem,
852925
this.usesSwiftPackageManager = false,
853926
this.isModule = false,
927+
this.compatibleWithSwiftPackageManager,
854928
});
855929

856930
final MemoryFileSystem fileSystem;
857931
final bool usesSwiftPackageManager;
932+
final bool? compatibleWithSwiftPackageManager;
858933

859934
@override
860935
late final ios = FakeIosProject(
861936
fileSystem: fileSystem,
862937
usesSwiftPackageManager: usesSwiftPackageManager,
938+
compatibleWithSwiftPackageManager: compatibleWithSwiftPackageManager,
863939
);
864940

865941
@override
866942
late final macos = FakeMacOSProject(
867943
fileSystem: fileSystem,
868944
usesSwiftPackageManager: usesSwiftPackageManager,
945+
compatibleWithSwiftPackageManager: compatibleWithSwiftPackageManager,
869946
);
870947

871948
@override

0 commit comments

Comments
 (0)