Skip to content

Commit 26d84ab

Browse files
authored
Merge pull request swiftlang#2755 from MAJKFL/fix-swift5.8-compatibility
[SwiftLexicalLookup][GSoC] Fix Swift 5.8 compatibility and update documentation.
2 parents 92ebf8e + 3035f7a commit 26d84ab

File tree

9 files changed

+148
-147
lines changed

9 files changed

+148
-147
lines changed

Sources/SwiftLexicalLookup/Configurations/FileScopeNameIntroductionStrategy.swift renamed to Sources/SwiftLexicalLookup/Configurations/FileScopeHandlingConfig.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ import SwiftSyntax
1414

1515
/// Specifies how names should be introduced at the file scope.
1616
@_spi(Experimental) public enum FileScopeHandlingConfig {
17-
/// Default behavior. Names introduced sequentially like in member block
18-
/// scope up to the first non-declaration after and including which,
19-
/// the declarations are treated like in code block scope.
17+
/// This is the behavior that is being used
18+
/// for Swift files with top-level code.
2019
case memberBlockUpToLastDecl
21-
/// File scope behaves like member block scope.
20+
/// This is the behavior that is being used
21+
/// for Swift files that don’t allow top-level code.
2222
case memberBlock
23-
/// File scope behaves like code block scope.
24-
case codeBlock
2523
}

Sources/SwiftLexicalLookup/Configurations/LookupConfig.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@
1313
import Foundation
1414

1515
@_spi(Experimental) public struct LookupConfig {
16-
/// Specifies behaviour of file scope.
17-
/// `memberBlockUpToLastDecl` by default.
18-
public var fileScopeHandling: FileScopeHandlingConfig = .memberBlockUpToLastDecl
16+
/// Specifies behavior of file scope.
17+
@_spi(Experimental) public var fileScopeHandling: FileScopeHandlingConfig
1918

20-
public init(fileScopeHandling: FileScopeHandlingConfig = .memberBlockUpToLastDecl) {
19+
/// Creates a new lookup configuration.
20+
///
21+
/// - `fileScopeHandling` - specifies behavior of file scope.
22+
/// `memberBlockUpToLastDecl` by default.
23+
@_spi(Experimental) public init(
24+
fileScopeHandling: FileScopeHandlingConfig = .memberBlockUpToLastDecl
25+
) {
2126
self.fileScopeHandling = fileScopeHandling
2227
}
2328
}

Sources/SwiftLexicalLookup/IdentifiableSyntax.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@
1313
import SwiftSyntax
1414

1515
/// Syntax node that can be refered to with an identifier.
16-
public protocol IdentifiableSyntax: SyntaxProtocol {
16+
@_spi(Experimental) public protocol IdentifiableSyntax: SyntaxProtocol {
1717
var identifier: TokenSyntax { get }
1818
}
1919

20-
extension IdentifierPatternSyntax: IdentifiableSyntax {}
20+
@_spi(Experimental) extension IdentifierPatternSyntax: IdentifiableSyntax {}
2121

22-
extension ClosureParameterSyntax: IdentifiableSyntax {
22+
@_spi(Experimental) extension ClosureParameterSyntax: IdentifiableSyntax {
2323
@_spi(Experimental) public var identifier: TokenSyntax {
2424
secondName ?? firstName
2525
}
2626
}
2727

28-
extension ClosureShorthandParameterSyntax: IdentifiableSyntax {
28+
@_spi(Experimental) extension ClosureShorthandParameterSyntax: IdentifiableSyntax {
2929
@_spi(Experimental) public var identifier: TokenSyntax {
3030
name
3131
}
3232
}
3333

34-
extension ClosureCaptureSyntax: IdentifiableSyntax {
34+
@_spi(Experimental) extension ClosureCaptureSyntax: IdentifiableSyntax {
3535
@_spi(Experimental) public var identifier: TokenSyntax {
3636
/* Doesn't work with closures like:
3737
_ = { [y=1+2] in

Sources/SwiftLexicalLookup/LookupName.swift

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,40 @@ import SwiftSyntax
1414

1515
@_spi(Experimental) public enum LookupName {
1616
/// Identifier associated with the name.
17-
/// Could be an identifier of a variable, function or closure parameter and more
17+
/// Could be an identifier of a variable, function or closure parameter and more.
1818
case identifier(IdentifiableSyntax, accessibleAfter: AbsolutePosition?)
1919
/// Declaration associated with the name.
20-
/// Could be class, struct, actor, protocol, function and more
21-
case declaration(NamedDeclSyntax, accessibleAfter: AbsolutePosition?)
20+
/// Could be class, struct, actor, protocol, function and more.
21+
case declaration(NamedDeclSyntax)
2222

2323
/// Syntax associated with this name.
2424
@_spi(Experimental) public var syntax: SyntaxProtocol {
2525
switch self {
2626
case .identifier(let syntax, _):
27-
syntax
28-
case .declaration(let syntax, _):
29-
syntax
27+
return syntax
28+
case .declaration(let syntax):
29+
return syntax
3030
}
3131
}
3232

3333
/// Introduced name.
3434
@_spi(Experimental) public var identifier: Identifier? {
3535
switch self {
3636
case .identifier(let syntax, _):
37-
Identifier(syntax.identifier)
38-
case .declaration(let syntax, _):
39-
Identifier(syntax.name)
37+
return Identifier(syntax.identifier)
38+
case .declaration(let syntax):
39+
return Identifier(syntax.name)
4040
}
4141
}
4242

4343
/// Point, after which the name is available in scope.
4444
/// If set to `nil`, the name is available at any point in scope.
4545
var accessibleAfter: AbsolutePosition? {
4646
switch self {
47-
case .identifier(_, let absolutePosition), .declaration(_, let absolutePosition):
48-
absolutePosition
47+
case .identifier(_, let absolutePosition):
48+
return absolutePosition
49+
default:
50+
return nil
4951
}
5052
}
5153

@@ -61,62 +63,78 @@ import SwiftSyntax
6163
return name == lookedUpName
6264
}
6365

64-
/// Extracts names introduced by the given `from` structure.
65-
static func getNames(from syntax: SyntaxProtocol, accessibleAfter: AbsolutePosition? = nil) -> [LookupName] {
66+
/// Extracts names introduced by the given `syntax` structure.
67+
///
68+
/// When e.g. looking up a variable declaration like `let a = a`,
69+
/// we expect `a` to be visible after the whole declaration.
70+
/// That's why we can't just use `syntax.endPosition` for the `a` identifier pattern,
71+
/// as the name would already be visible at the `a` reference withing the declaration.
72+
/// That’s why code block and file scopes have to set
73+
/// `accessibleAfter` to be the end position of the entire declaration syntax node.
74+
static func getNames(
75+
from syntax: SyntaxProtocol,
76+
accessibleAfter: AbsolutePosition? = nil
77+
) -> [LookupName] {
6678
switch Syntax(syntax).as(SyntaxEnum.self) {
6779
case .variableDecl(let variableDecl):
68-
variableDecl.bindings.flatMap { binding in
69-
getNames(from: binding.pattern, accessibleAfter: accessibleAfter)
80+
return variableDecl.bindings.flatMap { binding in
81+
getNames(
82+
from: binding.pattern,
83+
accessibleAfter: accessibleAfter != nil ? binding.endPositionBeforeTrailingTrivia : nil
84+
)
7085
}
7186
case .tuplePattern(let tuplePattern):
72-
tuplePattern.elements.flatMap { tupleElement in
87+
return tuplePattern.elements.flatMap { tupleElement in
7388
getNames(from: tupleElement.pattern, accessibleAfter: accessibleAfter)
7489
}
7590
case .valueBindingPattern(let valueBindingPattern):
76-
getNames(from: valueBindingPattern.pattern, accessibleAfter: accessibleAfter)
91+
return getNames(from: valueBindingPattern.pattern, accessibleAfter: accessibleAfter)
7792
case .expressionPattern(let expressionPattern):
78-
getNames(from: expressionPattern.expression, accessibleAfter: accessibleAfter)
93+
return getNames(from: expressionPattern.expression, accessibleAfter: accessibleAfter)
7994
case .sequenceExpr(let sequenceExpr):
80-
sequenceExpr.elements.flatMap { expression in
95+
return sequenceExpr.elements.flatMap { expression in
8196
getNames(from: expression, accessibleAfter: accessibleAfter)
8297
}
8398
case .patternExpr(let patternExpr):
84-
getNames(from: patternExpr.pattern, accessibleAfter: accessibleAfter)
99+
return getNames(from: patternExpr.pattern, accessibleAfter: accessibleAfter)
85100
case .optionalBindingCondition(let optionalBinding):
86-
getNames(from: optionalBinding.pattern, accessibleAfter: accessibleAfter)
101+
return getNames(from: optionalBinding.pattern, accessibleAfter: accessibleAfter)
87102
case .matchingPatternCondition(let matchingPatternCondition):
88-
getNames(from: matchingPatternCondition.pattern, accessibleAfter: accessibleAfter)
103+
return getNames(from: matchingPatternCondition.pattern, accessibleAfter: accessibleAfter)
89104
case .functionCallExpr(let functionCallExpr):
90-
functionCallExpr.arguments.flatMap { argument in
105+
return functionCallExpr.arguments.flatMap { argument in
91106
getNames(from: argument.expression, accessibleAfter: accessibleAfter)
92107
}
93108
case .guardStmt(let guardStmt):
94-
guardStmt.conditions.flatMap { cond in
109+
return guardStmt.conditions.flatMap { cond in
95110
getNames(from: cond.condition, accessibleAfter: cond.endPosition)
96111
}
97112
default:
98113
if let namedDecl = Syntax(syntax).asProtocol(SyntaxProtocol.self) as? NamedDeclSyntax {
99-
handle(namedDecl: namedDecl, accessibleAfter: accessibleAfter)
114+
return handle(namedDecl: namedDecl, accessibleAfter: accessibleAfter)
100115
} else if let identifiable = Syntax(syntax).asProtocol(SyntaxProtocol.self) as? IdentifiableSyntax {
101-
handle(identifiable: identifiable, accessibleAfter: accessibleAfter)
116+
return handle(identifiable: identifiable, accessibleAfter: accessibleAfter)
102117
} else {
103-
[]
118+
return []
104119
}
105120
}
106121
}
107122

108123
/// Extracts name introduced by `IdentifiableSyntax` node.
109124
private static func handle(identifiable: IdentifiableSyntax, accessibleAfter: AbsolutePosition? = nil) -> [LookupName]
110125
{
111-
if identifiable.identifier.text != "_" {
126+
if identifiable.identifier.tokenKind != .wildcard {
112127
return [.identifier(identifiable, accessibleAfter: accessibleAfter)]
113128
} else {
114129
return []
115130
}
116131
}
117132

118133
/// Extracts name introduced by `NamedDeclSyntax` node.
119-
private static func handle(namedDecl: NamedDeclSyntax, accessibleAfter: AbsolutePosition? = nil) -> [LookupName] {
120-
[.declaration(namedDecl, accessibleAfter: accessibleAfter)]
134+
private static func handle(
135+
namedDecl: NamedDeclSyntax,
136+
accessibleAfter: AbsolutePosition? = nil
137+
) -> [LookupName] {
138+
[.declaration(namedDecl)]
121139
}
122140
}

Sources/SwiftLexicalLookup/LookupResult.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import SwiftSyntax
1414

15-
/// Represents resul
15+
/// Represents result from a specific scope.
1616
@_spi(Experimental) public enum LookupResult {
1717
/// Scope and the names that matched lookup.
1818
case fromScope(ScopeSyntax, withNames: [LookupName])
@@ -23,17 +23,17 @@ import SwiftSyntax
2323
@_spi(Experimental) public var scope: ScopeSyntax? {
2424
switch self {
2525
case .fromScope(let scopeSyntax, _):
26-
scopeSyntax
26+
return scopeSyntax
2727
case .fromFileScope(let fileScopeSyntax, _):
28-
fileScopeSyntax
28+
return fileScopeSyntax
2929
}
3030
}
3131

3232
/// Names that matched lookup.
3333
@_spi(Experimental) public var names: [LookupName] {
3434
switch self {
3535
case .fromScope(_, let names), .fromFileScope(_, let names):
36-
names
36+
return names
3737
}
3838
}
3939
}

0 commit comments

Comments
 (0)