Skip to content

Commit 72cadec

Browse files
committed
[CodeCompletion] Split result delivery into a result colleciton and consumer phase
This will allow us to run two different completion kinds and deliver results from both of them. Also: Compute a unified type context for global lookup. Previously, we always used the expected type context of the last lookup. But really, we should be considering all possible types from all constraint system solutions when computing code completion results from the cache.
1 parent 2d171bd commit 72cadec

22 files changed

+261
-242
lines changed

include/swift/IDE/AfterPoundExprCompletion.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ class AfterPoundExprCompletion : public TypeCheckCompletionCallback {
4747
: CompletionExpr(CompletionExpr), DC(DC), ParentStmtKind(ParentStmtKind) {
4848
}
4949

50-
void deliverResults(ide::CodeCompletionContext &CompletionCtx,
51-
CodeCompletionConsumer &Consumer);
50+
void collectResults(ide::CodeCompletionContext &CompletionCtx);
5251
};
5352

5453
} // end namespace ide

include/swift/IDE/ArgumentCompletion.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,8 @@ class ArgumentTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
9393
/// function signature instead of suggesting individual labels. Used when
9494
/// completing after the opening '(' of a function call \param Loc The
9595
/// location of the code completion token
96-
void deliverResults(bool IncludeSignature, SourceLoc Loc, DeclContext *DC,
97-
CodeCompletionContext &CompletionCtx,
98-
CodeCompletionConsumer &Consumer);
96+
void collectResults(bool IncludeSignature, SourceLoc Loc, DeclContext *DC,
97+
CodeCompletionContext &CompletionCtx);
9998
};
10099

101100
} // end namespace ide

include/swift/IDE/CodeCompletion.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ void postProcessCompletionResults(
6565
MutableArrayRef<CodeCompletionResult *> results, CompletionKind Kind,
6666
const DeclContext *DC, CodeCompletionResultSink *Sink);
6767

68-
void deliverCompletionResults(CodeCompletionContext &CompletionContext,
68+
void collectCompletionResults(CodeCompletionContext &CompletionContext,
6969
CompletionLookup &Lookup, DeclContext *DC,
70-
CodeCompletionConsumer &Consumer);
70+
const ExpectedTypeContext &TypeContext,
71+
bool CanCurrDeclContextHandleAsync);
7172

7273
/// Create a factory for code completion callbacks.
7374
IDEInspectionCallbacksFactory *

include/swift/IDE/CodeCompletionConsumer.h

-21
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,9 @@ namespace ide {
2222
struct RequestedCachedModule;
2323

2424
/// An abstract base class for consumers of code completion results.
25-
/// \see \c SimpleCachingCodeCompletionConsumer.
2625
class CodeCompletionConsumer {
2726
public:
2827
virtual ~CodeCompletionConsumer() {}
29-
virtual void
30-
handleResultsAndModules(CodeCompletionContext &context,
31-
ArrayRef<RequestedCachedModule> requestedModules,
32-
const ExpectedTypeContext *TypeContext,
33-
const DeclContext *DC,
34-
bool CanCurrDeclContextHandleAsync) = 0;
35-
};
36-
37-
/// A simplified code completion consumer interface that clients can use to get
38-
/// CodeCompletionResults with automatic caching of top-level completions from
39-
/// imported modules.
40-
struct SimpleCachingCodeCompletionConsumer : public CodeCompletionConsumer {
41-
42-
// Implement the CodeCompletionConsumer interface.
43-
void handleResultsAndModules(CodeCompletionContext &context,
44-
ArrayRef<RequestedCachedModule> requestedModules,
45-
const ExpectedTypeContext *TypeContext,
46-
const DeclContext *DCForModules,
47-
bool CanCurrDeclContextHandleAsync) override;
48-
4928
/// Clients should override this method to receive \p Results.
5029
virtual void handleResults(CodeCompletionContext &context) = 0;
5130
};

include/swift/IDE/CodeCompletionContext.h

+8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace swift {
2020
namespace ide {
2121

2222
class CodeCompletionCache;
23+
struct RequestedCachedModule;
2324

2425
class CodeCompletionContext {
2526
friend class CodeCompletionResultBuilder;
@@ -103,6 +104,13 @@ class CodeCompletionContext {
103104
sortCompletionResults(ArrayRef<CodeCompletionResult *> Results);
104105

105106
CodeCompletionResultSink &getResultSink() { return CurrentResults; }
107+
108+
/// Add code completion results from the given requested modules to this
109+
/// context.
110+
void addResultsFromModules(ArrayRef<RequestedCachedModule> RequestedModules,
111+
const ExpectedTypeContext &TypeContext,
112+
const DeclContext *DC,
113+
bool CanCurrDeclContextHandleAsync);
106114
};
107115

108116
} // end namespace ide

include/swift/IDE/CodeCompletionResultType.h

+20
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,26 @@ class ExpectedTypeContext {
7474
}
7575
}
7676

77+
/// Form a union of this expected type context with \p Other.
78+
///
79+
/// Any possible type from either type context will be considered a possible
80+
/// type in the merged type context.
81+
void merge(const ExpectedTypeContext &Other) {
82+
PossibleTypes.append(Other.PossibleTypes);
83+
84+
// We can't merge ideal types. Setting to a null type is the best thing we
85+
// can do if they differ.
86+
if (IdealType.isNull() != Other.IdealType.isNull()) {
87+
IdealType = Type();
88+
} else if (IdealType && Other.IdealType &&
89+
!IdealType->isEqual(Other.IdealType)) {
90+
IdealType = Type();
91+
}
92+
IsImplicitSingleExpressionReturn |= Other.IsImplicitSingleExpressionReturn;
93+
PreferNonVoid &= Other.PreferNonVoid;
94+
ExpectedCustomAttributeKinds |= Other.ExpectedCustomAttributeKinds;
95+
}
96+
7797
Type getIdealType() const { return IdealType; }
7898

7999
void setIdealType(Type IdealType) { this->IdealType = IdealType; }

include/swift/IDE/ExprCompletion.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,8 @@ class ExprTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
9090
AddUnresolvedMemberCompletions(AddUnresolvedMemberCompletions) {}
9191

9292
/// \param CCLoc The location of the code completion token.
93-
void deliverResults(SourceLoc CCLoc,
94-
ide::CodeCompletionContext &CompletionCtx,
95-
CodeCompletionConsumer &Consumer);
93+
void collectResults(SourceLoc CCLoc,
94+
ide::CodeCompletionContext &CompletionCtx);
9695
};
9796

9897
} // end namespace ide

include/swift/IDE/KeyPathCompletion.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ class KeyPathTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
3737
public:
3838
KeyPathTypeCheckCompletionCallback(KeyPathExpr *KeyPath) : KeyPath(KeyPath) {}
3939

40-
void deliverResults(DeclContext *DC, SourceLoc DotLoc,
41-
ide::CodeCompletionContext &CompletionCtx,
42-
CodeCompletionConsumer &Consumer);
40+
void collectResults(DeclContext *DC, SourceLoc DotLoc,
41+
ide::CodeCompletionContext &CompletionCtx);
4342
};
4443

4544
} // end namespace ide

include/swift/IDE/PostfixCompletion.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,9 @@ class PostfixCompletionCallback : public TypeCheckCompletionCallback {
103103
/// \p DotLoc is invalid
104104
/// \param HasLeadingSpace Whether there is a space separating the exiting
105105
/// expression and the code completion token.
106-
void deliverResults(SourceLoc DotLoc, bool IsInSelector,
106+
void collectResults(SourceLoc DotLoc, bool IsInSelector,
107107
bool IncludeOperators, bool HasLeadingSpace,
108-
CodeCompletionContext &CompletionCtx,
109-
CodeCompletionConsumer &Consumer);
108+
CodeCompletionContext &CompletionCtx);
110109
};
111110

112111
} // end namespace ide

include/swift/IDE/UnresolvedMemberCompletion.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,8 @@ class UnresolvedMemberTypeCheckCompletionCallback
5959
CodeCompletionExpr *CompletionExpr, DeclContext *DC)
6060
: CompletionExpr(CompletionExpr), DC(DC) {}
6161

62-
void deliverResults(DeclContext *DC, SourceLoc DotLoc,
63-
ide::CodeCompletionContext &CompletionCtx,
64-
CodeCompletionConsumer &Consumer);
62+
void collectResults(DeclContext *DC, SourceLoc DotLoc,
63+
ide::CodeCompletionContext &CompletionCtx);
6564
};
6665

6766
} // end namespace ide

lib/IDE/AfterPoundExprCompletion.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,29 @@ void AfterPoundExprCompletion::sawSolutionImpl(const constraints::Solution &S) {
3737
}
3838
}
3939

40-
void AfterPoundExprCompletion::deliverResults(
41-
ide::CodeCompletionContext &CompletionCtx,
42-
CodeCompletionConsumer &Consumer) {
40+
void AfterPoundExprCompletion::collectResults(
41+
ide::CodeCompletionContext &CompletionCtx) {
4342
ASTContext &Ctx = DC->getASTContext();
4443
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
4544
&CompletionCtx);
4645

4746
Lookup.shouldCheckForDuplicates(Results.size() > 1);
4847

48+
// The type context that is being used for global results.
49+
ExpectedTypeContext UnifiedTypeContext;
50+
UnifiedTypeContext.setPreferNonVoid(true);
51+
4952
for (auto &Result : Results) {
5053
Lookup.setExpectedTypes({Result.ExpectedTy},
5154
Result.IsImplicitSingleExpressionReturn,
5255
/*expectsNonVoid=*/true);
5356
Lookup.addPoundAvailable(ParentStmtKind);
5457
Lookup.addObjCPoundKeywordCompletions(/*needPound=*/false);
5558
Lookup.getMacroCompletions(CodeCompletionMacroRole::Expression);
59+
60+
UnifiedTypeContext.merge(*Lookup.getExpectedTypeContext());
5661
}
5762

58-
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
63+
collectCompletionResults(CompletionCtx, Lookup, DC, UnifiedTypeContext,
64+
/*CanCurrDeclContextHandleAsync=*/false);
5965
}

lib/IDE/ArgumentCompletion.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,9 @@ void ArgumentTypeCheckCompletionCallback::computeShadowedDecls(
295295
}
296296
}
297297

298-
void ArgumentTypeCheckCompletionCallback::deliverResults(
298+
void ArgumentTypeCheckCompletionCallback::collectResults(
299299
bool IncludeSignature, SourceLoc Loc, DeclContext *DC,
300-
ide::CodeCompletionContext &CompletionCtx,
301-
CodeCompletionConsumer &Consumer) {
300+
ide::CodeCompletionContext &CompletionCtx) {
302301
ASTContext &Ctx = DC->getASTContext();
303302
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
304303
&CompletionCtx);
@@ -402,5 +401,7 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
402401
addExprKeywords(CompletionCtx.getResultSink(), DC);
403402
}
404403

405-
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
404+
collectCompletionResults(CompletionCtx, Lookup, DC,
405+
*Lookup.getExpectedTypeContext(),
406+
Lookup.canCurrDeclContextHandleAsync());
406407
}

lib/IDE/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ add_swift_host_library(swiftIDE STATIC
55
ArgumentCompletion.cpp
66
CodeCompletion.cpp
77
CodeCompletionCache.cpp
8-
CodeCompletionConsumer.cpp
98
CodeCompletionContext.cpp
109
CodeCompletionDiagnostics.cpp
1110
CodeCompletionResult.cpp

lib/IDE/CodeCompletion.cpp

+23-14
Original file line numberDiff line numberDiff line change
@@ -1298,9 +1298,10 @@ void swift::ide::postProcessCompletionResults(
12981298
}
12991299
}
13001300

1301-
void swift::ide::deliverCompletionResults(
1301+
void swift::ide::collectCompletionResults(
13021302
CodeCompletionContext &CompletionContext, CompletionLookup &Lookup,
1303-
DeclContext *DC, CodeCompletionConsumer &Consumer) {
1303+
DeclContext *DC, const ExpectedTypeContext &TypeContext,
1304+
bool CanCurrDeclContextHandleAsync) {
13041305
auto &SF = *DC->getParentSourceFile();
13051306
llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
13061307
std::vector<RequestedCachedModule> RequestedModules;
@@ -1420,9 +1421,8 @@ void swift::ide::deliverCompletionResults(
14201421
CompletionContext.CodeCompletionKind, DC,
14211422
/*Sink=*/nullptr);
14221423

1423-
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
1424-
Lookup.getExpectedTypeContext(), DC,
1425-
Lookup.canCurrDeclContextHandleAsync());
1424+
CompletionContext.addResultsFromModules(RequestedModules, TypeContext, DC,
1425+
CanCurrDeclContextHandleAsync);
14261426
}
14271427

14281428
bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
@@ -1489,8 +1489,9 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
14891489

14901490
bool IncludeOperators = (Kind == CompletionKind::PostfixExpr);
14911491

1492-
Lookup.deliverResults(DotLoc, isInsideObjCSelector(), IncludeOperators,
1493-
HasSpace, CompletionContext, Consumer);
1492+
Lookup.collectResults(DotLoc, isInsideObjCSelector(), IncludeOperators,
1493+
HasSpace, CompletionContext);
1494+
Consumer.handleResults(CompletionContext);
14941495
return true;
14951496
}
14961497
case CompletionKind::UnresolvedMember: {
@@ -1502,7 +1503,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
15021503
typeCheckWithLookup(Lookup);
15031504

15041505
addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
1505-
Lookup.deliverResults(CurDeclContext, DotLoc, CompletionContext, Consumer);
1506+
Lookup.collectResults(CurDeclContext, DotLoc, CompletionContext);
1507+
Consumer.handleResults(CompletionContext);
15061508
return true;
15071509
}
15081510
case CompletionKind::KeyPathExprSwift: {
@@ -1514,7 +1516,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
15141516
KeyPathTypeCheckCompletionCallback Lookup(KeyPath);
15151517
typeCheckWithLookup(Lookup);
15161518

1517-
Lookup.deliverResults(CurDeclContext, DotLoc, CompletionContext, Consumer);
1519+
Lookup.collectResults(CurDeclContext, DotLoc, CompletionContext);
1520+
Consumer.handleResults(CompletionContext);
15181521
return true;
15191522
}
15201523
case CompletionKind::PostfixExprParen:
@@ -1525,8 +1528,9 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
15251528
CurDeclContext);
15261529
typeCheckWithLookup(Lookup);
15271530

1528-
Lookup.deliverResults(ShouldCompleteCallPatternAfterParen, CompletionLoc,
1529-
CurDeclContext, CompletionContext, Consumer);
1531+
Lookup.collectResults(ShouldCompleteCallPatternAfterParen, CompletionLoc,
1532+
CurDeclContext, CompletionContext);
1533+
Consumer.handleResults(CompletionContext);
15301534
return true;
15311535
}
15321536
case CompletionKind::AccessorBeginning:
@@ -1556,7 +1560,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
15561560
addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
15571561

15581562
SourceLoc CCLoc = P.Context.SourceMgr.getIDEInspectionTargetLoc();
1559-
Lookup.deliverResults(CCLoc, CompletionContext, Consumer);
1563+
Lookup.collectResults(CCLoc, CompletionContext);
1564+
Consumer.handleResults(CompletionContext);
15601565
return true;
15611566
}
15621567
case CompletionKind::AfterPoundExpr: {
@@ -1569,7 +1574,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
15691574

15701575
addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
15711576

1572-
Lookup.deliverResults(CompletionContext, Consumer);
1577+
Lookup.collectResults(CompletionContext);
1578+
Consumer.handleResults(CompletionContext);
15731579
return true;
15741580
}
15751581
default:
@@ -2041,7 +2047,10 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
20412047
break;
20422048
}
20432049

2044-
deliverCompletionResults(CompletionContext, Lookup, CurDeclContext, Consumer);
2050+
collectCompletionResults(CompletionContext, Lookup, CurDeclContext,
2051+
*Lookup.getExpectedTypeContext(),
2052+
Lookup.canCurrDeclContextHandleAsync());
2053+
Consumer.handleResults(CompletionContext);
20452054
}
20462055

20472056
namespace {

0 commit comments

Comments
 (0)