Skip to content

Commit d898f6d

Browse files
committed
[CodeCompletetion] Handle binary/unary expression in context type analyzer
Don't discard parsed expression in Parser. This improves type inference for CodeCompletionExpr.
1 parent 0dfbf76 commit d898f6d

File tree

4 files changed

+57
-16
lines changed

4 files changed

+57
-16
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3900,7 +3900,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39003900
using FunctionParams = ArrayRef<AnyFunctionType::Param>;
39013901

39023902
static bool
3903-
collectPossibleParamLists(DeclContext &DC, CallExpr *callExpr,
3903+
collectPossibleParamLists(DeclContext &DC, ApplyExpr *callExpr,
39043904
SmallVectorImpl<FunctionParams> &candidates) {
39053905
auto *fnExpr = callExpr->getFn();
39063906

@@ -3967,7 +3967,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39673967
}
39683968

39693969
static bool
3970-
collectArgumentExpectation(DeclContext &DC, CallExpr *CallE, Expr *CCExpr,
3970+
collectArgumentExpectation(DeclContext &DC, ApplyExpr *CallE, Expr *CCExpr,
39713971
std::vector<Type> &ExpectedTypes,
39723972
std::vector<StringRef> &ExpectedNames) {
39733973
// Collect parameter lists for possible func decls.
@@ -3981,15 +3981,16 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39813981
if (!getPositionInArgs(DC, CallE->getArg(), CCExpr, Position, HasName))
39823982
return false;
39833983

3984-
// Collect possible types at the position.
3984+
// Collect possible types (or labels) at the position.
39853985
{
3986+
bool MayNeedName = !HasName && isa<CallExpr>(CallE);
39863987
SmallPtrSet<TypeBase *, 4> seenTypes;
39873988
SmallPtrSet<Identifier, 4> seenNames;
39883989
for (auto Params : Candidates) {
39893990
if (Position >= Params.size())
39903991
continue;
39913992
const auto &Param = Params[Position];
3992-
if (Param.hasLabel() && !HasName) {
3993+
if (Param.hasLabel() && MayNeedName) {
39933994
if (seenNames.insert(Param.getLabel()).second)
39943995
ExpectedNames.push_back(Param.getLabel().str());
39953996
} else {
@@ -4992,6 +4993,8 @@ class CodeCompletionTypeContextAnalyzer {
49924993
if (auto E = Node.dyn_cast<Expr *>()) {
49934994
switch(E->getKind()) {
49944995
case ExprKind::Call:
4996+
case ExprKind::Binary:
4997+
case ExprKind::PrefixUnary:
49954998
case ExprKind::Assign:
49964999
return true;
49975000
default:
@@ -5023,11 +5026,13 @@ class CodeCompletionTypeContextAnalyzer {
50235026
void analyzeExpr(Expr *Parent, llvm::function_ref<void(Type)> Callback,
50245027
SmallVectorImpl<StringRef> &PossibleNames) {
50255028
switch (Parent->getKind()) {
5026-
case ExprKind::Call: {
5029+
case ExprKind::Call:
5030+
case ExprKind::Binary:
5031+
case ExprKind::PrefixUnary: {
50275032
std::vector<Type> PotentialTypes;
50285033
std::vector<StringRef> ExpectedNames;
50295034
CompletionLookup::collectArgumentExpectation(
5030-
*DC, cast<CallExpr>(Parent), ParsedExpr, PotentialTypes,
5035+
*DC, cast<ApplyExpr>(Parent), ParsedExpr, PotentialTypes,
50315036
ExpectedNames);
50325037
for (Type Ty : PotentialTypes)
50335038
Callback(Ty);

lib/Parse/ParseExpr.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -532,10 +532,9 @@ ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
532532
}
533533

534534
ParserResult<Expr> SubExpr = parseExprUnary(Message, isExprBasic);
535-
if (SubExpr.hasCodeCompletion())
536-
return makeParserCodeCompletionResult<Expr>();
535+
ParserStatus Status = SubExpr;
537536
if (SubExpr.isNull())
538-
return nullptr;
537+
return Status;
539538

540539
// We are sure we can create a prefix prefix operator expr now.
541540
UnaryContext.setCreateSyntax(SyntaxKind::PrefixOperatorExpr);
@@ -545,12 +544,13 @@ ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
545544
if (auto *LE = dyn_cast<NumberLiteralExpr>(SubExpr.get())) {
546545
if (Operator->hasName() && Operator->getName().getBaseName() == "-") {
547546
LE->setNegative(Operator->getLoc());
548-
return makeParserResult(LE);
547+
return makeParserResult(Status, LE);
549548
}
550549
}
551550

552-
return makeParserResult(new (Context) PrefixUnaryExpr(
553-
Operator, formUnaryArgument(Context, SubExpr.get())));
551+
return makeParserResult(
552+
Status, new (Context) PrefixUnaryExpr(
553+
Operator, formUnaryArgument(Context, SubExpr.get())));
554554
}
555555

556556
/// expr-keypath-swift:
@@ -1667,9 +1667,6 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
16671667
rParenLoc,
16681668
trailingClosure,
16691669
SyntaxKind::FunctionCallArgumentList);
1670-
if (status.isError())
1671-
return nullptr;
1672-
16731670
SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr);
16741671
return makeParserResult(
16751672
status,

test/IDE/complete_expr_postfix_begin.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_TYPEALIAS_2 | %FileCheck %s -check-prefix=MY_ALIAS_2
5959

6060
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FOR_EACH_1 | %FileCheck %s -check-prefix=IN_FOR_EACH_1
61-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FOR_EACH_2 | %FileCheck %s -check-prefix=IN_FOR_EACH_1
61+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FOR_EACH_2 | %FileCheck %s -check-prefix=IN_FOR_EACH_2
6262
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FOR_EACH_3 | %FileCheck %s -check-prefix=IN_FOR_EACH_3
6363
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FOR_EACH_4 | %FileCheck %s -check-prefix=IN_FOR_EACH_3
6464
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FOR_EACH_5 | %FileCheck %s -check-prefix=IN_FOR_EACH_1
@@ -443,6 +443,12 @@ func testInForEach2(arg: Int) {
443443
let inBody = 3
444444
}
445445
let after = 4
446+
// IN_FOR_EACH_2-NOT: Decl[LocalVar]
447+
// IN_FOR_EACH_2: Decl[LocalVar]/Local/TypeRelation[Identical]: local[#Int#];
448+
// FIXME: shouldn't show 'after' here.
449+
// IN_FOR_EACH_2: Decl[LocalVar]/Local/TypeRelation[Identical]: after[#Int#];
450+
// IN_FOR_EACH_2: Decl[LocalVar]/Local/TypeRelation[Identical]: arg[#Int#];
451+
// IN_FOR_EACH_2-NOT: Decl[LocalVar]
446452
}
447453
func testInForEach3(arg: Int) {
448454
let local = 2
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=BINARY_RHS_1 | %FileCheck %s -check-prefix=BINARY_RHS_1
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=BINARY_RHS_2 | %FileCheck %s -check-prefix=BINARY_RHS_2
3+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PREFIX_1 | %FileCheck %s -check-prefix=PREFIX_1
4+
5+
infix operator <-->
6+
prefix operator -->
7+
8+
class C1 {}
9+
class C2 {}
10+
func <--> (lhs: C1, rhs: C2) -> Bool {}
11+
func <--> (lhs: C2, rhs: C1) -> Bool {}
12+
13+
func test_binary1(c1: C1, c2: C2) {
14+
_ = c1 <--> #^BINARY_RHS_1^#
15+
// BINARY_RHS_1: Begin completion
16+
// BINARY_RHS_1-NOT: Decl[LocalVar]/Local/TypeRelation[Identical]: c1[#C1#]; name=c1
17+
// BINARY_RHS_1-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: c2[#C2#]; name=c2
18+
19+
_ = c2 <--> #^BINARY_RHS_2^#
20+
// BINARY_RHS_2: Begin completion
21+
// BINARY_RHS_2-NOT: Decl[LocalVar]/Local/TypeRelation[Identical]: c2[#C2#]; name=c2
22+
// BINARY_RHS_2-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: c1[#C1#]; name=c1
23+
}
24+
25+
prefix func --> (operand: C1) -> Bool {}
26+
prefix func --> (operand: C2) -> Bool {}
27+
28+
func test_prefix1(c1: C1, c2: C2) {
29+
_ = -->#^PREFIX_1^#
30+
// PREFIX_1: Begin completion
31+
// PREFIX_1-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: c1[#C1#]; name=c1
32+
// PREFIX_1-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: c2[#C2#]; name=c2
33+
}

0 commit comments

Comments
 (0)