@@ -172,18 +172,150 @@ void UsableFilteringDeclConsumer::foundDecl(ValueDecl *D,
172
172
173
173
switch (reason) {
174
174
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 ())
178
202
return ;
179
203
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:
181
218
// 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.
184
220
break ;
185
221
}
186
222
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
+
187
319
ChainedConsumer.foundDecl (D, reason, dynamicLookupInfo);
188
320
}
189
321
0 commit comments