@@ -899,4 +899,160 @@ class PluginInvocationTests: XCTestCase {
899
899
}
900
900
}
901
901
}
902
+
903
+ func testScanImportsInPluginTargets( ) throws {
904
+ // Only run the test if the environment in which we're running actually supports Swift concurrency (which the plugin APIs require).
905
+ try XCTSkipIf ( !UserToolchain. default. supportsSwiftConcurrency ( ) , " skipping because test environment doesn't support concurrency " )
906
+
907
+ try testWithTemporaryDirectory { tmpPath in
908
+ // Create a sample package with a library target and a plugin.
909
+ let packageDir = tmpPath. appending ( components: " MyPackage " )
910
+ try localFileSystem. createDirectory ( packageDir, recursive: true )
911
+ try localFileSystem. writeFileContents ( packageDir. appending ( component: " Package.swift " ) , string: """
912
+ // swift-tools-version: 5.7
913
+ import PackageDescription
914
+ let package = Package(
915
+ name: " MyPackage " ,
916
+ dependencies: [
917
+ .package(path: " ../OtherPackage " ),
918
+ ],
919
+ targets: [
920
+ .target(
921
+ name: " MyLibrary " ,
922
+ dependencies: [.product(name: " OtherPlugin " , package: " OtherPackage " )]
923
+ ),
924
+ .plugin(
925
+ name: " XPlugin " ,
926
+ capability: .buildTool()
927
+ ),
928
+ .plugin(
929
+ name: " YPlugin " ,
930
+ capability: .command(
931
+ intent: .custom(verb: " YPlugin " , description: " Plugin example " ),
932
+ permissions: []
933
+ )
934
+ )
935
+ ]
936
+ )
937
+ """ )
938
+
939
+ let myLibraryTargetDir = packageDir. appending ( components: " Sources " , " MyLibrary " )
940
+ try localFileSystem. createDirectory ( myLibraryTargetDir, recursive: true )
941
+ try localFileSystem. writeFileContents ( myLibraryTargetDir. appending ( component: " library.swift " ) , string: """
942
+ public func hello() { }
943
+ """ )
944
+ let xPluginTargetDir = packageDir. appending ( components: " Plugins " , " XPlugin " )
945
+ try localFileSystem. createDirectory ( xPluginTargetDir, recursive: true )
946
+ try localFileSystem. writeFileContents ( xPluginTargetDir. appending ( component: " plugin.swift " ) , string: """
947
+ import PackagePlugin
948
+ import XcodeProjectPlugin
949
+ @main struct XBuildToolPlugin: BuildToolPlugin {
950
+ func createBuildCommands(
951
+ context: PluginContext,
952
+ target: Target
953
+ ) throws -> [Command] { }
954
+ }
955
+ """ )
956
+ let yPluginTargetDir = packageDir. appending ( components: " Plugins " , " YPlugin " )
957
+ try localFileSystem. createDirectory ( yPluginTargetDir, recursive: true )
958
+ try localFileSystem. writeFileContents ( yPluginTargetDir. appending ( component: " plugin.swift " ) , string: """
959
+ import PackagePlugin
960
+ import Foundation
961
+ @main struct YPlugin: BuildToolPlugin {
962
+ func createBuildCommands(
963
+ context: PluginContext,
964
+ target: Target
965
+ ) throws -> [Command] { }
966
+ }
967
+ """ )
968
+
969
+
970
+ //////
971
+
972
+ let otherPackageDir = tmpPath. appending ( components: " OtherPackage " )
973
+ try localFileSystem. createDirectory ( otherPackageDir, recursive: true )
974
+ try localFileSystem. writeFileContents ( otherPackageDir. appending ( component: " Package.swift " ) , string: """
975
+ // swift-tools-version: 5.7
976
+ import PackageDescription
977
+ let package = Package(
978
+ name: " OtherPackage " ,
979
+ products: [
980
+ .plugin(
981
+ name: " OtherPlugin " ,
982
+ targets: [ " QPlugin " ])
983
+ ],
984
+ targets: [
985
+ .plugin(
986
+ name: " QPlugin " ,
987
+ capability: .buildTool()
988
+ ),
989
+ .plugin(
990
+ name: " RPlugin " ,
991
+ capability: .command(
992
+ intent: .custom(verb: " RPlugin " , description: " Plugin example " ),
993
+ permissions: []
994
+ )
995
+ )
996
+ ]
997
+ )
998
+ """ )
999
+
1000
+ let qPluginTargetDir = otherPackageDir. appending ( components: " Plugins " , " QPlugin " )
1001
+ try localFileSystem. createDirectory ( qPluginTargetDir, recursive: true )
1002
+ try localFileSystem. writeFileContents ( qPluginTargetDir. appending ( component: " plugin.swift " ) , string: """
1003
+ import PackagePlugin
1004
+ import XcodeProjectPlugin
1005
+ @main struct QBuildToolPlugin: BuildToolPlugin {
1006
+ func createBuildCommands(
1007
+ context: PluginContext,
1008
+ target: Target
1009
+ ) throws -> [Command] { }
1010
+ }
1011
+ """ )
1012
+ /////////
1013
+ // Load a workspace from the package.
1014
+ let observability = ObservabilitySystem . makeForTesting ( )
1015
+ let workspace = try Workspace (
1016
+ fileSystem: localFileSystem,
1017
+ forRootPackage: packageDir,
1018
+ customManifestLoader: ManifestLoader ( toolchain: UserToolchain . default) ,
1019
+ delegate: MockWorkspaceDelegate ( )
1020
+ )
1021
+
1022
+ // Load the root manifest.
1023
+ let rootInput = PackageGraphRootInput ( packages: [ packageDir] , dependencies: [ ] )
1024
+ let rootManifests = try tsc_await {
1025
+ workspace. loadRootManifests (
1026
+ packages: rootInput. packages,
1027
+ observabilityScope: observability. topScope,
1028
+ completion: $0
1029
+ )
1030
+ }
1031
+ XCTAssert ( rootManifests. count == 1 , " \( rootManifests) " )
1032
+
1033
+ let graph = try workspace. loadPackageGraph ( rootInput: rootInput, observabilityScope: observability. topScope)
1034
+ workspace. loadPluginImports ( packageGraph: graph) { ( result: Result < [ PackageIdentity : [ String : [ String ] ] ] , Error > ) in
1035
+
1036
+ var count = 0
1037
+ if let dict = try ? result. get ( ) {
1038
+ for (pkg, entry) in dict {
1039
+ if pkg. description == " mypackage " {
1040
+ XCTAssertNotNil ( entry [ " XPlugin " ] )
1041
+ XCTAssertEqual ( entry [ " XPlugin " ] , [ " PackagePlugin " , " XcodeProjectPlugin " ] )
1042
+ XCTAssertEqual ( entry [ " YPlugin " ] , [ " PackagePlugin " , " Foundation " ] )
1043
+ count += 1
1044
+ } else if pkg. description == " otherpackage " {
1045
+ XCTAssertNotNil ( dict [ pkg] ? [ " QPlugin " ] )
1046
+ XCTAssertEqual ( entry [ " QPlugin " ] , [ " PackagePlugin " , " XcodeProjectPlugin " ] )
1047
+ count += 1
1048
+ }
1049
+ }
1050
+ } else {
1051
+ XCTFail ( " Scanned import list should not be empty " )
1052
+ }
1053
+
1054
+ XCTAssertEqual ( count, 2 )
1055
+ }
1056
+ }
1057
+ }
902
1058
}
0 commit comments