Skip to content

Commit

Permalink
dynamic member lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyapuchka authored and djbe committed Jul 27, 2022
1 parent a6d0428 commit f19d254
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 1 deletion.
14 changes: 14 additions & 0 deletions Sources/DynamicMemberLookup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// Implement this type for your own types that support `@dynamicMemberLookup`
public protocol DynamicMemberLookup {
/// Get a value for a given `String` key
subscript(dynamicMember member: String) -> Any? { get }
}

public extension DynamicMemberLookup where Self: RawRepresentable {
subscript(dynamicMember member: String) -> Any? {
switch member {
case "rawValue": return rawValue
default: return nil
}
}
}
2 changes: 2 additions & 0 deletions Sources/Variable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public struct Variable: Equatable, Resolvable {
return object.value(forKey: bit)
}
#endif
} else if let value = context as? DynamicMemberLookup {
return value[dynamicMember: bit]
} else if let value = context {
return Mirror(reflecting: value).getValue(for: bit)
}
Expand Down
31 changes: 30 additions & 1 deletion Tests/StencilTests/VariableSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ private class Blog: WebSite {
let featuring: Article? = Article(author: Person(name: "Jhon"))
}

@dynamicMemberLookup
private struct DynamicStruct: DynamicMemberLookup {
subscript(dynamicMember member: String) -> Any? {
member == "test" ? "this is a dynamic response" : nil
}
}

private enum DynamicEnum: String, DynamicMemberLookup {
case someValue = "this is raw value"
}

final class VariableTests: XCTestCase {
let context: Context = {
let ext = Extension()
Expand All @@ -49,7 +60,11 @@ final class VariableTests: XCTestCase {
],
"article": Article(author: Person(name: "Kyle")),
"blog": Blog(),
"tuple": (one: 1, two: 2)
"tuple": (one: 1, two: 2),
"dynamic": [
"enum": DynamicEnum.someValue,
"struct": DynamicStruct()
]
], environment: environment)
#if os(OSX)
context["object"] = Object()
Expand Down Expand Up @@ -158,6 +173,20 @@ final class VariableTests: XCTestCase {
}
}

func testDynamicMemberLookup() {
it("can resolve dynamic member lookup") {
let variable = Variable("dynamic.struct.test")
let result = try variable.resolve(self.context) as? String
try expect(result) == "this is a dynamic response"
}

it("can resolve dynamic enum rawValue") {
let variable = Variable("dynamic.enum.rawValue")
let result = try variable.resolve(self.context) as? String
try expect(result) == "this is raw value"
}
}

func testReflection() {
it("can resolve a property with reflection") {
let variable = Variable("article.author.name")
Expand Down

0 comments on commit f19d254

Please sign in to comment.