Skip to content

Commit 3ee5954

Browse files
authored
Merge pull request swiftlang#15653 from rintaro/quickfix-rdar38988444
[code-completion] Fix compiler crash on implicit member expression in string interpolation
2 parents d31747e + 7a80547 commit 3ee5954

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,20 +1654,25 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
16541654
Context.getIdentifier("_"), /*implicit=*/false);
16551655
auto Result = makeParserResult(Expr);
16561656
if (CodeCompletion) {
1657-
std::vector<StringRef> Identifiers;
1658-
1659-
// Move lexer to the start of the current line.
1660-
L->backtrackToState(L->getStateForBeginningOfTokenLoc(
1661-
L->getLocForStartOfLine(SourceMgr, Tok.getLoc())));
16621657

1658+
// FIXME: Code-completion should be able to find the contextual type
1659+
// from AST.
1660+
std::vector<StringRef> Identifiers;
16631661
bool HasReturn = false;
1664-
1665-
// Until we see the code completion token, collect identifiers.
1666-
for (L->lex(Tok); !Tok.is(tok::code_complete); consumeToken()) {
1667-
if (!HasReturn)
1668-
HasReturn = Tok.is(tok::kw_return);
1669-
if (Tok.is(tok::identifier)) {
1670-
Identifiers.push_back(Tok.getText());
1662+
{
1663+
ParserPositionRAII PPR(*this);
1664+
// Move lexer to the start of the current line.
1665+
L->backtrackToState(L->getStateForBeginningOfTokenLoc(
1666+
L->getLocForStartOfLine(SourceMgr, Tok.getLoc())));
1667+
1668+
// Until we see the code completion token, collect identifiers.
1669+
for (L->lex(Tok); !Tok.isAny(tok::code_complete, tok::eof);
1670+
consumeTokenWithoutFeedingReceiver()) {
1671+
if (!HasReturn)
1672+
HasReturn = Tok.is(tok::kw_return);
1673+
if (Tok.is(tok::identifier)) {
1674+
Identifiers.push_back(Tok.getText());
1675+
}
16711676
}
16721677
}
16731678
CodeCompletion->completeUnresolvedMember(Expr, Identifiers, HasReturn);

test/IDE/complete_unresolved_members.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NON_OPT_SET_2 | %FileCheck %s -check-prefix=NON_OPT_SET_1
5151
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NON_OPT_SET_3 | %FileCheck %s -check-prefix=NON_OPT_SET_1
5252

53+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRING_INTERPOLATION_1 | %FileCheck %s -check-prefix=STRING_INTERPOLATION_1
54+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRING_INTERPOLATION_INVALID
5355
enum SomeEnum1 {
5456
case South
5557
case North
@@ -366,3 +368,14 @@ func testNonOptSet() {
366368
func testNonOptSet() -> NonOptSet {
367369
return .#^NON_OPT_SET_3^#
368370
}
371+
372+
func testInStringInterpolation() {
373+
enum MyEnum { case foo, bar }
374+
func takeEnum(_ e: MyEnum) -> MyEnum { return e }
375+
let x = "enum: \(takeEnum(.#^STRING_INTERPOLATION_1^#))"
376+
let y = "enum: \(.#^STRING_INTERPOLATION_INVALID^#)" // Dont'crash.
377+
}
378+
// STRING_INTERPOLATION_1: Begin completions
379+
// STRING_INTERPOLATION_1-DAG: Decl[EnumElement]/ExprSpecific: foo[#MyEnum#];
380+
// STRING_INTERPOLATION_1-DAG: Decl[EnumElement]/ExprSpecific: bar[#MyEnum#];
381+
// STRING_INTERPOLATION_1: End completions

0 commit comments

Comments
 (0)