TypoCorrection.h revision 60a09dcc4656b82c7f96f8719a403a83247f6742
1//===--- TypoCorrection.h - Class for typo correction results ---*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the TypoCorrection class, which stores the results of
11// Sema's typo correction (Sema::CorrectTypo).
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H
16#define LLVM_CLANG_SEMA_TYPOCORRECTION_H
17
18#include "clang/AST/DeclCXX.h"
19#include "llvm/ADT/SmallVector.h"
20
21namespace clang {
22
23/// @brief Simple class containing the result of Sema::CorrectTypo
24class TypoCorrection {
25public:
26  TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
27                 NestedNameSpecifier *NNS=0, unsigned distance=0)
28      : CorrectionName(Name),
29        CorrectionNameSpec(NNS),
30        EditDistance(distance) {
31    if (NameDecl)
32      CorrectionDecls.push_back(NameDecl);
33  }
34
35  TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=0,
36                 unsigned distance=0)
37      : CorrectionName(Name->getDeclName()),
38        CorrectionNameSpec(NNS),
39        EditDistance(distance) {
40    if (Name)
41      CorrectionDecls.push_back(Name);
42  }
43
44  TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=0,
45                 unsigned distance=0)
46      : CorrectionName(Name),
47        CorrectionNameSpec(NNS),
48        EditDistance(distance) {}
49
50  TypoCorrection()
51      : CorrectionNameSpec(0), EditDistance(0) {}
52
53  /// \brief Gets the DeclarationName of the typo correction
54  DeclarationName getCorrection() const { return CorrectionName; }
55  IdentifierInfo* getCorrectionAsIdentifierInfo() const {
56    return CorrectionName.getAsIdentifierInfo();
57  }
58
59  /// \brief Gets the NestedNameSpecifier needed to use the typo correction
60  NestedNameSpecifier* getCorrectionSpecifier() const {
61    return CorrectionNameSpec;
62  }
63  void setCorrectionSpecifier(NestedNameSpecifier* NNS) {
64    CorrectionNameSpec = NNS;
65  }
66
67  /// \brief Gets the "edit distance" of the typo correction from the typo
68  unsigned getEditDistance() const { return EditDistance; }
69
70  /// \brief Gets the pointer to the declaration of the typo correction
71  NamedDecl* getCorrectionDecl() const {
72    return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
73  }
74  template <class DeclClass>
75  DeclClass *getCorrectionDeclAs() const {
76    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
77  }
78
79  /// \brief Clears the list of NamedDecls before adding the new one.
80  void setCorrectionDecl(NamedDecl *CDecl) {
81    CorrectionDecls.clear();
82    addCorrectionDecl(CDecl);
83  }
84
85  /// \brief Add the given NamedDecl to the list of NamedDecls that are the
86  /// declarations associated with the DeclarationName of this TypoCorrection
87  void addCorrectionDecl(NamedDecl *CDecl);
88
89  std::string getAsString(const LangOptions &LO) const;
90  std::string getQuoted(const LangOptions &LO) const {
91    return "'" + getAsString(LO) + "'";
92  }
93
94  /// \brief Returns whether this TypoCorrection has a non-empty DeclarationName
95  operator bool() const { return bool(CorrectionName); }
96
97  /// \brief Mark this TypoCorrection as being a keyword.
98  /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
99  /// added to the list of the correction's NamedDecl pointers, NULL is added
100  /// as the only element in the list to mark this TypoCorrection as a keyword.
101  void makeKeyword() {
102    CorrectionDecls.clear();
103    CorrectionDecls.push_back(0);
104  }
105
106  // Check if this TypoCorrection is a keyword by checking if the first
107  // item in CorrectionDecls is NULL.
108  bool isKeyword() const {
109    return !CorrectionDecls.empty() &&
110        CorrectionDecls.front() == 0;
111  }
112
113  // Check if this TypoCorrection is the given keyword.
114  template<std::size_t StrLen>
115  bool isKeyword(const char (&Str)[StrLen]) const {
116    return isKeyword() && getCorrectionAsIdentifierInfo()->isStr(Str);
117  }
118
119  // Returns true if the correction either is a keyword or has a known decl.
120  bool isResolved() const { return !CorrectionDecls.empty(); }
121
122  bool isOverloaded() const {
123    return CorrectionDecls.size() > 1;
124  }
125
126  typedef llvm::SmallVector<NamedDecl*, 1>::iterator decl_iterator;
127  decl_iterator begin() {
128    return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
129  }
130  decl_iterator end() { return CorrectionDecls.end(); }
131  typedef llvm::SmallVector<NamedDecl*, 1>::const_iterator const_decl_iterator;
132  const_decl_iterator begin() const {
133    return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
134  }
135  const_decl_iterator end() const { return CorrectionDecls.end(); }
136
137private:
138  bool hasCorrectionDecl() const {
139    return (!isKeyword() && !CorrectionDecls.empty());
140  }
141
142  // Results.
143  DeclarationName CorrectionName;
144  NestedNameSpecifier *CorrectionNameSpec;
145  llvm::SmallVector<NamedDecl*, 1> CorrectionDecls;
146  unsigned EditDistance;
147};
148
149/// @brief Base class for callback objects used by Sema::CorrectTypo to check
150/// the validity of a potential typo correction.
151class CorrectionCandidateCallback {
152 public:
153  CorrectionCandidateCallback()
154      : WantTypeSpecifiers(true), WantExpressionKeywords(true),
155        WantCXXNamedCasts(true), WantRemainingKeywords(true),
156        WantObjCSuper(false),
157        IsObjCIvarLookup(false) {}
158
159  virtual ~CorrectionCandidateCallback() {}
160
161  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
162    return true;
163  }
164
165  // Flags for context-dependent keywords.
166  // TODO: Expand these to apply to non-keywords or possibly remove them.
167  bool WantTypeSpecifiers;
168  bool WantExpressionKeywords;
169  bool WantCXXNamedCasts;
170  bool WantRemainingKeywords;
171  bool WantObjCSuper;
172  // Temporary hack for the one case where a CorrectTypoContext enum is used
173  // when looking up results.
174  bool IsObjCIvarLookup;
175};
176
177/// @brief Simple template class for restricting typo correction candidates
178/// to ones having a single Decl* of the given type.
179template <class C>
180class DeclFilterCCC : public CorrectionCandidateCallback {
181 public:
182  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
183    return candidate.getCorrectionDeclAs<C>();
184  }
185};
186
187}
188
189#endif
190