@@ -37,26 +37,48 @@ struct SecondPass
3737{
3838public :
3939
40+ /**
41+ * Construct this with the results of the first pass
42+ * Params:
43+ * first = the first pass
44+ */
4045 this (FirstPass first)
4146 {
4247 this .rootSymbol = first.rootSymbol;
4348 this .moduleScope = first.moduleScope;
4449 this .symbolAllocator = first.symbolAllocator;
4550 }
4651
52+ /**
53+ * Runs the second pass on the module.
54+ */
4755 void run ()
4856 {
4957 rootSymbol.acSymbol.parts.insert(builtinSymbols[]);
5058 assignToScopes(rootSymbol.acSymbol);
5159 resolveImports(moduleScope);
5260 }
5361
62+ /**
63+ * Allocator used for allocating autocomplete symbols.
64+ */
5465 CAllocator symbolAllocator;
66+
67+ /**
68+ * The root symbol from the first pass
69+ */
5570 SemanticSymbol* rootSymbol;
71+
72+ /**
73+ * The module scope from the first pass
74+ */
5675 Scope* moduleScope;
5776
5877private :
5978
79+ /**
80+ * Assigns symbols to scopes based on their location.
81+ */
6082 void assignToScopes (ACSymbol* currentSymbol)
6183 {
6284 Scope* s = moduleScope.getScopeByCursor(currentSymbol.location);
@@ -71,12 +93,19 @@ private:
7193
7294 /**
7395 * Creates package symbols as necessary to contain the given module symbol
96+ * Params:
97+ * info = the import information for the module being imported
98+ * currentScope = the scope in which the import statement is located
99+ * moduleSymbol = the module being imported
100+ * Returns: A package symbol that can be used for auto-completing qualified
101+ * symbol names.
74102 */
75103 ACSymbol* createImportSymbols (ImportInformation* info, Scope* currentScope,
76104 ACSymbol* moduleSymbol)
77105 in
78106 {
79107 assert (info ! is null );
108+ assert (currentScope ! is null );
80109 assert (moduleSymbol ! is null );
81110 }
82111 body
@@ -89,7 +118,6 @@ private:
89118 else
90119 firstSymbol = allocate! ACSymbol(symbolAllocator, firstPart,
91120 CompletionKind.packageName);
92- currentScope.symbols.insert(firstSymbol);
93121 ACSymbol* currentSymbol = firstSymbol;
94122 size_t i = 0 ;
95123 foreach (string importPart; info.importParts[])
@@ -99,9 +127,17 @@ private:
99127 if (i + 2 >= info.importParts.length) // Skip the last item as it's the module name
100128 break ;
101129 symbols = currentSymbol.getPartsByName(importPart);
102- ACSymbol* s = symbols.length > 0
103- ? cast (ACSymbol* ) symbols[0 ] : allocate! ACSymbol(symbolAllocator,
104- importPart, CompletionKind.packageName);
130+ ACSymbol* s = null ;
131+ if (symbols.length > 0 ) foreach (sy; symbols)
132+ {
133+ if (sy.kind == CompletionKind.packageName)
134+ {
135+ s = sy;
136+ break ;
137+ }
138+ }
139+ if (s is null )
140+ s = allocate! ACSymbol(symbolAllocator, importPart, CompletionKind.packageName);
105141 currentSymbol.parts.insert(s);
106142 currentSymbol = s;
107143 }
@@ -120,45 +156,50 @@ private:
120156 if (symbol is null )
121157 continue ;
122158 ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbol);
123- currentScope.symbols.insert(symbol.parts[]);
124159 if (importInfo.importedSymbols.length == 0 )
125160 {
126161 if (importInfo.isPublic && currentScope.parent is null )
127- {
128162 rootSymbol.acSymbol.parts.insert(allocate! ACSymbol(symbolAllocator,
129163 IMPORT_SYMBOL_NAME , CompletionKind.importSymbol, symbol));
130- }
164+ else
165+ currentScope.symbols.insert(symbol.parts[]);
131166 continue ;
132167 }
133- symbolLoop: foreach (sym; symbol.parts[])
168+
169+ foreach (tup; importInfo.importedSymbols[])
134170 {
135- foreach (tup; importInfo.importedSymbols[])
171+ ACSymbol needle = ACSymbol(tup[0 ]);
172+ ACSymbol* sym;
173+ auto r = symbol.parts.equalRange(&needle);
174+ if (r.empty) foreach (sy; symbol.parts[])
136175 {
137- if (tup[0 ] != symbol.name)
138- continue symbolLoop;
139- if (tup[1 ] ! is null )
140- {
141- ACSymbol* s = allocate! ACSymbol(symbolAllocator, tup[1 ],
142- sym.kind, sym.type);
143- s.parts.insert(sym.parts[]);
144- s.callTip = sym.callTip;
145- s.doc = sym.doc;
146- s.qualifier = sym.qualifier;
147- s.location = sym.location;
148- s.symbolFile = sym.symbolFile;
149- currentScope.symbols.insert(s);
150- moduleSymbol.parts.insert(s);
151- if (importInfo.isPublic && currentScope.parent is null )
152- rootSymbol.acSymbol.parts.insert(s);
153- }
154- else
155- {
156- moduleSymbol.parts.insert(sym);
157- currentScope.symbols.insert(sym);
158- if (importInfo.isPublic && currentScope.parent is null )
159- rootSymbol.acSymbol.parts.insert(sym);
160- }
176+ if (sy.kind != CompletionKind.importSymbol || sy.type is null )
177+ continue ;
178+ auto ra = sy.type.parts.equalRange(&needle);
179+ if (ra.empty)
180+ continue ;
181+ sym = ra.front;
161182 }
183+ else
184+ sym = r.front;
185+ if (sym is null )
186+ continue ;
187+ if (tup[1 ] ! is null )
188+ {
189+ ACSymbol* s = allocate! ACSymbol(symbolAllocator, tup[1 ],
190+ sym.kind, sym.type);
191+ s.parts.insert(sym.parts[]);
192+ s.callTip = sym.callTip;
193+ s.doc = sym.doc;
194+ s.qualifier = sym.qualifier;
195+ s.location = sym.location;
196+ s.symbolFile = sym.symbolFile;
197+ sym = s;
198+ }
199+ moduleSymbol.parts.insert(sym);
200+ currentScope.symbols.insert(sym);
201+ if (importInfo.isPublic && currentScope.parent is null )
202+ rootSymbol.acSymbol.parts.insert(sym);
162203 }
163204 }
164205 foreach (childScope; currentScope.children)
0 commit comments