Skip to content
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