Skip to content

Add support for rswift.json config to BuildToolPlugin #896

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

Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@
import Foundation
import PackagePlugin

struct RSwiftConfig: Codable {
enum Generator: String, Codable {
case image, string, color
case file, font, nib
case segue, storyboard, reuseIdentifier
case entitlements, info, id
}

let generators: [Generator]?
let rswiftignorePath: String?
let additionalArguments: [String]?
}

@main
struct RswiftGenerateInternalResources: BuildToolPlugin {
func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
Expand All @@ -29,7 +42,21 @@ struct RswiftGenerateInternalResources: BuildToolPlugin {

let bundleSource = target.kind == .generic ? "module" : "finder"
let description = "\(target.kind) module \(target.name)"


var additionalArguments: [String] = []
if let config = getConfig(from: target) {
if let generators = config.generators {
let generators = generators.map(\.rawValue).joined(separator: ",")
additionalArguments += ["--generators", generators]
}
if let rswiftignorePath = config.rswiftignorePath {
additionalArguments += ["--rswiftignore", rswiftignorePath]
}
if let other = config.additionalArguments {
additionalArguments += other
}
}

return [
.buildCommand(
displayName: "R.swift generate resources for \(description)",
Expand All @@ -38,19 +65,41 @@ struct RswiftGenerateInternalResources: BuildToolPlugin {
"generate", rswiftPath.string,
"--input-type", "input-files",
"--bundle-source", bundleSource,
] + inputFilesArguments,
] + inputFilesArguments + additionalArguments,
outputFiles: [rswiftPath]
),
]
}

func getConfig(from target: SourceModuleTarget) -> RSwiftConfig? {
guard let path = locateConfig(in: target) else {
return nil
}
return decodeConfig(at: path)
}

func locateConfig(in target: SourceModuleTarget) -> Path? {
let rootConfig = target.directory.appending(["rswift.json"])
if FileManager.default.fileExists(atPath: rootConfig.string) {
return rootConfig
}
return target.sourceFiles.map(\.path).first(where: { $0.lastComponent == "rswift.json" })
}

func decodeConfig(at path: Path) -> RSwiftConfig? {
guard let config = URL(string: "file://\(path.string)"),
let data = try? Data(contentsOf: config) else {
return nil
}
return try? JSONDecoder().decode(RSwiftConfig.self, from: data)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

extension RswiftGenerateInternalResources: XcodeBuildToolPlugin {
func createBuildCommands(context: XcodePluginContext, target: XcodeTarget) throws -> [Command] {

let resourcesDirectoryPath = context.pluginWorkDirectory
.appending(subpath: target.displayName)
.appending(subpath: "Resources")
Expand All @@ -65,6 +114,20 @@ extension RswiftGenerateInternalResources: XcodeBuildToolPlugin {
} else {
description = target.displayName
}

var additionalArguments: [String] = []
if let config = getConfig(from: context.xcodeProject) {
if let generators = config.generators {
let generators = generators.map(\.rawValue).joined(separator: ",")
additionalArguments += ["--generators", generators]
}
if let rswiftignorePath = config.rswiftignorePath {
additionalArguments += ["--rswiftignore", rswiftignorePath]
}
if let other = config.additionalArguments {
additionalArguments += other
}
}

return [
.buildCommand(
Expand All @@ -74,12 +137,27 @@ extension RswiftGenerateInternalResources: XcodeBuildToolPlugin {
"generate", rswiftPath.string,
"--target", target.displayName,
"--input-type", "xcodeproj",
"--bundle-source", "finder",
],
"--bundle-source", "finder"
] + additionalArguments,
outputFiles: [rswiftPath]
),
]
}

func getConfig(from xcodeProject: XcodeProject) -> RSwiftConfig? {
guard let path = locateConfig(in: xcodeProject) else {
return nil
}
return decodeConfig(at: path)
}

func locateConfig(in xcodeProject: XcodeProject) -> Path? {
let rootConfig = xcodeProject.directory.appending(["rswift.json"])
if FileManager.default.fileExists(atPath: rootConfig.string) {
return rootConfig
}
return xcodeProject.filePaths.first(where: { $0.lastComponent == "rswift.json" })
}
}

#endif