Skip to content

Commit 88d3677

Browse files
authored
Merge pull request #25755 from rintaro/ide-completion-casebeginning-rdar45219937
[CodeCompletion] Use unresolved member completion for case stmt beginning
2 parents 230666b + 35f8686 commit 88d3677

File tree

7 files changed

+27
-115
lines changed

7 files changed

+27
-115
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,6 @@ enum class CompletionKind {
495495
TypeIdentifierWithoutDot,
496496
CaseStmtKeyword,
497497
CaseStmtBeginning,
498-
CaseStmtDotPrefix,
499498
NominalMemberBeginning,
500499
AccessorBeginning,
501500
AttributeBegin,

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,7 @@ class CodeCompletionCallbacks {
175175
virtual void completeCaseStmtKeyword() {};
176176

177177
/// Complete at the beginning of a case stmt pattern.
178-
virtual void completeCaseStmtBeginning() {};
179-
180-
/// Complete a case stmt pattern that starts with a dot.
181-
virtual void completeCaseStmtDotPrefix() {};
178+
virtual void completeCaseStmtBeginning(CodeCompletionExpr *E) {};
182179

183180
/// Complete at the beginning of member of a nominal decl member -- no tokens
184181
/// provided by user.

lib/IDE/CodeCompletion.cpp

Lines changed: 8 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -338,44 +338,6 @@ std::string swift::ide::removeCodeCompletionTokens(
338338
return CleanFile;
339339
}
340340

341-
namespace {
342-
class StmtFinder : public ASTWalker {
343-
SourceManager &SM;
344-
SourceLoc Loc;
345-
StmtKind Kind;
346-
Stmt *Found = nullptr;
347-
348-
public:
349-
StmtFinder(SourceManager &SM, SourceLoc Loc, StmtKind Kind)
350-
: SM(SM), Loc(Loc), Kind(Kind) {}
351-
352-
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
353-
return { SM.rangeContainsTokenLoc(S->getSourceRange(), Loc), S };
354-
}
355-
356-
Stmt *walkToStmtPost(Stmt *S) override {
357-
if (S->getKind() == Kind) {
358-
Found = S;
359-
return nullptr;
360-
}
361-
return S;
362-
}
363-
364-
Stmt *getFoundStmt() const {
365-
return Found;
366-
}
367-
};
368-
} // end anonymous namespace
369-
370-
static Stmt *findNearestStmt(const DeclContext *DC, SourceLoc Loc,
371-
StmtKind Kind) {
372-
auto &SM = DC->getASTContext().SourceMgr;
373-
StmtFinder Finder(SM, Loc, Kind);
374-
// FIXME(thread-safety): the walker is mutating the AST.
375-
const_cast<DeclContext *>(DC)->walkContext(Finder);
376-
return Finder.getFoundStmt();
377-
}
378-
379341
CodeCompletionString::CodeCompletionString(ArrayRef<Chunk> Chunks) {
380342
std::uninitialized_copy(Chunks.begin(), Chunks.end(),
381343
getTrailingObjects<Chunk>());
@@ -1377,8 +1339,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
13771339
void completeTypeIdentifierWithoutDot(IdentTypeRepr *ITR) override;
13781340

13791341
void completeCaseStmtKeyword() override;
1380-
void completeCaseStmtBeginning() override;
1381-
void completeCaseStmtDotPrefix() override;
1342+
void completeCaseStmtBeginning(CodeCompletionExpr *E) override;
13821343
void completeDeclAttrBeginning(bool Sil, bool isIndependent) override;
13831344
void completeDeclAttrParam(DeclAttrKind DK, int Index) override;
13841345
void completeInPrecedenceGroup(SyntaxKind SK) override;
@@ -3908,27 +3869,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39083869
}
39093870
}
39103871

3911-
void getTypeContextEnumElementCompletions(SourceLoc Loc) {
3912-
llvm::SaveAndRestore<LookupKind> ChangeLookupKind(
3913-
Kind, LookupKind::EnumElement);
3914-
NeedLeadingDot = !HaveDot;
3915-
3916-
auto *Switch = cast_or_null<SwitchStmt>(
3917-
findNearestStmt(CurrDeclContext, Loc, StmtKind::Switch));
3918-
if (!Switch)
3919-
return;
3920-
auto Ty = Switch->getSubjectExpr()->getType();
3921-
if (!Ty)
3922-
return;
3923-
ExprType = Ty;
3924-
auto *TheEnumDecl = dyn_cast_or_null<EnumDecl>(Ty->getAnyNominal());
3925-
if (!TheEnumDecl)
3926-
return;
3927-
for (auto Element : TheEnumDecl->getAllElements()) {
3928-
foundDecl(Element, DeclVisibilityKind::MemberOfCurrentNominal, {});
3929-
}
3930-
}
3931-
39323872
void getTypeCompletions(Type BaseType) {
39333873
Kind = LookupKind::Type;
39343874
this->BaseType = BaseType;
@@ -4720,18 +4660,12 @@ void CodeCompletionCallbacksImpl::completeCaseStmtKeyword() {
47204660
CurDeclContext = P.CurDeclContext;
47214661
}
47224662

4723-
void CodeCompletionCallbacksImpl::completeCaseStmtBeginning() {
4663+
void CodeCompletionCallbacksImpl::completeCaseStmtBeginning(CodeCompletionExpr *E) {
47244664
assert(!InEnumElementRawValue);
47254665

47264666
Kind = CompletionKind::CaseStmtBeginning;
47274667
CurDeclContext = P.CurDeclContext;
4728-
}
4729-
4730-
void CodeCompletionCallbacksImpl::completeCaseStmtDotPrefix() {
4731-
assert(!InEnumElementRawValue);
4732-
4733-
Kind = CompletionKind::CaseStmtDotPrefix;
4734-
CurDeclContext = P.CurDeclContext;
4668+
CodeCompleteTokenExpr = E;
47354669
}
47364670

47374671
void CodeCompletionCallbacksImpl::completeImportDecl(
@@ -5017,7 +4951,6 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
50174951
case CompletionKind::SuperExpr:
50184952
case CompletionKind::SuperExprDot:
50194953
case CompletionKind::CaseStmtBeginning:
5020-
case CompletionKind::CaseStmtDotPrefix:
50214954
case CompletionKind::TypeIdentifierWithDot:
50224955
case CompletionKind::TypeIdentifierWithoutDot:
50234956
break;
@@ -5417,16 +5350,11 @@ void CodeCompletionCallbacksImpl::doneParsing() {
54175350
}
54185351

54195352
case CompletionKind::CaseStmtBeginning: {
5420-
SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
5421-
Lookup.getValueCompletionsInDeclContext(Loc);
5422-
Lookup.getTypeContextEnumElementCompletions(Loc);
5423-
break;
5424-
}
5425-
5426-
case CompletionKind::CaseStmtDotPrefix: {
5427-
Lookup.setHaveDot(SourceLoc());
5428-
SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
5429-
Lookup.getTypeContextEnumElementCompletions(Loc);
5353+
ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
5354+
Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
5355+
ContextInfo.isSingleExpressionBody());
5356+
Lookup.getUnresolvedMemberCompletions(ContextInfo.getPossibleTypes());
5357+
DoPostfixExprBeginning();
54305358
break;
54315359
}
54325360

lib/IDE/TypeContextInfo.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ContextInfoCallbacks : public CodeCompletionCallbacks {
3737

3838
void completePostfixExprBeginning(CodeCompletionExpr *E) override;
3939
void completeForEachSequenceBeginning(CodeCompletionExpr *E) override;
40-
void completeCaseStmtBeginning() override;
40+
void completeCaseStmtBeginning(CodeCompletionExpr *E) override;
4141

4242
void completeCallArg(CodeCompletionExpr *E, bool isFirst) override;
4343
void completeReturnStmt(CodeCompletionExpr *E) override;
@@ -46,7 +46,6 @@ class ContextInfoCallbacks : public CodeCompletionCallbacks {
4646

4747
void completeUnresolvedMember(CodeCompletionExpr *E,
4848
SourceLoc DotLoc) override;
49-
void completeCaseStmtDotPrefix() override;
5049

5150
void doneParsing() override;
5251
};
@@ -81,10 +80,7 @@ void ContextInfoCallbacks::completeUnresolvedMember(CodeCompletionExpr *E,
8180
ParsedExpr = E;
8281
}
8382

84-
void ContextInfoCallbacks::completeCaseStmtBeginning() {
85-
// TODO: Implement?
86-
}
87-
void ContextInfoCallbacks::completeCaseStmtDotPrefix() {
83+
void ContextInfoCallbacks::completeCaseStmtBeginning(CodeCompletionExpr *E) {
8884
// TODO: Implement?
8985
}
9086

lib/Parse/ParseStmt.cpp

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,29 +1081,19 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
10811081

10821082
// Do some special-case code completion for the start of the pattern.
10831083
if (P.Tok.is(tok::code_complete)) {
1084+
auto CCE = new (P.Context) CodeCompletionExpr(P.Tok.getLoc());
1085+
result.ThePattern = new (P.Context) ExprPattern(CCE);
10841086
if (P.CodeCompletion) {
10851087
switch (parsingContext) {
10861088
case GuardedPatternContext::Case:
1087-
P.CodeCompletion->completeCaseStmtBeginning();
1089+
P.CodeCompletion->completeCaseStmtBeginning(CCE);
10881090
break;
10891091
case GuardedPatternContext::Catch:
1090-
P.CodeCompletion->completePostfixExprBeginning(nullptr);
1092+
P.CodeCompletion->completePostfixExprBeginning(CCE);
10911093
break;
10921094
}
10931095
}
1094-
auto loc = P.consumeToken(tok::code_complete);
1095-
result.ThePattern = new (P.Context) AnyPattern(loc);
1096-
status.setHasCodeCompletion();
1097-
return;
1098-
}
1099-
if (parsingContext == GuardedPatternContext::Case &&
1100-
P.Tok.isAny(tok::period_prefix, tok::period) &&
1101-
P.peekToken().is(tok::code_complete)) {
1102-
P.consumeToken();
1103-
if (P.CodeCompletion)
1104-
P.CodeCompletion->completeCaseStmtDotPrefix();
1105-
auto loc = P.consumeToken(tok::code_complete);
1106-
result.ThePattern = new (P.Context) AnyPattern(loc);
1096+
P.consumeToken(tok::code_complete);
11071097
status.setHasCodeCompletion();
11081098
return;
11091099
}

test/IDE/complete_enum_elements.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
// RUN: %FileCheck %s -check-prefix=FOO_ENUM_DOT < %t.enum.txt
3636

3737
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_SW_IN_PATTERN_1 > %t.enum.txt
38-
// RUN: %FileCheck %s -check-prefix=WITH_GLOBAL_RESULTS_INVALID < %t.enum.txt
38+
// RUN: %FileCheck %s -check-prefix=WITH_GLOBAL_RESULTS < %t.enum.txt
3939
// RUN: %FileCheck %s -check-prefix=ENUM_SW_IN_PATTERN_1 < %t.enum.txt
4040

4141
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_SW_IN_PATTERN_2 > %t.enum.txt
@@ -85,16 +85,19 @@
8585
enum FooEnum: CaseIterable {
8686
case Foo1
8787
case Foo2
88+
static var alias1: FooEnum { return .Foo1 }
8889
}
8990

9091
// FOO_ENUM_TYPE_CONTEXT: Begin completions
9192
// FOO_ENUM_TYPE_CONTEXT-DAG: Decl[EnumElement]/ExprSpecific: .Foo1[#FooEnum#]{{; name=.+$}}
9293
// FOO_ENUM_TYPE_CONTEXT-DAG: Decl[EnumElement]/ExprSpecific: .Foo2[#FooEnum#]{{; name=.+$}}
94+
// FOO_ENUM_TYPE_CONTEXT-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: .alias1[#FooEnum#]; name=alias1
9395
// FOO_ENUM_TYPE_CONTEXT: End completions
9496

9597
// FOO_ENUM_NO_DOT: Begin completions
9698
// FOO_ENUM_NO_DOT-NEXT: Decl[EnumElement]/CurrNominal: .Foo1[#FooEnum#]{{; name=.+$}}
9799
// FOO_ENUM_NO_DOT-NEXT: Decl[EnumElement]/CurrNominal: .Foo2[#FooEnum#]{{; name=.+$}}
100+
// FOO_ENUM_NO_DOT-NEXT: Decl[StaticVar]/CurrNominal: .alias1[#FooEnum#]{{; name=.+$}}
98101
// FOO_ENUM_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .hash({#(self): FooEnum#})[#(into: inout Hasher) -> Void#]{{; name=.+$}}
99102
// FOO_ENUM_NO_DOT-NEXT: Decl[TypeAlias]/CurrNominal: .AllCases[#[FooEnum]#]{{; name=.+$}}
100103
// FOO_ENUM_NO_DOT-NEXT: Decl[StaticVar]/CurrNominal: .allCases[#[FooEnum]#]{{; name=.+$}}
@@ -107,6 +110,7 @@ enum FooEnum: CaseIterable {
107110
// FOO_ENUM_DOT-NEXT: Keyword/CurrNominal: Type[#FooEnum.Type#]; name=Type
108111
// FOO_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Foo1[#FooEnum#]{{; name=.+$}}
109112
// FOO_ENUM_DOT-NEXT: Decl[EnumElement]/CurrNominal: Foo2[#FooEnum#]{{; name=.+$}}
113+
// FOO_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: alias1[#FooEnum#]{{; name=.+$}}
110114
// FOO_ENUM_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: hash({#(self): FooEnum#})[#(into: inout Hasher) -> Void#]{{; name=.+$}}
111115
// FOO_ENUM_DOT-NEXT: Decl[TypeAlias]/CurrNominal: AllCases[#[FooEnum]#]{{; name=.+$}}
112116
// FOO_ENUM_DOT-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]{{; name=.+$}}
@@ -117,14 +121,16 @@ enum FooEnum: CaseIterable {
117121
// FOO_ENUM_DOT_INVALID-NEXT: Keyword/CurrNominal: Type[#FooEnum.Type#]; name=Type
118122
// FOO_ENUM_DOT_INVALID-NEXT: Decl[EnumElement]/CurrNominal: Foo1[#FooEnum#]{{; name=.+$}}
119123
// FOO_ENUM_DOT_INVALID-NEXT: Decl[EnumElement]/CurrNominal: Foo2[#FooEnum#]{{; name=.+$}}
124+
// FOO_ENUM_DOT_INVALID-NEXT: Decl[StaticVar]/CurrNominal: alias1[#FooEnum#]{{; name=.+$}}
120125
// FOO_ENUM_DOT_INVALID-NEXT: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: hash({#(self): FooEnum#})[#(into: inout Hasher) -> Void#]{{; name=.+$}}
121126
// FOO_ENUM_DOT_INVALID-NEXT: Decl[TypeAlias]/CurrNominal: AllCases[#[FooEnum]#]{{; name=.+$}}
122127
// FOO_ENUM_DOT_INVALID-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]{{; name=.+$}}
123128
// FOO_ENUM_DOT_INVALID-NEXT: End completions
124129

125-
// FOO_ENUM_DOT_ELEMENTS: Begin completions, 2 items
130+
// FOO_ENUM_DOT_ELEMENTS: Begin completions, 3 items
126131
// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[EnumElement]/ExprSpecific: Foo1[#FooEnum#]{{; name=.+$}}
127132
// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[EnumElement]/ExprSpecific: Foo2[#FooEnum#]{{; name=.+$}}
133+
// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: alias1[#FooEnum#]; name=alias1
128134
// FOO_ENUM_DOT_ELEMENTS-NEXT: End completions
129135

130136
enum BarEnum {
@@ -295,13 +301,9 @@ enum QuxEnum : Int {
295301
func freeFunc() {}
296302

297303
// WITH_GLOBAL_RESULTS: Begin completions
298-
// WITH_GLOBAL_RESULTS: Decl[FreeFunction]/CurrModule: freeFunc()[#Void#]{{; name=.+$}}
304+
// WITH_GLOBAL_RESULTS: Decl[FreeFunction]/CurrModule/NotRecommended/TypeRelation[Invalid]: freeFunc()[#Void#]{{; name=.+$}}
299305
// WITH_GLOBAL_RESULTS: End completions
300306

301-
// WITH_GLOBAL_RESULTS_INVALID: Begin completions
302-
// WITH_GLOBAL_RESULTS_INVALID: Decl[FreeFunction]/CurrModule/NotRecommended/TypeRelation[Invalid]: freeFunc()[#Void#]{{; name=.+$}}
303-
// WITH_GLOBAL_RESULTS_INVALID: End completions
304-
305307
//===--- Complete enum elements in 'switch'.
306308

307309
func testSwitch1(e: FooEnum) {

test/IDE/complete_value_expr.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,8 @@ func testSwitch1() {
637637
}
638638

639639
// IN_SWITCH_CASE: Begin completions
640-
// IN_SWITCH_CASE-DAG: Decl[GlobalVar]/CurrModule: fooObject[#FooStruct#]{{; name=.+$}}
641-
// IN_SWITCH_CASE-DAG: Decl[Struct]/CurrModule: FooStruct[#FooStruct#]{{; name=.+$}}
640+
// IN_SWITCH_CASE-DAG: Decl[GlobalVar]/CurrModule{{(/TypeRelation\[Identical\])?}}: fooObject[#FooStruct#]{{; name=.+$}}
641+
// IN_SWITCH_CASE-DAG: Decl[Struct]/CurrModule{{(/TypeRelation\[Identical\])?}}: FooStruct[#FooStruct#]{{; name=.+$}}
642642
// IN_SWITCH_CASE: End completions
643643

644644
//===--- Helper types that are used in this test

0 commit comments

Comments
 (0)