@@ -176,6 +176,15 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
176176 DiagnosticBuilder diag (SourceLocation Loc, StringRef Description,
177177 DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
178178
179+ // / Add a diagnostic with the check's name.
180+ DiagnosticBuilder diag (StringRef Description,
181+ DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
182+
183+ // / Adds a diagnostic to report errors in the check's configuration.
184+ DiagnosticBuilder
185+ configurationDiag (StringRef Description,
186+ DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
187+
179188 // / Should store all options supported by this check with their
180189 // / current values or default values for options that haven't been overridden.
181190 // /
@@ -192,7 +201,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
192201 public:
193202 // / Initializes the instance using \p CheckName + "." as a prefix.
194203 OptionsView (StringRef CheckName,
195- const ClangTidyOptions::OptionMap &CheckOptions);
204+ const ClangTidyOptions::OptionMap &CheckOptions,
205+ ClangTidyContext *Context);
196206
197207 // / Read a named option from the ``Context``.
198208 // /
@@ -268,7 +278,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
268278 if (llvm::Expected<T> ValueOr = get<T>(LocalName))
269279 return *ValueOr;
270280 else
271- logErrToStdErr (ValueOr.takeError ());
281+ reportOptionParsingError (ValueOr.takeError ());
272282 return Default;
273283 }
274284
@@ -314,7 +324,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
314324 if (llvm::Expected<T> ValueOr = getLocalOrGlobal<T>(LocalName))
315325 return *ValueOr;
316326 else
317- logErrToStdErr (ValueOr.takeError ());
327+ reportOptionParsingError (ValueOr.takeError ());
318328 return Default;
319329 }
320330
@@ -330,7 +340,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
330340 // / supply the mapping required to convert between ``T`` and a string.
331341 template <typename T>
332342 std::enable_if_t <std::is_enum<T>::value, llvm::Expected<T>>
333- get (StringRef LocalName, bool IgnoreCase = false ) {
343+ get (StringRef LocalName, bool IgnoreCase = false ) const {
334344 if (llvm::Expected<int64_t > ValueOr =
335345 getEnumInt (LocalName, typeEraseMapping<T>(), false , IgnoreCase))
336346 return static_cast <T>(*ValueOr);
@@ -349,11 +359,11 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
349359 // / supply the mapping required to convert between ``T`` and a string.
350360 template <typename T>
351361 std::enable_if_t <std::is_enum<T>::value, T>
352- get (StringRef LocalName, T Default, bool IgnoreCase = false ) {
362+ get (StringRef LocalName, T Default, bool IgnoreCase = false ) const {
353363 if (auto ValueOr = get<T>(LocalName, IgnoreCase))
354364 return *ValueOr;
355365 else
356- logErrToStdErr (ValueOr.takeError ());
366+ reportOptionParsingError (ValueOr.takeError ());
357367 return Default;
358368 }
359369
@@ -370,8 +380,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
370380 // / supply the mapping required to convert between ``T`` and a string.
371381 template <typename T>
372382 std::enable_if_t <std::is_enum<T>::value, llvm::Expected<T>>
373- getLocalOrGlobal (StringRef LocalName,
374- bool IgnoreCase = false ) {
383+ getLocalOrGlobal (StringRef LocalName, bool IgnoreCase = false ) const {
375384 if (llvm::Expected<int64_t > ValueOr =
376385 getEnumInt (LocalName, typeEraseMapping<T>(), true , IgnoreCase))
377386 return static_cast <T>(*ValueOr);
@@ -391,14 +400,40 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
391400 // / supply the mapping required to convert between ``T`` and a string.
392401 template <typename T>
393402 std::enable_if_t <std::is_enum<T>::value, T>
394- getLocalOrGlobal (StringRef LocalName, T Default, bool IgnoreCase = false ) {
403+ getLocalOrGlobal (StringRef LocalName, T Default,
404+ bool IgnoreCase = false ) const {
395405 if (auto ValueOr = getLocalOrGlobal<T>(LocalName, IgnoreCase))
396406 return *ValueOr;
397407 else
398- logErrToStdErr (ValueOr.takeError ());
408+ reportOptionParsingError (ValueOr.takeError ());
399409 return Default;
400410 }
401411
412+ // / Returns the value for the option \p LocalName represented as a ``T``.
413+ // / If the option is missing returns None, if the option can't be parsed
414+ // / as a ``T``, log that to stderr and return None.
415+ template <typename T = std::string>
416+ llvm::Optional<T> getOptional (StringRef LocalName) const {
417+ if (auto ValueOr = get<T>(LocalName))
418+ return *ValueOr;
419+ else
420+ reportOptionParsingError (ValueOr.takeError ());
421+ return llvm::None;
422+ }
423+
424+ // / Returns the value for the local or global option \p LocalName
425+ // / represented as a ``T``.
426+ // / If the option is missing returns None, if the
427+ // / option can't be parsed as a ``T``, log that to stderr and return None.
428+ template <typename T = std::string>
429+ llvm::Optional<T> getOptionalLocalOrGlobal (StringRef LocalName) const {
430+ if (auto ValueOr = getLocalOrGlobal<T>(LocalName))
431+ return *ValueOr;
432+ else
433+ reportOptionParsingError (ValueOr.takeError ());
434+ return llvm::None;
435+ }
436+
402437 // / Stores an option with the check-local name \p LocalName with
403438 // / string value \p Value to \p Options.
404439 void store (ClangTidyOptions::OptionMap &Options, StringRef LocalName,
@@ -420,7 +455,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
420455 // / supply the mapping required to convert between ``T`` and a string.
421456 template <typename T>
422457 std::enable_if_t <std::is_enum<T>::value>
423- store (ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) {
458+ store (ClangTidyOptions::OptionMap &Options, StringRef LocalName,
459+ T Value) const {
424460 ArrayRef<std::pair<T, StringRef>> Mapping =
425461 OptionEnumMapping<T>::getEnumMapping ();
426462 auto Iter = llvm::find_if (
@@ -436,11 +472,11 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
436472
437473 llvm::Expected<int64_t > getEnumInt (StringRef LocalName,
438474 ArrayRef<NameAndValue> Mapping,
439- bool CheckGlobal, bool IgnoreCase);
475+ bool CheckGlobal, bool IgnoreCase) const ;
440476
441477 template <typename T>
442478 std::enable_if_t <std::is_enum<T>::value, std::vector<NameAndValue>>
443- typeEraseMapping () {
479+ typeEraseMapping () const {
444480 ArrayRef<std::pair<T, StringRef>> Mapping =
445481 OptionEnumMapping<T>::getEnumMapping ();
446482 std::vector<NameAndValue> Result;
@@ -455,10 +491,12 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
455491 void storeInt (ClangTidyOptions::OptionMap &Options, StringRef LocalName,
456492 int64_t Value) const ;
457493
458- static void logErrToStdErr (llvm::Error &&Err);
494+ // / Emits a diagnostic if \p Err is not a MissingOptionError.
495+ void reportOptionParsingError (llvm::Error &&Err) const ;
459496
460497 std::string NamePrefix;
461498 const ClangTidyOptions::OptionMap &CheckOptions;
499+ ClangTidyContext *Context;
462500 };
463501
464502private:
@@ -523,6 +561,19 @@ void ClangTidyCheck::OptionsView::store<bool>(
523561 ClangTidyOptions::OptionMap &Options, StringRef LocalName,
524562 bool Value) const ;
525563
564+ // / Returns the value for the option \p LocalName.
565+ // / If the option is missing returns None.
566+ template <>
567+ Optional<std::string> ClangTidyCheck::OptionsView::getOptional<std::string>(
568+ StringRef LocalName) const ;
569+
570+ // / Returns the value for the local or global option \p LocalName.
571+ // / If the option is missing returns None.
572+ template <>
573+ Optional<std::string>
574+ ClangTidyCheck::OptionsView::getOptionalLocalOrGlobal<std::string>(
575+ StringRef LocalName) const ;
576+
526577} // namespace tidy
527578} // namespace clang
528579
0 commit comments