diff --git a/Sources/PackagePlugin/Command.swift b/Sources/PackagePlugin/Command.swift index 1c8c7f1e887..3dd5e50b37d 100644 --- a/Sources/PackagePlugin/Command.swift +++ b/Sources/PackagePlugin/Command.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors +// Copyright (c) 2021-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 @@ -16,7 +16,6 @@ import Foundation /// environment variables, initial working directory, etc. All paths should be /// based on the ones passed to the plugin in the target build context. public enum Command { - /// Returns a command that runs when any of its output files are needed by /// the build, but out-of-date. /// @@ -86,8 +85,7 @@ public enum Command { ) } -public extension Command { - +extension Command { /// Returns a command that runs when any of its output files are needed by /// the build, but out-of-date. /// @@ -114,8 +112,8 @@ public extension Command { /// was generated as if in its source directory; other files are treated /// as resources as if explicitly listed in `Package.swift` using /// `.process(...)`. - @available(_PackageDescription, deprecated: 6.0) - static func buildCommand( + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") + public static func buildCommand( displayName: String?, executable: Path, arguments: [CustomStringConvertible], @@ -123,11 +121,11 @@ public extension Command { inputFiles: [Path] = [], outputFiles: [Path] = [] ) -> Command { - return buildCommand( + self.buildCommand( displayName: displayName, executable: URL(fileURLWithPath: executable.stringValue), - arguments: arguments.map{ $0.description }, - environment: environment.mapValues{ $0.description }, + arguments: arguments.map(\.description), + environment: environment.mapValues { $0.description }, inputFiles: inputFiles.map { URL(fileURLWithPath: $0.stringValue) }, outputFiles: outputFiles.map { URL(fileURLWithPath: $0.stringValue) } ) @@ -160,7 +158,7 @@ public extension Command { /// as resources as if explicitly listed in `Package.swift` using /// `.process(...)`. @available(*, unavailable, message: "specifying the initial working directory for a command is not yet supported") - static func buildCommand( + public static func buildCommand( displayName: String?, executable: Path, arguments: [CustomStringConvertible], @@ -169,11 +167,11 @@ public extension Command { inputFiles: [Path] = [], outputFiles: [Path] = [] ) -> Command { - return buildCommand( + self.buildCommand( displayName: displayName, executable: URL(fileURLWithPath: executable.stringValue), - arguments: arguments.map{ $0.description }, - environment: environment.mapValues{ $0.description }, + arguments: arguments.map(\.description), + environment: environment.mapValues { $0.description }, inputFiles: inputFiles.map { URL(fileURLWithPath: $0.stringValue) }, outputFiles: outputFiles.map { URL(fileURLWithPath: $0.stringValue) } ) @@ -204,19 +202,19 @@ public extension Command { /// this command was generated as if in its source directory; other /// files are treated as resources as if explicitly listed in /// `Package.swift` using `.process(...)`. - @available(_PackageDescription, deprecated: 6.0) - static func prebuildCommand( + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") + public static func prebuildCommand( displayName: String?, executable: Path, arguments: [CustomStringConvertible], environment: [String: CustomStringConvertible] = [:], outputFilesDirectory: Path ) -> Command { - return prebuildCommand( + self.prebuildCommand( displayName: displayName, executable: URL(fileURLWithPath: executable.stringValue), - arguments: arguments.map{ $0.description }, - environment: environment.mapValues{ $0.description }, + arguments: arguments.map(\.description), + environment: environment.mapValues { $0.description }, outputFilesDirectory: URL(fileURLWithPath: outputFilesDirectory.stringValue) ) } @@ -247,7 +245,7 @@ public extension Command { /// files are treated as resources as if explicitly listed in /// `Package.swift` using `.process(...)`. @available(*, unavailable, message: "specifying the initial working directory for a command is not yet supported") - static func prebuildCommand( + public static func prebuildCommand( displayName: String?, executable: Path, arguments: [CustomStringConvertible], @@ -255,11 +253,11 @@ public extension Command { workingDirectory: Path? = .none, outputFilesDirectory: Path ) -> Command { - return prebuildCommand( + self.prebuildCommand( displayName: displayName, executable: URL(fileURLWithPath: executable.stringValue), - arguments: arguments.map{ $0.description }, - environment: environment.mapValues{ $0.description }, + arguments: arguments.map(\.description), + environment: environment.mapValues { $0.description }, outputFilesDirectory: URL(fileURLWithPath: outputFilesDirectory.stringValue) ) } diff --git a/Sources/PackagePlugin/Context.swift b/Sources/PackagePlugin/Context.swift index 521bfc95dce..924e6485298 100644 --- a/Sources/PackagePlugin/Context.swift +++ b/Sources/PackagePlugin/Context.swift @@ -31,7 +31,7 @@ public struct PluginContext { /// write its outputs to that directory. The plugin may also create other /// directories for cache files and other file system content that either /// it or the command will need. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "pluginWorkDirectoryURL") public let pluginWorkDirectory: Path /// The path of a writable directory into which the plugin or the build @@ -65,12 +65,12 @@ public struct PluginContext { } return Tool(name: name, path: Path(url: tool.path), url: tool.path) } else { - for dir in toolSearchDirectoryURLs { -#if os(Windows) + for dir in self.toolSearchDirectoryURLs { + #if os(Windows) let hostExecutableSuffix = ".exe" -#else + #else let hostExecutableSuffix = "" -#endif + #endif let path = dir.appendingPathComponent(name + hostExecutableSuffix) if FileManager.default.isExecutableFile(atPath: path.path) { return Tool(name: name, path: Path(url: path), url: path) @@ -86,7 +86,7 @@ public struct PluginContext { /// The paths of directories of in which to search for tools that aren't in /// the `toolNamesToPaths` map. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "toolSearchDirectoryURLs") let toolSearchDirectories: [Path] /// The paths of directories of in which to search for tools that aren't in @@ -100,7 +100,7 @@ public struct PluginContext { public let name: String /// Full path of the built or provided tool in the file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "url") public let path: Path /// Full path of the built or provided tool in the file system. diff --git a/Sources/PackagePlugin/PackageManagerProxy.swift b/Sources/PackagePlugin/PackageManagerProxy.swift index 8268b439512..01f8ddf3aa5 100644 --- a/Sources/PackagePlugin/PackageManagerProxy.swift +++ b/Sources/PackagePlugin/PackageManagerProxy.swift @@ -17,7 +17,6 @@ import Foundation /// functionality in whatever way is appropriate for them, but should preserve /// the same semantics described here. public struct PackageManager { - /// Performs a build of all or a subset of products and targets in a package. /// /// Any errors encountered during the build are reported in the build result, @@ -33,12 +32,12 @@ public struct PackageManager { ) throws -> BuildResult { // Ask the plugin host to build the specified products and targets, and wait for a response. // FIXME: We'll want to make this asynchronous when there is back deployment support for it. - return try sendMessageAndWaitForReply(.buildOperationRequest(subset: .init(subset), parameters: .init(parameters))) { + try sendMessageAndWaitForReply(.buildOperationRequest(subset: .init(subset), parameters: .init(parameters))) { guard case .buildOperationResponse(let result) = $0 else { return nil } return .init(result) } } - + /// Specifies a subset of products and targets of a package to build. public enum BuildSubset { /// Represents the subset consisting of all products and of either all @@ -51,12 +50,12 @@ public struct PackageManager { /// Represents the target with the specified name. case target(String) } - + /// Parameters and options to apply during a build. public struct BuildParameters { /// Whether to build for debug or release. public var configuration: BuildConfiguration - + /// Controls the amount of detail in the log returned in the build result. public var logging: BuildLogVerbosity @@ -71,46 +70,50 @@ public struct PackageManager { /// Additional flags to pass to all Swift compiler invocations. public var otherSwiftcFlags: [String] = [] - + /// Additional flags to pass to all linker invocations. public var otherLinkerFlags: [String] = [] - public init(configuration: BuildConfiguration = .debug, logging: BuildLogVerbosity = .concise, echoLogs: Bool = false) { + public init( + configuration: BuildConfiguration = .debug, + logging: BuildLogVerbosity = .concise, + echoLogs: Bool = false + ) { self.configuration = configuration self.logging = logging self.echoLogs = echoLogs } } - + /// Represents an overall purpose of the build, which affects such things /// as optimization and generation of debug symbols. public enum BuildConfiguration: String { case debug, release, inherit } - + /// Represents the amount of detail in a build log. public enum BuildLogVerbosity: String { case concise, verbose, debug } - + /// Represents the results of running a build. public struct BuildResult { /// Whether the build succeeded or failed. public var succeeded: Bool - + /// Log output (the verbatim text in the initial proposal). public var logText: String - + /// The artifacts built from the products in the package. Intermediates /// such as object files produced from individual targets are not listed. public var builtArtifacts: [BuiltArtifact] - + /// Represents a single artifact produced during a build. public struct BuiltArtifact { /// Full path of the built artifact in the local file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "url") public var path: Path { - return Path(url: url) + Path(url: self.url) } /// Full path of the built artifact in the local file system. @@ -119,7 +122,7 @@ public struct PackageManager { /// The kind of artifact that was built. public var kind: Kind - + /// Represents the kind of artifact that was built. The specific file /// formats may vary from platform to platform — for example, on macOS /// a dynamic library may in fact be built as a framework. @@ -128,7 +131,7 @@ public struct PackageManager { } } } - + /// Runs all or a specified subset of the unit tests of the package, after /// an incremental build if necessary (the same as `swift test` does). /// @@ -144,12 +147,12 @@ public struct PackageManager { ) throws -> TestResult { // Ask the plugin host to run the specified tests, and wait for a response. // FIXME: We'll want to make this asynchronous when there is back deployment support for it. - return try sendMessageAndWaitForReply(.testOperationRequest(subset: .init(subset), parameters: .init(parameters))) { + try sendMessageAndWaitForReply(.testOperationRequest(subset: .init(subset), parameters: .init(parameters))) { guard case .testOperationResponse(let result) = $0 else { return nil } return .init(result) } } - + /// Specifies what tests in a package to run. public enum TestSubset { /// Represents all tests in the package. @@ -160,31 +163,31 @@ public struct PackageManager { /// This is the same as the `--filter` option of `swift test`. case filtered([String]) } - + /// Parameters that control how the tests are run. public struct TestParameters { /// Whether to collect code coverage information while running the tests. public var enableCodeCoverage: Bool - + public init(enableCodeCoverage: Bool = false) { self.enableCodeCoverage = enableCodeCoverage } } - + /// Represents the result of running unit tests. public struct TestResult { /// Whether the test run succeeded or failed. public var succeeded: Bool - + /// Results for all the test targets that were run (filtered based on /// the input subset passed when running the test). public var testTargets: [TestTarget] - + /// Path of a generated `.profdata` file suitable for processing using /// `llvm-cov`, if `enableCodeCoverage` was set in the test parameters. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "codeCoverageDataFileURL") public var codeCoverageDataFile: Path? { - return codeCoverageDataFileURL.map { Path(url: $0) } + self.codeCoverageDataFileURL.map { Path(url: $0) } } /// Path of a generated `.profdata` file suitable for processing using @@ -197,7 +200,7 @@ public struct PackageManager { public struct TestTarget { public var name: String public var testCases: [TestCase] - + /// Represents the results of running some or all of the tests in /// a single test case. public struct TestCase { @@ -218,7 +221,7 @@ public struct PackageManager { } } } - + /// Return a directory containing symbol graph files for the given target /// and options. If the symbol graphs need to be created or updated first, /// they will be. SwiftPM or an IDE may generate these symbol graph files @@ -229,7 +232,7 @@ public struct PackageManager { ) throws -> SymbolGraphResult { // Ask the plugin host for symbol graph information for the target, and wait for a response. // FIXME: We'll want to make this asynchronous when there is back deployment support for it. - return try sendMessageAndWaitForReply(.symbolGraphRequest(targetName: target.name, options: .init(options))) { + try sendMessageAndWaitForReply(.symbolGraphRequest(targetName: target.name, options: .init(options))) { guard case .symbolGraphResponse(let result) = $0 else { return nil } return .init(result) } @@ -242,19 +245,24 @@ public struct PackageManager { /// Represents a Swift access level. public enum AccessLevel: String, CaseIterable { - case `private`, `fileprivate`, `internal`, `public`, `open` + case `private`, `fileprivate`, `internal`, `public`, open } /// Whether to include synthesized members. public var includeSynthesized: Bool - + /// Whether to include symbols marked as SPI. public var includeSPI: Bool /// Whether to emit symbols for extensions to external types. public var emitExtensionBlocks: Bool - - public init(minimumAccessLevel: AccessLevel = .public, includeSynthesized: Bool = false, includeSPI: Bool = false, emitExtensionBlocks: Bool = false) { + + public init( + minimumAccessLevel: AccessLevel = .public, + includeSynthesized: Bool = false, + includeSPI: Bool = false, + emitExtensionBlocks: Bool = false + ) { self.minimumAccessLevel = minimumAccessLevel self.includeSynthesized = includeSynthesized self.includeSPI = includeSPI @@ -265,9 +273,9 @@ public struct PackageManager { /// Represents the result of symbol graph generation. public struct SymbolGraphResult { /// The directory that contains the symbol graph files for the target. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "directoryURL") public var directoryPath: Path { - return Path(url: directoryURL) + Path(url: self.directoryURL) } /// The directory that contains the symbol graph files for the target. @@ -276,9 +284,13 @@ public struct PackageManager { } } -fileprivate extension PackageManager { - /// Private helper function that sends a message to the host and waits for a reply. The reply handler should return nil for any reply message it doesn't recognize. - func sendMessageAndWaitForReply(_ message: PluginToHostMessage, replyHandler: (HostToPluginMessage) -> T?) throws -> T { +extension PackageManager { + /// Private helper function that sends a message to the host and waits for a reply. The reply handler should return + /// `nil` for any reply message it doesn't recognize. + private func sendMessageAndWaitForReply( + _ message: PluginToHostMessage, + replyHandler: (HostToPluginMessage) -> T? + ) throws -> T { try pluginHostConnection.sendMessage(message) guard let reply = try pluginHostConnection.waitForNextMessage() else { throw PackageManagerProxyError.unspecified("internal error: unexpected lack of response message") @@ -296,13 +308,13 @@ fileprivate extension PackageManager { public enum PackageManagerProxyError: Error { /// Indicates that the functionality isn't implemented in the plugin host. case unimplemented(_ message: String) - + /// An unspecified other kind of error from the Package Manager proxy. case unspecified(_ message: String) } -fileprivate extension PluginToHostMessage.BuildSubset { - init(_ subset: PackageManager.BuildSubset) { +extension PluginToHostMessage.BuildSubset { + fileprivate init(_ subset: PackageManager.BuildSubset) { switch subset { case .all(let includingTests): self = .all(includingTests: includingTests) @@ -314,8 +326,8 @@ fileprivate extension PluginToHostMessage.BuildSubset { } } -fileprivate extension PluginToHostMessage.BuildParameters { - init(_ parameters: PackageManager.BuildParameters) { +extension PluginToHostMessage.BuildParameters { + fileprivate init(_ parameters: PackageManager.BuildParameters) { self.configuration = .init(parameters.configuration) self.logging = .init(parameters.logging) self.echoLogs = parameters.echoLogs @@ -326,8 +338,8 @@ fileprivate extension PluginToHostMessage.BuildParameters { } } -fileprivate extension PluginToHostMessage.BuildParameters.Configuration { - init(_ configuration: PackageManager.BuildConfiguration) { +extension PluginToHostMessage.BuildParameters.Configuration { + fileprivate init(_ configuration: PackageManager.BuildConfiguration) { switch configuration { case .debug: self = .debug @@ -339,8 +351,8 @@ fileprivate extension PluginToHostMessage.BuildParameters.Configuration { } } -fileprivate extension PluginToHostMessage.BuildParameters.LogVerbosity { - init(_ verbosity: PackageManager.BuildLogVerbosity) { +extension PluginToHostMessage.BuildParameters.LogVerbosity { + fileprivate init(_ verbosity: PackageManager.BuildLogVerbosity) { switch verbosity { case .concise: self = .concise @@ -352,23 +364,23 @@ fileprivate extension PluginToHostMessage.BuildParameters.LogVerbosity { } } -fileprivate extension PackageManager.BuildResult { - init(_ result: HostToPluginMessage.BuildResult) { +extension PackageManager.BuildResult { + fileprivate init(_ result: HostToPluginMessage.BuildResult) { self.succeeded = result.succeeded self.logText = result.logText self.builtArtifacts = result.builtArtifacts.map { .init($0) } } } -fileprivate extension PackageManager.BuildResult.BuiltArtifact { - init(_ artifact: HostToPluginMessage.BuildResult.BuiltArtifact) { +extension PackageManager.BuildResult.BuiltArtifact { + fileprivate init(_ artifact: HostToPluginMessage.BuildResult.BuiltArtifact) { self.kind = .init(artifact.kind) self.url = artifact.path } } -fileprivate extension PackageManager.BuildResult.BuiltArtifact.Kind { - init(_ kind: HostToPluginMessage.BuildResult.BuiltArtifact.Kind) { +extension PackageManager.BuildResult.BuiltArtifact.Kind { + fileprivate init(_ kind: HostToPluginMessage.BuildResult.BuiltArtifact.Kind) { switch kind { case .executable: self = .executable @@ -380,8 +392,8 @@ fileprivate extension PackageManager.BuildResult.BuiltArtifact.Kind { } } -fileprivate extension PluginToHostMessage.TestSubset { - init(_ subset: PackageManager.TestSubset) { +extension PluginToHostMessage.TestSubset { + fileprivate init(_ subset: PackageManager.TestSubset) { switch subset { case .all: self = .all @@ -391,44 +403,44 @@ fileprivate extension PluginToHostMessage.TestSubset { } } -fileprivate extension PluginToHostMessage.TestParameters { - init(_ parameters: PackageManager.TestParameters) { +extension PluginToHostMessage.TestParameters { + fileprivate init(_ parameters: PackageManager.TestParameters) { self.enableCodeCoverage = parameters.enableCodeCoverage } } -fileprivate extension PackageManager.TestResult { - init(_ result: HostToPluginMessage.TestResult) { +extension PackageManager.TestResult { + fileprivate init(_ result: HostToPluginMessage.TestResult) { self.succeeded = result.succeeded - self.testTargets = result.testTargets.map{ .init($0) } + self.testTargets = result.testTargets.map { .init($0) } self.codeCoverageDataFileURL = result.codeCoverageDataFile.map { URL(fileURLWithPath: $0) } } } -fileprivate extension PackageManager.TestResult.TestTarget { - init(_ testTarget: HostToPluginMessage.TestResult.TestTarget) { +extension PackageManager.TestResult.TestTarget { + fileprivate init(_ testTarget: HostToPluginMessage.TestResult.TestTarget) { self.name = testTarget.name - self.testCases = testTarget.testCases.map{ .init($0) } + self.testCases = testTarget.testCases.map { .init($0) } } } -fileprivate extension PackageManager.TestResult.TestTarget.TestCase { - init(_ testCase: HostToPluginMessage.TestResult.TestTarget.TestCase) { +extension PackageManager.TestResult.TestTarget.TestCase { + fileprivate init(_ testCase: HostToPluginMessage.TestResult.TestTarget.TestCase) { self.name = testCase.name - self.tests = testCase.tests.map{ .init($0) } + self.tests = testCase.tests.map { .init($0) } } } -fileprivate extension PackageManager.TestResult.TestTarget.TestCase.Test { - init(_ test: HostToPluginMessage.TestResult.TestTarget.TestCase.Test) { +extension PackageManager.TestResult.TestTarget.TestCase.Test { + fileprivate init(_ test: HostToPluginMessage.TestResult.TestTarget.TestCase.Test) { self.name = test.name self.result = .init(test.result) self.duration = test.duration } } -fileprivate extension PackageManager.TestResult.TestTarget.TestCase.Test.Result { - init(_ result: HostToPluginMessage.TestResult.TestTarget.TestCase.Test.Result) { +extension PackageManager.TestResult.TestTarget.TestCase.Test.Result { + fileprivate init(_ result: HostToPluginMessage.TestResult.TestTarget.TestCase.Test.Result) { switch result { case .succeeded: self = .succeeded @@ -440,8 +452,8 @@ fileprivate extension PackageManager.TestResult.TestTarget.TestCase.Test.Result } } -fileprivate extension PluginToHostMessage.SymbolGraphOptions { - init(_ options: PackageManager.SymbolGraphOptions) { +extension PluginToHostMessage.SymbolGraphOptions { + fileprivate init(_ options: PackageManager.SymbolGraphOptions) { self.minimumAccessLevel = .init(options.minimumAccessLevel) self.includeSynthesized = options.includeSynthesized self.includeSPI = options.includeSPI @@ -449,8 +461,8 @@ fileprivate extension PluginToHostMessage.SymbolGraphOptions { } } -fileprivate extension PluginToHostMessage.SymbolGraphOptions.AccessLevel { - init(_ accessLevel: PackageManager.SymbolGraphOptions.AccessLevel) { +extension PluginToHostMessage.SymbolGraphOptions.AccessLevel { + fileprivate init(_ accessLevel: PackageManager.SymbolGraphOptions.AccessLevel) { switch accessLevel { case .private: self = .private @@ -466,8 +478,8 @@ fileprivate extension PluginToHostMessage.SymbolGraphOptions.AccessLevel { } } -fileprivate extension PackageManager.SymbolGraphResult { - init(_ result: HostToPluginMessage.SymbolGraphResult) { +extension PackageManager.SymbolGraphResult { + fileprivate init(_ result: HostToPluginMessage.SymbolGraphResult) { self.directoryURL = result.directoryPath } } diff --git a/Sources/PackagePlugin/PackageModel.swift b/Sources/PackagePlugin/PackageModel.swift index fd61fe2b272..fff6774a26a 100644 --- a/Sources/PackagePlugin/PackageModel.swift +++ b/Sources/PackagePlugin/PackageModel.swift @@ -22,7 +22,7 @@ public struct Package { public let displayName: String /// The absolute path of the package directory in the local file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "directoryURL") public let directory: Path /// The absolute path of the package directory in the local file system. @@ -36,7 +36,7 @@ public struct Package { /// Behavior is often gated on the tools version, to make sure older /// packages continue to work as intended. public let toolsVersion: ToolsVersion - + /// Any dependencies on other packages, in the same order as they are /// specified in the package manifest. public let dependencies: [PackageDependency] @@ -89,7 +89,7 @@ public struct ToolsVersion { public struct PackageDependency { /// The package to which the dependency was resolved. public let package: Package - + init(package: Package) { self.package = package } @@ -100,11 +100,11 @@ public protocol Product { /// Unique identifier for the product. var id: ID { get } typealias ID = String - + /// The name of the product, as defined in the package manifest. This name /// is unique among the products of the package in which it is defined. var name: String { get } - + /// The targets that directly comprise the product, in the order in which /// they are declared in the package manifest. The product will contain the /// transitive closure of the these targets and their dependencies. Some @@ -118,7 +118,7 @@ public protocol Product { public struct ExecutableProduct: Product { /// Unique identifier for the product. public let id: ID - + /// The name of the product, as defined in the package manifest. This name /// is unique among the products of the package in which it is defined. public let name: String @@ -159,7 +159,7 @@ public struct LibraryProduct: Product { case `static` /// Dynamic library, whose code is referenced by its clients. - case `dynamic` + case dynamic /// The kind of library produced is unspecified and will be determined /// by the build system based on how the library is used. @@ -176,10 +176,10 @@ public protocol Target { /// The name of the target, as defined in the package manifest. This name /// is unique among the targets of the package in which it is defined. var name: String { get } - + /// The absolute path of the target directory in the local file system. var directory: Path { get } - + /// Any other targets on which this target depends, in the same order as /// they are specified in the package manifest. Conditional dependencies /// that do not apply have already been filtered out. @@ -201,7 +201,7 @@ public protocol SourceModuleTarget: Target { /// The name of the module produced by the target (derived from the target /// name, though future SwiftPM versions may allow this to be customized). var moduleName: String { get } - + /// The kind of module, describing whether it contains unit tests, contains /// the main entry point of an executable, or neither. var kind: ModuleKind { get } @@ -218,15 +218,19 @@ public protocol SourceModuleTarget: Target { /// package manifest. var linkedFrameworks: [String] { get } - /// Paths of any sources generated by other plugins that have been applied to the given target before the plugin currently being executed. + /// Paths of any sources generated by other plugins that have been applied to the given target before the plugin + /// currently being executed. /// - /// Note: Plugins are applied in order of declaration in the package manifest. Generated files are vended to the target the current plugin is being applied to, but not necessarily to other targets in the package graph. + /// Note: Plugins are applied in order of declaration in the package manifest. Generated files are vended to the + /// target the current plugin is being applied to, but not necessarily to other targets in the package graph. @available(_PackageDescription, introduced: 6.0) var pluginGeneratedSources: [URL] { get } - /// Paths of any resources generated by other plugins that have been applied to the given target before the plugin currently being executed. + /// Paths of any resources generated by other plugins that have been applied to the given target before the plugin + /// currently being executed. /// - /// Note: Plugins are applied in order of declaration in the package manifest. Generated files are vended to the target the current plugin is being applied to, but not necessarily to other targets in the package graph. + /// Note: Plugins are applied in order of declaration in the package manifest. Generated files are vended to the + /// target the current plugin is being applied to, but not necessarily to other targets in the package graph. @available(_PackageDescription, introduced: 6.0) var pluginGeneratedResources: [URL] { get } } @@ -251,17 +255,17 @@ public enum ModuleKind { public struct SwiftSourceModuleTarget: SourceModuleTarget { /// Unique identifier for the target. public let id: ID - + /// The name of the target, as defined in the package manifest. This name /// is unique among the targets of the package in which it is defined. public let name: String - + /// The kind of module, describing whether it contains unit tests, contains /// the main entry point of an executable, or neither. public let kind: ModuleKind /// The absolute path of the target directory in the local file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "directoryURL") public let directory: Path /// The absolute path of the target directory in the local file system. @@ -293,11 +297,13 @@ public struct SwiftSourceModuleTarget: SourceModuleTarget { /// package manifest. public let linkedFrameworks: [String] - /// Paths of any sources generated by other plugins that have been applied to the given target before the plugin currently being executed. + /// Paths of any sources generated by other plugins that have been applied to the given target before the plugin + /// currently being executed. @available(_PackageDescription, introduced: 6.0) public let pluginGeneratedSources: [URL] - /// Paths of any resources generated by other plugins that have been applied to the given target before the plugin currently being executed. + /// Paths of any resources generated by other plugins that have been applied to the given target before the plugin + /// currently being executed. @available(_PackageDescription, introduced: 6.0) public let pluginGeneratedResources: [URL] } @@ -306,17 +312,17 @@ public struct SwiftSourceModuleTarget: SourceModuleTarget { public struct ClangSourceModuleTarget: SourceModuleTarget { /// Unique identifier for the target. public let id: ID - + /// The name of the target, as defined in the package manifest. This name /// is unique among the targets of the package in which it is defined. public let name: String - + /// The kind of module, describing whether it contains unit tests, contains /// the main entry point of an executable, or neither. public let kind: ModuleKind /// The absolute path of the target directory in the local file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "directoryURL") public let directory: Path /// The absolute path of the target directory in the local file system. @@ -338,13 +344,13 @@ public struct ClangSourceModuleTarget: SourceModuleTarget { /// Any preprocessor definitions specified for the Clang target. public let preprocessorDefinitions: [String] - + /// Any custom header search paths specified for the Clang target. public let headerSearchPaths: [String] /// The directory containing public C headers, if applicable. This will /// only be set for targets that have a directory of a public headers. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "publicHeadersDirectoryURL") public let publicHeadersDirectory: Path? /// The directory containing public C headers, if applicable. This will @@ -360,11 +366,13 @@ public struct ClangSourceModuleTarget: SourceModuleTarget { /// package manifest. public let linkedFrameworks: [String] - /// Paths of any sources generated by other plugins that have been applied to the given target before the plugin currently being executed. + /// Paths of any sources generated by other plugins that have been applied to the given target before the plugin + /// currently being executed. @available(_PackageDescription, introduced: 6.0) public let pluginGeneratedSources: [URL] - /// Paths of any resources generated by other plugins that have been applied to the given target before the plugin currently being executed. + /// Paths of any resources generated by other plugins that have been applied to the given target before the plugin + /// currently being executed. @available(_PackageDescription, introduced: 6.0) public let pluginGeneratedResources: [URL] } @@ -378,9 +386,9 @@ public struct BinaryArtifactTarget: Target { /// The name of the target, as defined in the package manifest. This name /// is unique among the targets of the package in which it is defined. public let name: String - + /// The absolute path of the target directory in the local file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "directoryURL") public let directory: Path /// The absolute path of the target directory in the local file system. @@ -394,12 +402,12 @@ public struct BinaryArtifactTarget: Target { /// The kind of binary artifact. public let kind: Kind - + /// The original source of the binary artifact. public let origin: Origin - + /// The location of the binary artifact in the local file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "artifactURL") public let artifact: Path /// The location of the binary artifact in the local file system. @@ -411,7 +419,7 @@ public struct BinaryArtifactTarget: Target { case xcframework case artifactsArchive } - + // Represents the original location of a binary artifact. public enum Origin: Equatable { /// Represents an artifact that was available locally. @@ -420,7 +428,6 @@ public struct BinaryArtifactTarget: Target { /// Represents an artifact that was downloaded from a remote URL. case remote(url: String) } - } /// Represents a target describing a system library that is expected to be @@ -432,9 +439,9 @@ public struct SystemLibraryTarget: Target { /// The name of the target, as defined in the package manifest. This name /// is unique among the targets of the package in which it is defined. public var name: String - + /// The absolute path of the target directory in the local file system. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "directoryURL") public var directory: Path /// The absolute path of the target directory in the local file system. @@ -451,7 +458,7 @@ public struct SystemLibraryTarget: Target { /// Flags from `pkg-config` to pass to Clang (and to SwiftC via `-Xcc`). public let compilerFlags: [String] - + /// Flags from `pkg-config` to pass to the platform linker. public let linkerFlags: [String] } @@ -466,35 +473,38 @@ public struct FileList { self.files = files } } + extension FileList: Sequence { public struct Iterator: IteratorProtocol { private var files: ArraySlice fileprivate init(files: ArraySlice) { self.files = files } - mutating public func next() -> File? { + + public mutating func next() -> File? { guard let nextInfo = self.files.popFirst() else { return nil } return nextInfo } } + public func makeIterator() -> Iterator { - return Iterator(files: ArraySlice(self.files)) + Iterator(files: ArraySlice(self.files)) } } @available(_PackageDescription, introduced: 5.10) extension FileList: RandomAccessCollection { public var startIndex: Int { 0 } - public var endIndex: Int { files.endIndex } - public subscript(i: Int) -> File { files[i] } + public var endIndex: Int { self.files.endIndex } + public subscript(i: Int) -> File { self.files[i] } } /// Provides information about a single file in a FileList. public struct File { /// The path of the file. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, renamed: "url") public let path: Path /// The path of the file. diff --git a/Sources/PackagePlugin/Path.swift b/Sources/PackagePlugin/Path.swift index 19a6e3556fe..95fa82d348b 100644 --- a/Sources/PackagePlugin/Path.swift +++ b/Sources/PackagePlugin/Path.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors +// Copyright (c) 2021-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 @@ -18,31 +18,31 @@ public struct Path: Hashable { /// Initializes the path from the contents a string, which should be an /// absolute path in platform representation. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public init(_ string: String) { self._string = string } - internal init(url: URL) { + init(url: URL) { self._string = url.path } /// A string representation of the path. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public var string: String { - return _string + self._string } // Note: this avoids duplication warnings for our own code. - internal var stringValue: String { - return _string + var stringValue: String { + self._string } /// The last path component (including any extension). - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public var lastComponent: String { // Check for a special case of the root directory. - if _string == "/" { + if self._string == "/" { // Root directory, so the basename is a single path separator (the // root directory is special in this regard). return "/" @@ -50,15 +50,15 @@ public struct Path: Hashable { // Find the last path separator. guard let idx = _string.lastIndex(of: "/") else { // No path separators, so the basename is the whole string. - return _string + return self._string } // Otherwise, it's the string from (but not including) the last path // separator. - return String(_string.suffix(from: _string.index(after: idx))) + return String(self._string.suffix(from: self._string.index(after: idx))) } /// The last path component (without any extension). - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public var stem: String { let filename = self.lastComponent if let ext = self.extension { @@ -69,22 +69,22 @@ public struct Path: Hashable { } /// The filename extension, if any (without any leading dot). - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public var `extension`: String? { // Find the last path separator, if any. - let sIdx = _string.lastIndex(of: "/") + let sIdx = self._string.lastIndex(of: "/") // Find the start of the basename. - let bIdx = (sIdx != nil) ? _string.index(after: sIdx!) : _string.startIndex + let bIdx = (sIdx != nil) ? self._string.index(after: sIdx!) : self._string.startIndex // Find the last `.` (if any), starting from the second character of // the basename (a leading `.` does not make the whole path component // a suffix). - let fIdx = _string.index(bIdx, offsetBy: 1, limitedBy: _string.endIndex) ?? _string.startIndex + let fIdx = self._string.index(bIdx, offsetBy: 1, limitedBy: self._string.endIndex) ?? self._string.startIndex if let idx = _string[fIdx...].lastIndex(of: ".") { // Unless it's just a `.` at the end, we have found a suffix. - if _string.distance(from: idx, to: _string.endIndex) > 1 { - return String(_string.suffix(from: _string.index(idx, offsetBy: 1))) + if self._string.distance(from: idx, to: self._string.endIndex) > 1 { + return String(self._string.suffix(from: self._string.index(idx, offsetBy: 1))) } } // If we get this far, there is no suffix. @@ -92,7 +92,7 @@ public struct Path: Hashable { } /// The path except for the last path component. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public func removingLastComponent() -> Path { // Find the last path separator. guard let idx = string.lastIndex(of: "/") else { @@ -100,52 +100,50 @@ public struct Path: Hashable { return Path(".") } // Check if it's the only one in the string. - if idx == string.startIndex { + if idx == self.string.startIndex { // Just one path separator, so the directory name is `/`. return Path("/") } // Otherwise, it's the string up to (but not including) the last path // separator. - return Path(String(_string.prefix(upTo: idx))) + return Path(String(self._string.prefix(upTo: idx))) } - + /// The result of appending a subpath, which should be a relative path in /// platform representation. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public func appending(subpath: String) -> Path { - return Path(_string + (_string.hasSuffix("/") ? "" : "/") + subpath) + Path(self._string + (self._string.hasSuffix("/") ? "" : "/") + subpath) } /// The result of appending one or more path components. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public func appending(_ components: [String]) -> Path { - return self.appending(subpath: components.joined(separator: "/")) + self.appending(subpath: components.joined(separator: "/")) } /// The result of appending one or more path components. - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public func appending(_ components: String...) -> Path { - return self.appending(components) + self.appending(components) } } extension Path: CustomStringConvertible { - - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public var description: String { - return self.string + self.string } } extension Path: Codable { - - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(self.string) } - @available(_PackageDescription, deprecated: 6.0) + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let string = try container.decode(String.self) @@ -153,10 +151,9 @@ extension Path: Codable { } } -public extension String.StringInterpolation { - - @available(_PackageDescription, deprecated: 6.0) - mutating func appendInterpolation(_ path: Path) { +extension String.StringInterpolation { + @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") + public mutating func appendInterpolation(_ path: Path) { self.appendInterpolation(path.string) } }