Skip to content

Commit f50b666

Browse files
committed
[CodeCompletion] Fallback to nominal member completion after trailing closure
After trailing closure, we perform "Labeled trailing closure" completion and fall back to other completion depending on the position. If the completion happens at a newline position, it used to fallback to global expression completion, but in type context, we should do override completion instead. Also, we didn't use to propagate 'hasCodeCompletion()' status properly. rdar://problem/64650782
1 parent 5b6918f commit f50b666

File tree

3 files changed

+50
-9
lines changed

3 files changed

+50
-9
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6158,15 +6158,29 @@ void CodeCompletionCallbacksImpl::doneParsing() {
61586158
if (IsAtStartOfLine) {
61596159
// foo() {}
61606160
// <HERE>
6161-
// Global completion.
6161+
61626162
auto &Sink = CompletionContext.getResultSink();
6163-
addDeclKeywords(Sink);
6164-
addStmtKeywords(Sink, MaybeFuncBody);
6165-
addSuperKeyword(Sink);
6166-
addLetVarKeywords(Sink);
6167-
addExprKeywords(Sink);
6168-
addAnyTypeKeyword(Sink, CurDeclContext->getASTContext().TheAnyType);
6169-
DoPostfixExprBeginning();
6163+
if (isa<Initializer>(CurDeclContext))
6164+
CurDeclContext = CurDeclContext->getParent();
6165+
6166+
if (CurDeclContext->isTypeContext()) {
6167+
// Override completion (CompletionKind::NominalMemberBeginning).
6168+
addDeclKeywords(Sink);
6169+
addLetVarKeywords(Sink);
6170+
SmallVector<StringRef, 0> ParsedKeywords;
6171+
CompletionOverrideLookup OverrideLookup(Sink, Context, CurDeclContext,
6172+
ParsedKeywords, SourceLoc());
6173+
OverrideLookup.getOverrideCompletions(SourceLoc());
6174+
} else {
6175+
// Global completion (CompletionKind::PostfixExprBeginning).
6176+
addDeclKeywords(Sink);
6177+
addStmtKeywords(Sink, MaybeFuncBody);
6178+
addSuperKeyword(Sink);
6179+
addLetVarKeywords(Sink);
6180+
addExprKeywords(Sink);
6181+
addAnyTypeKeyword(Sink, Context.TheAnyType);
6182+
DoPostfixExprBeginning();
6183+
}
61706184
} else {
61716185
// foo() {} <HERE>
61726186
// Member completion.

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3225,7 +3225,7 @@ Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange,
32253225
if (CodeCompletion)
32263226
CodeCompletion->completeLabeledTrailingClosure(CCExpr, Tok.isAtStartOfLine());
32273227
consumeToken(tok::code_complete);
3228-
result.hasCodeCompletion();
3228+
result.setHasCodeCompletion();
32293229
closures.push_back({Identifier(), SourceLoc(), CCExpr});
32303230
continue;
32313231
}

test/IDE/complete_multiple_trailingclosure.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_NEWLINE_3 | %FileCheck %s -check-prefix=INIT_REQUIRED_NEWLINE_3
1616
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_1 | %FileCheck %s -check-prefix=INIT_FALLBACK
1717
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_2 | %FileCheck %s -check-prefix=INIT_FALLBACK
18+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBERDECL_SAMELINE | %FileCheck %s -check-prefix=MEMBERDECL_SAMELINE
19+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBERDECL_NEWLINE | %FileCheck %s -check-prefix=MEMBERDECL_NEWLINE
1820

1921
func globalFunc1(fn1: () -> Int, fn2: () -> String) {}
2022
func testGlobalFunc() {
@@ -207,3 +209,28 @@ func testFallbackPostfix() {
207209
1
208210
} #^INIT_FALLBACK_2^#
209211
}
212+
213+
protocol P {
214+
func foo()
215+
}
216+
struct TestNominalMember: P {
217+
var value = MyStruct().method1 { 1 } #^MEMBERDECL_SAMELINE^#
218+
#^MEMBERDECL_NEWLINE^#
219+
220+
// MEMBERDECL_SAMELINE: Begin completions, 4 items
221+
// MEMBERDECL_SAMELINE-DAG: Pattern/ExprSpecific: {#fn2: (() -> String)? {() -> String in|}#}[#(() -> String)?#]; name=fn2: (() -> String)?
222+
// MEMBERDECL_SAMELINE-DAG: Decl[InstanceMethod]/CurrNominal: .enumFunc()[#Void#]; name=enumFunc()
223+
// MEMBERDECL_SAMELINE-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']+ {#SimpleEnum#}[#SimpleEnum#]; name=+ SimpleEnum
224+
// MEMBERDECL_SAMELINE-DAG: Keyword[self]/CurrNominal: .self[#SimpleEnum#]; name=self
225+
// MEMBERDECL_SAMELINE: End completions
226+
227+
// MEMBERDECL_NEWLINE: Begin completions
228+
// MEMBERDECL_NEWLINE-DAG: Pattern/ExprSpecific: {#fn2: (() -> String)? {() -> String in|}#}[#(() -> String)?#]; name=fn2: (() -> String)?
229+
// MEMBERDECL_NEWLINE-DAG: Keyword[enum]/None: enum; name=enum
230+
// MEMBERDECL_NEWLINE-DAG: Keyword[func]/None: func; name=func
231+
// MEMBERDECL_NEWLINE-DAG: Keyword[private]/None: private; name=private
232+
// MEMBERDECL_NEWLINE-DAG: Keyword/None: lazy; name=lazy
233+
// MEMBERDECL_NEWLINE-DAG: Keyword[var]/None: var; name=var
234+
// MEMBERDECL_NEWLINE-DAG: Decl[InstanceMethod]/Super: func foo() {|}; name=foo()
235+
// MEMBERDECL_NEWLINE: End completions
236+
}

0 commit comments

Comments
 (0)