Skip to content
Snippets Groups Projects
Commit e020b51a authored by Tobias Ullerich's avatar Tobias Ullerich
Browse files

Generate value setter method

parent d246e611
Branches
No related tags found
No related merge requests found
...@@ -8,20 +8,51 @@ ...@@ -8,20 +8,51 @@
import Foundation import Foundation
import SwiftSyntax import SwiftSyntax
struct ClassDeclaration { class ClassDeclaration {
let name: String let name: String
let variables: [String] let parents: [String]
let variables: [Variable]
var needsMethodOverride: Bool
init(name: String, parents: [String], variables: [Variable]) {
self.name = name
self.parents = parents
self.variables = variables
self.needsMethodOverride = false
}
}
class Variable {
let name: String
let type: String?
let optional: Bool?
let constant: Bool
let privateVisibility: Bool
let staticModifier: Bool
let hasAccessor: Bool
init(name: String, type: String?, optional: Bool?, constant: Bool, privateVisibility: Bool, staticModifier: Bool, hasAccessor: Bool) {
self.name = name
self.type = type
self.optional = optional
self.constant = constant
self.privateVisibility = privateVisibility
self.staticModifier = staticModifier
self.hasAccessor = hasAccessor
}
} }
class DeclarationCollector: SyntaxVisitor { class DeclarationCollector: SyntaxVisitor {
private(set) var classes: [ClassDeclaration] = [] private(set) var classes: [ClassDeclaration] = []
private var currentVariables: [String] = [] private var currentVariables: [Variable] = []
override func visitPost(_ node: ClassDeclSyntax) { override func visitPost(_ node: ClassDeclSyntax) {
let name = node.identifier.text.trimmingCharacters(in: .whitespacesAndNewlines) let name = node.identifier.text.trimmingCharacters(in: .whitespacesAndNewlines)
let inherences = node.inheritanceClause?.inheritedTypeCollection.map({ $0.typeName.description.trimmingCharacters(in: .whitespacesAndNewlines) }) ?? []
classes.append(ClassDeclaration(name: name, variables: currentVariables)) classes.append(ClassDeclaration(name: name, parents: inherences, variables: currentVariables))
currentVariables = [] currentVariables = []
} }
...@@ -29,7 +60,18 @@ class DeclarationCollector: SyntaxVisitor { ...@@ -29,7 +60,18 @@ class DeclarationCollector: SyntaxVisitor {
for child: PatternBindingSyntax in node.bindings { for child: PatternBindingSyntax in node.bindings {
if let parent = child.context as? VariableDeclSyntax, parent.context is ClassDeclSyntax { if let parent = child.context as? VariableDeclSyntax, parent.context is ClassDeclSyntax {
let name = child.pattern.description.trimmingCharacters(in: .whitespacesAndNewlines) let name = child.pattern.description.trimmingCharacters(in: .whitespacesAndNewlines)
currentVariables.append(name) let type = child.typeAnnotation?.type.description.trimmingCharacters(in: .whitespacesAndNewlines)
let constant = parent.letOrVarKeyword.text.trimmingCharacters(in: .whitespacesAndNewlines) == "let"
let privateVisibility = parent.modifiers?.map({ $0.name.text }).contains("private") ?? false
let staticModifier = parent.modifiers?.map({ $0.name.text }).contains("static") ?? false
let hasAccessor = child.accessor != nil
if type == nil {
print("Fail to observe type for \(name)")
}
currentVariables.append(Variable(name: name, type: type?.replacingOccurrences(of: "?", with: ""), optional: type?.hasSuffix("?") , constant: constant, privateVisibility: privateVisibility, staticModifier: staticModifier, hasAccessor: hasAccessor))
} }
} }
return .skipChildren return .skipChildren
......
...@@ -31,6 +31,12 @@ struct SwiftMetaModelGenerator: ParsableCommand ...@@ -31,6 +31,12 @@ struct SwiftMetaModelGenerator: ParsableCommand
classes = try processFile(file: inputPath) classes = try processFile(file: inputPath)
} }
for clazz in classes {
if clazz.parents.contains(where: { classes.map(\.name).contains($0) }) {
clazz.needsMethodOverride = true
}
}
let context = [ let context = [
"classes": classes "classes": classes
] ]
......
...@@ -8,10 +8,29 @@ import Foundation ...@@ -8,10 +8,29 @@ import Foundation
// swiftlint:disable attributes file_length vertical_whitespace_closing_braces // swiftlint:disable attributes file_length vertical_whitespace_closing_braces
// swiftlint:disable identifier_name line_length type_body_length // swiftlint:disable identifier_name line_length type_body_length
{% for class in classes %} {% for class in classes %}
class {{class.name}}_ { class {{class.name}}_
{
{% for variable in class.variables %} {% for variable in class.variables %}
static let {{ variable }}: String = "{{ variable }}" static let {{ variable.name }}: String = "{{ variable.name }}"
{% endfor %} {% endfor %}
} }
extension {{class.name}}
{
@objc {% if class.needsMethodOverride %} override {% endif %} func setValueByKey(key: String, value: Any?)
{
switch key {
{% for variable in class.variables %}
{% if not variable.constant and not variable.privateVisibility and not variable.staticModifier and not variable.hasAccessor %}
case "{{variable.name}}":
self.{{ variable.name }} = value {% if variable.optional %} as? {% else %} as! {% endif %} {{ variable.type }}
{% endif %}
{% endfor %}
default:
fatalError("Cannot set value for key \(key)")
}
}
}
{% endfor %} {% endfor %}
// swiftlint:enable identifier_name line_length type_body_length // swiftlint:enable identifier_name line_length type_body_length
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment