Skip to content

Commit

Permalink
Merge pull request #130 from unsignedapps/visiting-containers
Browse files Browse the repository at this point in the history
Repurposed `FlagVisitor.beginGroup` and split functionality.
  • Loading branch information
bok- authored Dec 12, 2024
2 parents 05b246c + 3037a04 commit d5d55a1
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 550 deletions.
80 changes: 77 additions & 3 deletions Sources/Vexil/Visitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,76 @@
/// Visitor pattern. Conform your type to this protocol and pass
/// it to ``FlagPole/walk(visitor:)`` or any container using
/// ``FlagContainer/walk(visitor:)``.
///
/// Walking always starts at a Container, and then walks the children of that container.
/// When one of the children is a group, a call to ``beginGroup(keyPath:wigwag:)`` is made before
/// descending into the group's container. That container will then call ``beginContainer(keyPath:container:)``
/// itself. You can use this to differentiate between the operations you are looking for.
///
/// # Example
///
/// Given the following flag hierarchy:
///
/// ```swift
/// @FlagContainer
/// struct TestFlags {
///
/// @Flag(...)
/// var topLevelFlag: Bool
///
/// @FlagGroup(...)
/// var subgroup: SubgroupFlags
///
/// }
///
/// @FlagContainer
/// struct SubgroupFlags {
///
/// @FlagGroup(...)
/// var doubleSubgroup: DoubleSubgroupFlags
///
/// }
///
/// @FlagContainer
/// struct DoubleSubgroupFlags {
///
/// @Flag(...)
/// var thirdLevelFlag: Bool
///
/// }
/// ```
///
/// You should expect to see the following callbacks:
///
/// ```swift
/// visitor.beginContainer("") // root
/// visitor.visitFlag("top-level-flag")
/// visitor.beginGroup("subgroup")
///
/// visitor.beginContainer("subgroup")
/// visitor.beginGroup("subgroup.double-subgroup")
///
/// visitor.beginContainer("subgroup.double-subgroup")
/// visitor.visitFlag("subgroup.double-subgroup.third-level-flag")
/// visitor.endContainer("subgroup.double-subgroup")
///
/// visitor.endGroup("subgroup.double-subgroup")
/// visitor.endContainer("subgroup")
///
/// visitor.endGroup("subgroup")
/// visitor.endContainer("") // root
/// ```
///
public protocol FlagVisitor {

/// Called when beginning to visit a new ``FlagGroup``
func beginGroup(keyPath: FlagKeyPath)
/// Called when beginning to walk within a ``FlagContainer``
func beginContainer(keyPath: FlagKeyPath, containerType: Any.Type)

/// Called when finished visiting a ``FlagContainer``.
func endContainer(keyPath: FlagKeyPath)

/// Called when about to descend into a new ``FlagGroup``
func beginGroup(keyPath: FlagKeyPath, wigwag: () -> FlagGroupWigwag<some FlagContainer>)

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

public extension FlagVisitor {

func beginGroup(keyPath: FlagKeyPath) {
func beginContainer(keyPath: FlagKeyPath, containerType: Any.Type) {
// Intentionally left blank
}

func endContainer(keyPath: FlagKeyPath) {
// Intentionally left blank
}

func beginGroup(keyPath: FlagKeyPath, wigwag: () -> FlagGroupWigwag<some FlagContainer>) {
// Intentionally left blank
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/VexilMacros/FlagContainerMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ extension FlagContainerMacro: ExtensionMacro {
// Flag Hierarchy Walking

try FunctionDeclSyntax("func walk(visitor: any FlagVisitor)") {
"visitor.beginGroup(keyPath: _flagKeyPath)"
"visitor.beginContainer(keyPath: _flagKeyPath, containerType: \(type).self)"
for variable in declaration.memberBlock.variables {
if let flag = variable.asFlag(in: context) {
flag.makeVisitExpression()
} else if let group = variable.asFlagGroup(in: context) {
group.makeVisitExpression()
}
}
"visitor.endGroup(keyPath: _flagKeyPath)"
"visitor.endContainer(keyPath: _flagKeyPath)"
}
.with(\.modifiers, declaration.modifiers.scopeSyntax)

Expand Down
23 changes: 19 additions & 4 deletions Sources/VexilMacros/FlagGroupMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,25 @@ public struct FlagGroupMacro {
"""
}

func makeVisitExpression() -> CodeBlockItemSyntax {
"""
\(raw: propertyName).walk(visitor: visitor)
"""
func makeVisitExpression() -> CodeBlockItemListSyntax {
.init {
"""
visitor.beginGroup(
keyPath: \(key),
wigwag: {
FlagGroupWigwag<\(type)>(
keyPath: \(key),
name: \(name ?? "nil"),
description: \(description ?? "nil"),
displayOption: \(displayOption ?? ".navigation"),
lookup: _flagLookup
)
}
)
"""
"\(raw: propertyName).walk(visitor: visitor)"
"visitor.endGroup(keyPath: \(key))"
}
}

}
Expand Down
Loading

0 comments on commit d5d55a1

Please sign in to comment.