mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[code-completion] Add type context for single-expression closures
When completing in the only expression of closure, use the return type of the closure as the type context for the code-completion. However, since code-completion may be on an incomplete input, we only use the return type to improve the quality of the result, not to mark it invalid, since (a) we may add another statement afterwards, or (b) if the context type is Void it doesn't need to match the value.
This commit is contained in:
@@ -510,6 +510,7 @@ class ExprContextAnalyzer {
|
||||
SmallVectorImpl<Type> &PossibleTypes;
|
||||
SmallVectorImpl<StringRef> &PossibleNames;
|
||||
SmallVectorImpl<FunctionTypeAndDecl> &PossibleCallees;
|
||||
bool &singleExpressionBody;
|
||||
|
||||
void recordPossibleType(Type ty) {
|
||||
if (!ty || ty->is<ErrorType>())
|
||||
@@ -616,6 +617,13 @@ class ExprContextAnalyzer {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExprKind::Closure: {
|
||||
auto *CE = cast<ClosureExpr>(Parent);
|
||||
assert(isSingleExpressionBodyForCodeCompletion(CE->getBody()));
|
||||
singleExpressionBody = true;
|
||||
recordPossibleType(getReturnTypeFromContext(CE));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("Unhandled expression kind.");
|
||||
}
|
||||
@@ -705,14 +713,28 @@ class ExprContextAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
static bool isSingleExpressionBodyForCodeCompletion(BraceStmt *body) {
|
||||
switch (body->getNumElements()) {
|
||||
case 0:
|
||||
// Nothing in the body except the code-completion token.
|
||||
return true;
|
||||
case 1:
|
||||
return body->getElements()[0].is<Expr *>();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
ExprContextAnalyzer(DeclContext *DC, Expr *ParsedExpr,
|
||||
SmallVectorImpl<Type> &PossibleTypes,
|
||||
SmallVectorImpl<StringRef> &PossibleNames,
|
||||
SmallVectorImpl<FunctionTypeAndDecl> &PossibleCallees)
|
||||
SmallVectorImpl<FunctionTypeAndDecl> &PossibleCallees,
|
||||
bool &singleExpressionBody)
|
||||
: DC(DC), ParsedExpr(ParsedExpr), SM(DC->getASTContext().SourceMgr),
|
||||
Context(DC->getASTContext()), PossibleTypes(PossibleTypes),
|
||||
PossibleNames(PossibleNames), PossibleCallees(PossibleCallees) {}
|
||||
PossibleNames(PossibleNames), PossibleCallees(PossibleCallees),
|
||||
singleExpressionBody(singleExpressionBody) {}
|
||||
|
||||
void Analyze() {
|
||||
// We cannot analyze without target.
|
||||
@@ -735,6 +757,15 @@ public:
|
||||
(!isa<CallExpr>(ParentE) && !isa<SubscriptExpr>(ParentE) &&
|
||||
!isa<BinaryExpr>(ParentE) && !isa<TupleShuffleExpr>(ParentE));
|
||||
}
|
||||
case ExprKind::Closure: {
|
||||
// Note: we cannot use hasSingleExpressionBody, because we explicitly
|
||||
// do not use the single-expression-body when there is code-completion
|
||||
// in the expression in order to avoid a base expression affecting
|
||||
// the type. However, now that we've typechecked, we will take the
|
||||
// context type into account.
|
||||
return isSingleExpressionBodyForCodeCompletion(
|
||||
cast<ClosureExpr>(E)->getBody());
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -793,6 +824,6 @@ public:
|
||||
|
||||
ExprContextInfo::ExprContextInfo(DeclContext *DC, Expr *TargetExpr) {
|
||||
ExprContextAnalyzer Analyzer(DC, TargetExpr, PossibleTypes, PossibleNames,
|
||||
PossibleCallees);
|
||||
PossibleCallees, singleExpressionBody);
|
||||
Analyzer.Analyze();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user