@@ -25,20 +25,21 @@ extension SyntaxProtocol {
25
25
}
26
26
}
27
27
28
+ /// Provide common functionality for specialized scope implementatations.
28
29
protocol Scope {
30
+ /// The parent of this scope.
29
31
var parent : Scope ? { get }
30
32
33
+ /// Syntax node that introduces this protocol.
31
34
var sourceSyntax : SyntaxProtocol { get }
32
35
36
+ /// Returns the declaration `name` refers to at a particular syntax node location.
33
37
func getDeclarationFor( name: String , at syntax: SyntaxProtocol ) -> Syntax ?
34
38
}
35
39
36
40
extension Scope {
37
- var parent : Scope ? {
38
- getParentScope ( forSyntax: sourceSyntax)
39
- }
40
-
41
- private func getParentScope( forSyntax syntax: SyntaxProtocol ? ) -> Scope ? {
41
+ /// Recursively walks up syntax tree and finds the closest scope other than this scope.
42
+ func getParentScope( forSyntax syntax: SyntaxProtocol ? ) -> Scope ? {
42
43
if let lookedUpScope = syntax? . scope, lookedUpScope. sourceSyntax. id == syntax? . id {
43
44
return getParentScope ( forSyntax: sourceSyntax. parent)
44
45
} else {
@@ -48,42 +49,35 @@ extension Scope {
48
49
49
50
// MARK: - lookupLabeledStmts
50
51
52
+ /// Given syntax node position, returns all available labeled statements.
51
53
func lookupLabeledStmts( at syntax: SyntaxProtocol ) -> [ LabeledStmtSyntax ] {
52
- var result = [ LabeledStmtSyntax] ( )
53
- lookupLabeledStmtsHelper ( at: syntax. parent, accumulator: & result)
54
- return result
54
+ return lookupLabeledStmtsHelper ( at: syntax. parent, accumulator: [ ] )
55
55
}
56
56
57
- private func lookupLabeledStmtsHelper( at syntax: Syntax ? , accumulator: inout [ LabeledStmtSyntax ] ) {
58
- guard let syntax, !syntax. is ( MemberBlockSyntax . self) else { return }
57
+ /// Helper method to recursively collect labeled statements from the syntax node's parents.
58
+ private func lookupLabeledStmtsHelper( at syntax: Syntax ? , accumulator: [ LabeledStmtSyntax ] ) -> [ LabeledStmtSyntax ] {
59
+ guard let syntax, !syntax. is ( MemberBlockSyntax . self) else { return accumulator }
59
60
if let labeledStmtSyntax = syntax. as ( LabeledStmtSyntax . self) {
60
- accumulator. append ( labeledStmtSyntax)
61
- lookupLabeledStmtsHelper ( at: labeledStmtSyntax. parent, accumulator: & accumulator)
61
+ return lookupLabeledStmtsHelper ( at: labeledStmtSyntax. parent, accumulator: accumulator + [ labeledStmtSyntax] )
62
62
} else {
63
- lookupLabeledStmtsHelper ( at: syntax. parent, accumulator: & accumulator)
63
+ return lookupLabeledStmtsHelper ( at: syntax. parent, accumulator: accumulator)
64
64
}
65
65
}
66
66
67
67
// MARK: - lookupFallthroughSourceAndDest
68
68
69
- func lookupFallthroughSourceAndDest( at syntax: SyntaxProtocol ) -> ( SwitchCaseSyntax ? , SwitchCaseSyntax ? ) {
70
- guard let originalSwitchCase = lookupClosestSwitchCaseSyntaxAncestor ( at: syntax) else { return ( nil , nil ) }
69
+ /// Given syntax node position, returns the current switch case and it's fallthrough destination.
70
+ func lookupFallthroughSourceAndDestination( at syntax: SyntaxProtocol ) -> ( SwitchCaseSyntax ? , SwitchCaseSyntax ? ) {
71
+ guard let originalSwitchCase = syntax. ancestorOrSelf ( mapping: { $0. as ( SwitchCaseSyntax . self) } ) else {
72
+ return ( nil , nil )
73
+ }
71
74
72
75
let nextSwitchCase = lookupNextSwitchCase ( at: originalSwitchCase)
73
76
74
77
return ( originalSwitchCase, nextSwitchCase)
75
78
}
76
79
77
- private func lookupClosestSwitchCaseSyntaxAncestor( at syntax: SyntaxProtocol ? ) -> SwitchCaseSyntax ? {
78
- guard let syntax else { return nil }
79
-
80
- if let switchCaseSyntax = syntax. as ( SwitchCaseSyntax . self) {
81
- return switchCaseSyntax
82
- } else {
83
- return lookupClosestSwitchCaseSyntaxAncestor ( at: syntax. parent)
84
- }
85
- }
86
-
80
+ /// Given a switch case, returns the case that follows according to the parent.
87
81
private func lookupNextSwitchCase( at switchCaseSyntax: SwitchCaseSyntax ) -> SwitchCaseSyntax ? {
88
82
guard let switchCaseListSyntax = switchCaseSyntax. parent? . as ( SwitchCaseListSyntax . self) else { return nil }
89
83
@@ -104,30 +98,32 @@ extension Scope {
104
98
105
99
// MARK: - lookupCatchNode
106
100
101
+ /// Given syntax node position, returns the closest ancestor catch node.
107
102
func lookupCatchNode( at syntax: Syntax ) -> Syntax ? {
108
103
return lookupCatchNodeHelper ( at: syntax, traversedCatchClause: false )
109
104
}
110
105
106
+ /// Given syntax node location, finds where an error could be caught. If set to `true`, `traverseCatchClause`lookup will skip the next do statement.
111
107
private func lookupCatchNodeHelper( at syntax: Syntax ? , traversedCatchClause: Bool ) -> Syntax ? {
112
108
guard let syntax else { return nil }
113
109
114
- switch syntax. syntaxNodeType {
115
- case is DoStmtSyntax . Type :
110
+ switch syntax. as ( SyntaxEnum . self ) {
111
+ case . doStmt :
116
112
if traversedCatchClause {
117
113
return lookupCatchNodeHelper ( at: syntax. parent, traversedCatchClause: false )
118
114
} else {
119
115
return syntax
120
116
}
121
- case is CatchClauseSyntax . Type :
117
+ case . catchClause :
122
118
return lookupCatchNodeHelper ( at: syntax. parent, traversedCatchClause: true )
123
- case is TryExprSyntax . Type :
124
- if syntax . as ( TryExprSyntax . self ) ! . questionOrExclamationMark != nil {
119
+ case . tryExpr ( let tryExpr ) :
120
+ if tryExpr . questionOrExclamationMark != nil {
125
121
return syntax
126
122
} else {
127
123
return lookupCatchNodeHelper ( at: syntax. parent, traversedCatchClause: traversedCatchClause)
128
124
}
129
- case is FunctionDeclSyntax . Type :
130
- if syntax . as ( FunctionDeclSyntax . self ) ! . signature. effectSpecifiers? . throwsClause != nil {
125
+ case . functionDecl ( let functionDecl ) :
126
+ if functionDecl . signature. effectSpecifiers? . throwsClause != nil {
131
127
return syntax
132
128
} else {
133
129
return lookupCatchNodeHelper ( at: syntax. parent, traversedCatchClause: traversedCatchClause)
0 commit comments