GenerateDoccReference.swift 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Argument Parser open source project
  4. //
  5. // Copyright (c) 2025 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See https://swift.org/LICENSE.txt for license information
  9. //
  10. //===----------------------------------------------------------------------===//
  11. import Foundation
  12. import PackagePlugin
  13. @main
  14. struct GenerateDoccReferencePlugin: CommandPlugin {
  15. func performCommand(
  16. context: PluginContext,
  17. arguments: [String]
  18. ) async throws {
  19. // Locate generation tool.
  20. let generationTool = "generate-docc-reference"
  21. let generationToolFile = try context.tool(named: generationTool).path
  22. // Create an extractor to extract plugin-only arguments from the `arguments`
  23. // array.
  24. var extractor = ArgumentExtractor(arguments)
  25. // Run generation tool once if help is requested.
  26. if extractor.helpRequest() {
  27. try generationToolFile.exec(arguments: ["--help"])
  28. print(
  29. """
  30. ADDITIONAL OPTIONS:
  31. --configuration <configuration>
  32. Tool build configuration used to generate the
  33. reference document. (default: release)
  34. NOTE: The "GenerateDoccReference" plugin handles passing the "<tool>" and
  35. "--output-directory <output-directory>" arguments. Manually supplying
  36. these arguments will result in a runtime failure.
  37. """)
  38. return
  39. }
  40. // Extract configuration argument before making it to the
  41. // "generate-docc-reference" tool.
  42. let configuration = try extractor.configuration()
  43. // Build all products first.
  44. print("Building package in \(configuration) mode...")
  45. let buildResult = try packageManager.build(
  46. .all(includingTests: false),
  47. parameters: .init(configuration: configuration))
  48. guard buildResult.succeeded else {
  49. throw GenerateDoccReferencePluginError.buildFailed(buildResult.logText)
  50. }
  51. print("Built package in \(configuration) mode")
  52. // Run generate-docc-reference on all executable artifacts.
  53. for builtArtifact in buildResult.builtArtifacts {
  54. // Skip non-executable targets
  55. guard builtArtifact.kind == .executable else { continue }
  56. // Skip executables without a matching product.
  57. guard let product = builtArtifact.matchingProduct(context: context)
  58. else { continue }
  59. // Skip products without a dependency on ArgumentParser.
  60. guard product.hasDependency(named: "ArgumentParser") else { continue }
  61. // Skip products with multiple underlying targets.
  62. guard product.targets.count == 1 else { continue }
  63. let target = product.targets[0]
  64. // Get the artifacts name.
  65. let executableName = builtArtifact.path.lastComponent
  66. print("Generating docc reference for \(executableName)...")
  67. // Create output directory.
  68. let outputDirectory = target.directory
  69. .appending("\(target.name).docc")
  70. try outputDirectory.createOutputDirectory()
  71. // Create generation tool arguments.
  72. var generationToolArguments = [
  73. builtArtifact.path.string,
  74. "--output-directory",
  75. outputDirectory.string,
  76. ]
  77. generationToolArguments.append(
  78. contentsOf: extractor.remainingArguments)
  79. // Spawn generation tool.
  80. try generationToolFile.exec(arguments: generationToolArguments)
  81. print("Generated docc reference in '\(outputDirectory)'")
  82. }
  83. }
  84. }