110 lines
4.1 KiB
Swift
110 lines
4.1 KiB
Swift
//
|
|
// SwiftGen
|
|
// Copyright © 2022 SwiftGen
|
|
// MIT Licence
|
|
//
|
|
|
|
import PathKit
|
|
|
|
public enum TemplateRef: Equatable {
|
|
case name(String)
|
|
case path(Path)
|
|
|
|
enum Error: Swift.Error {
|
|
case namedTemplateNotFound(name: String)
|
|
case templatePathNotFound(path: Path)
|
|
case noTemplateProvided
|
|
case multipleTemplateOptions(path: String, name: String)
|
|
}
|
|
|
|
public init(templateShortName: String, templateFullPath: String) throws {
|
|
switch (!templateFullPath.isEmpty, !templateShortName.isEmpty) {
|
|
case (false, false):
|
|
throw Self.Error.noTemplateProvided
|
|
case (false, true):
|
|
self = .name(templateShortName)
|
|
case (true, false):
|
|
self = .path(Path(templateFullPath))
|
|
case (true, true):
|
|
throw Self.Error.multipleTemplateOptions(path: templateFullPath, name: templateShortName)
|
|
}
|
|
}
|
|
|
|
/// Returns the path of a template
|
|
///
|
|
/// * If it's a `.path`, check that the path exists and return it (throws if it isn't an existing file)
|
|
/// * If it's a `.name`, search the named template in the folder `parserName`
|
|
/// in the Application Support directory first, then in the bundled templates,
|
|
/// and returns the path if found (throws if none is found)
|
|
///
|
|
/// - Parameter parserName: The folder to search for the template.
|
|
/// Typically the name of one of the SwiftGen parsers like `strings`, `colors`, etc
|
|
/// - Returns: The Path matching the template found
|
|
/// - Throws: TemplateRef.Error
|
|
///
|
|
public func resolvePath(forParser parser: ParserCLI, logger: (LogLevel, String) -> Void = logMessage) throws -> Path {
|
|
switch self {
|
|
case .name(let templateShortName):
|
|
var path = Path.deprecatedAppSupportTemplates + parser.templateFolder + "\(templateShortName).stencil"
|
|
if path.isFile {
|
|
logger(
|
|
.warning,
|
|
"""
|
|
Referring to templates in Application Support by name is deprecated and will be removed in SwiftGen 7.0.
|
|
For custom templates, please use `templatePath` instead of `templateName` to point to them.
|
|
We also recommend you move your custom templates from \(Path.deprecatedAppSupportTemplates)
|
|
to your project's folder so that your project is able to run independently on all machines.
|
|
"""
|
|
)
|
|
} else {
|
|
path = Path.bundledTemplates + parser.templateFolder + "\(templateShortName).stencil"
|
|
}
|
|
guard path.isFile else {
|
|
throw Self.Error.namedTemplateNotFound(name: templateShortName)
|
|
}
|
|
return path
|
|
case .path(let fullPath):
|
|
guard fullPath.isFile else {
|
|
throw Self.Error.templatePathNotFound(path: fullPath)
|
|
}
|
|
return fullPath
|
|
}
|
|
}
|
|
|
|
/// Check if the template is a bundled template for the given parser
|
|
/// - Parameter parserName: The folder to search for the template.
|
|
/// Typically the name of one of the SwiftGen parsers like `strings`, `colors`, etc
|
|
/// - Returns: The Path matching the template found
|
|
public func isBundled(forParser parser: ParserCLI) -> Bool {
|
|
switch self {
|
|
case .name(let templateShortName):
|
|
let path = Path.bundledTemplates + parser.templateFolder + "\(templateShortName).stencil"
|
|
return path.isFile
|
|
case .path:
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
extension TemplateRef.Error: CustomStringConvertible {
|
|
var description: String {
|
|
switch self {
|
|
case .namedTemplateNotFound(let name):
|
|
return """
|
|
Template named \(name) not found. Use `swiftgen template list` to list available named templates \
|
|
or use `templatePath` to specify a template by its full path.
|
|
"""
|
|
case .templatePathNotFound(let path):
|
|
return "Template not found at path \(path.description)."
|
|
case .noTemplateProvided:
|
|
return """
|
|
You must specify a template by name (templateName) or path (templatePath).
|
|
|
|
To list all the available named templates, use 'swiftgen template list'.
|
|
"""
|
|
case .multipleTemplateOptions(let path, let name):
|
|
return "You need to choose EITHER a named template OR a template path. Found name '\(name)' and path '\(path)'"
|
|
}
|
|
}
|
|
}
|