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

📦 Adds support for Swift Package plugin command #1093

Merged
merged 18 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from 15 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
27 changes: 20 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.5
// swift-tools-version:5.6

import PackageDescription
import Foundation
Expand All @@ -17,16 +17,16 @@ let package = Package(
.library(name: "SourceryJS", targets: ["SourceryJS"]),
.library(name: "SourcerySwift", targets: ["SourcerySwift"]),
.library(name: "SourceryFramework", targets: ["SourceryFramework"]),
.plugin(name: "SourceryCommandPlugin", targets: ["SourceryCommandPlugin"])
],
dependencies: [
.package(url: "https://github.com/jpsim/Yams.git", from: "4.0.6"),
.package(url: "https://github.com/kylef/Commander.git", .exact("0.9.1")),
.package(url: "https://github.com/kylef/Commander.git", exact: "0.9.1"),
// PathKit needs to be exact to avoid a SwiftPM bug where dependency resolution takes a very long time.
.package(url: "https://github.com/kylef/PathKit.git", .exact("1.0.1")),
.package(url: "https://github.com/StencilProject/Stencil.git", .upToNextMajor(from: "0.14.0")),
.package(url: "https://github.com/SwiftGen/StencilSwiftKit.git", .exact("2.10.1")),
.package(url: "https://github.com/tuist/XcodeProj.git", .exact("8.3.1")),
.package(url: "https://github.com/apple/swift-syntax.git", .exact("0.50600.1")),
.package(url: "https://github.com/kylef/PathKit.git", exact: "1.0.1"),
.package(url: "https://github.com/SwiftGen/StencilSwiftKit.git", exact: "2.10.1"),
.package(url: "https://github.com/tuist/XcodeProj.git", exact: "8.3.1"),
.package(url: "https://github.com/apple/swift-syntax.git", exact: "0.50600.1"),
.package(url: "https://github.com/Quick/Quick.git", from: "3.0.0"),
.package(url: "https://github.com/Quick/Nimble.git", from: "9.0.0")
],
Expand Down Expand Up @@ -231,6 +231,19 @@ let package = Package(
name: "lib_InternalSwiftSyntaxParser",
url: "https://github.com/keith/StaticInternalSwiftSyntaxParser/releases/download/5.6/lib_InternalSwiftSyntaxParser.xcframework.zip",
checksum: "88d748f76ec45880a8250438bd68e5d6ba716c8042f520998a438db87083ae9d"
),
.plugin(
name: "SourceryCommandPlugin",
capability: .command(
intent: .custom(
verb: "sourcery-command",
description: "Sourcery command plugin for code generation"
),
permissions: [
.writeToPackageDirectory(reason: "Need permission to write generated files to package directory")
]
),
dependencies: ["SourceryExecutable"]
)
]
)
73 changes: 73 additions & 0 deletions Plugins/SourceryCommandPlugin/SourceryCommandPlugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import PackagePlugin
import Foundation

@main
struct SourceryCommandPlugin {
private func run(_ sourcery: String, withConfig configFilePath: String) throws {
let sourceryURL = URL(fileURLWithPath: sourcery)

let process = Process()
process.executableURL = sourceryURL
process.arguments = [
"--config",
configFilePath,
"--disableCache"
]

try process.run()
process.waitUntilExit()

let gracefulExit = process.terminationReason == .exit && process.terminationStatus == 0
if !gracefulExit {
throw "🛑 The plugin execution failed with reason: \(process.terminationReason.rawValue) and status: \(process.terminationStatus) "
}
}
}

// MARK: - CommandPlugin

extension SourceryCommandPlugin: CommandPlugin {
func performCommand(context: PluginContext, arguments: [String]) async throws {
// Run one per target
for target in context.package.targets {
let configFilePath = target.directory.appending(subpath: ".sourcery.yml").string
let sourcery = try context.tool(named: "SourceryExecutable").path.string

guard FileManager.default.fileExists(atPath: configFilePath) else {
Diagnostics.warning("⚠️ Could not find `.sourcery.yml` for the given target")
return
}

try run(sourcery, withConfig: configFilePath)
}
}
}

// MARK: - XcodeProjectPlugin

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

extension SourceryCommandPlugin: XcodeCommandPlugin {
func performCommand(context: XcodePluginContext, arguments: [String]) throws {
for target in context.xcodeProject.targets {
guard let configFilePath = target
.inputFiles
.filter({ $0.path.lastComponent == ".sourcery.yml" })
.first?
.path
.string else {
Diagnostics.warning("⚠️ Could not find `.sourcery.yml` in Xcode's input file list")
return
}
let sourcery = try context.tool(named: "SourceryExecutable").path.string

try run(sourcery, withConfig: configFilePath)
}
}
}
#endif

extension String: LocalizedError {
public var errorDescription: String? { return self }
}
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,21 @@ You can also watch this quick getting started and intro to mocking video by Insi

Run `xcodebuild -scheme sourcery -destination generic/platform=macOS -archivePath sourcery.xcarchive archive` and export the binary from the archive.

- _SPM (for plugin use only)_
Add the package dependency to your `Package.swift` manifest from version `1.8.3`.

```
.package(url: "https://github.com/krzysztofzablocki/Sourcery.git", from: "1.8.3")
```

## Documentation

Full documentation for the latest release is available [here](http://merowing.info/Sourcery/).

## Usage

### Running the executable

Sourcery is a command line tool; you can either run it manually or in a custom build phase using the following command:

```
Expand All @@ -134,6 +143,32 @@ $ ./bin/sourcery --sources <sources path> --templates <templates path> --output

> Note: this command differs depending on how you installed Sourcery (see [Installing](#installing))

### Swift Package command

Sourcery can now be used as a Swift package command plugin. In order to do this, the package must be added as a dependency to your Swift package or Xcode project (see [Installing](#installing) above).

To provide a configuration for the plugin to use, place a `.sourcery.yml` file at the root of the target's directory (in the sources folder rather than the root of the package).

#### Running from the command line

To verify the plugin can be found by SwiftPM, use:

```
$ swift package --list
polpielladev marked this conversation as resolved.
Show resolved Hide resolved
```

To run the code generator, you need to allow changes to the project with the `--allow-writing-to-package-directory` flag:

```
$ swift package --allow-writing-to-package-directory sourcery-command
```

#### Running in Xcode

Inside a project/package that uses this command plugin, right-click the project and select "SourceryCommand" from the "SourceryPlugins" menu group.

> ⚠️ Note that this is only available from Xcode 14 onwards.

### Command line options

- `--sources` - Path to a source swift files or directories. You can provide multiple paths using multiple `--sources` option.
Expand Down