// swift-tools-version: 5.6 import PackageDescription let package = Package( name: "MyFormatterPlugin", dependencies: [ .package(url: "https://github.com/apple/swift-format.git", from: "0.50500.0"), ], targets: [ .plugin( name: "MyFormatterPlugin", capability: .command( intent: .sourceCodeFormatting(), permissions: [ .writeToPackageDirectory(reason: "This command reformats source files") ] ), dependencies: [ .product(name: "swift-format", package: "swift-format"), ] ) ] )
.plugin()
で定義する MyFormatterPlugin
は swift-format
パッケージの swift-format
executable product に依存を宣言していて・・・import PackagePlugin import Foundation @main struct MyFormatterPlugin: CommandPlugin { func performCommand( context: PluginContext, arguments: [String] ) async throws { // We'll be invoking `swift-format`, so start by locating it. let swiftFormatTool = try context.tool(named: "swift-format") // By convention, use a configuration file in the package directory. let configFile = context.package.directory.appending(".swift-format.json") // Iterate over the targets in the package. for target in context.package.targets { // Skip any type of target that doesn't have source files. // Note: We could choose to instead emit a warning or error here. guard let target = target as? SourceModuleTarget else { continue } // Invoke `swift-format` on the target directory, passing a configuration // file from the package directory. let swiftFormatExec = URL(fileURLWithPath: swiftFormatTool.path.string) let swiftFormatArgs = [ "--configuration", "\(configFile)", "--in-place", "--recursive", "\(target.directory)" ] let process = try Process.run(swiftFormatExec, arguments: swiftFormatArgs) process.waitUntilExit() // Check whether the subprocess invocation was successful. if process.terminationReason == .exit && process.terminationStatus == 0 { print("Formatted the source code in \(target.directory).") } else { let problem = "\(process.terminationReason):\(process.terminationStatus)" Diagnostics.error("swift-format invocation failed: \(problem)") } } } }
MyFormatterPlugin
のコードでは、 context.tool(named: "swift-format")
という特殊なAPIを通して、 依存として宣言したexecutableのビルドされた実体を表すオブジェクトを取得し、swiftFormatTool.path.string
でファイルパスが書いてあるので、後は Process
でそれを発火する。 (edited)