@@ -172,18 +172,150 @@ void UsableFilteringDeclConsumer::foundDecl(ValueDecl *D,
172172
173173 switch (reason) {
174174 case DeclVisibilityKind::LocalVariable:
175- // Skip if Loc is before the found decl, unless its a TypeDecl (whose use
176- // before its declaration is still allowed)
177- if (!isa<TypeDecl>(D) && !SM.isBeforeInBuffer (D->getLoc (), Loc))
175+ case DeclVisibilityKind::FunctionParameter:
176+ // Skip if Loc is before the found decl if the decl is a var/let decl.
177+ // Type and func decls can be referenced before its declaration, or from
178+ // within nested type decls.
179+ if (isa<VarDecl>(D)) {
180+ if (reason == DeclVisibilityKind::LocalVariable) {
181+ // Workaround for fast-completion. A loc in the current context might be
182+ // in a loc
183+ auto tmpLoc = Loc;
184+ if (D->getDeclContext () != DC) {
185+ if (auto *contextD = DC->getAsDecl ())
186+ tmpLoc = contextD->getStartLoc ();
187+ }
188+ if (!SM.isBeforeInBuffer (D->getLoc (), Loc))
189+ return ;
190+ }
191+
192+ // A type context cannot close over values defined in outer type contexts.
193+ if (D->getDeclContext ()->getInnermostTypeContext () != typeContext)
194+ return ;
195+ }
196+ break ;
197+
198+ case DeclVisibilityKind::MemberOfOutsideNominal:
199+ // A type context cannot close over members of outer type contexts, except
200+ // for type decls.
201+ if (!isa<TypeDecl>(D) && !D->isStatic ())
178202 return ;
179203 break ;
180- default :
204+
205+ case DeclVisibilityKind::MemberOfCurrentNominal:
206+ case DeclVisibilityKind::MemberOfSuper:
207+ case DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal:
208+ case DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal:
209+ case DeclVisibilityKind::DynamicLookup:
210+ // Members on 'Self' including inherited/derived ones are always usable.
211+ break ;
212+
213+ case DeclVisibilityKind::GenericParameter:
214+ // Generic params are type decls and are always usable from nested context.
215+ break ;
216+
217+ case DeclVisibilityKind::VisibleAtTopLevel:
181218 // The rest of the file is currently skipped, so no need to check
182- // decl location for VisibleAtTopLevel. Other visibility kinds are always
183- // usable
219+ // decl location for VisibleAtTopLevel.
184220 break ;
185221 }
186222
223+ // Filter out shadowed decls. Do this for only usable values even though
224+ // unusable values actually can shadow outer values, because compilers might
225+ // be able to diagnose it with fix-it to add the qualification. E.g.
226+ // func foo(global: T) {}
227+ // struct Outer {
228+ // func foo(outer: T) {}
229+ // func test() {
230+ // struct Inner {
231+ // func test() {
232+ // <HERE>
233+ // }
234+ // }
235+ // }
236+ // }
237+ // In this case 'foo(global:)' is shadowed by 'foo(outer:)', but 'foo(outer:)'
238+ // is _not_ usable because it's outside the current type context, whereas
239+ // 'foo(global:)' is still usable with 'ModuleName.' qualification.
240+ // FIXME: (for code completion,) If a global value or a static type member is
241+ // shadowd, we should suggest it with prefix (e.g. 'ModuleName.value').
242+ auto inserted = SeenNames.insert ({D->getBaseName (), {D, reason}});
243+ if (!inserted.second ) {
244+ auto shadowingReason = inserted.first ->second .second ;
245+ auto *shadowingD = inserted.first ->second .first ;
246+
247+ // A type decl cannot have overloads, and shadows everything outside the
248+ // scope.
249+ if (isa<TypeDecl>(shadowingD))
250+ return ;
251+
252+ switch (shadowingReason) {
253+ case DeclVisibilityKind::LocalVariable:
254+ case DeclVisibilityKind::FunctionParameter:
255+ // Local func and var/let with a conflicting name.
256+ // func foo() {
257+ // func value(arg: Int) {}
258+ // var value = ""
259+ // }
260+ // In this case, 'var value' wins, regardless of their source order.
261+ // So, for confilicting local values in the same decl context, even if the
262+ // 'var value' is reported after 'func value', don't shadow it, but we
263+ // shadow everything with the name after that.
264+ if (reason == DeclVisibilityKind::LocalVariable &&
265+ isa<VarDecl>(D) && !isa<VarDecl>(shadowingD) &&
266+ shadowingD->getDeclContext () == D->getDeclContext ()) {
267+ // Replace the shadowing decl so we shadow subsequent conflicting decls.
268+ inserted.first ->second = {D, reason};
269+ break ;
270+ }
271+
272+ // Otherwise, a local value shadows everything outside the scope.
273+ return ;
274+
275+ case DeclVisibilityKind::GenericParameter:
276+ // A Generic parameter is a type name. It shadows everything outside the
277+ // generic context.
278+ return ;
279+
280+ case DeclVisibilityKind::MemberOfCurrentNominal:
281+ case DeclVisibilityKind::MemberOfSuper:
282+ case DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal:
283+ case DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal:
284+ case DeclVisibilityKind::DynamicLookup:
285+ switch (reason) {
286+ case DeclVisibilityKind::MemberOfCurrentNominal:
287+ case DeclVisibilityKind::MemberOfSuper:
288+ case DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal:
289+ case DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal:
290+ case DeclVisibilityKind::DynamicLookup:
291+ // Members on the current type context don't shadow members with the
292+ // same base name on the current type contxt. They are overloads.
293+ break ;
294+ default :
295+ // Members of a type context shadows values/types outside.
296+ return ;
297+ }
298+ break ;
299+
300+ case DeclVisibilityKind::MemberOfOutsideNominal:
301+ // For static values, it's unclear _which_ type context (i.e. this type,
302+ // super classes, conforming protocols) this decl was found in. For now,
303+ // consider all the outer nominals are the same.
304+
305+ if (reason == DeclVisibilityKind::MemberOfOutsideNominal)
306+ break ;
307+
308+ // Values outside the nominal are shadowed.
309+ return ;
310+
311+ case DeclVisibilityKind::VisibleAtTopLevel:
312+ // Top level decls don't shadow anything.
313+ // Well, that's not true. Decls in the current module shadows decls in
314+ // the imported modules. But we don't care them here.
315+ break ;
316+ }
317+ }
318+
187319 ChainedConsumer.foundDecl (D, reason, dynamicLookupInfo);
188320}
189321
0 commit comments