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

Support configuration property. #33

Merged
merged 7 commits into from
Dec 16, 2018
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
50 changes: 40 additions & 10 deletions Binary/Sources/Deli/Command/BuildCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ struct BuildCommand: CommandProtocol {

let configuration = Configuration()
let configure: Config
let properties = CommandLine.get(forKey: "property")
if let project = options.project {
guard let config = configuration.getConfig(project: project, scheme: options.scheme, output: options.output) else {
guard let config = configuration.getConfig(project: project, scheme: options.scheme, target: options.target, output: options.output, properties: properties) else {
return .failure(.failedToLoadConfigFile)
}
configure = config
Expand Down Expand Up @@ -51,7 +52,7 @@ struct BuildCommand: CommandProtocol {
outputFile = configuration.getOutputPath(info: info)
className = configuration.getClassName(info: info)
}

guard let sourceFiles = try? configuration.getSourceList(info: info) else { continue }
if sourceFiles.count == 0 {
Logger.log(.warn("No source files for processing.", nil))
Expand All @@ -61,32 +62,41 @@ struct BuildCommand: CommandProtocol {
Logger.log(.debug(" - \(source)"))
}

let propertyParser = PropertyParser()
let parser = Parser([
ComponentParser(),
ConfigurationParser(),
AutowiredParser(),
LazyAutowiredParser(),
AutowiredFactoryParser(),
LazyAutowiredFactoryParser(),
InjectParser()
InjectParser(),
InjectPropertyParser(),
ConfigPropertyParser()
])
let corrector = Corrector([
QualifierByCorrector(parser: parser, propertyParser: propertyParser),
QualifierCorrector(parser: parser),
ScopeCorrector(parser: parser),
NotImplementCorrector(parser: parser)
NotImplementCorrector(parser: parser),
ConfigPropertyCorrector(parser: parser, propertyParser: propertyParser)
])
let validator = Validator([
FactoryReferenceValidator(parser: parser),
CircularDependencyValidator(parser: parser)
CircularDependencyValidator(parser: parser),
InjectPropertyValidator(parser: parser, propertyParser: propertyParser)
])

let propertyFiles = configuration.getPropertyList(info: info, properties: properties)
propertyParser.load(propertyFiles)

do {
let results = try validator.run(
try corrector.run(
try parser.run(sourceFiles)
)
)
let outputData = try SourceGenerator(className: className, results: results).generate()
let outputData = try SourceGenerator(className: className, results: results, properties: propertyParser.properties).generate()
let url = URL(fileURLWithPath: outputFile)

var isDirectory: ObjCBool = false
Expand All @@ -112,13 +122,23 @@ struct BuildOptions: OptionsProtocol {
let configFile: String?
let project: String?
let scheme: String?
let target: String?
let output: String?
let properties: String?
let isVerbose: Bool

static func create(configFile: String?) -> (_ project: String?) -> (_ scheme: String?) -> (_ output: String?) -> (_ isVerbose: Bool) -> BuildOptions {
return { project in { scheme in { output in { isVerbose in
self.init(configFile: configFile, project: project, scheme: scheme, output: output, isVerbose: isVerbose)
}}}}
static func create(configFile: String?) -> (_ project: String?) -> (_ scheme: String?) -> (_ target: String?) -> (_ output: String?) -> (_ properties: String?) -> (_ isVerbose: Bool) -> BuildOptions {
return { project in { scheme in { target in { output in { properties in { isVerbose in
self.init(
configFile: configFile,
project: project,
scheme: scheme,
target: target,
output: output,
properties: properties,
isVerbose: isVerbose
)
}}}}}}
}

static func evaluate(_ mode: CommandMode) -> Result<BuildOptions, CommandantError<CommandError>> {
Expand All @@ -138,11 +158,21 @@ struct BuildOptions: OptionsProtocol {
defaultValue: nil,
usage: "using build scheme name"
)
<*> mode <| Option(
key: "target",
defaultValue: nil,
usage: "using build target name"
)
<*> mode <| Option(
key: "output",
defaultValue: nil,
usage: "the path of output file"
)
<*> mode <| Option(
key: "property",
defaultValue: nil,
usage: "the path of property file"
)
<*> mode <| Option(
key: "verbose",
defaultValue: false,
Expand Down
46 changes: 34 additions & 12 deletions Binary/Sources/Deli/Command/GenerateCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ struct GenerateCommand: CommandProtocol {

let configuration = Configuration()
let configure: Config
let properties = CommandLine.get(forKey: "property")
if let project = options.project {
guard let config = configuration.getConfig(project: project, scheme: options.scheme, output: nil) else {
guard let config = configuration.getConfig(project: project, scheme: options.scheme, target: options.target, output: nil, properties: properties) else {
return .failure(.failedToLoadConfigFile)
}
configure = config
Expand All @@ -43,7 +44,7 @@ struct GenerateCommand: CommandProtocol {

Logger.log(.info("Set Target `\(target)`"))
let className = configuration.getClassName(info: info)

guard let sourceFiles = try? configuration.getSourceList(info: info) else { continue }
if sourceFiles.count == 0 {
Logger.log(.warn("Empty source files.", nil))
Expand All @@ -53,25 +54,34 @@ struct GenerateCommand: CommandProtocol {
Logger.log(.debug(" - \(source)"))
}

let propertyParser = PropertyParser()
let parser = Parser([
ComponentParser(),
ConfigurationParser(),
AutowiredParser(),
LazyAutowiredParser(),
AutowiredFactoryParser(),
LazyAutowiredFactoryParser(),
InjectParser()
InjectParser(),
InjectPropertyParser(),
ConfigPropertyParser()
])
let corrector = Corrector([
QualifierByCorrector(parser: parser, propertyParser: propertyParser),
QualifierCorrector(parser: parser),
ScopeCorrector(parser: parser),
NotImplementCorrector(parser: parser)
NotImplementCorrector(parser: parser),
ConfigPropertyCorrector(parser: parser, propertyParser: propertyParser)
])
let validator = Validator([
FactoryReferenceValidator(parser: parser),
CircularDependencyValidator(parser: parser)
CircularDependencyValidator(parser: parser),
InjectPropertyValidator(parser: parser, propertyParser: propertyParser)
])

let propertyFiles = configuration.getPropertyList(info: info, properties: properties)
propertyParser.load(propertyFiles)

do {
let results = try validator.run(
try corrector.run(
Expand All @@ -82,11 +92,11 @@ struct GenerateCommand: CommandProtocol {
let outputData: String
switch options.type {
case "graph", "html":
outputData = try GraphGenerator(results: results).generate()
outputData = try GraphGenerator(results: results, properties: propertyParser.properties).generate()
case "code", "swift":
outputData = try SourceGenerator(className: className, results: results).generate()
outputData = try SourceGenerator(className: className, results: results, properties: propertyParser.properties).generate()
case "raw":
outputData = try RawGenerator(results: results).generate()
outputData = try RawGenerator(results: results, properties: propertyParser.properties).generate()
default:
throw CommandError.unacceptableType
}
Expand Down Expand Up @@ -118,13 +128,15 @@ struct GenerateOptions: OptionsProtocol {
let isVerbose: Bool
let project: String?
let scheme: String?
let target: String?
let output: String?
let properties: String?
let type: String

static func create(configFile: String?) -> (_ isVerbose: Bool) -> (_ project: String?) -> (_ scheme: String?) -> (_ output: String?) -> (_ type: String) -> GenerateOptions {
return { isVerbose in { project in { scheme in { output in { type in
self.init(configFile: configFile, isVerbose: isVerbose, project: project, scheme: scheme, output: output, type: type)
}}}}}
static func create(configFile: String?) -> (_ isVerbose: Bool) -> (_ project: String?) -> (_ scheme: String?) -> (_ target: String?) -> (_ output: String?) -> (_ properties: String?) -> (_ type: String) -> GenerateOptions {
return { isVerbose in { project in { scheme in { target in { output in { properties in { type in
self.init(configFile: configFile, isVerbose: isVerbose, project: project, scheme: scheme, target: target, output: output, properties: properties, type: type)
}}}}}}}
}

static func evaluate(_ mode: CommandMode) -> Result<GenerateOptions, CommandantError<CommandError>> {
Expand All @@ -149,11 +161,21 @@ struct GenerateOptions: OptionsProtocol {
defaultValue: nil,
usage: "using build scheme name"
)
<*> mode <| Option(
key: "target",
defaultValue: nil,
usage: "using build target name"
)
<*> mode <| Option(
key: "output",
defaultValue: nil,
usage: "the path of output file"
)
<*> mode <| Option(
key: "property",
defaultValue: nil,
usage: "the path of property file"
)
<*> mode <| Option(
key: "type",
defaultValue: "code",
Expand Down
38 changes: 30 additions & 8 deletions Binary/Sources/Deli/Command/ValidateCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ struct ValidateCommand: CommandProtocol {

let configuration = Configuration()
let configure: Config
let properties = CommandLine.get(forKey: "property")
if let project = options.project {
guard let config = configuration.getConfig(project: project, scheme: options.scheme, output: nil) else {
guard let config = configuration.getConfig(project: project, scheme: options.scheme, target: options.target, output: nil, properties: properties) else {
return .failure(.failedToLoadConfigFile)
}
configure = config
Expand Down Expand Up @@ -50,25 +51,34 @@ struct ValidateCommand: CommandProtocol {
Logger.log(.debug(" - \(source)"))
}

let propertyParser = PropertyParser()
let parser = Parser([
ComponentParser(),
ConfigurationParser(),
AutowiredParser(),
LazyAutowiredParser(),
AutowiredFactoryParser(),
LazyAutowiredFactoryParser(),
InjectParser()
InjectParser(),
InjectPropertyParser(),
ConfigPropertyParser()
])
let corrector = Corrector([
QualifierByCorrector(parser: parser, propertyParser: propertyParser),
QualifierCorrector(parser: parser),
ScopeCorrector(parser: parser),
NotImplementCorrector(parser: parser)
NotImplementCorrector(parser: parser),
ConfigPropertyCorrector(parser: parser, propertyParser: propertyParser)
])
let validator = Validator([
FactoryReferenceValidator(parser: parser),
CircularDependencyValidator(parser: parser)
CircularDependencyValidator(parser: parser),
InjectPropertyValidator(parser: parser, propertyParser: propertyParser)
])

let propertyFiles = configuration.getPropertyList(info: info, properties: properties)
propertyParser.load(propertyFiles)

do {
_ = try validator.run(
try corrector.run(
Expand All @@ -89,12 +99,14 @@ struct ValidateOptions: OptionsProtocol {
let configFile: String?
let project: String?
let scheme: String?
let target: String?
let properties: String?
let isVerbose: Bool

static func create(configFile: String?) -> (_ project: String?) -> (_ scheme: String?) -> (_ isVerbose: Bool) -> ValidateOptions {
return { project in { scheme in { isVerbose in
self.init(configFile: configFile, project: project, scheme: scheme, isVerbose: isVerbose)
}}}
static func create(configFile: String?) -> (_ project: String?) -> (_ scheme: String?) -> (_ target: String?) -> (_ properties: String?) -> (_ isVerbose: Bool) -> ValidateOptions {
return { project in { scheme in { target in { properties in { isVerbose in
self.init(configFile: configFile, project: project, scheme: scheme, target: target, properties: properties, isVerbose: isVerbose)
}}}}}
}

static func evaluate(_ mode: CommandMode) -> Result<ValidateOptions, CommandantError<CommandError>> {
Expand All @@ -114,6 +126,16 @@ struct ValidateOptions: OptionsProtocol {
defaultValue: nil,
usage: "using build scheme name"
)
<*> mode <| Option(
key: "target",
defaultValue: nil,
usage: "using build target name"
)
<*> mode <| Option(
key: "property",
defaultValue: nil,
usage: "the path of property file"
)
<*> mode <| Option(
key: "verbose",
defaultValue: false,
Expand Down
50 changes: 48 additions & 2 deletions Binary/Sources/Deli/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,10 @@ final class Configuration {
}
}
}
func getConfig(project: String, scheme: String?, output: String?) -> Config? {
func getConfig(project: String, scheme: String?, target: String?, output: String?, properties: [String]) -> Config? {
return Config(
target: [project],
config: [project: ConfigInfo(project: project, scheme: scheme, output: output)]
config: [project: ConfigInfo(project: project, scheme: scheme, target: target, output: output, properties: properties)]
)
}

Expand Down Expand Up @@ -287,6 +287,52 @@ final class Configuration {

return first + other
}
func getPropertyList(info: ConfigInfo, properties: [String]) -> [String] {
guard let baseURL = URL(string: basePath) else { return [] }

/// Find properties recursive
var propertyList: [String] = []
func findProperties(url: URL, target: [String]) {
var target = target

let urlPath = url.standardized.path.replacingOccurrences(of: "//", with: "/")

guard !target.isEmpty else {
if self.fileManager.fileExists(atPath: urlPath) {
propertyList.append(urlPath)
}
return
}

guard let path = target.popLast() else { return }
if path.contains("*") {
let newPath = url.appendingPathComponent(path)
.standardized.path
.replacingOccurrences(of: "/", with: "\\/")

let regex = newPath.split(separator: "*", omittingEmptySubsequences: false)
.map { "(\($0))" }
.joined(separator: "[^\\/]*").r!

let contents = (try? self.fileManager.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)) ?? []
for content in contents {
guard regex.findFirst(in: content.path) != nil else { continue }
findProperties(url: content, target: target)
}
} else {
findProperties(url: url.appendingPathComponent(path), target: target)
}
}

let properties = (info.properties + properties)
.map { $0.split(separator: "/").map { String($0) } }

for propertyPath in properties {
findProperties(url: baseURL, target: propertyPath.reversed())
}

return propertyList
}
func getSourceList(info: ConfigInfo) throws -> [String] {
/// Check if project file exists.
let projectFile = convertToProjectFile(info.project)
Expand Down
3 changes: 3 additions & 0 deletions Binary/Sources/Deli/Error/CorrectorError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
enum CorrectorError: Error {
case implementationNotFound
case ambiguousImplementation
case notFoundConfigurationProperty

var localizedDescription: String {
switch self {
case .implementationNotFound:
return "Not found implementation logic on dependency."
case .ambiguousImplementation:
return "Ambiguous implementation logic on dependency."
case .notFoundConfigurationProperty:
return "Not found configuration property."
}
}
}
Loading