mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user