Skip to content
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 Apple Inc. and the Swift project authors
// Copyright (c) 2022-2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -32,44 +32,34 @@ extension PackageManager {
}
}

/// Returns the relevant symbols graphs for Swift-DocC documentation generation for
/// the given target.
/// Returns the relevant symbols graphs for Swift-DocC documentation generation for the given target.
func doccSymbolGraphs(
for target: SwiftSourceModuleTarget,
context: PluginContext,
verbose: Bool,
snippetExtractor: SnippetExtractor?,
customSymbolGraphOptions: [PluginFlag],
minimumAccessLevel: SymbolGraphOptions.AccessLevel? = nil
customSymbolGraphOptions: ParsedSymbolGraphArguments
) throws -> DocCSymbolGraphResult {
// First generate the primary symbol graphs containing information about the
// symbols defined in the target itself.

var symbolGraphOptions = target.defaultSymbolGraphOptions(in: context.package)
if let minimumAccessLevel {

if let rawMinimumAccessLevel = customSymbolGraphOptions.minimumAccessLevel,
let minimumAccessLevel = SymbolGraphOptions.AccessLevel(rawValue: rawMinimumAccessLevel)
{
symbolGraphOptions.minimumAccessLevel = minimumAccessLevel
}

// Modify the symbol graph options with the custom ones
for customSymbolGraphOption in customSymbolGraphOptions {
switch customSymbolGraphOption {
case .extendedTypes.positive:
#if swift(>=5.8)
symbolGraphOptions.emitExtensionBlocks = true
#else
print("warning: detected '--include-extended-types' option, which is incompatible with your swift version (required: 5.8)")
#endif
case .extendedTypes.negative:
#if swift(>=5.8)
symbolGraphOptions.emitExtensionBlocks = false
if customSymbolGraphOptions.skipSynthesizedSymbols == true {
symbolGraphOptions.includeSynthesized = false
}

if let includeExtendedTypes = customSymbolGraphOptions.includeExtendedTypes {
#if swift(<5.8)
print("warning: detected '--\(includeExtendedTypes ? "include" : "exclude")-extended-types' option, which is incompatible with your swift version (required: 5.8)")
#else
print("warning: detected '--exclude-extended-types' option, which is incompatible with your swift version (required: 5.8)")
symbolGraphOptions.emitExtensionBlocks = includeExtendedTypes
#endif
case .skipSynthesizedSymbols:
symbolGraphOptions.includeSynthesized = false
default:
fatalError("error: unknown PluginFlag (\(customSymbolGraphOption.parsedValues.joined(separator: ", "))) detected in symbol graph generation - please create an issue at https://github.com/swiftlang/swift-docc-plugin")
}
}

if verbose {
Expand Down
48 changes: 18 additions & 30 deletions Plugins/Swift-DocC Convert/SwiftDocCConvert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,31 @@ import PackagePlugin
throw ArgumentParsingError.packageDoesNotContainSwiftSourceModuleTargets
}

let verbose = argumentExtractor.extractFlag(named: "verbose") > 0
let isCombinedDocumentationEnabled = argumentExtractor.extractFlag(named: PluginFlag.enableCombinedDocumentationSupportFlagName) > 0
// Parse the given command-line arguments
let parsedArguments = ParsedArguments(argumentExtractor.remainingArguments)

// If the `--help` or `-h` flag was passed, print the plugin's help information and exit.
guard !parsedArguments.pluginArguments.help else {
let helpInfo = try HelpInformation.forAction(.convert, doccExecutableURL: doccExecutableURL)
print(helpInfo)
return
}

let verbose = parsedArguments.pluginArguments.verbose
let isCombinedDocumentationEnabled = parsedArguments.pluginArguments.enableCombinedDocumentation

if isCombinedDocumentationEnabled {
let doccFeatures = try? DocCFeatures(doccExecutable: doccExecutableURL)
guard doccFeatures?.contains(.linkDependencies) == true else {
// The developer uses the combined documentation plugin flag with a DocC version that doesn't support combined documentation.
Diagnostics.error("""
Unsupported use of '--\(PluginFlag.enableCombinedDocumentationSupportFlagName)'. \
Unsupported use of '\(DocumentedFlag.enableCombinedDocumentation.names.preferred)'. \
DocC version at '\(doccExecutableURL.path)' doesn't support combined documentation.
""")
return
}
}

// Parse the given command-line arguments
let parsedArguments = ParsedArguments(argumentExtractor.remainingArguments)

// If the `--help` or `-h` flag was passed, print the plugin's help information
// and exit.
guard !parsedArguments.help else {
let helpInformation = try HelpInformation.forAction(
.convert,
doccExecutableURL: doccExecutableURL
)

print(helpInformation)
return
}

#if swift(>=5.7)
let snippetExtractTool = try context.tool(named: "snippet-extract")
let snippetExtractor = SnippetExtractor(
Expand All @@ -79,8 +74,7 @@ import PackagePlugin
context: context,
verbose: verbose,
snippetExtractor: snippetExtractor,
customSymbolGraphOptions: parsedArguments.symbolGraphArguments,
minimumAccessLevel: parsedArguments.arguments.symbolGraphMinimumAccessLevel.flatMap { .init(rawValue: $0) }
customSymbolGraphOptions: parsedArguments.symbolGraphArguments
)

if target.doccCatalogPath == nil,
Expand Down Expand Up @@ -120,16 +114,9 @@ import PackagePlugin
doccCatalogPath: target.doccCatalogPath,
targetName: target.name,
symbolGraphDirectoryPath: symbolGraphs.unifiedSymbolGraphsDirectory.path,
outputPath: doccArchiveOutputPath
outputPath: doccArchiveOutputPath,
dependencyArchivePaths: task.dependencies.map { $0.target.doccArchiveOutputPath(in: context) }
)
if isCombinedDocumentationEnabled {
doccArguments.append(CommandLineOption.enableExternalLinkSupport.defaultName)

for taskDependency in task.dependencies {
let dependencyArchivePath = taskDependency.target.doccArchiveOutputPath(in: context)
doccArguments.append(contentsOf: [CommandLineOption.externalLinkDependency.defaultName, dependencyArchivePath])
}
}

if verbose {
let arguments = doccArguments.joined(separator: " ")
Expand All @@ -149,7 +136,8 @@ import PackagePlugin
if process.terminationReason == .exit && process.terminationStatus == 0 {
print("Conversion complete! (\(conversionDuration.descriptionInSeconds))")

let describedOutputPath = doccArguments.outputPath ?? "unknown location"
var arguments = CommandLineArguments(doccArguments)
let describedOutputPath = arguments.extractOption(named: DocCArguments.outputPath).last ?? "unknown location"
print("Generated DocC archive at '\(describedOutputPath)'")
} else {
Diagnostics.error("'docc convert' invocation failed with a nonzero exit code: '\(process.terminationStatus)'")
Expand Down
14 changes: 6 additions & 8 deletions Plugins/Swift-DocC Preview/SwiftDocCPreview.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 Apple Inc. and the Swift project authors
// Copyright (c) 2022-2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -28,19 +28,18 @@ import PackagePlugin
possibleTargets = specifiedTargets
}

let verbose = argumentExtractor.extractFlag(named: "verbose") > 0

// Parse the given command-line arguments
let parsedArguments = ParsedArguments(argumentExtractor.remainingArguments)

// If the `--help` or `-h` flag was passed, print the plugin's help information
// and exit.
guard !parsedArguments.help else {
// If the `--help` or `-h` flag was passed, print the plugin's help information and exit.
guard !parsedArguments.pluginArguments.help else {
let helpInfo = try HelpInformation.forAction(.preview, doccExecutableURL: doccExecutableURL)
print(helpInfo)
return
}

let verbose = parsedArguments.pluginArguments.verbose

// Confirm that at least one compatible target was provided.
guard let target = possibleTargets.first else {
Diagnostics.error("""
Expand Down Expand Up @@ -84,8 +83,7 @@ import PackagePlugin
context: context,
verbose: verbose,
snippetExtractor: snippetExtractor,
customSymbolGraphOptions: parsedArguments.symbolGraphArguments,
minimumAccessLevel: parsedArguments.arguments.symbolGraphMinimumAccessLevel.flatMap { .init(rawValue: $0) }
customSymbolGraphOptions: parsedArguments.symbolGraphArguments
)

if try FileManager.default.contentsOfDirectory(atPath: symbolGraphs.targetSymbolGraphsDirectory.path).isEmpty {
Expand Down
30 changes: 0 additions & 30 deletions Sources/SwiftDocCPluginUtilities/Arguments+outputPath.swift

This file was deleted.

This file was deleted.

10 changes: 0 additions & 10 deletions Sources/SwiftDocCPluginUtilities/Arguments.swift

This file was deleted.

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

/// A named command line argument; either a flag or an option with a value.
public struct CommandLineArgument {
/// The names of this command line argument.
public var names: Names
/// The kind of command line argument.
public var kind: Kind

/// A collection of names for a command line argument.
public struct Names: Hashable {
/// The preferred name for this command line argument.
public var preferred: String
/// All possible names for this command line argument.
public var all: Set<String>

/// Creates a new command line argument collection of names.
///
/// - Parameters:
/// - preferred: The preferred name for this command line argument.
/// - alternatives: A collection of alternative names for this command line argument.
public init(preferred: String, alternatives: Set<String> = []) {
self.all = alternatives.union([preferred])
self.preferred = preferred
}
}

/// A kind of command line argument.
public enum Kind {
/// A flag argument without an associated value.
///
/// For example: `"--some-flag"`.
case flag
/// An option argument with an associated value.
///
/// For example: `"--some-option", "value"` or `"--some-option=value"`.
case option(value: String)
}

/// Creates a new command line flag with the given names.
/// - Parameters:
/// - names: The names for the new command line flag.
public static func flag(_ names: Names) -> Self {
.init(names: names, kind: .flag)
}

/// Creates a new command option with the given names and associated value.
/// - Parameters:
/// - names: The names for the new command line option.
/// - value: The value that's associated with this command line option.
public static func option(_ names: Names, value: String) -> Self {
.init(names: names, kind: .option(value: value))
}
}
Loading