diff options
| -rw-r--r-- | clang/include/clang/Sema/TypoCorrection.h | 25 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 97 |
2 files changed, 72 insertions, 50 deletions
diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h index 26bf0ac2327..e5c49124c61 100644 --- a/clang/include/clang/Sema/TypoCorrection.h +++ b/clang/include/clang/Sema/TypoCorrection.h @@ -247,11 +247,13 @@ class CorrectionCandidateCallback { public: static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; - CorrectionCandidateCallback() + explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, + NestedNameSpecifier *TypoNNS = nullptr) : WantTypeSpecifiers(true), WantExpressionKeywords(true), WantCXXNamedCasts(true), WantFunctionLikeCasts(true), WantRemainingKeywords(true), WantObjCSuper(false), - IsObjCIvarLookup(false), IsAddressOfOperand(false) {} + IsObjCIvarLookup(false), IsAddressOfOperand(false), Typo(Typo), + TypoNNS(TypoNNS) {} virtual ~CorrectionCandidateCallback() {} @@ -274,9 +276,14 @@ public: /// the default RankCandidate returns either 0 or InvalidDistance depending /// whether ValidateCandidate returns true or false. virtual unsigned RankCandidate(const TypoCorrection &candidate) { - return ValidateCandidate(candidate) ? 0 : InvalidDistance; + return (!MatchesTypo(candidate) && ValidateCandidate(candidate)) + ? 0 + : InvalidDistance; } + void setTypoName(IdentifierInfo *II) { Typo = II; } + void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } + // Flags for context-dependent keywords. WantFunctionLikeCasts is only // used/meaningful when WantCXXNamedCasts is false. // TODO: Expand these to apply to non-keywords or possibly remove them. @@ -290,6 +297,18 @@ public: // when looking up results. bool IsObjCIvarLookup; bool IsAddressOfOperand; + +protected: + bool MatchesTypo(const TypoCorrection &candidate) { + return Typo && candidate.isResolved() && !candidate.requiresImport() && + candidate.getCorrectionAsIdentifierInfo() == Typo && + // FIXME: This probably does not return true when both + // NestedNameSpecifiers have the same textual representation. + candidate.getCorrectionSpecifier() == TypoNNS; + } + + IdentifierInfo *Typo; + NestedNameSpecifier *TypoNNS; }; /// @brief Simple template class for restricting typo correction candidates diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 20102c90ebd..afb56fe9968 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3278,6 +3278,49 @@ static void LookupPotentialTypoResult(Sema &SemaRef, bool isObjCIvarLookup, bool FindHidden); +/// \brief Check whether the declarations found for a typo correction are +/// visible, and if none of them are, convert the correction to an 'import +/// a module' correction. +static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) { + if (TC.begin() == TC.end()) + return; + + TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); + + for (/**/; DI != DE; ++DI) + if (!LookupResult::isVisible(SemaRef, *DI)) + break; + // Nothing to do if all decls are visible. + if (DI == DE) + return; + + llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI); + bool AnyVisibleDecls = !NewDecls.empty(); + + for (/**/; DI != DE; ++DI) { + NamedDecl *VisibleDecl = *DI; + if (!LookupResult::isVisible(SemaRef, *DI)) + VisibleDecl = findAcceptableDecl(SemaRef, *DI); + + if (VisibleDecl) { + if (!AnyVisibleDecls) { + // Found a visible decl, discard all hidden ones. + AnyVisibleDecls = true; + NewDecls.clear(); + } + NewDecls.push_back(VisibleDecl); + } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate()) + NewDecls.push_back(*DI); + } + + if (NewDecls.empty()) + TC = TypoCorrection(); + else { + TC.setCorrectionDecls(NewDecls); + TC.setRequiresImport(!AnyVisibleDecls); + } +} + // Fill the supplied vector with the IdentifierInfo pointers for each piece of // the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::", // fill the vector with the IdentifierInfo pointers for "foo" and "bar"). @@ -3388,9 +3431,11 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) { return; // If the correction is resolved but is not viable, ignore it. - if (Correction.isResolved() && - !isCandidateViable(*CorrectionValidator, Correction)) - return; + if (Correction.isResolved()) { + checkCorrectionVisibility(SemaRef, Correction); + if (!Correction || !isCandidateViable(*CorrectionValidator, Correction)) + return; + } TypoResultList &CList = CorrectionResults[Correction.getEditDistance(false)][Name]; @@ -3464,7 +3509,7 @@ const TypoCorrection &TypoCorrectionConsumer::getNextCorrection() { } TypoCorrection TC = RI->second.pop_back_val(); - if (TC.isResolved() || resolveCorrection(TC)) { + if (TC.isResolved() || TC.requiresImport() || resolveCorrection(TC)) { ValidatedCorrections.push_back(TC); return ValidatedCorrections[CurrentTCIndex]; } @@ -3512,6 +3557,7 @@ retry_lookup: // Store all of the Decls for overloaded symbols for (auto *TRD : Result) Candidate.addCorrectionDecl(TRD); + checkCorrectionVisibility(SemaRef, Candidate); if (!isCandidateViable(*CorrectionValidator, Candidate)) { if (SearchNamespaces) QualifiedResults.push_back(Candidate); @@ -3945,49 +3991,6 @@ static void AddKeywordsToConsumer(Sema &SemaRef, } } -/// \brief Check whether the declarations found for a typo correction are -/// visible, and if none of them are, convert the correction to an 'import -/// a module' correction. -static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) { - if (TC.begin() == TC.end()) - return; - - TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); - - for (/**/; DI != DE; ++DI) - if (!LookupResult::isVisible(SemaRef, *DI)) - break; - // Nothing to do if all decls are visible. - if (DI == DE) - return; - - llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI); - bool AnyVisibleDecls = !NewDecls.empty(); - - for (/**/; DI != DE; ++DI) { - NamedDecl *VisibleDecl = *DI; - if (!LookupResult::isVisible(SemaRef, *DI)) - VisibleDecl = findAcceptableDecl(SemaRef, *DI); - - if (VisibleDecl) { - if (!AnyVisibleDecls) { - // Found a visible decl, discard all hidden ones. - AnyVisibleDecls = true; - NewDecls.clear(); - } - NewDecls.push_back(VisibleDecl); - } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate()) - NewDecls.push_back(*DI); - } - - if (NewDecls.empty()) - TC = TypoCorrection(); - else { - TC.setCorrectionDecls(NewDecls); - TC.setRequiresImport(!AnyVisibleDecls); - } -} - std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, |

