diff --git a/Sources/SwiftRefactor/PackageManifest/SyntaxEditUtils.swift b/Sources/SwiftRefactor/PackageManifest/SyntaxEditUtils.swift index 2f1abdb3a0c..c5eb4ff9648 100644 --- a/Sources/SwiftRefactor/PackageManifest/SyntaxEditUtils.swift +++ b/Sources/SwiftRefactor/PackageManifest/SyntaxEditUtils.swift @@ -198,7 +198,19 @@ extension FunctionCallExprSyntax { return literalValue == targetName } - guard let targetCall = FunctionCallExprSyntax.findFirst(in: targetArray, matching: matchesTargetCall) else { + // Only check the top-level elements of the targets array. A recursive + // search would incorrectly match a target name that appears inside + // another target's `dependencies:` array — e.g. `.target(name: "Foo")` + // listed as a dependency has the same `name:` argument as the actual + // `.target(name: "Foo")` definition at the top level. + guard let targetCall = targetArray.elements.lazy.compactMap({ element -> FunctionCallExprSyntax? in + guard let call = element.expression.as(FunctionCallExprSyntax.self), + matchesTargetCall(call: call) + else { + return nil + } + return call + }).first else { throw ManifestEditError.cannotFindTarget(targetName: targetName) } diff --git a/Tests/SwiftRefactorTest/ManifestEditTests.swift b/Tests/SwiftRefactorTest/ManifestEditTests.swift index eb53f384f90..a24fc5275de 100644 --- a/Tests/SwiftRefactorTest/ManifestEditTests.swift +++ b/Tests/SwiftRefactorTest/ManifestEditTests.swift @@ -642,6 +642,57 @@ final class ManifestEditTests: XCTestCase { ) } + func testAddTargetDependencyWhenTargetIsAlsoDependency() throws { + // Regression test: when a target's name appears inside another target's + // dependencies array, the refactoring must modify the actual target + // definition, not the nested dependency reference. + // See https://github.com/swiftlang/swift-package-manager/issues/10122 + try assertManifestRefactor( + """ + // swift-tools-version: 5.5 + let package = Package( + name: "packages", + targets: [ + .target( + name: "Library", + dependencies: [ + .target(name: "Helper"), + ] + ), + .target( + name: "Helper" + ), + ] + ) + """, + expectedManifest: """ + // swift-tools-version: 5.5 + let package = Package( + name: "packages", + targets: [ + .target( + name: "Library", + dependencies: [ + .target(name: "Helper"), + ] + ), + .target( + name: "Helper", + dependencies: [ + .target(name: "Support"), + ] + ), + ] + ) + """, + provider: AddTargetDependency.self, + context: .init( + dependency: .target(name: "Support"), + targetName: "Helper" + ) + ) + } + func testAddJava2SwiftPlugin() throws { try assertManifestRefactor( """