diff --git a/CHANGELOG.md b/CHANGELOG.md index 981fb6b6..e77b1891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Fixed checking dictionary values for nil in `default` filter - Fixed comparing string variables with string literals, in Swift 4 string literals became `Substring` and thus couldn't be directly compared to strings. - Integer literals now resolve into Int values, not Float +- Fixed accessing properties of optional properties via reflection ## 0.10.1 diff --git a/Sources/Variable.swift b/Sources/Variable.swift index baa55948..5af97efd 100644 --- a/Sources/Variable.swift +++ b/Sources/Variable.swift @@ -187,11 +187,33 @@ extension Mirror { if result == nil { // go through inheritance chain to reach superclass properties return superclassMirror?.getValue(for: key) - } else if let result = result, String(describing: result) == "nil" { - // mirror returns non-nil value even for nil-containing properties - // so we have to check if its value is actually nil or not - return nil + } else if let result = result { + guard String(describing: result) != "nil" else { + // mirror returns non-nil value even for nil-containing properties + // so we have to check if its value is actually nil or not + return nil + } + if let result = (result as? AnyOptional)?.wrapped { + return result + } else { + return result + } } return result } } + +protocol AnyOptional { + var wrapped: Any? { get } +} + +extension Optional: AnyOptional { + var wrapped: Any? { + switch self { + case let .some(value): return value + case .none: return nil + } + } +} + + diff --git a/Tests/StencilTests/VariableSpec.swift b/Tests/StencilTests/VariableSpec.swift index 6dd78eea..6dad505e 100644 --- a/Tests/StencilTests/VariableSpec.swift +++ b/Tests/StencilTests/VariableSpec.swift @@ -26,6 +26,7 @@ fileprivate class WebSite { fileprivate class Blog: WebSite { let articles: [Article] = [Article(author: Person(name: "Kyle"))] + let featuring: Article? = Article(author: Person(name: "Jhon")) } func testVariable() { @@ -160,5 +161,11 @@ func testVariable() { try expect(result) == "blog.com" } + $0.it("can resolve optional variable property using reflection") { + let variable = Variable("blog.featuring.author.name") + let result = try variable.resolve(context) as? String + try expect(result) == "Jhon" + } + } }