TypoCorrection.h revision 2f4d88f4418afafbd0b22ce0f79cdead6f3a6f99
19fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//===--- TypoCorrection.h - Class for typo correction results ---*- C++ -*-===//
29fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//
39fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//                     The LLVM Compiler Infrastructure
49fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//
59fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com// This file is distributed under the University of Illinois Open Source
69fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com// License. See LICENSE.TXT for details.
79fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//
89fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//===----------------------------------------------------------------------===//
99fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//
109fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com// This file defines the TypoCorrection class, which stores the results of
119fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com// Sema's typo correction (Sema::CorrectTypo).
129fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//
139fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com//===----------------------------------------------------------------------===//
144b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org
159fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H
16773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.org#define LLVM_CLANG_SEMA_TYPOCORRECTION_H
17773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.org
18773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.org#include "clang/AST/DeclCXX.h"
19773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.org#include "llvm/ADT/SmallVector.h"
20773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.org
21773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.orgnamespace clang {
22773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.org
23773f8e24214991332eaf903e72c13dca7d78d40dcommit-bot@chromium.org/// @brief Simple class containing the result of Sema::CorrectTypo
249fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.comclass TypoCorrection {
259fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.compublic:
269fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
279fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com                 NestedNameSpecifier *NNS=0, unsigned distance=0)
289fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com      : CorrectionName(Name),
299fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com        CorrectionNameSpec(NNS),
306fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com        EditDistance(distance) {
319fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    if (NameDecl)
329fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com      CorrectionDecls.push_back(NameDecl);
336fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com  }
349fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
359fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=0,
369fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com                 unsigned distance=0)
379fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com      : CorrectionName(Name->getDeclName()),
389fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com        CorrectionNameSpec(NNS),
399fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com        EditDistance(distance) {
409fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    if (Name)
419fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com      CorrectionDecls.push_back(Name);
426fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com  }
439fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
449fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=0,
459fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com                 unsigned distance=0)
469fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com      : CorrectionName(Name),
479fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com        CorrectionNameSpec(NNS),
484b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org        EditDistance(distance) {}
4949f085dddff10473b6ebf832a974288300224e60bsalomon
504b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org  TypoCorrection()
514b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org      : CorrectionNameSpec(0), EditDistance(0) {}
524b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org
534b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org  /// \brief Gets the DeclarationName of the typo correction
544b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org  DeclarationName getCorrection() const { return CorrectionName; }
554b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org  IdentifierInfo* getCorrectionAsIdentifierInfo() const {
564b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org    return CorrectionName.getAsIdentifierInfo();
574b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org  }
584b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org
594b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org  /// \brief Gets the NestedNameSpecifier needed to use the typo correction
609fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  NestedNameSpecifier* getCorrectionSpecifier() const {
614b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org    return CorrectionNameSpec;
629fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  }
639fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  void setCorrectionSpecifier(NestedNameSpecifier* NNS) {
649fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    CorrectionNameSpec = NNS;
659fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  }
669fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
679fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  /// \brief Gets the "edit distance" of the typo correction from the typo
689fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  unsigned getEditDistance() const { return EditDistance; }
699fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
709fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  /// \brief Gets the pointer to the declaration of the typo correction
719fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  NamedDecl* getCorrectionDecl() const {
726fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com    return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
739fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  }
749fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  template <class DeclClass>
759fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  DeclClass *getCorrectionDeclAs() const {
76ec66e6264de5110802c3d9927380d913242c9d5frobertphillips    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
77ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  }
78ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
79ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  /// \brief Clears the list of NamedDecls before adding the new one.
809fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  void setCorrectionDecl(NamedDecl *CDecl) {
819fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    CorrectionDecls.clear();
826fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com    addCorrectionDecl(CDecl);
839fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  }
846fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com
859fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  /// \brief Add the given NamedDecl to the list of NamedDecls that are the
869fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  /// declarations associated with the DeclarationName of this TypoCorrection
879fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  void addCorrectionDecl(NamedDecl *CDecl);
889fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
899fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  std::string getAsString(const LangOptions &LO) const;
909fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  std::string getQuoted(const LangOptions &LO) const {
919fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    return "'" + getAsString(LO) + "'";
92ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  }
93ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
94ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  /// \brief Returns whether this TypoCorrection has a non-empty DeclarationName
95ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  operator bool() const { return bool(CorrectionName); }
96ec66e6264de5110802c3d9927380d913242c9d5frobertphillips
97ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  /// \brief Mark this TypoCorrection as being a keyword.
98ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
99ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  /// added to the list of the correction's NamedDecl pointers, NULL is added
100ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  /// as the only element in the list to mark this TypoCorrection as a keyword.
101ec66e6264de5110802c3d9927380d913242c9d5frobertphillips  void makeKeyword() {
1029fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    CorrectionDecls.clear();
1039fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    CorrectionDecls.push_back(0);
104a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  }
10549f085dddff10473b6ebf832a974288300224e60bsalomon
106a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  // Check if this TypoCorrection is a keyword by checking if the first
107a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  // item in CorrectionDecls is NULL.
108a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  bool isKeyword() const {
109a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org    return !CorrectionDecls.empty() &&
110a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org        CorrectionDecls.front() == 0;
111a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  }
112a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org
113a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  // Check if this TypoCorrection is the given keyword.
114a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  template<std::size_t StrLen>
115a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  bool isKeyword(const char (&Str)[StrLen]) const {
116a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org    return isKeyword() && getCorrectionAsIdentifierInfo()->isStr(Str);
117a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  }
118a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org
119beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  // Returns true if the correction either is a keyword or has a known decl.
120beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  bool isResolved() const { return !CorrectionDecls.empty(); }
121beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com
122beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  bool isOverloaded() const {
123beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com    return CorrectionDecls.size() > 1;
124beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  }
125beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com
126beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  typedef llvm::SmallVector<NamedDecl*, 1>::iterator decl_iterator;
127beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  decl_iterator begin() {
128beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com    return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
129beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  }
130db35dab49e0e6bf16ccad5052bf6e6826daad27dskia.committer@gmail.com  decl_iterator end() { return CorrectionDecls.end(); }
131db35dab49e0e6bf16ccad5052bf6e6826daad27dskia.committer@gmail.com
1322b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.orgprivate:
133beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  bool hasCorrectionDecl() const {
134a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org    return (!isKeyword() && !CorrectionDecls.empty());
135beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  }
136beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com
137beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  // Results.
138beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  DeclarationName CorrectionName;
139a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  NestedNameSpecifier *CorrectionNameSpec;
140beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  llvm::SmallVector<NamedDecl*, 1> CorrectionDecls;
141beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com  unsigned EditDistance;
142beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com};
143beb1af2f34b5c538fc08d849b132355160b4c93frobertphillips@google.com
1449fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com/// @brief Base class for callback objects used by Sema::CorrectTypo to check
1459fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com/// the validity of a potential typo correction.
1468515e79a7699922e0f95f93e8cc11d4c88657c58rileya@google.comclass CorrectionCandidateCallback {
1479fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com public:
1489fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  CorrectionCandidateCallback()
1499fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com      : WantTypeSpecifiers(true), WantExpressionKeywords(true),
150a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org        WantCXXNamedCasts(true), WantRemainingKeywords(true),
1519fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com        WantObjCSuper(false),
1529fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com        IsObjCIvarLookup(false) {}
1539fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
1549fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  virtual ~CorrectionCandidateCallback() {}
1559fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
1569fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
1579fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com    return true;
1589fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  }
1599fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
1609fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  // Flags for context-dependent keywords.
1619fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  // TODO: Expand these to apply to non-keywords or possibly remove them.
1629fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  bool WantTypeSpecifiers;
1639fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  bool WantExpressionKeywords;
1649fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  bool WantCXXNamedCasts;
1659fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  bool WantRemainingKeywords;
1669fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  bool WantObjCSuper;
1679fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  // Temporary hack for the one case where a CorrectTypoContext enum is used
1689fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  // when looking up results.
169db35dab49e0e6bf16ccad5052bf6e6826daad27dskia.committer@gmail.com  bool IsObjCIvarLookup;
170db35dab49e0e6bf16ccad5052bf6e6826daad27dskia.committer@gmail.com};
171a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org
172a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org/// @brief Simple template class for restricting typo correction candidates
1732b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.org/// to ones having a single Decl* of the given type.
174db35dab49e0e6bf16ccad5052bf6e6826daad27dskia.committer@gmail.comtemplate <class C>
175db35dab49e0e6bf16ccad5052bf6e6826daad27dskia.committer@gmail.comclass DeclFilterCCC : public CorrectionCandidateCallback {
176a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org public:
177a31eacb22e12a4223740e53ff5a11bd08340106ecommit-bot@chromium.org  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
1782b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.org    return candidate.getCorrectionDeclAs<C>();
1799fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com  }
1809fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com};
1819fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
1829fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com}
1839fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com
1849fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com#endif
1859fd7f8d2906365637dc25f98ffdede87d631ef71rileya@google.com