Skip to content

Commit 2f079df

Browse files
authored
Merge pull request #5136 from benlangmuir/cc-func-ref-1
2 parents b675ce9 + d2e2d5f commit 2f079df

File tree

2 files changed

+203
-15
lines changed

2 files changed

+203
-15
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -921,22 +921,30 @@ static CodeCompletionResult::ExpectedTypeRelation calculateTypeRelation(
921921
if (auto FT = Ty->getAs<AnyFunctionType>()) {
922922
if (FT->getResult()->isVoid())
923923
return CodeCompletionResult::ExpectedTypeRelation::Invalid;
924-
return std::max(calculateTypeRelation(FT->getResult(), ExpectedTy, DC),
925-
CodeCompletionResult::ExpectedTypeRelation::Unrelated);
926924
}
927925
return CodeCompletionResult::ExpectedTypeRelation::Unrelated;
928926
}
929927

930-
static CodeCompletionResult::ExpectedTypeRelation calculateTypeRelationForDecl (
931-
const Decl *D,
932-
Type ExpectedType) {
928+
static CodeCompletionResult::ExpectedTypeRelation
929+
calculateTypeRelationForDecl(const Decl *D, Type ExpectedType,
930+
bool UseFuncResultType = true) {
933931
auto VD = dyn_cast<ValueDecl>(D);
934932
auto DC = D->getDeclContext();
935933
if (!VD)
936934
return CodeCompletionResult::ExpectedTypeRelation::Unrelated;
937-
if (auto FD = dyn_cast<FuncDecl>(VD)) {
938-
return std::max(calculateTypeRelation(FD->getType(), ExpectedType, DC),
939-
calculateTypeRelation(FD->getResultType(), ExpectedType, DC));
935+
936+
if (auto FD = dyn_cast<AbstractFunctionDecl>(VD)) {
937+
auto funcType = FD->getType()->getAs<AnyFunctionType>();
938+
if (DC->isTypeContext() && funcType && funcType->is<AnyFunctionType>())
939+
funcType = funcType->getResult()->getAs<AnyFunctionType>();
940+
if (funcType) {
941+
auto relation = calculateTypeRelation(funcType, ExpectedType, DC);
942+
if (UseFuncResultType)
943+
relation =
944+
std::max(relation, calculateTypeRelation(funcType->getResult(),
945+
ExpectedType, DC));
946+
return relation;
947+
}
940948
}
941949
if (auto NTD = dyn_cast<NominalTypeDecl>(VD)) {
942950
return std::max(calculateTypeRelation(NTD->getType(), ExpectedType, DC),
@@ -1634,6 +1642,19 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
16341642
Builder.addDeclDocCommentWords(llvm::makeArrayRef(Pairs));
16351643
}
16361644

1645+
bool shouldUseFunctionReference(AbstractFunctionDecl *D) {
1646+
if (PreferFunctionReferencesToCalls)
1647+
return true;
1648+
for (auto expectedType : ExpectedTypes) {
1649+
if (expectedType && expectedType->is<AnyFunctionType>() &&
1650+
calculateTypeRelationForDecl(D, expectedType, false) >=
1651+
CodeCompletionResult::ExpectedTypeRelation::Convertible) {
1652+
return true;
1653+
}
1654+
}
1655+
return false;
1656+
}
1657+
16371658
public:
16381659
struct RequestedResultsTy {
16391660
const Module *TheModule;
@@ -2731,10 +2752,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27312752
Builder.addTextChunk(":");
27322753
}
27332754

2734-
if (!HaveRParen)
2735-
Builder.addRightParen();
2736-
else
2737-
Builder.addAnnotatedRightParen();
2755+
Builder.addRightParen();
27382756
}
27392757
}
27402758

@@ -2757,7 +2775,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27572775
case LookupKind::ValueExpr:
27582776
if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
27592777
// Do we want compound function names here?
2760-
if (PreferFunctionReferencesToCalls) {
2778+
if (shouldUseFunctionReference(CD)) {
27612779
addCompoundFunctionName(CD, Reason);
27622780
return;
27632781
}
@@ -2821,7 +2839,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28212839
return;
28222840

28232841
// Do we want compound function names here?
2824-
if (PreferFunctionReferencesToCalls) {
2842+
if (shouldUseFunctionReference(FD)) {
28252843
addCompoundFunctionName(FD, Reason);
28262844
return;
28272845
}
@@ -2889,7 +2907,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28892907
return;
28902908

28912909
// Do we want compound function names here?
2892-
if (PreferFunctionReferencesToCalls) {
2910+
if (shouldUseFunctionReference(FD)) {
28932911
addCompoundFunctionName(FD, Reason);
28942912
return;
28952913
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_0 | %FileCheck %s -check-prefix=VOID_VOID
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_1 | %FileCheck %s -check-prefix=VOID_VOID
3+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_2 | %FileCheck %s -check-prefix=VOID_VOID
4+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_3 | %FileCheck %s -check-prefix=VOID_VOID
5+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_4 | %FileCheck %s -check-prefix=VOID_VOID
6+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_0 | %FileCheck %s -check-prefix=ANY_INT
7+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_1 | %FileCheck %s -check-prefix=ANY_INT
8+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_2 | %FileCheck %s -check-prefix=ANY_INT
9+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INT_ANY_0 | %FileCheck %s -check-prefix=INT_ANY
10+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INT_ANY_1 | %FileCheck %s -check-prefix=INT_ANY
11+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INT_ANY_2 | %FileCheck %s -check-prefix=INT_ANY
12+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_0 | %FileCheck %s -check-prefix=VOID_INT_INT
13+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_1 | %FileCheck %s -check-prefix=VOID_INT_INT
14+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_2 | %FileCheck %s -check-prefix=VOID_INT_INT
15+
16+
func voidToVoid() {}
17+
func voidToInt() -> Int {}
18+
func intToInt(a: Int) -> Int {}
19+
func intToVoid(a: Int) {}
20+
21+
func voidToAny() -> Any {}
22+
func anyToAny(a: Any) -> Any {}
23+
func anyToVoid(a: Any) {}
24+
25+
func intToAny(a: Int) -> Any {}
26+
func anyToInt(a: Any) -> Int {}
27+
28+
func returnsIntToInt() -> (Int) -> Int {}
29+
30+
struct S0 {
31+
func voidToVoid() {}
32+
func voidToInt() -> Int {}
33+
func intToInt(a: Int) -> Int {}
34+
func intToVoid(a: Int) {}
35+
36+
func voidToAny() -> Any {}
37+
func anyToAny(a: Any) -> Any {}
38+
func anyToVoid(a: Any) {}
39+
40+
func intToAny(a: Int) -> Any {}
41+
func anyToInt(a: Any) -> Int {}
42+
43+
func returnsIntToInt() -> (Int) -> Int {}
44+
45+
static func voidToVoid() {}
46+
static func voidToInt() -> Int {}
47+
static func intToInt(a: Int) -> Int {}
48+
static func intToVoid(a: Int) {}
49+
50+
static func voidToAny() -> Any {}
51+
static func anyToAny(a: Any) -> Any {}
52+
static func anyToVoid(a: Any) {}
53+
54+
static func intToAny(a: Int) -> Any {}
55+
static func anyToInt(a: Any) -> Int {}
56+
57+
static func returnsIntToInt() -> (Int) -> Int {}
58+
}
59+
60+
do {
61+
func take(_: @escaping ()->()) {}
62+
take(#^VOID_VOID_0^#)
63+
}
64+
// VOID_VOID: Begin completions
65+
// VOID_VOID-DAG: Decl{{.*}}/TypeRelation[Identical]: voidToVoid;
66+
// VOID_VOID-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToVoid(a:);
67+
// VOID_VOID-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: intToVoid({#a: Int#})[#Void#];
68+
// VOID_VOID-DAT: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: anyToVoid({#a: Any#})[#Void#];
69+
// VOID_VOID-DAG: Decl{{.*}}: anyToAny({#a: Any#})[#Any#];
70+
// VOID_VOID-DAG: Decl{{.*}}: intToAny({#a: Int#})[#Any#];
71+
// VOID_VOID-DAG: Decl{{.*}}: voidToInt()[#Int#];
72+
// VOID_VOID-DAG: Decl{{.*}}: anyToInt({#a: Any#})[#Int#];
73+
// VOID_VOID-DAG: Decl{{.*}}: intToInt({#a: Int#})[#Int#];
74+
// VOID_VOID-DAG: Decl{{.*}}: voidToAny()[#Any#];
75+
// VOID_VOID-DAG: Decl{{.*}}: returnsIntToInt()[#(Int) -> Int#];
76+
// VOID_VOID: End completions
77+
78+
do {
79+
func take(_: Int, _: Int, c: @escaping ()->()) {}
80+
take(1, 2, c: #^VOID_VOID_1^#)
81+
}
82+
83+
do {
84+
let take: ()->()
85+
take = #^VOID_VOID_2^#
86+
}
87+
do {
88+
let take: ()->()
89+
take = S0().#^VOID_VOID_3^#
90+
}
91+
do {
92+
let take: ()->()
93+
take = S0.#^VOID_VOID_4^#
94+
}
95+
96+
do {
97+
func take(_: @escaping (Any)->Int) {}
98+
take(#^ANY_INT_0^#)
99+
}
100+
do {
101+
func take(_: @escaping (Any)->Int) {}
102+
take(S0().#^ANY_INT_1^#)
103+
}
104+
do {
105+
func take(_: @escaping (Any)->Int) {}
106+
take(S0.#^ANY_INT_2^#)
107+
}
108+
109+
// ANY_INT: Begin completions
110+
// ANY_INT-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToInt(a:);
111+
// ANY_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: intToVoid({#a: Int#})[#Void#];
112+
// ANY_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: anyToVoid({#a: Any#})[#Void#];
113+
// ANY_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: voidToVoid()[#Void#];
114+
// ANY_INT-DAG: Decl{{.*}}: voidToAny()[#Any#];
115+
// ANY_INT-DAG: Decl{{.*}}: intToInt({#a: Int#})[#Int#];
116+
// ANY_INT-DAG: Decl{{.*}}: intToAny({#a: Int#})[#Any#];
117+
// ANY_INT-DAG: Decl{{.*}}: anyToAny({#a: Any#})[#Any#];
118+
// ANY_INT-DAG: Decl{{.*}}: voidToInt()[#Int#];
119+
// ANY_INT-DAG: Decl{{.*}}: returnsIntToInt()[#(Int) -> Int#];
120+
// ANY_INT: End completions
121+
122+
do {
123+
func take(_: @escaping (Int)->Any) {}
124+
take(#^INT_ANY_0^#)
125+
}
126+
127+
// INT_ANY: Begin completions
128+
// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: intToAny(a:);
129+
// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: intToInt(a:);
130+
// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: intToVoid(a:);
131+
// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToAny(a:);
132+
// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToInt(a:);
133+
// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToVoid(a:);
134+
// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: returnsIntToInt()[#(Int) -> Int#];
135+
// INT_ANY-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: voidToVoid()[#Void#];
136+
// INT_ANY-DAG: Decl{{.*}}: voidToInt()[#Int#];
137+
// INT_ANY-DAG: Decl{{.*}}: voidToAny()[#Any#];
138+
// INT_ANY: End completions
139+
140+
do {
141+
func take(_: @escaping (Int)->Any) {}
142+
take(S0().#^INT_ANY_1^#)
143+
}
144+
do {
145+
func take(_: @escaping (Int)->Any) {}
146+
take(S0.#^INT_ANY_2^#)
147+
}
148+
149+
do {
150+
func take(_: @escaping ()->(Int)->Int) {}
151+
take(#^VOID_INT_INT_0^#)
152+
}
153+
do {
154+
func take(_: @escaping ()->(Int)->Int) {}
155+
take(S0().#^VOID_INT_INT_1^#)
156+
}
157+
do {
158+
func take(_: @escaping ()->(Int)->Int) {}
159+
take(S0.#^VOID_INT_INT_2^#)
160+
}
161+
// VOID_INT_INT-DAG: Decl{{.*}}/TypeRelation[Identical]: returnsIntToInt;
162+
// VOID_INT_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: intToVoid({#a: Int#})[#Void#];
163+
// VOID_INT_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: anyToVoid({#a: Any#})[#Void#];
164+
// VOID_INT_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: voidToVoid()[#Void#];
165+
// VOID_INT_INT-DAG: Decl{{.*}}: voidToAny()[#Any#];
166+
// VOID_INT_INT-DAG: Decl{{.*}}: intToAny({#a: Int#})[#Any#];
167+
// VOID_INT_INT-DAG: Decl{{.*}}: anyToAny({#a: Any#})[#Any#];
168+
// VOID_INT_INT-DAG: Decl{{.*}}: voidToInt()[#Int#];
169+
// VOID_INT_INT-DAG: Decl{{.*}}: anyToInt({#a: Any#})[#Int#];
170+
// VOID_INT_INT-DAG: Decl{{.*}}: intToInt({#a: Int#})[#Int#];

0 commit comments

Comments
 (0)