aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/deprecated-features.cc
diff options
context:
space:
mode:
authorpiegames <git@piegames.de>2024-07-13 05:24:41 +0200
committerpiegames <git@piegames.de>2024-08-17 19:47:51 +0200
commit49d61b2e4bf338042364c85d3c2ead0b33963e65 (patch)
tree09ffba6841df5a3990aa2d1c6bb9e19e0e355b14 /src/libutil/deprecated-features.cc
parent1c080a8239f1be5a61d9fb2121ca958542ec183f (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.cc108
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);
+}
+
+}