From 2bf0c012c30488880563c7c7327aa4f15dacb277 Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Thu, 20 Mar 2025 14:31:09 +0000 Subject: [PATCH 1/9] Add a documentation catalog and top-level organization to PackagePlugin. --- .../PackagePlugin.docc/Info.plist | 26 ++ .../PackagePlugin.docc/PackagePlugin.md | 223 ++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 Sources/PackagePlugin/PackagePlugin.docc/Info.plist create mode 100644 Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md diff --git a/Sources/PackagePlugin/PackagePlugin.docc/Info.plist b/Sources/PackagePlugin/PackagePlugin.docc/Info.plist new file mode 100644 index 00000000000..1d479ae109f --- /dev/null +++ b/Sources/PackagePlugin/PackagePlugin.docc/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleName + PackagePlugin + CFBundleDisplayName + PackagePlugin + CFBundleIdentifier + org.swift.swiftpm.packageplugin + CFBundleDevelopmentRegion + en + CFBundleIconFile + DocumentationIcon + CFBundleIconName + DocumentationIcon + CFBundlePackageType + DOCS + CFBundleShortVersionString + 0.1.0 + CDDefaultCodeListingLanguage + swift + CFBundleVersion + 0.1.0 + + diff --git a/Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md b/Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md new file mode 100644 index 00000000000..b4e53cc7bb9 --- /dev/null +++ b/Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md @@ -0,0 +1,223 @@ +# ``PackagePlugin`` + +Create custom build steps and command-line actions for your Swift package. + +## Overview + +Use `PackagePlugin` to create plugins that extend Swift package manager's behavior in one of two ways: + +* term Build-tool plugins: Create a command that Swift package manager runs either before or during a target's build process. +* term Command plugins: Create a command that someone runs by passing its name as an argument to the `swift package` command-line tool. + +Define your plugins as targets in your `Package.swift` file. +To make a build-tool plugin available for other packages to use, define a product that exports the plugin. + +### Create a build-tool plugin + +Add a build-tool plugin target to your package by creating a `.plugin` target with the `buildTool()` capability in your package description. +List any command-line tools the plugin uses as dependencies of the plugin target, and their packages as dependencies of your package. +For example: + +```swift +// swift-tools-version: 5.6 +import PackageDescription + +let package = Package( + name: "MyPluginPackage", + dependencies: [ + .package( + url: "https://github.com/example/sometool", + from: "0.1.0" + ) + ], + targets: [ + .plugin( + name: "MyBuildToolPlugin", + capability: .buildTool(), + dependencies: [ + .product(name: "SomeTool", package: "sometool"), + ] + ) + ] +) + +``` + +Create a `Plugins` folder in your Swift package, and a sub-folder with the same name as your build-tool plugin. +Inside that sub-folder, create a Swift file that contains your plugin source. +Your plugin needs to conform to ``BuildToolPlugin``. + +Your implementation of ``BuildToolPlugin/createBuildCommands(context:target:)`` returns either a ``Command/buildCommand(displayName:executable:arguments:environment:inputFiles:outputFiles:)-enum.case`` or ``Command/prebuildCommand(displayName:executable:arguments:environment:outputFilesDirectory:)-enum.case``, depending on where in the build process your plugin's command runs: + + - Return ``Command/buildCommand(displayName:executable:arguments:environment:inputFiles:outputFiles:)-enum.case`` if your plugin depends on one or more input files in the target's source (including files that the build process generates), and creates one or more output files that you know the paths to. + Swift package manager adds your plugin's command to the dependency graph at a point where all of its inputs are available. +- Return ``Command/prebuildCommand(displayName:executable:arguments:environment:outputFilesDirectory:)-enum.case`` if your plugin creates a collection of output files with names that you don't know until after the command runs. + Swift package manager runs your plugin's command every time it builds the target, before it calculates the target's dependency graph. + +Use the ``PluginContext`` Swift package manager passes to your plugin to get information about the target Swift package manager is building, and to find the paths to commands your plugin uses. + +### Use a build-tool plugin + +In your target that uses a build-tool plugin as part of its build process, add the `plugins:` argument to the target's definition in your package description. +Each entry in the list is a `.plugin(name:package:)` that specifies the plugin's name, and the package that provides the plugin. +For example: + +```swift +// swift-tools-version: 5.6 +import PackageDescription + +let package = Package( + name: "my-plugin-using-example", + dependencies: [ + .package(url: "https://github.com/example/my-plugin-package.git", from: "1.0"), + ], + targets: [ + .executableTarget( + name: "MyExample", + plugins: [ + .plugin(name: "MyBuildToolPlugin", package: "my-plugin-package"), + ] + ) + ] +) +``` + +### Create a command plugin + +Add a command plugin to your package by creating a `.plugin` target with the `command()` capability in your package description. +The capability describes the intent of your command plugin, and the permissions it needs to work. +List any commands your plugin uses as the target's dependencies. +For example: + +```swift +// swift-tools-version: 5.6 +import PackageDescription + +let package = Package( + name: "MyPluginPackage", + dependencies: [ + .package( + url: "https://github.com/example/sometool", + from: "0.1.0" + ) + ], + targets: [ + .plugin( + name: "MyCommandPlugin", + capability: .command( + intent: .sourceCodeFormatting(), + permissions: [ + .writeToPackageDirectory(reason: "This command reformats source files") + ] + ), + dependencies: [ + .product(name: "SomeTool", package: "sometool"), + ] + ) + ] +) +``` +Create a `Plugins` folder in your Swift package, and a sub-folder with the same name as your build-tool plugin. +Inside that sub-folder, create a Swift file that contains your plugin source. +Your plugin needs to conform to ``CommandPlugin``. + +Your implementation of ``CommandPlugin/performCommand(context:arguments:)`` runs the command and prints any output. +Use methods on ``Diagnostics`` to report errors, warnings, progress, and other information to the person who runs your command plugin. +Use ``ArgumentExtractor`` to parse arguments someone supplies to your command. + +Use the ``PluginContext`` Swift package manager passes to your plugin to find paths to commands your plugin uses. +Command plugins don't have target information in their `PluginContext` structure, because Swift package manager isn't building a target when it runs your command plugin. + +### Use a command plugin + +To run a command plugin, pass its name and any arguments it needs as arguments to the `swift package` command, for example: + +```sh +% swift package my-plugin --example-flag parameter +``` + +### Share a plugin with other packages + +Make your plugin available to developers to use in other packages by declaring a `.plugin` product in your package description, that has your plugin target in its targets list. +For example: + +```swift +// swift-tools-version: 5.6 +import PackageDescription + +let package = Package( + name: "MyPluginPackage", + products: [ + .plugin( + name: "MyBuildToolPlugin", + targets: [ + "MyBuildToolPlugin" + ] + ) + ], + // Define the plugin. +) +``` + +## Topics + +### Build-tool plugins + +- ``BuildToolPlugin`` +- ``Command`` +- ``Target`` + +### Command plugins + +- ``CommandPlugin`` +- ``ArgumentExtractor`` + +### Contextual information + +- ``PluginContext`` +- ``PackageManager`` +- ``ToolsVersion`` + +### Packages + +- ``Package`` +- ``PackageOrigin`` + +### Package products + +- ``Product`` +- ``ExecutableProduct`` +- ``LibraryProduct`` + +### Targets and modules + +- ``BinaryArtifactTarget`` +- ``SourceModuleTarget`` +- ``ClangSourceModuleTarget`` +- ``SwiftSourceModuleTarget`` +- ``SystemLibraryTarget`` +- ``ModuleKind`` + +### Files and paths + +- ``FileList`` +- ``File`` +- ``FileType`` +- ``PathList`` +- ``Path`` + +### Dependencies + +- ``PackageDependency`` +- ``TargetDependency`` + +### Errors and feedback + +- ``Diagnostics`` +- ``PackageManagerProxyError`` +- ``PluginContextError`` +- ``PluginDeserializationError`` + +### Types that support plugins + +- ``Plugin`` From 7e748158b5b8f5d62411267314aa48ccbc4c7a7f Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Fri, 21 Mar 2025 14:30:30 +0000 Subject: [PATCH 2/9] Suggestions in PR review. --- Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md b/Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md index b4e53cc7bb9..9f8847d59ad 100644 --- a/Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md +++ b/Sources/PackagePlugin/PackagePlugin.docc/PackagePlugin.md @@ -6,8 +6,8 @@ Create custom build steps and command-line actions for your Swift package. Use `PackagePlugin` to create plugins that extend Swift package manager's behavior in one of two ways: -* term Build-tool plugins: Create a command that Swift package manager runs either before or during a target's build process. -* term Command plugins: Create a command that someone runs by passing its name as an argument to the `swift package` command-line tool. +* term Build-tool plugins: Create a command that Swift package manager runs either as a pre-build step before it performs a build action, or as a specific step in a target's build process. +* term Command plugins: Create a command that someone runs either by passing its name as an argument to the `swift package` command-line tool, or from UI their developer environment. Define your plugins as targets in your `Package.swift` file. To make a build-tool plugin available for other packages to use, define a product that exports the plugin. From 88edf101982f465fb7ad6f4ad76440d801290c71 Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Fri, 21 Mar 2025 14:49:33 +0000 Subject: [PATCH 3/9] Reformat the documentation on BuildToolPlugin and CommandPlugin. --- Sources/PackagePlugin/Protocols.swift | 40 +++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/Sources/PackagePlugin/Protocols.swift b/Sources/PackagePlugin/Protocols.swift index 3e3fd35fb05..e1346850fc5 100644 --- a/Sources/PackagePlugin/Protocols.swift +++ b/Sources/PackagePlugin/Protocols.swift @@ -25,42 +25,46 @@ public protocol Plugin { init() } -/// Defines functionality for all plugins having a `buildTool` capability. +/// A protocol you implement to define a build-tool plugin. public protocol BuildToolPlugin: Plugin { - /// Invoked by SwiftPM to create build commands for a particular target. - /// The context parameter contains information about the package and its - /// dependencies, as well as other environmental inputs. + /// Creates build commands for the given target. /// - /// This function should create and return build commands or prebuild - /// commands, configured based on the information in the context. Note - /// that it does not directly run those commands. + /// - Parameters: + /// - context: Information about the package and its + /// dependencies, as well as other environmental inputs. + /// - target: The build target for which the package manager invokes the plugin. + /// - Returns: A list of commands that the system runs before it performs the build action (for ``Command/prebuildCommand(displayName:executable:arguments:environment:outputFilesDirectory:)-enum.case``), + /// or as specific steps during the build (for ``Command/buildCommand(displayName:executable:arguments:environment:inputFiles:outputFiles:)-enum.case``). + /// + /// You don't run commands directly in your implementation of this method. Instead, create and return ``Command`` instances. + /// The system runs pre-build commands before it performs the build action, and adds build commands to the dependency tree for the build + /// based on which steps create the command's inputs, and which steps depend on the command's outputs. func createBuildCommands( context: PluginContext, target: Target ) async throws -> [Command] } -/// Defines functionality for all plugins that have a `command` capability. +/// A protocol you implement to define a command plugin. public protocol CommandPlugin: Plugin { - /// Invoked by SwiftPM to perform the custom actions of the command. + /// Performs the command's custom actions. + /// + /// - Parameters: + /// - context: Information about the package and other environmental inputs. + /// - arguments: Literal arguments that someone passed in the command invocation, after the command verb. func performCommand( - /// The context in which the plugin is invoked. This is the same for all - /// kinds of plugins, and provides access to the package graph, to cache - /// directories, etc. context: PluginContext, - - /// Any literal arguments passed after the verb in the command invocation. arguments: [String] ) async throws - /// A proxy to the Swift Package Manager or IDE hosting the command plugin, - /// through which the plugin can ask for specialized information or actions. + /// An object that represents the Swift Package Manager or IDE hosting the command plugin. + /// + /// Use this object to discover specialized information about the plugin host, or actions your plugin can invoke. var packageManager: PackageManager { get } } extension CommandPlugin { - /// A proxy to the Swift Package Manager or IDE hosting the command plugin, - /// through which the plugin can ask for specialized information or actions. + /// An object that represents the Swift Package Manager or IDE hosting the command plugin. public var packageManager: PackageManager { return PackageManager() } From d410667cce3d70e8474beef27dc15c19632f3f53 Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Mon, 31 Mar 2025 15:42:19 +0100 Subject: [PATCH 4/9] Reformat the documentation in ArgumentExtractor. --- Sources/PackagePlugin/ArgumentExtractor.swift | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/Sources/PackagePlugin/ArgumentExtractor.swift b/Sources/PackagePlugin/ArgumentExtractor.swift index 4b39c9eba6b..746e73892d2 100644 --- a/Sources/PackagePlugin/ArgumentExtractor.swift +++ b/Sources/PackagePlugin/ArgumentExtractor.swift @@ -10,12 +10,22 @@ // //===----------------------------------------------------------------------===// -/// A rudimentary helper for extracting options and flags from a string list representing command line arguments. The idea is to extract all known options and flags, leaving just the positional arguments. This does not handle well the case in which positional arguments (or option argument values) happen to have the same name as an option or a flag. It only handles the long `--` form of options, but it does respect `--` as an indication that all remaining arguments are positional. +/// A structure that extracts options and flags from a string list representing command-line arguments. +/// +/// `ArgumentExtractor` leaves positional arguments, and extracts option arguments and flags. +/// It supports long-form option names with two hyphens (for example, `--verbose`), and treats `--` as an indicator that all remaining arguments are positional. +/// +/// > Warning: +/// > `ArgumentExtractor` doesn't detect situations in which positional arguments or optional parameters have the same name as a long option argument. public struct ArgumentExtractor { private var args: [String] private let literals: [String] - /// Initializes a ArgumentExtractor with a list of strings from which to extract flags and options. If the list contains `--`, any arguments that follow it are considered to be literals. + /// Initializes an argument with a list of strings from which to extract flags and options. + /// + /// If the list contains `--`, `ArgumentExtractor` treats any arguments that follow it as positional arguments. + /// + /// - Parameter arguments: The list of command-line arguments. public init(_ arguments: [String]) { // Split the array on the first `--`, if there is one. Everything after that is a literal. let parts = arguments.split(separator: "--", maxSplits: 1, omittingEmptySubsequences: false) @@ -23,7 +33,18 @@ public struct ArgumentExtractor { self.literals = Array(parts.count == 2 ? parts[1] : []) } - /// Extracts options of the form `-- ` or `--=` from the remaining arguments, and returns the extracted values. + /// Extracts the value of a named argument from the list of remaining arguments. + /// + /// A named argument has one of these two forms: + /// * `--=` + /// * `-- ` + /// + /// If this method detects an argument that matches the supplied name, it removes the argument and its value from the list of arguments and returns the value. + /// The same name can appear in the list of arguments multiple times, and this method returns a list of all matching values. + /// + /// - Parameters: + /// - name: The option name to extract the value for. + /// - Returns: An array of values for the named option. public mutating func extractOption(named name: String) -> [String] { var values: [String] = [] var idx = 0 @@ -49,7 +70,10 @@ public struct ArgumentExtractor { return values } - /// Extracts flags of the form `--` from the remaining arguments, and returns the count. + /// Extracts options with the given name from the remaining arguments. + /// + /// - Parameter name: The option to search for. The method prefixes it with two hyphens. For example, pass `verbose` to extract the `--verbose` option. + /// - Returns: The number of matching options in the list of arguments. public mutating func extractFlag(named name: String) -> Int { var count = 0 var idx = 0 @@ -66,12 +90,16 @@ public struct ArgumentExtractor { return count } - /// Returns any unextracted flags or options (based strictly on whether remaining arguments have a "--" prefix). + /// A list of unextracted flags or options. + /// + /// A flag or option is any argument that has the prefix `--` (two hyphens). public var unextractedOptionsOrFlags: [String] { return args.filter{ $0.hasPrefix("--") } } - /// Returns all remaining arguments, including any literals after the first `--` if there is one. + /// A list of all remaining arguments. + /// + /// If the arguments list contains the string `--`, then all arguments after it are included in this list even if they would otherwise match named flags or options. public var remainingArguments: [String] { return args + literals } From d5760f3304d80ec19b827ce066b6910883608cbf Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Mon, 31 Mar 2025 16:45:36 +0100 Subject: [PATCH 5/9] Reformat documentation in Command enum --- Sources/PackagePlugin/Command.swift | 195 ++++++++++++++-------------- 1 file changed, 96 insertions(+), 99 deletions(-) diff --git a/Sources/PackagePlugin/Command.swift b/Sources/PackagePlugin/Command.swift index 3dd5e50b37d..fed124b6b7b 100644 --- a/Sources/PackagePlugin/Command.swift +++ b/Sources/PackagePlugin/Command.swift @@ -12,35 +12,38 @@ import Foundation -/// A command to run during the build, including executable, command lines, -/// environment variables, initial working directory, etc. All paths should be -/// based on the ones passed to the plugin in the target build context. +/// A command to run during a build. +/// +/// A `Command` represents all of the parameters of the build comment, +/// including the executable, command-line arguments, +/// environment variables, initial working directory, and input and output files. +/// +/// The system interprets relative paths starting from the path 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. + /// Returns a command that the system runs when a build needs updated versions of any of its output files. /// /// An output file is out-of-date if it doesn't exist, or if any input files - /// have changed since the command was last run. + /// are newer than the output file. /// - /// - Note: the paths in the list of output files may depend on the list of - /// input file paths, but **must not** depend on reading the contents of - /// any input files. Such cases must be handled using a `prebuildCommand`. + /// - Note: The paths in the list of output files can depend on the paths in the list of input files, + /// but not on the content of input files. To create a command that generates output files based + /// on the content of its input files, use ``prebuildCommand(displayName:executable:arguments:environment:outputFilesDirectory:)-enum.case``. /// /// - parameters: /// - displayName: An optional string to show in build logs and other /// status areas. - /// - executable: The absolute path to the executable to be invoked. - /// - arguments: Command-line arguments to be passed to the executable. + /// - executable: The absolute path to the command's executable. + /// - arguments: Command-line arguments the system passes to the executable. /// - environment: Environment variable assignments visible to the /// executable. /// - inputFiles: Files on which the contents of output files may depend. - /// Any paths passed as `arguments` should typically be passed here as - /// well. - /// - outputFiles: Files to be generated or updated by the executable. - /// Any files recognizable by their extension as source files - /// (e.g. `.swift`) are compiled into the target for which this command - /// was generated as if in its source directory; other files are treated - /// as resources as if explicitly listed in `Package.swift` using + /// You should pass any paths you pass in `arguments` as input files. + /// - outputFiles: Files the build command generates or updates. + /// Any files the system recognizes by their extension as source files + /// (for example, `.swift`) are compiled into the target for which this command + /// is generated as if they are in the target's source directory; the system + /// treats other files as resources as if they are explicitly listed in + /// `Package.swift` using /// `.process(...)`. @available(_PackageDescription, introduced: 6.0) case buildCommand( @@ -52,28 +55,28 @@ public enum Command { outputFiles: [URL] = [] ) - /// Returns a command that runs unconditionally before every build. + /// Returns a command that the build system runs unconditionally before every build. /// - /// Prebuild commands can have a significant performance impact - /// and should only be used when there would be no way to know the + /// Prebuild commands can have a significant performance impact, + /// use them only when there's no way to know the /// list of output file paths without first reading the contents - /// of one or more input files. Typically there is no way to - /// determine this list without first running the command, so - /// instead of encoding that list, the caller supplies an - /// `outputFilesDirectory` parameter, and all files in that - /// directory after the command runs are treated as output files. + /// of one or more input files. + /// + /// Use the `outputFilesDirectory` parameter to tell the build system where the + /// command creates or updates output files. The system treats all files in that + /// directory after the command runs as output files. /// /// - parameters: /// - displayName: An optional string to show in build logs and other /// status areas. - /// - executable: The absolute path to the executable to be invoked. - /// - arguments: Command-line arguments to be passed to the executable. + /// - executable: The absolute path to the command's executable. + /// - arguments: Command-line arguments the system passes to the executable. /// - environment: Environment variable assignments visible to the executable. /// - outputFilesDirectory: A directory into which the command writes its - /// output files. Any files there recognizable by their extension as - /// source files (e.g. `.swift`) are compiled into the target for which - /// this command was generated as if in its source directory; other - /// files are treated as resources as if explicitly listed in + /// output files. Any files in that directory that the system recognizes by their + /// extension as source files (for example, `.swift`) are compiled into the target + /// for which the system generated this command, as if they are in its source + /// directory; the system treats other files as resources as if explicitly listed in /// `Package.swift` using `.process(...)`. @available(_PackageDescription, introduced: 6.0) case prebuildCommand( @@ -86,31 +89,30 @@ public enum Command { } extension Command { - /// Returns a command that runs when any of its output files are needed by - /// the build, but out-of-date. + /// Returns a command that the system runs when the build needs updated versions of any of its output files. /// - /// An output file is out-of-date if it doesn't exist, or if any input files - /// have changed since the command was last run. + /// An output file is out of date if it doesn't exist, or if any input files + /// are newer than the output file. /// - /// - Note: the paths in the list of output files may depend on the list of - /// input file paths, but **must not** depend on reading the contents of - /// any input files. Such cases must be handled using a `prebuildCommand`. + /// - Note: The paths in the list of output files can depend on the paths in the list of input files, + /// but not on the content of input files. To create a command that generates output files based + /// on the content of its input files, use ``prebuildCommand(displayName:executable:arguments:environment:outputFilesDirectory:)-enum.case``. /// /// - parameters: /// - displayName: An optional string to show in build logs and other /// status areas. - /// - executable: The absolute path to the executable to be invoked. - /// - arguments: Command-line arguments to be passed to the executable. + /// - executable: The absolute path to the command's executable. + /// - arguments: Command-line arguments the system passes to the executable. /// - environment: Environment variable assignments visible to the /// executable. /// - inputFiles: Files on which the contents of output files may depend. - /// Any paths passed as `arguments` should typically be passed here as - /// well. - /// - outputFiles: Files to be generated or updated by the executable. - /// Any files recognizable by their extension as source files - /// (e.g. `.swift`) are compiled into the target for which this command - /// was generated as if in its source directory; other files are treated - /// as resources as if explicitly listed in `Package.swift` using + /// You should pass any paths you pass in `arguments` as input files. + /// - outputFiles: Files the build command generates or updates. + /// Any files the system recognizes by their extension as source files + /// (for example, `.swift`) are compiled into the target for which this command + /// is generated as if they are in the target's source directory; the system + /// treats other files as resources as if they are explicitly listed in + /// `Package.swift` using /// `.process(...)`. @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public static func buildCommand( @@ -131,31 +133,30 @@ extension Command { ) } - /// Returns a command that runs when any of its output files are needed - /// by the build, but out-of-date. + /// Returns a command that the system runs when the build needs updated versions of any of its output files. /// - /// An output file is out-of-date if it doesn't exist, or if any input - /// files have changed since the command was last run. + /// An output file is out of date if it doesn't exist, or if any input files + /// are newer than the output file. /// - /// - Note: the paths in the list of output files may depend on the list - /// of input file paths, but **must not** depend on reading the contents - /// of any input files. Such cases must be handled using a `prebuildCommand`. + /// - Note: The paths in the list of output files can depend on the paths in the list of input files, + /// but not on the content of input files. To create a command that generates output files based + /// on the content of its input files, use ``prebuildCommand(displayName:executable:arguments:environment:outputFilesDirectory:)-enum.case``. /// /// - parameters: /// - displayName: An optional string to show in build logs and other /// status areas. - /// - executable: The absolute path to the executable to be invoked. - /// - arguments: Command-line arguments to be passed to the executable. - /// - environment: Environment variable assignments visible to the executable. - /// - workingDirectory: Optional initial working directory when the executable - /// runs. + /// - executable: The absolute path to the command's executable. + /// - arguments: Command-line arguments the system passes to the executable. + /// - environment: Environment variable assignments visible to the + /// executable. /// - inputFiles: Files on which the contents of output files may depend. - /// Any paths passed as `arguments` should typically be passed here as well. - /// - outputFiles: Files to be generated or updated by the executable. - /// Any files recognizable by their extension as source files - /// (e.g. `.swift`) are compiled into the target for which this command - /// was generated as if in its source directory; other files are treated - /// as resources as if explicitly listed in `Package.swift` using + /// You should pass any paths you pass in `arguments` as input files. + /// - outputFiles: Files the build command generates or updates. + /// Any files the system recognizes by their extension as source files + /// (for example, `.swift`) are compiled into the target for which this command + /// is generated as if they are in the target's source directory; the system + /// treats other files as resources as if they are explicitly listed in + /// `Package.swift` using /// `.process(...)`. @available(*, unavailable, message: "specifying the initial working directory for a command is not yet supported") public static func buildCommand( @@ -177,30 +178,28 @@ extension Command { ) } - /// Returns a command that runs unconditionally before every build. + /// Returns a command that the build system runs unconditionally before every build. /// - /// Prebuild commands can have a significant performance impact - /// and should only be used when there would be no way to know the + /// Prebuild commands can have a significant performance impact, + /// use them only when there's no way to know the /// list of output file paths without first reading the contents - /// of one or more input files. Typically there is no way to - /// determine this list without first running the command, so - /// instead of encoding that list, the caller supplies an - /// `outputFilesDirectory` parameter, and all files in that - /// directory after the command runs are treated as output files. + /// of one or more input files. + /// + /// Use the `outputFilesDirectory` parameter to tell the build system where the + /// command creates or updates output files. The system treats all files in that + /// directory after the command runs as output files. /// /// - parameters: /// - displayName: An optional string to show in build logs and other /// status areas. - /// - executable: The absolute path to the executable to be invoked. - /// - arguments: Command-line arguments to be passed to the executable. + /// - executable: The absolute path to the command's executable. + /// - arguments: Command-line arguments the system passes to the executable. /// - environment: Environment variable assignments visible to the executable. - /// - workingDirectory: Optional initial working directory when the executable - /// runs. /// - outputFilesDirectory: A directory into which the command writes its - /// output files. Any files there recognizable by their extension as - /// source files (e.g. `.swift`) are compiled into the target for which - /// this command was generated as if in its source directory; other - /// files are treated as resources as if explicitly listed in + /// output files. Any files in that directory that the system recognizes by their + /// extension as source files (for example, `.swift`) are compiled into the target + /// for which the system generated this command, as if they are in its source + /// directory; the system treats other files as resources as if explicitly listed in /// `Package.swift` using `.process(...)`. @available(_PackageDescription, deprecated: 6.0, message: "Use `URL` type instead of `Path`.") public static func prebuildCommand( @@ -219,30 +218,28 @@ extension Command { ) } - /// Returns a command that runs unconditionally before every build. + /// Returns a command that the build system runs unconditionally before every build. + /// + /// Prebuild commands can have a significant performance impact, + /// use them only when there's no way to know the + /// list of output file paths without first reading the contents + /// of one or more input files. /// - /// Because prebuild commands are run on every build, they can have a - /// significant performance impact and should only be used when there - /// would be no way to know the list of output file paths without first - /// reading the contents of one or more input files. Typically there is - /// no way to determine this list without first running the command, so - /// instead of encoding that list, the caller supplies an - /// `outputFilesDirectory` parameter, and all files in that directory - /// after the command runs are treated as output files. + /// Use the `outputFilesDirectory` parameter to tell the build system where the + /// command creates or updates output files. The system treats all files in that + /// directory after the command runs as output files. /// /// - parameters: /// - displayName: An optional string to show in build logs and other /// status areas. - /// - executable: The absolute path to the executable to be invoked. - /// - arguments: Command-line arguments to be passed to the executable. + /// - executable: The absolute path to the command's executable. + /// - arguments: Command-line arguments the system passes to the executable. /// - environment: Environment variable assignments visible to the executable. - /// - workingDirectory: Optional initial working directory when the executable - /// runs. /// - outputFilesDirectory: A directory into which the command writes its - /// output files. Any files there recognizable by their extension as - /// source files (e.g. `.swift`) are compiled into the target for which - /// this command was generated as if in its source directory; other - /// files are treated as resources as if explicitly listed in + /// output files. Any files in that directory that the system recognizes by their + /// extension as source files (for example, `.swift`) are compiled into the target + /// for which the system generated this command, as if they are in its source + /// directory; the system treats other files 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") public static func prebuildCommand( From f80ac56176d00e0720c541e086de197c4c7acc4a Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Tue, 1 Apr 2025 11:40:17 +0100 Subject: [PATCH 6/9] Clean up documentation in PluginContext. --- Sources/PackagePlugin/Context.swift | 81 +++++++++++++++++------------ 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/Sources/PackagePlugin/Context.swift b/Sources/PackagePlugin/Context.swift index 1dc25a56ef7..f5899c878fc 100644 --- a/Sources/PackagePlugin/Context.swift +++ b/Sources/PackagePlugin/Context.swift @@ -12,47 +12,60 @@ import Foundation -/// Provides information about the package for which the plugin is invoked, -/// as well as contextual information based on the plugin's stated intent -/// and requirements. +/// Provides information about the package for which the plugin is invoked. +/// +/// The plugin context includes metadata about the package, and information about the +/// build environment in which the plugin runs. public struct PluginContext { - /// Information about the package to which the plugin is being applied. + /// Information about the package to which the plugin is applied. public let package: Package - /// The path of a writable directory into which the plugin or the build - /// commands it constructs can write anything it wants. This could include - /// any generated source files that should be processed further, and it - /// could include any caches used by the build tool or the plugin itself. - /// The plugin is in complete control of what is written under this di- - /// rectory, and the contents are preserved between builds. + /// The path to a directory into which the plugin or its build + /// commands can write data. /// - /// A plugin would usually create a separate subdirectory of this directory - /// for each command it creates, and the command would be configured to - /// 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. + /// @DeprecationSummary{Use ``pluginWorkDirectoryURL`` instead.} + /// + /// The plugin and its build commands use the work directory to + /// store any generated source files that the build system processes further, + /// and for cache files that the plugin and its build commands use. + /// The plugin is in complete control of what is written under this directory, + /// and the system preserves its contents between builds. + /// + /// A common pattern is for a plugin to create a separate subdirectory of this + /// directory for each build command it creates, and configure the build + /// command to write its outputs to that subdirectory. The plugin may also + /// create other directories for cache files and other file system content that either + /// it or its build commands need. @available(_PackageDescription, deprecated: 6.0, renamed: "pluginWorkDirectoryURL") public let pluginWorkDirectory: Path - /// The path of a writable directory into which the plugin or the build - /// commands it constructs can write anything it wants. This could include - /// any generated source files that should be processed further, and it - /// could include any caches used by the build tool or the plugin itself. - /// The plugin is in complete control of what is written under this di- - /// rectory, and the contents are preserved between builds. + /// The URL that locates a directory into which the plugin or its build + /// commands can write data. + /// + /// @DeprecationSummary{Use ``pluginWorkDirectoryURL`` instead.} /// - /// A plugin would usually create a separate subdirectory of this directory - /// for each command it creates, and the command would be configured to - /// 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. + /// The plugin and its build commands use the work directory to + /// store any generated source files that the build system processes further, + /// and for cache files that the plugin and its build commands use. + /// The plugin is in complete control of what is written under this directory, + /// and the system preserves its contents between builds. + /// + /// A common pattern is for a plugin to create a separate subdirectory of this + /// directory for each build command it creates, and configure the build + /// command to write its outputs to that subdirectory. The plugin may also + /// create other directories for cache files and other file system content that either + /// it or its build commands need. @available(_PackageDescription, introduced: 6.0) public let pluginWorkDirectoryURL: URL - /// Looks up and returns the path of a named command line executable tool. - /// The executable must be provided by an executable target or a binary + /// Finds a named command-line tool. + /// + /// The tool's executable must be provided by an executable target or a binary /// target on which the package plugin target depends. This function throws - /// an error if the tool cannot be found. The lookup is case sensitive. + /// an error if the system can't find the tool. + /// + /// - Parameter name: The case-sensitive name of the tool to find. + /// - Returns An object that represents the command-line tool. public func tool(named name: String) throws -> Tool { if let tool = self.accessibleTools[name] { // For PluginAccessibleTool.builtTool, the triples value is not saved, thus @@ -97,14 +110,18 @@ public struct PluginContext { /// Information about a particular tool that is available to a plugin. public struct Tool { - /// Name of the tool (suitable for display purposes). + /// The tool's name. + /// + /// This property is suitable for display in a UI. public let name: String - /// Full path of the built or provided tool in the file system. + /// The full path to the tool in the file system. + /// + /// @DeprecationSummary{Use ``url`` instead.} @available(_PackageDescription, deprecated: 6.0, renamed: "url") public let path: Path - /// Full path of the built or provided tool in the file system. + /// A URL that locates the tool in the file system. @available(_PackageDescription, introduced: 6.0) public let url: URL From b7082febb4ea27956a528e1545232f63671b69e4 Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Tue, 1 Apr 2025 11:48:11 +0100 Subject: [PATCH 7/9] Clean up documentation in Diagnostics. --- Sources/PackagePlugin/Diagnostics.swift | 43 +++++++++++++++++++++---- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/Sources/PackagePlugin/Diagnostics.swift b/Sources/PackagePlugin/Diagnostics.swift index 0d05eff2f92..76b891fb0b8 100644 --- a/Sources/PackagePlugin/Diagnostics.swift +++ b/Sources/PackagePlugin/Diagnostics.swift @@ -10,17 +10,29 @@ // //===----------------------------------------------------------------------===// -/// Emits errors, warnings, and remarks to be shown as a result of running the -/// plugin. After emitting one or more errors, the plugin should return a -/// non-zero exit code. +/// Emits messages the system shows as a result of running the plugin. +/// +/// > Note: If the plugin emits one or more errors, it should return a +/// > non-zero exit code. public struct Diagnostics { - /// Severity of the diagnostic. + /// Severity of the diagnostic message. public enum Severity: String, Encodable { - case error, warning, remark + /// The diagnostic message is an error. + case error + /// The diagnostic message is a warning. + case warning + /// The diagnostic message is a remark. + case remark } - /// Emits an error with a specified severity and message, and optional file path and line number. + /// Emits a message with a specified severity, and optional file path and line number. + /// + /// - Parameters: + /// - severity: The severity of the message. + /// - description: The message to display. + /// - file: The source file to which the message relates. + /// - line: The line number in the source file to which the message relates. public static func emit(_ severity: Severity, _ description: String, file: String? = #file, line: Int? = #line) { let message: PluginToHostMessage switch severity { @@ -36,21 +48,38 @@ public struct Diagnostics { } /// Emits an error with the specified message, and optional file path and line number. + /// + /// - Parameters: + /// - message: The text of the error. + /// - file: The source file to which the error relates. + /// - line: The line number in the source file to which the error relates. public static func error(_ message: String, file: String? = #file, line: Int? = #line) { self.emit(.error, message, file: file, line: line) } /// Emits a warning with the specified message, and optional file path and line number. + /// + /// - Parameters: + /// - message: The text of the warning. + /// - file: The source file to which the warning relates. + /// - line: The line number in the source file to which the warning relates. public static func warning(_ message: String, file: String? = #file, line: Int? = #line) { self.emit(.warning, message, file: file, line: line) } /// Emits a remark with the specified message, and optional file path and line number. + /// + /// - Parameters: + /// - message: The text of the remark. + /// - file: The source file to which the remark relates. + /// - line: The line number in the source file to which the remark relates. public static func remark(_ message: String, file: String? = #file, line: Int? = #line) { self.emit(.remark, message, file: file, line: line) } - /// Emits a progress message + /// Emits a progress message. + /// + /// - Parameter message: The text of the progress update. public static func progress(_ message: String) { try? pluginHostConnection.sendMessage(.emitProgress(message: message)) } From d6b31c20f4518f93dcca03030290250481ab6b18 Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Tue, 1 Apr 2025 12:17:10 +0100 Subject: [PATCH 8/9] Clean up documentation on plugin errors. --- Sources/PackagePlugin/Errors.swift | 34 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/Sources/PackagePlugin/Errors.swift b/Sources/PackagePlugin/Errors.swift index 2d7a08c21f5..0faa65d54fb 100644 --- a/Sources/PackagePlugin/Errors.swift +++ b/Sources/PackagePlugin/Errors.swift @@ -10,18 +10,21 @@ // //===----------------------------------------------------------------------===// +/// Errors the system can encounter discovering a plugin's context. public enum PluginContextError: Error { - /// Could not find a tool with the given name. This could be either because - /// it doesn't exist, or because the plugin doesn't have a dependency on it. + /// The system couldn't find a tool with the given name. + /// + /// This error can occur because the tool doesn't exist, + /// or because the plugin doesn't have a dependency on it. case toolNotFound(name: String) - /// Tool is not supported on the target platform + /// The tool isn't supported on the target platform. case toolNotSupportedOnTargetPlatform(name: String) - /// Could not find a target with the given name. + /// The system couldn't find a target with the specified name in the package. case targetNotFound(name: String, package: Package) - /// Could not find a product with the given name. + /// The system couldn't find a product with the specified name in the package. case productNotFound(name: String, package: Package) } @@ -40,16 +43,27 @@ extension PluginContextError: CustomStringConvertible { } } +/// Errors the system can encounter deserializing a plugin. public enum PluginDeserializationError: Error { - /// The input JSON is malformed in some way; the message provides more details. + /// The input JSON is malformed. + /// + /// The associated message provides more details about the problem. case malformedInputJSON(_ message: String) - /// The plugin doesn't support Xcode (it doesn't link against XcodeProjectPlugin). + /// The plugin doesn't support Xcode. + /// + /// To support Xcode, a plugin needs to link against `XcodeProjectPlugin`. case missingXcodeProjectPluginSupport - /// The plugin doesn't conform to an expected specialization of the BuildToolPlugin protocol. + /// The package uses a build-tool plugin that doesn't conform to the correct protocol. + /// + /// To act as a build-tool plugin, the plugin needs to conform to ``BuildToolPlugin``. case missingBuildToolPluginProtocolConformance(protocolName: String) - /// The plugin doesn't conform to an expected specialization of the CommandPlugin protocol. + /// The package uses a command plugin that doesn't conform to the correct protocol. + /// + /// To act as a command plugin, the plugin needs to conform to ``CommandPlugin``. case missingCommandPluginProtocolConformance(protocolName: String) - /// An internal error of some kind; the message provides more details. + /// An internal error occurred. + /// + /// The associated message provides more details about the problem. case internalError(_ message: String) } From c14bfb588e2c74d076741d40d34e4d0b0bf36cfb Mon Sep 17 00:00:00 2001 From: Graham Lee Date: Fri, 11 Apr 2025 11:13:00 +0100 Subject: [PATCH 9/9] Document public symbols in PackageManagerProxy. --- .../PackagePlugin/PackageManagerProxy.swift | 268 ++++++++++++------ 1 file changed, 185 insertions(+), 83 deletions(-) diff --git a/Sources/PackagePlugin/PackageManagerProxy.swift b/Sources/PackagePlugin/PackageManagerProxy.swift index 0119f149695..6b34e760981 100644 --- a/Sources/PackagePlugin/PackageManagerProxy.swift +++ b/Sources/PackagePlugin/PackageManagerProxy.swift @@ -12,20 +12,26 @@ import Foundation -/// Provides specialized information and services from the Swift Package Manager -/// or an IDE that supports Swift Packages. Different plugin hosts implement the -/// functionality in whatever way is appropriate for them, but should preserve -/// the same semantics described here. +/// A structure that provides information and services from the Swift Package Manager +/// or a developer environment that supports Swift Packages. +/// +/// Implement this structure in a plugin host to provide the facilities of your developer +/// environment to the package manager. public struct PackageManager { - /// Performs a build of all or a subset of products and targets in a package. + /// Builds the specified products and targets in a package. /// /// Any errors encountered during the build are reported in the build result, /// as is the log of the build commands that were run. This method throws an - /// error if the input parameters are invalid or in case the build cannot be - /// started. + /// error if the input parameters are invalid or if the package manager can't + /// start the build. /// - /// The SwiftPM CLI or any IDE that supports packages may show the progress - /// of the build as it happens. + /// The SwiftPM CLI or any developer environment that supports packages + /// may show the progress of the build as it happens. + /// + /// - Parameters: + /// - subset: The products and targets to build. + /// - parameters: Parameters that control aspects of the build. + /// - Returns: A build result. public func build( _ subset: BuildSubset, parameters: BuildParameters @@ -38,42 +44,50 @@ public struct PackageManager { } } - /// Specifies a subset of products and targets of a package to build. + /// An enumeration that 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 - /// targets or (if `includingTests` is false) just non-test targets. + /// Build all products and all targets, optionally including test targets. + /// + /// If `includingTests` is `true` then this case represents all targets of all products; + /// otherwise, it represents all non-test targets. case all(includingTests: Bool) - /// Represents the product with the specified name. + /// Build the product with the specified name. case product(String) - /// Represents the target with the specified name. + /// Build the target with the specified name. case target(String) } - /// Parameters and options to apply during a build. + /// Parameters and options for the system to apply during a build. public struct BuildParameters { - /// Whether to build for debug or release. + /// Whether to build the debug or release configuration. public var configuration: BuildConfiguration - /// Controls the amount of detail in the log returned in the build result. + /// The amount of detail to include in the log returned in the build result. public var logging: BuildLogVerbosity - /// Whether to print build logs to the console + /// Whether to print build logs to the console. public var echoLogs: Bool - /// Additional flags to pass to all C compiler invocations. + /// A list of additional flags to pass to all C compiler invocations. public var otherCFlags: [String] = [] - /// Additional flags to pass to all C++ compiler invocations. + /// A list of additional flags to pass to all C++ compiler invocations. public var otherCxxFlags: [String] = [] - /// Additional flags to pass to all Swift compiler invocations. + /// A list of additional flags to pass to all Swift compiler invocations. public var otherSwiftcFlags: [String] = [] - /// Additional flags to pass to all linker invocations. + /// A list of additional flags to pass to all linker invocations. public var otherLinkerFlags: [String] = [] + /// Initializes a build parameters structure. + /// + /// - Parameters: + /// - configuration: Whether to build the debug or release configuration. + /// - logging: The amount of detail to include in the build log. + /// - echoLogs: Whether to display build logs while the build is in progress. public init( configuration: BuildConfiguration = .debug, logging: BuildLogVerbosity = .concise, @@ -85,62 +99,92 @@ public struct PackageManager { } } - /// Represents an overall purpose of the build, which affects such things - /// as optimization and generation of debug symbols. + /// An enumeration that represents the build's purpose. + /// + /// The build's purpose affects whether the system + /// generates debugging symbols, and enables compiler optimizations.. public enum BuildConfiguration: String { - case debug, release, inherit + /// The build is for debugging. + case debug + /// The build is for release. + case release + /// The build is a dependency and its purpose is inherited from the build that causes it. + case inherit } - /// Represents the amount of detail in a build log. + /// An enumeration that represents the amount of detail + /// the system includes in a build log. public enum BuildLogVerbosity: String { - case concise, verbose, debug + /// The build log should be concise. + case concise + /// The build log should be verbose. + case verbose + /// The build log should include debugging information. + case debug } - /// Represents the results of running a build. + /// An object that represents the results of running a build. public struct BuildResult { - /// Whether the build succeeded or failed. + /// A Boolean vaule that indicates whether the build succeeded or failed. public var succeeded: Bool - /// Log output (the verbatim text in the initial proposal). + /// A string that contains the build's log output. 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. + /// A list of the artifacts built from the products in the package. + /// + /// Intermediate artificacts, such as object files produced from + /// individual targets, aren't included in the list. public var builtArtifacts: [BuiltArtifact] - /// Represents a single artifact produced during a build. + /// An object that represents an artifact produced during a build. public struct BuiltArtifact { - /// Full path of the built artifact in the local file system. + /// The full path to the built artifact in the local file system. + /// + /// @DeprecationSummary{Use ``url`` instead.} @available(_PackageDescription, deprecated: 6.0, renamed: "url") public var path: Path { try! Path(url: self.url) } - /// Full path of the built artifact in the local file system. + /// A URL that locates the built artifact in the local file system. @available(_PackageDescription, introduced: 6.0) public var url: URL - /// The kind of artifact that was built. + /// The build artificact's kind. public var kind: Kind - /// Represents the kind of artifact that was built. The specific file + /// An enumeration that represents the kind of a built artifact. + /// + /// 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. + /// a dynamic library may be built as a framework. public enum Kind: String { - case executable, dynamicLibrary, staticLibrary + /// The artifact is an executable. + case executable + /// The artifact is a dynamic library. + case dynamicLibrary + /// The artifact is a static library. + case staticLibrary } } } - /// 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). + /// Runs the tests in the specified subset. + /// + /// As with the `swift test` command, this method performs + /// an incremental build if necessary before it runs the tests. /// /// Any test failures are reported in the test result. This method throws an - /// error if the input parameters are invalid or in case the test cannot be - /// started. + /// error if the input parameters are invalid, or it can't start the test. /// - /// The SwiftPM CLI or any IDE that supports packages may show the progress - /// of the tests as they happen. + /// The SwiftPM command-line program, or an IDE that supports packages, + /// may show the progress of the tests as they happen. + /// + /// - Parameters: + /// - subset: The tests to run. + /// - parameters: Parameters that control how the system runs the tests. + /// - Returns: The outcome of running the tests. public func test( _ subset: TestSubset, parameters: TestParameters @@ -153,79 +197,117 @@ public struct PackageManager { } } - /// Specifies what tests in a package to run. + /// An enumeration that specifies what tests in a package the system runs. public enum TestSubset { - /// Represents all tests in the package. + /// All tests in the package. case all - /// Represents one or more tests filtered by regular expression, with the - /// format . or ./. - /// This is the same as the `--filter` option of `swift test`. + /// One or more tests filtered by regular expression. + /// + /// Identify tests using the format `.`, + /// or `./`. + /// The `--filter` option of `swift test` uses the same format. case filtered([String]) } - /// Parameters that control how the tests are run. + /// Parameters that control how the system runs tests. public struct TestParameters { - /// Whether to collect code coverage information while running the tests. + /// A Boolean that tells the system whether to collect code coverage information. public var enableCodeCoverage: Bool + /// Initializes a test parameter structure. + /// - Parameter enableCodeCoverage: Whether the system collects code coverage information. public init(enableCodeCoverage: Bool = false) { self.enableCodeCoverage = enableCodeCoverage } } - /// Represents the result of running unit tests. + /// A structure that represents the result of running tests. public struct TestResult { - /// Whether the test run succeeded or failed. + /// A Boolean that indicates whether the test run succeeded. public var succeeded: Bool - /// Results for all the test targets that were run (filtered based on - /// the input subset passed when running the test). + /// A list of results for each of the test targets run. + /// + /// If the system ran a filtered subset of tests, only results + /// for the test targets that include the filtered tests are included. public var testTargets: [TestTarget] - /// Path of a generated `.profdata` file suitable for processing using - /// `llvm-cov`, if `enableCodeCoverage` was set in the test parameters. + /// The optional path to a code coverage file. + /// + /// @DeprecationSummary{Use ``codeCoverageDataFileURL`` instead.} + /// + /// The file is a generated `.profdata` file suitable for processing using + /// `llvm-cov`, if ``PackageManager/TestParameters/enableCodeCoverage`` + /// is `true` in the test parameters. If it's `false`, this value is `nil`. @available(_PackageDescription, deprecated: 6.0, renamed: "codeCoverageDataFileURL") public var codeCoverageDataFile: Path? { self.codeCoverageDataFileURL.map { try! Path(url: $0) } } - /// Path of a generated `.profdata` file suitable for processing using - /// `llvm-cov`, if `enableCodeCoverage` was set in the test parameters. + /// The optional location of a code coverage file. + /// + /// The file is a generated `.profdata` file suitable for processing using + /// `llvm-cov`, if ``PackageManager/TestParameters/enableCodeCoverage`` + /// is `true` in the test parameters. If it's `false`, this value is `nil`. @available(_PackageDescription, introduced: 6.0) public var codeCoverageDataFileURL: URL? - /// Represents the results of running some or all of the tests in a - /// single test target. + /// A structure that represents the results of running tests in a single test target. + /// + /// If you use ``PackageManager/TestSubset/filtered(_:)`` to run a filtered + /// subset of tests, this structure contains results only for tests in + /// the target that match the filter regex. public struct TestTarget { + /// The test target's name. public var name: String + /// A list of results for test cases defined in the test target. public var testCases: [TestCase] - /// Represents the results of running some or all of the tests in - /// a single test case. + /// A structure that represents the results of running tests in a + /// single test case. + /// + /// If you use ``PackageManager/TestSubset/filtered(_:)`` to run a filtered + /// subset of tests, this structure contains results only for tests in + /// the test case that match the filter regex. public struct TestCase { + /// The test case's name. public var name: String + /// A list of results for tests defined in the test case. public var tests: [Test] - /// Represents the results of running a single test. + /// A structure that represents the result of running a single test. public struct Test { + /// The test's name. public var name: String + /// The test's outcome. public var result: Result + /// The time taken for the system to run the test. public var duration: Double - /// Represents the result of running a single test. + /// An enumeration that represents the result of running a single test. public enum Result: String { - case succeeded, skipped, failed + /// The test succeeded. + case succeeded + /// The system skipped the test. + case skipped + /// The test failed. + case failed } } } } } - /// 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 - /// in any way it sees fit. + /// Returns a directory containing symbol graph files for the specified target. + /// + /// This method directs the package manager or IDE to create or update the + /// symbol graphs, if it needs to. How the system creates or updates these + /// files depends on the implementation of the package manager or IDE. + /// - Parameters: + /// - target: The target for which to generate symbol graphs. + /// - options: Options that control how the system generates the symbol graphs. + /// - Returns: The symbol graphs. public func getSymbolGraph( for target: Target, options: SymbolGraphOptions @@ -238,25 +320,42 @@ public struct PackageManager { } } - /// Represents options for symbol graph generation. + /// A structure that contains options for controlling how the system generates symbol graphs. public struct SymbolGraphOptions { - /// The symbol graph will include symbols at this access level and higher. + /// The symbol graph includes symbols at this access level and higher. public var minimumAccessLevel: AccessLevel - /// Represents a Swift access level. + /// An enumeration that represents a symbol access level in Swift. public enum AccessLevel: String, CaseIterable { - case `private`, `fileprivate`, `internal`, `package`, `public`, open + /// The symbol is private. + case `private` + /// The symbol is file-private. + case `fileprivate` + /// The symbol is internal. + case `internal` + /// The symbol has package-level visibility. + case `package` + /// The symbol is public. + case `public` + /// The symbol is open. + case open } - /// Whether to include synthesized members. + /// A Boolean value that indicates whether the symbol graph includes synthesized members. public var includeSynthesized: Bool - /// Whether to include symbols marked as SPI. + /// A Boolean value that indicates whether the symbol graph includes symbols marked as SPI. public var includeSPI: Bool - /// Whether to emit symbols for extensions to external types. + /// A Boolean value that indicates whether the symbol graph includes symbols for extensions to external types. public var emitExtensionBlocks: Bool + /// Initializes a symbol graph options structure. + /// - Parameters: + /// - minimumAccessLevel: The lowest access level to include in the symbol graph. + /// - includeSynthesized: Whether to include synthesized symbols in the symbol graph. + /// - includeSPI: Whether to include symbols marked as SPI in the symbol graph. + /// - emitExtensionBlocks: Whether to include symbols for extensions to external types in the symbol graph. public init( minimumAccessLevel: AccessLevel = .public, includeSynthesized: Bool = false, @@ -270,15 +369,17 @@ public struct PackageManager { } } - /// Represents the result of symbol graph generation. + /// A structure that represents the result of generating a symbol graph. public struct SymbolGraphResult { - /// The directory that contains the symbol graph files for the target. + /// A path to a directory that contains the symbol graph files. + /// + /// @DeprecationSummary{Use ``directoryURL`` instead.} @available(_PackageDescription, deprecated: 6.0, renamed: "directoryURL") public var directoryPath: Path { try! Path(url: self.directoryURL) } - /// The directory that contains the symbol graph files for the target. + /// A URL that locates a directory that contains the symbol graph files. @available(_PackageDescription, introduced: 6.0) public var directoryURL: URL } @@ -305,11 +406,12 @@ extension PackageManager { } } +/// Errors the package manager encounters communicating with its host application. public enum PackageManagerProxyError: Error { - /// Indicates that the functionality isn't implemented in the plugin host. + /// The functionality isn't implemented in the plugin host. case unimplemented(_ message: String) - /// An unspecified other kind of error from the Package Manager proxy. + /// The package manager proxy encountered an unspecified error. case unspecified(_ message: String) }