aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Sema/SemaInternal.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Sema/SemaInternal.h')
-rw-r--r--include/clang/Sema/SemaInternal.h212
1 files changed, 210 insertions, 2 deletions
diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
index 9199b0fba2a5..045bacf21360 100644
--- a/include/clang/Sema/SemaInternal.h
+++ b/include/clang/Sema/SemaInternal.h
@@ -12,10 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_SEMA_INTERNAL_H
-#define LLVM_CLANG_SEMA_SEMA_INTERNAL_H
+#ifndef LLVM_CLANG_SEMA_SEMAINTERNAL_H
+#define LLVM_CLANG_SEMA_SEMAINTERNAL_H
#include "clang/AST/ASTContext.h"
+#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
@@ -86,6 +87,213 @@ inline InheritableAttr *getDLLAttr(Decl *D) {
return nullptr;
}
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+ typedef SmallVector<TypoCorrection, 1> TypoResultList;
+ typedef llvm::StringMap<TypoResultList> TypoResultsMap;
+ typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
+
+public:
+ TypoCorrectionConsumer(Sema &SemaRef,
+ const DeclarationNameInfo &TypoName,
+ Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext)
+ : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0),
+ SemaRef(SemaRef), S(S),
+ SS(SS ? llvm::make_unique<CXXScopeSpec>(*SS) : nullptr),
+ CorrectionValidator(std::move(CCC)), MemberContext(MemberContext),
+ Result(SemaRef, TypoName, LookupKind),
+ Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
+ EnteringContext(EnteringContext), SearchNamespaces(false) {
+ Result.suppressDiagnostics();
+ // Arrange for ValidatedCorrections[0] to always be an empty correction.
+ ValidatedCorrections.push_back(TypoCorrection());
+ }
+
+ bool includeHiddenDecls() const override { return true; }
+
+ // Methods for adding potential corrections to the consumer.
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override;
+ void FoundName(StringRef Name);
+ void addKeywordResult(StringRef Keyword);
+ void addCorrection(TypoCorrection Correction);
+
+ bool empty() const {
+ return CorrectionResults.empty() && ValidatedCorrections.size() == 1;
+ }
+
+ /// \brief Return the list of TypoCorrections for the given identifier from
+ /// the set of corrections that have the closest edit distance, if any.
+ TypoResultList &operator[](StringRef Name) {
+ return CorrectionResults.begin()->second[Name];
+ }
+
+ /// \brief Return the edit distance of the corrections that have the
+ /// closest/best edit distance from the original typop.
+ unsigned getBestEditDistance(bool Normalized) {
+ if (CorrectionResults.empty())
+ return (std::numeric_limits<unsigned>::max)();
+
+ unsigned BestED = CorrectionResults.begin()->first;
+ return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
+ }
+
+ /// \brief Set-up method to add to the consumer the set of namespaces to use
+ /// in performing corrections to nested name specifiers. This method also
+ /// implicitly adds all of the known classes in the current AST context to the
+ /// to the consumer for correcting nested name specifiers.
+ void
+ addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces);
+
+ /// \brief Return the next typo correction that passes all internal filters
+ /// and is deemed valid by the consumer's CorrectionCandidateCallback,
+ /// starting with the corrections that have the closest edit distance. An
+ /// empty TypoCorrection is returned once no more viable corrections remain
+ /// in the consumer.
+ const TypoCorrection &getNextCorrection();
+
+ /// \brief Get the last correction returned by getNextCorrection().
+ const TypoCorrection &getCurrentCorrection() {
+ return CurrentTCIndex < ValidatedCorrections.size()
+ ? ValidatedCorrections[CurrentTCIndex]
+ : ValidatedCorrections[0]; // The empty correction.
+ }
+
+ /// \brief Return the next typo correction like getNextCorrection, but keep
+ /// the internal state pointed to the current correction (i.e. the next time
+ /// getNextCorrection is called, it will return the same correction returned
+ /// by peekNextcorrection).
+ const TypoCorrection &peekNextCorrection() {
+ auto Current = CurrentTCIndex;
+ const TypoCorrection &TC = getNextCorrection();
+ CurrentTCIndex = Current;
+ return TC;
+ }
+
+ /// \brief Reset the consumer's position in the stream of viable corrections
+ /// (i.e. getNextCorrection() will return each of the previously returned
+ /// corrections in order before returning any new corrections).
+ void resetCorrectionStream() {
+ CurrentTCIndex = 0;
+ }
+
+ /// \brief Return whether the end of the stream of corrections has been
+ /// reached.
+ bool finished() {
+ return CorrectionResults.empty() &&
+ CurrentTCIndex >= ValidatedCorrections.size();
+ }
+
+ ASTContext &getContext() const { return SemaRef.Context; }
+ const LookupResult &getLookupResult() const { return Result; }
+
+ bool isAddressOfOperand() const { return CorrectionValidator->IsAddressOfOperand; }
+ const CXXScopeSpec *getSS() const { return SS.get(); }
+ Scope *getScope() const { return S; }
+
+private:
+ class NamespaceSpecifierSet {
+ struct SpecifierInfo {
+ DeclContext* DeclCtx;
+ NestedNameSpecifier* NameSpecifier;
+ unsigned EditDistance;
+ };
+
+ typedef SmallVector<DeclContext*, 4> DeclContextList;
+ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
+
+ ASTContext &Context;
+ DeclContextList CurContextChain;
+ std::string CurNameSpecifier;
+ SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
+ SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
+ bool isSorted;
+
+ SpecifierInfoList Specifiers;
+ llvm::SmallSetVector<unsigned, 4> Distances;
+ llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap;
+
+ /// \brief Helper for building the list of DeclContexts between the current
+ /// context and the top of the translation unit
+ static DeclContextList buildContextChain(DeclContext *Start);
+
+ void sortNamespaces();
+
+ unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
+ NestedNameSpecifier *&NNS);
+
+ public:
+ NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
+ CXXScopeSpec *CurScopeSpec);
+
+ /// \brief Add the DeclContext (a namespace or record) to the set, computing
+ /// the corresponding NestedNameSpecifier and its distance in the process.
+ void addNameSpecifier(DeclContext *Ctx);
+
+ typedef SpecifierInfoList::iterator iterator;
+ iterator begin() {
+ if (!isSorted) sortNamespaces();
+ return Specifiers.begin();
+ }
+ iterator end() { return Specifiers.end(); }
+ };
+
+ void addName(StringRef Name, NamedDecl *ND,
+ NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
+
+ /// \brief Find any visible decls for the given typo correction candidate.
+ /// If none are found, it to the set of candidates for which qualified lookups
+ /// will be performed to find possible nested name specifier changes.
+ bool resolveCorrection(TypoCorrection &Candidate);
+
+ /// \brief Perform qualified lookups on the queued set of typo correction
+ /// candidates and add the nested name specifier changes to each candidate if
+ /// a lookup succeeds (at which point the candidate will be returned to the
+ /// main pool of potential corrections).
+ void performQualifiedLookups();
+
+ /// \brief The name written that is a typo in the source.
+ IdentifierInfo *Typo;
+
+ /// \brief The results found that have the smallest edit distance
+ /// found (so far) with the typo name.
+ ///
+ /// The pointer value being set to the current DeclContext indicates
+ /// whether there is a keyword with this name.
+ TypoEditDistanceMap CorrectionResults;
+
+ SmallVector<TypoCorrection, 4> ValidatedCorrections;
+ size_t CurrentTCIndex;
+
+ Sema &SemaRef;
+ Scope *S;
+ std::unique_ptr<CXXScopeSpec> SS;
+ std::unique_ptr<CorrectionCandidateCallback> CorrectionValidator;
+ DeclContext *MemberContext;
+ LookupResult Result;
+ NamespaceSpecifierSet Namespaces;
+ SmallVector<TypoCorrection, 2> QualifiedResults;
+ bool EnteringContext;
+ bool SearchNamespaces;
+};
+
+inline Sema::TypoExprState::TypoExprState() {}
+
+inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) LLVM_NOEXCEPT {
+ *this = std::move(other);
}
+inline Sema::TypoExprState &Sema::TypoExprState::operator=(
+ Sema::TypoExprState &&other) LLVM_NOEXCEPT {
+ Consumer = std::move(other.Consumer);
+ DiagHandler = std::move(other.DiagHandler);
+ RecoveryHandler = std::move(other.RecoveryHandler);
+ return *this;
+}
+
+} // end namespace clang
+
#endif