[CodeCompletion][Sema] Migrate CallArgurment position completion to the solver-based implementation

This hooks up call argument position completion to the typeCheckForCodeCompletion API to generate completions from all the solutions the constraint solver produces (even those requiring fixes), rather than relying on a single solution being applied to the AST (if any).

Co-authored-by: Nathan Hawes <nathan.john.hawes@gmail.com>
This commit is contained in:
Alex Hoppen
2022-03-17 09:06:47 +01:00
parent ca9056a275
commit f538d33e5f
29 changed files with 1535 additions and 184 deletions

View File

@@ -32,6 +32,7 @@
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Frontend/FrontendOptions.h"
#include "swift/IDE/ArgumentCompletion.h"
#include "swift/IDE/CodeCompletionCache.h"
#include "swift/IDE/CodeCompletionConsumer.h"
#include "swift/IDE/CodeCompletionResultPrinter.h"
@@ -830,7 +831,8 @@ static void addObserverKeywords(CodeCompletionResultSink &Sink) {
addKeyword(Sink, "didSet", CodeCompletionKeywordKind::None);
}
static void addExprKeywords(CodeCompletionResultSink &Sink, DeclContext *DC) {
void swift::ide::addExprKeywords(CodeCompletionResultSink &Sink,
DeclContext *DC) {
// Expression is invalid at top-level of non-script files.
CodeCompletionFlair flair;
if (isCodeCompletionAtTopLevelOfLibraryFile(DC)) {
@@ -844,7 +846,8 @@ static void addExprKeywords(CodeCompletionResultSink &Sink, DeclContext *DC) {
addKeyword(Sink, "await", CodeCompletionKeywordKind::None, "", flair);
}
static void addSuperKeyword(CodeCompletionResultSink &Sink, DeclContext *DC) {
void swift::ide::addSuperKeyword(CodeCompletionResultSink &Sink,
DeclContext *DC) {
if (!DC)
return;
auto *TC = DC->getInnermostTypeContext();
@@ -1373,6 +1376,22 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
Lookup.deliverResults(CurDeclContext, DotLoc, CompletionContext, Consumer);
return true;
}
case CompletionKind::CallArg: {
assert(CodeCompleteTokenExpr);
assert(CurDeclContext);
ArgumentTypeCheckCompletionCallback Lookup(CodeCompleteTokenExpr);
llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector(
Context.CompletionCallback, &Lookup);
typeCheckContextAt(CurDeclContext, CompletionLoc);
if (!Lookup.gotCallback()) {
Lookup.fallbackTypeCheck(CurDeclContext);
}
Lookup.deliverResults(ShouldCompleteCallPatternAfterParen, CompletionLoc,
CurDeclContext, CompletionContext, Consumer);
return true;
}
default:
return false;
}
@@ -1494,6 +1513,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
case CompletionKind::DotExpr:
case CompletionKind::UnresolvedMember:
case CompletionKind::KeyPathExprSwift:
case CompletionKind::CallArg:
llvm_unreachable("should be already handled");
return;
@@ -1657,58 +1677,6 @@ void CodeCompletionCallbacksImpl::doneParsing() {
Lookup.addImportModuleNames();
break;
}
case CompletionKind::CallArg: {
ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
bool shouldPerformGlobalCompletion = true;
if (ShouldCompleteCallPatternAfterParen &&
!ContextInfo.getPossibleCallees().empty()) {
Lookup.setHaveLParen(true);
for (auto &typeAndDecl : ContextInfo.getPossibleCallees()) {
auto apply = ContextInfo.getAnalyzedExpr();
if (isa_and_nonnull<SubscriptExpr>(apply)) {
Lookup.addSubscriptCallPattern(
typeAndDecl.Type,
dyn_cast_or_null<SubscriptDecl>(typeAndDecl.Decl),
typeAndDecl.SemanticContext);
} else {
Lookup.addFunctionCallPattern(
typeAndDecl.Type,
dyn_cast_or_null<AbstractFunctionDecl>(typeAndDecl.Decl),
typeAndDecl.SemanticContext);
}
}
Lookup.setHaveLParen(false);
shouldPerformGlobalCompletion =
!Lookup.FoundFunctionCalls ||
(Lookup.FoundFunctionCalls &&
Lookup.FoundFunctionsWithoutFirstKeyword);
} else if (!ContextInfo.getPossibleParams().empty()) {
auto params = ContextInfo.getPossibleParams();
Lookup.addCallArgumentCompletionResults(params);
shouldPerformGlobalCompletion = !ContextInfo.getPossibleTypes().empty();
// Fallback to global completion if the position is out of number. It's
// better than suggest nothing.
shouldPerformGlobalCompletion |= llvm::all_of(
params, [](const PossibleParamInfo &P) { return !P.Param; });
}
if (shouldPerformGlobalCompletion) {
Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
ContextInfo.isImplicitSingleExpressionReturn());
// Add any keywords that can be used in an argument expr position.
addSuperKeyword(CompletionContext.getResultSink(), CurDeclContext);
addExprKeywords(CompletionContext.getResultSink(), CurDeclContext);
DoPostfixExprBeginning();
}
break;
}
case CompletionKind::LabeledTrailingClosure: {
ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);