[TypeChecker] Add a entry point to be used for code completion

As part of the code completion redesign this new entry point is going
to replace use of:

- `typeCheckExpression`
- `getTypeOfExpressionWithoutApplying` (which could be removed)

and possibly other methods currently used to retrieve information
for code completion purposes.

Advantages of a new approach:

- Avoids mutating AST;
- Allows to avoid sub-expression type-checking;
- Allows code completion access to multiple solutions in ambiguous cases;
- Provides all possible solutions - valid and invalid (with holes);
- Allows code completion to easily access not only types but
  overload choices and other supplimentary information associated
  with each solution.
This commit is contained in:
Pavel Yaskevich
2020-06-15 13:55:00 -07:00
parent 2a377bcdaa
commit ccd7167371
4 changed files with 92 additions and 0 deletions

View File

@@ -1375,6 +1375,49 @@ void ConstraintSystem::solveImpl(SmallVectorImpl<Solution> &solutions) {
}
}
void ConstraintSystem::solveForCodeCompletion(
Expr *expr, DeclContext *DC, Type contextualType, ContextualTypePurpose CTP,
llvm::function_ref<void(const Solution &)> callback) {
// First, pre-check the expression, validating any types that occur in the
// expression and folding sequence expressions.
if (ConstraintSystem::preCheckExpression(expr, DC))
return;
ConstraintSystemOptions options;
options |= ConstraintSystemFlags::AllowFixes;
options |= ConstraintSystemFlags::SuppressDiagnostics;
ConstraintSystem cs(DC, options);
if (CTP != ContextualTypePurpose::CTP_Unused)
cs.setContextualType(expr, TypeLoc::withoutLoc(contextualType), CTP);
// Set up the expression type checker timer.
cs.Timer.emplace(expr, cs);
cs.shrink(expr);
if (cs.generateConstraints(expr, DC))
return;
llvm::SmallVector<Solution, 4> solutions;
{
SolverState state(cs, FreeTypeVariableBinding::Disallow);
// Enable "diagnostic mode" by default, this means that
// solver would produce "fixed" solutions along side of
// valid ones, which helps code completion to rank choices.
state.recordFixes = true;
cs.solveImpl(solutions);
}
for (const auto &solution : solutions) {
callback(solution);
}
}
void ConstraintSystem::collectDisjunctions(
SmallVectorImpl<Constraint *> &disjunctions) {
for (auto &constraint : InactiveConstraints) {