Skip to content

Commit 01086bc

Browse files
authored
Merge pull request #65688 from bnbarham/swap-cursor-info-order
[CursorInfo] Prefer AST based results over solver based
2 parents f5fbee2 + 5beeca7 commit 01086bc

File tree

6 files changed

+102
-64
lines changed

6 files changed

+102
-64
lines changed
Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
1+
func bar() -> Int { return 1 }
2+
func bar() -> String { return "" }
3+
14
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 2):7 %s -- %s == -req=cursor -pos=%(line + 3):7 %s -- %s | %FileCheck %s --check-prefix IN-FUNCTION
25
func foo() {
3-
let inFunctionA = 1
4-
let inFunctionB = "hi"
6+
_ = bar()
7+
_ = bar()
58
}
69

7-
// IN-FUNCTION: source.lang.swift.decl.var.local
8-
// IN-FUNCTION-NEXT: inFunctionA
10+
// IN-FUNCTION: source.lang.swift.ref.function.free
11+
// IN-FUNCTION-NEXT: bar
912
// IN-FUNCTION: DID REUSE AST CONTEXT: 0
10-
// IN-FUNCTION: source.lang.swift.decl.var.local
11-
// IN-FUNCTION-NEXT: inFunctionB
13+
// IN-FUNCTION: source.lang.swift.ref.function.free
14+
// IN-FUNCTION-NEXT: bar
15+
// IN-FUNCTION-NEXT: bar
1216
// IN-FUNCTION: DID REUSE AST CONTEXT: 1
1317

1418
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 3):9 %s -- %s == -req=cursor -pos=%(line + 4):9 %s -- %s | %FileCheck %s --check-prefix IN-INSTANCE-METHOD
1519
struct MyStruct {
1620
func test() {
17-
let inInstanceMethod1 = 2
18-
let inInstanceMethod2 = "hello"
21+
_ = bar()
22+
_ = bar()
1923
}
2024
}
2125

22-
// IN-INSTANCE-METHOD: source.lang.swift.decl.var.local
23-
// IN-INSTANCE-METHOD-NEXT: inInstanceMethod1
26+
// IN-INSTANCE-METHOD: source.lang.swift.ref.function.free
27+
// IN-INSTANCE-METHOD-NEXT: bar
2428
// IN-INSTANCE-METHOD: DID REUSE AST CONTEXT: 0
25-
// IN-INSTANCE-METHOD: source.lang.swift.decl.var.local
26-
// IN-INSTANCE-METHOD-NEXT: inInstanceMethod2
29+
// IN-INSTANCE-METHOD: source.lang.swift.ref.function.free
30+
// IN-INSTANCE-METHOD-NEXT: bar
2731
// IN-INSTANCE-METHOD: DID REUSE AST CONTEXT: 1

test/SourceKit/CursorInfo/cursor_with_file_replacement.swift

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,90 +3,90 @@
33

44
// RUN: %sourcekitd-test \
55
// RUN: -shell -- echo '## State 1' == \
6-
// RUN: -req=cursor -pos=5:7 %t/file.swift -- %t/file.swift == \
6+
// RUN: -req=cursor -pos=6:21 %t/file.swift -- %t/file.swift == \
77
// RUN: -shell -- echo '## State 2' == \
88
// RUN: -shell -- cp %t/State2.swift %t/file.swift == \
9-
// RUN: -req=cursor -pos=6:7 %t/file.swift -- %t/file.swift == \
9+
// RUN: -req=cursor -pos=7:21 %t/file.swift -- %t/file.swift == \
1010
// RUN: -shell -- echo '## State 3' == \
1111
// RUN: -shell -- cp %t/State3.swift %t/file.swift == \
12-
// RUN: -req=cursor -pos=4:7 %t/file.swift -- %t/file.swift == \
12+
// RUN: -req=cursor -pos=5:21 %t/file.swift -- %t/file.swift == \
1313
// RUN: -shell -- echo '## State 4' == \
1414
// RUN: -shell -- cp %t/State4.swift %t/file.swift == \
15-
// RUN: -req=cursor -pos=4:7 %t/file.swift -- %t/file.swift == \
15+
// RUN: -req=cursor -pos=5:19 %t/file.swift -- %t/file.swift == \
1616
// RUN: -shell -- echo '## State 5' == \
1717
// RUN: -shell -- cp %t/State5.swift %t/file.swift == \
18-
// RUN: -req=cursor -pos=4:7 %t/file.swift -- %t/file.swift == \
18+
// RUN: -req=cursor -pos=5:19 %t/file.swift -- %t/file.swift == \
1919
// RUN: -shell -- echo '## State 6' == \
2020
// RUN: -shell -- cp %t/State6.swift %t/file.swift == \
21-
// RUN: -req=cursor -pos=4:7 %t/file.swift -- %t/file.swift > %t/response.txt
21+
// RUN: -req=cursor -pos=5:19 %t/file.swift -- %t/file.swift > %t/response.txt
2222
// RUN: %FileCheck %s < %t/response.txt
2323

2424
// CHECK-LABEL: ## State 1
25-
// CHECK: source.lang.swift.decl.var.local (5:7-5:18)
26-
// CHECK: <Declaration>let inFunctionB: <Type usr="s:SS">String</Type></Declaration>
25+
// CHECK: source.lang.swift.ref.function.free
2726
// CHECK: DID REUSE AST CONTEXT: 0
2827
// CHECK-LABEL: ## State 2
29-
// CHECK: source.lang.swift.decl.var.local (6:7-6:18)
30-
// CHECK: <Declaration>let inFunctionB: <Type usr="s:SS">String</Type></Declaration>
28+
// CHECK: source.lang.swift.ref.function.free
3129
// CHECK: DID REUSE AST CONTEXT: 1
3230
// CHECK-LABEL: ## State 3
33-
// CHECK: source.lang.swift.decl.var.local (4:7-4:18)
34-
// CHECK: <Declaration>let inFunctionB: <Type usr="s:SS">String</Type></Declaration>
31+
// CHECK: source.lang.swift.ref.function.free
3532
// CHECK: DID REUSE AST CONTEXT: 1
3633
// CHECK-LABEL: ## State 4
37-
// CHECK: source.lang.swift.decl.var.local (4:7-4:16)
38-
// CHECK: <Declaration>let myNewName: <Type usr="s:SS">String</Type></Declaration>
34+
// CHECK: source.lang.swift.ref.function.free
3935
// CHECK: DID REUSE AST CONTEXT: 1
4036
// CHECK-LABEL: ## State 5
41-
// CHECK: source.lang.swift.decl.var.local (4:7-4:16)
42-
// CHECK: <Declaration>let myNewName: <Type usr="s:SS">String</Type></Declaration>
37+
// CHECK: source.lang.swift.ref.function.free
4338
// CHECK: DID REUSE AST CONTEXT: 0
4439
// CHECK-LABEL: ## State 6
45-
// CHECK: source.lang.swift.decl.var.local (4:7-4:16)
46-
// CHECK: <Declaration>let myNewName: <Type usr="s:Si">Int</Type></Declaration>
40+
// CHECK: source.lang.swift.ref.function.free
4741
// CHECK: DID REUSE AST CONTEXT: 1
4842

4943
//--- file.swift
50-
func unrelated() {}
44+
func bar() -> Int { return 1 }
45+
func bar() -> String { return "" }
5146

5247
func foo() {
53-
let inFunctionA = 1
54-
let inFunctionB = "hi"
48+
let inFunctionA = bar()
49+
let inFunctionB = bar()
5550
}
5651

5752
//--- State2.swift
58-
func unrelated() {}
53+
func bar() -> Int { return 1 }
54+
func bar() -> String { return "" }
5955

6056
func foo() {
61-
let newlyAddedMember = 3
62-
let inFunctionA = 1
63-
let inFunctionB = "hi"
57+
let newlyAddedMember: Int = bar()
58+
let inFunctionA = bar()
59+
let inFunctionB = bar()
6460
}
6561

6662
//--- State3.swift
67-
func unrelated() {}
63+
func bar() -> Int { return 1 }
64+
func bar() -> String { return "" }
6865

6966
func foo() {
70-
let inFunctionB = "hi"
67+
let inFunctionB = bar()
7168
}
7269

7370
//--- State4.swift
74-
func unrelated() {}
71+
func bar() -> Int { return 1 }
72+
func bar() -> String { return "" }
7573

7674
func foo() {
77-
let myNewName = "hi"
75+
let myNewName = bar()
7876
}
7977

8078
//--- State5.swift
81-
func unrelated() {}
79+
func bar() -> Int { return 1 }
80+
func bar() -> String { return "" }
8281

8382
func foo(param: Int) {
84-
let myNewName = "hi"
83+
let myNewName = bar()
8584
}
8685

8786
//--- State6.swift
88-
func unrelated() {}
87+
func bar() -> Int { return 1 }
88+
func bar() -> String { return "" }
8989

9090
func foo(param: Int) {
91-
let myNewName = 7
91+
let myNewName = bar() + bar()
9292
}

test/SourceKit/CursorInfo/static_vs_class_spelling.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ func application() {
2121
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):18 %t/test.swift -- %t/test.swift -I %t/Modules -target %target-triple | %FileCheck %s --check-prefix=SHARED_STATIC
2222
UserCollection.sharedStatic
2323
// FIXME: This should be reported as 'static var' rdar://105239467
24-
// SHARED_STATIC: <Declaration>class let sharedStatic: <Type usr="s:8MyModule14UserCollectionC">UserCollection</Type></Declaration>
25-
// 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>
24+
// SHARED_STATIC: <Declaration>static let sharedStatic: <Type usr="s:8MyModule14UserCollectionC">UserCollection</Type></Declaration>
25+
// SHARED_STATIC: <decl.var.static><syntaxtype.keyword>static</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.static>
2626

2727
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):18 %t/test.swift -- %t/test.swift -I %t/Modules -target %target-triple | %FileCheck %s --check-prefix=SHARED_COMPUTED_CLASS
2828
UserCollection.sharedComputedClass

tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ SwiftInvocation::~SwiftInvocation() {
109109
delete &Impl;
110110
}
111111

112+
ArrayRef<std::string> SwiftInvocation::getArgs() const {
113+
return ArrayRef(Impl.Opts.Args);
114+
}
115+
112116
void SwiftInvocation::applyTo(swift::CompilerInvocation &CompInvok) const {
113117
return Impl.Opts.applyTo(CompInvok);
114118
}

tools/SourceKit/lib/SwiftLang/SwiftInvocation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class SwiftInvocation : public llvm::ThreadSafeRefCountedBase<SwiftInvocation> {
3333
struct Implementation;
3434
Implementation &Impl;
3535

36+
ArrayRef<std::string> getArgs() const;
3637
void applyTo(swift::CompilerInvocation &CompInvok) const;
3738
void raw(std::vector<std::string> &Args, std::string &PrimaryFile) const;
3839

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,27 +2018,52 @@ void SwiftLangSupport::getCursorInfo(
20182018
return;
20192019
}
20202020

2021-
bool SolverBasedProducedResult = false;
20222021
// Solver based cursor info cannot handle generated buffers or range based
20232022
// cursor info.
2024-
std::unique_ptr<llvm::MemoryBuffer> InputBuffer;
2023+
std::shared_ptr<llvm::MemoryBuffer> InputBuffer;
20252024
if (InputBufferName.empty() && Length == 0) {
20262025
std::string InputFileError;
20272026
llvm::SmallString<128> RealInputFilePath;
20282027
fileSystem->getRealPath(PrimaryFilePath, RealInputFilePath);
2029-
InputBuffer = getASTManager()->getMemoryBuffer(RealInputFilePath,
2030-
fileSystem, InputFileError);
2031-
}
2032-
2033-
if (InputBuffer) {
2034-
auto SolverBasedReceiver = [&](const RequestResult<CursorInfoData> &Res) {
2035-
SolverBasedProducedResult = true;
2028+
InputBuffer =
2029+
std::shared_ptr<llvm::MemoryBuffer>(getASTManager()->getMemoryBuffer(
2030+
RealInputFilePath, fileSystem, InputFileError));
2031+
}
2032+
2033+
// Receiver is async, so be careful about captured values. This is all
2034+
// fairly hacky in order to run AST based cursor info before solver based.
2035+
// ie. we shouldn't need to apply the compiler invocation again or copy any
2036+
// arguments. We could possibly sink this down into `resolveCursor`. Or
2037+
// improve the solver based so we don't need to run the old.
2038+
auto ASTBasedReceiver = [this, CancellationToken, Invok, InputBuffer,
2039+
fileSystem, Receiver, Offset, Actionables,
2040+
SymbolGraph](
2041+
const RequestResult<CursorInfoData> &Res) {
2042+
// AST based completion *always* produces a result
2043+
bool NoResults = Res.isError() || Res.isCancelled();
2044+
if (Res.isValue()) {
2045+
NoResults = Res.value().Symbols.empty();
2046+
}
2047+
if (!NoResults || !InputBuffer) {
20362048
Receiver(Res);
2037-
};
2049+
return;
2050+
}
20382051

20392052
CompilerInvocation CompInvok;
20402053
Invok->applyTo(CompInvok);
20412054

2055+
SmallVector<const char *, 0> Args;
2056+
Args.reserve(Invok->getArgs().size());
2057+
for (const std::string &Arg : Invok->getArgs()) {
2058+
Args.push_back(Arg.c_str());
2059+
}
2060+
2061+
bool SolverProducedResults = false;
2062+
auto SolverBasedReceiver = [&](const RequestResult<CursorInfoData> &Res) {
2063+
SolverProducedResults = true;
2064+
Receiver(Res);
2065+
};
2066+
20422067
performWithParamsToCompletionLikeOperation(
20432068
InputBuffer.get(), Offset,
20442069
/*InsertCodeCompletionToken=*/false, Args, fileSystem,
@@ -2056,14 +2081,18 @@ void SwiftLangSupport::getCursorInfo(
20562081
CompInvok, Actionables, SymbolGraph);
20572082
});
20582083
});
2059-
}
20602084

2061-
if (!SolverBasedProducedResult) {
2062-
resolveCursor(*this, InputBufferName, Offset, Length, Actionables,
2063-
SymbolGraph, Invok, /*TryExistingAST=*/true,
2064-
CancelOnSubsequentRequest, fileSystem, CancellationToken,
2065-
Receiver);
2066-
}
2085+
// If the solver based cursor info produced no results, fallback to the
2086+
// original AST based.
2087+
if (!SolverProducedResults) {
2088+
Receiver(Res);
2089+
}
2090+
};
2091+
2092+
resolveCursor(*this, InputBufferName, Offset, Length, Actionables,
2093+
SymbolGraph, Invok, /*TryExistingAST=*/true,
2094+
CancelOnSubsequentRequest, fileSystem, CancellationToken,
2095+
ASTBasedReceiver);
20672096
}
20682097

20692098
void SwiftLangSupport::getDiagnostics(

0 commit comments

Comments
 (0)