Skip to content

Commit 3de7208

Browse files
committed
Add initializer declaration scope. Generalize function decl and initializer decl scopes to function scope. Introduce self keyword on the edge of computed properties.
1 parent fae4d0e commit 3de7208

File tree

6 files changed

+146
-50
lines changed

6 files changed

+146
-50
lines changed

Sources/SwiftLexicalLookup/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_swift_syntax_library(SwiftLexicalLookup
1515
Configurations/FileScopeHandlingConfig.swift
1616
Configurations/LookupConfig.swift
1717

18+
Scopes/FunctionScopeSyntax.swift
1819
Scopes/GenericParameterScopeSyntax.swift
1920
Scopes/IntroducingToSequentialParentScopeSyntax.swift
2021
Scopes/LookInMembersScopeSyntax.swift

Sources/SwiftLexicalLookup/LookupName.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,20 @@ import SwiftSyntax
154154
switch Syntax(declSyntax).as(SyntaxEnum.self) {
155155
case .functionDecl(let functionDecl):
156156
return functionDecl.name.position
157+
case .initializerDecl(let initializerDecl):
158+
return initializerDecl.initKeyword.positionAfterSkippingLeadingTrivia
157159
case .subscriptDecl(let subscriptDecl):
158160
return subscriptDecl.accessorBlock?.position ?? subscriptDecl.endPosition
161+
case .variableDecl(let variableDecl):
162+
return variableDecl.bindings.first?.accessorBlock?.positionAfterSkippingLeadingTrivia
163+
?? variableDecl.endPosition
164+
default:
165+
return declSyntax.positionAfterSkippingLeadingTrivia
166+
}
167+
case .Self(let declSyntax):
168+
switch Syntax(declSyntax).as(SyntaxEnum.self) {
169+
case .protocolDecl(let protocolDecl):
170+
return protocolDecl.name.positionAfterSkippingLeadingTrivia
159171
default:
160172
return declSyntax.positionAfterSkippingLeadingTrivia
161173
}
@@ -226,6 +238,8 @@ import SwiftSyntax
226238
return functionCallExpr.arguments.flatMap { argument in
227239
getNames(from: argument.expression, accessibleAfter: accessibleAfter)
228240
}
241+
case .optionalChainingExpr(let optionalChainingExpr):
242+
return getNames(from: optionalChainingExpr.expression, accessibleAfter: accessibleAfter)
229243
default:
230244
if let namedDecl = Syntax(syntax).asProtocol(SyntaxProtocol.self) as? NamedDeclSyntax {
231245
return handle(namedDecl: namedDecl, accessibleAfter: accessibleAfter)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
15+
protocol FunctionScopeSyntax: DeclSyntaxProtocol, WithGenericParametersScopeSyntax {
16+
var signature: FunctionSignatureSyntax { get }
17+
}
18+
19+
extension FunctionScopeSyntax {
20+
/// Function parameters introduced by this function's signature.
21+
@_spi(Experimental) public var introducedNames: [LookupName] {
22+
signature.parameterClause.parameters.flatMap { parameter in
23+
LookupName.getNames(from: parameter)
24+
} + (parentScope?.is(MemberBlockSyntax.self) ?? false ? [.implicit(.self(self))] : [])
25+
}
26+
27+
/// Lookup results from this function scope.
28+
/// Routes to generic parameter clause scope if exists.
29+
@_spi(Experimental) public func lookup(
30+
_ identifier: Identifier?,
31+
at lookUpPosition: AbsolutePosition,
32+
with config: LookupConfig
33+
) -> [LookupResult] {
34+
var thisScopeResults: [LookupResult] = []
35+
36+
if !signature.range.contains(lookUpPosition) {
37+
thisScopeResults = defaultLookupImplementation(
38+
identifier,
39+
at: position,
40+
with: config,
41+
propagateToParent: false
42+
)
43+
}
44+
45+
return thisScopeResults
46+
+ lookupThroughGenericParameterScope(
47+
identifier,
48+
at: lookUpPosition,
49+
with: config
50+
)
51+
}
52+
}

Sources/SwiftLexicalLookup/Scopes/ScopeImplementations.swift

Lines changed: 74 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ import SwiftSyntax
115115
switch config.fileScopeHandling {
116116
case .memberBlock:
117117
guard config.includeMembers else { return [] }
118-
118+
119119
let names = introducedNames(using: .memberBlock)
120120
.filter { lookupName in
121121
checkIdentifier(identifier, refersTo: lookupName, at: lookUpPosition)
@@ -150,7 +150,8 @@ import SwiftSyntax
150150
with: config
151151
)
152152

153-
return (members.isEmpty || !config.includeMembers ? [] : [.fromFileScope(self, withNames: members)]) + sequentialNames
153+
return (members.isEmpty || !config.includeMembers ? [] : [.fromFileScope(self, withNames: members)])
154+
+ sequentialNames
154155
}
155156
}
156157
}
@@ -528,7 +529,7 @@ import SwiftSyntax
528529
@_spi(Experimental) public var scopeDebugName: String {
529530
"AccessorDeclScope"
530531
}
531-
532+
532533
/// Returns result with matching names from
533534
/// this scope and passes result with implicit `self`
534535
/// to be introduced after the `subscript`
@@ -541,18 +542,24 @@ import SwiftSyntax
541542
guard let parentAccessorBlockScope = parentScope?.as(AccessorBlockSyntax.self) else {
542543
return defaultLookupImplementation(identifier, at: lookUpPosition, with: config)
543544
}
544-
545+
546+
let implicitSelf: [LookupName] = [.implicit(.self(self))]
547+
.filter { name in
548+
checkIdentifier(identifier, refersTo: name, at: lookUpPosition)
549+
}
550+
545551
return defaultLookupImplementation(
546552
identifier,
547553
at: lookUpPosition,
548554
with: config,
549555
propagateToParent: false
550-
) + parentAccessorBlockScope.interleaveAccessorResultsAfterSubscriptLookup(
551-
identifier,
552-
at: lookUpPosition,
553-
with: config,
554-
resultsToInterleave: [.fromScope(self, withNames: [.implicit(.self(self))])]
555556
)
557+
+ parentAccessorBlockScope.interleaveAccessorResultsAfterSubscriptLookup(
558+
identifier,
559+
at: lookUpPosition,
560+
with: config,
561+
resultsToInterleave: implicitSelf.isEmpty ? [] : [.fromScope(self, withNames: implicitSelf)]
562+
)
556563
}
557564
}
558565

@@ -606,14 +613,18 @@ import SwiftSyntax
606613
with: config,
607614
propagateToParent: false
608615
) + (filteredNamesFromLabel.isEmpty ? [] : [.fromScope(self, withNames: filteredNamesFromLabel)])
609-
+ (config.finishInSequentialScope ? [] : lookupInParent(identifier, at: lookUpPosition, with: config))
616+
+ (config.finishInSequentialScope ? [] : lookupInParent(identifier, at: lookUpPosition, with: config))
610617
}
611618
}
612619

613-
@_spi(Experimental) extension ProtocolDeclSyntax: ScopeSyntax {
620+
@_spi(Experimental) extension ProtocolDeclSyntax: ScopeSyntax, LookInMembersScopeSyntax {
614621
/// Protocol declarations don't introduce names by themselves.
615622
@_spi(Experimental) public var introducedNames: [LookupName] {
616-
[]
623+
[.implicit(.Self(self))]
624+
}
625+
626+
@_spi(Experimental) public var lookupMembersPosition: AbsolutePosition {
627+
name.positionAfterSkippingLeadingTrivia
617628
}
618629

619630
@_spi(Experimental) public var scopeDebugName: String {
@@ -655,7 +666,13 @@ import SwiftSyntax
655666
)
656667
}
657668

658-
return results + defaultLookupImplementation(identifier, at: lookUpPosition, with: config)
669+
return results
670+
+ defaultLookupImplementation(
671+
identifier,
672+
at: lookUpPosition,
673+
with: config,
674+
propagateToParent: false
675+
) + [.lookInMembers(self)] + lookupInParent(identifier, at: lookUpPosition, with: config)
659676
}
660677
}
661678

@@ -672,42 +689,15 @@ import SwiftSyntax
672689
}
673690
}
674691

675-
@_spi(Experimental) extension FunctionDeclSyntax: WithGenericParametersScopeSyntax {
676-
/// Function parameters introduced by this function's signature.
677-
@_spi(Experimental) public var introducedNames: [LookupName] {
678-
signature.parameterClause.parameters.flatMap { parameter in
679-
LookupName.getNames(from: parameter)
680-
} + (parentScope?.is(MemberBlockSyntax.self) ?? false ? [.implicit(.self(self))] : [])
681-
}
682-
692+
@_spi(Experimental) extension FunctionDeclSyntax: FunctionScopeSyntax {
683693
@_spi(Experimental) public var scopeDebugName: String {
684694
"FunctionDeclScope"
685695
}
696+
}
686697

687-
/// Lookup results from this function scope.
688-
/// Routes to generic parameter clause scope if exists.
689-
@_spi(Experimental) public func lookup(
690-
_ identifier: Identifier?,
691-
at lookUpPosition: AbsolutePosition,
692-
with config: LookupConfig
693-
) -> [LookupResult] {
694-
var thisScopeResults: [LookupResult] = []
695-
696-
if !signature.range.contains(lookUpPosition) {
697-
thisScopeResults = defaultLookupImplementation(
698-
identifier,
699-
at: position,
700-
with: config,
701-
propagateToParent: false
702-
)
703-
}
704-
705-
return thisScopeResults
706-
+ lookupThroughGenericParameterScope(
707-
identifier,
708-
at: lookUpPosition,
709-
with: config
710-
)
698+
@_spi(Experimental) extension InitializerDeclSyntax: FunctionScopeSyntax {
699+
@_spi(Experimental) public var scopeDebugName: String {
700+
"InitializerDeclScope"
711701
}
712702
}
713703

@@ -743,7 +733,7 @@ import SwiftSyntax
743733
resultsToInterleave: []
744734
)
745735
}
746-
736+
747737
/// Lookup names in this scope and add `resultsToInterleave`
748738
/// after results from this scope.
749739
///
@@ -822,7 +812,7 @@ import SwiftSyntax
822812
return lookupInParent(identifier, at: lookUpPosition, with: config)
823813
}
824814
}
825-
815+
826816
/// Used by children accessors to interleave
827817
/// their results with parent `subscript` declaration scope.
828818
func interleaveAccessorResultsAfterSubscriptLookup(
@@ -834,7 +824,7 @@ import SwiftSyntax
834824
guard let parentSubscriptScope = parentScope?.as(SubscriptDeclSyntax.self) else {
835825
return lookupInParent(identifier, at: lookUpPosition, with: config)
836826
}
837-
827+
838828
return parentSubscriptScope.interleaveResultsAfterThisSubscriptLookup(
839829
identifier,
840830
at: lookUpPosition,
@@ -854,3 +844,39 @@ import SwiftSyntax
854844
"TypeAliasDeclScope"
855845
}
856846
}
847+
848+
@_spi(Experimental) extension VariableDeclSyntax: ScopeSyntax {
849+
/// Variable decl scope doesn't introduce any
850+
/// names unless it is a member and is looked
851+
/// up from inside it's accessor block.
852+
@_spi(Experimental) public var introducedNames: [LookupName] {
853+
[]
854+
}
855+
856+
@_spi(Experimental) public var scopeDebugName: String {
857+
"VariableDeclScope"
858+
}
859+
860+
/// If a member and looked up from inside
861+
/// it's accessor block, introduce implicit
862+
/// `self` and propagate the lookup further.
863+
@_spi(Experimental) public func lookup(
864+
_ identifier: Identifier?,
865+
at lookUpPosition: AbsolutePosition,
866+
with config: LookupConfig
867+
) -> [LookupResult] {
868+
if let parentScope,
869+
parentScope.is(MemberBlockSyntax.self),
870+
bindings.first?.accessorBlock?.range.contains(lookUpPosition) ?? false
871+
{
872+
return defaultLookupImplementation(
873+
in: [.implicit(.self(self))],
874+
identifier,
875+
at: lookUpPosition,
876+
with: config
877+
)
878+
} else {
879+
return lookupInParent(identifier, at: lookUpPosition, with: config)
880+
}
881+
}
882+
}

Sources/SwiftLexicalLookup/Scopes/ScopeSyntax.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,14 @@ extension SyntaxProtocol {
8787
/// refers to and is accessible at given syntax node then passes lookup to the parent.
8888
/// If `identifier` set to `nil`, returns all available names at the given node.
8989
func defaultLookupImplementation(
90+
in names: [LookupName]? = nil,
9091
_ identifier: Identifier?,
9192
at lookUpPosition: AbsolutePosition,
9293
with config: LookupConfig,
9394
propagateToParent: Bool = true
9495
) -> [LookupResult] {
9596
let filteredNames =
96-
introducedNames
97+
(names ?? introducedNames)
9798
.filter { introducedName in
9899
checkIdentifier(identifier, refersTo: introducedName, at: lookUpPosition)
99100
}

Tests/SwiftLexicalLookupTest/NameLookupTests.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,10 +1005,12 @@ final class testNameLookup: XCTestCase {
10051005
references: [
10061006
"1️⃣": [
10071007
.fromScope(MemberBlockSyntax.self, expectedNames: ["3️⃣"]),
1008+
.lookInMembers(ProtocolDeclSyntax.self),
10081009
.fromFileScope(expectedNames: ["0️⃣"]),
10091010
],
10101011
"2️⃣": [
1011-
.fromScope(MemberBlockSyntax.self, expectedNames: ["4️⃣"])
1012+
.fromScope(MemberBlockSyntax.self, expectedNames: ["4️⃣"]),
1013+
.lookInMembers(ProtocolDeclSyntax.self),
10121014
],
10131015
],
10141016
expectedResultTypes: .all(

0 commit comments

Comments
 (0)