Files
2022-07-30 20:47:39 +02:00

106 lines
2.9 KiB
Swift

//
// SwiftGen
// Copyright © 2022 SwiftGen
// MIT Licence
//
import AppKit
import PathKit
import Stencil
import StencilSwiftKit
import SwiftGenKit
extension Config {
public func runCommands(
modernSpacing: Bool,
logLevel: CommandLogLevel,
logger: (LogLevel, String) -> Void = logMessage
) throws {
let errors = commands.parallelCompactMap { cmd, entry -> Swift.Error? in
do {
try run(parserCommand: cmd, entry: entry, modernSpacing: modernSpacing, logLevel: logLevel, logger: logger)
return nil
} catch {
return error
}
}
if errors.count == 1 {
throw errors[0]
} else if errors.count > 1 {
throw Error.multipleErrors(errors)
}
}
private func run(
parserCommand: ParserCLI,
entry: ConfigEntry,
modernSpacing: Bool,
logLevel: CommandLogLevel,
logger: (LogLevel, String) -> Void
) throws {
var entry = entry
entry.makeRelativeTo(inputDir: inputDir, outputDir: outputDir)
if logLevel == .verbose {
for item in entry.commandLine(forCommand: parserCommand.name) {
logger(.info, " $ \(item)")
}
}
try entry.checkPaths()
try entry.run(parserCommand: parserCommand, modernSpacing: modernSpacing, logger: logger)
}
}
extension ConfigEntry {
func run(parserCommand: ParserCLI, modernSpacing: Bool, logger: (LogLevel, String) -> Void) throws {
let context: [String: Any] = try withoutActuallyEscaping(logger) { logger in
let parser = try parserCommand.parserType.init(options: options) { msg, _, _ in
logger(.warning, msg)
}
let filter = try Filter(
pattern: self.filter ?? parserCommand.parserType.defaultFilter,
options: parserCommand.parserType.filterOptions
)
try parser.searchAndParse(paths: inputs, filter: filter)
return parser.stencilContext()
}
for entryOutput in outputs {
let templateRealPath = try entryOutput.template.resolvePath(forParser: parserCommand, logger: logger)
let isBundledTemplate = entryOutput.template.isBundled(forParser: parserCommand)
let template = try Template.load(from: templateRealPath, modernSpacing: isBundledTemplate || modernSpacing)
let enriched = try StencilContext.enrich(context: context, parameters: entryOutput.parameters)
let rendered = try template.render(enriched)
let output = OutputDestination.file(entryOutput.output)
try output.write(content: rendered, onlyIfChanged: true, logger: logger)
}
}
}
// MARK: - Path checks
extension ConfigEntry {
func checkPaths() throws {
for inputPath in self.inputs {
guard inputPath.exists else {
throw Config.Error.pathNotFound(path: inputPath)
}
}
for output in outputs {
try output.checkPaths()
}
}
}
extension ConfigEntryOutput {
func checkPaths() throws {
guard self.output.parent().exists else {
throw Config.Error.pathNotFound(path: self.output.parent())
}
}
}