@@ -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,
@@ -547,6 +544,10 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
547
544
548
545
bool addRelation (IndexSymbol &Info, SymbolRoleSet RelationRoles, Decl *D) {
549
546
assert (D);
547
+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
548
+ if (!shouldIndex (VD, /* IsRef*/ true ))
549
+ return true ;
550
+ }
550
551
auto Match = std::find_if (Info.Relations .begin (), Info.Relations .end (),
551
552
[D](IndexRelation R) { return R.decl == D; });
552
553
if (Match != Info.Relations .end ()) {
@@ -924,7 +925,14 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
924
925
}
925
926
926
927
void addContainedByRelationIfContained (IndexSymbol &Info) {
927
- Containers.forEachActiveContainer ([&](const Decl *D) {
928
+ // Only consider the innermost container that we are allowed to index.
929
+ auto allowDecl = [&](const Decl *D) {
930
+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
931
+ return shouldIndex (VD, /* IsRef*/ true );
932
+ }
933
+ return true ;
934
+ };
935
+ Containers.forEachActiveContainer (allowDecl, [&](const Decl *D) {
928
936
addRelation (Info, (unsigned )SymbolRole::RelationContainedBy,
929
937
const_cast <Decl *>(D));
930
938
});
@@ -1044,7 +1052,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
1044
1052
return {{line, col, inGeneratedBuffer}};
1045
1053
}
1046
1054
1047
- bool shouldIndex (ValueDecl *D, bool IsRef) const {
1055
+ bool shouldIndex (const ValueDecl *D, bool IsRef) const {
1048
1056
if (D->isImplicit () && isa<VarDecl>(D) && IsRef) {
1049
1057
// Bypass the implicit VarDecls introduced in CaseStmt bodies by using the
1050
1058
// canonical VarDecl for these checks instead.
0 commit comments