1515import SwiftSyntax
1616@_spi ( Experimental) import SwiftLexicalLookup
1717
18+ /// Unqualified type lookup manager.
19+ /// All unqualified lookup should be done via this instance. This caches the
20+ /// association of `Syntax.ID` to `SwiftTypeDeclaration`, and guarantees that
21+ /// there's only one `SwiftTypeDeclaration` per declaration `Syntax`.
1822class SwiftTypeLookupContext {
1923 var symbolTable : SwiftSymbolTable
2024
21- var typeDecls : [ Syntax . ID : SwiftTypeDeclaration ] = [ : ]
25+ private var typeDecls : [ Syntax . ID : SwiftTypeDeclaration ] = [ : ]
2226
2327 init ( symbolTable: SwiftSymbolTable ) {
2428 self . symbolTable = symbolTable
2529 }
2630
27- func typeDeclaration( for node: some SyntaxProtocol ) throws -> SwiftTypeDeclaration ? {
28- if let found = typeDecls [ node. id] {
29- return found
30- }
31-
32- let typeDecl : SwiftTypeDeclaration
33- switch Syntax ( node) . as ( SyntaxEnum . self) {
34- case . genericParameter( let node) :
35- typeDecl = SwiftGenericParameterDeclaration ( moduleName: symbolTable. moduleName, node: node)
36- case . classDecl( let node) :
37- typeDecl = try nominalTypeDeclaration ( for: node)
38- case . actorDecl( let node) :
39- typeDecl = try nominalTypeDeclaration ( for: node)
40- case . structDecl( let node) :
41- typeDecl = try nominalTypeDeclaration ( for: node)
42- case . enumDecl( let node) :
43- typeDecl = try nominalTypeDeclaration ( for: node)
44- case . protocolDecl( let node) :
45- typeDecl = try nominalTypeDeclaration ( for: node)
46- case . typeAliasDecl:
47- fatalError ( " typealias not implemented " )
48- case . associatedTypeDecl:
49- fatalError ( " associatedtype not implemented " )
50- default :
51- throw TypeLookupError . notType ( Syntax ( node) )
52- }
53-
54- typeDecls [ node. id] = typeDecl
55- return typeDecl
56- }
57-
58- func parentTypeDecl( for node: some DeclSyntaxProtocol ) throws -> SwiftNominalTypeDeclaration ? {
59- var node : DeclSyntax = DeclSyntax ( node)
60- while let parentDecl = node. ancestorDecl {
61- switch parentDecl. as ( DeclSyntaxEnum . self) {
62- case . structDecl, . classDecl, . actorDecl, . enumDecl, . protocolDecl:
63- return ( try typeDeclaration ( for: parentDecl) as! SwiftNominalTypeDeclaration )
64- default :
65- node = parentDecl
66- continue
67- }
68- }
69- return nil
70- }
71-
72- func nominalTypeDeclaration( for node: NominalTypeDeclSyntaxNode ) throws -> SwiftNominalTypeDeclaration {
73- SwiftNominalTypeDeclaration (
74- moduleName: self . symbolTable. moduleName,
75- parent: try parentTypeDecl ( for: node) ,
76- node: node
77- )
78- }
79-
31+ /// Perform unqualified type lookup.
32+ ///
33+ /// - Parameters:
34+ /// - name: name to lookup
35+ /// - node: `Syntax` node the lookup happened
8036 func unqualifiedLookup( name: Identifier , from node: some SyntaxProtocol ) throws -> SwiftTypeDeclaration ? {
8137
8238 for result in node. lookup ( name) {
@@ -113,6 +69,7 @@ class SwiftTypeLookupContext {
11369 return symbolTable. lookupTopLevelNominalType ( name. name)
11470 }
11571
72+ /// Find the first type declaration in the `LookupName` results.
11673 func typeDeclaration( for names: [ LookupName ] ) -> SwiftTypeDeclaration ? {
11774 for name in names {
11875 switch name {
@@ -130,6 +87,63 @@ class SwiftTypeLookupContext {
13087 }
13188 return nil
13289 }
90+
91+ /// Returns the type declaration object associated with the `Syntax` node.
92+ /// If there's no declaration created, create an instance on demand, and cache it.
93+ private func typeDeclaration( for node: some SyntaxProtocol ) throws -> SwiftTypeDeclaration ? {
94+ if let found = typeDecls [ node. id] {
95+ return found
96+ }
97+
98+ let typeDecl : SwiftTypeDeclaration
99+ switch Syntax ( node) . as ( SyntaxEnum . self) {
100+ case . genericParameter( let node) :
101+ typeDecl = SwiftGenericParameterDeclaration ( moduleName: symbolTable. moduleName, node: node)
102+ case . classDecl( let node) :
103+ typeDecl = try nominalTypeDeclaration ( for: node)
104+ case . actorDecl( let node) :
105+ typeDecl = try nominalTypeDeclaration ( for: node)
106+ case . structDecl( let node) :
107+ typeDecl = try nominalTypeDeclaration ( for: node)
108+ case . enumDecl( let node) :
109+ typeDecl = try nominalTypeDeclaration ( for: node)
110+ case . protocolDecl( let node) :
111+ typeDecl = try nominalTypeDeclaration ( for: node)
112+ case . typeAliasDecl:
113+ fatalError ( " typealias not implemented " )
114+ case . associatedTypeDecl:
115+ fatalError ( " associatedtype not implemented " )
116+ default :
117+ throw TypeLookupError . notType ( Syntax ( node) )
118+ }
119+
120+ typeDecls [ node. id] = typeDecl
121+ return typeDecl
122+ }
123+
124+ /// Create a nominal type declaration instance for the specified syntax node.
125+ private func nominalTypeDeclaration( for node: NominalTypeDeclSyntaxNode ) throws -> SwiftNominalTypeDeclaration {
126+ SwiftNominalTypeDeclaration (
127+ moduleName: self . symbolTable. moduleName,
128+ parent: try parentTypeDecl ( for: node) ,
129+ node: node
130+ )
131+ }
132+
133+ /// Find a parent nominal type declaration of the specified syntax node.
134+ private func parentTypeDecl( for node: some DeclSyntaxProtocol ) throws -> SwiftNominalTypeDeclaration ? {
135+ var node : DeclSyntax = DeclSyntax ( node)
136+ while let parentDecl = node. ancestorDecl {
137+ switch parentDecl. as ( DeclSyntaxEnum . self) {
138+ case . structDecl, . classDecl, . actorDecl, . enumDecl, . protocolDecl:
139+ return ( try typeDeclaration ( for: parentDecl) as! SwiftNominalTypeDeclaration )
140+ default :
141+ node = parentDecl
142+ continue
143+ }
144+ }
145+ return nil
146+ }
133147}
134148
135149enum TypeLookupError : Error {
0 commit comments