Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | 1d019706d866 |
children | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
172:9fbae9c8bf63 | 173:0572611fdcc8 |
---|---|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // | 6 // |
7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
8 | 8 |
9 #include "ClangTidyCheck.h" | 9 #include "ClangTidyCheck.h" |
10 #include "llvm/ADT/SmallString.h" | |
11 #include "llvm/ADT/StringRef.h" | |
12 #include "llvm/Support/Error.h" | |
13 #include "llvm/Support/raw_ostream.h" | |
10 | 14 |
11 namespace clang { | 15 namespace clang { |
12 namespace tidy { | 16 namespace tidy { |
17 | |
18 char MissingOptionError::ID; | |
19 char UnparseableEnumOptionError::ID; | |
20 char UnparseableIntegerOptionError::ID; | |
21 | |
22 std::string MissingOptionError::message() const { | |
23 llvm::SmallString<128> Buffer; | |
24 llvm::raw_svector_ostream Output(Buffer); | |
25 Output << "option not found '" << OptionName << '\''; | |
26 return std::string(Buffer); | |
27 } | |
28 | |
29 std::string UnparseableEnumOptionError::message() const { | |
30 llvm::SmallString<128> Buffer; | |
31 llvm::raw_svector_ostream Output(Buffer); | |
32 Output << "invalid configuration value '" << LookupValue << "' for option '" | |
33 << LookupName << '\''; | |
34 if (SuggestedValue) | |
35 Output << "; did you mean '" << *SuggestedValue << "'?"; | |
36 return std::string(Buffer); | |
37 } | |
38 | |
39 std::string UnparseableIntegerOptionError::message() const { | |
40 llvm::SmallString<128> Buffer; | |
41 llvm::raw_svector_ostream Output(Buffer); | |
42 Output << "invalid configuration value '" << LookupValue << "' for option '" | |
43 << LookupName << "'; expected " | |
44 << (IsBoolean ? "a bool" : "an integer value"); | |
45 return std::string(Buffer); | |
46 } | |
13 | 47 |
14 ClangTidyCheck::ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context) | 48 ClangTidyCheck::ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context) |
15 : CheckName(CheckName), Context(Context), | 49 : CheckName(CheckName), Context(Context), |
16 Options(CheckName, Context->getOptions().CheckOptions) { | 50 Options(CheckName, Context->getOptions().CheckOptions) { |
17 assert(Context != nullptr); | 51 assert(Context != nullptr); |
32 | 66 |
33 ClangTidyCheck::OptionsView::OptionsView(StringRef CheckName, | 67 ClangTidyCheck::OptionsView::OptionsView(StringRef CheckName, |
34 const ClangTidyOptions::OptionMap &CheckOptions) | 68 const ClangTidyOptions::OptionMap &CheckOptions) |
35 : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {} | 69 : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {} |
36 | 70 |
37 std::string ClangTidyCheck::OptionsView::get(StringRef LocalName, | 71 llvm::Expected<std::string> |
38 StringRef Default) const { | 72 ClangTidyCheck::OptionsView::get(StringRef LocalName) const { |
39 const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str()); | 73 const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str()); |
40 if (Iter != CheckOptions.end()) | 74 if (Iter != CheckOptions.end()) |
41 return Iter->second; | 75 return Iter->second.Value; |
42 return std::string(Default); | 76 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); |
43 } | 77 } |
44 | 78 |
45 std::string | 79 llvm::Expected<std::string> |
46 ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName, | 80 ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const { |
47 StringRef Default) const { | 81 auto IterLocal = CheckOptions.find(NamePrefix + LocalName.str()); |
48 auto Iter = CheckOptions.find(NamePrefix + LocalName.str()); | 82 auto IterGlobal = CheckOptions.find(LocalName.str()); |
49 if (Iter != CheckOptions.end()) | 83 if (IterLocal != CheckOptions.end() && |
50 return Iter->second; | 84 (IterGlobal == CheckOptions.end() || |
51 // Fallback to global setting, if present. | 85 IterLocal->second.Priority >= IterGlobal->second.Priority)) |
52 Iter = CheckOptions.find(LocalName.str()); | 86 return IterLocal->second.Value; |
53 if (Iter != CheckOptions.end()) | 87 if (IterGlobal != CheckOptions.end()) |
54 return Iter->second; | 88 return IterGlobal->second.Value; |
55 return std::string(Default); | 89 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); |
90 } | |
91 | |
92 static llvm::Expected<bool> getAsBool(StringRef Value, | |
93 const llvm::Twine &LookupName) { | |
94 if (Value == "true") | |
95 return true; | |
96 if (Value == "false") | |
97 return false; | |
98 bool Result; | |
99 if (!Value.getAsInteger(10, Result)) | |
100 return Result; | |
101 return llvm::make_error<UnparseableIntegerOptionError>(LookupName.str(), | |
102 Value.str(), true); | |
103 } | |
104 | |
105 template <> | |
106 llvm::Expected<bool> | |
107 ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName) const { | |
108 llvm::Expected<std::string> ValueOr = get(LocalName); | |
109 if (ValueOr) | |
110 return getAsBool(*ValueOr, NamePrefix + LocalName); | |
111 return ValueOr.takeError(); | |
112 } | |
113 | |
114 template <> | |
115 bool ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName, | |
116 bool Default) const { | |
117 llvm::Expected<bool> ValueOr = get<bool>(LocalName); | |
118 if (ValueOr) | |
119 return *ValueOr; | |
120 logErrToStdErr(ValueOr.takeError()); | |
121 return Default; | |
122 } | |
123 | |
124 template <> | |
125 llvm::Expected<bool> | |
126 ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName) const { | |
127 auto IterLocal = CheckOptions.find(NamePrefix + LocalName.str()); | |
128 auto IterGlobal = CheckOptions.find(LocalName.str()); | |
129 if (IterLocal != CheckOptions.end() && | |
130 (IterGlobal == CheckOptions.end() || | |
131 IterLocal->second.Priority >= IterGlobal->second.Priority)) | |
132 return getAsBool(IterLocal->second.Value, NamePrefix + LocalName); | |
133 if (IterGlobal != CheckOptions.end()) | |
134 return getAsBool(IterGlobal->second.Value, llvm::Twine(LocalName)); | |
135 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); | |
136 } | |
137 | |
138 template <> | |
139 bool ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName, | |
140 bool Default) const { | |
141 llvm::Expected<bool> ValueOr = getLocalOrGlobal<bool>(LocalName); | |
142 if (ValueOr) | |
143 return *ValueOr; | |
144 logErrToStdErr(ValueOr.takeError()); | |
145 return Default; | |
56 } | 146 } |
57 | 147 |
58 void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options, | 148 void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options, |
59 StringRef LocalName, | 149 StringRef LocalName, |
60 StringRef Value) const { | 150 StringRef Value) const { |
61 Options[NamePrefix + LocalName.str()] = std::string(Value); | 151 Options[NamePrefix + LocalName.str()] = Value; |
62 } | 152 } |
63 | 153 |
64 void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options, | 154 void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options, |
65 StringRef LocalName, | 155 StringRef LocalName, |
66 int64_t Value) const { | 156 int64_t Value) const { |
67 store(Options, LocalName, llvm::itostr(Value)); | 157 store(Options, LocalName, llvm::itostr(Value)); |
68 } | 158 } |
69 | 159 |
160 llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt( | |
161 StringRef LocalName, ArrayRef<std::pair<StringRef, int64_t>> Mapping, | |
162 bool CheckGlobal, bool IgnoreCase) { | |
163 auto Iter = CheckOptions.find((NamePrefix + LocalName).str()); | |
164 if (CheckGlobal && Iter == CheckOptions.end()) | |
165 Iter = CheckOptions.find(LocalName.str()); | |
166 if (Iter == CheckOptions.end()) | |
167 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); | |
168 | |
169 StringRef Value = Iter->second.Value; | |
170 StringRef Closest; | |
171 unsigned EditDistance = -1; | |
172 for (const auto &NameAndEnum : Mapping) { | |
173 if (IgnoreCase) { | |
174 if (Value.equals_lower(NameAndEnum.first)) | |
175 return NameAndEnum.second; | |
176 } else if (Value.equals(NameAndEnum.first)) { | |
177 return NameAndEnum.second; | |
178 } else if (Value.equals_lower(NameAndEnum.first)) { | |
179 Closest = NameAndEnum.first; | |
180 EditDistance = 0; | |
181 continue; | |
182 } | |
183 unsigned Distance = Value.edit_distance(NameAndEnum.first); | |
184 if (Distance < EditDistance) { | |
185 EditDistance = Distance; | |
186 Closest = NameAndEnum.first; | |
187 } | |
188 } | |
189 if (EditDistance < 3) | |
190 return llvm::make_error<UnparseableEnumOptionError>( | |
191 Iter->first, Iter->second.Value, std::string(Closest)); | |
192 return llvm::make_error<UnparseableEnumOptionError>(Iter->first, | |
193 Iter->second.Value); | |
194 } | |
195 | |
196 void ClangTidyCheck::OptionsView::logErrToStdErr(llvm::Error &&Err) { | |
197 llvm::logAllUnhandledErrors( | |
198 llvm::handleErrors(std::move(Err), | |
199 [](const MissingOptionError &) -> llvm::Error { | |
200 return llvm::Error::success(); | |
201 }), | |
202 llvm::errs(), "warning: "); | |
203 } | |
70 } // namespace tidy | 204 } // namespace tidy |
71 } // namespace clang | 205 } // namespace clang |