Skip to content

Commit 502a7bf

Browse files
authored
Merge pull request #24180 from rintaro/ide-completion-static-subscript-rdar49131687
[CodeCompletion] Completion support for static subscript
2 parents 73d3fd6 + 6e0b8c2 commit 502a7bf

File tree

4 files changed

+88
-7
lines changed

4 files changed

+88
-7
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2607,8 +2607,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26072607
}
26082608

26092609
void addSubscriptCall(const SubscriptDecl *SD, DeclVisibilityKind Reason) {
2610-
// Don't add subscript call to meta types.
2611-
if (!ExprType || ExprType->is<AnyMetatypeType>())
2610+
// Don't add subscript call to unqualified completion.
2611+
if (!ExprType)
26122612
return;
26132613

26142614
// Subscript after '.' is valid only after type part of Swift keypath

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ class ExprParentFinder : public ASTWalker {
268268
static void collectPossibleCalleesByQualifiedLookup(
269269
DeclContext &DC, Type baseTy, DeclBaseName name,
270270
SmallVectorImpl<FunctionTypeAndDecl> &candidates) {
271+
bool isOnMetaType = baseTy->is<AnyMetatypeType>();
271272

272273
SmallVector<ValueDecl *, 2> decls;
273274
auto resolver = DC.getASTContext().getLazyResolver();
@@ -287,16 +288,18 @@ static void collectPossibleCalleesByQualifiedLookup(
287288
continue;
288289
Type declaredMemberType = VD->getInterfaceType();
289290
if (VD->getDeclContext()->isTypeContext()) {
290-
if (auto *FD = dyn_cast<FuncDecl>(VD)) {
291-
if (!baseTy->is<AnyMetatypeType>())
291+
if (isa<FuncDecl>(VD)) {
292+
if (!isOnMetaType)
292293
declaredMemberType =
293294
declaredMemberType->castTo<AnyFunctionType>()->getResult();
294-
}
295-
if (auto *CD = dyn_cast<ConstructorDecl>(VD)) {
296-
if (!baseTy->is<AnyMetatypeType>())
295+
} else if (isa<ConstructorDecl>(VD)) {
296+
if (!isOnMetaType)
297297
continue;
298298
declaredMemberType =
299299
declaredMemberType->castTo<AnyFunctionType>()->getResult();
300+
} else if (isa<SubscriptDecl>(VD)) {
301+
if (isOnMetaType != VD->isStatic())
302+
continue;
300303
}
301304
}
302305

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,17 @@ static bool isDeclVisibleInLookupMode(ValueDecl *Member, LookupState LS,
142142
// Otherwise, either call a function or curry it.
143143
return true;
144144
}
145+
if (auto *SD = dyn_cast<SubscriptDecl>(Member)) {
146+
// Cannot use static subscripts on non-metatypes.
147+
if (!LS.isOnMetatype() && SD->isStatic())
148+
return false;
149+
150+
// Cannot use instance subscript on metatypes.
151+
if (LS.isOnMetatype() && !SD->isStatic() && !LS.isIncludingInstanceMembers())
152+
return false;
153+
154+
return true;
155+
}
145156
if (auto *VD = dyn_cast<VarDecl>(Member)) {
146157
// Cannot use static properties on non-metatypes.
147158
if (!(LS.isQualified() && LS.isOnMetatype()) && VD->isStatic())

test/IDE/complete_subscript.swift

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=METATYPE_UNRESOLVED | %FileCheck %s -check-prefix=METATYPE_UNRESOLVED
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=METATYPE_INT | %FileCheck %s -check-prefix=METATYPE_INT
3+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INSTANCE_INT | %FileCheck %s -check-prefix=INSTANCE_INT
4+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=METATYPE_ARCHETYPE | %FileCheck %s -check-prefix=METATYPE_ARCHETYPE
5+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INSTANCE_ARCHETYPE | %FileCheck %s -check-prefix=INSTANCE_ARCHETYPE
6+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=METATYPE_LABEL | %FileCheck %s -check-prefix=METATYPE_LABEL
7+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INSTANCE_LABEL | %FileCheck %s -check-prefix=INSTANCE_LABEL
8+
9+
struct MyStruct<T> {
10+
static subscript(x: Int, static defValue: T) -> MyStruct<T> {
11+
fatalError()
12+
}
13+
subscript(x: Int, instance defValue: T) -> Int {
14+
fatalError()
15+
}
16+
}
17+
18+
func test1() {
19+
let _ = MyStruct #^METATYPE_UNRESOLVED^#
20+
// METATYPE_UNRESOLVED: Begin completions, 4 items
21+
// METATYPE_UNRESOLVED-DAG: Decl[Subscript]/CurrNominal: [{#(x): Int#}, {#static: _#}][#MyStruct<_>#];
22+
// METATYPE_UNRESOLVED-DAG: Decl[Constructor]/CurrNominal: ()[#MyStruct<_>#];
23+
// METATYPE_UNRESOLVED-DAG: Keyword[self]/CurrNominal: .self[#MyStruct<_>.Type#];
24+
// METATYPE_UNRESOLVED-DAG: Keyword/CurrNominal: .Type[#MyStruct<_>.Type#];
25+
// METATYPE_UNRESOLVED: End completions
26+
27+
28+
let _ = MyStruct<Int> #^METATYPE_INT^#
29+
// METATYPE_INT: Begin completions, 4 items
30+
// METATYPE_INT-DAG: Decl[Subscript]/CurrNominal: [{#(x): Int#}, {#static: Int#}][#MyStruct<Int>#];
31+
// METATYPE_INT-DAG: Decl[Constructor]/CurrNominal: ()[#MyStruct<Int>#];
32+
// METATYPE_INT-DAG: Keyword[self]/CurrNominal: .self[#MyStruct<Int>.Type#];
33+
// METATYPE_INT-DAG: Keyword/CurrNominal: .Type[#MyStruct<Int>.Type#];
34+
// METATYPE_INT: End completions
35+
36+
let _ = MyStruct<Int>()#^INSTANCE_INT^#
37+
// INSTANCE_INT: Begin completions, 2 items
38+
// INSTANCE_INT-DAG: Decl[Subscript]/CurrNominal: [{#(x): Int#}, {#instance: Int#}][#Int#];
39+
// INSTANCE_INT-DAG: Keyword[self]/CurrNominal: .self[#MyStruct<Int>#];
40+
// INSTANCE_INT: End completions
41+
42+
}
43+
func test2<U>(value: MyStruct<U>) {
44+
let _ = MyStruct<U>#^METATYPE_ARCHETYPE^#
45+
// METATYPE_ARCHETYPE: Begin completions, 4 items
46+
// METATYPE_ARCHETYPE-DAG: Decl[Subscript]/CurrNominal: [{#(x): Int#}, {#static: U#}][#MyStruct<U>#];
47+
// METATYPE_ARCHETYPE-DAG: Decl[Constructor]/CurrNominal: ()[#MyStruct<U>#];
48+
// METATYPE_ARCHETYPE-DAG: Keyword[self]/CurrNominal: .self[#MyStruct<U>.Type#];
49+
// METATYPE_ARCHETYPE-DAG: Keyword/CurrNominal: .Type[#MyStruct<U>.Type#];
50+
// METATYPE_ARCHETYPE: End completions
51+
52+
let _ = value #^INSTANCE_ARCHETYPE^#
53+
// INSTANCE_ARCHETYPE: Begin completions, 2 items
54+
// INSTANCE_ARCHETYPE-DAG: Decl[Subscript]/CurrNominal: [{#(x): Int#}, {#instance: U#}][#Int#];
55+
// INSTANCE_ARCHETYPE-DAG: Keyword[self]/CurrNominal: .self[#MyStruct<U>#];
56+
// INSTANCE_ARCHETYPE: End completions
57+
58+
let _ = MyStruct<U>[42, #^METATYPE_LABEL^#
59+
// METATYPE_LABEL: Begin completions, 1 items
60+
// METATYPE_LABEL-DAG: Keyword/ExprSpecific: static: [#Argument name#];
61+
// METATYPE_LABEL: End completions
62+
63+
let _ = value[42, #^INSTANCE_LABEL^#
64+
// INSTANCE_LABEL: Begin completions, 1 items
65+
// INSTANCE_LABEL-DAG: Keyword/ExprSpecific: instance: [#Argument name#];
66+
// INSTANCE_LABEL: End completions
67+
}

0 commit comments

Comments
 (0)