Skip to content

Commit 1903497

Browse files
committed
[IDE] Report ambiguous cursor info results
1 parent 4584c59 commit 1903497

File tree

5 files changed

+55
-10
lines changed

5 files changed

+55
-10
lines changed

lib/IDE/CursorInfo.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ class NodeFinder : ASTWalker {
225225
switch (E->getKind()) {
226226
case ExprKind::DeclRef:
227227
case ExprKind::UnresolvedDot:
228-
case ExprKind::UnresolvedDeclRef: {
228+
case ExprKind::UnresolvedDeclRef:
229+
case ExprKind::OverloadedDeclRef: {
229230
assert(Result == nullptr);
230231
Result =
231232
std::make_unique<NodeFinderExprResult>(E, getCurrentDeclContext());
@@ -273,13 +274,33 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
273274
};
274275

275276
private:
276-
/// The expression for which we want to provide cursor info results.
277-
Expr *ResolveExpr;
277+
/// The source file and location to resolve.
278+
/// Note that we cannot store the expression to resolve directly because an
279+
/// \c UnresolvedDeclRefExpr might be replaced by an \c OverloadedDeclRefExpr
280+
/// and thus the constraint system solution doesn't know about the
281+
/// \c UnresolvedDeclRefExpr. Instead, we find the expression to resolve in
282+
/// the source file again after expression pre-check has run.
283+
SourceFile &SrcFile;
284+
SourceLoc ResolveLoc;
278285

279286
SmallVector<CursorInfoDeclReference, 1> Results;
280287

288+
Expr *getExprToResolve() {
289+
NodeFinder Finder(SrcFile, ResolveLoc);
290+
Finder.resolve();
291+
auto Result = Finder.takeResult();
292+
if (!Result || Result->getKind() != NodeFinderResultKind::Expr) {
293+
return nullptr;
294+
}
295+
return cast<NodeFinderExprResult>(Result.get())->getExpr();
296+
}
297+
281298
void sawSolutionImpl(const Solution &S) override {
282299
auto &CS = S.getConstraintSystem();
300+
auto ResolveExpr = getExprToResolve();
301+
if (!ResolveExpr) {
302+
return;
303+
}
283304

284305
auto Locator = CS.getConstraintLocator(ResolveExpr);
285306
auto CalleeLocator = S.getCalleeLocator(Locator);
@@ -303,8 +324,8 @@ class CursorInfoTypeCheckSolutionCallback : public TypeCheckCompletionCallback {
303324
}
304325

305326
public:
306-
CursorInfoTypeCheckSolutionCallback(Expr *ResolveExpr)
307-
: ResolveExpr(ResolveExpr) {}
327+
CursorInfoTypeCheckSolutionCallback(SourceFile &SrcFile, SourceLoc ResolveLoc)
328+
: SrcFile(SrcFile), ResolveLoc(ResolveLoc) {}
308329

309330
ArrayRef<CursorInfoDeclReference> getResults() const { return Results; }
310331
};
@@ -325,7 +346,7 @@ class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
325346
getDeclResult(NodeFinderDeclResult *DeclResult, SourceFile *SrcFile,
326347
NodeFinder &Finder) const {
327348
typeCheckDeclAndParentClosures(DeclResult->getDecl());
328-
return new ResolvedValueRefCursorInfo(
349+
auto CursorInfo = new ResolvedValueRefCursorInfo(
329350
SrcFile, RequestedLoc, DeclResult->getDecl(),
330351
/*CtorTyRef=*/nullptr,
331352
/*ExtTyRef=*/nullptr, /*IsRef=*/false, /*Ty=*/Type(),
@@ -345,7 +366,7 @@ class CursorInfoDoneParsingCallback : public IDEInspectionCallbacks {
345366
DeclContext *DC = ExprResult->getDeclContext();
346367

347368
// Type check the statemnt containing E and listen for solutions.
348-
CursorInfoTypeCheckSolutionCallback Callback(E);
369+
CursorInfoTypeCheckSolutionCallback Callback(*SrcFile, RequestedLoc);
349370
llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector(
350371
DC->getASTContext().SolutionCallback, &Callback);
351372
typeCheckASTNodeAtLoc(TypeCheckASTNodeAtLocContext::declContext(DC),

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,11 @@ TypeChecker::typeCheckTarget(SolutionApplicationTarget &target,
416416
// Construct a constraint system from this expression.
417417
ConstraintSystemOptions csOptions = ConstraintSystemFlags::AllowFixes;
418418

419-
if (DiagnosticSuppression::isEnabled(Context.Diags))
419+
/// If we have a SolutionCallback, we are inspecting constraint system
420+
/// solutions directly and thus also want to receive ambiguous solutions.
421+
/// Hence, don't set SuppressDiagnsostics to salvage the constraint system.
422+
if (DiagnosticSuppression::isEnabled(Context.Diags) &&
423+
!Context.SolutionCallback)
420424
csOptions |= ConstraintSystemFlags::SuppressDiagnostics;
421425

422426
if (options.contains(TypeCheckExprFlags::LeaveClosureBodyUnchecked))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
func testAmbiguousFunctionReference() {
2+
func foo(a: Int) {}
3+
func foo(a: String) {}
4+
5+
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):7 %s -- %s | %FileCheck %s
6+
_ = foo
7+
8+
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):7 %s -- %s | %FileCheck %s
9+
_ = foo(a: UInt(1))
10+
}
11+
12+
// CHECK: source.lang.swift.ref.function.free (2:8-2:19)
13+
// CHECK: <Declaration>func foo(a: <Type usr="s:Si">Int</Type>)</Declaration>
14+
// CHECK: SECONDARY SYMBOLS BEGIN
15+
// CHECK: source.lang.swift.ref.function.free (3:8-3:22)
16+
// CHECK: <Declaration>func foo(a: <Type usr="s:SS">String</Type>)</Declaration>
17+
// CHECK: SECONDARY SYMBOLS END

test/SourceKit/Refactoring/basic.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ func hasCallToAsyncAlternative(c: ConvertAsync) {
170170
// RUN: %sourcekitd-test -req=cursor -pos=117:16 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-GLOBAL
171171
// RUN: %sourcekitd-test -req=cursor -pos=117:17 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-GLOBAL
172172

173-
// RUN: %sourcekitd-test -req=cursor -pos=35:10 -end-pos=35:16 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-RENAME-EXTRACT
173+
// RUN: %sourcekitd-test -req=cursor -pos=35:10 -end-pos=35:16 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-RENAME
174174

175175
// RUN: %sourcekitd-test -req=cursor -pos=54:10 -end-pos=54:22 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-LOCAL
176176
// RUN: %sourcekitd-test -req=cursor -pos=54:12 -end-pos=54:22 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-SELF-RENAME1
@@ -231,6 +231,8 @@ func hasCallToAsyncAlternative(c: ConvertAsync) {
231231
// CHECK-LOCAL-NOT: Global Rename
232232
// CHECK-LOCAL: ACTIONS END
233233

234+
// CHECK-RENAME: Global Rename
235+
234236
// CHECK-RENAME-EXTRACT: Global Rename
235237
// CHECK-RENAME-EXTRACT: Extract Method
236238

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2015,7 +2015,8 @@ void SwiftLangSupport::getCursorInfo(
20152015
std::unique_ptr<llvm::MemoryBuffer> UnresolvedInputFile =
20162016
getASTManager()->getMemoryBuffer(RealInputFilePath, fileSystem,
20172017
InputFileError);
2018-
if (UnresolvedInputFile) {
2018+
// The solver-based implementation doesn't support range based cursor info.
2019+
if (UnresolvedInputFile && Length == 0) {
20192020
auto SolverBasedReceiver = [&](const RequestResult<CursorInfoData> &Res) {
20202021
SolverBasedProducedResult = true;
20212022
Receiver(Res);

0 commit comments

Comments
 (0)