Skip to content

Commit d5d55a1

Browse files
authored
Merge pull request #130 from unsignedapps/visiting-containers
Repurposed `FlagVisitor.beginGroup` and split functionality.
2 parents 05b246c + 3037a04 commit d5d55a1

File tree

6 files changed

+275
-550
lines changed

6 files changed

+275
-550
lines changed

Sources/Vexil/Visitor.swift

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,76 @@
1515
/// Visitor pattern. Conform your type to this protocol and pass
1616
/// it to ``FlagPole/walk(visitor:)`` or any container using
1717
/// ``FlagContainer/walk(visitor:)``.
18+
///
19+
/// Walking always starts at a Container, and then walks the children of that container.
20+
/// When one of the children is a group, a call to ``beginGroup(keyPath:wigwag:)`` is made before
21+
/// descending into the group's container. That container will then call ``beginContainer(keyPath:container:)``
22+
/// itself. You can use this to differentiate between the operations you are looking for.
23+
///
24+
/// # Example
25+
///
26+
/// Given the following flag hierarchy:
27+
///
28+
/// ```swift
29+
/// @FlagContainer
30+
/// struct TestFlags {
31+
///
32+
/// @Flag(...)
33+
/// var topLevelFlag: Bool
34+
///
35+
/// @FlagGroup(...)
36+
/// var subgroup: SubgroupFlags
37+
///
38+
/// }
39+
///
40+
/// @FlagContainer
41+
/// struct SubgroupFlags {
42+
///
43+
/// @FlagGroup(...)
44+
/// var doubleSubgroup: DoubleSubgroupFlags
45+
///
46+
/// }
47+
///
48+
/// @FlagContainer
49+
/// struct DoubleSubgroupFlags {
50+
///
51+
/// @Flag(...)
52+
/// var thirdLevelFlag: Bool
53+
///
54+
/// }
55+
/// ```
56+
///
57+
/// You should expect to see the following callbacks:
58+
///
59+
/// ```swift
60+
/// visitor.beginContainer("") // root
61+
/// visitor.visitFlag("top-level-flag")
62+
/// visitor.beginGroup("subgroup")
63+
///
64+
/// visitor.beginContainer("subgroup")
65+
/// visitor.beginGroup("subgroup.double-subgroup")
66+
///
67+
/// visitor.beginContainer("subgroup.double-subgroup")
68+
/// visitor.visitFlag("subgroup.double-subgroup.third-level-flag")
69+
/// visitor.endContainer("subgroup.double-subgroup")
70+
///
71+
/// visitor.endGroup("subgroup.double-subgroup")
72+
/// visitor.endContainer("subgroup")
73+
///
74+
/// visitor.endGroup("subgroup")
75+
/// visitor.endContainer("") // root
76+
/// ```
77+
///
1878
public protocol FlagVisitor {
1979

20-
/// Called when beginning to visit a new ``FlagGroup``
21-
func beginGroup(keyPath: FlagKeyPath)
80+
/// Called when beginning to walk within a ``FlagContainer``
81+
func beginContainer(keyPath: FlagKeyPath, containerType: Any.Type)
82+
83+
/// Called when finished visiting a ``FlagContainer``.
84+
func endContainer(keyPath: FlagKeyPath)
85+
86+
/// Called when about to descend into a new ``FlagGroup``
87+
func beginGroup(keyPath: FlagKeyPath, wigwag: () -> FlagGroupWigwag<some FlagContainer>)
2288

2389
/// Called when finished visiting a ``FlagGroup``
2490
func endGroup(keyPath: FlagKeyPath)
@@ -49,7 +115,15 @@ public protocol FlagVisitor {
49115

50116
public extension FlagVisitor {
51117

52-
func beginGroup(keyPath: FlagKeyPath) {
118+
func beginContainer(keyPath: FlagKeyPath, containerType: Any.Type) {
119+
// Intentionally left blank
120+
}
121+
122+
func endContainer(keyPath: FlagKeyPath) {
123+
// Intentionally left blank
124+
}
125+
126+
func beginGroup(keyPath: FlagKeyPath, wigwag: () -> FlagGroupWigwag<some FlagContainer>) {
53127
// Intentionally left blank
54128
}
55129

Sources/VexilMacros/FlagContainerMacro.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,15 @@ extension FlagContainerMacro: ExtensionMacro {
9292
// Flag Hierarchy Walking
9393

9494
try FunctionDeclSyntax("func walk(visitor: any FlagVisitor)") {
95-
"visitor.beginGroup(keyPath: _flagKeyPath)"
95+
"visitor.beginContainer(keyPath: _flagKeyPath, containerType: \(type).self)"
9696
for variable in declaration.memberBlock.variables {
9797
if let flag = variable.asFlag(in: context) {
9898
flag.makeVisitExpression()
9999
} else if let group = variable.asFlagGroup(in: context) {
100100
group.makeVisitExpression()
101101
}
102102
}
103-
"visitor.endGroup(keyPath: _flagKeyPath)"
103+
"visitor.endContainer(keyPath: _flagKeyPath)"
104104
}
105105
.with(\.modifiers, declaration.modifiers.scopeSyntax)
106106

Sources/VexilMacros/FlagGroupMacro.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,25 @@ public struct FlagGroupMacro {
6969
"""
7070
}
7171

72-
func makeVisitExpression() -> CodeBlockItemSyntax {
73-
"""
74-
\(raw: propertyName).walk(visitor: visitor)
75-
"""
72+
func makeVisitExpression() -> CodeBlockItemListSyntax {
73+
.init {
74+
"""
75+
visitor.beginGroup(
76+
keyPath: \(key),
77+
wigwag: {
78+
FlagGroupWigwag<\(type)>(
79+
keyPath: \(key),
80+
name: \(name ?? "nil"),
81+
description: \(description ?? "nil"),
82+
displayOption: \(displayOption ?? ".navigation"),
83+
lookup: _flagLookup
84+
)
85+
}
86+
)
87+
"""
88+
"\(raw: propertyName).walk(visitor: visitor)"
89+
"visitor.endGroup(keyPath: \(key))"
90+
}
7691
}
7792

7893
}

0 commit comments

Comments
 (0)