mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #38049 from ahoppen/pr/keypath-completion
[CodeCompletion] Migrate key path completion to be solver based
This commit is contained in:
@@ -6747,6 +6747,28 @@ void deliverUnresolvedMemberResults(
|
||||
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
|
||||
}
|
||||
|
||||
void deliverKeyPathResults(
|
||||
ArrayRef<KeyPathTypeCheckCompletionCallback::Result> Results,
|
||||
DeclContext *DC, SourceLoc DotLoc,
|
||||
ide::CodeCompletionContext &CompletionCtx,
|
||||
CodeCompletionConsumer &Consumer) {
|
||||
ASTContext &Ctx = DC->getASTContext();
|
||||
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
|
||||
&CompletionCtx);
|
||||
|
||||
if (DotLoc.isValid()) {
|
||||
Lookup.setHaveDot(DotLoc);
|
||||
}
|
||||
Lookup.shouldCheckForDuplicates(Results.size() > 1);
|
||||
|
||||
for (auto &Result : Results) {
|
||||
Lookup.setIsSwiftKeyPathExpr(Result.OnRoot);
|
||||
Lookup.getValueExprCompletions(Result.BaseType);
|
||||
}
|
||||
|
||||
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
|
||||
}
|
||||
|
||||
void deliverDotExprResults(
|
||||
ArrayRef<DotExprTypeCheckCompletionCallback::Result> Results,
|
||||
Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
|
||||
@@ -6838,6 +6860,21 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
|
||||
CompletionContext, Consumer);
|
||||
return true;
|
||||
}
|
||||
case CompletionKind::KeyPathExprSwift: {
|
||||
assert(CurDeclContext);
|
||||
|
||||
// CodeCompletionCallbacks::completeExprKeyPath takes a \c KeyPathExpr,
|
||||
// so we can safely cast the \c ParsedExpr back to a \c KeyPathExpr.
|
||||
auto KeyPath = cast<KeyPathExpr>(ParsedExpr);
|
||||
KeyPathTypeCheckCompletionCallback Lookup(KeyPath);
|
||||
llvm::SaveAndRestore<TypeCheckCompletionCallback *> CompletionCollector(
|
||||
Context.CompletionCallback, &Lookup);
|
||||
typeCheckContextAt(CurDeclContext, CompletionLoc);
|
||||
|
||||
deliverKeyPathResults(Lookup.getResults(), CurDeclContext, DotLoc,
|
||||
CompletionContext, Consumer);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -6958,60 +6995,10 @@ void CodeCompletionCallbacksImpl::doneParsing() {
|
||||
case CompletionKind::None:
|
||||
case CompletionKind::DotExpr:
|
||||
case CompletionKind::UnresolvedMember:
|
||||
case CompletionKind::KeyPathExprSwift:
|
||||
llvm_unreachable("should be already handled");
|
||||
return;
|
||||
|
||||
case CompletionKind::KeyPathExprSwift: {
|
||||
auto KPE = dyn_cast<KeyPathExpr>(ParsedExpr);
|
||||
auto BGT = (*ExprType)->getAs<BoundGenericType>();
|
||||
if (!KPE || !BGT || BGT->getGenericArgs().size() != 2)
|
||||
break;
|
||||
assert(!KPE->isObjC());
|
||||
|
||||
if (DotLoc.isValid())
|
||||
Lookup.setHaveDot(DotLoc);
|
||||
|
||||
bool OnRoot = !KPE->getComponents().front().isValid();
|
||||
Lookup.setIsSwiftKeyPathExpr(OnRoot);
|
||||
|
||||
Type baseType = BGT->getGenericArgs()[OnRoot ? 0 : 1];
|
||||
if (OnRoot && baseType->is<UnresolvedType>()) {
|
||||
// Infer the root type of the keypath from the context type.
|
||||
ExprContextInfo ContextInfo(CurDeclContext, ParsedExpr);
|
||||
for (auto T : ContextInfo.getPossibleTypes()) {
|
||||
if (auto unwrapped = T->getOptionalObjectType())
|
||||
T = unwrapped;
|
||||
|
||||
// If the context type is any of the KeyPath types, use it.
|
||||
if (T->getAnyNominal() && T->getAnyNominal()->getKeyPathTypeKind() &&
|
||||
!T->hasUnresolvedType() && T->is<BoundGenericType>()) {
|
||||
baseType = T->castTo<BoundGenericType>()->getGenericArgs()[0];
|
||||
break;
|
||||
}
|
||||
|
||||
// KeyPath can be used as a function that receives its root type.
|
||||
if (T->is<AnyFunctionType>()) {
|
||||
auto *fnType = T->castTo<AnyFunctionType>();
|
||||
if (fnType->getNumParams() == 1) {
|
||||
const AnyFunctionType::Param ¶m = fnType->getParams()[0];
|
||||
baseType = param.getParameterType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!OnRoot && KPE->getComponents().back().getKind() ==
|
||||
KeyPathExpr::Component::Kind::OptionalWrap) {
|
||||
// KeyPath expr with '?' (e.g. '\Ty.[0].prop?.another').
|
||||
// Although expected type is optional, we should unwrap it because it's
|
||||
// unwrapped.
|
||||
baseType = baseType->getOptionalObjectType();
|
||||
}
|
||||
|
||||
Lookup.getValueExprCompletions(baseType);
|
||||
break;
|
||||
}
|
||||
|
||||
case CompletionKind::StmtOrExpr:
|
||||
case CompletionKind::ForEachSequence:
|
||||
case CompletionKind::PostfixExprBeginning: {
|
||||
|
||||
Reference in New Issue
Block a user