mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
features: centralise requirement logic
This has room for conflicting features in future which will be used with the OIL implementation. For now it makes it much easier to add requirements.
This commit is contained in:
parent
2d32a30bb9
commit
3a2cef0372
@ -15,8 +15,12 @@
|
||||
*/
|
||||
#include "Features.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace oi::detail {
|
||||
@ -57,6 +61,22 @@ std::string_view featureHelp(Feature f) {
|
||||
}
|
||||
}
|
||||
|
||||
std::span<const Feature> requirements(Feature f) {
|
||||
switch (f) {
|
||||
case Feature::TypedDataSegment:
|
||||
static constexpr std::array tds = {Feature::TypeGraph};
|
||||
return tds;
|
||||
case Feature::TreeBuilderTypeChecking:
|
||||
static constexpr std::array tc = {Feature::TypedDataSegment};
|
||||
return tc;
|
||||
case Feature::TreeBuilderV2:
|
||||
static constexpr std::array tb2 = {Feature::TreeBuilderTypeChecking};
|
||||
return tb2;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Feature featureFromStr(std::string_view str) {
|
||||
@ -101,4 +121,32 @@ void featuresHelp(std::ostream& out) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<FeatureSet> handleFeatureConflicts(FeatureSet enabled,
|
||||
const FeatureSet& disabled) {
|
||||
FeatureSet toCheck = enabled;
|
||||
while (toCheck.any()) {
|
||||
for (const auto f : allFeatures) {
|
||||
if (!toCheck[f])
|
||||
continue;
|
||||
toCheck[f] = false;
|
||||
|
||||
for (const auto r : requirements(f)) {
|
||||
if (enabled[r])
|
||||
continue;
|
||||
if (disabled[r]) {
|
||||
LOG(ERROR) << featureToStr(f) << " feature requires "
|
||||
<< featureToStr(r) << "but it was explicitly disabled!";
|
||||
return std::nullopt;
|
||||
}
|
||||
enabled[r] = true;
|
||||
toCheck[r] = true;
|
||||
LOG(WARNING) << featureToStr(f) << " feature requires "
|
||||
<< featureToStr(r) << ", enabling it now.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
} // namespace oi::detail
|
||||
|
@ -16,6 +16,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <string_view>
|
||||
|
||||
@ -45,10 +46,6 @@ enum class Feature {
|
||||
#undef X
|
||||
};
|
||||
|
||||
Feature featureFromStr(std::string_view);
|
||||
const char* featureToStr(Feature);
|
||||
void featuresHelp(std::ostream& out);
|
||||
|
||||
constexpr std::array allFeatures = {
|
||||
#define X(name, _) Feature::name,
|
||||
OI_FEATURE_LIST
|
||||
@ -58,4 +55,10 @@ constexpr std::array allFeatures = {
|
||||
// Use "size+1" to account for UnknownFeature"
|
||||
using FeatureSet = EnumBitset<Feature, allFeatures.size() + 1>;
|
||||
|
||||
Feature featureFromStr(std::string_view);
|
||||
const char* featureToStr(Feature);
|
||||
void featuresHelp(std::ostream& out);
|
||||
std::optional<FeatureSet> handleFeatureConflicts(FeatureSet enabled,
|
||||
const FeatureSet& disabled);
|
||||
|
||||
} // namespace oi::detail
|
||||
|
@ -172,39 +172,16 @@ std::optional<FeatureSet> processConfigFile(
|
||||
}
|
||||
}
|
||||
|
||||
FeatureSet featuresSet;
|
||||
FeatureSet enabledFeatures;
|
||||
FeatureSet disabledFeatures;
|
||||
for (auto [k, v] : featureMap) {
|
||||
if (v) {
|
||||
featuresSet[k] = true;
|
||||
enabledFeatures[k] = true;
|
||||
} else {
|
||||
disabledFeatures[k] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (featuresSet[Feature::TreeBuilderTypeChecking] &&
|
||||
!featuresSet[Feature::TypedDataSegment]) {
|
||||
if (auto search = featureMap.find(Feature::TypedDataSegment);
|
||||
search != featureMap.end() && !search->second) {
|
||||
LOG(ERROR) << "TreeBuilderTypeChecking feature requires TypedDataSegment "
|
||||
"feature to be enabled but it was explicitly disabled!";
|
||||
return {};
|
||||
}
|
||||
featuresSet[Feature::TypedDataSegment] = true;
|
||||
LOG(WARNING) << "TreeBuilderTypeChecking feature requires TypedDataSegment "
|
||||
"feature to be enabled, enabling now.";
|
||||
}
|
||||
if (featuresSet[Feature::TypedDataSegment] &&
|
||||
!featuresSet[Feature::TypeGraph]) {
|
||||
if (auto search = featureMap.find(Feature::TypeGraph);
|
||||
search != featureMap.end() && !search->second) {
|
||||
LOG(ERROR) << "TypedDataSegment feature requires TypeGraph feature to be "
|
||||
"enabled but it was explicitly disabled!";
|
||||
return {};
|
||||
}
|
||||
featuresSet[Feature::TypeGraph] = true;
|
||||
LOG(WARNING) << "TypedDataSegment feature requires TypeGraph feature to be "
|
||||
"enabled, enabling now.";
|
||||
}
|
||||
|
||||
return featuresSet;
|
||||
return handleFeatureConflicts(enabledFeatures, disabledFeatures);
|
||||
}
|
||||
|
||||
} // namespace oi::detail::utils
|
||||
|
Loading…
Reference in New Issue
Block a user