diff --git a/Sources/Commands/PackageCommands/AddDependency.swift b/Sources/Commands/PackageCommands/AddDependency.swift index f14fa2f8f71..cf11c6e5d5d 100644 --- a/Sources/Commands/PackageCommands/AddDependency.swift +++ b/Sources/Commands/PackageCommands/AddDependency.swift @@ -66,24 +66,24 @@ extension SwiftPackageCommand { throw StringError("unknown package") } - switch type { + switch self.type { case .url: try self.createSourceControlPackage( packagePath: packagePath, workspace: workspace, - url: dependency + url: self.dependency ) case .path: try self.createFileSystemPackage( packagePath: packagePath, workspace: workspace, - directory: dependency + directory: self.dependency ) case .registry: try self.createRegistryPackage( packagePath: packagePath, workspace: workspace, - id: dependency + id: self.dependency ) } } @@ -144,19 +144,10 @@ extension SwiftPackageCommand { } } - let packageDependency: PackageDependency = .sourceControl( - identity: identity, - nameForTargetDependencyResolutionOnly: nil, - location: .remote(.init(url)), - requirement: requirement, - productFilter: .everything, - traits: [] - ) - - try applyEdits( + try self.applyEdits( packagePath: packagePath, workspace: workspace, - packageDependency: packageDependency + packageDependency: .sourceControl(name: nil, location: url, requirement: requirement) ) } @@ -208,18 +199,10 @@ extension SwiftPackageCommand { } } - let packageDependency: PackageDependency = .registry( - identity: identity, - requirement: requirement, - productFilter: .everything, - traits: [] - ) - - - try applyEdits( + try self.applyEdits( packagePath: packagePath, workspace: workspace, - packageDependency: packageDependency + packageDependency: .registry(id: id, requirement: requirement) ) } @@ -228,29 +211,17 @@ extension SwiftPackageCommand { workspace: Workspace, directory: String ) throws { - guard let path = try? Basics.AbsolutePath(validating: directory) else { - throw StringError("Package path not found") - } - let identity = PackageIdentity(path: path) - let packageDependency: PackageDependency = .fileSystem( - identity: identity, - nameForTargetDependencyResolutionOnly: nil, - path: path, - productFilter: .everything, - traits: [] - ) - - try applyEdits( + try self.applyEdits( packagePath: packagePath, workspace: workspace, - packageDependency: packageDependency + packageDependency: .fileSystem(name: nil, path: directory) ) } private func applyEdits( packagePath: Basics.AbsolutePath, workspace: Workspace, - packageDependency: PackageDependency + packageDependency: MappablePackageDependency.Kind ) throws { // Load the manifest file let fileSystem = workspace.fileSystem diff --git a/Sources/PackageModelSyntax/AddPackageDependency.swift b/Sources/PackageModelSyntax/AddPackageDependency.swift index 09231a49293..5061195b5db 100644 --- a/Sources/PackageModelSyntax/AddPackageDependency.swift +++ b/Sources/PackageModelSyntax/AddPackageDependency.swift @@ -18,7 +18,7 @@ import SwiftSyntax import SwiftSyntaxBuilder /// Add a package dependency to a manifest's source code. -public struct AddPackageDependency { +public enum AddPackageDependency { /// The set of argument labels that can occur after the "dependencies" /// argument in the Package initializers. /// @@ -28,13 +28,13 @@ public struct AddPackageDependency { "targets", "swiftLanguageVersions", "cLanguageStandard", - "cxxLanguageStandard" + "cxxLanguageStandard", ] /// Produce the set of source edits needed to add the given package /// dependency to the given manifest file. public static func addPackageDependency( - _ dependency: PackageDependency, + _ dependency: MappablePackageDependency.Kind, to manifest: SourceFileSyntax ) throws -> PackageEditResult { // Make sure we have a suitable tools version in the manifest. @@ -50,19 +50,19 @@ public struct AddPackageDependency { return PackageEditResult( manifestEdits: [ - .replace(packageCall, with: newPackageCall.description) + .replace(packageCall, with: newPackageCall.description), ] ) } /// Implementation of adding a package dependency to an existing call. static func addPackageDependencyLocal( - _ dependency: PackageDependency, + _ dependency: MappablePackageDependency.Kind, to packageCall: FunctionCallExprSyntax ) throws -> FunctionCallExprSyntax { try packageCall.appendingToArrayArgument( label: "dependencies", - trailingLabels: Self.argumentLabelsAfterDependencies, + trailingLabels: self.argumentLabelsAfterDependencies, newElement: dependency.asSyntax() ) } diff --git a/Sources/PackageModelSyntax/AddTarget.swift b/Sources/PackageModelSyntax/AddTarget.swift index 5a3fe79f625..51a34323079 100644 --- a/Sources/PackageModelSyntax/AddTarget.swift +++ b/Sources/PackageModelSyntax/AddTarget.swift @@ -18,7 +18,7 @@ import SwiftSyntaxBuilder import struct TSCUtility.Version /// Add a target to a manifest's source code. -public struct AddTarget { +public enum AddTarget { /// The set of argument labels that can occur after the "targets" /// argument in the Package initializers. /// @@ -27,7 +27,7 @@ public struct AddTarget { private static let argumentLabelsAfterTargets: Set = [ "swiftLanguageVersions", "cLanguageStandard", - "cxxLanguageStandard" + "cxxLanguageStandard", ] /// The kind of test harness to use. This isn't part of the manifest @@ -85,7 +85,7 @@ public struct AddTarget { target.dependencies.append(contentsOf: macroTargetDependencies) default: - break; + break } var newPackageCall = try packageCall.appendingToArrayArgument( @@ -103,7 +103,7 @@ public struct AddTarget { guard let outerDirectory else { return PackageEditResult( manifestEdits: [ - .replace(packageCall, with: newPackageCall.description) + .replace(packageCall, with: newPackageCall.description), ] ) } @@ -114,7 +114,7 @@ public struct AddTarget { var auxiliaryFiles: AuxiliaryFiles = [] // Add the primary source file. Every target type has this. - addPrimarySourceFile( + self.addPrimarySourceFile( outerPath: outerPath, target: target, configuration: configuration, @@ -125,7 +125,7 @@ public struct AddTarget { var extraManifestEdits: [SourceEdit] = [] switch target.type { case .macro: - addProvidedMacrosSourceFile( + self.addProvidedMacrosSourceFile( outerPath: outerPath, target: target, to: &auxiliaryFiles @@ -135,7 +135,7 @@ public struct AddTarget { newPackageCall = try AddPackageDependency .addPackageDependencyLocal( .swiftSyntax( - configuration: installedSwiftPMConfiguration + configuration: installedSwiftPMConfiguration ), to: newPackageCall ) @@ -149,7 +149,7 @@ public struct AddTarget { .positionAfterSkippingLeadingTrivia extraManifestEdits.append( SourceEdit( - range: insertPos.. PackageDependency { + fileprivate static func swiftSyntax( + configuration: InstalledSwiftPMConfiguration + ) -> MappablePackageDependency.Kind { let swiftSyntaxVersionDefault = configuration .swiftSyntaxVersionForMacroTemplate let swiftSyntaxVersion = Version(swiftSyntaxVersionDefault.description)! return .sourceControl( - identity: PackageIdentity(url: swiftSyntaxURL), - nameForTargetDependencyResolutionOnly: nil, - location: .remote(swiftSyntaxURL), - requirement: .range(.upToNextMajor(from: swiftSyntaxVersion)), - productFilter: .everything, - traits: [] + name: nil, + location: self.swiftSyntaxURL.absoluteString, + requirement: .range(.upToNextMajor(from: swiftSyntaxVersion)) ) } } -fileprivate extension TargetDescription { - var sanitizedName: String { - name +extension TargetDescription { + fileprivate var sanitizedName: String { + self.name .spm_mangledToC99ExtendedIdentifier() .localizedFirstWordCapitalized() } } -fileprivate extension String { - func localizedFirstWordCapitalized() -> String { prefix(1).localizedCapitalized + dropFirst() } +extension String { + fileprivate func localizedFirstWordCapitalized() -> String { prefix(1).localizedCapitalized + dropFirst() } } diff --git a/Sources/PackageModelSyntax/PackageDependency+Syntax.swift b/Sources/PackageModelSyntax/PackageDependency+Syntax.swift index 20a62a9f1dd..b8a7445938e 100644 --- a/Sources/PackageModelSyntax/PackageDependency+Syntax.swift +++ b/Sources/PackageModelSyntax/PackageDependency+Syntax.swift @@ -16,41 +16,19 @@ import SwiftParser import SwiftSyntax import struct TSCUtility.Version -extension PackageDependency: ManifestSyntaxRepresentable { +extension MappablePackageDependency.Kind: ManifestSyntaxRepresentable { func asSyntax() -> ExprSyntax { switch self { - case .fileSystem(let filesystem): filesystem.asSyntax() - case .sourceControl(let sourceControl): sourceControl.asSyntax() - case .registry(let registry): registry.asSyntax() + case .fileSystem(name: _, path: let path): + ".package(path: \(literal: path.description))" + case .sourceControl(name: _, location: let location, requirement: let requirement): + ".package(url: \(literal: location.description), \(requirement.asSyntax()))" + case .registry(id: let id, requirement: let requirement): + ".package(id: \(literal: id.description), \(requirement.asSyntax()))" } } } -extension PackageDependency.FileSystem: ManifestSyntaxRepresentable { - func asSyntax() -> ExprSyntax { - ".package(path: \(literal: path.description))" - } -} - -extension PackageDependency.SourceControl: ManifestSyntaxRepresentable { - func asSyntax() -> ExprSyntax { - // TODO: Not handling identity, nameForTargetDependencyResolutionOnly, - // or productFilter yet. - switch location { - case .local: - fatalError() - case .remote(let url): - ".package(url: \(literal: url.description), \(requirement.asSyntax()))" - } - } -} - -extension PackageDependency.Registry: ManifestSyntaxRepresentable { - func asSyntax() -> ExprSyntax { - ".package(id: \(literal: identity.description), \(requirement.asSyntax()))" - } -} - extension PackageDependency.SourceControl.Requirement: ManifestSyntaxRepresentable { func asSyntax() -> LabeledExprSyntax { switch self { diff --git a/Tests/CommandsTests/PackageCommandTests.swift b/Tests/CommandsTests/PackageCommandTests.swift index dc21e3d9795..7fa754ef877 100644 --- a/Tests/CommandsTests/PackageCommandTests.swift +++ b/Tests/CommandsTests/PackageCommandTests.swift @@ -886,6 +886,18 @@ final class PackageCommandTests: CommandsTestCase { packagePath: path ) + _ = try await execute( + [ + "add-dependency", + "https://github.com/swiftlang/swift-syntax.git", + "--from", + "2.0.0", + "--to", + "2.2.0", + ], + packagePath: path + ) + _ = try await execute( [ "add-dependency", @@ -896,6 +908,18 @@ final class PackageCommandTests: CommandsTestCase { packagePath: path ) + _ = try await execute( + [ + "add-dependency", + "https://github.com/swiftlang/swift-syntax.git", + "--up-to-next-minor-from", + "3.0.0", + "--to", + "3.3.0", + ], + packagePath: path + ) + let manifest = path.appending("Package.swift") XCTAssertFileExists(manifest) @@ -905,7 +929,9 @@ final class PackageCommandTests: CommandsTestCase { XCTAssertMatch(contents, .contains(#".package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"),"#)) XCTAssertMatch(contents, .contains(#".package(url: "https://github.com/swiftlang/swift-syntax.git", revision: "58e9de4e7b79e67c72a46e164158e3542e570ab6"),"#)) XCTAssertMatch(contents, .contains(#".package(url: "https://github.com/swiftlang/swift-syntax.git", from: "1.0.0"),"#)) + XCTAssertMatch(contents, .contains(#".package(url: "https://github.com/swiftlang/swift-syntax.git", "2.0.0" ..< "2.2.0"),"#)) XCTAssertMatch(contents, .contains(#".package(url: "https://github.com/swiftlang/swift-syntax.git", "1.0.0" ..< "1.1.0"),"#)) + XCTAssertMatch(contents, .contains(#".package(url: "https://github.com/swiftlang/swift-syntax.git", "3.0.0" ..< "3.3.0"),"#)) } } @@ -929,10 +955,19 @@ final class PackageCommandTests: CommandsTestCase { _ = try await execute( [ "add-dependency", - "/directory", + "/absolute", "--type", "path" + ], + packagePath: path + ) + _ = try await execute( + [ + "add-dependency", + "../relative", + "--type", + "path" ], packagePath: path ) @@ -941,7 +976,8 @@ final class PackageCommandTests: CommandsTestCase { XCTAssertFileExists(manifest) let contents: String = try fs.readFileContents(manifest) - XCTAssertMatch(contents, .contains(#".package(path: "/directory"),"#)) + XCTAssertMatch(contents, .contains(#".package(path: "/absolute"),"#)) + XCTAssertMatch(contents, .contains(#".package(path: "../relative"),"#)) } } @@ -986,6 +1022,20 @@ final class PackageCommandTests: CommandsTestCase { packagePath: path ) + _ = try await execute( + [ + "add-dependency", + "scope.name", + "--type", + "registry", + "--from", + "2.0.0", + "--to", + "2.2.0", + ], + packagePath: path + ) + _ = try await execute( [ "add-dependency", @@ -998,13 +1048,29 @@ final class PackageCommandTests: CommandsTestCase { packagePath: path ) + _ = try await execute( + [ + "add-dependency", + "scope.name", + "--type", + "registry", + "--up-to-next-minor-from", + "3.0.0", + "--to", + "3.3.0", + ], + packagePath: path + ) + let manifest = path.appending("Package.swift") XCTAssertFileExists(manifest) let contents: String = try fs.readFileContents(manifest) XCTAssertMatch(contents, .contains(#".package(id: "scope.name", exact: "1.0.0"),"#)) XCTAssertMatch(contents, .contains(#".package(id: "scope.name", from: "1.0.0"),"#)) + XCTAssertMatch(contents, .contains(#".package(id: "scope.name", "2.0.0" ..< "2.2.0"),"#)) XCTAssertMatch(contents, .contains(#".package(id: "scope.name", "1.0.0" ..< "1.1.0"),"#)) + XCTAssertMatch(contents, .contains(#".package(id: "scope.name", "3.0.0" ..< "3.3.0"),"#)) } } diff --git a/Tests/PackageModelSyntaxTests/ManifestEditTests.swift b/Tests/PackageModelSyntaxTests/ManifestEditTests.swift index e868b7a06e3..5ac024ddae6 100644 --- a/Tests/PackageModelSyntaxTests/ManifestEditTests.swift +++ b/Tests/PackageModelSyntaxTests/ManifestEditTests.swift @@ -67,15 +67,12 @@ func assertManifestRefactor( } class ManifestEditTests: XCTestCase { - static let swiftSystemURL: SourceControlURL = "https://github.com/apple/swift-system.git" - static let swiftSystemPackageDependency = PackageDependency.remoteSourceControl( - identity: PackageIdentity(url: swiftSystemURL), - nameForTargetDependencyResolutionOnly: nil, - url: swiftSystemURL, - requirement: .branch("main"), productFilter: .nothing, - traits: [] - ) - + static let swiftSystemURL: String = "https://github.com/apple/swift-system.git" + static let swiftSystemPackageDependency: MappablePackageDependency.Kind = .sourceControl( + name: nil, + location: swiftSystemURL, + requirement: .branch("main") + ) func testAddPackageDependencyExistingComma() throws { try assertManifestRefactor(""" // swift-tools-version: 5.5 @@ -96,13 +93,7 @@ class ManifestEditTests: XCTestCase { ) """) { manifest in try AddPackageDependency.addPackageDependency( - PackageDependency.remoteSourceControl( - identity: PackageIdentity(url: Self.swiftSystemURL), - nameForTargetDependencyResolutionOnly: nil, - url: Self.swiftSystemURL, - requirement: .branch("main"), productFilter: .nothing, - traits:[] - ), + .sourceControl(name: nil, location: Self.swiftSystemURL, requirement: .branch("main")), to: manifest ) } @@ -128,14 +119,7 @@ class ManifestEditTests: XCTestCase { ) """) { manifest in try AddPackageDependency.addPackageDependency( - PackageDependency.remoteSourceControl( - identity: PackageIdentity(url: Self.swiftSystemURL), - nameForTargetDependencyResolutionOnly: nil, - url: Self.swiftSystemURL, - requirement: .exact("510.0.0"), - productFilter: .nothing, - traits: [] - ), + .sourceControl(name: nil, location: Self.swiftSystemURL, requirement: .exact("510.0.0")), to: manifest ) } @@ -163,14 +147,7 @@ class ManifestEditTests: XCTestCase { let versionRange = Range.upToNextMajor(from: Version(510, 0, 0)) return try AddPackageDependency.addPackageDependency( - PackageDependency.remoteSourceControl( - identity: PackageIdentity(url: Self.swiftSystemURL), - nameForTargetDependencyResolutionOnly: nil, - url: Self.swiftSystemURL, - requirement: .range(versionRange), - productFilter: .nothing, - traits: [] - ), + .sourceControl(name: nil, location: Self.swiftSystemURL, requirement: .range(versionRange)), to: manifest ) } @@ -193,14 +170,7 @@ class ManifestEditTests: XCTestCase { let versionRange = Range.upToNextMajor(from: Version(510, 0, 0)) return try AddPackageDependency.addPackageDependency( - PackageDependency.remoteSourceControl( - identity: PackageIdentity(url: Self.swiftSystemURL), - nameForTargetDependencyResolutionOnly: nil, - url: Self.swiftSystemURL, - requirement: .range(versionRange), - productFilter: .nothing, - traits: [] - ), + .sourceControl(name: nil, location: Self.swiftSystemURL, requirement: .range(versionRange)), to: manifest ) } @@ -223,14 +193,7 @@ class ManifestEditTests: XCTestCase { ) """) { manifest in try AddPackageDependency.addPackageDependency( - PackageDependency.remoteSourceControl( - identity: PackageIdentity(url: Self.swiftSystemURL), - nameForTargetDependencyResolutionOnly: nil, - url: Self.swiftSystemURL, - requirement: .range(Version(508,0,0)..