diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp index 84defccde513e..afa88cb4f80d1 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -117,10 +117,48 @@ void yamlize(IO &IO, ClangTidyOptions::OptionMap &Options, bool, } } +struct ChecksVariant { + std::optional AsString; + std::optional> AsVector; +}; + +template <> +void yamlize(IO &IO, ChecksVariant &Checks, bool, EmptyContext &Ctx) { + if (!IO.outputting()) { + // Special case for reading from YAML + // Must support reading from both a string or a list + Input &I = reinterpret_cast(IO); + if (isa(I.getCurrentNode())) { + Checks.AsString = std::string(); + yamlize(IO, *Checks.AsString, true, Ctx); + } else if (isa(I.getCurrentNode())) { + Checks.AsVector = std::vector(); + yamlize(IO, *Checks.AsVector, true, Ctx); + } else { + IO.setError("expected string or sequence"); + } + } +} + +static void mapChecks(IO &IO, std::optional &Checks) { + if (IO.outputting()) { + // Output always a string + IO.mapOptional("Checks", Checks); + } else { + // Input as either a string or a list + ChecksVariant ChecksAsVariant; + IO.mapOptional("Checks", ChecksAsVariant); + if (ChecksAsVariant.AsString) + Checks = ChecksAsVariant.AsString; + else if (ChecksAsVariant.AsVector) + Checks = llvm::join(*ChecksAsVariant.AsVector, ","); + } +} + template <> struct MappingTraits { static void mapping(IO &IO, ClangTidyOptions &Options) { bool Ignored = false; - IO.mapOptional("Checks", Options.Checks); + mapChecks(IO, Options.Checks); IO.mapOptional("WarningsAsErrors", Options.WarningsAsErrors); IO.mapOptional("HeaderFileExtensions", Options.HeaderFileExtensions); IO.mapOptional("ImplementationFileExtensions", diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index 09162995a0974..2bed6dfda3a0a 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -52,7 +52,9 @@ Configuration files: options. Example: CheckOptions: some-check.SomeOption: 'some value' - Checks - Same as '--checks'. + Checks - Same as '--checks'. Additionally, the list of + globs can be specified as a list instead of a + string. ExtraArgs - Same as '--extra-args'. ExtraArgsBefore - Same as '--extra-args-before'. FormatStyle - Same as '--format-style'. diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index cb10385d8e87f..9c5b86fc8606d 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -98,6 +98,9 @@ Improvements to clang-tidy `ImplementationFileExtensions`, replacing the check-local options of the same name. +- Support specifying `Checks` as a YAML list in the `.clang-tidy` configuration + file. + New checks ^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst index 899c3ea6ed540..444d03d6cb08a 100644 --- a/clang-tools-extra/docs/clang-tidy/index.rst +++ b/clang-tools-extra/docs/clang-tidy/index.rst @@ -259,7 +259,9 @@ An overview of all the command-line options: options. Example: CheckOptions: some-check.SomeOption: 'some value' - Checks - Same as '--checks'. + Checks - Same as '--checks'. Additionally, the list of + globs can be specified as a list instead of a + string. ExtraArgs - Same as '--extra-args'. ExtraArgsBefore - Same as '--extra-args-before'. FormatStyle - Same as '--format-style'. diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-file/config-file-list-bracket b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-file/config-file-list-bracket new file mode 100644 index 0000000000000..d2bfe57880c2b --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-file/config-file-list-bracket @@ -0,0 +1,6 @@ +Checks: [ + "-*", + "hicpp-uppercase-literal-suffix", + "hicpp-use-auto", + "hicpp-use-emplace", +] diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-file/config-file-list-dash b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-file/config-file-list-dash new file mode 100644 index 0000000000000..ce1c88d1148cb --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-file/config-file-list-dash @@ -0,0 +1,5 @@ +Checks: + - "-*" + - "hicpp-uppercase-literal-suffix" + - "hicpp-use-auto" + - "hicpp-use-emplace" diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/config-file.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/config-file.cpp index 16b216a1d4f69..b929fb15193d1 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/config-file.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/config-file.cpp @@ -6,3 +6,15 @@ // CHECK-SPACES-NEXT: hicpp-use-auto // CHECK-SPACES-NEXT: hicpp-use-emplace // CHECK-SPACES-EMPTY: +// RUN: clang-tidy -config-file=%S/Inputs/config-file/config-file-list-dash --list-checks -- | FileCheck %s -check-prefix=CHECK-LIST-DASH +// CHECK-LIST-DASH: Enabled checks: +// CHECK-LIST-DASH-NEXT: hicpp-uppercase-literal-suffix +// CHECK-LIST-DASH-NEXT: hicpp-use-auto +// CHECK-LIST-DASH-NEXT: hicpp-use-emplace +// CHECK-LIST-DASH-EMPTY: +// RUN: clang-tidy -config-file=%S/Inputs/config-file/config-file-list-bracket --list-checks -- | FileCheck %s -check-prefix=CHECK-LIST-BRACKET +// CHECK-LIST-BRACKET: Enabled checks: +// CHECK-LIST-BRACKET-NEXT: hicpp-uppercase-literal-suffix +// CHECK-LIST-BRACKET-NEXT: hicpp-use-auto +// CHECK-LIST-BRACKET-NEXT: hicpp-use-emplace +// CHECK-LIST-BRACKET-EMPTY: