void TypeChecker::performTypoCorrection(DeclContext *DC, DeclRefKind refKind, Type baseTypeOrNull, DeclName targetDeclName, SourceLoc nameLoc, NameLookupOptions lookupOptions, LookupResult &result, unsigned maxResults) { // Disable typo-correction if we won't show the diagnostic anyway. if (getLangOpts().DisableTypoCorrection || (Diags.hasFatalErrorOccurred() && !Diags.getShowDiagnosticsAfterFatalError())) return; // Fill in a collection of the most reasonable entries. TopCollection<unsigned, ValueDecl*> entries(maxResults); auto consumer = makeDeclConsumer([&](ValueDecl *decl, DeclVisibilityKind reason) { // Never match an operator with an identifier or vice-versa; this is // not a plausible typo. if (!isPlausibleTypo(refKind, targetDeclName, decl)) return; // Don't suggest a variable within its own initializer. if (auto var = dyn_cast<VarDecl>(decl)) { if (isLocInVarInit(*this, var, nameLoc)) return; } // Don't waste time computing edit distances that are more than // the worst in our collection. unsigned maxDistance = entries.getMinUninterestingScore(UnreasonableCallEditDistance); unsigned distance = getCallEditDistance(targetDeclName, decl->getFullName(), maxDistance); // Ignore values that are further than a reasonable distance. if (distance >= UnreasonableCallEditDistance) return; entries.insert(distance, std::move(decl)); }); TypoCorrectionResolver resolver(*this, nameLoc); if (baseTypeOrNull) { lookupVisibleMemberDecls(consumer, baseTypeOrNull, DC, &resolver, /*include instance members*/ true); } else { lookupVisibleDecls(consumer, DC, &resolver, /*top level*/ true, nameLoc); } // Impose a maximum distance from the best score. entries.filterMaxScoreRange(MaxCallEditDistanceFromBestCandidate); for (auto &entry : entries) result.add({ entry.Value, nullptr }); }
void TypoCorrectionResults::addAllCandidatesToLookup(LookupResult &lookup) const { for (auto candidate : Candidates) lookup.add(LookupResultEntry(candidate), /*isOuter=*/false); }