Skip to content

Commit 34877c5

Browse files
committed
Update SPMPackageEditor library to work with current toolchains
1 parent 53c735c commit 34877c5

File tree

3 files changed

+77
-61
lines changed

3 files changed

+77
-61
lines changed

Package.swift

+13
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,16 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
305305
.package(path: "../swift-driver"),
306306
]
307307
}
308+
309+
// Because SwiftSyntax is closely tied to the compiler, only attempt to build
310+
// the package editor library if we're in a build-script environment and can
311+
// assume we're using a just-built compiler and SwiftSyntax library.
312+
if ProcessInfo.processInfo.environment["SWIFT_BUILD_SCRIPT_ENVIRONMENT"] != nil {
313+
package.dependencies += [.package(path: "../swift-syntax")]
314+
package.targets += [
315+
.target(name: "SPMPackageEditor",
316+
dependencies: ["Workspace", "PackageModel", "PackageLoading",
317+
"SourceControl", "SwiftSyntax", "SwiftToolsSupport-auto"]),
318+
.testTarget(name: "SPMPackageEditorTests", dependencies: ["SPMPackageEditor", "SPMTestSupport"]),
319+
]
320+
}

Sources/SPMPackageEditor/ManifestRewriter.swift

+60-60
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public final class ManifestRewriter {
3737
/// Create a new manfiest editor with the given contents.
3838
public init(_ manifest: String) throws {
3939
self.originalManifest = manifest
40-
self.editedSource = try SyntaxParser.parse(source: manifest)
40+
self.editedSource = Syntax(try SyntaxParser.parse(source: manifest))
4141
}
4242

4343
/// Add a package dependency.
@@ -47,15 +47,15 @@ public final class ManifestRewriter {
4747
) throws {
4848
// Find Package initializer.
4949
let packageFinder = PackageInitFinder()
50-
editedSource.walk(packageFinder)
50+
packageFinder.walk(editedSource)
5151

5252
guard let initFnExpr = packageFinder.packageInit else {
5353
throw Error.error("Couldn't find Package initializer")
5454
}
5555

5656
// Find dependencies section in the argument list of Package(...).
5757
let packageDependenciesFinder = DependenciesArrayFinder()
58-
initFnExpr.argumentList.walk(packageDependenciesFinder)
58+
packageDependenciesFinder.walk(initFnExpr.argumentList)
5959

6060
let packageDependencies: ArrayExprSyntax
6161
if let existingPackageDependencies = packageDependenciesFinder.dependenciesArrayExpr {
@@ -66,7 +66,7 @@ public final class ManifestRewriter {
6666

6767
// Find the inserted section.
6868
let packageDependenciesFinder = DependenciesArrayFinder()
69-
argListWithDependencies.walk(packageDependenciesFinder)
69+
packageDependenciesFinder.walk(argListWithDependencies)
7070
packageDependencies = packageDependenciesFinder.dependenciesArrayExpr!
7171
}
7272

@@ -86,28 +86,28 @@ public final class ManifestRewriter {
8686
) throws {
8787
// Find Package initializer.
8888
let packageFinder = PackageInitFinder()
89-
editedSource.walk(packageFinder)
89+
packageFinder.walk(editedSource)
9090

9191
guard let initFnExpr = packageFinder.packageInit else {
9292
throw Error.error("Couldn't find Package initializer")
9393
}
9494

9595
// Find the `targets: []` array.
9696
let targetsArrayFinder = TargetsArrayFinder()
97-
initFnExpr.argumentList.walk(targetsArrayFinder)
97+
targetsArrayFinder.walk(initFnExpr.argumentList)
9898
guard let targetsArrayExpr = targetsArrayFinder.targets else {
9999
throw Error.error("Couldn't find targets label")
100100
}
101101

102102
// Find the target node.
103103
let targetFinder = TargetFinder(name: target)
104-
targetsArrayExpr.walk(targetFinder)
104+
targetFinder.walk(targetsArrayExpr)
105105
guard let targetNode = targetFinder.foundTarget else {
106106
throw Error.error("Couldn't find target \(target)")
107107
}
108108

109109
let targetDependencyFinder = DependenciesArrayFinder()
110-
targetNode.walk(targetDependencyFinder)
110+
targetDependencyFinder.walk(targetNode)
111111

112112
guard let targetDependencies = targetDependencyFinder.dependenciesArrayExpr else {
113113
throw Error.error("Couldn't find dependencies section")
@@ -128,14 +128,14 @@ public final class ManifestRewriter {
128128
) throws {
129129
// Find Package initializer.
130130
let packageFinder = PackageInitFinder()
131-
editedSource.walk(packageFinder)
131+
packageFinder.walk(editedSource)
132132

133133
guard let initFnExpr = packageFinder.packageInit else {
134134
throw Error.error("Couldn't find Package initializer")
135135
}
136136

137137
let targetsFinder = TargetsArrayFinder()
138-
initFnExpr.argumentList.walk(targetsFinder)
138+
targetsFinder.walk(initFnExpr.argumentList)
139139

140140
guard let targetsNode = targetsFinder.targets else {
141141
throw Error.error("Couldn't find targets section")
@@ -157,12 +157,8 @@ final class PackageInitFinder: SyntaxVisitor {
157157
/// Reference to the function call of the package initializer.
158158
private(set) var packageInit: FunctionCallExprSyntax?
159159

160-
override func shouldVisit(_ kind: SyntaxKind) -> Bool {
161-
return kind == .initializerClause
162-
}
163-
164160
override func visit(_ node: InitializerClauseSyntax) -> SyntaxVisitorContinueKind {
165-
if let fnCall = node.value as? FunctionCallExprSyntax,
161+
if let fnCall = FunctionCallExprSyntax(Syntax(node.value)),
166162
let identifier = fnCall.calledExpression.firstToken,
167163
identifier.text == "Package" {
168164
assert(packageInit == nil, "Found two package initializers")
@@ -177,15 +173,15 @@ final class DependenciesArrayFinder: SyntaxVisitor {
177173

178174
private(set) var dependenciesArrayExpr: ArrayExprSyntax?
179175

180-
override func visit(_ node: FunctionCallArgumentSyntax) -> SyntaxVisitorContinueKind {
176+
override func visit(_ node: TupleExprElementSyntax) -> SyntaxVisitorContinueKind {
181177
guard node.label?.text == "dependencies" else {
182178
return .skipChildren
183179
}
184180

185181
// We have custom code like foo + bar + [] (hopefully there is an array expr here).
186-
if let seq = node.expression as? SequenceExprSyntax {
187-
dependenciesArrayExpr = seq.elements.first(where: { $0 is ArrayExprSyntax }) as? ArrayExprSyntax
188-
} else if let arrayExpr = node.expression as? ArrayExprSyntax {
182+
if let seq = node.expression.as(SequenceExprSyntax.self) {
183+
dependenciesArrayExpr = seq.elements.first(where: { $0.is(ArrayExprSyntax.self) })?.as(ArrayExprSyntax.self)
184+
} else if let arrayExpr = node.expression.as(ArrayExprSyntax.self) {
189185
dependenciesArrayExpr = arrayExpr
190186
}
191187

@@ -202,9 +198,9 @@ final class TargetsArrayFinder: SyntaxVisitor {
202198
/// The found targets array expr.
203199
private(set) var targets: ArrayExprSyntax?
204200

205-
override func visit(_ node: FunctionCallArgumentSyntax) -> SyntaxVisitorContinueKind {
201+
override func visit(_ node: TupleExprElementSyntax) -> SyntaxVisitorContinueKind {
206202
if node.label?.text == "targets",
207-
let expr = node.expression as? ArrayExprSyntax {
203+
let expr = node.expression.as(ArrayExprSyntax.self) {
208204
assert(targets == nil, "Found two targets labels")
209205
targets = expr
210206
}
@@ -216,25 +212,27 @@ final class TargetsArrayFinder: SyntaxVisitor {
216212
final class TargetFinder: SyntaxVisitor {
217213

218214
let targetToFind: String
219-
private(set) var foundTarget: FunctionCallArgumentListSyntax?
215+
private(set) var foundTarget: TupleExprElementListSyntax?
220216

221217
init(name: String) {
222218
self.targetToFind = name
223219
}
224220

225-
override func visit(_ node: FunctionCallArgumentSyntax) -> SyntaxVisitorContinueKind {
221+
override func visit(_ node: TupleExprElementSyntax) -> SyntaxVisitorContinueKind {
226222
guard case .identifier(let label)? = node.label?.tokenKind else {
227223
return .skipChildren
228224
}
229-
guard label == "name", let targetNameExpr = node.expression as? StringLiteralExprSyntax else {
225+
guard label == "name", let targetNameExpr = node.expression.as(StringLiteralExprSyntax.self),
226+
targetNameExpr.segments.count == 1, let segment = targetNameExpr.segments.first?.as(StringSegmentSyntax.self) else {
230227
return .skipChildren
231228
}
232-
guard case .stringLiteral(let targetName) = targetNameExpr.stringLiteral.tokenKind else {
229+
230+
guard case .stringSegment(let targetName) = segment.content.tokenKind else {
233231
return .skipChildren
234232
}
235233

236-
if targetName == "\"" + self.targetToFind + "\"" {
237-
self.foundTarget = node.parent as? FunctionCallArgumentListSyntax
234+
if targetName == self.targetToFind {
235+
self.foundTarget = node.parent?.as(TupleExprElementListSyntax.self)
238236
return .skipChildren
239237
}
240238

@@ -247,22 +245,22 @@ final class TargetFinder: SyntaxVisitor {
247245
/// Writer for "dependencies" array syntax.
248246
final class DependenciesArrayWriter: SyntaxRewriter {
249247

250-
override func visit(_ node: FunctionCallArgumentListSyntax) -> Syntax {
248+
override func visit(_ node: TupleExprElementListSyntax) -> Syntax {
251249
let leadingTrivia = node.firstToken?.leadingTrivia ?? .zero
252250

253-
let dependenciesArg = SyntaxFactory.makeFunctionCallArgument(
251+
let dependenciesArg = SyntaxFactory.makeTupleExprElement(
254252
label: SyntaxFactory.makeIdentifier("dependencies", leadingTrivia: leadingTrivia),
255253
colon: SyntaxFactory.makeColonToken(trailingTrivia: .spaces(1)),
256-
expression: SyntaxFactory.makeArrayExpr(
257-
leftSquare: SyntaxFactory.makeLeftSquareBracketToken(),
258-
elements: SyntaxFactory.makeBlankArrayElementList(),
259-
rightSquare: SyntaxFactory.makeRightSquareBracketToken()),
254+
expression: ExprSyntax(SyntaxFactory.makeArrayExpr(
255+
leftSquare: SyntaxFactory.makeLeftSquareBracketToken(),
256+
elements: SyntaxFactory.makeBlankArrayElementList(),
257+
rightSquare: SyntaxFactory.makeRightSquareBracketToken())),
260258
trailingComma: SyntaxFactory.makeCommaToken()
261259
)
262260

263261
// FIXME: This is not correct, we need to find the
264262
// proper position for inserting `dependencies: []`.
265-
return node.inserting(dependenciesArg, at: 1)
263+
return Syntax(node.inserting(dependenciesArg, at: 1))
266264
}
267265
}
268266

@@ -276,9 +274,9 @@ final class ArrayTrailingCommaWriter: SyntaxRewriter {
276274

277275
override func visit(_ node: ArrayElementSyntax) -> Syntax {
278276
guard lastElement == node else {
279-
return node
277+
return Syntax(node)
280278
}
281-
return node.withTrailingComma(SyntaxFactory.makeCommaToken(trailingTrivia: .spaces(1)))
279+
return Syntax(node.withTrailingComma(SyntaxFactory.makeCommaToken(trailingTrivia: .spaces(1))))
282280
}
283281
}
284282

@@ -307,46 +305,47 @@ final class PackageDependencyWriter: SyntaxRewriter {
307305
declNameArguments: nil
308306
)
309307

310-
var args: [FunctionCallArgumentSyntax] = []
308+
var args: [TupleExprElementSyntax] = []
311309

312310
let firstArgLabel = requirement == .localPackage ? "path" : "url"
313-
let url = SyntaxFactory.makeFunctionCallArgument(
311+
let url = SyntaxFactory.makeTupleExprElement(
314312
label: SyntaxFactory.makeIdentifier(firstArgLabel),
315313
colon: SyntaxFactory.makeColonToken(trailingTrivia: .spaces(1)),
316-
expression: SyntaxFactory.makeStringLiteralExpr(self.url),
314+
expression: ExprSyntax(SyntaxFactory.makeStringLiteralExpr(self.url)),
317315
trailingComma: requirement == .localPackage ? nil : SyntaxFactory.makeCommaToken(trailingTrivia: .spaces(1))
318316
)
319317
args.append(url)
320318

321319
// FIXME: Handle other types of requirements.
322320
if requirement != .localPackage {
323-
let secondArg = SyntaxFactory.makeFunctionCallArgument(
321+
let secondArg = SyntaxFactory.makeTupleExprElement(
324322
label: SyntaxFactory.makeIdentifier("from"),
325323
colon: SyntaxFactory.makeColonToken(trailingTrivia: .spaces(1)),
326-
expression: SyntaxFactory.makeStringLiteralExpr(requirement.ref!),
324+
expression: ExprSyntax(SyntaxFactory.makeStringLiteralExpr(requirement.ref!)),
327325
trailingComma: nil
328326
)
329327
args.append(secondArg)
330328
}
331329

332330
let expr = SyntaxFactory.makeFunctionCallExpr(
333-
calledExpression: dotPackageExpr,
331+
calledExpression: ExprSyntax(dotPackageExpr),
334332
leftParen: SyntaxFactory.makeLeftParenToken(),
335-
argumentList: SyntaxFactory.makeFunctionCallArgumentList(args),
333+
argumentList: SyntaxFactory.makeTupleExprElementList(args),
336334
rightParen: SyntaxFactory.makeRightParenToken(),
337-
trailingClosure: nil
335+
trailingClosure: nil,
336+
additionalTrailingClosures: nil
338337
)
339338

340339
let newDependencyElement = SyntaxFactory.makeArrayElement(
341-
expression: expr,
340+
expression: ExprSyntax(expr),
342341
trailingComma: SyntaxFactory.makeCommaToken()
343342
)
344343

345344
let rightBrace = SyntaxFactory.makeRightSquareBracketToken(
346345
leadingTrivia: [.newlines(1), .spaces(4)])
347346

348-
return node.addArrayElement(newDependencyElement)
349-
.withRightSquare(rightBrace)
347+
return ExprSyntax(node.addElement(newDependencyElement)
348+
.withRightSquare(rightBrace))
350349
}
351350
}
352351

@@ -368,15 +367,15 @@ final class TargetDependencyWriter: SyntaxRewriter {
368367
let lastElement = node.elements.map{$0}.last!
369368
let trailingTriviaWriter = ArrayTrailingCommaWriter(lastElement: lastElement)
370369
let newElements = trailingTriviaWriter.visit(node.elements)
371-
node = node.withElements((newElements as! ArrayElementListSyntax))
370+
node = node.withElements((newElements.as(ArrayElementListSyntax.self)!))
372371
}
373372

374373
let newDependencyElement = SyntaxFactory.makeArrayElement(
375-
expression: SyntaxFactory.makeStringLiteralExpr(self.dependencyName),
374+
expression: ExprSyntax(SyntaxFactory.makeStringLiteralExpr(self.dependencyName)),
376375
trailingComma: nil
377376
)
378377

379-
return node.addArrayElement(newDependencyElement)
378+
return ExprSyntax(node.addElement(newDependencyElement))
380379
}
381380
}
382381

@@ -403,36 +402,37 @@ final class NewTargetWriter: SyntaxRewriter {
403402
declNameArguments: nil
404403
)
405404

406-
let nameArg = SyntaxFactory.makeFunctionCallArgument(
405+
let nameArg = SyntaxFactory.makeTupleExprElement(
407406
label: SyntaxFactory.makeIdentifier("name", leadingTrivia: leadingTriviaArgs),
408407
colon: SyntaxFactory.makeColonToken(trailingTrivia: .spaces(1)),
409-
expression: SyntaxFactory.makeStringLiteralExpr(self.name),
408+
expression: ExprSyntax(SyntaxFactory.makeStringLiteralExpr(self.name)),
410409
trailingComma: SyntaxFactory.makeCommaToken()
411410
)
412411

413412
let emptyArray = SyntaxFactory.makeArrayExpr(leftSquare: SyntaxFactory.makeLeftSquareBracketToken(), elements: SyntaxFactory.makeBlankArrayElementList(), rightSquare: SyntaxFactory.makeRightSquareBracketToken())
414-
let depenenciesArg = SyntaxFactory.makeFunctionCallArgument(
413+
let depenenciesArg = SyntaxFactory.makeTupleExprElement(
415414
label: SyntaxFactory.makeIdentifier("dependencies", leadingTrivia: leadingTriviaArgs),
416415
colon: SyntaxFactory.makeColonToken(trailingTrivia: .spaces(1)),
417-
expression: emptyArray,
416+
expression: ExprSyntax(emptyArray),
418417
trailingComma: nil
419418
)
420419

421420
let expr = SyntaxFactory.makeFunctionCallExpr(
422-
calledExpression: dotPackageExpr,
421+
calledExpression: ExprSyntax(dotPackageExpr),
423422
leftParen: SyntaxFactory.makeLeftParenToken(),
424-
argumentList: SyntaxFactory.makeFunctionCallArgumentList([
423+
argumentList: SyntaxFactory.makeTupleExprElementList([
425424
nameArg, depenenciesArg,
426-
]),
425+
]),
427426
rightParen: SyntaxFactory.makeRightParenToken(),
428-
trailingClosure: nil
427+
trailingClosure: nil,
428+
additionalTrailingClosures: nil
429429
)
430430

431431
let newDependencyElement = SyntaxFactory.makeArrayElement(
432-
expression: expr,
432+
expression: ExprSyntax(expr),
433433
trailingComma: SyntaxFactory.makeCommaToken()
434434
)
435435

436-
return node.addArrayElement(newDependencyElement)
436+
return ExprSyntax(node.addElement(newDependencyElement))
437437
}
438438
}

Sources/SPMPackageEditor/PackageEditor.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ extension Array where Element == TargetDescription.Dependency {
161161
func containsDependency(_ other: String) -> Bool {
162162
return self.contains {
163163
switch $0 {
164-
case .target(let name), .product(let name, _), .byName(let name):
164+
case .target(name: let name, condition: _),
165+
.product(name: let name, package: _, condition: _),
166+
.byName(name: let name, condition: _):
165167
return name == other
166168
}
167169
}
@@ -292,6 +294,7 @@ public final class PackageEditorContext {
292294
baseURL: path.description,
293295
version: nil,
294296
toolsVersion: toolsVersion,
297+
packageKind: .local,
295298
fileSystem: fs
296299
)
297300
}

0 commit comments

Comments
 (0)