1313import SwiftDiagnostics
1414import SwiftSyntax
1515
16+ /// Describes all of the #if/#elseif/#else clauses within the given syntax node,
17+ /// indicating their active state. This operation will recurse into all
18+ /// clauses to indicate regions of active / inactive / unparsed code.
19+ ///
20+ /// For example, given code like the following:
21+ /// #if DEBUG
22+ /// #if A
23+ /// func f()
24+ /// #elseif B
25+ /// func g()
26+ /// #elseif compiler(>= 12.0)
27+ /// please print the number after 41
28+ /// #endif
29+ /// #else
30+ /// #endif
31+ ///
32+ /// If the configuration options `DEBUG` and `B` are provided, but `A` is not,
33+ /// and the compiler version is less than 12.0, the results will be contain:
34+ /// - Active region for the `#if DEBUG`.
35+ /// - Inactive region for the `#if A`.
36+ /// - Active region for the `#elseif B`.
37+ /// - Unparsed region for the `#elseif compiler(>= 12.0)`.
38+ /// - Inactive region for the final `#else`.
39+ public struct ConfiguredRegions {
40+ let regions : [ Element ]
41+
42+ /// The set of diagnostics produced when evaluating the configured regions.
43+ public let diagnostics : [ Diagnostic ]
44+
45+ /// Determine whether the given syntax node is active within the configured
46+ /// regions.
47+ public func isActive( _ node: some SyntaxProtocol ) -> IfConfigRegionState {
48+ var currentState : IfConfigRegionState = . active
49+ for (ifClause, state) in regions {
50+ if node. position < ifClause. position {
51+ return currentState
52+ }
53+
54+ if node. position <= ifClause. endPosition {
55+ currentState = state
56+ }
57+ }
58+
59+ return currentState
60+ }
61+ }
62+
63+ extension ConfiguredRegions : RandomAccessCollection {
64+ public typealias Element = ( IfConfigClauseSyntax , IfConfigRegionState )
65+ public var startIndex : Int { regions. startIndex }
66+ public var endIndex : Int { regions. endIndex }
67+
68+ public subscript( index: Int ) -> Element {
69+ regions [ index]
70+ }
71+ }
72+
1673extension SyntaxProtocol {
1774 /// Find all of the #if/#elseif/#else clauses within the given syntax node,
1875 /// indicating their active state. This operation will recurse into all
@@ -39,10 +96,13 @@ extension SyntaxProtocol {
3996 /// - Inactive region for the final `#else`.
4097 public func configuredRegions(
4198 in configuration: some BuildConfiguration
42- ) -> [ ( IfConfigClauseSyntax , IfConfigRegionState ) ] {
99+ ) -> ConfiguredRegions {
43100 let visitor = ConfiguredRegionVisitor ( configuration: configuration)
44101 visitor. walk ( self )
45- return visitor. regions
102+ return ConfiguredRegions (
103+ regions: visitor. regions,
104+ diagnostics: visitor. diagnostics
105+ )
46106 }
47107}
48108
0 commit comments