Skip to content

Commit 7234d42

Browse files
authored
Merge pull request #24221 from rintaro/5.1-ide-completion-static-subscript-rdar49131687
[5.1][CodeCompletion] Completion support for static subscript
2 parents 77d23ef + 962af06 commit 7234d42

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
@@ -2595,8 +2595,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25952595
}
25962596

25972597
void addSubscriptCall(const SubscriptDecl *SD, DeclVisibilityKind Reason) {
2598-
// Don't add subscript call to meta types.
2599-
if (!ExprType || ExprType->is<AnyMetatypeType>())
2598+
// Don't add subscript call to unqualified completion.
2599+
if (!ExprType)
26002600
return;
26012601

26022602
// 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
@@ -315,6 +315,7 @@ class ExprParentFinder : public ASTWalker {
315315
void collectPossibleCalleesByQualifiedLookup(
316316
DeclContext &DC, Type baseTy, DeclBaseName name,
317317
SmallVectorImpl<FunctionTypeAndDecl> &candidates) {
318+
bool isOnMetaType = baseTy->is<AnyMetatypeType>();
318319

319320
SmallVector<ValueDecl *, 2> decls;
320321
auto resolver = DC.getASTContext().getLazyResolver();
@@ -334,16 +335,18 @@ void collectPossibleCalleesByQualifiedLookup(
334335
continue;
335336
Type declaredMemberType = VD->getInterfaceType();
336337
if (VD->getDeclContext()->isTypeContext()) {
337-
if (auto *FD = dyn_cast<FuncDecl>(VD)) {
338-
if (!baseTy->is<AnyMetatypeType>())
338+
if (isa<FuncDecl>(VD)) {
339+
if (!isOnMetaType)
339340
declaredMemberType =
340341
declaredMemberType->castTo<AnyFunctionType>()->getResult();
341-
}
342-
if (auto *CD = dyn_cast<ConstructorDecl>(VD)) {
343-
if (!baseTy->is<AnyMetatypeType>())
342+
} else if (isa<ConstructorDecl>(VD)) {
343+
if (!isOnMetaType)
344344
continue;
345345
declaredMemberType =
346346
declaredMemberType->castTo<AnyFunctionType>()->getResult();
347+
} else if (isa<SubscriptDecl>(VD)) {
348+
if (isOnMetaType != VD->isStatic())
349+
continue;
347350
}
348351
}
349352

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)