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