Skip to content

Commit 78d0f6a

Browse files
committed
[CodeCompletion] Primarily use getPossibleCallees() for call signature completion
instead of the pre-typechecked type and the referenced decl in the AST so that we can suggests all overloads even if it happen to be typechecked to a method. For example struct MyType { func foo() {} func foo(_ int: Int) {} func foo(name: String, value: String) {} } func test(val: MyType) { value.foo(#^COMPLETE^#) } In this case, the call is typechecked to 'MyType.foo(_:)', but we want to suggest all overloads. rdar://problem/59285399
1 parent 75c3661 commit 78d0f6a

8 files changed

+132
-73
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2379,8 +2379,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
23792379
return SemanticContextKind::OtherModule;
23802380
}
23812381

2382-
void addSubscriptCallPattern(const AnyFunctionType *AFT,
2383-
const SubscriptDecl *SD) {
2382+
void addSubscriptCallPattern(
2383+
const AnyFunctionType *AFT, const SubscriptDecl *SD,
2384+
const Optional<SemanticContextKind> SemanticContext = None) {
23842385
foundFunction(AFT);
23852386
auto genericSig =
23862387
SD->getInnermostDeclContext()->getGenericSignatureOfContext();
@@ -2390,7 +2391,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
23902391
CommandWordsPairs Pairs;
23912392
CodeCompletionResultBuilder Builder(
23922393
Sink, CodeCompletionResult::ResultKind::Declaration,
2393-
getSemanticContextKind(SD), expectedTypeContext);
2394+
SemanticContext ? *SemanticContext : getSemanticContextKind(SD),
2395+
expectedTypeContext);
23942396
Builder.setAssociatedDecl(SD);
23952397
setClangDeclKeywords(SD, Pairs, Builder);
23962398
if (!HaveLParen)
@@ -2409,8 +2411,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
24092411
addTypeAnnotation(Builder, AFT->getResult());
24102412
}
24112413

2412-
void addFunctionCallPattern(const AnyFunctionType *AFT,
2413-
const AbstractFunctionDecl *AFD = nullptr) {
2414+
void addFunctionCallPattern(
2415+
const AnyFunctionType *AFT, const AbstractFunctionDecl *AFD = nullptr,
2416+
const Optional<SemanticContextKind> SemanticContext = None) {
24142417
if (AFD) {
24152418
auto genericSig =
24162419
AFD->getInnermostDeclContext()->getGenericSignatureOfContext();
@@ -2426,7 +2429,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
24262429
Sink,
24272430
AFD ? CodeCompletionResult::ResultKind::Declaration
24282431
: CodeCompletionResult::ResultKind::Pattern,
2429-
getSemanticContextKind(AFD), expectedTypeContext);
2432+
SemanticContext ? *SemanticContext : getSemanticContextKind(AFD),
2433+
expectedTypeContext);
24302434
if (AFD) {
24312435
Builder.setAssociatedDecl(AFD);
24322436
setClangDeclKeywords(AFD, Pairs, Builder);
@@ -3216,11 +3220,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
32163220
return true;
32173221
}
32183222

3219-
bool tryFunctionCallCompletions(Type ExprType, const ValueDecl *VD) {
3223+
bool tryFunctionCallCompletions(Type ExprType, const ValueDecl *VD, Optional<SemanticContextKind> SemanticContext = None) {
32203224
ExprType = ExprType->getRValueType();
32213225
if (auto AFT = ExprType->getAs<AnyFunctionType>()) {
32223226
if (auto *AFD = dyn_cast_or_null<AbstractFunctionDecl>(VD)) {
3223-
addFunctionCallPattern(AFT, AFD);
3227+
addFunctionCallPattern(AFT, AFD, SemanticContext);
32243228
} else {
32253229
addFunctionCallPattern(AFT);
32263230
}
@@ -5354,12 +5358,13 @@ void CodeCompletionCallbacksImpl::doneParsing() {
53545358
ExprContextInfo ParentContextInfo(CurDeclContext, ParsedExpr);
53555359
Lookup.setExpectedTypes(ParentContextInfo.getPossibleTypes(),
53565360
ParentContextInfo.isSingleExpressionBody());
5357-
if (ExprType && ((*ExprType)->is<AnyFunctionType>() ||
5358-
(*ExprType)->is<AnyMetatypeType>())) {
5359-
Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
5360-
} else {
5361+
if (!ContextInfo.getPossibleCallees().empty()) {
53615362
for (auto &typeAndDecl : ContextInfo.getPossibleCallees())
5362-
Lookup.tryFunctionCallCompletions(typeAndDecl.first, typeAndDecl.second);
5363+
Lookup.tryFunctionCallCompletions(typeAndDecl.Type, typeAndDecl.Decl,
5364+
typeAndDecl.SemanticContext);
5365+
} else if (ExprType && ((*ExprType)->is<AnyFunctionType>() ||
5366+
(*ExprType)->is<AnyMetatypeType>())) {
5367+
Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
53635368
}
53645369
} else {
53655370
// Add argument labels, then fallthrough to get values.
@@ -5485,12 +5490,14 @@ void CodeCompletionCallbacksImpl::doneParsing() {
54855490
!ContextInfo.getPossibleCallees().empty()) {
54865491
Lookup.setHaveLParen(true);
54875492
for (auto &typeAndDecl : ContextInfo.getPossibleCallees()) {
5488-
if (auto SD = dyn_cast_or_null<SubscriptDecl>(typeAndDecl.second)) {
5489-
Lookup.addSubscriptCallPattern(typeAndDecl.first, SD);
5493+
if (auto SD = dyn_cast_or_null<SubscriptDecl>(typeAndDecl.Decl)) {
5494+
Lookup.addSubscriptCallPattern(typeAndDecl.Type, SD,
5495+
typeAndDecl.SemanticContext);
54905496
} else {
54915497
Lookup.addFunctionCallPattern(
5492-
typeAndDecl.first,
5493-
dyn_cast_or_null<AbstractFunctionDecl>(typeAndDecl.second));
5498+
typeAndDecl.Type,
5499+
dyn_cast_or_null<AbstractFunctionDecl>(typeAndDecl.Decl),
5500+
typeAndDecl.SemanticContext);
54945501
}
54955502
}
54965503
Lookup.setHaveLParen(false);

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/AST/Type.h"
2828
#include "swift/AST/Types.h"
2929
#include "swift/Basic/SourceManager.h"
30+
#include "swift/IDE/CodeCompletion.h"
3031
#include "swift/Sema/IDETypeChecking.h"
3132
#include "clang/AST/Attr.h"
3233
#include "clang/AST/Decl.h"
@@ -279,19 +280,21 @@ static void collectPossibleCalleesByQualifiedLookup(
279280
DeclContext &DC, Type baseTy, DeclNameRef name,
280281
SmallVectorImpl<FunctionTypeAndDecl> &candidates) {
281282
bool isOnMetaType = baseTy->is<AnyMetatypeType>();
283+
auto baseInstanceTy = baseTy->getMetatypeInstanceType();
282284

283285
SmallVector<ValueDecl *, 2> decls;
284-
if (!DC.lookupQualified(baseTy->getMetatypeInstanceType(),
286+
if (!DC.lookupQualified(baseInstanceTy,
285287
name.withoutArgumentLabels(),
286288
NL_QualifiedDefault | NL_ProtocolMembers,
287289
decls))
288290
return;
289291

292+
auto *baseNominal = baseInstanceTy->getAnyNominal();
290293
for (auto *VD : decls) {
291294
if ((!isa<AbstractFunctionDecl>(VD) && !isa<SubscriptDecl>(VD)) ||
292295
VD->shouldHideFromEditor())
293296
continue;
294-
if (!isMemberDeclApplied(&DC, baseTy->getMetatypeInstanceType(), VD))
297+
if (!isMemberDeclApplied(&DC, baseInstanceTy, VD))
295298
continue;
296299
Type declaredMemberType = VD->getInterfaceType();
297300
if (!declaredMemberType->is<AnyFunctionType>())
@@ -314,16 +317,15 @@ static void collectPossibleCalleesByQualifiedLookup(
314317
}
315318
}
316319

317-
auto subs = baseTy->getMetatypeInstanceType()->getMemberSubstitutionMap(
320+
auto subs = baseInstanceTy->getMemberSubstitutionMap(
318321
DC.getParentModule(), VD,
319322
VD->getInnermostDeclContext()->getGenericEnvironmentOfContext());
320323
auto fnType = declaredMemberType.subst(subs);
321324
if (!fnType)
322325
continue;
323326

324327
if (fnType->is<AnyFunctionType>()) {
325-
auto baseInstanceTy = baseTy->getMetatypeInstanceType();
326-
// If we are calling to typealias type,
328+
// If we are calling to typealias type,
327329
if (isa<SugarType>(baseInstanceTy.getPointer())) {
328330
auto canBaseTy = baseInstanceTy->getCanonicalType();
329331
fnType = fnType.transform([&](Type t) -> Type {
@@ -332,7 +334,13 @@ static void collectPossibleCalleesByQualifiedLookup(
332334
return t;
333335
});
334336
}
335-
candidates.emplace_back(fnType->castTo<AnyFunctionType>(), VD);
337+
auto semanticContext = SemanticContextKind::CurrentNominal;
338+
if (baseNominal &&
339+
VD->getDeclContext()->getSelfNominalTypeDecl() != baseNominal)
340+
semanticContext = SemanticContextKind::Super;
341+
342+
candidates.emplace_back(fnType->castTo<AnyFunctionType>(), VD,
343+
semanticContext);
336344
}
337345
}
338346
}
@@ -347,10 +355,16 @@ static void collectPossibleCalleesByQualifiedLookup(
347355
DC.getASTContext(), &DC, CompletionTypeCheckKind::Normal, baseExpr, ref);
348356
if (!baseTyOpt)
349357
return;
350-
auto baseTy = (*baseTyOpt)->getRValueType();
358+
359+
auto baseTy = (*baseTyOpt)->getWithoutSpecifierType();
351360
if (!baseTy->getMetatypeInstanceType()->mayHaveMembers())
352361
return;
353362

363+
// Use metatype for lookup 'super.init' if it's inside constructors.
364+
if (isa<SuperRefExpr>(baseExpr) && isa<ConstructorDecl>(DC) &&
365+
name == DeclNameRef::createConstructor())
366+
baseTy = MetatypeType::get(baseTy);
367+
354368
collectPossibleCalleesByQualifiedLookup(DC, baseTy, name, candidates);
355369
}
356370

@@ -360,24 +374,17 @@ static bool collectPossibleCalleesForApply(
360374
SmallVectorImpl<FunctionTypeAndDecl> &candidates) {
361375
auto *fnExpr = callExpr->getFn();
362376

363-
if (auto type = fnExpr->getType()) {
364-
if (!type->hasUnresolvedType() && !type->hasError()) {
365-
if (auto *funcType = type->getAs<AnyFunctionType>()) {
366-
auto refDecl = fnExpr->getReferencedDecl();
367-
if (!refDecl)
368-
if (auto apply = dyn_cast<ApplyExpr>(fnExpr))
369-
refDecl = apply->getFn()->getReferencedDecl();
370-
candidates.emplace_back(funcType, refDecl.getDecl());
371-
return true;
372-
}
373-
}
374-
}
375-
376377
if (auto *DRE = dyn_cast<DeclRefExpr>(fnExpr)) {
377378
if (auto *decl = DRE->getDecl()) {
378-
if (decl->hasInterfaceType())
379-
if (auto *funcType = decl->getInterfaceType()->getAs<AnyFunctionType>())
380-
candidates.emplace_back(funcType, decl);
379+
Type fnType = fnExpr->getType();
380+
if ((!fnType || fnType->hasError() || fnType->hasUnresolvedType()) &&
381+
decl->hasInterfaceType())
382+
fnType = decl->getInterfaceType();
383+
if (fnType) {
384+
fnType = fnType->getWithoutSpecifierType();
385+
if (auto *funcTy = fnType->getAs<AnyFunctionType>())
386+
candidates.emplace_back(funcTy, decl);
387+
}
381388
}
382389
} else if (auto *OSRE = dyn_cast<OverloadSetRefExpr>(fnExpr)) {
383390
for (auto *decl : OSRE->getDecls()) {
@@ -386,30 +393,49 @@ static bool collectPossibleCalleesForApply(
386393
candidates.emplace_back(funcType, decl);
387394
}
388395
} else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(fnExpr)) {
389-
collectPossibleCalleesByQualifiedLookup(
390-
DC, UDE->getBase(), UDE->getName(), candidates);
396+
collectPossibleCalleesByQualifiedLookup(DC, UDE->getBase(), UDE->getName(),
397+
candidates);
391398
} else if (auto *DSCE = dyn_cast<DotSyntaxCallExpr>(fnExpr)) {
392399
if (auto *DRE = dyn_cast<DeclRefExpr>(DSCE->getFn())) {
393-
collectPossibleCalleesByQualifiedLookup(
394-
DC, DSCE->getArg(), DeclNameRef(DRE->getDecl()->getFullName()),
395-
candidates);
400+
collectPossibleCalleesByQualifiedLookup(
401+
DC, DSCE->getArg(), DeclNameRef(DRE->getDecl()->getFullName()),
402+
candidates);
396403
}
404+
} else if (auto CRCE = dyn_cast<ConstructorRefCallExpr>(fnExpr)) {
405+
collectPossibleCalleesByQualifiedLookup(
406+
DC, CRCE->getArg(), DeclNameRef::createConstructor(), candidates);
397407
}
398408

399-
if (candidates.empty()) {
400-
ConcreteDeclRef ref = nullptr;
401-
auto fnType = getTypeOfCompletionContextExpr(
402-
DC.getASTContext(), &DC, CompletionTypeCheckKind::Normal, fnExpr, ref);
403-
if (!fnType)
404-
return false;
409+
if (!candidates.empty())
410+
return true;
405411

406-
if (auto *AFT = (*fnType)->getAs<AnyFunctionType>()) {
407-
candidates.emplace_back(AFT, ref.getDecl());
408-
} else if (auto *AMT = (*fnType)->getAs<AnyMetatypeType>()) {
409-
auto baseTy = AMT->getInstanceType();
410-
if (baseTy->mayHaveMembers())
411-
collectPossibleCalleesByQualifiedLookup(
412-
DC, AMT, DeclNameRef::createConstructor(), candidates);
412+
ConcreteDeclRef refDecl = nullptr;
413+
Type fnType = fnExpr->getType();
414+
if (fnType) {
415+
refDecl = fnExpr->getReferencedDecl();
416+
if (!refDecl)
417+
if (auto apply = dyn_cast<ApplyExpr>(fnExpr))
418+
refDecl = apply->getFn()->getReferencedDecl();
419+
}
420+
if (!fnType) {
421+
auto fnTypeOpt = getTypeOfCompletionContextExpr(
422+
DC.getASTContext(), &DC, CompletionTypeCheckKind::Normal, fnExpr,
423+
refDecl);
424+
if (fnTypeOpt)
425+
fnType = *fnTypeOpt;
426+
}
427+
428+
if (!fnType || fnType->hasUnresolvedType() || fnType->hasError())
429+
return false;
430+
fnType = fnType->getWithoutSpecifierType();
431+
432+
if (auto *AFT = fnType->getAs<AnyFunctionType>()) {
433+
candidates.emplace_back(AFT, refDecl.getDecl());
434+
} else if (auto *AMT = fnType->getAs<AnyMetatypeType>()) {
435+
auto baseTy = AMT->getInstanceType();
436+
if (isa<TypeExpr>(fnExpr) && baseTy->mayHaveMembers()) {
437+
collectPossibleCalleesByQualifiedLookup(
438+
DC, AMT, DeclNameRef::createConstructor(), candidates);
413439
}
414440
}
415441

@@ -454,7 +480,7 @@ static bool collectPossibleCalleesForUnresolvedMember(
454480
members);
455481
for (auto member : members) {
456482
if (isReferenceableByImplicitMemberExpr(currModule, &DC, expectedTy,
457-
member.second))
483+
member.Decl))
458484
candidates.push_back(member);
459485
}
460486
}
@@ -549,12 +575,12 @@ class ExprContextAnalyzer {
549575
SmallPtrSet<Identifier, 4> seenNames;
550576
for (auto &typeAndDecl : Candidates) {
551577
DeclContext *memberDC = nullptr;
552-
if (typeAndDecl.second)
553-
memberDC = typeAndDecl.second->getInnermostDeclContext();
578+
if (typeAndDecl.Decl)
579+
memberDC = typeAndDecl.Decl->getInnermostDeclContext();
554580

555-
auto Params = typeAndDecl.first->getParams();
581+
auto Params = typeAndDecl.Type->getParams();
556582
ParameterList *paramList = nullptr;
557-
if (auto VD = typeAndDecl.second) {
583+
if (auto VD = typeAndDecl.Decl) {
558584
if (auto FD = dyn_cast<AbstractFunctionDecl>(VD))
559585
paramList = FD->getParameters();
560586
else if (auto SD = dyn_cast<SubscriptDecl>(VD))

lib/IDE/ExprContextAnalysis.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ValueDecl;
2424
class AnyFunctionType;
2525

2626
namespace ide {
27+
enum class SemanticContextKind;
2728

2829
/// Type check parent contexts of the given decl context, and the body of the
2930
/// given context until \c Loc if the context is a function body.
@@ -37,7 +38,17 @@ Expr *findParsedExpr(const DeclContext *DC, SourceRange TargetRange);
3738
/// \p DC should be an \c AbstractFunctionDecl or an \c AbstractClosureExpr.
3839
Type getReturnTypeFromContext(const DeclContext *DC);
3940

40-
using FunctionTypeAndDecl = std::pair<AnyFunctionType *, ValueDecl *>;
41+
struct FunctionTypeAndDecl {
42+
AnyFunctionType *Type;
43+
ValueDecl *Decl;
44+
Optional<SemanticContextKind> SemanticContext;
45+
46+
FunctionTypeAndDecl(AnyFunctionType *Type, ValueDecl *Decl)
47+
: Type(Type), Decl(Decl) {}
48+
FunctionTypeAndDecl(AnyFunctionType *Type, ValueDecl *Decl,
49+
SemanticContextKind SemanticContext)
50+
: Type(Type), Decl(Decl), SemanticContext(SemanticContext) {}
51+
};
4152

4253
/// Given an expression and its decl context, the analyzer tries to figure out
4354
/// the expected type of the expression by analyzing its context.

test/IDE/complete_at_top_level.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ func resyncParserB14() {}
470470
var stringInterp = "\(#^STRING_INTERP_3^#)"
471471
_ = "" + "\(#^STRING_INTERP_4^#)" + ""
472472
// STRING_INTERP: Begin completions
473-
// STRING_INTERP-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(value): _#}[')'][#Void#]; name=value: _
473+
// STRING_INTERP-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(value): T#}[')'][#Void#];
474474
// STRING_INTERP-DAG: Decl[Struct]/CurrModule: FooStruct[#FooStruct#];
475475
// STRING_INTERP-DAG: Decl[FreeFunction]/CurrModule/NotRecommended/TypeRelation[Invalid]: fooFunc1()[#Void#];
476476
// STRING_INTERP-DAG: Decl[FreeFunction]/CurrModule: optStr()[#String?#];

test/IDE/complete_call_arg.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393

9494
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARCHETYPE_GENERIC_1 | %FileCheck %s -check-prefix=ARCHETYPE_GENERIC_1
9595
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PARAM_WITH_ERROR_AUTOCLOSURE| %FileCheck %s -check-prefix=PARAM_WITH_ERROR_AUTOCLOSURE
96+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TYPECHECKED_OVERLOADED | %FileCheck %s -check-prefix=TYPECHECKED_OVERLOADED
9697

9798
var i1 = 1
9899
var i2 = 2
@@ -737,7 +738,7 @@ struct Wrap<T> {
737738
func testGenricMethodOnGenericOfArchetype<Wrapped>(value: Wrap<Wrapped>) {
738739
value.method(#^ARCHETYPE_GENERIC_1^#)
739740
// ARCHETYPE_GENERIC_1: Begin completions
740-
// ARCHETYPE_GENERIC_1: Decl[InstanceMethod]/CurrNominal: ['(']{#(fn): (Wrapped) -> _##(Wrapped) -> _#}[')'][#Wrap<_>#];
741+
// ARCHETYPE_GENERIC_1: Decl[InstanceMethod]/CurrNominal: ['(']{#(fn): (Wrapped) -> U##(Wrapped) -> U#}[')'][#Wrap<U>#];
741742
}
742743

743744
struct TestHasErrorAutoclosureParam {
@@ -751,3 +752,17 @@ struct TestHasErrorAutoclosureParam {
751752
// PARAM_WITH_ERROR_AUTOCLOSURE: End completions
752753
}
753754
}
755+
756+
struct MyType {
757+
func overloaded() {}
758+
func overloaded(_ int: Int) {}
759+
func overloaded(name: String, value: String) {}
760+
}
761+
func testTypecheckedOverloaded(value: MyType) {
762+
value.overloaded(#^TYPECHECKED_OVERLOADED^#)
763+
// TYPECHECKED_OVERLOADED: Begin completions
764+
// TYPECHECKED_OVERLOADED-DAG: Decl[InstanceMethod]/CurrNominal: ['('][')'][#Void#];
765+
// TYPECHECKED_OVERLOADED-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(int): Int#}[')'][#Void#];
766+
// TYPECHECKED_OVERLOADED-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#name: String#}, {#value: String#}[')'][#Void#];
767+
// TYPECHECKED_OVERLOADED: End completions
768+
}

0 commit comments

Comments
 (0)