Skip to content

Commit 146d8bc

Browse files
committed
[CodeCompletion] Migrate conforming methods list to solver-based
1 parent 1ee1fbf commit 146d8bc

File tree

2 files changed

+47
-17
lines changed

2 files changed

+47
-17
lines changed

lib/IDE/ConformingMethodList.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/GenericEnvironment.h"
1717
#include "swift/AST/NameLookup.h"
1818
#include "swift/AST/USRGeneration.h"
19+
#include "swift/IDE/TypeCheckCompletionCallback.h"
1920
#include "swift/Parse/CodeCompletionCallbacks.h"
2021
#include "swift/Sema/IDETypeChecking.h"
2122
#include "clang/AST/Attr.h"
@@ -29,7 +30,7 @@ class ConformingMethodListCallbacks : public CodeCompletionCallbacks {
2930
ArrayRef<const char *> ExpectedTypeNames;
3031
ConformingMethodListConsumer &Consumer;
3132
SourceLoc Loc;
32-
Expr *ParsedExpr = nullptr;
33+
CodeCompletionExpr *CCExpr = nullptr;
3334
DeclContext *CurDeclContext = nullptr;
3435

3536
void getMatchingMethods(Type T,
@@ -55,34 +56,46 @@ class ConformingMethodListCallbacks : public CodeCompletionCallbacks {
5556
void ConformingMethodListCallbacks::completeDotExpr(CodeCompletionExpr *E,
5657
SourceLoc DotLoc) {
5758
CurDeclContext = P.CurDeclContext;
58-
ParsedExpr = E->getBase();
59+
CCExpr = E;
5960
}
6061

6162
void ConformingMethodListCallbacks::completePostfixExpr(CodeCompletionExpr *E,
6263
bool hasSpace) {
6364
CurDeclContext = P.CurDeclContext;
64-
ParsedExpr = E->getBase();
65+
CCExpr = E;
6566
}
6667

68+
class ConformingMethodListCallback : public TypeCheckCompletionCallback {
69+
CodeCompletionExpr *CCExpr;
70+
SmallVector<Type, 2> Types;
71+
72+
void sawSolutionImpl(const constraints::Solution &S) override {
73+
if (Type T = getTypeForCompletion(S, CCExpr->getBase())) {
74+
Types.push_back(T);
75+
}
76+
}
77+
78+
public:
79+
ConformingMethodListCallback(CodeCompletionExpr *CCExpr) : CCExpr(CCExpr) {}
80+
81+
ArrayRef<Type> getTypes() const { return Types; }
82+
};
83+
6784
void ConformingMethodListCallbacks::doneParsing() {
68-
if (!ParsedExpr)
85+
if (!CCExpr || !CCExpr->getBase())
6986
return;
7087

88+
ConformingMethodListCallback TypeCheckCallback(CCExpr);
89+
llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector(
90+
Context.CompletionCallback, &TypeCheckCallback);
7191
typeCheckContextAt(TypeCheckASTNodeAtLocContext::declContext(CurDeclContext),
72-
ParsedExpr->getLoc());
73-
74-
Type T = ParsedExpr->getType();
75-
76-
// Type check the expression if needed.
77-
if (!T || T->is<ErrorType>()) {
78-
ConcreteDeclRef ReferencedDecl = nullptr;
79-
auto optT = getTypeOfCompletionContextExpr(P.Context, CurDeclContext,
80-
CompletionTypeCheckKind::Normal,
81-
ParsedExpr, ReferencedDecl);
82-
if (!optT)
83-
return;
84-
T = *optT;
92+
CCExpr->getLoc());
93+
94+
if (TypeCheckCallback.getTypes().size() != 1) {
95+
// Either no results or results were ambiguous, which we cannot handle.
96+
return;
8597
}
98+
Type T = TypeCheckCallback.getTypes()[0];
8699

87100
if (!T || T->is<ErrorType>() || T->is<UnresolvedType>())
88101
return;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-ide-test -conforming-methods -source-filename %s -code-completion-token COMPLETE
2+
3+
// This test used to crash while PostfixExpr completion was migrated to solver-based.
4+
5+
struct MyPublisher {
6+
func removeDuplicates() {}
7+
}
8+
9+
func handleEvents(receiveOutput: ((String) -> Void)? = nil) -> MyPublisher {}
10+
11+
protocol AnyCancellable {}
12+
13+
class CategoriesSearchViewModel {
14+
func foo() {
15+
var searchCancellable: AnyCancellable = handleEvents(receiveOutput: { [weak self] _ in }).removeDuplicates #^COMPLETE^#
16+
}
17+
}

0 commit comments

Comments
 (0)