[CodeCompletion] Unresolved member completion at type parameter context

We need to map 'GenericTypeParamType' to 'ArchetypeType' to lookup its
members.

rdar://problem/46657585
This commit is contained in:
Rintaro Ishizaki
2018-12-12 20:18:31 +09:00
parent 1e27f21ed2
commit 4b39c20ace
2 changed files with 134 additions and 10 deletions

View File

@@ -1523,10 +1523,10 @@ static Type getReturnTypeFromContext(const DeclContext *DC) {
if (FD->getDeclContext()->isTypeContext())
Ty = FD->getMethodInterfaceType();
if (auto FT = Ty->getAs<AnyFunctionType>())
return FT->getResult();
return DC->mapTypeIntoContext(FT->getResult());
}
} else if (auto ACE = dyn_cast<AbstractClosureExpr>(DC)) {
if (ACE->getType())
if (ACE->getType() && !ACE->getType()->hasError())
return ACE->getResultType();
if (auto CE = dyn_cast<ClosureExpr>(ACE)) {
if (CE->hasExplicitResultType())
@@ -3670,9 +3670,11 @@ public:
}
void getUnresolvedMemberCompletions(Type T) {
if (!T->getNominalOrBoundGenericNominal())
if (!T->mayHaveMembers())
return;
ModuleDecl *CurrModule = CurrDeclContext->getParentModule();
// We can only say .foo where foo is a static member of the contextual
// type and has the same type (or if the member is a function, then the
// same result type) as the contextual type.
@@ -3704,8 +3706,8 @@ public:
}
// Otherwise, check the result type matches the contextual type.
auto declTy = getTypeOfMember(VD, T);
if (declTy->hasError())
auto declTy = T->getTypeOfMember(CurrModule, VD);
if (declTy->is<ErrorType>())
return false;
DeclContext *DC = const_cast<DeclContext *>(CurrDeclContext);
@@ -5174,6 +5176,7 @@ class CodeCompletionTypeContextAnalyzer {
void recordPossibleType(Type ty) {
if (!ty || ty->is<ErrorType>())
return;
PossibleTypes.push_back(ty->getRValueType());
}
@@ -5212,6 +5215,10 @@ class CodeCompletionTypeContextAnalyzer {
SmallPtrSet<TypeBase *, 4> seenTypes;
SmallPtrSet<Identifier, 4> seenNames;
for (auto &typeAndDecl : Candidates) {
DeclContext *memberDC = nullptr;
if (typeAndDecl.second)
memberDC = typeAndDecl.second->getInnermostDeclContext();
auto Params = typeAndDecl.first->getParams();
if (Position >= Params.size())
continue;
@@ -5220,8 +5227,11 @@ class CodeCompletionTypeContextAnalyzer {
if (seenNames.insert(Param.getLabel()).second)
recordPossibleName(Param.getLabel().str());
} else {
if (seenTypes.insert(Param.getOldType().getPointer()).second)
recordPossibleType(Param.getOldType());
Type ty = Param.getOldType();
if (memberDC && ty->hasTypeParameter())
ty = memberDC->mapTypeIntoContext(ty);
if (seenTypes.insert(ty.getPointer()).second)
recordPossibleType(ty);
}
}
}
@@ -5302,8 +5312,11 @@ public:
if (auto type = destExpr->getType()) {
recordPossibleType(type);
} else if (auto *DRE = dyn_cast<DeclRefExpr>(destExpr)) {
if (auto *decl = DRE->getDecl())
recordPossibleType(decl->getInterfaceType());
if (auto *decl = DRE->getDecl()) {
if (decl->hasInterfaceType())
recordPossibleType(decl->getDeclContext()->mapTypeIntoContext(
decl->getInterfaceType()));
}
}
}
break;
@@ -5398,7 +5411,8 @@ public:
auto ExprPat = cast<ExprPattern>(P);
if (auto D = ExprPat->getMatchVar()) {
if (D->hasInterfaceType())
recordPossibleType(D->getInterfaceType());
recordPossibleType(
D->getDeclContext()->mapTypeIntoContext(D->getInterfaceType()));
}
break;
}

View File

@@ -78,6 +78,28 @@
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOADED_INIT_1 | %FileCheck %s -check-prefix=OVERLOADED_METHOD_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOADED_INIT_2 | %FileCheck %s -check-prefix=OVERLOADED_METHOD_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_1 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_2 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_3 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_4 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_5 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_6 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_7 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_8 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_9 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_10 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_11 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_12 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_13 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_14 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_15 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_16 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_17 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_18 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_19 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_20 | %FileCheck %s -check-prefix=GENERICPARAM_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_21 | %FileCheck %s -check-prefix=GENERICPARAM_1
enum SomeEnum1 {
case South
case North
@@ -535,3 +557,91 @@ func testOverload(val: HasOverloaded) {
let _ = HasOverloaded(e: .#^OVERLOADED_INIT_2^#)
// Same as OVERLOADED_METHOD_1.
}
protocol HasStatic {
static var instance: Self { get }
}
func receiveHasStatic<T: HasStatic>(x: T) {}
func testingGenericParam1<T: HasStatic>(x: inout T, fn: (T) -> Void) -> T {
x = .#^GENERICPARAM_1^#
// GENERICPARAM_1: Begin completions, 1 items
// GENERICPARAM_1: Decl[StaticVar]/CurrNominal: instance[#HasStatic#]; name=instance
// GENERICPARAM_1: End completions
/* Parser sync. */;
let _: (Int, T) = (1, .#^GENERICPARAM_2^#)
// Same as GENERICPARAM_1.
(_, x) = (1, .#^GENERICPARAM_3^#)
// Same as GENERICPARAM_1.
let _ = fn(.#^GENERICPARAM_4^#)
// Same as GENERICPARAM_1.
let _ = receiveHasStatic(x: .#^GENERICPARAM_5^#)
// Same as GENERICPARAM_1.
let _ = { () -> T in
return .#^GENERICPARAM_6^#
// Same as GENERICPARAM_1.
}
let _: () -> T = {
return .#^GENERICPARAM_7^#
// Same as GENERICPARAM_1.
}
let _ = { (_: InvalidTy) -> T in
return .#^GENERICPARAM_8^#
// Same as GENERICPARAM_1.
}
if case .#^GENERICPARAM_9^# = x {}
// Same as GENERICPARAM_1.
return .#^GENERICPARAM_10^#
// Same as GENERICPARAM_1.
}
class C<T: HasStatic> {
var t: T = .instance
func foo(x: T) -> T {
return .#^GENERICPARAM_11^#
// Same as GENERICPARAM_1.
}
func bar<U: HasStatic>(x: U) -> U {
return .#^GENERICPARAM_12^#
// Same as GENERICPARAM_1.
}
func testing() {
let _ = foo(x: .#^GENERICPARAM_13^#)
// Same as GENERICPARAM_1.
let _ = bar(x: .#^GENERICPARAM_14^#)
// Same as GENERICPARAM_1.
t = .#^GENERICPARAM_15^#
// Same as GENERICPARAM_1.
/* Parser sync. */; func sync1() {}
self.t = .#^GENERICPARAM_16^#
// Same as GENERICPARAM_1.
/* Parser sync. */; func sync2() {}
(_, t) = (1, .#^GENERICPARAM_17^#)
// Same as GENERICPARAM_1.
(_, self.t) = (1, .#^GENERICPARAM_18^#)
// Same as GENERICPARAM_1.
}
}
func testingGenericParam2<X>(obj: C<X>) {
let _ = obj.foo(x: .#^GENERICPARAM_19^#)
// Same as GENERICPARAM_1.
let _ = obj.bar(x: .#^GENERICPARAM_20^#)
// Same as GENERICPARAM_1.
obj.t = .#^GENERICPARAM_21^#
// Same as GENERICPARAM_1.
}