@@ -216,26 +216,38 @@ class ContainerTracker {
216
216
217
217
bool empty () const { return Stack.empty (); }
218
218
219
- void forEachActiveContainer (llvm::function_ref<void (const Decl *)> f) const {
220
- if (Stack.empty ())
221
- return ;
219
+ void forEachActiveContainer (llvm::function_ref<bool (const Decl *)> allowDecl,
220
+ llvm::function_ref<void(const Decl *)> f) const {
221
+ for (const auto &Entry : llvm::reverse (Stack)) {
222
+ // No active container, we're done.
223
+ if (!Entry.ActiveKey )
224
+ return ;
222
225
223
- const StackEntry &Entry = Stack.back ();
226
+ auto MapEntry = Entry.Containers .find (Entry.ActiveKey );
227
+ if (MapEntry == Entry.Containers .end ())
228
+ return ;
224
229
225
- if (!Entry.ActiveKey )
226
- return ;
230
+ SmallVector<const Decl *, 4 > Containers;
231
+ if (auto C = MapEntry->second ) {
232
+ if (auto *D = C.dyn_cast <const Decl *>()) {
233
+ if (allowDecl (D))
234
+ Containers.push_back (D);
235
+ } else {
236
+ auto *P = C.get <const Pattern *>();
237
+ P->forEachVariable ([&](VarDecl *VD) {
238
+ if (allowDecl (VD))
239
+ Containers.push_back (VD);
240
+ });
241
+ }
242
+ }
243
+ // If we didn't have any viable containers, continue walking up the stack.
244
+ if (Containers.empty ())
245
+ continue ;
227
246
228
- auto MapEntry = Entry.Containers .find (Entry.ActiveKey );
247
+ for (auto *decl : Containers)
248
+ f (decl);
229
249
230
- if (MapEntry == Entry.Containers .end ())
231
250
return ;
232
-
233
- Container C = MapEntry->second ;
234
-
235
- if (auto *D = C.dyn_cast <const Decl *>()) {
236
- f (D);
237
- } else if (auto *P = C.dyn_cast <const Pattern *>()) {
238
- P->forEachVariable ([&](VarDecl *VD) { f (VD); });
239
251
}
240
252
}
241
253
@@ -343,26 +355,10 @@ class ContainerTracker {
343
355
}
344
356
345
357
// AnyPatterns behave differently to other patterns as they've no associated
346
- // VarDecl. The given ActivationKey is therefore associated with the current
347
- // active container, if any .
358
+ // VarDecl. We store null here, and will walk up to the parent container in
359
+ // forEachActiveContainer .
348
360
void associateAnyPattern (ActivationKey K, StackEntry &Entry) const {
349
- Entry.Containers [K] = activeContainer ();
350
- }
351
-
352
- Container activeContainer () const {
353
- if (Stack.empty ())
354
- return nullptr ;
355
-
356
- const StackEntry &Entry = Stack.back ();
357
-
358
- if (Entry.ActiveKey ) {
359
- auto ActiveContainer = Entry.Containers .find (Entry.ActiveKey );
360
-
361
- if (ActiveContainer != Entry.Containers .end ())
362
- return ActiveContainer->second ;
363
- }
364
-
365
- return nullptr ;
361
+ Entry.Containers [K] = nullptr ;
366
362
}
367
363
368
364
void associateAllPatternElements (const Pattern *P, ActivationKey K,
@@ -924,7 +920,14 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
924
920
}
925
921
926
922
void addContainedByRelationIfContained (IndexSymbol &Info) {
927
- Containers.forEachActiveContainer ([&](const Decl *D) {
923
+ // Only consider the innermost container that we are allowed to index.
924
+ auto allowDecl = [&](const Decl *D) {
925
+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
926
+ return shouldIndex (VD, /* IsRef*/ true );
927
+ }
928
+ return true ;
929
+ };
930
+ Containers.forEachActiveContainer (allowDecl, [&](const Decl *D) {
928
931
addRelation (Info, (unsigned )SymbolRole::RelationContainedBy,
929
932
const_cast <Decl *>(D));
930
933
});
@@ -1044,7 +1047,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
1044
1047
return {{line, col, inGeneratedBuffer}};
1045
1048
}
1046
1049
1047
- bool shouldIndex (ValueDecl *D, bool IsRef) const {
1050
+ bool shouldIndex (const ValueDecl *D, bool IsRef) const {
1048
1051
if (D->isImplicit () && isa<VarDecl>(D) && IsRef) {
1049
1052
// Bypass the implicit VarDecls introduced in CaseStmt bodies by using the
1050
1053
// canonical VarDecl for these checks instead.
0 commit comments