Skip to content

Commit 211cb6f

Browse files
committed
Add suggested changes
1 parent d4fb767 commit 211cb6f

File tree

3 files changed

+56
-53
lines changed

3 files changed

+56
-53
lines changed

Sources/SwiftLexicalScopes/LexicalScopes.swift

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,19 @@
1313
import Foundation
1414
import SwiftSyntax
1515

16-
public struct LexicalScopes {
17-
16+
public enum LexicalScopes {
1817
/// Given syntax node position, returns all available labeled statements.
19-
public static func lookupLabeledStmts(at syntax: SyntaxProtocol)
20-
-> [LabeledStmtSyntax]
21-
{
18+
public static func lookupLabeledStmts(at syntax: SyntaxProtocol) -> [LabeledStmtSyntax] {
2219
guard let scope = syntax.scope else { return [] }
2320
return scope.lookupLabeledStmts(at: syntax)
2421
}
2522

2623
/// Given syntax node position, returns the current switch case and it's fallthrough destination.
27-
public static func lookupFallthroughSourceAndDest(at syntax: SyntaxProtocol) -> (
28-
SwitchCaseSyntax?, SwitchCaseSyntax?
29-
) {
24+
public static func lookupFallthroughSourceAndDest(
25+
at syntax: SyntaxProtocol
26+
) -> (source: SwitchCaseSyntax?, destination: SwitchCaseSyntax?) {
3027
guard let scope = syntax.scope else { return (nil, nil) }
31-
return scope.lookupFallthroughSourceAndDest(at: syntax)
28+
return scope.lookupFallthroughSourceAndDestination(at: syntax)
3229
}
3330

3431
/// Given syntax node position, returns the closest ancestor catch node.

Sources/SwiftLexicalScopes/Scope.swift

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,21 @@ extension SyntaxProtocol {
2525
}
2626
}
2727

28+
/// Provide common functionality for specialized scope implementatations.
2829
protocol Scope {
30+
/// The parent of this scope.
2931
var parent: Scope? { get }
3032

33+
/// Syntax node that introduces this protocol.
3134
var sourceSyntax: SyntaxProtocol { get }
3235

36+
/// Returns the declaration `name` refers to at a particular syntax node location.
3337
func getDeclarationFor(name: String, at syntax: SyntaxProtocol) -> Syntax?
3438
}
3539

3640
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? {
4243
if let lookedUpScope = syntax?.scope, lookedUpScope.sourceSyntax.id == syntax?.id {
4344
return getParentScope(forSyntax: sourceSyntax.parent)
4445
} else {
@@ -48,42 +49,35 @@ extension Scope {
4849

4950
// MARK: - lookupLabeledStmts
5051

52+
/// Given syntax node position, returns all available labeled statements.
5153
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: [])
5555
}
5656

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 }
5960
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])
6262
} else {
63-
lookupLabeledStmtsHelper(at: syntax.parent, accumulator: &accumulator)
63+
return lookupLabeledStmtsHelper(at: syntax.parent, accumulator: accumulator)
6464
}
6565
}
6666

6767
// MARK: - lookupFallthroughSourceAndDest
6868

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+
}
7174

7275
let nextSwitchCase = lookupNextSwitchCase(at: originalSwitchCase)
7376

7477
return (originalSwitchCase, nextSwitchCase)
7578
}
7679

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.
8781
private func lookupNextSwitchCase(at switchCaseSyntax: SwitchCaseSyntax) -> SwitchCaseSyntax? {
8882
guard let switchCaseListSyntax = switchCaseSyntax.parent?.as(SwitchCaseListSyntax.self) else { return nil }
8983

@@ -104,30 +98,32 @@ extension Scope {
10498

10599
// MARK: - lookupCatchNode
106100

101+
/// Given syntax node position, returns the closest ancestor catch node.
107102
func lookupCatchNode(at syntax: Syntax) -> Syntax? {
108103
return lookupCatchNodeHelper(at: syntax, traversedCatchClause: false)
109104
}
110105

106+
/// Given syntax node location, finds where an error could be caught. If set to `true`, `traverseCatchClause`lookup will skip the next do statement.
111107
private func lookupCatchNodeHelper(at syntax: Syntax?, traversedCatchClause: Bool) -> Syntax? {
112108
guard let syntax else { return nil }
113109

114-
switch syntax.syntaxNodeType {
115-
case is DoStmtSyntax.Type:
110+
switch syntax.as(SyntaxEnum.self) {
111+
case .doStmt:
116112
if traversedCatchClause {
117113
return lookupCatchNodeHelper(at: syntax.parent, traversedCatchClause: false)
118114
} else {
119115
return syntax
120116
}
121-
case is CatchClauseSyntax.Type:
117+
case .catchClause:
122118
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 {
125121
return syntax
126122
} else {
127123
return lookupCatchNodeHelper(at: syntax.parent, traversedCatchClause: traversedCatchClause)
128124
}
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 {
131127
return syntax
132128
} else {
133129
return lookupCatchNodeHelper(at: syntax.parent, traversedCatchClause: traversedCatchClause)

Tests/SwiftLexicalScopesTest/SimpleQueryTests.swift

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ final class testSimpleQueries: XCTestCase {
1818
func testLabeledStmtLookupThreeNestedScopes() {
1919
assertLexicalScopeQuery(
2020
source: """
21-
while true {
22-
5️⃣break
23-
}
24-
2521
1️⃣one: for i in 1..<10 {
2622
while true {
2723
2️⃣two: do {
@@ -34,7 +30,21 @@ final class testSimpleQueries: XCTestCase {
3430
methodUnderTest: { argument in
3531
LexicalScopes.lookupLabeledStmts(at: argument)
3632
},
37-
expected: ["3️⃣": ["2️⃣", "1️⃣"], "4️⃣": ["1️⃣"], "5️⃣": []]
33+
expected: ["3️⃣": ["2️⃣", "1️⃣"], "4️⃣": ["1️⃣"]]
34+
)
35+
}
36+
37+
func testNoLabeledStatements() {
38+
assertLexicalScopeQuery(
39+
source: """
40+
while true {
41+
1️⃣break
42+
}
43+
""",
44+
methodUnderTest: { argument in
45+
LexicalScopes.lookupLabeledStmts(at: argument)
46+
},
47+
expected: ["1️⃣": []]
3848
)
3949
}
4050

@@ -63,21 +73,21 @@ final class testSimpleQueries: XCTestCase {
6373
assertLexicalScopeQuery(
6474
source: """
6575
func foo() {
66-
7️⃣print(0)
76+
7️⃣print(0)
6777
}
6878
6979
switch a {
7080
1️⃣case 1:
71-
2️⃣print(1)
81+
2️⃣print(1)
7282
3️⃣case 2:
73-
4️⃣print(2)
83+
4️⃣print(2)
7484
5️⃣default:
75-
6️⃣print(3)
85+
6️⃣print(3)
7686
}
7787
""",
7888
methodUnderTest: { argument in
7989
let result = LexicalScopes.lookupFallthroughSourceAndDest(at: argument)
80-
return [result.0, result.1]
90+
return [result.source, result.destination]
8191
},
8292
expected: ["2️⃣": ["1️⃣", "3️⃣"], "4️⃣": ["3️⃣", "5️⃣"], "6️⃣": ["5️⃣", nil], "7️⃣": [nil, nil]]
8393
)
@@ -112,9 +122,9 @@ final class testSimpleQueries: XCTestCase {
112122
1️⃣func foo() rethrows {
113123
2️⃣do {
114124
3️⃣do {
115-
try 4️⃣f()
125+
try 4️⃣f()
116126
} catch {
117-
try 5️⃣f()
127+
try 5️⃣f()
118128
}
119129
} catch {
120130
6️⃣try! 7️⃣f()

0 commit comments

Comments
 (0)