Skip to content

Support CommandPlugin #449

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ let package = Package(
name: "SwiftFormatConfiguration",
targets: ["SwiftFormatConfiguration"]
),
.plugin(
name: "FormatPlugin",
targets: ["Format Source Code"]
),
.plugin(
name: "LintPlugin",
targets: ["Lint Source Code"]
),
],
dependencies: [
// See the "Dependencies" section below.
Expand Down Expand Up @@ -91,7 +99,32 @@ let package = Package(
.product(name: "SwiftSyntax", package: "swift-syntax"),
]
),

.plugin(
name: "Format Source Code",
capability: .command(
intent: .sourceCodeFormatting(),
permissions: [
.writeToPackageDirectory(reason: "This command formats the Swift source files")
]
),
dependencies: [
.target(name: "swift-format")
],
path: "Plugins/FormatPlugin"
),
.plugin(
name: "Lint Source Code",
capability: .command(
intent: .custom(
verb: "lint-source-code",
description: "Lint source code for a specified target."
)
),
dependencies: [
.target(name: "swift-format")
],
path: "Plugins/LintPlugin"
),
.executableTarget(
name: "generate-pipeline",
dependencies: [
Expand Down
72 changes: 72 additions & 0 deletions Plugins/FormatPlugin/plugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import PackagePlugin
import Foundation

@main
struct FormatPlugin {
func format(tool: PluginContext.Tool, targetDirectories: [String], configurationFilePath: String?) throws {
let swiftFormatExec = URL(fileURLWithPath: tool.path.string)

var arguments: [String] = ["format"]

arguments.append(contentsOf: targetDirectories)

arguments.append(contentsOf: ["--recursive", "--parallel", "--in-place"])

if let configurationFilePath = configurationFilePath {
arguments.append(contentsOf: ["--configuration", configurationFilePath])
}

let process = try Process.run(swiftFormatExec, arguments: arguments)
process.waitUntilExit()

if process.terminationReason == .exit && process.terminationStatus == 0 {
print("Formatted the source code.")
}
else {
let problem = "\(process.terminationReason):\(process.terminationStatus)"
Diagnostics.error("swift-format invocation failed: \(problem)")
}
}
}

extension FormatPlugin: CommandPlugin {
func performCommand(
context: PluginContext,
arguments: [String]
) async throws {
let swiftFormatTool = try context.tool(named: "swift-format")

var argExtractor = ArgumentExtractor(arguments)
let targetNames = argExtractor.extractOption(named: "target")
let targetsToFormat = try context.package.targets(named: targetNames)

let configurationFilePath = argExtractor.extractOption(named: "configuration").first

let sourceCodeTargets = targetsToFormat.compactMap{ $0 as? SourceModuleTarget }

try format(
tool: swiftFormatTool,
targetDirectories: sourceCodeTargets.map(\.directory.string),
configurationFilePath: configurationFilePath
)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

extension FormatPlugin: XcodeCommandPlugin {
func performCommand(context: XcodeProjectPlugin.XcodePluginContext, arguments: [String]) throws {
let swiftFormatTool = try context.tool(named: "swift-format")

var argExtractor = ArgumentExtractor(arguments)
let configurationFilePath = argExtractor.extractOption(named: "configuration").first

try format(
tool: swiftFormatTool,
targetDirectories: [context.xcodeProject.directory.string],
configurationFilePath: configurationFilePath
)
}
}
#endif
72 changes: 72 additions & 0 deletions Plugins/LintPlugin/plugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import PackagePlugin
import Foundation

@main
struct LintPlugin {
func lint(tool: PluginContext.Tool, targetDirectories: [String], configurationFilePath: String?) throws {
let swiftFormatExec = URL(fileURLWithPath: tool.path.string)

var arguments: [String] = ["lint"]

arguments.append(contentsOf: targetDirectories)

arguments.append(contentsOf: ["--recursive", "--parallel", "--strict"])

if let configurationFilePath = configurationFilePath {
arguments.append(contentsOf: ["--configuration", configurationFilePath])
}

let process = try Process.run(swiftFormatExec, arguments: arguments)
process.waitUntilExit()

if process.terminationReason == .exit && process.terminationStatus == 0 {
print("Lintted the source code.")
}
else {
let problem = "\(process.terminationReason):\(process.terminationStatus)"
Diagnostics.error("swift-format invocation failed: \(problem)")
}
}
}

extension LintPlugin: CommandPlugin {
func performCommand(
context: PluginContext,
arguments: [String]
) async throws {
let swiftFormatTool = try context.tool(named: "swift-format")

// Extract the arguments that specify what targets to format.
var argExtractor = ArgumentExtractor(arguments)
let targetNames = argExtractor.extractOption(named: "target")
let targetsToFormat = try context.package.targets(named: targetNames)

let configurationFilePath = argExtractor.extractOption(named: "configuration").first

let sourceCodeTargets = targetsToFormat.compactMap { $0 as? SourceModuleTarget }

try lint(
tool: swiftFormatTool,
targetDirectories: sourceCodeTargets.map(\.directory.string),
configurationFilePath: configurationFilePath
)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

extension LintPlugin: XcodeCommandPlugin {
func performCommand(context: XcodeProjectPlugin.XcodePluginContext, arguments: [String]) throws {
let swiftFormatTool = try context.tool(named: "swift-format")
var argExtractor = ArgumentExtractor(arguments)
let configurationFilePath = argExtractor.extractOption(named: "configuration").first

try lint(
tool: swiftFormatTool,
targetDirectories: [context.xcodeProject.directory.string],
configurationFilePath: configurationFilePath
)
}
}
#endif