Skip to content

Commit db8ca19

Browse files
authored
Merge pull request #70014 from ahoppen/ahoppen/some-any-completion
[CodeCompletion] Add keyword completion for 'some', 'any', 'repeat', and 'each'
2 parents 0ec84e7 + 9cb2a24 commit db8ca19

File tree

8 files changed

+91
-47
lines changed

8 files changed

+91
-47
lines changed

include/swift/IDE/CodeCompletionResult.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ enum class CompletionKind : uint8_t {
199199
KeyPathExprObjC,
200200
KeyPathExprSwift,
201201
TypeDeclResultBeginning,
202+
TypeBeginning,
203+
TypeSimpleOrComposition,
202204
TypeSimpleBeginning,
203205
TypeSimpleWithDot,
204206
TypeSimpleWithoutDot,

include/swift/Parse/IDEInspectionCallbacks.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ class CodeCompletionCallbacks {
185185
/// Complete the beginning of the type of result of func/var/let/subscript.
186186
virtual void completeTypeDeclResultBeginning() {};
187187

188+
/// Same as `completeTypeSimpleOrComposition` but also allows `repeat`.
189+
virtual void completeTypeBeginning(){};
190+
191+
/// Same as `completeTypeSimpleBeginning` but also allows `any`, `some` and
192+
/// `each`.
193+
virtual void completeTypeSimpleOrComposition(){};
194+
188195
/// Complete the beginning of type-simple -- no tokens provided
189196
/// by user.
190197
virtual void completeTypeSimpleBeginning() {};

lib/IDE/CodeCompletion.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
263263
void completeExprKeyPath(KeyPathExpr *KPE, SourceLoc DotLoc) override;
264264

265265
void completeTypeDeclResultBeginning() override;
266+
void completeTypeBeginning() override;
267+
void completeTypeSimpleOrComposition() override;
266268
void completeTypeSimpleBeginning() override;
267269
void completeTypeSimpleWithDot(TypeRepr *TR) override;
268270
void completeTypeSimpleWithoutDot(TypeRepr *TR) override;
@@ -462,6 +464,16 @@ void CodeCompletionCallbacksImpl::completeTypeDeclResultBeginning() {
462464
CurDeclContext = P.CurDeclContext;
463465
}
464466

467+
void CodeCompletionCallbacksImpl::completeTypeBeginning() {
468+
Kind = CompletionKind::TypeBeginning;
469+
CurDeclContext = P.CurDeclContext;
470+
}
471+
472+
void CodeCompletionCallbacksImpl::completeTypeSimpleOrComposition() {
473+
Kind = CompletionKind::TypeSimpleOrComposition;
474+
CurDeclContext = P.CurDeclContext;
475+
}
476+
465477
void CodeCompletionCallbacksImpl::completeTypeSimpleBeginning() {
466478
Kind = CompletionKind::TypeSimpleBeginning;
467479
CurDeclContext = P.CurDeclContext;
@@ -961,10 +973,6 @@ void swift::ide::addSuperKeyword(CodeCompletionResultSink &Sink,
961973
Builder.addTypeAnnotation(ST, PrintOptions());
962974
}
963975

964-
static void addOpaqueTypeKeyword(CodeCompletionResultSink &Sink) {
965-
addKeyword(Sink, "some", CodeCompletionKeywordKind::None, "some");
966-
}
967-
968976
static void addAnyTypeKeyword(CodeCompletionResultSink &Sink, Type T) {
969977
CodeCompletionResultBuilder Builder(Sink, CodeCompletionResultKind::Keyword,
970978
SemanticContextKind::None);
@@ -1094,16 +1102,15 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
10941102
}
10951103
break;
10961104

1097-
case CompletionKind::TypeDeclResultBeginning: {
1098-
auto DC = CurDeclContext;
1099-
if (ParsedDecl && ParsedDecl == CurDeclContext->getAsDecl())
1100-
DC = ParsedDecl->getDeclContext();
1101-
if (!isa<ProtocolDecl>(DC))
1102-
if (DC->isTypeContext() || isa_and_nonnull<FuncDecl>(ParsedDecl))
1103-
addOpaqueTypeKeyword(Sink);
1104-
1105+
case CompletionKind::TypeBeginning:
1106+
addKeyword(Sink, "repeat", CodeCompletionKeywordKind::None);
1107+
LLVM_FALLTHROUGH;
1108+
case CompletionKind::TypeDeclResultBeginning:
1109+
case CompletionKind::TypeSimpleOrComposition:
1110+
addKeyword(Sink, "some", CodeCompletionKeywordKind::None);
1111+
addKeyword(Sink, "any", CodeCompletionKeywordKind::None);
1112+
addKeyword(Sink, "each", CodeCompletionKeywordKind::None);
11051113
LLVM_FALLTHROUGH;
1106-
}
11071114
case CompletionKind::TypeSimpleBeginning:
11081115
addAnyTypeKeyword(Sink, CurDeclContext->getASTContext().TheAnyType);
11091116
break;
@@ -1299,6 +1306,8 @@ void swift::ide::postProcessCompletionResults(
12991306
// names at non-type name position are "rare".
13001307
if (result->getKind() == CodeCompletionResultKind::Declaration &&
13011308
result->getAssociatedDeclKind() == CodeCompletionDeclKind::Protocol &&
1309+
Kind != CompletionKind::TypeBeginning &&
1310+
Kind != CompletionKind::TypeSimpleOrComposition &&
13021311
Kind != CompletionKind::TypeSimpleBeginning &&
13031312
Kind != CompletionKind::TypeSimpleWithoutDot &&
13041313
Kind != CompletionKind::TypeSimpleWithDot &&
@@ -1828,6 +1837,8 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
18281837
}
18291838

18301839
case CompletionKind::TypeDeclResultBeginning:
1840+
case CompletionKind::TypeBeginning:
1841+
case CompletionKind::TypeSimpleOrComposition:
18311842
case CompletionKind::TypeSimpleBeginning: {
18321843
auto Loc = Context.SourceMgr.getIDEInspectionTargetLoc();
18331844
Lookup.getTypeCompletionsInDeclContext(Loc);

lib/Parse/ParseType.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,12 @@ Parser::parseType(Diag<> MessageID, ParseTypeReason reason, bool fromASTGen) {
632632

633633
return makeParserResult(ty,
634634
new (Context) PackExpansionTypeRepr(repeatLoc, ty.get()));
635+
} else if (Tok.is(tok::code_complete)) {
636+
if (CodeCompletionCallbacks) {
637+
CodeCompletionCallbacks->completeTypeBeginning();
638+
}
639+
return makeParserCodeCompletionResult<TypeRepr>(
640+
ErrorTypeRepr::create(Context, consumeToken(tok::code_complete)));
635641
}
636642

637643
ty = parseTypeScalar(MessageID, reason);
@@ -954,6 +960,12 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason) {
954960

955961
auto *typeRepr = new (Context) PackElementTypeRepr(eachLoc, packElt.get());
956962
return makeParserResult(ParserStatus(packElt), typeRepr);
963+
} else if (Tok.is(tok::code_complete)) {
964+
if (CodeCompletionCallbacks) {
965+
CodeCompletionCallbacks->completeTypeSimpleOrComposition();
966+
}
967+
return makeParserCodeCompletionResult<TypeRepr>(
968+
ErrorTypeRepr::create(Context, consumeToken(tok::code_complete)));
957969
}
958970

959971
auto applyOpaque = [&](TypeRepr *type) -> TypeRepr * {

test/IDE/complete_generic_param.swift

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT1 | %FileCheck %s -check-prefix=INHERIT
2-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT2 | %FileCheck %s -check-prefix=INHERIT
3-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT3 | %FileCheck %s -check-prefix=INHERIT
4-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT4 | %FileCheck %s -check-prefix=INHERIT
5-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT5 | %FileCheck %s -check-prefix=INHERIT
6-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INHERIT6 | %FileCheck %s -check-prefix=INHERIT
7-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_TYPE_PARAM
8-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=SECOND_GENERIC_TYPE_PARAM | %FileCheck %s -check-prefix=GENERIC_TYPE_PARAM
9-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_PARAM_ON_NESTED_TYPE_GLOBAL_VAR | %FileCheck %s -check-prefix=GENERIC_PARAM_ON_NESTED_TYPE
10-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_PARAM_ON_NESTED_TYPE_LOCAL_VAR | %FileCheck %s -check-prefix=GENERIC_PARAM_ON_NESTED_TYPE
1+
// RUN: %batch-code-completion
112

123
class C1{}
134
protocol P1{}
@@ -17,17 +8,17 @@ let ValueInt1 = 1
178
let ValueString2 = ""
189
func TopLevelFunc() {}
1910

20-
func f1<S : #^INHERIT1^#>(p : S) {}
21-
func f2<S : #^INHERIT2^#
11+
func f1<S : #^INHERIT1?check=INHERIT^#>(p : S) {}
12+
func f2<S : #^INHERIT2?check=INHERIT^#
2213

2314
class C2 {
24-
func f1<S : #^INHERIT3^#>(p : S) {}
25-
func f2<S : #^INHERIT4^#
15+
func f1<S : #^INHERIT3?check=INHERIT^#>(p : S) {}
16+
func f2<S : #^INHERIT4?check=INHERIT^#
2617
}
2718

2819
class C3 {
29-
func f1<S1: P1, S2 : #^INHERIT5^#>(p : S1) {}
30-
func f2<S1: P1, S2 : #^INHERIT6^#
20+
func f1<S1: P1, S2 : #^INHERIT5?check=INHERIT^#>(p : S1) {}
21+
func f2<S1: P1, S2 : #^INHERIT6?check=INHERIT^#
3122
}
3223

3324
// INHERIT-DAG: Decl[Class]/CurrModule: C1[#C1#]{{; name=.+$}}
@@ -44,7 +35,7 @@ class C3 {
4435
class C4<T, U> {}
4536

4637
_ = C4<#^GENERIC_TYPE_PARAM^# >()
47-
_ = C4<SomeType, #^SECOND_GENERIC_TYPE_PARAM^# >()
38+
_ = C4<SomeType, #^SECOND_GENERIC_TYPE_PARAM?check=GENERIC_TYPE_PARAM^# >()
4839
// GENERIC_TYPE_PARAM-DAG: Decl[Class]/CurrModule: C1[#C1#];
4940

5041
// https://github.com/apple/swift/issues/56979
@@ -55,10 +46,10 @@ struct S2 {
5546
}
5647
}
5748

58-
var s2_globalVar = S2.Nested< #^GENERIC_PARAM_ON_NESTED_TYPE_GLOBAL_VAR^#>()
49+
var s2_globalVar = S2.Nested< #^GENERIC_PARAM_ON_NESTED_TYPE_GLOBAL_VAR?check=GENERIC_PARAM_ON_NESTED_TYPE^#>()
5950

6051
func someFunction() {
61-
var s2_localVar = S2.Nested< #^GENERIC_PARAM_ON_NESTED_TYPE_LOCAL_VAR^#>()
52+
var s2_localVar = S2.Nested< #^GENERIC_PARAM_ON_NESTED_TYPE_LOCAL_VAR?check=GENERIC_PARAM_ON_NESTED_TYPE^#>()
6253
}
6354

6455
// GENERIC_PARAM_ON_NESTED_TYPE-DAG: Decl[Struct]/CurrModule: S2[#S2#];

test/IDE/complete_opaque_result.swift

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,21 @@ struct ConcreteMyProtocol : MyProtocol {
1212

1313
// MARK: 'some' keyword.
1414

15-
// BEGINNING_WITH_SOME-DAG: Keyword/None: some[#some#]; name=some
15+
// BEGINNING_WITH_SOME-DAG: Keyword/None: some; name=some
1616
// BEGINNING_WITH_SOME-DAG: Keyword/None: Any[#Any#]; name=Any
1717
// BEGINNING_WITH_SOME-DAG: Decl[Enum]/CurrModule: MyEnum[#MyEnum#]; name=MyEnum
1818
// BEGINNING_WITH_SOME-DAG: Decl[Class]/CurrModule: MyClass[#MyClass#]; name=MyClass
1919
// BEGINNING_WITH_SOME-DAG: Decl[Protocol]/CurrModule: MyProtocol[#MyProtocol#]; name=MyProtocol
2020
// BEGINNING_WITH_SOME-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
2121

22-
// BEGINNING_WITHOUT_SOME-NOT: Keyword/None: some
23-
// BEGINNING_WITHOUT_SOME-DAG: Keyword/None: Any[#Any#]; name=Any
24-
// BEGINNING_WITHOUT_SOME-DAG: Decl[Enum]/CurrModule: MyEnum[#MyEnum#]; name=MyEnum
25-
// BEGINNING_WITHOUT_SOME-DAG: Decl[Class]/CurrModule: MyClass[#MyClass#]; name=MyClass
26-
// BEGINNING_WITHOUT_SOME-DAG: Decl[Protocol]/CurrModule: MyProtocol[#MyProtocol#]; name=MyProtocol
27-
// BEGINNING_WITHOUT_SOME-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
28-
// BEGINNING_WITHOUT_SOME-NOT: Keyword/None: some
29-
3022
func gloabalFunc() -> #^GLOBAL_FUNC?check=BEGINNING_WITH_SOME^#
31-
var globalVar: #^GLOBAL_VAR?check=BEGINNING_WITHOUT_SOME^#
23+
var globalVar: #^GLOBAL_VAR?check=BEGINNING_WITH_SOME^#
3224

3325
protocol SomeProto {
34-
associatedtype protoAssocTy: #^PROTOCOL_ASSOCIATEDTYPE?check=BEGINNING_WITHOUT_SOME^#
35-
func protoMethodReq() -> #^PROTOCOL_METHOD_REQUIREMENT?check=BEGINNING_WITHOUT_SOME^#
36-
var protoVarReq: #^PROTOCOL_VAR_REQUIREMENT?check=BEGINNING_WITHOUT_SOME^#
37-
subscript(req: Int) -> #^PROTOCOL_SUBSCRIPT_REQUIREMENT?check=BEGINNING_WITHOUT_SOME^#
26+
associatedtype protoAssocTy: #^PROTOCOL_ASSOCIATEDTYPE?check=BEGINNING_WITH_SOME^#
27+
func protoMethodReq() -> #^PROTOCOL_METHOD_REQUIREMENT?check=BEGINNING_WITH_SOME^#
28+
var protoVarReq: #^PROTOCOL_VAR_REQUIREMENT?check=BEGINNING_WITH_SOME^#
29+
subscript(req: Int) -> #^PROTOCOL_SUBSCRIPT_REQUIREMENT?check=BEGINNING_WITH_SOME^#
3830
}
3931

4032
extension SomeProto {
@@ -44,7 +36,7 @@ extension SomeProto {
4436
}
4537

4638
struct SomeStruct {
47-
typealias TyAlias = #^STRUCT_TYPEALIAS_RHS?check=BEGINNING_WITHOUT_SOME^#
39+
typealias TyAlias = #^STRUCT_TYPEALIAS_RHS?check=BEGINNING_WITH_SOME^#
4840
func structMethodExt() -> #^STRUCT_METHOD?check=BEGINNING_WITH_SOME^#
4941
var structVarExt: #^STRUCT_VAR?check=BEGINNING_WITH_SOME^#
5042
subscript(struct: Int) -> #^STRUCT_SUBSCRIPT?check=BEGINNING_WITH_SOME^#

test/IDE/complete_some_any.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %batch-code-completion
2+
3+
func test1(x: #^PARAM?check=HAS_SOME_ANY;check=HAS_REPEAT^#) {}
4+
5+
func test2() -> #^RESULT?check=HAS_SOME_ANY;check=NO_REPEAT^# {}
6+
7+
func test3() {
8+
// FIXME: 'repeat' is not valid here semantically but we allow it syntactically and can't (easily) tell in the parser whether 'repeat' is valid. Not worth fixing in the old parser.
9+
let a: [#^ARRAY_TYPE?check=HAS_SOME_ANY;check=HAS_REPEAT^#]
10+
let b: any #^AFTER_ANY?check=NO_SOME_ANY;check=NO_REPEAT^#
11+
}
12+
13+
func test4(x: repeat #^AFTER_REPEAT?check=HAS_SOME_ANY;check=NO_REPEAT^#) {}
14+
15+
// HAS_SOME_ANY-DAG: Keyword/None: some; name=some
16+
// HAS_SOME_ANY-DAG: Keyword/None: any; name=any
17+
// HAS_SOME_ANY-DAG: Keyword/None: each; name=each
18+
19+
// NO_SOME_ANY-NOT: Keyword/None: some; name=some
20+
// NO_SOME_ANY-NOT: Keyword/None: any; name=any
21+
// NO_SOME_ANY-NOT: Keyword/None: each; name=each
22+
23+
// HAS_REPEAT-DAG: Keyword/None: repeat; name=repeat
24+
25+
// NO_REPEAT-NOT: Keyword/None: repeat; name=repeat

tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ bool SourceKit::CodeCompletion::addCustomCompletions(
176176
}
177177
break;
178178
case CompletionKind::TypeDeclResultBeginning:
179+
case CompletionKind::TypeBeginning:
180+
case CompletionKind::TypeSimpleOrComposition:
179181
case CompletionKind::TypeSimpleBeginning:
180182
if (custom.Contexts.contains(CustomCompletionInfo::Type)) {
181183
changed = true;
@@ -451,6 +453,8 @@ void CodeCompletionOrganizer::Impl::addCompletionsWithFilter(
451453
bool hideLowPriority =
452454
options.hideLowPriority &&
453455
completionKind != CompletionKind::TypeDeclResultBeginning &&
456+
completionKind != CompletionKind::TypeBeginning &&
457+
completionKind != CompletionKind::TypeSimpleOrComposition &&
454458
completionKind != CompletionKind::TypeSimpleBeginning &&
455459
completionKind != CompletionKind::PostfixExpr;
456460
for (Completion *completion : completions) {

0 commit comments

Comments
 (0)