Skip to content

Commit ef2c316

Browse files
committed
Add arguments to Plugins
1 parent 4dc41b0 commit ef2c316

14 files changed

+74
-35
lines changed

Sources/PackageDescription/PackageDescriptionSerialization.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ enum Serialization {
196196
}
197197

198198
enum PluginUsage: Codable {
199-
case plugin(name: String, package: String?)
199+
case plugin(name: String, package: String?, arguments: [String])
200200
}
201201

202202
struct Target: Codable {

Sources/PackageDescription/PackageDescriptionSerializationConversion.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ extension Serialization.PluginNetworkPermissionScope {
274274
extension Serialization.PluginUsage {
275275
init(_ usage: PackageDescription.Target.PluginUsage) {
276276
switch usage {
277-
case .plugin(let name, let package): self = .plugin(name: name, package: package)
277+
case .plugin(let name, let package, let arguments): self = .plugin(name: name, package: package, arguments: arguments)
278278
}
279279
}
280280
}

Sources/PackageDescription/Target.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public final class Target {
161161
/// The plug-in to apply to each target that uses it, and creates commands
162162
/// that run before or during the build of the target.
163163
@available(_PackageDescription, introduced: 5.5)
164-
case buildTool
164+
case buildTool(arguments: [String])
165165

166166
/// Specifies that the plug-in provides a user command capability.
167167
///
@@ -227,7 +227,7 @@ public final class Target {
227227
/// - Parameters:
228228
/// - name: The name of the plug-in target.
229229
/// - package: The name of the package that defines the plug-in target.
230-
case plugin(name: String, package: String?)
230+
case plugin(name: String, package: String?, arguments: [String])
231231
}
232232

233233
/// Construct a target.
@@ -1398,7 +1398,7 @@ extension Target.PluginCapability {
13981398
/// - Returns: A plug-in capability that defines a build tool.
13991399
@available(_PackageDescription, introduced: 5.5)
14001400
public static func buildTool() -> Target.PluginCapability {
1401-
return .buildTool
1401+
return .buildTool(arguments: [])
14021402
}
14031403
}
14041404

@@ -1507,8 +1507,8 @@ extension Target.PluginUsage {
15071507
/// - Parameter name: The name of the plugin target.
15081508
/// - Returns: A `PluginUsage` instance.
15091509
@available(_PackageDescription, introduced: 5.5)
1510-
public static func plugin(name: String) -> Target.PluginUsage {
1511-
return .plugin(name: name, package: nil)
1510+
public static func plugin(name: String, arguments: [String]) -> Target.PluginUsage {
1511+
return .plugin(name: name, package: nil, arguments: arguments)
15121512
}
15131513
}
15141514

@@ -1535,7 +1535,7 @@ extension Target.PluginUsage: ExpressibleByStringLiteral {
15351535
///
15361536
/// - Parameter value: A string literal.
15371537
public init(stringLiteral value: String) {
1538-
self = .plugin(name: value, package: nil)
1538+
self = .plugin(name: value, package: nil, arguments: [])
15391539
}
15401540
}
15411541

Sources/PackageLoading/ManifestJSONParser.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,8 @@ extension TargetDescription.PluginNetworkPermissionScope {
427427
extension TargetDescription.PluginUsage {
428428
init(_ usage: Serialization.PluginUsage) {
429429
switch usage {
430-
case .plugin(let name, let package):
431-
self = .plugin(name: name, package: package)
430+
case .plugin(let name, let package, let arguments):
431+
self = .plugin(name: name, package: package, arguments: arguments)
432432
}
433433
}
434434
}

Sources/PackageLoading/PackageBuilder.swift

+10-5
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ public final class PackageBuilder {
672672
let potentialModuleMap = Dictionary(potentialModules.map { ($0.name, $0) }, uniquingKeysWith: { $1 })
673673
let successors: (PotentialModule) -> [PotentialModule] = {
674674
// No reference of this target in manifest, i.e. it has no dependencies.
675-
guard let target = self.manifest.targetMap[$0.name] else { return [] }
675+
guard let target: TargetDescription = self.manifest.targetMap[$0.name] else { return [] }
676676
// Collect the successors from declared dependencies.
677677
var successors: [PotentialModule] = target.dependencies.compactMap {
678678
switch $0 {
@@ -692,9 +692,9 @@ public final class PackageBuilder {
692692
if let pluginUsages = target.pluginUsages {
693693
successors += pluginUsages.compactMap {
694694
switch $0 {
695-
case .plugin(_, .some(_)):
695+
case .plugin(_, .some(_), _):
696696
nil
697-
case .plugin(let name, nil):
697+
case .plugin(let name, nil, _):
698698
if let potentialModule = potentialModuleMap[name] {
699699
potentialModule
700700
} else if let targetName = pluginTargetName(for: name),
@@ -766,13 +766,17 @@ public final class PackageBuilder {
766766
let pluginUsages: [Target.PluginUsage] = manifestTarget?.pluginUsages.map {
767767
$0.compactMap { usage in
768768
switch usage {
769-
case .plugin(let name, let package):
769+
case .plugin(let name, let package, let arguments):
770770
if let package {
771771
return .product(Target.ProductReference(name: name, package: package), conditions: [])
772772
} else {
773773
if let target = targets[name] {
774+
if let arguments {
775+
(target as? PluginTarget)?.arguments = arguments
776+
}
774777
return .target(target, conditions: [])
775778
} else if let targetName = pluginTargetName(for: name), let target = targets[targetName] {
779+
// TODO: Check
776780
return .target(target, conditions: [])
777781
} else {
778782
self.observabilityScope.emit(.pluginNotFound(name: name))
@@ -960,7 +964,8 @@ public final class PackageBuilder {
960964
apiVersion: self.manifest.toolsVersion,
961965
pluginCapability: PluginCapability(from: declaredCapability),
962966
dependencies: dependencies,
963-
packageAccess: potentialModule.packageAccess
967+
packageAccess: potentialModule.packageAccess,
968+
arguments: []
964969
)
965970
}
966971

Sources/PackageModel/Manifest/Manifest.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public final class Manifest: Sendable {
237237

238238
let plugins: [String] = target.pluginUsages?.compactMap { pluginUsage in
239239
switch pluginUsage {
240-
case .plugin(name: let name, package: nil):
240+
case .plugin(name: let name, package: nil, _):
241241
if targetsByName.keys.contains(name) {
242242
return name
243243
} else if let targetName = productsByName[name]?.targets.first {
@@ -334,7 +334,7 @@ public final class Manifest: Sendable {
334334
referencedBy pluginUsage: TargetDescription.PluginUsage
335335
) -> PackageDependency? {
336336
switch pluginUsage {
337-
case .plugin(_, .some(let package)):
337+
case .plugin(_, .some(let package), let arguments):
338338
return self.packageDependency(referencedBy: package)
339339
default:
340340
return nil
@@ -433,7 +433,7 @@ public final class Manifest: Sendable {
433433
availablePackages: Set<PackageIdentity>
434434
) {
435435
switch requiredPlugIn {
436-
case .plugin(let name, let package):
436+
case .plugin(let name, let package, let arguments):
437437
if let package {
438438
if !self.register(
439439
product: name,

Sources/PackageModel/Manifest/TargetDescription.swift

+9-4
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public struct TargetDescription: Hashable, Encodable, Sendable {
113113
/// Represents the declared capability of a package plugin.
114114
public enum PluginCapability: Hashable, Sendable {
115115
case buildTool
116-
case command(intent: PluginCommandIntent, permissions: [PluginPermission])
116+
case command(intent: PluginCommandIntent, permissions: [PluginPermission]) // args
117117
}
118118

119119
public enum PluginCommandIntent: Hashable, Codable, Sendable {
@@ -157,7 +157,7 @@ public struct TargetDescription: Hashable, Encodable, Sendable {
157157

158158
/// Represents a target's usage of a plugin target or product.
159159
public enum PluginUsage: Hashable, Sendable {
160-
case plugin(name: String, package: String?)
160+
case plugin(name: String, package: String?, arguments: [String]?)
161161
}
162162

163163
public init(
@@ -339,6 +339,9 @@ extension TargetDescription.PluginCapability: Codable {
339339
}
340340
switch key {
341341
case .buildTool:
342+
// var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key)
343+
// let a1 = try unkeyedValues.decode([String].self)
344+
// self = .bui
342345
self = .buildTool
343346
case .command:
344347
var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key)
@@ -357,10 +360,11 @@ extension TargetDescription.PluginUsage: Codable {
357360
public func encode(to encoder: Encoder) throws {
358361
var container = encoder.container(keyedBy: CodingKeys.self)
359362
switch self {
360-
case let .plugin(name, package):
363+
case let .plugin(name, package, arguments):
361364
var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .plugin)
362365
try unkeyedContainer.encode(name)
363366
try unkeyedContainer.encode(package)
367+
try unkeyedContainer.encode(arguments)
364368
}
365369
}
366370

@@ -374,7 +378,8 @@ extension TargetDescription.PluginUsage: Codable {
374378
var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key)
375379
let name = try unkeyedValues.decode(String.self)
376380
let package = try unkeyedValues.decodeIfPresent(String.self)
377-
self = .plugin(name: name, package: package)
381+
let arguments = try? unkeyedValues.decodeIfPresent([String].self)
382+
self = .plugin(name: name, package: package, arguments: arguments)
378383
}
379384
}
380385
}

Sources/PackageModel/Target/PluginTarget.swift

+9-2
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,20 @@ public final class PluginTarget: Target {
1818
/// API version to use for PackagePlugin API availability.
1919
public let apiVersion: ToolsVersion
2020

21+
public var arguments: [String]
22+
2123
public init(
2224
name: String,
2325
sources: Sources,
2426
apiVersion: ToolsVersion,
2527
pluginCapability: PluginCapability,
2628
dependencies: [Target.Dependency] = [],
27-
packageAccess: Bool
29+
packageAccess: Bool,
30+
arguments: [String]
2831
) {
2932
self.capability = pluginCapability
3033
self.apiVersion = apiVersion
34+
self.arguments = arguments
3135
super.init(
3236
name: name,
3337
type: .plugin,
@@ -45,26 +49,29 @@ public final class PluginTarget: Target {
4549
private enum CodingKeys: String, CodingKey {
4650
case capability
4751
case apiVersion
52+
case arguments
4853
}
4954

5055
public override func encode(to encoder: Encoder) throws {
5156
var container = encoder.container(keyedBy: CodingKeys.self)
5257
try container.encode(self.capability, forKey: .capability)
5358
try container.encode(self.apiVersion, forKey: .apiVersion)
59+
try container.encode(self.arguments, forKey: .arguments)
5460
try super.encode(to: encoder)
5561
}
5662

5763
required public init(from decoder: Decoder) throws {
5864
let container = try decoder.container(keyedBy: CodingKeys.self)
5965
self.capability = try container.decode(PluginCapability.self, forKey: .capability)
6066
self.apiVersion = try container.decode(ToolsVersion.self, forKey: .apiVersion)
67+
self.arguments = try container.decode([String].self, forKey: .arguments)
6168
try super.init(from: decoder)
6269
}
6370
}
6471

6572
public enum PluginCapability: Hashable, Codable {
6673
case buildTool
67-
case command(intent: PluginCommandIntent, permissions: [PluginPermission])
74+
case command(intent: PluginCommandIntent, permissions: [PluginPermission]) // arguments
6875

6976
private enum CodingKeys: String, CodingKey {
7077
case buildTool, command

Sources/PackagePlugin/Plugin.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ extension Plugin {
141141
fileprivate static func handleMessage(_ message: HostToPluginMessage) async throws {
142142
switch message {
143143

144-
case .createBuildToolCommands(let wireInput, let rootPackageId, let targetId, let generatedSources, let generatedResources):
144+
case .createBuildToolCommands(let wireInput, let rootPackageId, let targetId, let generatedSources, let generatedResources, let arguments):
145145
// Deserialize the context from the wire input structures. The root
146146
// package is the one we'll set the context's `package` property to.
147147
let context: PluginContext
@@ -195,7 +195,7 @@ extension Plugin {
195195
}
196196

197197
// Invoke the plugin to create build commands for the target.
198-
let generatedCommands = try await plugin.createBuildCommands(context: context, target: target)
198+
let generatedCommands = try await plugin.createBuildCommands(context: context, target: target, arguments: arguments)
199199

200200
// Send each of the generated commands to the host.
201201
for command in generatedCommands {

Sources/PackagePlugin/PluginMessages.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ enum HostToPluginMessage: Codable {
2121
rootPackageId: InputContext.Package.Id,
2222
targetId: InputContext.Target.Id,
2323
pluginGeneratedSources: [InputContext.URL.Id],
24-
pluginGeneratedResources: [InputContext.URL.Id]
24+
pluginGeneratedResources: [InputContext.URL.Id],
25+
arguments: [String]
2526
)
2627

2728
/// The host requests that the plugin perform a user command (corresponding to a `.command` capability) on a package in the graph.

Sources/PackagePlugin/Protocols.swift

+17-1
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,22 @@ public protocol Plugin {
2525
init()
2626
}
2727

28+
@available(_PackageDescription, introduced: 5.10)
29+
public struct PluginOption {
30+
var value: String?
31+
32+
init(stringLiteral value: String) {
33+
self.value = value
34+
}
35+
36+
// public static func codable<Value: Codable>(_ value: Value, decoder: JSONDecoder = JSONDecoder()) -> Argument {
37+
// return PluginOption(stringLiteral: decoder.decode(Value.self, from: value.))
38+
// }
39+
}
40+
2841
/// Defines functionality for all plugins having a `buildTool` capability.
2942
public protocol BuildToolPlugin: Plugin {
43+
// associatedtype Argument = Argument
3044
/// Invoked by SwiftPM to create build commands for a particular target.
3145
/// The context parameter contains information about the package and its
3246
/// dependencies, as well as other environmental inputs.
@@ -36,7 +50,9 @@ public protocol BuildToolPlugin: Plugin {
3650
/// that it does not directly run those commands.
3751
func createBuildCommands(
3852
context: PluginContext,
39-
target: Target
53+
target: Target,
54+
// https://github.com/apple/swift-evolution/blob/main/proposals/0303-swiftpm-extensible-build-tools.md#type-safe-options
55+
arguments: [String]
4056
) async throws -> [Command]
4157
}
4258

Sources/SPMBuildCore/Plugins/PluginInvocation.swift

+9-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public enum PluginAction {
2323
package: ResolvedPackage,
2424
target: ResolvedModule,
2525
pluginGeneratedSources: [AbsolutePath],
26-
pluginGeneratedResources: [AbsolutePath]
26+
pluginGeneratedResources: [AbsolutePath],
27+
arguments: [String]
2728
)
2829
case performCommand(package: ResolvedPackage, arguments: [String])
2930
}
@@ -46,7 +47,8 @@ extension PluginTarget {
4647
modulesGraph: ModulesGraph,
4748
observabilityScope: ObservabilityScope,
4849
callbackQueue: DispatchQueue,
49-
delegate: PluginInvocationDelegate
50+
delegate: PluginInvocationDelegate,
51+
arguments: [String]
5052
) async throws -> Bool {
5153
try await safe_async {
5254
self.invoke(
@@ -142,7 +144,7 @@ extension PluginTarget {
142144
let actionMessage: HostToPluginMessage
143145
switch action {
144146

145-
case .createBuildToolCommands(let package, let target, let pluginGeneratedSources, let pluginGeneratedResources):
147+
case .createBuildToolCommands(let package, let target, let pluginGeneratedSources, let pluginGeneratedResources, let arguments):
146148
let rootPackageId = try serializer.serialize(package: package)
147149
guard let targetId = try serializer.serialize(target: target) else {
148150
throw StringError("unexpectedly was unable to serialize target \(target)")
@@ -162,7 +164,8 @@ extension PluginTarget {
162164
rootPackageId: rootPackageId,
163165
targetId: targetId,
164166
pluginGeneratedSources: generatedSources,
165-
pluginGeneratedResources: generatedResources
167+
pluginGeneratedResources: generatedResources,
168+
arguments: arguments
166169
)
167170
case .performCommand(let package, let arguments):
168171
let rootPackageId = try serializer.serialize(package: package)
@@ -561,7 +564,8 @@ extension ModulesGraph {
561564
package: package,
562565
target: target,
563566
pluginGeneratedSources: pluginDerivedSources.paths,
564-
pluginGeneratedResources: pluginDerivedResources.map { $0.path }
567+
pluginGeneratedResources: pluginDerivedResources.map { $0.path },
568+
arguments: pluginTarget.arguments
565569
),
566570
buildEnvironment: buildParameters.buildEnvironment,
567571
scriptRunner: pluginScriptRunner,

Tests/FunctionalTests/PluginTests.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,8 @@ final class PluginTests: XCTestCase {
831831
modulesGraph: packageGraph,
832832
observabilityScope: observability.topScope,
833833
callbackQueue: delegateQueue,
834-
delegate: delegate
834+
delegate: delegate,
835+
arguments: []
835836
)
836837
} onCancel: {
837838
do {

Tests/SPMBuildCoreTests/PluginInvocationTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ final class PluginInvocationTests: XCTestCase {
5757
TargetDescription(
5858
name: "Foo",
5959
type: .regular,
60-
pluginUsages: [.plugin(name: "FooPlugin", package: nil)]
60+
pluginUsages: [.plugin(name: "FooPlugin", package: nil, arguments: ["123", "321"])]
6161
),
6262
TargetDescription(
6363
name: "FooPlugin",

0 commit comments

Comments
 (0)