10 #include "llvm/ADT/SmallString.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/Error.h"
13 #include "llvm/Support/YAMLParser.h"
19 : CheckName(CheckName), Context(Context),
20 Options(CheckName, Context->getOptions().CheckOptions, Context) {
21 assert(Context !=
nullptr);
22 assert(!CheckName.empty());
26 DiagnosticIDs::Level Level) {
31 DiagnosticIDs::Level Level) {
37 DiagnosticIDs::Level Level)
const {
41 void ClangTidyCheck::run(
const ast_matchers::MatchFinder::MatchResult &Result) {
51 : NamePrefix((CheckName +
".").str()), CheckOptions(CheckOptions),
54 llvm::Optional<StringRef>
56 const auto &Iter = CheckOptions.find((NamePrefix + LocalName).str());
57 if (Iter != CheckOptions.end())
58 return StringRef(Iter->getValue().Value);
62 static ClangTidyOptions::OptionMap::const_iterator
64 StringRef LocalName) {
65 auto IterLocal =
Options.find((NamePrefix + LocalName).str());
66 auto IterGlobal =
Options.find(LocalName);
69 if (IterGlobal ==
Options.end())
71 if (IterLocal->getValue().Priority >= IterGlobal->getValue().Priority)
76 llvm::Optional<StringRef>
79 if (Iter != CheckOptions.end())
80 return StringRef(Iter->getValue().Value);
85 const llvm::Twine &LookupName) {
87 if (llvm::Optional<bool> Parsed = llvm::yaml::parseBool(Value))
92 if (!Value.getAsInteger(10,
Number))
99 ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName)
const {
100 if (llvm::Optional<StringRef> ValueOr = get(LocalName)) {
101 if (
auto Result =
getAsBool(*ValueOr, NamePrefix + LocalName))
103 diagnoseBadBooleanOption(NamePrefix + LocalName, *ValueOr);
110 ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName)
const {
112 if (Iter != CheckOptions.end()) {
113 if (
auto Result =
getAsBool(Iter->getValue().Value, Iter->getKey()))
115 diagnoseBadBooleanOption(Iter->getKey(), Iter->getValue().Value);
122 StringRef Value)
const {
123 Options[(NamePrefix + LocalName).str()] = Value;
128 int64_t Value)
const {
129 store(
Options, LocalName, llvm::itostr(Value));
133 void ClangTidyCheck::OptionsView::store<bool>(
136 store(
Options, LocalName, Value ? StringRef(
"true") : StringRef(
"false"));
139 llvm::Optional<int64_t> ClangTidyCheck::OptionsView::getEnumInt(
140 StringRef LocalName, ArrayRef<NameAndValue> Mapping,
bool CheckGlobal,
141 bool IgnoreCase)
const {
142 auto Iter = CheckGlobal
144 : CheckOptions.find((NamePrefix + LocalName).str());
145 if (Iter == CheckOptions.end())
148 StringRef Value = Iter->getValue().Value;
150 unsigned EditDistance = 3;
151 for (
const auto &NameAndEnum : Mapping) {
153 if (Value.equals_insensitive(NameAndEnum.second))
154 return NameAndEnum.first;
155 }
else if (Value.equals(NameAndEnum.second)) {
156 return NameAndEnum.first;
157 }
else if (Value.equals_insensitive(NameAndEnum.second)) {
158 Closest = NameAndEnum.second;
163 Value.edit_distance(NameAndEnum.second,
true, EditDistance);
164 if (Distance < EditDistance) {
165 EditDistance = Distance;
166 Closest = NameAndEnum.second;
169 if (EditDistance < 3)
170 diagnoseBadEnumOption(Iter->getKey(), Iter->getValue().Value, Closest);
172 diagnoseBadEnumOption(Iter->getKey(), Iter->getValue().Value);
177 "invalid configuration value '%0' for option '%1'%select{|; expected a "
178 "bool|; expected an integer|; did you mean '%3'?}2");
180 void ClangTidyCheck::OptionsView::diagnoseBadBooleanOption(
181 const Twine &Lookup, StringRef Unparsed)
const {
182 SmallString<64> Buffer;
184 << Unparsed << Lookup.toStringRef(Buffer) << 1;
187 void ClangTidyCheck::OptionsView::diagnoseBadIntegerOption(
188 const Twine &Lookup, StringRef Unparsed)
const {
189 SmallString<64> Buffer;
191 << Unparsed << Lookup.toStringRef(Buffer) << 2;
194 void ClangTidyCheck::OptionsView::diagnoseBadEnumOption(
195 const Twine &Lookup, StringRef Unparsed, StringRef Suggestion)
const {
196 SmallString<64> Buffer;
198 << Unparsed << Lookup.toStringRef(Buffer);
199 if (Suggestion.empty())
202 Diag << 3 << Suggestion;
206 StringRef Default)
const {
207 return get(LocalName).getValueOr(Default);
212 StringRef Default)
const {
213 return getLocalOrGlobal(LocalName).getValueOr(Default);