Skip to content

Commit e7ee839

Browse files
committed
[CursorInfo] A few miscellaneous fixes to the AST-based cursor info and new test cases
In these cases the solver-based and AST-based cursor info differed in their results. Fix the AST-based cursor info to return the correct results and add test cases to make sure the solver-based implementation doesn’t regress them.
1 parent fcc5d98 commit e7ee839

File tree

4 files changed

+106
-5
lines changed

4 files changed

+106
-5
lines changed

lib/IDE/Utils.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,9 @@ Expr *swift::ide::getBase(ArrayRef<Expr *> ExprStack) {
860860

861861
Expr *CurrentE = ExprStack.back();
862862
Expr *ParentE = getContainingExpr(ExprStack, 1);
863+
if (ParentE && isa<FunctionConversionExpr>(ParentE)) {
864+
ParentE = getContainingExpr(ExprStack, 2);
865+
}
863866
Expr *Base = nullptr;
864867

865868
if (auto DSE = dyn_cast_or_null<DotSyntaxCallExpr>(ParentE))
@@ -925,6 +928,8 @@ bool swift::ide::isDynamicRef(Expr *Base, ValueDecl *D, llvm::function_ref<Type(
925928
if (!isDeclOverridable(D))
926929
return false;
927930

931+
Base = Base->getSemanticsProvidingExpr();
932+
928933
// super.method()
929934
// TODO: Should be dynamic if `D` is marked as dynamic and @objc, but in
930935
// that case we really need to change the role the index outputs as
@@ -956,11 +961,9 @@ void swift::ide::getReceiverType(Expr *Base,
956961
if (!ReceiverTy)
957962
return;
958963

959-
if (auto LVT = ReceiverTy->getAs<LValueType>())
960-
ReceiverTy = LVT->getObjectType();
961-
else if (auto MetaT = ReceiverTy->getAs<MetatypeType>())
962-
ReceiverTy = MetaT->getInstanceType();
963-
else if (auto SelfT = ReceiverTy->getAs<DynamicSelfType>())
964+
ReceiverTy = ReceiverTy->getWithoutSpecifierType();
965+
ReceiverTy = ReceiverTy->getMetatypeInstanceType();
966+
if (auto SelfT = ReceiverTy->getAs<DynamicSelfType>())
964967
ReceiverTy = SelfT->getSelfType();
965968

966969
// TODO: Handle generics and composed protocols
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
protocol Publisher<Output> {
2+
associatedtype Output
3+
}
4+
5+
extension Publisher {
6+
func stage2() -> MyGenerictype<Self.Output> {
7+
fatalError()
8+
}
9+
10+
func stage3() -> Self {
11+
fatalError()
12+
}
13+
}
14+
15+
struct MyGenerictype<Output> : Publisher {
16+
init() {}
17+
18+
func stage1(with output: Self.Output) -> HasTypeAccessInTypealias<Self> {
19+
fatalError()
20+
}
21+
}
22+
23+
struct HasTypeAccessInTypealias<Upstream> : Publisher where Upstream : Publisher {
24+
typealias Output = Upstream.Output
25+
}
26+
27+
func test() {
28+
MyGenerictype()
29+
.stage1(with: 0)
30+
.stage2()
31+
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):6 %s -- %s
32+
.stage3()
33+
}
34+
35+
// CHECK: <Declaration>func stage3() -&gt; <Type usr="s:4test13MyGenerictypeV">MyGenerictype</Type>&lt;<Type usr="s:4test24HasTypeAccessInTypealiasV">HasTypeAccessInTypealias</Type>&lt;<Type usr="s:4test13MyGenerictypeV">MyGenerictype</Type>&lt;<Type usr="s:Si">Int</Type>&gt;&gt;.<Type usr="s:4test24HasTypeAccessInTypealiasV6Outputa">Output</Type>&gt;</Declaration>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
func lookThroughFunctionConversions() {
2+
class DispatchQueue {
3+
class var main: DispatchQueue { get }
4+
func async(execute work: @escaping @convention(block) () -> Void)
5+
}
6+
7+
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):22 %s -- %s | %FileCheck %s --check-prefix=FUNCTION_CONVERSION
8+
DispatchQueue.main.async {}
9+
}
10+
11+
// FUNCTION_CONVERSION: (DispatchQueue) -> (@escaping @convention(block) () -> ()) -> ()
12+
// FUNCTION_CONVERSION: DYNAMIC
13+
14+
func lookThorughInout() {
15+
public struct Villager {}
16+
let villager = Villager()
17+
18+
var villagers: [Villager] = []
19+
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):13 %s -- %s | %FileCheck %s
20+
villagers.removeAll(where: { _ in true })
21+
}
22+
23+
// CHECK: RECEIVERS BEGIN
24+
// CHECK: s:Sa
25+
// CHECK: RECEIVERS END
26+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/Modules)
3+
// RUN: %{python} %utils/split_file.py -o %t %s
4+
5+
6+
// BEGIN MyModule.swift
7+
8+
public class UserCollection {
9+
public static let sharedStatic = UserCollection()
10+
public class var sharedComputedClass: UserCollection { UserCollection() }
11+
}
12+
13+
// RUN: %target-swift-frontend \
14+
// RUN: -emit-module \
15+
// RUN: -module-name MyModule \
16+
// RUN: -emit-module-path %t/Modules/MyModule.swiftmodule \
17+
// RUN: -emit-module-doc-path %t/Modules/MyModule.swiftdoc \
18+
// RUN: %t/MyModule.swift
19+
20+
// BEGIN test.swift
21+
import MyModule
22+
23+
func application() {
24+
UserCollection.sharedStatic
25+
UserCollection.sharedComputedClass
26+
}
27+
28+
// RUN: %sourcekitd-test -req=cursor -pos=4:18 %t/test.swift -- %t/test.swift -I %t/Modules | %FileCheck %s --check-prefix=SHARED_STATIC
29+
30+
// FIXME: This should be reported as 'static var' rdar://105239467
31+
// SHARED_STATIC: <Declaration>class let sharedStatic: <Type usr="s:8MyModule14UserCollectionC">UserCollection</Type></Declaration>
32+
// SHARED_STATIC: <decl.var.class><syntaxtype.keyword>class</syntaxtype.keyword> <syntaxtype.keyword>let</syntaxtype.keyword> <decl.name>sharedStatic</decl.name>: <decl.var.type><ref.class usr="s:8MyModule14UserCollectionC">UserCollection</ref.class></decl.var.type></decl.var.class>
33+
34+
// RUN: %sourcekitd-test -req=cursor -pos=5:18 %t/test.swift -- %t/test.swift -I %t/Modules| %FileCheck %s --check-prefix=SHARED_COMPUTED_CLASS
35+
36+
// SHARED_COMPUTED_CLASS: <Declaration>class var sharedComputedClass: <Type usr="s:8MyModule14UserCollectionC">UserCollection</Type> { get }</Declaration>
37+
// SHARED_COMPUTED_CLASS: <decl.var.class><syntaxtype.keyword>class</syntaxtype.keyword> <syntaxtype.keyword>var</syntaxtype.keyword> <decl.name>sharedComputedClass</decl.name>: <decl.var.type><ref.class usr="s:8MyModule14UserCollectionC">UserCollection</ref.class></decl.var.type> { <syntaxtype.keyword>get</syntaxtype.keyword> }</decl.var.class>

0 commit comments

Comments
 (0)