diff options
author | piegames <git@piegames.de> | 2024-07-13 05:24:41 +0200 |
---|---|---|
committer | piegames <git@piegames.de> | 2024-08-17 19:47:51 +0200 |
commit | 49d61b2e4bf338042364c85d3c2ead0b33963e65 (patch) | |
tree | 09ffba6841df5a3990aa2d1c6bb9e19e0e355b14 /src/libutil/deprecated-features.cc | |
parent | 1c080a8239f1be5a61d9fb2121ca958542ec183f (diff) |
libexpr: Introduce Deprecated features
They are like experimental features, but opt-in instead of opt-out. They
will allow us to gracefully remove language features. See #437
Change-Id: I9ca04cc48e6926750c4d622c2b229b25cc142c42
Diffstat (limited to 'src/libutil/deprecated-features.cc')
-rw-r--r-- | src/libutil/deprecated-features.cc | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/libutil/deprecated-features.cc b/src/libutil/deprecated-features.cc new file mode 100644 index 000000000..7c59d8598 --- /dev/null +++ b/src/libutil/deprecated-features.cc @@ -0,0 +1,108 @@ +#include "deprecated-features.hh" +// Required for instances of to_json and from_json for DeprecatedFeature +#include "deprecated-features-json.hh" +#include "strings.hh" + +#include "nlohmann/json.hpp" + +namespace nix { + +struct DeprecatedFeatureDetails +{ + DeprecatedFeature tag; + std::string_view name; + std::string_view description; +}; + +/** + * If two different PRs both add a deprecated feature, and we just + * used a number for this, we *woudln't* get merge conflict and the + * counter will be incremented once instead of twice, causing a build + * failure. + * + * By instead defining this instead as 1 + the bottom deprecated + * feature, we either have no issue at all if few features are not added + * at the end of the list, or a proper merge conflict if they are. + */ +constexpr size_t numDepFeatures = 0; + +constexpr std::array<DeprecatedFeatureDetails, numDepFeatures> depFeatureDetails = {{ +}}; + +static_assert( + []() constexpr { + for (auto [index, feature] : enumerate(depFeatureDetails)) + if (index != (size_t)feature.tag) + return false; + return true; + }(), + "array order does not match enum tag order"); + +const std::optional<DeprecatedFeature> parseDeprecatedFeature(const std::string_view & name) +{ + using ReverseDepMap = std::map<std::string_view, DeprecatedFeature>; + + static std::unique_ptr<ReverseDepMap> reverseDepMap = []() { + auto reverseDepMap = std::make_unique<ReverseDepMap>(); + for (auto & depFeature : depFeatureDetails) + (*reverseDepMap)[depFeature.name] = depFeature.tag; + return reverseDepMap; + }(); + + if (auto feature = get(*reverseDepMap, name)) + return *feature; + else + return std::nullopt; +} + +std::string_view showDeprecatedFeature(const DeprecatedFeature tag) +{ + assert((size_t)tag < depFeatureDetails.size()); + return depFeatureDetails[(size_t)tag].name; +} + +nlohmann::json documentDeprecatedFeatures() +{ + StringMap res; + for (auto & depFeature : depFeatureDetails) + res[std::string { depFeature.name }] = + trim(stripIndentation(depFeature.description)); + return (nlohmann::json) res; +} + +std::set<DeprecatedFeature> parseDeprecatedFeatures(const std::set<std::string> & rawFeatures) +{ + std::set<DeprecatedFeature> res; + for (auto & rawFeature : rawFeatures) + if (auto feature = parseDeprecatedFeature(rawFeature)) + res.insert(*feature); + return res; +} + +MissingDeprecatedFeature::MissingDeprecatedFeature(DeprecatedFeature feature) + : Error("Lix feature '%1%' is deprecated and should not be used anymore; use '--extra-deprecated-features %1%' to disable this error", showDeprecatedFeature(feature)) + , missingFeature(feature) +{} + +std::ostream & operator <<(std::ostream & str, const DeprecatedFeature & feature) +{ + return str << showDeprecatedFeature(feature); +} + +void to_json(nlohmann::json & j, const DeprecatedFeature & feature) +{ + j = showDeprecatedFeature(feature); +} + +void from_json(const nlohmann::json & j, DeprecatedFeature & feature) +{ + const std::string input = j; + const auto parsed = parseDeprecatedFeature(input); + + if (parsed.has_value()) + feature = *parsed; + else + throw Error("Unknown deprecated feature '%s' in JSON input", input); +} + +} |