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"
23 llvm::SmallString<128> Buffer;
24 llvm::raw_svector_ostream
Output(Buffer);
25 Output <<
"option not found '" << OptionName <<
'\'';
26 return std::string(Buffer);
30 llvm::SmallString<128> Buffer;
31 llvm::raw_svector_ostream
Output(Buffer);
32 Output <<
"invalid configuration value '" << LookupValue <<
"' for option '"
33 << LookupName <<
'\'';
35 Output <<
"; did you mean '" << *SuggestedValue <<
"'?";
36 return std::string(Buffer);
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);
49 : CheckName(CheckName), Context(Context),
50 Options(CheckName, Context->getOptions().CheckOptions) {
51 assert(Context !=
nullptr);
52 assert(!CheckName.empty());
56 DiagnosticIDs::Level Level) {
60 void ClangTidyCheck::run(
const ast_matchers::MatchFinder::MatchResult &Result) {
69 : NamePrefix(CheckName.str() +
"."), CheckOptions(CheckOptions) {}
71 llvm::Expected<std::string>
73 const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str());
74 if (Iter != CheckOptions.end())
75 return Iter->second.Value;
76 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str());
79 static ClangTidyOptions::OptionMap::const_iterator
81 StringRef LocalName) {
82 auto IterLocal =
Options.find((NamePrefix + LocalName).str());
83 auto IterGlobal =
Options.find(LocalName.str());
86 if (IterGlobal ==
Options.end())
88 if (IterLocal->second.Priority >= IterGlobal->second.Priority)
93 llvm::Expected<std::string>
96 if (Iter != CheckOptions.end())
97 return Iter->second.Value;
98 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str());
102 const llvm::Twine &LookupName) {
105 if (Value ==
"false")
108 if (!Value.getAsInteger(10, Result))
110 return llvm::make_error<UnparseableIntegerOptionError>(LookupName.str(),
116 ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName)
const {
117 llvm::Expected<std::string> ValueOr = get(LocalName);
119 return getAsBool(*ValueOr, NamePrefix + LocalName);
120 return ValueOr.takeError();
124 bool ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName,
125 bool Default)
const {
126 llvm::Expected<bool> ValueOr = get<bool>(LocalName);
129 logErrToStdErr(ValueOr.takeError());
135 ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName)
const {
137 if (Iter != CheckOptions.end())
138 return getAsBool(Iter->second.Value, Iter->first);
139 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str());
143 bool ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName,
144 bool Default)
const {
145 llvm::Expected<bool> ValueOr = getLocalOrGlobal<bool>(LocalName);
148 logErrToStdErr(ValueOr.takeError());
154 StringRef Value)
const {
155 Options[NamePrefix + LocalName.str()] = Value;
160 int64_t Value)
const {
161 store(
Options, LocalName, llvm::itostr(Value));
165 void ClangTidyCheck::OptionsView::store<bool>(
168 store(
Options, LocalName, Value ? StringRef(
"true") : StringRef(
"false"));
171 llvm::Expected<int64_t>
172 ClangTidyCheck::OptionsView::getEnumInt(StringRef LocalName,
173 ArrayRef<NameAndValue> Mapping,
174 bool CheckGlobal,
bool IgnoreCase) {
175 auto Iter = CheckGlobal
177 : CheckOptions.find((NamePrefix + LocalName).str());
178 if (Iter == CheckOptions.end())
179 return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str());
181 StringRef Value = Iter->second.Value;
183 unsigned EditDistance = -1;
184 for (
const auto &NameAndEnum : Mapping) {
186 if (Value.equals_lower(NameAndEnum.second))
187 return NameAndEnum.first;
188 }
else if (Value.equals(NameAndEnum.second)) {
189 return NameAndEnum.first;
190 }
else if (Value.equals_lower(NameAndEnum.second)) {
191 Closest = NameAndEnum.second;
195 unsigned Distance = Value.edit_distance(NameAndEnum.second);
196 if (Distance < EditDistance) {
197 EditDistance = Distance;
198 Closest = NameAndEnum.second;
201 if (EditDistance < 3)
202 return llvm::make_error<UnparseableEnumOptionError>(
203 Iter->first, Iter->second.Value, std::string(Closest));
204 return llvm::make_error<UnparseableEnumOptionError>(Iter->first,
208 void ClangTidyCheck::OptionsView::logErrToStdErr(llvm::Error &&Err) {
209 llvm::logAllUnhandledErrors(
211 [](
const MissingOptionError &) -> llvm::Error {
212 return llvm::Error::success();
214 llvm::errs(),
"warning: ");