cmJSONHelpers.h: Add generic predicate checking helper

And use it in the `cmCMakePresetsGraphReadJSON.cxx` to check
presets schema version in the declarative way.

Co-authored-by: Martin Duffy <martin.duffy@kitware.com>
This commit is contained in:
Alex Turbov
2024-08-13 22:39:21 +04:00
parent 503a73b183
commit 0b334e5bfb
6 changed files with 35 additions and 8 deletions

View File

@@ -238,6 +238,16 @@ void TRACE_UNSUPPORTED(cmJSONState* state)
state->AddError("File version must be 7 or higher for trace preset support");
}
JsonErrors::ErrorGenerator UNRECOGNIZED_VERSION_RANGE(int min, int max)
{
return [min, max](const Json::Value* value, cmJSONState* state) -> void {
state->AddErrorAtValue(cmStrCat("Unrecognized \"version\" ",
value->asString(), ": must be >=", min,
" and <=", max),
value);
};
}
JsonErrors::ErrorGenerator UNRECOGNIZED_CMAKE_VERSION(
const std::string& version, int current, int required)
{

View File

@@ -94,6 +94,8 @@ void CTEST_JUNIT_UNSUPPORTED(cmJSONState* state);
void TRACE_UNSUPPORTED(cmJSONState* state);
JsonErrors::ErrorGenerator UNRECOGNIZED_VERSION_RANGE(int min, int max);
JsonErrors::ErrorGenerator UNRECOGNIZED_CMAKE_VERSION(
const std::string& version, int current, int required);

View File

@@ -256,9 +256,14 @@ auto const VersionIntHelper =
auto const VersionHelper = JSONHelperBuilder::Required<int>(
cmCMakePresetsErrors::NO_VERSION, VersionIntHelper);
auto const VersionRangeHelper = JSONHelperBuilder::Checked<int>(
cmCMakePresetsErrors::UNRECOGNIZED_VERSION_RANGE(MIN_VERSION, MAX_VERSION),
VersionHelper,
[](const int v) -> bool { return v >= MIN_VERSION && v <= MAX_VERSION; });
auto const RootVersionHelper =
JSONHelperBuilder::Object<int>(cmCMakePresetsErrors::INVALID_ROOT_OBJECT)
.Bind("version"_s, VersionHelper, false);
.Bind("version"_s, VersionRangeHelper, false);
auto const CMakeVersionUIntHelper =
JSONHelperBuilder::UInt(cmCMakePresetsErrors::INVALID_VERSION);
@@ -481,11 +486,6 @@ bool cmCMakePresetsGraph::ReadJSONFile(const std::string& filename,
if ((result = RootVersionHelper(v, &root, &parseState)) != true) {
return result;
}
if (v < MIN_VERSION || v > MAX_VERSION) {
cmCMakePresetsErrors::UNRECOGNIZED_VERSION(&root["version"],
&this->parseState);
return false;
}
// Support for build and test presets added in version 2.
if (v < 2) {

View File

@@ -390,4 +390,19 @@ struct cmJSONHelperBuilder
return func(out, value, state);
};
}
template <typename T, typename F, typename P>
static cmJSONHelper<T> Checked(const JsonErrors::ErrorGenerator& error,
F func, P predicate)
{
return [error, func, predicate](T& out, const Json::Value* value,
cmJSONState* state) -> bool {
bool result = func(out, value, state);
if (result && !predicate(out)) {
error(value, state);
result = false;
}
return result;
};
}
};

View File

@@ -1,5 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/HighVersion:
Error: @2,14: Unrecognized "version" field
Error: @2,14: Unrecognized "version" 1000: must be >=1 and <=10
"version": 1000,
\^$

View File

@@ -1,5 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/LowVersion:
Error: @2,14: Unrecognized "version" field
Error: @2,14: Unrecognized "version" 0: must be >=1 and <=10
"version": 0,
\^