Cache the location of failed typo corrections so that typo correction

isn't repeatedly attempted for the same identifier at the same location.

llvm-svn: 191543
This commit is contained in:
Kaelyn Uhrain 2013-09-27 19:40:08 +00:00
parent 8ba47d017b
commit 0e23844f57
3 changed files with 50 additions and 29 deletions

View File

@ -2493,7 +2493,8 @@ public:
CorrectionCandidateCallback &CCC,
DeclContext *MemberContext = 0,
bool EnteringContext = false,
const ObjCObjectPointerType *OPT = 0);
const ObjCObjectPointerType *OPT = 0,
bool RecordFailure = true);
void diagnoseTypo(const TypoCorrection &Correction,
const PartialDiagnostic &TypoDiag,
@ -2705,6 +2706,17 @@ private:
bool receiverIdOrClass,
bool warn, bool instance);
/// \brief Record the typo correction failure and return an empty correction.
TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
bool RecordFailure = true,
bool IsUnqualifiedLookup = false) {
if (IsUnqualifiedLookup)
(void)UnqualifiedTyposCorrected[Typo];
if (RecordFailure)
TypoCorrectionFailures[Typo].insert(TypoLoc);
return TypoCorrection();
}
public:
/// AddInstanceMethodToGlobalPool - All instance methods in a translation
/// unit are added to a global pool. This allows us to efficiently associate
@ -6308,6 +6320,14 @@ public:
/// string represents a keyword.
UnqualifiedTyposCorrectedMap UnqualifiedTyposCorrected;
typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet;
typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations;
/// \brief A cache containing identifiers for which typo correction failed and
/// their locations, so that repeated attempts to correct an identifier in a
/// given location are ignored if typo correction already failed for it.
IdentifierSourceLocations TypoCorrectionFailures;
/// \brief Worker object for performing CFG-based warnings.
sema::AnalysisBasedWarnings AnalysisWarnings;

View File

@ -1839,9 +1839,9 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
}
ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
Result.getLookupKind(), S, NULL,
Validator)) {
if (TypoCorrection Corrected =
CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S,
NULL, Validator, NULL, false, NULL, false)) {
if (Corrected.isKeyword()) {
// If we've found the keyword "super" (the only keyword that would be
// returned by CorrectTypo), this is a send to super.

View File

@ -4056,7 +4056,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
CorrectionCandidateCallback &CCC,
DeclContext *MemberContext,
bool EnteringContext,
const ObjCObjectPointerType *OPT) {
const ObjCObjectPointerType *OPT,
bool RecordFailure) {
// Always let the ExternalSource have the first chance at correction, even
// if we would otherwise have given up.
if (ExternalSource) {
@ -4095,6 +4096,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier())
return TypoCorrection();
// Abort if typo correction already failed for this specific typo.
IdentifierSourceLocations::iterator locs = TypoCorrectionFailures.find(Typo);
if (locs != TypoCorrectionFailures.end() &&
locs->second.count(TypoName.getLoc()) > 0)
return TypoCorrection();
NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
TypoCorrectionConsumer Consumer(*this, Typo);
@ -4193,24 +4200,16 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
AddKeywordsToConsumer(*this, Consumer, S, CCC, SS && SS->isNotEmpty());
// If we haven't found anything, we're done.
if (Consumer.empty()) {
// If this was an unqualified lookup, note that no correction was found.
if (IsUnqualifiedLookup)
(void)UnqualifiedTyposCorrected[Typo];
return TypoCorrection();
}
if (Consumer.empty())
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
IsUnqualifiedLookup);
// Make sure the best edit distance (prior to adding any namespace qualifiers)
// is not more that about a third of the length of the typo's identifier.
unsigned ED = Consumer.getBestEditDistance(true);
if (ED > 0 && Typo->getName().size() / ED < 3) {
// If this was an unqualified lookup, note that no correction was found.
if (IsUnqualifiedLookup)
(void)UnqualifiedTyposCorrected[Typo];
return TypoCorrection();
}
if (ED > 0 && Typo->getName().size() / ED < 3)
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
IsUnqualifiedLookup);
// Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
// to search those namespaces.
@ -4327,7 +4326,7 @@ retry_lookup:
case LookupResult::Ambiguous:
// We don't deal with ambiguities.
return TypoCorrection();
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
case LookupResult::FoundOverloaded: {
TypoCorrectionConsumer::result_iterator Prev = I;
@ -4431,7 +4430,8 @@ retry_lookup:
}
// No corrections remain...
if (Consumer.empty()) return TypoCorrection();
if (Consumer.empty())
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
TypoResultsMap &BestResults = Consumer.getBestResults();
ED = Consumer.getBestEditDistance(true);
@ -4440,21 +4440,21 @@ retry_lookup:
// If this was an unqualified lookup and we believe the callback
// object wouldn't have filtered out possible corrections, note
// that no correction was found.
if (IsUnqualifiedLookup && !ValidatingCallback)
(void)UnqualifiedTyposCorrected[Typo];
return TypoCorrection();
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
IsUnqualifiedLookup && !ValidatingCallback);
}
// If only a single name remains, return that result.
if (BestResults.size() == 1) {
const TypoResultList &CorrectionList = BestResults.begin()->second;
const TypoCorrection &Result = CorrectionList.front();
if (CorrectionList.size() != 1) return TypoCorrection();
if (CorrectionList.size() != 1)
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
if (ED == 0 && Result.isKeyword()) return TypoCorrection();
if (ED == 0 && Result.isKeyword())
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
// Record the correction for unqualified lookup.
if (IsUnqualifiedLookup)
@ -4477,7 +4477,8 @@ retry_lookup:
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
if (ED == 0) return TypoCorrection();
if (ED == 0)
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
// Record the correction for unqualified lookup.
if (IsUnqualifiedLookup)
@ -4493,7 +4494,7 @@ retry_lookup:
if (IsUnqualifiedLookup && !ValidatingCallback)
(void)UnqualifiedTyposCorrected[Typo];
return TypoCorrection();
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
}
void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {