forked from OSchip/llvm-project
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:
parent
8ba47d017b
commit
0e23844f57
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue