Skip to content

Commit

Permalink
[code-completion] Disable diagnostics in @functionBuilder bodies
Browse files Browse the repository at this point in the history
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
  • Loading branch information
benlangmuir committed Jul 2, 2019
1 parent 7211a51 commit c6eade1
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 0 deletions.
7 changes: 7 additions & 0 deletions include/swift/Basic/SourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ class SourceManager {
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,
Expand Down
12 changes: 12 additions & 0 deletions lib/Sema/BuilderTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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());
Expand Down

0 comments on commit c6eade1

Please sign in to comment.