@@ -27,6 +27,13 @@ class CompilerInstance;
27
27
28
28
namespace tidy {
29
29
30
+ // / This class should be specialized by any enum type that needs to be converted
31
+ // / to and from an \ref llvm::StringRef.
32
+ template <class T > struct OptionEnumMapping {
33
+ // Specializations of this struct must implement this function.
34
+ static ArrayRef<std::pair<T, StringRef>> getEnumMapping () = delete;
35
+ };
36
+
30
37
template <typename T> class OptionError : public llvm ::ErrorInfo<T> {
31
38
std::error_code convertToErrorCode () const override {
32
39
return llvm::inconvertibleErrorCode ();
@@ -313,77 +320,80 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
313
320
}
314
321
315
322
// / Read a named option from the ``Context`` and parse it as an
316
- // / enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
317
- // / it will search the mapping ignoring the case.
323
+ // / enum type ``T``.
318
324
// /
319
325
// / Reads the option with the check-local name \p LocalName from the
320
326
// / ``CheckOptions``. If the corresponding key is not present, returns a
321
327
// / ``MissingOptionError``. If the key can't be parsed as a ``T`` returns a
322
328
// / ``UnparseableEnumOptionError``.
329
+ // /
330
+ // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
331
+ // / supply the mapping required to convert between ``T`` and a string.
323
332
template <typename T>
324
333
std::enable_if_t <std::is_enum<T>::value, llvm::Expected<T>>
325
- get (StringRef LocalName, ArrayRef<std::pair<StringRef, T>> Mapping,
326
- bool IgnoreCase = false ) {
327
- if (llvm::Expected<int64_t > ValueOr = getEnumInt (
328
- LocalName, typeEraseMapping (Mapping), false , IgnoreCase))
334
+ get (StringRef LocalName, bool IgnoreCase = false ) {
335
+ if (llvm::Expected<int64_t > ValueOr =
336
+ getEnumInt (LocalName, typeEraseMapping<T>(), false , IgnoreCase))
329
337
return static_cast <T>(*ValueOr);
330
338
else
331
339
return std::move (ValueOr.takeError ());
332
340
}
333
341
334
342
// / Read a named option from the ``Context`` and parse it as an
335
- // / enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
336
- // / it will search the mapping ignoring the case.
343
+ // / enum type ``T``.
337
344
// /
338
345
// / Reads the option with the check-local name \p LocalName from the
339
346
// / ``CheckOptions``. If the corresponding key is not present or it can't be
340
347
// / parsed as a ``T``, returns \p Default.
348
+ // /
349
+ // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
350
+ // / supply the mapping required to convert between ``T`` and a string.
341
351
template <typename T>
342
352
std::enable_if_t <std::is_enum<T>::value, T>
343
- get (StringRef LocalName, ArrayRef<std::pair<StringRef, T>> Mapping,
344
- T Default, bool IgnoreCase = false ) {
345
- if (auto ValueOr = get (LocalName, Mapping, IgnoreCase))
353
+ get (StringRef LocalName, T Default, bool IgnoreCase = false ) {
354
+ if (auto ValueOr = get<T>(LocalName, IgnoreCase))
346
355
return *ValueOr;
347
356
else
348
357
logErrToStdErr (ValueOr.takeError ());
349
358
return Default;
350
359
}
351
360
352
361
// / Read a named option from the ``Context`` and parse it as an
353
- // / enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
354
- // / it will search the mapping ignoring the case.
362
+ // / enum type ``T``.
355
363
// /
356
364
// / Reads the option with the check-local name \p LocalName from local or
357
365
// / global ``CheckOptions``. Gets local option first. If local is not
358
366
// / present, falls back to get global option. If global option is not
359
367
// / present either, returns a ``MissingOptionError``. If the key can't be
360
368
// / parsed as a ``T`` returns a ``UnparseableEnumOptionError``.
369
+ // /
370
+ // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
371
+ // / supply the mapping required to convert between ``T`` and a string.
361
372
template <typename T>
362
373
std::enable_if_t <std::is_enum<T>::value, llvm::Expected<T>>
363
374
getLocalOrGlobal (StringRef LocalName,
364
- ArrayRef<std::pair<StringRef, T>> Mapping,
365
375
bool IgnoreCase = false ) {
366
- if (llvm::Expected<int64_t > ValueOr = getEnumInt (
367
- LocalName, typeEraseMapping (Mapping ), true , IgnoreCase))
376
+ if (llvm::Expected<int64_t > ValueOr =
377
+ getEnumInt ( LocalName, typeEraseMapping<T>( ), true , IgnoreCase))
368
378
return static_cast <T>(*ValueOr);
369
379
else
370
380
return std::move (ValueOr.takeError ());
371
381
}
372
382
373
383
// / Read a named option from the ``Context`` and parse it as an
374
- // / enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
375
- // / it will search the mapping ignoring the case.
384
+ // / enum type ``T``.
376
385
// /
377
386
// / Reads the option with the check-local name \p LocalName from local or
378
387
// / global ``CheckOptions``. Gets local option first. If local is not
379
388
// / present, falls back to get global option. If global option is not
380
389
// / present either or it can't be parsed as a ``T``, returns \p Default.
390
+ // /
391
+ // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
392
+ // / supply the mapping required to convert between ``T`` and a string.
381
393
template <typename T>
382
394
std::enable_if_t <std::is_enum<T>::value, T>
383
- getLocalOrGlobal (StringRef LocalName,
384
- ArrayRef<std::pair<StringRef, T>> Mapping, T Default,
385
- bool IgnoreCase = false ) {
386
- if (auto ValueOr = getLocalOrGlobal (LocalName, Mapping, IgnoreCase))
395
+ getLocalOrGlobal (StringRef LocalName, T Default, bool IgnoreCase = false ) {
396
+ if (auto ValueOr = getLocalOrGlobal<T>(LocalName, IgnoreCase))
387
397
return *ValueOr;
388
398
else
389
399
logErrToStdErr (ValueOr.takeError ());
@@ -401,34 +411,40 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
401
411
int64_t Value) const ;
402
412
403
413
// / Stores an option with the check-local name \p LocalName as the string
404
- // / representation of the Enum \p Value using the \p Mapping to \p Options.
414
+ // / representation of the Enum \p Value to \p Options.
415
+ // /
416
+ // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
417
+ // / supply the mapping required to convert between ``T`` and a string.
405
418
template <typename T>
406
419
std::enable_if_t <std::is_enum<T>::value>
407
- store (ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value,
408
- ArrayRef<std::pair<StringRef, T>> Mapping) {
420
+ store (ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) {
421
+ ArrayRef<std::pair<T, StringRef>> Mapping =
422
+ OptionEnumMapping<T>::getEnumMapping ();
409
423
auto Iter = llvm::find_if (
410
- Mapping, [&](const std::pair<StringRef, T > &NameAndEnum) {
411
- return NameAndEnum.second == Value;
424
+ Mapping, [&](const std::pair<T, StringRef > &NameAndEnum) {
425
+ return NameAndEnum.first == Value;
412
426
});
413
427
assert (Iter != Mapping.end () && " Unknown Case Value" );
414
- store (Options, LocalName, Iter->first );
428
+ store (Options, LocalName, Iter->second );
415
429
}
416
430
417
431
private:
418
- using NameAndValue = std::pair<StringRef, int64_t >;
432
+ using NameAndValue = std::pair<int64_t , StringRef >;
419
433
420
434
llvm::Expected<int64_t > getEnumInt (StringRef LocalName,
421
435
ArrayRef<NameAndValue> Mapping,
422
436
bool CheckGlobal, bool IgnoreCase);
423
437
424
438
template <typename T>
425
439
std::enable_if_t <std::is_enum<T>::value, std::vector<NameAndValue>>
426
- typeEraseMapping (ArrayRef<std::pair<StringRef, T>> Mapping) {
440
+ typeEraseMapping () {
441
+ ArrayRef<std::pair<T, StringRef>> Mapping =
442
+ OptionEnumMapping<T>::getEnumMapping ();
427
443
std::vector<NameAndValue> Result;
428
444
Result.reserve (Mapping.size ());
429
445
for (auto &MappedItem : Mapping) {
430
- Result.emplace_back (MappedItem.first ,
431
- static_cast < int64_t >( MappedItem.second ) );
446
+ Result.emplace_back (static_cast < int64_t >( MappedItem.first ) ,
447
+ MappedItem.second );
432
448
}
433
449
return Result;
434
450
}
0 commit comments