[code-completion] Disable diagnostics in @functionBuilder bodies

When performing code-completion inside the body of a @functionBuilder
closure/function, set the flag to suppress diagnostics. This works
around a big performance problem in some complex bodies that do not
typecheck, which is typical during code-completion. A real-world example
with SwitfUI went from ~50 seconds to 0.5. We do not disable diagnostics
in general because the diagnostic paths provide falback types that are
useful to code-completion.

rdar://52356229
This commit is contained in:
Ben Langmuir
2019-07-02 07:31:53 -07:00
parent 7211a51dc3
commit c6eade1c44
2 changed files with 19 additions and 0 deletions

View File

@@ -103,6 +103,13 @@ public:
rangeContainsTokenLoc(Enclosing, Inner.End);
}
/// Returns true if range \p R contains the code-completion location, if any.
bool rangeContainsCodeCompletionLoc(SourceRange R) const {
return CodeCompletionBufferID
? rangeContainsTokenLoc(R, getCodeCompletionLoc())
: false;
}
/// Returns the buffer ID for the specified *valid* location.
///
/// Because a valid source location always corresponds to a source buffer,

View File

@@ -496,6 +496,12 @@ bool TypeChecker::typeCheckFunctionBuilderFuncBody(FuncDecl *FD,
options |= TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType;
}
// If we are performing code-completion inside the functions body, supress
// diagnostics to workaround typechecking performance problems.
if (Context.SourceMgr.rangeContainsCodeCompletionLoc(
FD->getBody()->getSourceRange()))
options |= TypeCheckExprFlags::SuppressDiagnostics;
// Type-check the single result expression.
Type returnExprType = typeCheckExpression(returnExpr, FD,
TypeLoc::withoutLoc(returnType),
@@ -574,6 +580,12 @@ ConstraintSystem::TypeMatchResult ConstraintSystem::applyFunctionBuilder(
assert(!builderType->hasTypeParameter());
}
// If we are performing code-completion inside the closure body, supress
// diagnostics to workaround typechecking performance problems.
if (getASTContext().SourceMgr.rangeContainsCodeCompletionLoc(
closure->getSourceRange()))
Options |= ConstraintSystemFlags::SuppressDiagnostics;
BuilderClosureVisitor visitor(getASTContext(), this,
/*wantExpr=*/true, builderType);
Expr *singleExpr = visitor.visit(closure->getBody());