From df24cf4071449ca858c23aadac442417fae07287 Mon Sep 17 00:00:00 2001 From: David Hardiman Date: Fri, 26 Apr 2019 12:09:00 +0100 Subject: [PATCH] Allow template to specify a default type --- Sources/Config/ConfigurationFile.swift | 32 ++++++++++++------- .../ConfigTests/ConfigurationFileTests.swift | 28 ++++++++++++++++ 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/Sources/Config/ConfigurationFile.swift b/Sources/Config/ConfigurationFile.swift index 5123aed..9cf5a55 100644 --- a/Sources/Config/ConfigurationFile.swift +++ b/Sources/Config/ConfigurationFile.swift @@ -26,12 +26,12 @@ struct Configuration { let properties: [String: Property] let childConfigurations: [String: Configuration] - init(config: [String: Any], referenceSource: [String: Any]?, customTypes: [CustomType]) { + init(config: [String: Any], referenceSource: [String: Any]?, customTypes: [CustomType], defaultType: PropertyType?) { properties = config.reduce([String: Property]()) { properties, pair in - return parseNextProperty(properties: properties, pair: pair, config: config, referenceSource: referenceSource, customTypes: customTypes) + return parseNextProperty(properties: properties, pair: pair, config: config, referenceSource: referenceSource, customTypes: customTypes, defaultType: defaultType) } childConfigurations = config.reduce([String: Configuration]()) { configurations, pair in - return parseNextConfiguration(configurations: configurations, pair: pair, config: config, referenceSource: referenceSource, customTypes: customTypes) + return parseNextConfiguration(configurations: configurations, pair: pair, config: config, referenceSource: referenceSource, customTypes: customTypes, defaultType: defaultType) } } @@ -90,10 +90,12 @@ extension String { } } -func parseNextProperty(properties: [String: Property], pair: (key: String, value: Any), config: [String: Any], referenceSource: [String: Any]?, customTypes: [CustomType]) -> [String: Property] { - guard let dict = pair.value as? [String: Any], - let typeHintValue = dict["type"] as? String else { - return properties +func parseNextProperty(properties: [String: Property], pair: (key: String, value: Any), config: [String: Any], referenceSource: [String: Any]?, customTypes: [CustomType], defaultType: PropertyType?) -> [String: Property] { + guard let dict = pair.value as? [String: Any] else { + return properties + } + guard let typeHintValue = (dict["type"] as? String ?? defaultType?.rawValue) else { + return properties } var copy = properties if let typeHint = PropertyType(rawValue: typeHintValue) { @@ -147,12 +149,12 @@ private func referenceDict(for key: String, from config: [String: Any], or refer return referenceSource?[key] as? [String: Any] } -func parseNextConfiguration(configurations: [String: Configuration], pair: (key: String, value: Any), config: [String: Any], referenceSource: [String: Any]?, customTypes: [CustomType]) -> [String: Configuration] { - guard let dict = pair.value as? [String: Any], dict["type"] == nil, pair.key != "template" else { +func parseNextConfiguration(configurations: [String: Configuration], pair: (key: String, value: Any), config: [String: Any], referenceSource: [String: Any]?, customTypes: [CustomType], defaultType: PropertyType?) -> [String: Configuration] { + guard let dict = pair.value as? [String: Any], dict["defaultValue"] == nil, pair.key != "template" else { return configurations } var copy = configurations - copy[pair.key] = Configuration(config: dict, referenceSource: referenceSource, customTypes: customTypes) + copy[pair.key] = Configuration(config: dict, referenceSource: referenceSource, customTypes: customTypes, defaultType: defaultType) return copy } @@ -171,6 +173,8 @@ struct ConfigurationFile: Template { let customTypes: [CustomType] + let defaultType: PropertyType? + init(config: [String: Any], name: String, scheme: String, source: URL) throws { self.scheme = scheme self.name = name @@ -181,6 +185,12 @@ struct ConfigurationFile: Template { self.customTypes = CustomType.typeArray(from: self.template) + if let defaultType = template?["defaultType"] as? String { + self.defaultType = PropertyType(rawValue: defaultType) + } else { + self.defaultType = nil + } + var referenceSource: [String: Any]? if let referenceSourceFileName = template?["referenceSource"] as? String { let referenceSourceURL = source.appendingPathComponent(referenceSourceFileName).appendingPathExtension("config") @@ -189,7 +199,7 @@ struct ConfigurationFile: Template { iv = try IV(dict: config) - let root = Configuration(config: config, referenceSource: referenceSource, customTypes: customTypes) + let root = Configuration(config: config, referenceSource: referenceSource, customTypes: customTypes, defaultType: defaultType) var parsedProperties = root.properties encryptionKey = parsedProperties.values.compactMap { $0 as? ConfigurationProperty } diff --git a/Tests/ConfigTests/ConfigurationFileTests.swift b/Tests/ConfigTests/ConfigurationFileTests.swift index fa754ad..569c66c 100644 --- a/Tests/ConfigTests/ConfigurationFileTests.swift +++ b/Tests/ConfigTests/ConfigurationFileTests.swift @@ -287,6 +287,26 @@ class ConfigurationFileTests: XCTestCase { expect(config.description).to(equal(expectedOutput)) } + func testItUsesADefaultTypeIfOneIsNotSpecified() throws { + let config = try ConfigurationFile(config: configurationWithDefaultType, name: "Test", scheme: "any", source: URL(fileURLWithPath: "/")) + let expectedOutput = """ + /* Test.swift auto-generated from any */ + + import Foundation + + // swiftlint:disable force_unwrapping type_body_length file_length superfluous_disable_command + public enum Test { + public static let property: String = #"test value"# + + public static let schemeName: String = #"any"# + } + + // swiftlint:enable force_unwrapping type_body_length file_length superfluous_disable_command + + """ + expect(config.description).to(equal(expectedOutput)) + } + func givenAConfigDictionary(withTemplate template: [String: Any]? = nil) -> [String: Any] { var dictionary: [String: Any] = [:] dictionary["template"] = template @@ -420,3 +440,11 @@ private let configurationWithCustomType: [String: Any] = [ ] ] +private let configurationWithDefaultType: [String: Any] = [ + "template": [ + "defaultType": "String" + ], + "property": [ + "defaultValue": "test value" + ] +]