Skip to content

Commit 8084868

Browse files
committed
[LookupVisibleDecls] Tweak unquialified lookup
- Show static var decls in non-qualified metatype lookup - Show enum element decls in non-qualified metatype lookup - Never show initializers in non-qualified lookup - Perform instance lookups in lazy var initializer - Perform non-qualified metatype lookup inside static func rdar://problem/57622639
1 parent 946f234 commit 8084868

File tree

3 files changed

+168
-12
lines changed

3 files changed

+168
-12
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,16 +2547,22 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25472547
}
25482548

25492549
bool isImplicitlyCurriedInstanceMethod(const AbstractFunctionDecl *FD) {
2550+
if (FD->isStatic())
2551+
return false;
2552+
25502553
switch (Kind) {
25512554
case LookupKind::ValueExpr:
2552-
return ExprType->is<AnyMetatypeType>() && !FD->isStatic();
2555+
return ExprType->is<AnyMetatypeType>();
25532556
case LookupKind::ValueInDeclContext:
2554-
if (InsideStaticMethod &&
2555-
FD->getDeclContext() == CurrentMethod->getDeclContext() &&
2556-
!FD->isStatic())
2557-
return true;
2558-
if (auto Init = dyn_cast<Initializer>(CurrDeclContext))
2559-
return FD->getDeclContext() == Init->getParent() && !FD->isStatic();
2557+
if (InsideStaticMethod)
2558+
return FD->getDeclContext() == CurrentMethod->getDeclContext();
2559+
if (auto Init = dyn_cast<Initializer>(CurrDeclContext)) {
2560+
if (auto PatInit = dyn_cast<PatternBindingInitializer>(Init)) {
2561+
if (PatInit->getInitializedLazyVar())
2562+
return false;
2563+
}
2564+
return FD->getDeclContext() == Init->getInnermostTypeContext();
2565+
}
25602566
return false;
25612567
case LookupKind::EnumElement:
25622568
case LookupKind::Type:

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static bool isDeclVisibleInLookupMode(ValueDecl *Member, LookupState LS,
156156
}
157157
if (auto *VD = dyn_cast<VarDecl>(Member)) {
158158
// Cannot use static properties on non-metatypes.
159-
if (!(LS.isQualified() && LS.isOnMetatype()) && VD->isStatic())
159+
if (!LS.isOnMetatype() && VD->isStatic())
160160
return false;
161161

162162
// Cannot use instance properties on metatypes.
@@ -167,14 +167,16 @@ static bool isDeclVisibleInLookupMode(ValueDecl *Member, LookupState LS,
167167
}
168168
if (isa<EnumElementDecl>(Member)) {
169169
// Cannot reference enum elements on non-metatypes.
170-
if (!(LS.isQualified() && LS.isOnMetatype()))
170+
if (!LS.isOnMetatype())
171171
return false;
172172
}
173173
if (auto CD = dyn_cast<ConstructorDecl>(Member)) {
174+
if (!LS.isQualified())
175+
return false;
174176
// Constructors with stub implementations cannot be called in Swift.
175177
if (CD->hasStubImplementation())
176178
return false;
177-
if (LS.isQualified() && LS.isOnSuperclass()) {
179+
if (LS.isOnSuperclass()) {
178180
// Cannot call initializers from a superclass, except for inherited
179181
// convenience initializers.
180182
return LS.isInheritsSuperclassInitializers() && CD->isInheritable();
@@ -1065,8 +1067,11 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
10651067

10661068
// Skip initializer contexts, we will not find any declarations there.
10671069
if (isa<Initializer>(DC)) {
1070+
// For non-'lazy' decls, lookup on the meta type.
1071+
if (!isa<PatternBindingInitializer>(DC) ||
1072+
!cast<PatternBindingInitializer>(DC)->getInitializedLazyVar())
1073+
LS = LS.withOnMetatype();
10681074
DC = DC->getParent();
1069-
LS = LS.withOnMetatype();
10701075
}
10711076

10721077
// We don't look for generic parameters if we are in the context of a
@@ -1083,6 +1088,8 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
10831088
if (auto *SE = dyn_cast<SubscriptDecl>(DC)) {
10841089
ExtendedType = SE->getDeclContext()->getSelfTypeInContext();
10851090
DC = DC->getParent();
1091+
if (SE->isStatic())
1092+
LS = LS.withOnMetatype();
10861093
} else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
10871094

10881095
// Look for local variables; normally, the parser resolves these
@@ -1112,7 +1119,7 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
11121119

11131120
if (auto *FD = dyn_cast<FuncDecl>(AFD))
11141121
if (FD->isStatic())
1115-
ExtendedType = MetatypeType::get(ExtendedType);
1122+
LS = LS.withOnMetatype();
11161123
}
11171124
} else if (auto CE = dyn_cast<ClosureExpr>(DC)) {
11181125
if (Loc.isValid()) {
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INSTANCE_VAR_INIT | %FileCheck %s -check-prefix=STRUCT_STATIC
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_STATIC_VAR_INIT | %FileCheck %s -check-prefix=STRUCT_STATIC
3+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_LAZY_VAR_INIT | %FileCheck %s -check-prefix=STRUCT_INSTANCE
4+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INSTANCE_VAR_BODY | %FileCheck %s -check-prefix=STRUCT_INSTANCE
5+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_STATIC_VAR_BODY | %FileCheck %s -check-prefix=STRUCT_STATIC
6+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INITIALIZER_DEFAULTPARAM | %FileCheck %s -check-prefix=STRUCT_STATIC
7+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INITIALIZER_BODY | %FileCheck %s -check-prefix=STRUCT_INSTANCE
8+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INSTANCE_FUNC_DEFAULTPARAM | %FileCheck %s -check-prefix=STRUCT_STATIC
9+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INSTANCE_FUNC_BODY | %FileCheck %s -check-prefix=STRUCT_INSTANCE
10+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_STATIC_FUNC_DEFAULTPARAM | %FileCheck %s -check-prefix=STRUCT_STATIC
11+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_STATIC_FUNC_BODY | %FileCheck %s -check-prefix=STRUCT_STATIC
12+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INSTANCE_SUBSCRIPT_DEFAULTPARAM | %FileCheck %s -check-prefix=STRUCT_STATIC
13+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_INSTANCE_SUBSCRIPT_BODY | %FileCheck %s -check-prefix=STRUCT_INSTANCE
14+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_STATIC_SUBSCRIPT_DEFAULTPARAM | %FileCheck %s -check-prefix=STRUCT_STATIC
15+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_STATIC_SUBSCRIPT_BODY | %FileCheck %s -check-prefix=STRUCT_STATIC
16+
17+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_STATIC_VAR_INIT | %FileCheck %s -check-prefix=ENUM_STATIC
18+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_INSTANCE_VAR_BODY | %FileCheck %s -check-prefix=ENUM_INSTANCE
19+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_STATIC_VAR_BODY | %FileCheck %s -check-prefix=ENUM_STATIC
20+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_INITIALIZER_DEFAULTPARAM | %FileCheck %s -check-prefix=ENUM_STATIC
21+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_INITIALIZER_BODY | %FileCheck %s -check-prefix=ENUM_INSTANCE
22+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_INSTANCE_FUNC_DEFAULTPARAM | %FileCheck %s -check-prefix=ENUM_STATIC
23+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_INSTANCE_FUNC_BODY | %FileCheck %s -check-prefix=ENUM_INSTANCE
24+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_STATIC_FUNC_DEFAULTPARAM | %FileCheck %s -check-prefix=ENUM_STATIC
25+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_STATIC_FUNC_BODY | %FileCheck %s -check-prefix=ENUM_STATIC
26+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_INSTANCE_SUBSCRIPT_DEFAULTPARAM | %FileCheck %s -check-prefix=ENUM_STATIC
27+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_INSTANCE_SUBSCRIPT_BODY | %FileCheck %s -check-prefix=ENUM_INSTANCE
28+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_STATIC_SUBSCRIPT_DEFAULTPARAM | %FileCheck %s -check-prefix=ENUM_STATIC
29+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_STATIC_SUBSCRIPT_BODY | %FileCheck %s -check-prefix=ENUM_STATIC
30+
31+
32+
// STRUCT_INSTANCE: Begin completions
33+
// STRUCT_INSTANCE-NOT: init()
34+
// STRUCT_INSTANCE-NOT: staticVar
35+
// STRUCT_INSTANCE-NOT: staticFunc
36+
// STRUCT_INSTANCE-DAG: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#];
37+
// STRUCT_INSTANCE-DAG: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#Int#];
38+
// STRUCT_INSTANCE-NOT: init()
39+
// STRUCT_INSTANCE-NOT: staticVar
40+
// STRUCT_INSTANCE-NOT: staticFunc
41+
// STRUCT_INSTANCE: End completions
42+
43+
// STRUCT_STATIC: Begin completions
44+
// STRUCT_STATIC-NOT: init()
45+
// STRUCT_STATIC-NOT: instanceVar
46+
// STRUCT_STATIC-DAG: Decl[StaticVar]/CurrNominal: staticVar[#Int#];
47+
// STRUCT_STATIC-DAG: Decl[StaticMethod]/CurrNominal: staticFunc()[#Int#];
48+
// STRUCT_STATIC-DAG: Decl[InstanceMethod]/CurrNominal: instanceFunc({#(self): MyStruct#})[#() -> Int#];
49+
// STRUCT_STATIC-NOT: init()
50+
// STRUCT_STATIC-NOT: instanceVar
51+
// STRUCT_STATIC: End completions
52+
53+
struct MyStruct {
54+
init() { self = MyEnum.east }
55+
static var staticVar: Int { 1 }
56+
static func staticFunc() -> Int { 1 }
57+
var instanceVar: Int { 1 }
58+
func instanceFunc() -> Int { 1 }
59+
60+
var testInstanceVarInit: String = (#^STRUCT_INSTANCE_VAR_INIT^#)
61+
static var testStaticVarInit: String = (#^STRUCT_STATIC_VAR_INIT^#)
62+
lazy var testLazyVarInit: String = (#^STRUCT_LAZY_VAR_INIT^#)
63+
var testInstanceVar: String {
64+
#^STRUCT_INSTANCE_VAR_BODY^#
65+
}
66+
static var testStaticVar: String {
67+
#^STRUCT_STATIC_VAR_BODY^#
68+
}
69+
init(testInit: String = #^STRUCT_INITIALIZER_DEFAULTPARAM^#) {
70+
#^STRUCT_INITIALIZER_BODY^#
71+
}
72+
func testInstanceMethod(x: String = #^STRUCT_INSTANCE_FUNC_DEFAULTPARAM^#) {
73+
#^STRUCT_INSTANCE_FUNC_BODY^#
74+
}
75+
static func testStaticMethod(x: String = #^STRUCT_STATIC_FUNC_DEFAULTPARAM^#) {
76+
#^STRUCT_STATIC_FUNC_BODY^#
77+
}
78+
subscript(testInstanceSubscript idx: String = #^STRUCT_INSTANCE_SUBSCRIPT_DEFAULTPARAM^#) {
79+
#^STRUCT_INSTANCE_SUBSCRIPT_BODY^#
80+
}
81+
static subscript(testStaticSubscript idx: String = #^STRUCT_STATIC_SUBSCRIPT_DEFAULTPARAM^#) {
82+
#^STRUCT_STATIC_SUBSCRIPT_BODY^#
83+
}
84+
}
85+
86+
// ENUM_INSTANCE: Begin completions
87+
// ENUM_INSTANCE-NOT: east
88+
// ENUM_INSTANCE-NOT: west
89+
// ENUM_INSTANCE-NOT: init()
90+
// ENUM_INSTANCE-NOT: staticVar
91+
// ENUM_INSTANCE-NOT: staticFunc
92+
// ENUM_INSTANCE-DAG: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#];
93+
// ENUM_INSTANCE-DAG: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#Int#];
94+
// ENUM_INSTANCE-NOT: east
95+
// ENUM_INSTANCE-NOT: west
96+
// ENUM_INSTANCE-NOT: init()
97+
// ENUM_INSTANCE-NOT: staticVar
98+
// ENUM_INSTANCE-NOT: staticFunc
99+
// ENUM_INSTANCE: End completions
100+
101+
// ENUM_STATIC: Begin completions
102+
// ENUM_STATIC-NOT: init()
103+
// ENUM_STATIC-NOT: instanceVar
104+
// ENUM_STATIC-DAG: Decl[EnumElement]/CurrNominal: east[#MyEnum#];
105+
// ENUM_STATIC-DAG: Decl[EnumElement]/CurrNominal: west[#MyEnum#];
106+
// ENUM_STATIC-DAG: Decl[StaticVar]/CurrNominal: staticVar[#Int#];
107+
// ENUM_STATIC-DAG: Decl[StaticMethod]/CurrNominal: staticFunc()[#Int#];
108+
// ENUM_STATIC-DAG: Decl[InstanceMethod]/CurrNominal: instanceFunc({#(self): MyEnum#})[#() -> Int#];
109+
// ENUM_STATIC-NOT: init()
110+
// ENUM_STATIC-NOT: instanceVar
111+
// ENUM_STATIC: End completions
112+
113+
enum MyEnum {
114+
case east, west
115+
init() { self = MyEnum.east }
116+
static var staticVar: Int = 1
117+
static func staticFunc() -> Int { 1 }
118+
var instanceVar: Int { 1 }
119+
func instanceFunc() -> Int { 1 }
120+
121+
static var testStaticVarInit: String = (#^ENUM_STATIC_VAR_INIT^#)
122+
var testInstanceVar: String {
123+
#^ENUM_INSTANCE_VAR_BODY^#
124+
}
125+
static var testStaticVar: String {
126+
#^ENUM_STATIC_VAR_BODY^#
127+
}
128+
func init(testInit: String = #^ENUM_INITIALIZER_DEFAULTPARAM^#) {
129+
#^ENUM_INITIALIZER_BODY^#
130+
}
131+
func testInstanceMethod(x: String = #^ENUM_INSTANCE_FUNC_DEFAULTPARAM^#) {
132+
#^ENUM_INSTANCE_FUNC_BODY^#
133+
}
134+
static func testStaticMethod(x: String = #^ENUM_STATIC_FUNC_DEFAULTPARAM^#) {
135+
#^ENUM_STATIC_FUNC_BODY^#
136+
}
137+
subscript(testInstanceSubscript idx: String = #^ENUM_INSTANCE_SUBSCRIPT_DEFAULTPARAM^#) {
138+
#^ENUM_INSTANCE_SUBSCRIPT_BODY^#
139+
}
140+
static subscript(testStaticSubscript idx: String = #^ENUM_STATIC_SUBSCRIPT_DEFAULTPARAM^#) {
141+
#^ENUM_STATIC_SUBSCRIPT_BODY^#
142+
}
143+
}

0 commit comments

Comments
 (0)