Skip to content

Commit a57db3f

Browse files
authored
Merge pull request #37346 from rintaro/5.5-ide-completion-rdar76355581
[5.5][CodeCompletion] Complete pattern introducer for 'for'
2 parents e1e6c37 + 2208ee7 commit a57db3f

File tree

5 files changed

+62
-6
lines changed

5 files changed

+62
-6
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ enum class CompletionKind {
561561
GenericRequirement,
562562
PrecedenceGroup,
563563
StmtLabel,
564+
ForEachPatternBeginning,
564565
};
565566

566567
/// A single code completion result.

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,9 @@ class CodeCompletionCallbacks {
231231

232232
virtual void completeStmtLabel(StmtKind ParentKind) {};
233233

234+
virtual
235+
void completeForEachPatternBeginning(bool hasTry, bool hasAwait) {};
236+
234237
/// Signals that the AST for the all the delayed-parsed code was
235238
/// constructed. No \c complete*() callbacks will be done after this.
236239
virtual void doneParsing() = 0;

lib/IDE/CodeCompletion.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
16691669
void completeGenericRequirement() override;
16701670
void completeAfterIfStmt(bool hasElse) override;
16711671
void completeStmtLabel(StmtKind ParentKind) override;
1672+
void completeForEachPatternBeginning(bool hasTry, bool hasAwait) override;
16721673

16731674
void doneParsing() override;
16741675

@@ -5820,6 +5821,17 @@ void CodeCompletionCallbacksImpl::completeStmtLabel(StmtKind ParentKind) {
58205821
ParentStmtKind = ParentKind;
58215822
}
58225823

5824+
void CodeCompletionCallbacksImpl::completeForEachPatternBeginning(
5825+
bool hasTry, bool hasAwait) {
5826+
CurDeclContext = P.CurDeclContext;
5827+
Kind = CompletionKind::ForEachPatternBeginning;
5828+
ParsedKeywords.clear();
5829+
if (hasTry)
5830+
ParsedKeywords.emplace_back("try");
5831+
if (hasAwait)
5832+
ParsedKeywords.emplace_back("await");
5833+
}
5834+
58235835
static bool isDynamicLookup(Type T) {
58245836
return T->getRValueType()->isAnyObject();
58255837
}
@@ -6055,6 +6067,13 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
60556067
case CompletionKind::AfterIfStmtElse:
60566068
addKeyword(Sink, "if", CodeCompletionKeywordKind::kw_if);
60576069
break;
6070+
case CompletionKind::ForEachPatternBeginning:
6071+
if (!llvm::is_contained(ParsedKeywords, "try"))
6072+
addKeyword(Sink, "try", CodeCompletionKeywordKind::kw_try);
6073+
if (!llvm::is_contained(ParsedKeywords, "await"))
6074+
addKeyword(Sink, "await", CodeCompletionKeywordKind::None);
6075+
addKeyword(Sink, "var", CodeCompletionKeywordKind::kw_var);
6076+
addKeyword(Sink, "case", CodeCompletionKeywordKind::kw_case);
60586077
}
60596078
}
60606079

@@ -6952,6 +6971,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
69526971
case CompletionKind::AfterIfStmtElse:
69536972
case CompletionKind::CaseStmtKeyword:
69546973
case CompletionKind::EffectsSpecifier:
6974+
case CompletionKind::ForEachPatternBeginning:
69556975
// Handled earlier by keyword completions.
69566976
break;
69576977
}

lib/Parse/ParseStmt.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,17 @@ ParserResult<Stmt> Parser::parseStmtForEach(LabeledStmtInfo LabelInfo) {
21362136
}
21372137
}
21382138

2139+
if (Tok.is(tok::code_complete)) {
2140+
if (CodeCompletion) {
2141+
CodeCompletion->completeForEachPatternBeginning(TryLoc.isValid(),
2142+
AwaitLoc.isValid());
2143+
}
2144+
consumeToken(tok::code_complete);
2145+
// Since 'completeForeachPatternBeginning' is a keyword only completion,
2146+
// we don't need to parse the rest of 'for' statement.
2147+
return makeParserCodeCompletionStatus();
2148+
}
2149+
21392150
// Parse the pattern. This is either 'case <refutable pattern>' or just a
21402151
// normal pattern.
21412152
if (consumeIf(tok::kw_case)) {

test/IDE/complete_stmt_controlling_expr.swift

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,22 +142,43 @@ func testRepeatWhile2(_ fooObject: FooStruct) {
142142
} while localFooObject.#^COND_DO_WHILE_2?check=COND-WITH-RELATION1^#
143143
}
144144

145-
func testCStyleForInit1(_ fooObject: FooStruct) {
145+
func testForeachPattern1(_ fooObject: FooStruct) {
146146
var localInt = 42
147147
var localFooObject = FooStruct(localInt)
148-
for #^C_STYLE_FOR_INIT_1?check=COND_NONE^#
148+
for #^FOREACH_PATTERN_1^#
149+
// FOREACH_PATTERN_1: Begin completions, 4 items
150+
// FOREACH_PATTERN_1-DAG: Keyword[try]/None: try; name=try
151+
// FOREACH_PATTERN_1-DAG: Keyword/None: await; name=await
152+
// FOREACH_PATTERN_1-DAG: Keyword[var]/None: var; name=var
153+
// FOREACH_PATTERN_1-DAG: Keyword[case]/None: case; name=case
154+
// FOREACH_PATTERN_1: End completions
149155
}
150156

151-
func testCStyleForInit2(_ fooObject: FooStruct) {
157+
func testForeachPattern2(_ fooObject: FooStruct) {
152158
var localInt = 42
153159
var localFooObject = FooStruct(localInt)
154-
for #^C_STYLE_FOR_INIT_2?check=COND_COMMON^#;
160+
for try #^FOREACH_PATTERN_2^#
161+
// FOREACH_PATTERN_2: Begin completions, 3 items
162+
// FOREACH_PATTERN_2-DAG: Keyword/None: await; name=await
163+
// FOREACH_PATTERN_2-DAG: Keyword[var]/None: var; name=var
164+
// FOREACH_PATTERN_2-DAG: Keyword[case]/None: case; name=case
165+
// FOREACH_PATTERN_2: End completions
155166
}
156167

157-
func testCStyleForInit3(_ fooObject: FooStruct) {
168+
func testForeachPattern3(_ fooObject: FooStruct) {
158169
var localInt = 42
159170
var localFooObject = FooStruct(localInt)
160-
for #^C_STYLE_FOR_INIT_3?check=COND_COMMON^# ;
171+
for try await #^FOREACH_PATTERN_3^#
172+
// FOREACH_PATTERN_3: Begin completions, 2 items
173+
// FOREACH_PATTERN_3-DAG: Keyword[var]/None: var; name=var
174+
// FOREACH_PATTERN_3-DAG: Keyword[case]/None: case; name=case
175+
// FOREACH_PATTERN_3: End completions
176+
}
177+
178+
func testForeachPattern4(_ fooObject: FooStruct) {
179+
var localInt = 42
180+
var localFooObject = FooStruct(localInt)
181+
for var #^FOREACH_PATTERN_4?check=COND_NONE^#
161182
}
162183

163184
func testCStyleForCond1(_ fooObject: FooStruct) {

0 commit comments

Comments
 (0)