carlosgalvezp created this revision. Herald added subscribers: PiotrZSL, xazax.hun. Herald added a reviewer: njames93. Herald added a project: All. carlosgalvezp requested review of this revision. Herald added a project: clang-tools-extra. Herald added a subscriber: cfe-commits.
Fixes https://github.com/llvm/llvm-project/issues/51428 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D147876 Files: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp Index: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -70,7 +70,8 @@ NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap) { Options.reserve(OptionMap.size()); for (const auto &KeyValue : OptionMap) - Options.emplace_back(std::string(KeyValue.getKey()), KeyValue.getValue().Value); + Options.emplace_back(std::string(KeyValue.getKey()), + KeyValue.getValue().Value); } ClangTidyOptions::OptionMap denormalize(IO &) { ClangTidyOptions::OptionMap Map; @@ -117,10 +118,58 @@ } } +struct ChecksVariant { + std::optional<std::string> AsString; + std::optional<std::vector<std::string>> 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<Input &>(IO); + + if (isa<ScalarNode>(I.getCurrentNode()) || + isa<BlockScalarNode>(I.getCurrentNode())) { + Checks.AsString = std::string(); + yamlize(IO, *Checks.AsString, true, Ctx); + } else if (isa<SequenceNode>(I.getCurrentNode())) { + Checks.AsVector = std::vector<std::string>(); + yamlize(IO, *Checks.AsVector, true, Ctx); + } else { + IO.setError("expected string or sequence"); + } + } +} + +static void mapChecks(IO &IO, std::optional<std::string> &Checks) { + if (IO.outputting()) { + // Output as a string + IO.mapOptional("Checks", Checks); + } else { + // Input as either a string or a list + ChecksVariant ChecksAsVariant; + IO.mapOptional("Checks", ChecksAsVariant); + + // If we got the input as string, assign directly + if (ChecksAsVariant.AsString) { + Checks = ChecksAsVariant.AsString; + } + // If we got the input as a list, concatenate the items to create string + else if (ChecksAsVariant.AsVector) { + Checks = std::string(); + for (std::string const &check : *ChecksAsVariant.AsVector) { + *Checks += check + ","; + } + } + } +} + template <> struct MappingTraits<ClangTidyOptions> { 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",
Index: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -70,7 +70,8 @@ NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap) { Options.reserve(OptionMap.size()); for (const auto &KeyValue : OptionMap) - Options.emplace_back(std::string(KeyValue.getKey()), KeyValue.getValue().Value); + Options.emplace_back(std::string(KeyValue.getKey()), + KeyValue.getValue().Value); } ClangTidyOptions::OptionMap denormalize(IO &) { ClangTidyOptions::OptionMap Map; @@ -117,10 +118,58 @@ } } +struct ChecksVariant { + std::optional<std::string> AsString; + std::optional<std::vector<std::string>> 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<Input &>(IO); + + if (isa<ScalarNode>(I.getCurrentNode()) || + isa<BlockScalarNode>(I.getCurrentNode())) { + Checks.AsString = std::string(); + yamlize(IO, *Checks.AsString, true, Ctx); + } else if (isa<SequenceNode>(I.getCurrentNode())) { + Checks.AsVector = std::vector<std::string>(); + yamlize(IO, *Checks.AsVector, true, Ctx); + } else { + IO.setError("expected string or sequence"); + } + } +} + +static void mapChecks(IO &IO, std::optional<std::string> &Checks) { + if (IO.outputting()) { + // Output as a string + IO.mapOptional("Checks", Checks); + } else { + // Input as either a string or a list + ChecksVariant ChecksAsVariant; + IO.mapOptional("Checks", ChecksAsVariant); + + // If we got the input as string, assign directly + if (ChecksAsVariant.AsString) { + Checks = ChecksAsVariant.AsString; + } + // If we got the input as a list, concatenate the items to create string + else if (ChecksAsVariant.AsVector) { + Checks = std::string(); + for (std::string const &check : *ChecksAsVariant.AsVector) { + *Checks += check + ","; + } + } + } +} + template <> struct MappingTraits<ClangTidyOptions> { 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",
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits