Skip to content

Commit 18582d3

Browse files
committed
[CodeCompletion] Handle ExprPattern in context type analysis
This improves type inference for code completion in argument position of EnumElementPattern.
1 parent c01eb93 commit 18582d3

File tree

4 files changed

+66
-9
lines changed

4 files changed

+66
-9
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4974,6 +4974,18 @@ namespace {
49744974
Ancestors.pop_back();
49754975
return true;
49764976
}
4977+
4978+
std::pair<bool, Pattern *> walkToPatternPre(Pattern *P) override {
4979+
if (Predicate(P))
4980+
Ancestors.push_back(P);
4981+
return { true, P };
4982+
}
4983+
4984+
Pattern *walkToPatternPost(Pattern *P) override {
4985+
if (Predicate(P))
4986+
Ancestors.pop_back();
4987+
return P;
4988+
}
49774989
};
49784990
} // end anonymous namespace
49794991

@@ -5020,6 +5032,13 @@ class CodeCompletionTypeContextAnalyzer {
50205032
default:
50215033
return false;
50225034
}
5035+
} else if (auto P = Node.getAsPattern()) {
5036+
switch (P->getKind()) {
5037+
case PatternKind::Expr:
5038+
return true;
5039+
default:
5040+
return false;
5041+
}
50235042
} else
50245043
return false;
50255044
}) {}
@@ -5060,7 +5079,7 @@ class CodeCompletionTypeContextAnalyzer {
50605079
break;
50615080
}
50625081
default:
5063-
llvm_unreachable("Unhandled expression kinds.");
5082+
llvm_unreachable("Unhandled expression kind.");
50645083
}
50655084
}
50665085

@@ -5085,7 +5104,7 @@ class CodeCompletionTypeContextAnalyzer {
50855104
}
50865105
break;
50875106
default:
5088-
llvm_unreachable("Unhandled statement kinds.");
5107+
llvm_unreachable("Unhandled statement kind.");
50895108
}
50905109
}
50915110

@@ -5127,7 +5146,22 @@ class CodeCompletionTypeContextAnalyzer {
51275146
break;
51285147
}
51295148
default:
5130-
llvm_unreachable("Unhandled decl kinds.");
5149+
llvm_unreachable("Unhandled decl kind.");
5150+
}
5151+
}
5152+
5153+
void analyzePattern(Pattern *P, llvm::function_ref<void(Type)> Callback) {
5154+
switch (P->getKind()) {
5155+
case PatternKind::Expr: {
5156+
auto ExprPat = cast<ExprPattern>(P);
5157+
if (auto D = ExprPat->getMatchVar()) {
5158+
if (D->hasInterfaceType())
5159+
Callback(D->getInterfaceType());
5160+
}
5161+
break;
5162+
}
5163+
default:
5164+
llvm_unreachable("Unhandled pattern kind.");
51315165
}
51325166
}
51335167

@@ -5155,6 +5189,8 @@ class CodeCompletionTypeContextAnalyzer {
51555189
analyzeStmt(Parent, Callback);
51565190
} else if (auto Parent = It->getAsDecl()) {
51575191
analyzeDecl(Parent, Callback);
5192+
} else if (auto Parent = It->getAsPattern()) {
5193+
analyzePattern(Parent, Callback);
51585194
}
51595195
if (!PossibleTypes.empty() || !PossibleNames.empty())
51605196
return true;

lib/Parse/ParsePattern.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,10 +1109,9 @@ ParserResult<Pattern> Parser::parseMatchingPattern(bool isExprBasic) {
11091109
// disambiguate.
11101110
ParserResult<Expr> subExpr =
11111111
parseExprImpl(diag::expected_pattern, isExprBasic);
1112-
if (subExpr.hasCodeCompletion())
1113-
return makeParserCodeCompletionStatus();
1112+
ParserStatus status = subExpr;
11141113
if (subExpr.isNull())
1115-
return nullptr;
1114+
return status;
11161115

11171116
if (SyntaxContext->isEnabled()) {
11181117
if (auto UPES = PatternCtx.popIf<UnresolvedPatternExprSyntax>()) {
@@ -1125,9 +1124,9 @@ ParserResult<Pattern> Parser::parseMatchingPattern(bool isExprBasic) {
11251124
// obvious pattern, which will come back wrapped in an immediate
11261125
// UnresolvedPatternExpr. Transform this now to simplify later code.
11271126
if (auto *UPE = dyn_cast<UnresolvedPatternExpr>(subExpr.get()))
1128-
return makeParserResult(UPE->getSubPattern());
1127+
return makeParserResult(status, UPE->getSubPattern());
11291128

1130-
return makeParserResult(new (Context) ExprPattern(subExpr.get()));
1129+
return makeParserResult(status, new (Context) ExprPattern(subExpr.get()));
11311130
}
11321131

11331132
ParserResult<Pattern> Parser::parseMatchingPatternAsLetOrVar(bool isLet,

test/IDE/complete_enum_elements.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
// RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT < %t.enum.txt
2929

3030
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_SW_IN_PATTERN_1 > %t.enum.txt
31-
// RUN: %FileCheck %s -check-prefix=WITH_GLOBAL_RESULTS < %t.enum.txt
31+
// RUN: %FileCheck %s -check-prefix=WITH_GLOBAL_RESULTS_INVALID < %t.enum.txt
3232
// RUN: %FileCheck %s -check-prefix=ENUM_SW_IN_PATTERN_1 < %t.enum.txt
3333

3434
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_SW_IN_PATTERN_2 > %t.enum.txt
@@ -280,6 +280,10 @@ func freeFunc() {}
280280
// WITH_GLOBAL_RESULTS: Decl[FreeFunction]/CurrModule: freeFunc()[#Void#]{{; name=.+$}}
281281
// WITH_GLOBAL_RESULTS: End completions
282282

283+
// WITH_GLOBAL_RESULTS_INVALID: Begin completions
284+
// WITH_GLOBAL_RESULTS_INVALID: Decl[FreeFunction]/CurrModule/NotRecommended/TypeRelation[Invalid]: freeFunc()[#Void#]{{; name=.+$}}
285+
// WITH_GLOBAL_RESULTS_INVALID: End completions
286+
283287
//===--- Complete enum elements in 'switch'.
284288

285289
func testSwitch1(e: FooEnum) {

test/IDE/complete_pattern.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MULTI_PATTERN_3 | %FileCheck %s -check-prefix=MULTI_PATTERN_3
5656
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MULTI_PATTERN_4 | %FileCheck %s -check-prefix=MULTI_PATTERN_4
5757

58+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CC_IN_PATTERN_1 | %FileCheck %s -check-prefix=CC_IN_PATTERN_1
59+
5860

5961
//===--- Helper types that are used in this test
6062

@@ -261,3 +263,19 @@ func test_multiple_patterns4(x: Int) {
261263
// MULTI_PATTERN_4-DAG: Decl[LocalVar]/Local: x[#Int#]{{; name=.+$}}
262264
// MULTI_PATTERN_4: End completions
263265

266+
enum IntHolder {
267+
case hold(Int)
268+
}
269+
func ident(int: Int) -> Int { return int }
270+
func ident(double: Double) -> Int { return Double }
271+
272+
func test_cc_in_pattern(subject: IntHolder, i1: Int) {
273+
switch subject {
274+
case .hold(#^CC_IN_PATTERN_1^#):
275+
()
276+
}
277+
}
278+
279+
// CC_IN_PATTERN_1: Begin completions
280+
// CC_IN_PATTERN_1-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: i1[#Int#]; name=i1
281+
// CC_IN_PATTERN_1: End completions

0 commit comments

Comments
 (0)