@@ -216,26 +216,39 @@ 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 ;
222
-
223
- const StackEntry &Entry = Stack.back ();
224
-
225
- if (!Entry.ActiveKey )
226
- return ;
227
-
228
- auto MapEntry = Entry.Containers .find (Entry.ActiveKey );
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 ;
229
225
230
- if (MapEntry == Entry.Containers .end ())
231
- return ;
226
+ auto MapEntry = Entry.Containers .find (Entry.ActiveKey );
227
+ if (MapEntry == Entry.Containers .end ())
228
+ return ;
232
229
233
- Container C = MapEntry->second ;
230
+ bool hadViableContainer = false ;
231
+ auto tryContainer = [&](const Decl *D) {
232
+ if (!allowDecl (D))
233
+ return ;
234
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); });
235
+ f (D);
236
+ hadViableContainer = true ;
237
+ };
238
+ if (auto C = MapEntry->second ) {
239
+ if (auto *D = C.dyn_cast <const Decl *>()) {
240
+ tryContainer (D);
241
+ } else {
242
+ auto *P = C.get <const Pattern *>();
243
+ P->forEachVariable ([&](VarDecl *VD) {
244
+ tryContainer (VD);
245
+ });
246
+ }
247
+ }
248
+ // If we had a viable containers, we're done. Otherwise continue walking
249
+ // up the stack.
250
+ if (hadViableContainer)
251
+ return ;
239
252
}
240
253
}
241
254
@@ -343,26 +356,10 @@ class ContainerTracker {
343
356
}
344
357
345
358
// 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 .
359
+ // VarDecl. We store null here, and will walk up to the parent container in
360
+ // forEachActiveContainer .
348
361
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 ;
362
+ Entry.Containers [K] = nullptr ;
366
363
}
367
364
368
365
void associateAllPatternElements (const Pattern *P, ActivationKey K,
@@ -924,7 +921,14 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
924
921
}
925
922
926
923
void addContainedByRelationIfContained (IndexSymbol &Info) {
927
- Containers.forEachActiveContainer ([&](const Decl *D) {
924
+ // Only consider the innermost container that we are allowed to index.
925
+ auto allowDecl = [&](const Decl *D) {
926
+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
927
+ return shouldIndex (VD, /* IsRef*/ true );
928
+ }
929
+ return true ;
930
+ };
931
+ Containers.forEachActiveContainer (allowDecl, [&](const Decl *D) {
928
932
addRelation (Info, (unsigned )SymbolRole::RelationContainedBy,
929
933
const_cast <Decl *>(D));
930
934
});
@@ -1044,7 +1048,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
1044
1048
return {{line, col, inGeneratedBuffer}};
1045
1049
}
1046
1050
1047
- bool shouldIndex (ValueDecl *D, bool IsRef) const {
1051
+ bool shouldIndex (const ValueDecl *D, bool IsRef) const {
1048
1052
if (D->isImplicit () && isa<VarDecl>(D) && IsRef) {
1049
1053
// Bypass the implicit VarDecls introduced in CaseStmt bodies by using the
1050
1054
// canonical VarDecl for these checks instead.
0 commit comments