/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Sema/TypoCorrection.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- TypoCorrection.h - Class for typo correction results -----*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file defines the TypoCorrection class, which stores the results of |
10 | | // Sema's typo correction (Sema::CorrectTypo). |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H |
15 | | #define LLVM_CLANG_SEMA_TYPOCORRECTION_H |
16 | | |
17 | | #include "clang/AST/Decl.h" |
18 | | #include "clang/AST/DeclarationName.h" |
19 | | #include "clang/Basic/LLVM.h" |
20 | | #include "clang/Basic/PartialDiagnostic.h" |
21 | | #include "clang/Basic/SourceLocation.h" |
22 | | #include "clang/Sema/DeclSpec.h" |
23 | | #include "llvm/ADT/ArrayRef.h" |
24 | | #include "llvm/ADT/SmallVector.h" |
25 | | #include "llvm/Support/Casting.h" |
26 | | #include <cstddef> |
27 | | #include <limits> |
28 | | #include <string> |
29 | | #include <utility> |
30 | | #include <vector> |
31 | | |
32 | | namespace clang { |
33 | | |
34 | | class DeclContext; |
35 | | class IdentifierInfo; |
36 | | class LangOptions; |
37 | | class MemberExpr; |
38 | | class NestedNameSpecifier; |
39 | | class Sema; |
40 | | |
41 | | /// Simple class containing the result of Sema::CorrectTypo |
42 | | class TypoCorrection { |
43 | | public: |
44 | | // "Distance" for unusable corrections |
45 | | static const unsigned InvalidDistance = std::numeric_limits<unsigned>::max(); |
46 | | |
47 | | // The largest distance still considered valid (larger edit distances are |
48 | | // mapped to InvalidDistance by getEditDistance). |
49 | | static const unsigned MaximumDistance = 10000U; |
50 | | |
51 | | // Relative weightings of the "edit distance" components. The higher the |
52 | | // weight, the more of a penalty to fitness the component will give (higher |
53 | | // weights mean greater contribution to the total edit distance, with the |
54 | | // best correction candidates having the lowest edit distance). |
55 | | static const unsigned CharDistanceWeight = 100U; |
56 | | static const unsigned QualifierDistanceWeight = 110U; |
57 | | static const unsigned CallbackDistanceWeight = 150U; |
58 | | |
59 | | TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl, |
60 | | NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0, |
61 | | unsigned QualifierDistance = 0) |
62 | | : CorrectionName(Name), CorrectionNameSpec(NNS), |
63 | 50.6k | CharDistance(CharDistance), QualifierDistance(QualifierDistance) { |
64 | 50.6k | if (NameDecl) |
65 | 0 | CorrectionDecls.push_back(NameDecl); |
66 | 50.6k | } |
67 | | |
68 | | TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr, |
69 | | unsigned CharDistance = 0) |
70 | | : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS), |
71 | 0 | CharDistance(CharDistance) { |
72 | 0 | if (Name) |
73 | 0 | CorrectionDecls.push_back(Name); |
74 | 0 | } |
75 | | |
76 | | TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr, |
77 | | unsigned CharDistance = 0) |
78 | | : CorrectionName(Name), CorrectionNameSpec(NNS), |
79 | | CharDistance(CharDistance) {} |
80 | | |
81 | 30.4k | TypoCorrection() = default; |
82 | | |
83 | | /// Gets the DeclarationName of the typo correction |
84 | 622 | DeclarationName getCorrection() const { return CorrectionName; } |
85 | | |
86 | 369k | IdentifierInfo *getCorrectionAsIdentifierInfo() const { |
87 | 369k | return CorrectionName.getAsIdentifierInfo(); |
88 | 369k | } |
89 | | |
90 | | /// Gets the NestedNameSpecifier needed to use the typo correction |
91 | 1.67k | NestedNameSpecifier *getCorrectionSpecifier() const { |
92 | 1.67k | return CorrectionNameSpec; |
93 | 1.67k | } |
94 | | |
95 | 130k | void setCorrectionSpecifier(NestedNameSpecifier *NNS) { |
96 | 130k | CorrectionNameSpec = NNS; |
97 | 130k | ForceSpecifierReplacement = (NNS != nullptr); |
98 | 130k | } |
99 | | |
100 | 7.94k | void WillReplaceSpecifier(bool ForceReplacement) { |
101 | 7.94k | ForceSpecifierReplacement = ForceReplacement; |
102 | 7.94k | } |
103 | | |
104 | 12.1k | bool WillReplaceSpecifier() const { |
105 | 12.1k | return ForceSpecifierReplacement; |
106 | 12.1k | } |
107 | | |
108 | 130k | void setQualifierDistance(unsigned ED) { |
109 | 130k | QualifierDistance = ED; |
110 | 130k | } |
111 | | |
112 | 135k | void setCallbackDistance(unsigned ED) { |
113 | 135k | CallbackDistance = ED; |
114 | 135k | } |
115 | | |
116 | | // Convert the given weighted edit distance to a roughly equivalent number of |
117 | | // single-character edits (typically for comparison to the length of the |
118 | | // string being edited). |
119 | 141k | static unsigned NormalizeEditDistance(unsigned ED) { |
120 | 141k | if (ED > MaximumDistance) |
121 | 0 | return InvalidDistance; |
122 | 141k | return (ED + CharDistanceWeight / 2) / CharDistanceWeight; |
123 | 141k | } |
124 | | |
125 | | /// Gets the "edit distance" of the typo correction from the typo. |
126 | | /// If Normalized is true, scale the distance down by the CharDistanceWeight |
127 | | /// to return the edit distance in terms of single-character edits. |
128 | 167k | unsigned getEditDistance(bool Normalized = true) const { |
129 | 167k | if (CharDistance > MaximumDistance || QualifierDistance > MaximumDistance || |
130 | 167k | CallbackDistance > MaximumDistance) |
131 | 2.15k | return InvalidDistance; |
132 | 165k | unsigned ED = |
133 | 165k | CharDistance * CharDistanceWeight + |
134 | 165k | QualifierDistance * QualifierDistanceWeight + |
135 | 165k | CallbackDistance * CallbackDistanceWeight; |
136 | 165k | if (ED > MaximumDistance) |
137 | 0 | return InvalidDistance; |
138 | | // Half the CharDistanceWeight is added to ED to simulate rounding since |
139 | | // integer division truncates the value (i.e. round-to-nearest-int instead |
140 | | // of round-to-zero). |
141 | 165k | return Normalized ? NormalizeEditDistance(ED)135k : ED29.7k ; |
142 | 165k | } |
143 | | |
144 | | /// Get the correction declaration found by name lookup (before we |
145 | | /// looked through using shadow declarations and the like). |
146 | 33.9k | NamedDecl *getFoundDecl() const { |
147 | 33.9k | return hasCorrectionDecl() ? *(CorrectionDecls.begin())8.38k : nullptr25.5k ; |
148 | 33.9k | } |
149 | | |
150 | | /// Gets the pointer to the declaration of the typo correction |
151 | 31.4k | NamedDecl *getCorrectionDecl() const { |
152 | 31.4k | auto *D = getFoundDecl(); |
153 | 31.4k | return D ? D->getUnderlyingDecl()5.90k : nullptr25.5k ; |
154 | 31.4k | } |
155 | | template <class DeclClass> |
156 | 1.11k | DeclClass *getCorrectionDeclAs() const { |
157 | 1.11k | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); |
158 | 1.11k | } clang::NamespaceDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::NamespaceDecl>() const Line | Count | Source | 156 | 16 | DeclClass *getCorrectionDeclAs() const { | 157 | 16 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 16 | } |
clang::FunctionDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::FunctionDecl>() const Line | Count | Source | 156 | 70 | DeclClass *getCorrectionDeclAs() const { | 157 | 70 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 70 | } |
clang::ObjCInterfaceDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCInterfaceDecl>() const Line | Count | Source | 156 | 113 | DeclClass *getCorrectionDeclAs() const { | 157 | 113 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 113 | } |
clang::ObjCProtocolDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCProtocolDecl>() const Line | Count | Source | 156 | 10 | DeclClass *getCorrectionDeclAs() const { | 157 | 10 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 10 | } |
clang::TypeDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::TypeDecl>() const Line | Count | Source | 156 | 8 | DeclClass *getCorrectionDeclAs() const { | 157 | 8 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 8 | } |
clang::ImplicitParamDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ImplicitParamDecl>() const Line | Count | Source | 156 | 550 | DeclClass *getCorrectionDeclAs() const { | 157 | 550 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 550 | } |
clang::ObjCIvarDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCIvarDecl>() const Line | Count | Source | 156 | 22 | DeclClass *getCorrectionDeclAs() const { | 157 | 22 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 22 | } |
clang::ObjCPropertyDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCPropertyDecl>() const Line | Count | Source | 156 | 19 | DeclClass *getCorrectionDeclAs() const { | 157 | 19 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 19 | } |
clang::FieldDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::FieldDecl>() const Line | Count | Source | 156 | 234 | DeclClass *getCorrectionDeclAs() const { | 157 | 234 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 234 | } |
clang::VarDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::VarDecl>() const Line | Count | Source | 156 | 39 | DeclClass *getCorrectionDeclAs() const { | 157 | 39 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 39 | } |
clang::TemplateDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::TemplateDecl>() const Line | Count | Source | 156 | 36 | DeclClass *getCorrectionDeclAs() const { | 157 | 36 | return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); | 158 | 36 | } |
|
159 | | |
160 | | /// Clears the list of NamedDecls. |
161 | 130k | void ClearCorrectionDecls() { |
162 | 130k | CorrectionDecls.clear(); |
163 | 130k | } |
164 | | |
165 | | /// Clears the list of NamedDecls before adding the new one. |
166 | 452 | void setCorrectionDecl(NamedDecl *CDecl) { |
167 | 452 | CorrectionDecls.clear(); |
168 | 452 | addCorrectionDecl(CDecl); |
169 | 452 | } |
170 | | |
171 | | /// Clears the list of NamedDecls and adds the given set. |
172 | 454 | void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) { |
173 | 454 | CorrectionDecls.clear(); |
174 | 454 | CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end()); |
175 | 454 | } |
176 | | |
177 | | /// Add the given NamedDecl to the list of NamedDecls that are the |
178 | | /// declarations associated with the DeclarationName of this TypoCorrection |
179 | | void addCorrectionDecl(NamedDecl *CDecl); |
180 | | |
181 | | std::string getAsString(const LangOptions &LO) const; |
182 | | |
183 | 1.22k | std::string getQuoted(const LangOptions &LO) const { |
184 | 1.22k | return "'" + getAsString(LO) + "'"; |
185 | 1.22k | } |
186 | | |
187 | | /// Returns whether this TypoCorrection has a non-empty DeclarationName |
188 | 27.4k | explicit operator bool() const { return bool(CorrectionName); } |
189 | | |
190 | | /// Mark this TypoCorrection as being a keyword. |
191 | | /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be |
192 | | /// added to the list of the correction's NamedDecl pointers, NULL is added |
193 | | /// as the only element in the list to mark this TypoCorrection as a keyword. |
194 | 162 | void makeKeyword() { |
195 | 162 | CorrectionDecls.clear(); |
196 | 162 | CorrectionDecls.push_back(nullptr); |
197 | 162 | ForceSpecifierReplacement = true; |
198 | 162 | } |
199 | | |
200 | | // Check if this TypoCorrection is a keyword by checking if the first |
201 | | // item in CorrectionDecls is NULL. |
202 | 55.7k | bool isKeyword() const { |
203 | 55.7k | return !CorrectionDecls.empty() && CorrectionDecls.front() == nullptr23.0k ; |
204 | 55.7k | } |
205 | | |
206 | | // Check if this TypoCorrection is the given keyword. |
207 | | template<std::size_t StrLen> |
208 | 8 | bool isKeyword(const char (&Str)[StrLen]) const { |
209 | 8 | return isKeyword() && getCorrectionAsIdentifierInfo()->isStr(Str)5 ; |
210 | 8 | } |
211 | | |
212 | | // Returns true if the correction either is a keyword or has a known decl. |
213 | 47.2k | bool isResolved() const { return !CorrectionDecls.empty(); } |
214 | | |
215 | 252 | bool isOverloaded() const { |
216 | 252 | return CorrectionDecls.size() > 1; |
217 | 252 | } |
218 | | |
219 | | void setCorrectionRange(CXXScopeSpec *SS, |
220 | 55.0k | const DeclarationNameInfo &TypoName) { |
221 | 55.0k | CorrectionRange = TypoName.getSourceRange(); |
222 | 55.0k | if (ForceSpecifierReplacement && SS2.50k && !SS->isEmpty()1.84k ) |
223 | 809 | CorrectionRange.setBegin(SS->getBeginLoc()); |
224 | 55.0k | } |
225 | | |
226 | 5.03k | SourceRange getCorrectionRange() const { |
227 | 5.03k | return CorrectionRange; |
228 | 5.03k | } |
229 | | |
230 | | using decl_iterator = SmallVectorImpl<NamedDecl *>::iterator; |
231 | | |
232 | 6.22k | decl_iterator begin() { |
233 | 6.22k | return isKeyword() ? CorrectionDecls.end()204 : CorrectionDecls.begin()6.02k ; |
234 | 6.22k | } |
235 | | |
236 | 5.75k | decl_iterator end() { return CorrectionDecls.end(); } |
237 | | |
238 | | using const_decl_iterator = SmallVectorImpl<NamedDecl *>::const_iterator; |
239 | | |
240 | 2.84k | const_decl_iterator begin() const { |
241 | 2.84k | return isKeyword() ? CorrectionDecls.end()0 : CorrectionDecls.begin(); |
242 | 2.84k | } |
243 | | |
244 | 2.84k | const_decl_iterator end() const { return CorrectionDecls.end(); } |
245 | | |
246 | | /// Returns whether this typo correction is correcting to a |
247 | | /// declaration that was declared in a module that has not been imported. |
248 | 16.3k | bool requiresImport() const { return RequiresImport; } |
249 | 5.47k | void setRequiresImport(bool Req) { RequiresImport = Req; } |
250 | | |
251 | | /// Extra diagnostics are printed after the first diagnostic for the typo. |
252 | | /// This can be used to attach external notes to the diag. |
253 | | void addExtraDiagnostic(PartialDiagnostic PD) { |
254 | | ExtraDiagnostics.push_back(std::move(PD)); |
255 | | } |
256 | 973 | ArrayRef<PartialDiagnostic> getExtraDiagnostics() const { |
257 | 973 | return ExtraDiagnostics; |
258 | 973 | } |
259 | | |
260 | | private: |
261 | 33.9k | bool hasCorrectionDecl() const { |
262 | 33.9k | return (!isKeyword() && !CorrectionDecls.empty()33.6k ); |
263 | 33.9k | } |
264 | | |
265 | | // Results. |
266 | | DeclarationName CorrectionName; |
267 | | NestedNameSpecifier *CorrectionNameSpec = nullptr; |
268 | | SmallVector<NamedDecl *, 1> CorrectionDecls; |
269 | | unsigned CharDistance = 0; |
270 | | unsigned QualifierDistance = 0; |
271 | | unsigned CallbackDistance = 0; |
272 | | SourceRange CorrectionRange; |
273 | | bool ForceSpecifierReplacement = false; |
274 | | bool RequiresImport = false; |
275 | | |
276 | | std::vector<PartialDiagnostic> ExtraDiagnostics; |
277 | | }; |
278 | | |
279 | | /// Base class for callback objects used by Sema::CorrectTypo to check |
280 | | /// the validity of a potential typo correction. |
281 | | class CorrectionCandidateCallback { |
282 | | public: |
283 | | static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; |
284 | | |
285 | | explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, |
286 | | NestedNameSpecifier *TypoNNS = nullptr) |
287 | 31.6M | : Typo(Typo), TypoNNS(TypoNNS) {} |
288 | | |
289 | 31.6M | virtual ~CorrectionCandidateCallback() = default; |
290 | | |
291 | | /// Simple predicate used by the default RankCandidate to |
292 | | /// determine whether to return an edit distance of 0 or InvalidDistance. |
293 | | /// This can be overridden by validators that only need to determine if a |
294 | | /// candidate is viable, without ranking potentially viable candidates. |
295 | | /// Only ValidateCandidate or RankCandidate need to be overridden by a |
296 | | /// callback wishing to check the viability of correction candidates. |
297 | | /// The default predicate always returns true if the candidate is not a type |
298 | | /// name or keyword, true for types if WantTypeSpecifiers is true, and true |
299 | | /// for keywords if WantTypeSpecifiers, WantExpressionKeywords, |
300 | | /// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true. |
301 | | virtual bool ValidateCandidate(const TypoCorrection &candidate); |
302 | | |
303 | | /// Method used by Sema::CorrectTypo to assign an "edit distance" rank |
304 | | /// to a candidate (where a lower value represents a better candidate), or |
305 | | /// returning InvalidDistance if the candidate is not at all viable. For |
306 | | /// validation callbacks that only need to determine if a candidate is viable, |
307 | | /// the default RankCandidate returns either 0 or InvalidDistance depending |
308 | | /// whether ValidateCandidate returns true or false. |
309 | 4.63k | virtual unsigned RankCandidate(const TypoCorrection &candidate) { |
310 | 4.63k | return (!MatchesTypo(candidate) && ValidateCandidate(candidate)4.62k ) |
311 | 4.63k | ? 02.48k |
312 | 4.63k | : InvalidDistance2.15k ; |
313 | 4.63k | } |
314 | | |
315 | | /// Clone this CorrectionCandidateCallback. CorrectionCandidateCallbacks are |
316 | | /// initially stack-allocated. However in case where delayed typo-correction |
317 | | /// is done we need to move the callback to storage with a longer lifetime. |
318 | | /// Every class deriving from CorrectionCandidateCallback must implement |
319 | | /// this method. |
320 | | virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0; |
321 | | |
322 | 4.15k | void setTypoName(IdentifierInfo *II) { Typo = II; } |
323 | 0 | void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } |
324 | | |
325 | | // Flags for context-dependent keywords. WantFunctionLikeCasts is only |
326 | | // used/meaningful when WantCXXNamedCasts is false. |
327 | | // TODO: Expand these to apply to non-keywords or possibly remove them. |
328 | | bool WantTypeSpecifiers = true; |
329 | | bool WantExpressionKeywords = true; |
330 | | bool WantCXXNamedCasts = true; |
331 | | bool WantFunctionLikeCasts = true; |
332 | | bool WantRemainingKeywords = true; |
333 | | bool WantObjCSuper = false; |
334 | | // Temporary hack for the one case where a CorrectTypoContext enum is used |
335 | | // when looking up results. |
336 | | bool IsObjCIvarLookup = false; |
337 | | bool IsAddressOfOperand = false; |
338 | | |
339 | | protected: |
340 | 4.63k | bool MatchesTypo(const TypoCorrection &candidate) { |
341 | 4.63k | return Typo && candidate.isResolved()579 && !candidate.requiresImport()578 && |
342 | 4.63k | candidate.getCorrectionAsIdentifierInfo() == Typo508 && |
343 | | // FIXME: This probably does not return true when both |
344 | | // NestedNameSpecifiers have the same textual representation. |
345 | 4.63k | candidate.getCorrectionSpecifier() == TypoNNS192 ; |
346 | 4.63k | } |
347 | | |
348 | | IdentifierInfo *Typo; |
349 | | NestedNameSpecifier *TypoNNS; |
350 | | }; |
351 | | |
352 | | class DefaultFilterCCC final : public CorrectionCandidateCallback { |
353 | | public: |
354 | | explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr, |
355 | | NestedNameSpecifier *TypoNNS = nullptr) |
356 | 4.65k | : CorrectionCandidateCallback(Typo, TypoNNS) {} |
357 | | |
358 | 169 | std::unique_ptr<CorrectionCandidateCallback> clone() override { |
359 | 169 | return std::make_unique<DefaultFilterCCC>(*this); |
360 | 169 | } |
361 | | }; |
362 | | |
363 | | /// Simple template class for restricting typo correction candidates |
364 | | /// to ones having a single Decl* of the given type. |
365 | | template <class C> |
366 | | class DeclFilterCCC final : public CorrectionCandidateCallback { |
367 | | public: |
368 | 105 | bool ValidateCandidate(const TypoCorrection &candidate) override { |
369 | 105 | return candidate.getCorrectionDeclAs<C>(); |
370 | 105 | } clang::DeclFilterCCC<clang::ObjCInterfaceDecl>::ValidateCandidate(clang::TypoCorrection const&) Line | Count | Source | 368 | 1 | bool ValidateCandidate(const TypoCorrection &candidate) override { | 369 | 1 | return candidate.getCorrectionDeclAs<C>(); | 370 | 1 | } |
clang::DeclFilterCCC<clang::FunctionDecl>::ValidateCandidate(clang::TypoCorrection const&) Line | Count | Source | 368 | 70 | bool ValidateCandidate(const TypoCorrection &candidate) override { | 369 | 70 | return candidate.getCorrectionDeclAs<C>(); | 370 | 70 | } |
clang::DeclFilterCCC<clang::ObjCProtocolDecl>::ValidateCandidate(clang::TypoCorrection const&) Line | Count | Source | 368 | 1 | bool ValidateCandidate(const TypoCorrection &candidate) override { | 369 | 1 | return candidate.getCorrectionDeclAs<C>(); | 370 | 1 | } |
clang::DeclFilterCCC<clang::ObjCIvarDecl>::ValidateCandidate(clang::TypoCorrection const&) Line | Count | Source | 368 | 13 | bool ValidateCandidate(const TypoCorrection &candidate) override { | 369 | 13 | return candidate.getCorrectionDeclAs<C>(); | 370 | 13 | } |
clang::DeclFilterCCC<clang::ObjCPropertyDecl>::ValidateCandidate(clang::TypoCorrection const&) Line | Count | Source | 368 | 19 | bool ValidateCandidate(const TypoCorrection &candidate) override { | 369 | 19 | return candidate.getCorrectionDeclAs<C>(); | 370 | 19 | } |
clang::DeclFilterCCC<clang::VarDecl>::ValidateCandidate(clang::TypoCorrection const&) Line | Count | Source | 368 | 1 | bool ValidateCandidate(const TypoCorrection &candidate) override { | 369 | 1 | return candidate.getCorrectionDeclAs<C>(); | 370 | 1 | } |
|
371 | 170 | std::unique_ptr<CorrectionCandidateCallback> clone() override { |
372 | 170 | return std::make_unique<DeclFilterCCC>(*this); |
373 | 170 | } clang::DeclFilterCCC<clang::ObjCInterfaceDecl>::clone() Line | Count | Source | 371 | 33 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | 372 | 33 | return std::make_unique<DeclFilterCCC>(*this); | 373 | 33 | } |
clang::DeclFilterCCC<clang::FunctionDecl>::clone() Line | Count | Source | 371 | 92 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | 372 | 92 | return std::make_unique<DeclFilterCCC>(*this); | 373 | 92 | } |
clang::DeclFilterCCC<clang::ObjCProtocolDecl>::clone() Line | Count | Source | 371 | 2 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | 372 | 2 | return std::make_unique<DeclFilterCCC>(*this); | 373 | 2 | } |
clang::DeclFilterCCC<clang::ObjCIvarDecl>::clone() Line | Count | Source | 371 | 17 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | 372 | 17 | return std::make_unique<DeclFilterCCC>(*this); | 373 | 17 | } |
clang::DeclFilterCCC<clang::ObjCPropertyDecl>::clone() Line | Count | Source | 371 | 25 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | 372 | 25 | return std::make_unique<DeclFilterCCC>(*this); | 373 | 25 | } |
clang::DeclFilterCCC<clang::VarDecl>::clone() Line | Count | Source | 371 | 1 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | 372 | 1 | return std::make_unique<DeclFilterCCC>(*this); | 373 | 1 | } |
|
374 | | }; |
375 | | |
376 | | // Callback class to limit the allowed keywords and to only accept typo |
377 | | // corrections that are keywords or whose decls refer to functions (or template |
378 | | // functions) that accept the given number of arguments. |
379 | | class FunctionCallFilterCCC : public CorrectionCandidateCallback { |
380 | | public: |
381 | | FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, |
382 | | bool HasExplicitTemplateArgs, |
383 | | MemberExpr *ME = nullptr); |
384 | | |
385 | | bool ValidateCandidate(const TypoCorrection &candidate) override; |
386 | 580 | std::unique_ptr<CorrectionCandidateCallback> clone() override { |
387 | 580 | return std::make_unique<FunctionCallFilterCCC>(*this); |
388 | 580 | } |
389 | | |
390 | | private: |
391 | | unsigned NumArgs; |
392 | | bool HasExplicitTemplateArgs; |
393 | | DeclContext *CurContext; |
394 | | MemberExpr *MemberFn; |
395 | | }; |
396 | | |
397 | | // Callback class that effectively disabled typo correction |
398 | | class NoTypoCorrectionCCC final : public CorrectionCandidateCallback { |
399 | | public: |
400 | 3.87k | NoTypoCorrectionCCC() { |
401 | 3.87k | WantTypeSpecifiers = false; |
402 | 3.87k | WantExpressionKeywords = false; |
403 | 3.87k | WantCXXNamedCasts = false; |
404 | 3.87k | WantFunctionLikeCasts = false; |
405 | 3.87k | WantRemainingKeywords = false; |
406 | 3.87k | } |
407 | | |
408 | 0 | bool ValidateCandidate(const TypoCorrection &candidate) override { |
409 | 0 | return false; |
410 | 0 | } |
411 | 0 | std::unique_ptr<CorrectionCandidateCallback> clone() override { |
412 | 0 | return std::make_unique<NoTypoCorrectionCCC>(*this); |
413 | 0 | } |
414 | | }; |
415 | | |
416 | | } // namespace clang |
417 | | |
418 | | #endif // LLVM_CLANG_SEMA_TYPOCORRECTION_H |