Skip to content

Commit

Permalink
Merge pull request #152 from kylef/resolving-superclass-keys
Browse files Browse the repository at this point in the history
Added recursive resolution for superclass properties
  • Loading branch information
ilyapuchka authored Nov 30, 2017
2 parents 0017aee + a96fcff commit 9357df3
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 8 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@

## Master

### Enhancements

- Added support for resolving superclass properties for not-NSObject subclasses

### Bug Fixes

- Fixed rendering `{{ block.super }}` with several levels of inheritance


## 0.10.1

### Enhancements
Expand Down
23 changes: 16 additions & 7 deletions Sources/Variable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,9 @@ public struct Variable : Equatable, Resolvable {
current = object.value(forKey: bit)
#endif
} else if let value = current {
let mirror = Mirror(reflecting: value)
current = mirror.descendant(bit)

current = Mirror(reflecting: value).getValue(for: bit)
if current == nil {
return nil
// mirror returns non-nil value even for nil-containing properties
// so we have to check if its value is actually nil or not
} else if let current = current, String(describing: current) == "nil" {
return nil
}
} else {
return nil
Expand Down Expand Up @@ -179,3 +173,18 @@ func parseFilterComponents(token: String) -> (String, [Variable]) {
.map { Variable($0) }
return (name, variables)
}

extension Mirror {
func getValue(for key: String) -> Any? {
let result = descendant(key)
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
}
return result
}
}
32 changes: 31 additions & 1 deletion Tests/StencilTests/VariableSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import Spectre


#if os(OSX)
@objc class Object : NSObject {
@objc class Superclass: NSObject {
let name = "Foo"
}
@objc class Object : Superclass {
let title = "Hello World"
}
#endif
Expand All @@ -17,6 +20,13 @@ fileprivate struct Article {
let author: Person
}

fileprivate class WebSite {
let url: String = "blog.com"
}

fileprivate class Blog: WebSite {
let articles: [Article] = [Article(author: Person(name: "Kyle"))]
}

func testVariable() {
describe("Variable") {
Expand All @@ -35,6 +45,7 @@ func testVariable() {
#if os(OSX)
context["object"] = Object()
#endif
context["blog"] = Blog()

$0.it("can resolve a string literal with double quotes") {
let variable = Variable("\"name\"")
Expand Down Expand Up @@ -122,6 +133,25 @@ func testVariable() {
let result = try variable.resolve(context) as? String
try expect(result) == "Hello World"
}

$0.it("can resolve a superclass value via KVO") {
let variable = Variable("object.name")
let result = try variable.resolve(context) as? String
try expect(result) == "Foo"
}
#endif

$0.it("can resolve a value via reflection") {
let variable = Variable("blog.articles.0.author.name")
let result = try variable.resolve(context) as? String
try expect(result) == "Kyle"
}

$0.it("can resolve a superclass value via reflection") {
let variable = Variable("blog.url")
let result = try variable.resolve(context) as? String
try expect(result) == "blog.com"
}

}
}

0 comments on commit 9357df3

Please sign in to comment.