-
Notifications
You must be signed in to change notification settings - Fork 501
Expand file tree
/
Copy pathPackageTarget.swift
More file actions
164 lines (136 loc) · 4.35 KB
/
PackageTarget.swift
File metadata and controls
164 lines (136 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import SwiftSyntax
import SwiftSyntaxBuilder
/// Syntactic wrapper type that describes a target for refactoring
/// purposes but does not interpret its contents.
@_spi(PackageRefactor)
public struct PackageTarget {
public let name: String
public var sanitizedName: String {
name
.mangledToC99ExtendedIdentifier()
.localizedFirstWordCapitalized()
}
/// The type of target.
public let type: TargetKind
public internal(set) var dependencies: [Dependency]
public let path: String?
public let url: String?
public let checksum: String?
/// The usages of package plugins by the target.
public let pluginUsages: [PluginUsage]?
/// Represents a target's usage of a plugin target or product.
public enum PluginUsage {
case plugin(name: String, package: String?)
}
public enum TargetKind: String {
case binary
case executable
case library
case macro
case plugin
case system
case test
}
public enum Dependency: Sendable {
case byName(name: String)
case target(name: String)
case product(name: String, package: String?)
/// Retrieve the name of the dependency
public var name: String {
switch self {
case .byName(let name),
.target(let name),
.product(let name, package: _):
return name
}
}
}
public init(
name: String,
type: TargetKind = .library,
dependencies: [Dependency] = [],
path: String? = nil,
url: String? = nil,
checksum: String? = nil,
pluginUsages: [PluginUsage]? = nil
) {
self.name = name
self.type = type
self.dependencies = dependencies
self.path = path
self.url = url
self.checksum = checksum
self.pluginUsages = pluginUsages
}
}
extension PackageTarget: ManifestSyntaxRepresentable {
/// The function name in the package manifest.
private var functionName: String {
switch type {
case .binary: return "binaryTarget"
case .executable: return "executableTarget"
case .library: return "target"
case .macro: return "macro"
case .plugin: return "plugin"
case .system: return "systemLibrary"
case .test: return "testTarget"
}
}
func asSyntax() -> ExprSyntax {
var arguments: [LabeledExprSyntax] = []
arguments.append(label: "name", stringLiteral: name)
// FIXME: pluginCapability
arguments.appendIfNonEmpty(
label: "dependencies",
arrayLiteral: dependencies
)
arguments.appendIf(label: "path", stringLiteral: path)
arguments.appendIf(label: "url", stringLiteral: url)
// Only for plugins
arguments.appendIf(label: "checksum", stringLiteral: checksum)
if let pluginUsages {
arguments.appendIfNonEmpty(label: "plugins", arrayLiteral: pluginUsages)
}
let separateParen: String = arguments.count > 1 ? "\n" : ""
let argumentsSyntax = LabeledExprListSyntax(arguments)
return ".\(raw: functionName)(\(argumentsSyntax)\(raw: separateParen))"
}
}
extension PackageTarget.Dependency: ManifestSyntaxRepresentable {
func asSyntax() -> ExprSyntax {
switch self {
case .byName(let name):
return "\(literal: name)"
case .target(let name):
return ".target(name: \(literal: name))"
case .product(let name, package: nil):
return ".product(name: \(literal: name))"
case .product(let name, let package):
return ".product(name: \(literal: name), package: \(literal: package))"
}
}
}
extension PackageTarget.PluginUsage: ManifestSyntaxRepresentable {
func asSyntax() -> ExprSyntax {
switch self {
case .plugin(let name, package: nil):
return ".plugin(name: \(literal: name))"
case .plugin(let name, let package):
return ".plugin(name: \(literal: name), package: \(literal: package))"
}
}
}
fileprivate extension String {
func localizedFirstWordCapitalized() -> String { prefix(1).uppercased() + dropFirst() }
}