Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swift package manifest refactoring actions #2904

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ let package = Package(

.testTarget(
name: "SwiftRefactorTest",
dependencies: ["_SwiftSyntaxTestSupport", "SwiftRefactor"]
dependencies: ["_SwiftSyntaxTestSupport", "SwiftIDEUtils", "SwiftRefactor"]
),

// MARK: - Deprecated targets
Expand Down
20 changes: 20 additions & 0 deletions Sources/SwiftRefactor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,26 @@ add_swift_syntax_library(SwiftRefactor
RefactoringProvider.swift
RemoveSeparatorsFromIntegerLiteral.swift
SyntaxUtils.swift

PackageManifest/AbsolutePath.swift
PackageManifest/AddPackageDependency.swift
PackageManifest/AddPackageTarget.swift
PackageManifest/AddPluginUsage.swift
PackageManifest/AddProduct.swift
PackageManifest/AddTargetDependency.swift
PackageManifest/ManifestEditError.swift
PackageManifest/ManifestEditRefactoringProvider.swift
PackageManifest/ManifestSyntaxRepresentable.swift
PackageManifest/PackageDependency.swift
PackageManifest/PackageEdit.swift
PackageManifest/PackageIdentity.swift
PackageManifest/ProductDescription.swift
PackageManifest/RelativePath.swift
PackageManifest/SemanticVersion.swift
PackageManifest/SourceControlURL.swift
PackageManifest/StringUtils.swift
PackageManifest/SyntaxEditUtils.swift
PackageManifest/Target.swift
)

target_link_swift_syntax_libraries(SwiftRefactor PUBLIC
Expand Down
21 changes: 21 additions & 0 deletions Sources/SwiftRefactor/PackageManifest/AbsolutePath.swift
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you’re adding new public declarations, could you add a release notes entry?

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

/// Syntactic wrapper type that describes an absolute path for refactoring
/// purposes but does not interpret its contents.
public struct AbsolutePath: CustomStringConvertible, Equatable, Hashable, Sendable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer not introducing so many fairly generic public types here (AbsolutePath, PackageIdentity, RelativePath, SemanticVersion, SourceControlURL). How much do you prefer this over just strings for these cases? Another alternative would be to namespace them in an enum, but I believe @ahoppen is generally not a fan of that.

Also, could we make Target -> PackageTarget?

public private(set) var description: String
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn’t look like you ever modify it so could be

Suggested change
public private(set) var description: String
public let description: String

Same for the other wrapper types.


public init(_ description: String) {
self.description = description
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftParser
import SwiftSyntax
import SwiftSyntaxBuilder

/// Add a package dependency to a package manifest's source code.
public struct AddPackageDependency: ManifestEditRefactoringProvider {
public struct Context {
public var dependency: PackageDependency

public init(dependency: PackageDependency) {
self.dependency = dependency
}
}

/// The set of argument labels that can occur after the "dependencies"
/// argument in the Package initializers.
///
/// TODO: Could we generate this from the the PackageDescription module, so
/// we don't have keep it up-to-date manually?
private static let argumentLabelsAfterDependencies: Set<String> = [
"targets",
"swiftLanguageVersions",
"cLanguageStandard",
"cxxLanguageStandard",
]

/// Produce the set of source edits needed to add the given package
/// dependency to the given manifest file.
public static func manifestRefactor(
syntax manifest: SourceFileSyntax,
in context: Context
) throws -> PackageEdit {
let dependency = context.dependency
guard let packageCall = manifest.findCall(calleeName: "Package") else {
throw ManifestEditError.cannotFindPackage
}

let newPackageCall = try addPackageDependencyLocal(
dependency,
to: packageCall
)

return PackageEdit(
manifestEdits: [
.replace(packageCall, with: newPackageCall.description)
]
)
}

/// Implementation of adding a package dependency to an existing call.
static func addPackageDependencyLocal(
_ dependency: PackageDependency,
to packageCall: FunctionCallExprSyntax
) throws -> FunctionCallExprSyntax {
try packageCall.appendingToArrayArgument(
label: "dependencies",
trailingLabels: Self.argumentLabelsAfterDependencies,
newElement: dependency.asSyntax()
)
}
}
Loading