presets: Improve JSON parser and error messages

This commit is contained in:
Martin Duffy
2023-03-29 10:41:19 -04:00
committed by Brad King
parent 6b08358e17
commit 19305afd8a
114 changed files with 1937 additions and 1220 deletions
+3
View File
@@ -140,6 +140,7 @@ add_library(
cmCLocaleEnvironmentScope.cxx
cmCMakePath.h
cmCMakePath.cxx
cmCMakePresetErrors.h
cmCMakePresetsGraph.cxx
cmCMakePresetsGraph.h
cmCMakePresetsGraphInternal.h
@@ -331,6 +332,8 @@ add_library(
cmInstallDirectoryGenerator.h
cmInstallDirectoryGenerator.cxx
cmJSONHelpers.h
cmJSONState.cxx
cmJSONState.h
cmLDConfigLDConfigTool.cxx
cmLDConfigLDConfigTool.h
cmLDConfigTool.cxx
+4 -3
View File
@@ -28,6 +28,7 @@
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmJSONState.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
@@ -265,11 +266,11 @@ int main(int argc, char const* const* argv)
cmCMakePresetsGraph presetsGraph;
auto result = presetsGraph.ReadProjectPresets(workingDirectory);
if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
if (result != true) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Could not read presets from "
<< workingDirectory << ": "
<< cmCMakePresetsGraph::ResultToString(result) << '\n');
<< workingDirectory << ":"
<< presetsGraph.parseState.GetErrorMessage() << '\n');
return 1;
}
+42 -106
View File
@@ -10,17 +10,14 @@
#include <cmext/string_view>
#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include "cmJSONHelpers.h"
namespace {
using JSONHelperBuilder =
cmJSONHelperBuilder<cmCTestResourceSpec::ReadFileResult>;
using JSONHelperBuilder = cmJSONHelperBuilder;
const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" };
const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" };
@@ -36,165 +33,104 @@ struct TopVersion
};
auto const VersionFieldHelper =
JSONHelperBuilder::Int(cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_VERSION);
JSONHelperBuilder::Int(cmCTestResourceSpecErrors::INVALID_VERSION);
auto const VersionHelper = JSONHelperBuilder::Required<Version>(
cmCTestResourceSpec::ReadFileResult::NO_VERSION,
JSONHelperBuilder::Object<Version>(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_VERSION)
cmCTestResourceSpecErrors::NO_VERSION,
JSONHelperBuilder::Object<Version>()
.Bind("major"_s, &Version::Major, VersionFieldHelper)
.Bind("minor"_s, &Version::Minor, VersionFieldHelper));
auto const RootVersionHelper =
JSONHelperBuilder::Object<TopVersion>(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_ROOT)
.Bind("version"_s, &TopVersion::Version, VersionHelper, false);
auto const RootVersionHelper = JSONHelperBuilder::Object<TopVersion>().Bind(
"version"_s, &TopVersion::Version, VersionHelper, false);
cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out,
const Json::Value* value)
bool ResourceIdHelper(std::string& out, const Json::Value* value,
cmJSONState* state)
{
auto result = JSONHelperBuilder::String(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)(out, value);
if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
return result;
if (!JSONHelperBuilder::String(cmCTestResourceSpecErrors::INVALID_RESOURCE)(
out, value, state)) {
return false;
}
cmsys::RegularExpressionMatch match;
if (!IdRegex.find(out.c_str(), match)) {
return cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE;
cmCTestResourceSpecErrors::INVALID_RESOURCE(value, state);
return false;
}
return cmCTestResourceSpec::ReadFileResult::READ_OK;
return true;
}
auto const ResourceHelper =
JSONHelperBuilder::Object<cmCTestResourceSpec::Resource>(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)
JSONHelperBuilder::Object<cmCTestResourceSpec::Resource>()
.Bind("id"_s, &cmCTestResourceSpec::Resource::Id, ResourceIdHelper)
.Bind("slots"_s, &cmCTestResourceSpec::Resource::Capacity,
JSONHelperBuilder::UInt(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, 1),
false);
.Bind(
"slots"_s, &cmCTestResourceSpec::Resource::Capacity,
JSONHelperBuilder::UInt(cmCTestResourceSpecErrors::INVALID_RESOURCE, 1),
false);
auto const ResourceListHelper =
JSONHelperBuilder::Vector<cmCTestResourceSpec::Resource>(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE,
ResourceHelper);
cmCTestResourceSpecErrors::INVALID_RESOURCE_TYPE, ResourceHelper);
auto const ResourceMapHelper =
JSONHelperBuilder::MapFilter<std::vector<cmCTestResourceSpec::Resource>>(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC,
ResourceListHelper, [](const std::string& key) -> bool {
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC, ResourceListHelper,
[](const std::string& key) -> bool {
cmsys::RegularExpressionMatch match;
return IdentifierRegex.find(key.c_str(), match);
});
auto const SocketSetHelper = JSONHelperBuilder::Vector<
std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceMapHelper);
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC, ResourceMapHelper);
cmCTestResourceSpec::ReadFileResult SocketHelper(
cmCTestResourceSpec::Socket& out, const Json::Value* value)
bool SocketHelper(cmCTestResourceSpec::Socket& out, const Json::Value* value,
cmJSONState* state)
{
std::vector<
std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>
sockets;
cmCTestResourceSpec::ReadFileResult result = SocketSetHelper(sockets, value);
if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
return result;
if (!SocketSetHelper(sockets, value, state)) {
return false;
}
if (sockets.size() > 1) {
return cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC;
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC(value, state);
return false;
}
if (sockets.empty()) {
out.Resources.clear();
} else {
out.Resources = std::move(sockets[0]);
}
return cmCTestResourceSpec::ReadFileResult::READ_OK;
return true;
}
auto const LocalRequiredHelper =
JSONHelperBuilder::Required<cmCTestResourceSpec::Socket>(
cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, SocketHelper);
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC, SocketHelper);
auto const RootHelper = JSONHelperBuilder::Object<cmCTestResourceSpec>(
cmCTestResourceSpec::ReadFileResult::READ_OK,
cmCTestResourceSpec::ReadFileResult::INVALID_ROOT)
.Bind("local", &cmCTestResourceSpec::LocalSocket,
LocalRequiredHelper, false);
auto const RootHelper = JSONHelperBuilder::Object<cmCTestResourceSpec>().Bind(
"local", &cmCTestResourceSpec::LocalSocket, LocalRequiredHelper, false);
}
cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile(
const std::string& filename)
bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename)
{
cmsys::ifstream fin(filename.c_str());
if (!fin) {
return ReadFileResult::FILE_NOT_FOUND;
}
Json::Value root;
Json::CharReaderBuilder builder;
if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
return ReadFileResult::JSON_PARSE_ERROR;
this->parseState = cmJSONState(filename, &root);
if (!this->parseState.errors.empty()) {
return false;
}
TopVersion version;
ReadFileResult result;
if ((result = RootVersionHelper(version, &root)) !=
ReadFileResult::READ_OK) {
bool result;
if ((result = RootVersionHelper(version, &root, &parseState)) != true) {
return result;
}
if (version.Version.Major != 1 || version.Version.Minor != 0) {
return ReadFileResult::UNSUPPORTED_VERSION;
return false;
}
return RootHelper(*this, &root);
}
const char* cmCTestResourceSpec::ResultToString(ReadFileResult result)
{
switch (result) {
case ReadFileResult::READ_OK:
return "OK";
case ReadFileResult::FILE_NOT_FOUND:
return "File not found";
case ReadFileResult::JSON_PARSE_ERROR:
return "JSON parse error";
case ReadFileResult::INVALID_ROOT:
return "Invalid root object";
case ReadFileResult::NO_VERSION:
return "No version specified";
case ReadFileResult::INVALID_VERSION:
return "Invalid version object";
case ReadFileResult::UNSUPPORTED_VERSION:
return "Unsupported version";
case ReadFileResult::INVALID_SOCKET_SPEC:
return "Invalid socket object";
case ReadFileResult::INVALID_RESOURCE_TYPE:
return "Invalid resource type object";
case ReadFileResult::INVALID_RESOURCE:
return "Invalid resource object";
default:
return "Unknown";
}
return RootHelper(*this, &root, &parseState);
}
bool cmCTestResourceSpec::operator==(const cmCTestResourceSpec& other) const
+43 -16
View File
@@ -8,6 +8,12 @@
#include <string>
#include <vector>
#include "cmJSONState.h"
namespace Json {
class Value;
}
class cmCTestResourceSpec
{
public:
@@ -31,24 +37,45 @@ public:
};
Socket LocalSocket;
cmJSONState parseState;
enum class ReadFileResult
{
READ_OK,
FILE_NOT_FOUND,
JSON_PARSE_ERROR,
INVALID_ROOT,
NO_VERSION,
INVALID_VERSION,
UNSUPPORTED_VERSION,
INVALID_SOCKET_SPEC, // Can't be INVALID_SOCKET due to a Windows macro
INVALID_RESOURCE_TYPE,
INVALID_RESOURCE,
};
ReadFileResult ReadFromJSONFile(const std::string& filename);
static const char* ResultToString(ReadFileResult result);
bool ReadFromJSONFile(const std::string& filename);
bool operator==(const cmCTestResourceSpec& other) const;
bool operator!=(const cmCTestResourceSpec& other) const;
};
namespace cmCTestResourceSpecErrors {
const auto FILE_NOT_FOUND = [](const Json::Value*, cmJSONState* state) {
state->AddError("File not found");
};
const auto JSON_PARSE_ERROR = [](const Json::Value* value,
cmJSONState* state) {
state->AddErrorAtValue("JSON parse error", value);
};
const auto INVALID_ROOT = [](const Json::Value* value, cmJSONState* state) {
state->AddErrorAtValue("Invalid root object", value);
};
const auto NO_VERSION = [](const Json::Value* value, cmJSONState* state) {
state->AddErrorAtValue("No version specified", value);
};
const auto INVALID_VERSION = [](const Json::Value* value, cmJSONState* state) {
state->AddErrorAtValue("Invalid version object", value);
};
const auto UNSUPPORTED_VERSION = [](const Json::Value* value,
cmJSONState* state) {
state->AddErrorAtValue("Unsupported version", value);
};
const auto INVALID_SOCKET_SPEC = [](const Json::Value* value,
cmJSONState* state) {
state->AddErrorAtValue("Invalid socket object", value);
};
const auto INVALID_RESOURCE_TYPE = [](const Json::Value* value,
cmJSONState* state) {
state->AddErrorAtValue("Invalid resource type object", value);
};
const auto INVALID_RESOURCE = [](const Json::Value* value,
cmJSONState* state) {
state->AddErrorAtValue("Invalid resource object", value);
};
}
+3 -3
View File
@@ -37,6 +37,7 @@
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmJSONState.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
@@ -1346,12 +1347,11 @@ bool cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
}
if (!this->ResourceSpecFile.empty()) {
this->UseResourceSpec = true;
auto result = this->ResourceSpec.ReadFromJSONFile(this->ResourceSpecFile);
if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
if (!this->ResourceSpec.ReadFromJSONFile(this->ResourceSpecFile)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Could not read/parse resource spec file "
<< this->ResourceSpecFile << ": "
<< cmCTestResourceSpec::ResultToString(result)
<< this->ResourceSpec.parseState.GetErrorMessage()
<< std::endl);
return false;
}
+3 -4
View File
@@ -732,13 +732,12 @@ void CMakeSetupDialog::updatePreset(const QString& name)
}
}
void CMakeSetupDialog::showPresetLoadError(
const QString& dir, cmCMakePresetsGraph::ReadFileResult result)
void CMakeSetupDialog::showPresetLoadError(const QString& dir,
const QString& message)
{
QMessageBox::warning(
this, "Error Reading CMake Presets",
QString("Could not read presets from %1: %2")
.arg(dir, cmCMakePresetsGraph::ResultToString(result)));
QString("Could not read presets from %1: %2").arg(dir, message));
}
void CMakeSetupDialog::doBinaryBrowse()
+1 -2
View File
@@ -59,8 +59,7 @@ protected slots:
void updateBinaryDirectory(const QString& dir);
void updatePresets(const QVector<QCMakePreset>& presets);
void updatePreset(const QString& name);
void showPresetLoadError(const QString& dir,
cmCMakePresetsGraph::ReadFileResult result);
void showPresetLoadError(const QString& dir, const QString& message);
void showProgress(const QString& msg, float percent);
void setEnabledState(bool);
bool setupFirstConfigure();
+5 -4
View File
@@ -33,7 +33,6 @@ QCMake::QCMake(QObject* p)
qRegisterMetaType<QCMakePropertyList>();
qRegisterMetaType<QProcessEnvironment>();
qRegisterMetaType<QVector<QCMakePreset>>();
qRegisterMetaType<cmCMakePresetsGraph::ReadFileResult>();
cmSystemTools::DisableRunCommandOutput();
cmSystemTools::SetRunCommandHideConsole(true);
@@ -530,9 +529,11 @@ void QCMake::loadPresets()
{
auto result = this->CMakePresetsGraph.ReadProjectPresets(
this->SourceDirectory.toStdString(), true);
if (result != this->LastLoadPresetsResult &&
result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
emit this->presetLoadError(this->SourceDirectory, result);
if (result != this->LastLoadPresetsResult && !result) {
emit this->presetLoadError(
this->SourceDirectory,
QString::fromStdString(
this->CMakePresetsGraph.parseState.GetErrorMessage(false)));
}
this->LastLoadPresetsResult = result;
+2 -5
View File
@@ -60,7 +60,6 @@ using QCMakePropertyList = QList<QCMakeProperty>;
Q_DECLARE_METATYPE(QCMakeProperty)
Q_DECLARE_METATYPE(QCMakePropertyList)
Q_DECLARE_METATYPE(QProcessEnvironment)
Q_DECLARE_METATYPE(cmCMakePresetsGraph::ReadFileResult)
/// Qt API for CMake library.
/// Wrapper like class allows for easier integration with
@@ -158,8 +157,7 @@ signals:
/// signal when the selected preset changes
void presetChanged(const QString& name);
/// signal when there's an error reading the presets files
void presetLoadError(const QString& dir,
cmCMakePresetsGraph::ReadFileResult error);
void presetLoadError(const QString& dir, const QString& error);
/// signal when uninitialized warning changes
void warnUninitializedModeChanged(bool value);
/// signal for progress events
@@ -203,8 +201,7 @@ protected:
QString Toolset;
std::vector<cmake::GeneratorInfo> AvailableGenerators;
cmCMakePresetsGraph CMakePresetsGraph;
cmCMakePresetsGraph::ReadFileResult LastLoadPresetsResult =
cmCMakePresetsGraph::ReadFileResult::READ_OK;
bool LastLoadPresetsResult = true;
QString PresetName;
QString CMakeExecutable;
QAtomicInt InterruptFlag;
+242
View File
@@ -0,0 +1,242 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <cm3p/json/value.h>
#include "cmJSONHelpers.h"
#include "cmJSONState.h"
#include "cmStringAlgorithms.h"
namespace cmCMakePresetErrors {
const auto getPreset = [](cmJSONState* state) -> const Json::Value* {
if (state->parseStack.size() < 2) {
return nullptr;
}
std::string firstKey = state->parseStack[0].first;
if (firstKey == "configurePresets" || firstKey == "packagePresets" ||
firstKey == "buildPresets" || firstKey == "testPresets") {
return state->parseStack[1].second;
}
return nullptr;
};
const auto getPresetName = [](cmJSONState* state) -> std::string {
#if !defined(CMAKE_BOOTSTRAP)
const Json::Value* preset = getPreset(state);
if (preset != nullptr && preset->isMember("name")) {
return preset->operator[]("name").asString();
}
#endif
return "";
};
const auto getVariableName = [](cmJSONState* state) -> std::string {
std::string var = state->key_after("cacheVariables");
std::string errMsg = cmStrCat("variable \"", var, "\"");
errMsg = cmStrCat(errMsg, " for preset \"", getPresetName(state), "\"");
return errMsg;
};
const auto FILE_NOT_FOUND = [](const std::string& filename,
cmJSONState* state) -> void {
state->AddError(cmStrCat("File not found: ", filename));
};
const auto INVALID_ROOT = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue("Invalid root object", value);
};
const auto NO_VERSION = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue("No \"version\" field", value);
};
const auto INVALID_VERSION = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue("Invalid \"version\" field", value);
};
const auto UNRECOGNIZED_VERSION = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue("Unrecognized \"version\" field", value);
};
const auto INVALID_PRESETS = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue("Invalid \"configurePresets\" field", value);
};
const auto INVALID_PRESET = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue("Invalid preset", value);
};
const auto INVALID_PRESET_NAMED = [](const std::string& presetName,
cmJSONState* state) -> void {
state->AddError(cmStrCat("Invalid preset: \"", presetName, "\""));
};
const auto INVALID_VARIABLE = [](const Json::Value* value,
cmJSONState* state) -> void {
std::string var = cmCMakePresetErrors::getVariableName(state);
state->AddErrorAtValue(cmStrCat("Invalid CMake ", var), value);
};
const auto DUPLICATE_PRESETS = [](const std::string& presetName,
cmJSONState* state) -> void {
state->AddError(cmStrCat("Duplicate preset: \"", presetName, "\""));
};
const auto CYCLIC_PRESET_INHERITANCE = [](const std::string& presetName,
cmJSONState* state) -> void {
state->AddError(
cmStrCat("Cyclic preset inheritance for preset \"", presetName, "\""));
};
const auto INHERITED_PRESET_UNREACHABLE_FROM_FILE =
[](const std::string& presetName, cmJSONState* state) -> void {
state->AddError(cmStrCat("Inherited preset \"", presetName,
"\" is unreachable from preset's file"));
};
const auto CONFIGURE_PRESET_UNREACHABLE_FROM_FILE =
[](const std::string& presetName, cmJSONState* state) -> void {
state->AddError(cmStrCat("Configure preset \"", presetName,
"\" is unreachable from preset's file"));
};
const auto INVALID_MACRO_EXPANSION = [](const std::string& presetName,
cmJSONState* state) -> void {
state->AddError(cmStrCat("Invalid macro expansion in \"", presetName, "\""));
};
const auto BUILD_TEST_PRESETS_UNSUPPORTED = [](const Json::Value*,
cmJSONState* state) -> void {
state->AddError("File version must be 2 or higher for build and test preset "
"support");
};
const auto PACKAGE_PRESETS_UNSUPPORTED = [](const Json::Value*,
cmJSONState* state) -> void {
state->AddError(
"File version must be 6 or higher for package preset support");
};
const auto WORKFLOW_PRESETS_UNSUPPORTED = [](const Json::Value*,
cmJSONState* state) -> void {
state->AddError(
"File version must be 6 or higher for workflow preset support");
};
const auto INCLUDE_UNSUPPORTED = [](const Json::Value*,
cmJSONState* state) -> void {
state->AddError("File version must be 4 or higher for include support");
};
const auto INVALID_INCLUDE = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue("Invalid \"include\" field", value);
};
const auto INVALID_CONFIGURE_PRESET = [](const std::string& presetName,
cmJSONState* state) -> void {
state->AddError(
cmStrCat(R"(Invalid "configurePreset": ")", presetName, "\""));
};
const auto INSTALL_PREFIX_UNSUPPORTED = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue(
"File version must be 3 or higher for installDir preset "
"support",
value);
};
const auto CONDITION_UNSUPPORTED = [](cmJSONState* state) -> void {
state->AddError("File version must be 3 or higher for condition support");
};
const auto TOOLCHAIN_FILE_UNSUPPORTED = [](cmJSONState* state) -> void {
state->AddError("File version must be 3 or higher for toolchainFile preset "
"support");
};
const auto CYCLIC_INCLUDE = [](const std::string& file,
cmJSONState* state) -> void {
state->AddError(cmStrCat("Cyclic include among preset files: ", file));
};
const auto TEST_OUTPUT_TRUNCATION_UNSUPPORTED =
[](cmJSONState* state) -> void {
state->AddError("File version must be 5 or higher for testOutputTruncation "
"preset support");
};
const auto INVALID_WORKFLOW_STEPS = [](const std::string& workflowStep,
cmJSONState* state) -> void {
state->AddError(cmStrCat("Invalid workflow step \"", workflowStep, "\""));
};
const auto NO_WORKFLOW_STEPS = [](const std::string& presetName,
cmJSONState* state) -> void {
state->AddError(
cmStrCat("No workflow steps specified for \"", presetName, "\""));
};
const auto FIRST_WORKFLOW_STEP_NOT_CONFIGURE = [](const std::string& stepName,
cmJSONState* state) -> void {
state->AddError(cmStrCat("First workflow step \"", stepName,
"\" must be a configure step"));
};
const auto CONFIGURE_WORKFLOW_STEP_NOT_FIRST = [](const std::string& stepName,
cmJSONState* state) -> void {
state->AddError(cmStrCat("Configure workflow step \"", stepName,
"\" must be the first step"));
};
const auto WORKFLOW_STEP_UNREACHABLE_FROM_FILE =
[](const std::string& workflowStep, cmJSONState* state) -> void {
state->AddError(cmStrCat("Workflow step \"", workflowStep,
"\" is unreachable from preset's file"));
};
const auto CTEST_JUNIT_UNSUPPORTED = [](cmJSONState* state) -> void {
state->AddError(
"File version must be 6 or higher for CTest JUnit output support");
};
const auto UNRECOGNIZED_CMAKE_VERSION = [](const std::string& version,
int current, int required) {
return [version, current, required](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue(cmStrCat("\"cmakeMinimumRequired\" ", version,
" version ", required,
" must be less than ", current),
value);
};
};
const auto INVALID_PRESET_NAME = [](const Json::Value* value,
cmJSONState* state) -> void {
std::string errMsg = "Invalid Preset Name";
if (value && value->isConvertibleTo(Json::ValueType::stringValue) &&
!value->asString().empty()) {
errMsg = cmStrCat(errMsg, ": ", value->asString());
}
state->AddErrorAtValue(errMsg, value);
};
const auto INVALID_CONDITION = [](const Json::Value* value,
cmJSONState* state) -> void {
state->AddErrorAtValue(
cmStrCat("Invalid condition for preset \"", getPresetName(state), "\""),
value);
};
const auto INVALID_CONDITION_OBJECT =
[](JsonErrors::ObjectError errorType,
const Json::Value::Members& extraFields) {
return JsonErrors::INVALID_NAMED_OBJECT(
[](const Json::Value*, cmJSONState* state) -> std::string {
return cmStrCat(" condition for preset \"", getPresetName(state),
"\"");
})(errorType, extraFields);
};
const auto INVALID_VARIABLE_OBJECT =
[](JsonErrors::ObjectError errorType,
const Json::Value::Members& extraFields) {
return JsonErrors::INVALID_NAMED_OBJECT(
[](const Json::Value*, cmJSONState* state) -> std::string {
return getVariableName(state);
})(errorType, extraFields);
};
const auto INVALID_PRESET_OBJECT =
[](JsonErrors::ObjectError errorType,
const Json::Value::Members& extraFields) {
return JsonErrors::INVALID_NAMED_OBJECT(
[](const Json::Value*, cmJSONState*) -> std::string {
return "Preset";
})(errorType, extraFields);
};
const auto INVALID_ROOT_OBJECT = [](JsonErrors::ObjectError errorType,
const Json::Value::Members& extraFields) {
return JsonErrors::INVALID_NAMED_OBJECT(
[](const Json::Value*, cmJSONState*) -> std::string {
return "root object";
})(errorType, extraFields);
};
const auto PRESET_MISSING_FIELD = [](const std::string& presetName,
const std::string& missingField,
cmJSONState* state) {
state->AddError(cmStrCat("Preset \"", presetName, "\" missing field \"",
missingField, "\""));
};
}
+178 -201
View File
@@ -14,6 +14,7 @@
#include "cmsys/RegularExpression.hxx"
#include "cmCMakePresetErrors.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -39,7 +40,6 @@ enum class CycleStatus
Verified,
};
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
@@ -81,17 +81,18 @@ void InheritVector(std::vector<T>& child, const std::vector<T>& parent)
* inheritance.
*/
template <class T>
ReadFileResult VisitPreset(
bool VisitPreset(
T& preset,
std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
std::map<std::string, CycleStatus> cycleStatus,
const cmCMakePresetsGraph& graph)
std::map<std::string, CycleStatus> cycleStatus, cmCMakePresetsGraph& graph)
{
switch (cycleStatus[preset.Name]) {
case CycleStatus::InProgress:
return ReadFileResult::CYCLIC_PRESET_INHERITANCE;
cmCMakePresetErrors::CYCLIC_PRESET_INHERITANCE(preset.Name,
&graph.parseState);
return false;
case CycleStatus::Verified:
return ReadFileResult::READ_OK;
return true;
default:
break;
}
@@ -99,28 +100,41 @@ ReadFileResult VisitPreset(
cycleStatus[preset.Name] = CycleStatus::InProgress;
if (preset.Environment.count("") != 0) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET_NAMED(preset.Name, &graph.parseState);
return false;
}
CHECK_OK(preset.VisitPresetBeforeInherit());
bool result = preset.VisitPresetBeforeInherit();
if (!result) {
cmCMakePresetErrors::INVALID_PRESET_NAMED(preset.Name, &graph.parseState);
return false;
}
for (auto const& i : preset.Inherits) {
auto parent = presets.find(i);
if (parent == presets.end()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET_NAMED(preset.Name,
&graph.parseState);
return false;
}
auto& parentPreset = parent->second.Unexpanded;
if (!preset.OriginFile->ReachableFiles.count(parentPreset.OriginFile)) {
return ReadFileResult::INHERITED_PRESET_UNREACHABLE_FROM_FILE;
cmCMakePresetErrors::INHERITED_PRESET_UNREACHABLE_FROM_FILE(
preset.Name, &graph.parseState);
return false;
}
auto result = VisitPreset(parentPreset, presets, cycleStatus, graph);
if (result != ReadFileResult::READ_OK) {
return result;
if (!VisitPreset(parentPreset, presets, cycleStatus, graph)) {
return false;
}
CHECK_OK(preset.VisitPresetInherit(parentPreset));
result = preset.VisitPresetInherit(parentPreset);
if (!result) {
cmCMakePresetErrors::INVALID_PRESET_NAMED(preset.Name,
&graph.parseState);
return false;
}
for (auto const& v : parentPreset.Environment) {
preset.Environment.insert(v);
@@ -135,16 +149,21 @@ ReadFileResult VisitPreset(
preset.ConditionEvaluator.reset();
}
CHECK_OK(preset.VisitPresetAfterInherit(graph.GetVersion(preset)));
result = preset.VisitPresetAfterInherit(graph.GetVersion(preset),
&graph.parseState);
if (!result) {
cmCMakePresetErrors::INVALID_PRESET_NAMED(preset.Name, &graph.parseState);
return false;
}
cycleStatus[preset.Name] = CycleStatus::Verified;
return ReadFileResult::READ_OK;
return true;
}
template <class T>
ReadFileResult ComputePresetInheritance(
bool ComputePresetInheritance(
std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
const cmCMakePresetsGraph& graph)
cmCMakePresetsGraph& graph)
{
std::map<std::string, CycleStatus> cycleStatus;
for (auto const& it : presets) {
@@ -153,13 +172,12 @@ ReadFileResult ComputePresetInheritance(
for (auto& it : presets) {
auto& preset = it.second.Unexpanded;
auto result = VisitPreset<T>(preset, presets, cycleStatus, graph);
if (result != ReadFileResult::READ_OK) {
return result;
if (!VisitPreset<T>(preset, presets, cycleStatus, graph)) {
return false;
}
}
return ReadFileResult::READ_OK;
return true;
}
constexpr const char* ValidPrefixes[] = {
@@ -338,7 +356,7 @@ bool ExpandMacros(const cmCMakePresetsGraph& /*graph*/,
}
template <class T>
bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset,
bool ExpandMacros(cmCMakePresetsGraph& graph, const T& preset,
cm::optional<T>& out)
{
out.emplace(preset);
@@ -448,6 +466,8 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset,
switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders,
graph.GetVersion(preset))) {
case ExpandMacroResult::Error:
cmCMakePresetErrors::INVALID_PRESET_NAMED(preset.Name,
&graph.parseState);
return false;
case ExpandMacroResult::Ignore:
out.reset();
@@ -462,6 +482,8 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset,
cm::optional<bool> result;
if (!preset.ConditionEvaluator->Evaluate(
macroExpanders, graph.GetVersion(preset), result)) {
cmCMakePresetErrors::INVALID_PRESET_NAMED(preset.Name,
&graph.parseState);
return false;
}
if (!result) {
@@ -594,39 +616,44 @@ ExpandMacroResult ExpandMacro(std::string& out,
}
template <typename T>
ReadFileResult SetupWorkflowConfigurePreset(
const T& preset, const ConfigurePreset*& configurePreset)
bool SetupWorkflowConfigurePreset(const T& preset,
const ConfigurePreset*& configurePreset,
cmJSONState* state)
{
if (preset.ConfigurePreset != configurePreset->Name) {
return ReadFileResult::INVALID_WORKFLOW_STEPS;
cmCMakePresetErrors::INVALID_WORKFLOW_STEPS(configurePreset->Name, state);
return false;
}
return ReadFileResult::READ_OK;
return true;
}
template <>
ReadFileResult SetupWorkflowConfigurePreset<ConfigurePreset>(
const ConfigurePreset& preset, const ConfigurePreset*& configurePreset)
bool SetupWorkflowConfigurePreset<ConfigurePreset>(
const ConfigurePreset& preset, const ConfigurePreset*& configurePreset,
cmJSONState*)
{
configurePreset = &preset;
return ReadFileResult::READ_OK;
return true;
}
template <typename T>
ReadFileResult TryReachPresetFromWorkflow(
bool TryReachPresetFromWorkflow(
const WorkflowPreset& origin,
const std::map<std::string, PresetPair<T>>& presets, const std::string& name,
const ConfigurePreset*& configurePreset)
const ConfigurePreset*& configurePreset, cmJSONState* state)
{
auto it = presets.find(name);
if (it == presets.end()) {
return ReadFileResult::INVALID_WORKFLOW_STEPS;
cmCMakePresetErrors::INVALID_WORKFLOW_STEPS(name, state);
return false;
}
if (!origin.OriginFile->ReachableFiles.count(
it->second.Unexpanded.OriginFile)) {
return ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE;
cmCMakePresetErrors::WORKFLOW_STEP_UNREACHABLE_FROM_FILE(name, state);
return false;
}
return SetupWorkflowConfigurePreset<T>(it->second.Unexpanded,
configurePreset);
configurePreset, state);
}
}
@@ -722,8 +749,7 @@ bool cmCMakePresetsGraphInternal::NotCondition::Evaluate(
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::ConfigurePreset::VisitPresetInherit(
bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetInherit(
const cmCMakePresetsGraph::Preset& parentPreset)
{
auto& preset = *this;
@@ -753,50 +779,52 @@ cmCMakePresetsGraph::ConfigurePreset::VisitPresetInherit(
preset.CacheVariables.insert(v);
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::ConfigurePreset::VisitPresetBeforeInherit()
bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetBeforeInherit()
{
auto& preset = *this;
if (preset.Environment.count("") != 0) {
return ReadFileResult::INVALID_PRESET;
return false;
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::ConfigurePreset::VisitPresetAfterInherit(int version)
bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetAfterInherit(
int version, cmJSONState* state)
{
auto& preset = *this;
if (!preset.Hidden) {
if (version < 3) {
if (preset.Generator.empty()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::PRESET_MISSING_FIELD(preset.Name, "generator",
state);
return false;
}
if (preset.BinaryDir.empty()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::PRESET_MISSING_FIELD(preset.Name, "binaryDir",
state);
return false;
}
}
if (preset.WarnDev == false && preset.ErrorDev == true) {
return ReadFileResult::INVALID_PRESET;
return false;
}
if (preset.WarnDeprecated == false && preset.ErrorDeprecated == true) {
return ReadFileResult::INVALID_PRESET;
return false;
}
if (preset.CacheVariables.count("") != 0) {
return ReadFileResult::INVALID_PRESET;
return false;
}
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::BuildPreset::VisitPresetInherit(
bool cmCMakePresetsGraph::BuildPreset::VisitPresetInherit(
const cmCMakePresetsGraph::Preset& parentPreset)
{
auto& preset = *this;
@@ -815,21 +843,20 @@ cmCMakePresetsGraph::BuildPreset::VisitPresetInherit(
preset.ResolvePackageReferences = parent.ResolvePackageReferences;
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::BuildPreset::VisitPresetAfterInherit(int /* version */)
bool cmCMakePresetsGraph::BuildPreset::VisitPresetAfterInherit(
int /* version */, cmJSONState* /*stat*/)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
return ReadFileResult::INVALID_PRESET;
return false;
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
bool cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
const cmCMakePresetsGraph::Preset& parentPreset)
{
auto& preset = *this;
@@ -928,21 +955,20 @@ cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
}
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(int /* version */)
bool cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(
int /* version */, cmJSONState* /*state*/)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
return ReadFileResult::INVALID_PRESET;
return false;
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
bool cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
const cmCMakePresetsGraph::Preset& parentPreset)
{
auto& preset = *this;
@@ -966,30 +992,29 @@ cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
InheritString(preset.PackageDirectory, parent.PackageDirectory);
InheritString(preset.VendorName, parent.VendorName);
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(int /* version */)
bool cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(
int /* version */, cmJSONState* /*state*/)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
return ReadFileResult::INVALID_PRESET;
return false;
}
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit(
bool cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit(
const cmCMakePresetsGraph::Preset& /*parentPreset*/)
{
return ReadFileResult::READ_OK;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::WorkflowPreset::VisitPresetAfterInherit(int /* version */)
bool cmCMakePresetsGraph::WorkflowPreset::VisitPresetAfterInherit(
int /* version */, cmJSONState* /*state*/)
{
return ReadFileResult::READ_OK;
return true;
}
std::string cmCMakePresetsGraph::GetFilename(const std::string& sourceDir)
@@ -1002,22 +1027,21 @@ std::string cmCMakePresetsGraph::GetUserFilename(const std::string& sourceDir)
return cmStrCat(sourceDir, "/CMakeUserPresets.json");
}
cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadProjectPresets(
const std::string& sourceDir, bool allowNoFiles)
bool cmCMakePresetsGraph::ReadProjectPresets(const std::string& sourceDir,
bool allowNoFiles)
{
this->SourceDir = sourceDir;
this->ClearPresets();
auto result = this->ReadProjectPresetsInternal(allowNoFiles);
if (result != ReadFileResult::READ_OK) {
if (!this->ReadProjectPresetsInternal(allowNoFiles)) {
this->ClearPresets();
return false;
}
return result;
return true;
}
cmCMakePresetsGraph::ReadFileResult
cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
bool cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
{
bool haveOneFile = false;
@@ -1025,21 +1049,17 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
std::string filename = GetUserFilename(this->SourceDir);
std::vector<File*> inProgressFiles;
if (cmSystemTools::FileExists(filename)) {
auto result =
this->ReadJSONFile(filename, RootType::User, ReadReason::Root,
inProgressFiles, file, this->errors);
if (result != ReadFileResult::READ_OK) {
return result;
if (!this->ReadJSONFile(filename, RootType::User, ReadReason::Root,
inProgressFiles, file, this->errors)) {
return false;
}
haveOneFile = true;
} else {
filename = GetFilename(this->SourceDir);
if (cmSystemTools::FileExists(filename)) {
auto result =
this->ReadJSONFile(filename, RootType::Project, ReadReason::Root,
inProgressFiles, file, this->errors);
if (result != ReadFileResult::READ_OK) {
return result;
if (!this->ReadJSONFile(filename, RootType::Project, ReadReason::Root,
inProgressFiles, file, this->errors)) {
return false;
}
haveOneFile = true;
}
@@ -1047,19 +1067,28 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
assert(inProgressFiles.empty());
if (!haveOneFile) {
return allowNoFiles ? ReadFileResult::READ_OK
: ReadFileResult::FILE_NOT_FOUND;
if (allowNoFiles) {
return true;
}
cmCMakePresetErrors::FILE_NOT_FOUND(filename, &this->parseState);
return false;
}
CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this));
CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this));
CHECK_OK(ComputePresetInheritance(this->TestPresets, *this));
CHECK_OK(ComputePresetInheritance(this->PackagePresets, *this));
CHECK_OK(ComputePresetInheritance(this->WorkflowPresets, *this));
bool result = ComputePresetInheritance(this->ConfigurePresets, *this) &&
ComputePresetInheritance(this->ConfigurePresets, *this) &&
ComputePresetInheritance(this->BuildPresets, *this) &&
ComputePresetInheritance(this->TestPresets, *this) &&
ComputePresetInheritance(this->PackagePresets, *this) &&
ComputePresetInheritance(this->WorkflowPresets, *this);
if (!result) {
return false;
}
for (auto& it : this->ConfigurePresets) {
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
return ReadFileResult::INVALID_MACRO_EXPANSION;
cmCMakePresetErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
}
}
@@ -1068,11 +1097,15 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
const auto configurePreset =
this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
if (configurePreset == this->ConfigurePresets.end()) {
return ReadFileResult::INVALID_CONFIGURE_PRESET;
cmCMakePresetErrors::INVALID_CONFIGURE_PRESET(it.first,
&this->parseState);
return false;
}
if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
configurePreset->second.Unexpanded.OriginFile)) {
return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE;
cmCMakePresetErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
it.first, &this->parseState);
return false;
}
if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
@@ -1083,7 +1116,9 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
}
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
return ReadFileResult::INVALID_MACRO_EXPANSION;
cmCMakePresetErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
}
}
@@ -1092,11 +1127,15 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
const auto configurePreset =
this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
if (configurePreset == this->ConfigurePresets.end()) {
return ReadFileResult::INVALID_CONFIGURE_PRESET;
cmCMakePresetErrors::INVALID_CONFIGURE_PRESET(it.first,
&this->parseState);
return false;
}
if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
configurePreset->second.Unexpanded.OriginFile)) {
return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE;
cmCMakePresetErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
it.first, &this->parseState);
return false;
}
if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
@@ -1107,7 +1146,9 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
}
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
return ReadFileResult::INVALID_MACRO_EXPANSION;
cmCMakePresetErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
}
}
@@ -1116,11 +1157,15 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
const auto configurePreset =
this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
if (configurePreset == this->ConfigurePresets.end()) {
return ReadFileResult::INVALID_CONFIGURE_PRESET;
cmCMakePresetErrors::INVALID_CONFIGURE_PRESET(it.first,
&this->parseState);
return false;
}
if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
configurePreset->second.Unexpanded.OriginFile)) {
return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE;
cmCMakePresetErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
it.first, &this->parseState);
return false;
}
if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
@@ -1131,7 +1176,9 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
}
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
return ReadFileResult::INVALID_MACRO_EXPANSION;
cmCMakePresetErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
}
}
@@ -1141,126 +1188,56 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
const ConfigurePreset* configurePreset = nullptr;
for (auto const& step : it.second.Unexpanded.Steps) {
if (configurePreset == nullptr && step.PresetType != Type::Configure) {
return ReadFileResult::INVALID_WORKFLOW_STEPS;
cmCMakePresetErrors::FIRST_WORKFLOW_STEP_NOT_CONFIGURE(
step.PresetName, &this->parseState);
return false;
}
if (configurePreset != nullptr && step.PresetType == Type::Configure) {
return ReadFileResult::INVALID_WORKFLOW_STEPS;
cmCMakePresetErrors::CONFIGURE_WORKFLOW_STEP_NOT_FIRST(
step.PresetName, &this->parseState);
return false;
}
ReadFileResult result;
switch (step.PresetType) {
case Type::Configure:
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->ConfigurePresets, step.PresetName,
configurePreset);
configurePreset, &this->parseState);
break;
case Type::Build:
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->BuildPresets, step.PresetName,
configurePreset);
configurePreset, &this->parseState);
break;
case Type::Test:
result =
TryReachPresetFromWorkflow(it.second.Unexpanded, this->TestPresets,
step.PresetName, configurePreset);
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->TestPresets, step.PresetName,
configurePreset, &this->parseState);
break;
case Type::Package:
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->PackagePresets, step.PresetName,
configurePreset);
configurePreset, &this->parseState);
break;
}
if (result != ReadFileResult::READ_OK) {
return result;
if (!result) {
return false;
}
}
if (configurePreset == nullptr) {
return ReadFileResult::INVALID_WORKFLOW_STEPS;
cmCMakePresetErrors::NO_WORKFLOW_STEPS(it.first, &this->parseState);
return false;
}
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
return ReadFileResult::INVALID_MACRO_EXPANSION;
cmCMakePresetErrors::INVALID_MACRO_EXPANSION(it.first,
&this->parseState);
return false;
}
}
return ReadFileResult::READ_OK;
}
const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result)
{
switch (result) {
case ReadFileResult::READ_OK:
return "OK";
case ReadFileResult::FILE_NOT_FOUND:
return "File not found";
case ReadFileResult::JSON_PARSE_ERROR:
return "JSON parse error";
case ReadFileResult::INVALID_ROOT:
return "Invalid root object";
case ReadFileResult::NO_VERSION:
return "No \"version\" field";
case ReadFileResult::INVALID_VERSION:
return "Invalid \"version\" field";
case ReadFileResult::UNRECOGNIZED_VERSION:
return "Unrecognized \"version\" field";
case ReadFileResult::INVALID_CMAKE_VERSION:
return "Invalid \"cmakeMinimumRequired\" field";
case ReadFileResult::UNRECOGNIZED_CMAKE_VERSION:
return "\"cmakeMinimumRequired\" version too new";
case ReadFileResult::INVALID_PRESETS:
return "Invalid \"configurePresets\" field";
case ReadFileResult::INVALID_PRESET:
return "Invalid preset";
case ReadFileResult::INVALID_VARIABLE:
return "Invalid CMake variable definition";
case ReadFileResult::DUPLICATE_PRESETS:
return "Duplicate presets";
case ReadFileResult::CYCLIC_PRESET_INHERITANCE:
return "Cyclic preset inheritance";
case ReadFileResult::INHERITED_PRESET_UNREACHABLE_FROM_FILE:
return "Inherited preset is unreachable from preset's file";
case ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE:
return "Configure preset is unreachable from preset's file";
case ReadFileResult::INVALID_MACRO_EXPANSION:
return "Invalid macro expansion";
case ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED:
return "File version must be 2 or higher for build and test preset "
"support.";
case ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED:
return "File version must be 6 or higher for package preset support";
case ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED:
return "File version must be 6 or higher for workflow preset support";
case ReadFileResult::INCLUDE_UNSUPPORTED:
return "File version must be 4 or higher for include support";
case ReadFileResult::INVALID_INCLUDE:
return "Invalid \"include\" field";
case ReadFileResult::INVALID_CONFIGURE_PRESET:
return "Invalid \"configurePreset\" field";
case ReadFileResult::INSTALL_PREFIX_UNSUPPORTED:
return "File version must be 3 or higher for installDir preset "
"support.";
case ReadFileResult::INVALID_CONDITION:
return "Invalid preset condition";
case ReadFileResult::CONDITION_UNSUPPORTED:
return "File version must be 3 or higher for condition support";
case ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED:
return "File version must be 3 or higher for toolchainFile preset "
"support.";
case ReadFileResult::CYCLIC_INCLUDE:
return "Cyclic include among preset files";
case ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED:
return "File version must be 5 or higher for testOutputTruncation "
"preset support.";
case ReadFileResult::INVALID_WORKFLOW_STEPS:
return "Invalid workflow steps";
case ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE:
return "Workflow step is unreachable from preset's file";
case ReadFileResult::CTEST_JUNIT_UNSUPPORTED:
return "File version must be 6 or higher for CTest JUnit output support";
}
return "Unknown error";
return true;
}
void cmCMakePresetsGraph::ClearPresets()
+30 -62
View File
@@ -14,6 +14,8 @@
#include <cm/optional>
#include "cmJSONState.h"
#include "CTest/cmCTestTypes.h"
enum class PackageResolveMode;
@@ -21,43 +23,9 @@ enum class PackageResolveMode;
class cmCMakePresetsGraph
{
public:
enum class ReadFileResult
{
READ_OK,
FILE_NOT_FOUND,
JSON_PARSE_ERROR,
INVALID_ROOT,
NO_VERSION,
INVALID_VERSION,
UNRECOGNIZED_VERSION,
INVALID_CMAKE_VERSION,
UNRECOGNIZED_CMAKE_VERSION,
INVALID_PRESETS,
INVALID_PRESET,
INVALID_VARIABLE,
DUPLICATE_PRESETS,
CYCLIC_PRESET_INHERITANCE,
INHERITED_PRESET_UNREACHABLE_FROM_FILE,
CONFIGURE_PRESET_UNREACHABLE_FROM_FILE,
INVALID_MACRO_EXPANSION,
BUILD_TEST_PRESETS_UNSUPPORTED,
PACKAGE_PRESETS_UNSUPPORTED,
WORKFLOW_PRESETS_UNSUPPORTED,
INCLUDE_UNSUPPORTED,
INVALID_INCLUDE,
INVALID_CONFIGURE_PRESET,
INSTALL_PREFIX_UNSUPPORTED,
INVALID_CONDITION,
CONDITION_UNSUPPORTED,
TOOLCHAIN_FILE_UNSUPPORTED,
CYCLIC_INCLUDE,
TEST_OUTPUT_TRUNCATION_UNSUPPORTED,
INVALID_WORKFLOW_STEPS,
WORKFLOW_STEP_UNREACHABLE_FROM_FILE,
CTEST_JUNIT_UNSUPPORTED,
};
std::string errors;
cmJSONState parseState;
enum class ArchToolsetStrategy
{
Set,
@@ -111,15 +79,13 @@ public:
std::map<std::string, cm::optional<std::string>> Environment;
virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0;
virtual ReadFileResult VisitPresetBeforeInherit()
{
return ReadFileResult::READ_OK;
}
virtual bool VisitPresetInherit(const Preset& parent) = 0;
virtual bool VisitPresetBeforeInherit() { return true; }
virtual ReadFileResult VisitPresetAfterInherit(int /* version */)
virtual bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /*state*/)
{
return ReadFileResult::READ_OK;
return true;
}
};
@@ -163,9 +129,9 @@ public:
cm::optional<bool> DebugTryCompile;
cm::optional<bool> DebugFind;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetBeforeInherit() override;
ReadFileResult VisitPresetAfterInherit(int version) override;
bool VisitPresetInherit(const Preset& parent) override;
bool VisitPresetBeforeInherit() override;
bool VisitPresetAfterInherit(int version, cmJSONState* state) override;
};
class BuildPreset : public Preset
@@ -195,8 +161,9 @@ public:
std::vector<std::string> NativeToolOptions;
cm::optional<PackageResolveMode> ResolvePackageReferences;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
bool VisitPresetInherit(const Preset& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /*state*/) override;
};
class TestPreset : public Preset
@@ -328,8 +295,9 @@ public:
cm::optional<FilterOptions> Filter;
cm::optional<ExecutionOptions> Execution;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
bool VisitPresetInherit(const Preset& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /*state*/) override;
};
class PackagePreset : public Preset
@@ -364,8 +332,9 @@ public:
std::string PackageDirectory;
std::string VendorName;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
bool VisitPresetInherit(const Preset& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /*state*/) override;
};
class WorkflowPreset : public Preset
@@ -401,8 +370,9 @@ public:
std::vector<WorkflowStep> Steps;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
bool VisitPresetInherit(const Preset& parent) override;
bool VisitPresetAfterInherit(int /* version */,
cmJSONState* /* state */) override;
};
template <class T>
@@ -435,9 +405,8 @@ public:
static std::string GetFilename(const std::string& sourceDir);
static std::string GetUserFilename(const std::string& sourceDir);
ReadFileResult ReadProjectPresets(const std::string& sourceDir,
bool allowNoFiles = false);
static const char* ResultToString(ReadFileResult result);
bool ReadProjectPresets(const std::string& sourceDir,
bool allowNoFiles = false);
std::string GetGeneratorForPreset(const std::string& presetName) const
{
@@ -502,10 +471,9 @@ private:
Included,
};
ReadFileResult ReadProjectPresetsInternal(bool allowNoFiles);
ReadFileResult ReadJSONFile(const std::string& filename, RootType rootType,
ReadReason readReason,
std::vector<File*>& inProgressFiles, File*& file,
std::string& errMsg);
bool ReadProjectPresetsInternal(bool allowNoFiles);
bool ReadJSONFile(const std::string& filename, RootType rootType,
ReadReason readReason, std::vector<File*>& inProgressFiles,
File*& file, std::string& errMsg);
void ClearPresets();
};
+34 -35
View File
@@ -14,7 +14,7 @@
#define CHECK_OK(expr) \
do { \
auto _result = expr; \
if (_result != ReadFileResult::READ_OK) \
if (_result != true) \
return _result; \
} while (false)
@@ -117,57 +117,56 @@ public:
std::unique_ptr<Condition> SubCondition;
};
cmCMakePresetsGraph::ReadFileResult PresetStringHelper(
std::string& out, const Json::Value* value);
bool PresetStringHelper(std::string& out, const Json::Value* value,
cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper(
std::vector<std::string>& out, const Json::Value* value);
bool PresetNameHelper(std::string& out, const Json::Value* value,
cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out,
const Json::Value* value);
bool PresetVectorStringHelper(std::vector<std::string>& out,
const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper(
cm::optional<bool>& out, const Json::Value* value);
bool PresetBoolHelper(bool& out, const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out,
const Json::Value* value);
bool PresetOptionalBoolHelper(cm::optional<bool>& out,
const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper(
cm::optional<int>& out, const Json::Value* value);
bool PresetIntHelper(int& out, const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper(
std::vector<int>& out, const Json::Value* value);
bool PresetOptionalIntHelper(cm::optional<int>& out, const Json::Value* value,
cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult ConfigurePresetsHelper(
bool PresetVectorIntHelper(std::vector<int>& out, const Json::Value* value,
cmJSONState* state);
bool ConfigurePresetsHelper(
std::vector<cmCMakePresetsGraph::ConfigurePreset>& out,
const Json::Value* value);
const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult BuildPresetsHelper(
std::vector<cmCMakePresetsGraph::BuildPreset>& out,
const Json::Value* value);
bool BuildPresetsHelper(std::vector<cmCMakePresetsGraph::BuildPreset>& out,
const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult TestPresetsHelper(
std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value);
bool TestPresetsHelper(std::vector<cmCMakePresetsGraph::TestPreset>& out,
const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper(
std::vector<cmCMakePresetsGraph::PackagePreset>& out,
const Json::Value* value);
bool PackagePresetsHelper(std::vector<cmCMakePresetsGraph::PackagePreset>& out,
const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper(
bool WorkflowPresetsHelper(
std::vector<cmCMakePresetsGraph::WorkflowPreset>& out,
const Json::Value* value);
const Json::Value* value, cmJSONState* state);
cmJSONHelper<std::nullptr_t, cmCMakePresetsGraph::ReadFileResult> VendorHelper(
cmCMakePresetsGraph::ReadFileResult error);
cmJSONHelper<std::nullptr_t> VendorHelper(const ErrorGenerator& error);
cmCMakePresetsGraph::ReadFileResult PresetConditionHelper(
bool PresetConditionHelper(
std::shared_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value);
const Json::Value* value, cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult PresetVectorOneOrMoreStringHelper(
std::vector<std::string>& out, const Json::Value* value);
bool PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
const Json::Value* value,
cmJSONState* state);
cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper(
bool EnvironmentMapHelper(
std::map<std::string, cm::optional<std::string>>& out,
const Json::Value* value);
const Json::Value* value, cmJSONState* state);
}
+234 -204
View File
@@ -1,6 +1,7 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include <algorithm>
#include <fstream>
#include <functional>
#include <map>
#include <string>
@@ -12,20 +13,18 @@
#include <cm/optional>
#include <cmext/string_view>
#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
#include "cmsys/FStream.hxx"
#include "cmCMakePresetErrors.h"
#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmJSONHelpers.h"
#include "cmJSONState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
namespace {
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using CacheVariable = cmCMakePresetsGraph::CacheVariable;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
@@ -33,7 +32,7 @@ using TestPreset = cmCMakePresetsGraph::TestPreset;
using PackagePreset = cmCMakePresetsGraph::PackagePreset;
using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>;
using JSONHelperBuilder = cmJSONHelperBuilder;
constexpr int MIN_VERSION = 1;
constexpr int MAX_VERSION = 6;
@@ -64,26 +63,23 @@ std::unique_ptr<cmCMakePresetsGraphInternal::NotCondition> InvertCondition(
return retval;
}
auto const ConditionStringHelper = JSONHelperBuilder::String(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
auto const ConditionStringHelper = JSONHelperBuilder::String();
auto const ConditionBoolHelper = JSONHelperBuilder::Bool(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
auto const ConditionBoolHelper = JSONHelperBuilder::Bool();
auto const ConditionStringListHelper = JSONHelperBuilder::Vector<std::string>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
ConditionStringHelper);
cmCMakePresetErrors::INVALID_CONDITION, ConditionStringHelper);
auto const ConstConditionHelper =
JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::ConstCondition>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false)
.Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
.Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value,
ConditionBoolHelper, true);
auto const EqualsConditionHelper =
JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::EqualsCondition>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false)
.Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
.Bind("lhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Lhs,
ConditionStringHelper, true)
@@ -92,7 +88,7 @@ auto const EqualsConditionHelper =
auto const InListConditionHelper =
JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::InListCondition>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false)
.Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
.Bind("string"_s, &cmCMakePresetsGraphInternal::InListCondition::String,
ConditionStringHelper, true)
@@ -101,24 +97,22 @@ auto const InListConditionHelper =
auto const MatchesConditionHelper =
JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::MatchesCondition>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false)
.Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
.Bind("string"_s, &cmCMakePresetsGraphInternal::MatchesCondition::String,
ConditionStringHelper, true)
.Bind("regex"_s, &cmCMakePresetsGraphInternal::MatchesCondition::Regex,
ConditionStringHelper, true);
ReadFileResult SubConditionHelper(
std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value);
bool SubConditionHelper(std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value, cmJSONState* state);
auto const ListConditionVectorHelper =
JSONHelperBuilder::Vector<std::unique_ptr<cmCMakePresetsGraph::Condition>>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
SubConditionHelper);
cmCMakePresetErrors::INVALID_CONDITION, SubConditionHelper);
auto const AnyAllOfConditionHelper =
JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::AnyAllOfCondition>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false)
.Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
.Bind("conditions"_s,
&cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions,
@@ -126,158 +120,160 @@ auto const AnyAllOfConditionHelper =
auto const NotConditionHelper =
JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::NotCondition>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false)
.Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
.Bind("condition"_s,
&cmCMakePresetsGraphInternal::NotCondition::SubCondition,
SubConditionHelper);
ReadFileResult ConditionHelper(
std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value)
bool ConditionHelper(std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value, cmJSONState* state)
{
if (!value) {
out.reset();
return ReadFileResult::READ_OK;
return true;
}
if (value->isBool()) {
auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
c->Value = value->asBool();
out = std::move(c);
return ReadFileResult::READ_OK;
return true;
}
if (value->isNull()) {
out = cm::make_unique<cmCMakePresetsGraphInternal::NullCondition>();
return ReadFileResult::READ_OK;
return true;
}
if (value->isObject()) {
if (!value->isMember("type")) {
return ReadFileResult::INVALID_CONDITION;
cmCMakePresetErrors::INVALID_CONDITION(value, state);
return false;
}
if (!(*value)["type"].isString()) {
return ReadFileResult::INVALID_CONDITION;
cmCMakePresetErrors::INVALID_CONDITION(value, state);
return false;
}
auto type = (*value)["type"].asString();
if (type == "const") {
auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
CHECK_OK(ConstConditionHelper(*c, value));
CHECK_OK(ConstConditionHelper(*c, value, state));
out = std::move(c);
return ReadFileResult::READ_OK;
return true;
}
if (type == "equals" || type == "notEquals") {
auto c = cm::make_unique<cmCMakePresetsGraphInternal::EqualsCondition>();
CHECK_OK(EqualsConditionHelper(*c, value));
CHECK_OK(EqualsConditionHelper(*c, value, state));
out = std::move(c);
if (type == "notEquals") {
out = InvertCondition(std::move(out));
}
return ReadFileResult::READ_OK;
return true;
}
if (type == "inList" || type == "notInList") {
auto c = cm::make_unique<cmCMakePresetsGraphInternal::InListCondition>();
CHECK_OK(InListConditionHelper(*c, value));
CHECK_OK(InListConditionHelper(*c, value, state));
out = std::move(c);
if (type == "notInList") {
out = InvertCondition(std::move(out));
}
return ReadFileResult::READ_OK;
return true;
}
if (type == "matches" || type == "notMatches") {
auto c =
cm::make_unique<cmCMakePresetsGraphInternal::MatchesCondition>();
CHECK_OK(MatchesConditionHelper(*c, value));
CHECK_OK(MatchesConditionHelper(*c, value, state));
out = std::move(c);
if (type == "notMatches") {
out = InvertCondition(std::move(out));
}
return ReadFileResult::READ_OK;
return true;
}
if (type == "anyOf" || type == "allOf") {
auto c =
cm::make_unique<cmCMakePresetsGraphInternal::AnyAllOfCondition>();
c->StopValue = (type == "anyOf");
CHECK_OK(AnyAllOfConditionHelper(*c, value));
CHECK_OK(AnyAllOfConditionHelper(*c, value, state));
out = std::move(c);
return ReadFileResult::READ_OK;
return true;
}
if (type == "not") {
auto c = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>();
CHECK_OK(NotConditionHelper(*c, value));
CHECK_OK(NotConditionHelper(*c, value, state));
out = std::move(c);
return ReadFileResult::READ_OK;
return true;
}
}
return ReadFileResult::INVALID_CONDITION;
cmCMakePresetErrors::INVALID_CONDITION(value, state);
return false;
}
ReadFileResult SubConditionHelper(
std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value)
bool SubConditionHelper(std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value, cmJSONState* state)
{
std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
auto result = ConditionHelper(ptr, value);
auto result = ConditionHelper(ptr, value, state);
if (ptr && ptr->IsNull()) {
return ReadFileResult::INVALID_CONDITION;
cmCMakePresetErrors::INVALID_CONDITION(value, state);
return false;
}
out = std::move(ptr);
return result;
}
ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
const Json::Value* value)
bool EnvironmentHelper(cm::optional<std::string>& out,
const Json::Value* value, cmJSONState* state)
{
if (!value || value->isNull()) {
out = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
if (value->isString()) {
out = value->asString();
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
auto const VersionIntHelper = JSONHelperBuilder::Int(
ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
auto const VersionIntHelper =
JSONHelperBuilder::Int(cmCMakePresetErrors::INVALID_VERSION);
auto const VersionHelper = JSONHelperBuilder::Required<int>(
ReadFileResult::NO_VERSION, VersionIntHelper);
cmCMakePresetErrors::NO_VERSION, VersionIntHelper);
auto const RootVersionHelper =
JSONHelperBuilder::Object<int>(ReadFileResult::READ_OK,
ReadFileResult::INVALID_ROOT)
JSONHelperBuilder::Object<int>(cmCMakePresetErrors::INVALID_ROOT_OBJECT)
.Bind("version"_s, VersionHelper, false);
auto const CMakeVersionUIntHelper = JSONHelperBuilder::UInt(
ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
auto const CMakeVersionUIntHelper =
JSONHelperBuilder::UInt(cmCMakePresetErrors::INVALID_VERSION);
auto const CMakeVersionHelper =
JSONHelperBuilder::Object<CMakeVersion>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
JSONHelperBuilder::Object<CMakeVersion>(JsonErrors::INVALID_NAMED_OBJECT_KEY,
false)
.Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
.Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
.Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
auto const IncludeHelper = JSONHelperBuilder::String(
ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE);
auto const IncludeHelper =
JSONHelperBuilder::String(cmCMakePresetErrors::INVALID_INCLUDE);
auto const IncludeVectorHelper = JSONHelperBuilder::Vector<std::string>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper);
cmCMakePresetErrors::INVALID_INCLUDE, IncludeHelper);
auto const RootPresetsHelper =
JSONHelperBuilder::Object<RootPresets>(ReadFileResult::READ_OK,
ReadFileResult::INVALID_ROOT, false)
JSONHelperBuilder::Object<RootPresets>(
cmCMakePresetErrors::INVALID_ROOT_OBJECT, false)
.Bind<int>("version"_s, nullptr, VersionHelper)
.Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
cmCMakePresetsGraphInternal::ConfigurePresetsHelper, false)
@@ -292,136 +288,137 @@ auto const RootPresetsHelper =
.Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
CMakeVersionHelper, false)
.Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
.Bind<std::nullptr_t>(
"vendor"_s, nullptr,
cmCMakePresetsGraphInternal::VendorHelper(ReadFileResult::INVALID_ROOT),
false);
.Bind<std::nullptr_t>("vendor"_s, nullptr,
cmCMakePresetsGraphInternal::VendorHelper(
cmCMakePresetErrors::INVALID_ROOT),
false);
}
namespace cmCMakePresetsGraphInternal {
cmCMakePresetsGraph::ReadFileResult PresetStringHelper(
std::string& out, const Json::Value* value)
bool PresetStringHelper(std::string& out, const Json::Value* value,
cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::String(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
return helper(out, value);
static auto const helper = JSONHelperBuilder::String();
return helper(out, value, state);
}
cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper(
std::vector<std::string>& out, const Json::Value* value)
bool PresetNameHelper(std::string& out, const Json::Value* value,
cmJSONState* state)
{
if (!value || !value->isString() || value->asString().empty()) {
cmCMakePresetErrors::INVALID_PRESET_NAME(value, state);
return false;
}
out = value->asString();
return true;
}
bool PresetVectorStringHelper(std::vector<std::string>& out,
const Json::Value* value, cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Vector<std::string>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
cmCMakePresetErrors::INVALID_PRESET,
cmCMakePresetsGraphInternal::PresetStringHelper);
return helper(out, value);
return helper(out, value, state);
}
cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out,
const Json::Value* value)
bool PresetBoolHelper(bool& out, const Json::Value* value, cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Bool(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
return helper(out, value);
static auto const helper = JSONHelperBuilder::Bool();
return helper(out, value, state);
}
cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper(
cm::optional<bool>& out, const Json::Value* value)
{
static auto const helper = JSONHelperBuilder::Optional<bool>(
ReadFileResult::READ_OK, PresetBoolHelper);
return helper(out, value);
}
cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out,
const Json::Value* value)
{
static auto const helper = JSONHelperBuilder::Int(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
return helper(out, value);
}
cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper(
cm::optional<int>& out, const Json::Value* value)
bool PresetOptionalBoolHelper(cm::optional<bool>& out,
const Json::Value* value, cmJSONState* state)
{
static auto const helper =
JSONHelperBuilder::Optional<int>(ReadFileResult::READ_OK, PresetIntHelper);
return helper(out, value);
JSONHelperBuilder::Optional<bool>(PresetBoolHelper);
return helper(out, value, state);
}
cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper(
std::vector<int>& out, const Json::Value* value)
bool PresetIntHelper(int& out, const Json::Value* value, cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Int();
return helper(out, value, state);
}
bool PresetOptionalIntHelper(cm::optional<int>& out, const Json::Value* value,
cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Optional<int>(PresetIntHelper);
return helper(out, value, state);
}
bool PresetVectorIntHelper(std::vector<int>& out, const Json::Value* value,
cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Vector<int>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
return helper(out, value);
cmCMakePresetErrors::INVALID_PRESET, PresetIntHelper);
return helper(out, value, state);
}
cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
cmJSONHelper<std::nullptr_t> VendorHelper(const ErrorGenerator& error)
{
return [error](std::nullptr_t& /*out*/,
const Json::Value* value) -> ReadFileResult {
return [error](std::nullptr_t& /*out*/, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
return ReadFileResult::READ_OK;
return true;
}
if (!value->isObject()) {
return error;
error(value, state);
return false;
}
return ReadFileResult::READ_OK;
return true;
};
}
ReadFileResult PresetConditionHelper(
bool PresetConditionHelper(
std::shared_ptr<cmCMakePresetsGraph::Condition>& out,
const Json::Value* value)
const Json::Value* value, cmJSONState* state)
{
std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
auto result = ConditionHelper(ptr, value);
auto result = ConditionHelper(ptr, value, state);
out = std::move(ptr);
return result;
}
ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
const Json::Value* value)
bool PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
const Json::Value* value,
cmJSONState* state)
{
out.clear();
if (!value) {
return ReadFileResult::READ_OK;
return true;
}
if (value->isString()) {
out.push_back(value->asString());
return ReadFileResult::READ_OK;
return true;
}
return PresetVectorStringHelper(out, value);
return PresetVectorStringHelper(out, value, state);
}
cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper(
bool EnvironmentMapHelper(
std::map<std::string, cm::optional<std::string>>& out,
const Json::Value* value)
const Json::Value* value, cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Map<cm::optional<std::string>>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
EnvironmentHelper);
cmCMakePresetErrors::INVALID_PRESET, EnvironmentHelper);
return helper(out, value);
return helper(out, value, state);
}
}
cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
const std::string& filename, RootType rootType, ReadReason readReason,
std::vector<File*>& inProgressFiles, File*& file, std::string& errMsg)
bool cmCMakePresetsGraph::ReadJSONFile(const std::string& filename,
RootType rootType,
ReadReason readReason,
std::vector<File*>& inProgressFiles,
File*& file, std::string& errMsg)
{
ReadFileResult result;
bool result;
for (auto const& f : this->Files) {
if (cmSystemTools::SameFile(filename, f->Filename)) {
@@ -429,61 +426,67 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
auto fileIt =
std::find(inProgressFiles.begin(), inProgressFiles.end(), file);
if (fileIt != inProgressFiles.end()) {
return cmCMakePresetsGraph::ReadFileResult::CYCLIC_INCLUDE;
cmCMakePresetErrors::CYCLIC_INCLUDE(filename, &this->parseState);
return false;
}
return cmCMakePresetsGraph::ReadFileResult::READ_OK;
return true;
}
}
cmsys::ifstream fin(filename.c_str());
if (!fin) {
errMsg = cmStrCat(filename, ": Failed to read file\n", errMsg);
return ReadFileResult::FILE_NOT_FOUND;
}
// If there's a BOM, toss it.
cmsys::FStream::ReadBOM(fin);
Json::Value root;
Json::CharReaderBuilder builder;
Json::CharReaderBuilder::strictMode(&builder.settings_);
if (!Json::parseFromStream(builder, fin, &root, &errMsg)) {
errMsg = cmStrCat(filename, ":\n", errMsg);
return ReadFileResult::JSON_PARSE_ERROR;
this->parseState = cmJSONState(filename, &root);
if (!this->parseState.errors.empty()) {
return false;
}
int v = 0;
if ((result = RootVersionHelper(v, &root)) != ReadFileResult::READ_OK) {
if ((result = RootVersionHelper(v, &root, &parseState)) != true) {
return result;
}
if (v < MIN_VERSION || v > MAX_VERSION) {
return ReadFileResult::UNRECOGNIZED_VERSION;
cmCMakePresetErrors::UNRECOGNIZED_VERSION(&root["version"],
&this->parseState);
return false;
}
// Support for build and test presets added in version 2.
if (v < 2 &&
(root.isMember("buildPresets") || root.isMember("testPresets"))) {
return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
if (v < 2) {
if (root.isMember("buildPresets")) {
cmCMakePresetErrors::BUILD_TEST_PRESETS_UNSUPPORTED(
&root["buildPresets"], &this->parseState);
return false;
}
if (root.isMember("testPresets")) {
cmCMakePresetErrors::BUILD_TEST_PRESETS_UNSUPPORTED(&root["testPresets"],
&this->parseState);
return false;
}
}
// Support for package presets added in version 6.
if (v < 6 && root.isMember("packagePresets")) {
return ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED;
cmCMakePresetErrors::PACKAGE_PRESETS_UNSUPPORTED(&root["packagePresets"],
&this->parseState);
return false;
}
// Support for workflow presets added in version 6.
if (v < 6 && root.isMember("workflowPresets")) {
return ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED;
cmCMakePresetErrors::WORKFLOW_PRESETS_UNSUPPORTED(&root["workflowPresets"],
&this->parseState);
return false;
}
// Support for include added in version 4.
if (v < 4 && root.isMember("include")) {
return ReadFileResult::INCLUDE_UNSUPPORTED;
cmCMakePresetErrors::INCLUDE_UNSUPPORTED(&root["include"],
&this->parseState);
return false;
}
RootPresets presets;
if ((result = RootPresetsHelper(presets, &root)) !=
ReadFileResult::READ_OK) {
if ((result = RootPresetsHelper(presets, &root, &parseState)) != true) {
return result;
}
@@ -491,12 +494,25 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
unsigned int currentMinor = cmVersion::GetMinorVersion();
unsigned int currentPatch = cmVersion::GetPatchVersion();
auto const& required = presets.CMakeMinimumRequired;
if (required.Major > currentMajor ||
(required.Major == currentMajor &&
(required.Minor > currentMinor ||
(required.Minor == currentMinor &&
(required.Patch > currentPatch))))) {
return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
if (required.Major > currentMajor) {
ErrorGenerator error = cmCMakePresetErrors::UNRECOGNIZED_CMAKE_VERSION(
"major", currentMajor, required.Major);
error(&root["cmakeMinimumRequired"]["major"], &this->parseState);
return false;
}
if (required.Major == currentMajor) {
if (required.Minor > currentMinor) {
ErrorGenerator error = cmCMakePresetErrors::UNRECOGNIZED_CMAKE_VERSION(
"minor", currentMinor, required.Minor);
error(&root["cmakeMinimumRequired"]["minor"], &this->parseState);
return false;
}
if (required.Minor == currentMinor && required.Patch > currentPatch) {
ErrorGenerator error = cmCMakePresetErrors::UNRECOGNIZED_CMAKE_VERSION(
"patch", currentPatch, required.Patch);
error(&root["cmakeMinimumRequired"]["patch"], &this->parseState);
return false;
}
}
auto filePtr = cm::make_unique<File>();
@@ -510,31 +526,35 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
for (auto& preset : presets.ConfigurePresets) {
preset.OriginFile = file;
if (preset.Name.empty()) {
errMsg += R"(\n\t)";
errMsg += filename;
return ReadFileResult::INVALID_PRESET;
// No error, already handled by PresetNameHelper
return false;
}
PresetPair<ConfigurePreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
if (!this->ConfigurePresets.emplace(preset.Name, presetPair).second) {
return ReadFileResult::DUPLICATE_PRESETS;
cmCMakePresetErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
return false;
}
// Support for installDir presets added in version 3.
if (v < 3 && !preset.InstallDir.empty()) {
return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
cmCMakePresetErrors::INSTALL_PREFIX_UNSUPPORTED(&root["installDir"],
&this->parseState);
return false;
}
// Support for conditions added in version 3.
if (v < 3 && preset.ConditionEvaluator) {
return ReadFileResult::CONDITION_UNSUPPORTED;
cmCMakePresetErrors::CONDITION_UNSUPPORTED(&this->parseState);
return false;
}
// Support for toolchainFile presets added in version 3.
if (v < 3 && !preset.ToolchainFile.empty()) {
return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED;
cmCMakePresetErrors::TOOLCHAIN_FILE_UNSUPPORTED(&this->parseState);
return false;
}
this->ConfigurePresetOrder.push_back(preset.Name);
@@ -543,21 +563,22 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
for (auto& preset : presets.BuildPresets) {
preset.OriginFile = file;
if (preset.Name.empty()) {
errMsg += R"(\n\t)";
errMsg += filename;
return ReadFileResult::INVALID_PRESET;
// No error, already handled by PresetNameHelper
return false;
}
PresetPair<BuildPreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
return ReadFileResult::DUPLICATE_PRESETS;
cmCMakePresetErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
return false;
}
// Support for conditions added in version 3.
if (v < 3 && preset.ConditionEvaluator) {
return ReadFileResult::CONDITION_UNSUPPORTED;
cmCMakePresetErrors::CONDITION_UNSUPPORTED(&this->parseState);
return false;
}
this->BuildPresetOrder.push_back(preset.Name);
@@ -566,29 +587,35 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
for (auto& preset : presets.TestPresets) {
preset.OriginFile = file;
if (preset.Name.empty()) {
return ReadFileResult::INVALID_PRESET;
// No error, already handled by PresetNameHelper
return false;
}
PresetPair<TestPreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
return ReadFileResult::DUPLICATE_PRESETS;
cmCMakePresetErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
return false;
}
// Support for conditions added in version 3.
if (v < 3 && preset.ConditionEvaluator) {
return ReadFileResult::CONDITION_UNSUPPORTED;
cmCMakePresetErrors::CONDITION_UNSUPPORTED(&this->parseState);
return false;
}
// Support for TestOutputTruncation added in version 5.
if (v < 5 && preset.Output && preset.Output->TestOutputTruncation) {
return ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED;
cmCMakePresetErrors::TEST_OUTPUT_TRUNCATION_UNSUPPORTED(
&this->parseState);
return false;
}
// Support for outputJUnitFile added in version 6.
if (v < 6 && preset.Output && !preset.Output->OutputJUnitFile.empty()) {
return ReadFileResult::CTEST_JUNIT_UNSUPPORTED;
cmCMakePresetErrors::CTEST_JUNIT_UNSUPPORTED(&this->parseState);
return false;
}
this->TestPresetOrder.push_back(preset.Name);
@@ -597,14 +624,16 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
for (auto& preset : presets.PackagePresets) {
preset.OriginFile = file;
if (preset.Name.empty()) {
return ReadFileResult::INVALID_PRESET;
// No error, already handled by PresetNameHelper
return false;
}
PresetPair<PackagePreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
if (!this->PackagePresets.emplace(preset.Name, presetPair).second) {
return ReadFileResult::DUPLICATE_PRESETS;
cmCMakePresetErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
return false;
}
// Support for conditions added in version 3, but this requires version 5
@@ -616,14 +645,16 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
for (auto& preset : presets.WorkflowPresets) {
preset.OriginFile = file;
if (preset.Name.empty()) {
return ReadFileResult::INVALID_PRESET;
// No error, already handled by PresetNameHelper
return false;
}
PresetPair<WorkflowPreset> presetPair;
presetPair.Unexpanded = preset;
presetPair.Expanded = cm::nullopt;
if (!this->WorkflowPresets.emplace(preset.Name, presetPair).second) {
return ReadFileResult::DUPLICATE_PRESETS;
cmCMakePresetErrors::DUPLICATE_PRESETS(preset.Name, &this->parseState);
return false;
}
// Support for conditions added in version 3, but this requires version 6
@@ -632,21 +663,21 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
this->WorkflowPresetOrder.push_back(preset.Name);
}
auto const includeFile = [this, &inProgressFiles, file](
const std::string& include, RootType rootType2,
ReadReason readReason2,
std::string& FailureMessage) -> ReadFileResult {
ReadFileResult r;
auto const includeFile = [this, &inProgressFiles,
file](const std::string& include,
RootType rootType2, ReadReason readReason2,
std::string& FailureMessage) -> bool {
bool r;
File* includedFile;
if ((r = this->ReadJSONFile(include, rootType2, readReason2,
inProgressFiles, includedFile,
FailureMessage)) != ReadFileResult::READ_OK) {
if ((r =
this->ReadJSONFile(include, rootType2, readReason2, inProgressFiles,
includedFile, FailureMessage)) != true) {
return r;
}
file->ReachableFiles.insert(includedFile->ReachableFiles.begin(),
includedFile->ReachableFiles.end());
return ReadFileResult::READ_OK;
return true;
};
for (auto include : presets.Include) {
@@ -656,7 +687,7 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
}
if ((result = includeFile(include, rootType, ReadReason::Included,
errMsg)) != ReadFileResult::READ_OK) {
errMsg)) != true) {
return result;
}
}
@@ -665,13 +696,12 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
auto cmakePresetsFilename = GetFilename(this->SourceDir);
if (cmSystemTools::FileExists(cmakePresetsFilename)) {
if ((result = includeFile(cmakePresetsFilename, RootType::Project,
ReadReason::Root, errMsg)) !=
ReadFileResult::READ_OK) {
ReadReason::Root, errMsg)) != true) {
return result;
}
}
}
inProgressFiles.pop_back();
return ReadFileResult::READ_OK;
return true;
}
@@ -13,25 +13,27 @@
#include <cm3p/json/value.h>
#include "cmBuildOptions.h"
#include "cmCMakePresetErrors.h"
#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmJSONHelpers.h"
class cmJSONState;
namespace {
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>;
using JSONHelperBuilder = cmJSONHelperBuilder;
ReadFileResult PackageResolveModeHelper(cm::optional<PackageResolveMode>& out,
const Json::Value* value)
bool PackageResolveModeHelper(cm::optional<PackageResolveMode>& out,
const Json::Value* value, cmJSONState* state)
{
if (!value) {
out = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
if (!value->isString()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (value->asString() == "on") {
@@ -41,23 +43,25 @@ ReadFileResult PackageResolveModeHelper(cm::optional<PackageResolveMode>& out,
} else if (value->asString() == "only") {
out = PackageResolveMode::OnlyResolve;
} else {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
return ReadFileResult::READ_OK;
return true;
}
std::function<ReadFileResult(BuildPreset&, const Json::Value*)> const
ResolvePackageReferencesHelper =
[](BuildPreset& out, const Json::Value* value) -> ReadFileResult {
return PackageResolveModeHelper(out.ResolvePackageReferences, value);
std::function<bool(BuildPreset&, const Json::Value*, cmJSONState*)> const
ResolvePackageReferencesHelper = [](BuildPreset& out,
const Json::Value* value,
cmJSONState* state) -> bool {
return PackageResolveModeHelper(out.ResolvePackageReferences, value, state);
};
auto const BuildPresetHelper =
JSONHelperBuilder::Object<BuildPreset>(ReadFileResult::READ_OK,
ReadFileResult::INVALID_PRESET, false)
JSONHelperBuilder::Object<BuildPreset>(
cmCMakePresetErrors::INVALID_PRESET_OBJECT, false)
.Bind("name"_s, &BuildPreset::Name,
cmCMakePresetsGraphInternal::PresetStringHelper)
cmCMakePresetsGraphInternal::PresetNameHelper)
.Bind("inherits"_s, &BuildPreset::Inherits,
cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
false)
@@ -65,7 +69,7 @@ auto const BuildPresetHelper =
cmCMakePresetsGraphInternal::PresetBoolHelper, false)
.Bind<std::nullptr_t>("vendor"_s, nullptr,
cmCMakePresetsGraphInternal::VendorHelper(
ReadFileResult::INVALID_PRESET),
cmCMakePresetErrors::INVALID_PRESET),
false)
.Bind("displayName"_s, &BuildPreset::DisplayName,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
@@ -97,13 +101,12 @@ auto const BuildPresetHelper =
}
namespace cmCMakePresetsGraphInternal {
ReadFileResult BuildPresetsHelper(std::vector<BuildPreset>& out,
const Json::Value* value)
bool BuildPresetsHelper(std::vector<BuildPreset>& out,
const Json::Value* value, cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Vector<BuildPreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
BuildPresetHelper);
cmCMakePresetErrors::INVALID_PRESETS, BuildPresetHelper);
return helper(out, value);
return helper(out, value, state);
}
}
@@ -12,72 +12,77 @@
#include <cm3p/json/value.h>
#include "cmCMakePresetErrors.h"
#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmJSONHelpers.h"
#include "cmJSONState.h"
namespace {
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using CacheVariable = cmCMakePresetsGraph::CacheVariable;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>;
using JSONHelperBuilder = cmJSONHelperBuilder;
ReadFileResult ArchToolsetStrategyHelper(
cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
bool ArchToolsetStrategyHelper(cm::optional<ArchToolsetStrategy>& out,
const Json::Value* value, cmJSONState* state)
{
if (!value) {
out = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
if (!value->isString()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (value->asString() == "set") {
out = ArchToolsetStrategy::Set;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "external") {
out = ArchToolsetStrategy::External;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
std::function<bool(ConfigurePreset&, const Json::Value*, cmJSONState*)>
ArchToolsetHelper(
std::string ConfigurePreset::*valueField,
cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
{
auto const objectHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
JSONHelperBuilder::Object<ConfigurePreset>(JsonErrors::INVALID_OBJECT,
false)
.Bind("value", valueField,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
.Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
return [valueField, strategyField, objectHelper](
ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
return [valueField, strategyField,
objectHelper](ConfigurePreset& out, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
(out.*valueField).clear();
out.*strategyField = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
if (value->isString()) {
out.*valueField = value->asString();
out.*strategyField = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
if (value->isObject()) {
return objectHelper(out, value);
return objectHelper(out, value, state);
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
};
}
@@ -86,65 +91,66 @@ auto const ArchitectureHelper = ArchToolsetHelper(
auto const ToolsetHelper = ArchToolsetHelper(
&ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
auto const VariableStringHelper = JSONHelperBuilder::String(
ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
auto const VariableStringHelper = JSONHelperBuilder::String();
ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
bool VariableValueHelper(std::string& out, const Json::Value* value,
cmJSONState* state)
{
if (!value) {
out.clear();
return ReadFileResult::READ_OK;
return true;
}
if (value->isBool()) {
out = value->asBool() ? "TRUE" : "FALSE";
return ReadFileResult::READ_OK;
return true;
}
return VariableStringHelper(out, value);
return VariableStringHelper(out, value, state);
}
auto const VariableObjectHelper =
JSONHelperBuilder::Object<CacheVariable>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
cmCMakePresetErrors::INVALID_VARIABLE_OBJECT, false)
.Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
.Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
const Json::Value* value)
bool VariableHelper(cm::optional<CacheVariable>& out, const Json::Value* value,
cmJSONState* state)
{
if (value->isBool()) {
out = CacheVariable{
/*Type=*/"BOOL",
/*Value=*/value->asBool() ? "TRUE" : "FALSE",
};
return ReadFileResult::READ_OK;
return true;
}
if (value->isString()) {
out = CacheVariable{
/*Type=*/"",
/*Value=*/value->asString(),
};
return ReadFileResult::READ_OK;
return true;
}
if (value->isObject()) {
out.emplace();
return VariableObjectHelper(*out, value);
return VariableObjectHelper(*out, value, state);
}
if (value->isNull()) {
out = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_VARIABLE;
cmCMakePresetErrors::INVALID_VARIABLE(value, state);
return false;
}
auto const VariablesHelper =
JSONHelperBuilder::Map<cm::optional<CacheVariable>>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
cmCMakePresetErrors::INVALID_PRESET, VariableHelper);
auto const PresetWarningsHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
JsonErrors::INVALID_NAMED_OBJECT_KEY, false)
.Bind("dev"_s, &ConfigurePreset::WarnDev,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
@@ -158,7 +164,7 @@ auto const PresetWarningsHelper =
auto const PresetErrorsHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
JsonErrors::INVALID_NAMED_OBJECT_KEY, false)
.Bind("dev"_s, &ConfigurePreset::ErrorDev,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
@@ -166,7 +172,7 @@ auto const PresetErrorsHelper =
auto const PresetDebugHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
JsonErrors::INVALID_NAMED_OBJECT_KEY, false)
.Bind("output"_s, &ConfigurePreset::DebugOutput,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
@@ -176,9 +182,9 @@ auto const PresetDebugHelper =
auto const ConfigurePresetHelper =
JSONHelperBuilder::Object<ConfigurePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
cmCMakePresetErrors::INVALID_PRESET_OBJECT, false)
.Bind("name"_s, &ConfigurePreset::Name,
cmCMakePresetsGraphInternal::PresetStringHelper)
cmCMakePresetsGraphInternal::PresetNameHelper)
.Bind("inherits"_s, &ConfigurePreset::Inherits,
cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
false)
@@ -186,7 +192,7 @@ auto const ConfigurePresetHelper =
cmCMakePresetsGraphInternal::PresetBoolHelper, false)
.Bind<std::nullptr_t>("vendor"_s, nullptr,
cmCMakePresetsGraphInternal::VendorHelper(
ReadFileResult::INVALID_PRESET),
cmCMakePresetErrors::INVALID_PRESET),
false)
.Bind("displayName"_s, &ConfigurePreset::DisplayName,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
@@ -216,13 +222,12 @@ auto const ConfigurePresetHelper =
}
namespace cmCMakePresetsGraphInternal {
ReadFileResult ConfigurePresetsHelper(std::vector<ConfigurePreset>& out,
const Json::Value* value)
bool ConfigurePresetsHelper(std::vector<ConfigurePreset>& out,
const Json::Value* value, cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Vector<ConfigurePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
ConfigurePresetHelper);
cmCMakePresetErrors::INVALID_PRESETS, ConfigurePresetHelper);
return helper(out, value);
return helper(out, value, state);
}
}
@@ -12,34 +12,34 @@
#include <cm3p/json/value.h>
#include "cmCMakePresetErrors.h"
#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmJSONHelpers.h"
class cmJSONState;
namespace {
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using PackagePreset = cmCMakePresetsGraph::PackagePreset;
auto const OutputHelper =
cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
cmJSONHelperBuilder::Object<PackagePreset>(
JsonErrors::INVALID_NAMED_OBJECT_KEY, false)
.Bind("debug"_s, &PackagePreset::DebugOutput,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("verbose"_s, &PackagePreset::VerboseOutput,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
auto const VariableHelper = cmJSONHelperBuilder<ReadFileResult>::String(
ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
auto const VariableHelper =
cmJSONHelperBuilder::String(cmCMakePresetErrors::INVALID_VARIABLE);
auto const VariablesHelper =
cmJSONHelperBuilder<ReadFileResult>::Map<std::string>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
auto const VariablesHelper = cmJSONHelperBuilder::Map<std::string>(
cmCMakePresetErrors::INVALID_VARIABLE, VariableHelper);
auto const PackagePresetHelper =
cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
cmJSONHelperBuilder::Object<PackagePreset>(
cmCMakePresetErrors::INVALID_PRESET_OBJECT, false)
.Bind("name"_s, &PackagePreset::Name,
cmCMakePresetsGraphInternal::PresetStringHelper)
cmCMakePresetsGraphInternal::PresetNameHelper)
.Bind("inherits"_s, &PackagePreset::Inherits,
cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
false)
@@ -47,7 +47,7 @@ auto const PackagePresetHelper =
cmCMakePresetsGraphInternal::PresetBoolHelper, false)
.Bind<std::nullptr_t>("vendor"_s, nullptr,
cmCMakePresetsGraphInternal::VendorHelper(
ReadFileResult::INVALID_PRESET),
cmCMakePresetErrors::INVALID_PRESET),
false)
.Bind("displayName"_s, &PackagePreset::DisplayName,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
@@ -81,15 +81,12 @@ auto const PackagePresetHelper =
}
namespace cmCMakePresetsGraphInternal {
cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper(
std::vector<cmCMakePresetsGraph::PackagePreset>& out,
const Json::Value* value)
bool PackagePresetsHelper(std::vector<cmCMakePresetsGraph::PackagePreset>& out,
const Json::Value* value, cmJSONState* state)
{
static auto const helper =
cmJSONHelperBuilder<ReadFileResult>::Vector<PackagePreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
PackagePresetHelper);
static auto const helper = cmJSONHelperBuilder::Vector<PackagePreset>(
cmCMakePresetErrors::INVALID_PRESETS, PackagePresetHelper);
return helper(out, value);
return helper(out, value, state);
}
}
@@ -12,86 +12,93 @@
#include <cm3p/json/value.h>
#include "cmCMakePresetErrors.h"
#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmJSONHelpers.h"
#include "CTest/cmCTestTypes.h"
namespace {
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using TestPreset = cmCMakePresetsGraph::TestPreset;
using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>;
class cmJSONState;
ReadFileResult TestPresetOutputVerbosityHelper(
TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value)
namespace {
using TestPreset = cmCMakePresetsGraph::TestPreset;
using JSONHelperBuilder = cmJSONHelperBuilder;
bool TestPresetOutputVerbosityHelper(
TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value,
cmJSONState* state)
{
if (!value) {
out = TestPreset::OutputOptions::VerbosityEnum::Default;
return ReadFileResult::READ_OK;
return true;
}
if (!value->isString()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (value->asString() == "default") {
out = TestPreset::OutputOptions::VerbosityEnum::Default;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "verbose") {
out = TestPreset::OutputOptions::VerbosityEnum::Verbose;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "extra") {
out = TestPreset::OutputOptions::VerbosityEnum::Extra;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
auto const TestPresetOptionalOutputVerbosityHelper =
JSONHelperBuilder::Optional<TestPreset::OutputOptions::VerbosityEnum>(
ReadFileResult::READ_OK, TestPresetOutputVerbosityHelper);
TestPresetOutputVerbosityHelper);
ReadFileResult TestPresetOutputTruncationHelper(
cm::optional<cmCTestTypes::TruncationMode>& out, const Json::Value* value)
bool TestPresetOutputTruncationHelper(
cm::optional<cmCTestTypes::TruncationMode>& out, const Json::Value* value,
cmJSONState* state)
{
if (!value) {
out = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
if (!value->isString()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (value->asString() == "tail") {
out = cmCTestTypes::TruncationMode::Tail;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "middle") {
out = cmCTestTypes::TruncationMode::Middle;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "head") {
out = cmCTestTypes::TruncationMode::Head;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
auto const TestPresetOptionalOutputHelper =
JSONHelperBuilder::Optional<TestPreset::OutputOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::OutputOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
JsonErrors::INVALID_OBJECT, false)
.Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity,
@@ -125,9 +132,7 @@ auto const TestPresetOptionalOutputHelper =
auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
JSONHelperBuilder::Optional<TestPreset::IncludeOptions::IndexOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::IncludeOptions::IndexOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
JSONHelperBuilder::Object<TestPreset::IncludeOptions::IndexOptions>()
.Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start,
cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
.Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End,
@@ -138,33 +143,31 @@ auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
&TestPreset::IncludeOptions::IndexOptions::SpecificTests,
cmCMakePresetsGraphInternal::PresetVectorIntHelper, false));
ReadFileResult TestPresetOptionalFilterIncludeIndexHelper(
bool TestPresetOptionalFilterIncludeIndexHelper(
cm::optional<TestPreset::IncludeOptions::IndexOptions>& out,
const Json::Value* value)
const Json::Value* value, cmJSONState* state)
{
if (!value) {
out = cm::nullopt;
return ReadFileResult::READ_OK;
return true;
}
if (value->isString()) {
out.emplace();
out->IndexFile = value->asString();
return ReadFileResult::READ_OK;
return true;
}
if (value->isObject()) {
return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value);
return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value, state);
}
return ReadFileResult::INVALID_PRESET;
return false;
}
auto const TestPresetOptionalFilterIncludeHelper =
JSONHelperBuilder::Optional<TestPreset::IncludeOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::IncludeOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
JSONHelperBuilder::Object<TestPreset::IncludeOptions>()
.Bind("name"_s, &TestPreset::IncludeOptions::Name,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
.Bind("label"_s, &TestPreset::IncludeOptions::Label,
@@ -176,9 +179,7 @@ auto const TestPresetOptionalFilterIncludeHelper =
auto const TestPresetOptionalFilterExcludeFixturesHelper =
JSONHelperBuilder::Optional<TestPreset::ExcludeOptions::FixturesOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::ExcludeOptions::FixturesOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
JSONHelperBuilder::Object<TestPreset::ExcludeOptions::FixturesOptions>()
.Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
.Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup,
@@ -188,9 +189,7 @@ auto const TestPresetOptionalFilterExcludeFixturesHelper =
auto const TestPresetOptionalFilterExcludeHelper =
JSONHelperBuilder::Optional<TestPreset::ExcludeOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::ExcludeOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
JSONHelperBuilder::Object<TestPreset::ExcludeOptions>()
.Bind("name"_s, &TestPreset::ExcludeOptions::Name,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
.Bind("label"_s, &TestPreset::ExcludeOptions::Label,
@@ -198,110 +197,113 @@ auto const TestPresetOptionalFilterExcludeHelper =
.Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures,
TestPresetOptionalFilterExcludeFixturesHelper, false));
ReadFileResult TestPresetExecutionShowOnlyHelper(
TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value)
bool TestPresetExecutionShowOnlyHelper(
TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value,
cmJSONState* state)
{
if (!value || !value->isString()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (value->asString() == "human") {
out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "json-v1") {
out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
auto const TestPresetOptionalExecutionShowOnlyHelper =
JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::ShowOnlyEnum>(
ReadFileResult::READ_OK, TestPresetExecutionShowOnlyHelper);
TestPresetExecutionShowOnlyHelper);
ReadFileResult TestPresetExecutionModeHelper(
bool TestPresetExecutionModeHelper(
TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out,
const Json::Value* value)
const Json::Value* value, cmJSONState* state)
{
if (!value) {
return ReadFileResult::READ_OK;
return true;
}
if (!value->isString()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (value->asString() == "until-fail") {
out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "until-pass") {
out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "after-timeout") {
out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
auto const TestPresetOptionalExecutionRepeatHelper =
JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::RepeatOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::ExecutionOptions::RepeatOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
JSONHelperBuilder::Object<TestPreset::ExecutionOptions::RepeatOptions>()
.Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode,
TestPresetExecutionModeHelper, true)
.Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count,
cmCMakePresetsGraphInternal::PresetIntHelper, true));
ReadFileResult TestPresetExecutionNoTestsActionHelper(
bool TestPresetExecutionNoTestsActionHelper(
TestPreset::ExecutionOptions::NoTestsActionEnum& out,
const Json::Value* value)
const Json::Value* value, cmJSONState* state)
{
if (!value) {
out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
return ReadFileResult::READ_OK;
return true;
}
if (!value->isString()) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (value->asString() == "default") {
out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "error") {
out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "ignore") {
out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
auto const TestPresetOptionalExecutionNoTestsActionHelper =
JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::NoTestsActionEnum>(
ReadFileResult::READ_OK, TestPresetExecutionNoTestsActionHelper);
TestPresetExecutionNoTestsActionHelper);
auto const TestPresetExecutionHelper =
JSONHelperBuilder::Optional<TestPreset::ExecutionOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::ExecutionOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
JSONHelperBuilder::Object<TestPreset::ExecutionOptions>()
.Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure,
cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
.Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover,
@@ -329,19 +331,17 @@ auto const TestPresetExecutionHelper =
auto const TestPresetFilterHelper =
JSONHelperBuilder::Optional<TestPreset::FilterOptions>(
ReadFileResult::READ_OK,
JSONHelperBuilder::Object<TestPreset::FilterOptions>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
JSONHelperBuilder::Object<TestPreset::FilterOptions>()
.Bind("include"_s, &TestPreset::FilterOptions::Include,
TestPresetOptionalFilterIncludeHelper, false)
.Bind("exclude"_s, &TestPreset::FilterOptions::Exclude,
TestPresetOptionalFilterExcludeHelper, false));
auto const TestPresetHelper =
JSONHelperBuilder::Object<TestPreset>(ReadFileResult::READ_OK,
ReadFileResult::INVALID_PRESET, false)
JSONHelperBuilder::Object<TestPreset>(
cmCMakePresetErrors::INVALID_PRESET_OBJECT, false)
.Bind("name"_s, &TestPreset::Name,
cmCMakePresetsGraphInternal::PresetStringHelper)
cmCMakePresetsGraphInternal::PresetNameHelper)
.Bind("inherits"_s, &TestPreset::Inherits,
cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
false)
@@ -349,7 +349,7 @@ auto const TestPresetHelper =
cmCMakePresetsGraphInternal::PresetBoolHelper, false)
.Bind<std::nullptr_t>("vendor"_s, nullptr,
cmCMakePresetsGraphInternal::VendorHelper(
ReadFileResult::INVALID_PRESET),
cmCMakePresetErrors::INVALID_PRESET),
false)
.Bind("displayName"_s, &TestPreset::DisplayName,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
@@ -377,13 +377,12 @@ auto const TestPresetHelper =
}
namespace cmCMakePresetsGraphInternal {
cmCMakePresetsGraph::ReadFileResult TestPresetsHelper(
std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value)
bool TestPresetsHelper(std::vector<cmCMakePresetsGraph::TestPreset>& out,
const Json::Value* value, cmJSONState* state)
{
static auto const helper = JSONHelperBuilder::Vector<TestPreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
TestPresetHelper);
cmCMakePresetErrors::INVALID_PRESETS, TestPresetHelper);
return helper(out, value);
return helper(out, value, state);
}
}
@@ -9,69 +9,72 @@
#include <cm3p/json/value.h>
#include "cmCMakePresetErrors.h"
#include "cmCMakePresetsGraph.h"
#include "cmCMakePresetsGraphInternal.h"
#include "cmJSONHelpers.h"
class cmJSONState;
namespace {
using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
ReadFileResult WorkflowStepTypeHelper(WorkflowPreset::WorkflowStep::Type& out,
const Json::Value* value)
bool WorkflowStepTypeHelper(WorkflowPreset::WorkflowStep::Type& out,
const Json::Value* value, cmJSONState* state)
{
if (!value) {
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
if (!value->isString()) {
return ReadFileResult::INVALID_PRESET;
return false;
}
if (value->asString() == "configure") {
out = WorkflowPreset::WorkflowStep::Type::Configure;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "build") {
out = WorkflowPreset::WorkflowStep::Type::Build;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "test") {
out = WorkflowPreset::WorkflowStep::Type::Test;
return ReadFileResult::READ_OK;
return true;
}
if (value->asString() == "package") {
out = WorkflowPreset::WorkflowStep::Type::Package;
return ReadFileResult::READ_OK;
return true;
}
return ReadFileResult::INVALID_PRESET;
cmCMakePresetErrors::INVALID_PRESET(value, state);
return false;
}
auto const WorkflowStepHelper =
cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset::WorkflowStep>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
cmJSONHelperBuilder::Object<WorkflowPreset::WorkflowStep>(
JsonErrors::INVALID_OBJECT, false)
.Bind("type"_s, &WorkflowPreset::WorkflowStep::PresetType,
WorkflowStepTypeHelper)
.Bind("name"_s, &WorkflowPreset::WorkflowStep::PresetName,
cmCMakePresetsGraphInternal::PresetStringHelper);
auto const WorkflowStepsHelper =
cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset::WorkflowStep>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
WorkflowStepHelper);
cmJSONHelperBuilder::Vector<WorkflowPreset::WorkflowStep>(
cmCMakePresetErrors::INVALID_PRESET, WorkflowStepHelper);
auto const WorkflowPresetHelper =
cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
cmJSONHelperBuilder::Object<WorkflowPreset>(
cmCMakePresetErrors::INVALID_PRESET_OBJECT, false)
.Bind("name"_s, &WorkflowPreset::Name,
cmCMakePresetsGraphInternal::PresetStringHelper)
cmCMakePresetsGraphInternal::PresetNameHelper)
.Bind<std::nullptr_t>("vendor"_s, nullptr,
cmCMakePresetsGraphInternal::VendorHelper(
ReadFileResult::INVALID_PRESET),
cmCMakePresetErrors::INVALID_PRESET),
false)
.Bind("displayName"_s, &WorkflowPreset::DisplayName,
cmCMakePresetsGraphInternal::PresetStringHelper, false)
@@ -81,15 +84,13 @@ auto const WorkflowPresetHelper =
}
namespace cmCMakePresetsGraphInternal {
cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper(
bool WorkflowPresetsHelper(
std::vector<cmCMakePresetsGraph::WorkflowPreset>& out,
const Json::Value* value)
const Json::Value* value, cmJSONState* state)
{
static auto const helper =
cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
WorkflowPresetHelper);
static auto const helper = cmJSONHelperBuilder::Vector<WorkflowPreset>(
cmCMakePresetErrors::INVALID_PRESETS, WorkflowPresetHelper);
return helper(out, value);
return helper(out, value, state);
}
}
+5 -4
View File
@@ -54,6 +54,7 @@
#include "cmDynamicLoader.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmJSONState.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
#include "cmState.h"
@@ -2336,10 +2337,10 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
cmCMakePresetsGraph settingsFile;
auto result = settingsFile.ReadProjectPresets(workingDirectory);
if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
cmSystemTools::Error(
cmStrCat("Could not read presets from ", workingDirectory, ": ",
cmCMakePresetsGraph::ResultToString(result)));
if (result != true) {
cmSystemTools::Error(cmStrCat("Could not read presets from ",
workingDirectory, ":",
settingsFile.parseState.GetErrorMessage()));
return false;
}
+258 -94
View File
@@ -2,9 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <vector>
@@ -14,20 +17,129 @@
#include <cm3p/json/value.h>
template <typename T, typename E, typename... CallState>
#include "cmJSONState.h"
template <typename T>
using cmJSONHelper =
std::function<E(T& out, const Json::Value* value, CallState&&... state)>;
std::function<bool(T& out, const Json::Value* value, cmJSONState* state)>;
using ErrorGenerator = std::function<void(const Json::Value*, cmJSONState*)>;
namespace JsonErrors {
enum ObjectError
{
RequiredMissing,
InvalidObject,
ExtraField,
MissingRequired
};
using ErrorGenerator = std::function<void(const Json::Value*, cmJSONState*)>;
using ObjectErrorGenerator =
std::function<ErrorGenerator(ObjectError, const Json::Value::Members&)>;
const auto EXPECTED_TYPE = [](const std::string& type) {
return [type](const Json::Value* value, cmJSONState* state) -> void {
#if !defined(CMAKE_BOOTSTRAP)
if (state->key().empty()) {
state->AddErrorAtValue(cmStrCat("Expected ", type), value);
return;
}
std::string errMsg = cmStrCat("\"", state->key(), "\" expected ", type);
if (value && value->isConvertibleTo(Json::ValueType::stringValue)) {
errMsg = cmStrCat(errMsg, ", got: ", value->asString());
}
state->AddErrorAtValue(errMsg, value);
#endif
};
};
const auto INVALID_STRING = [](const Json::Value* value,
cmJSONState* state) -> void {
JsonErrors::EXPECTED_TYPE("a string")(value, state);
};
const auto INVALID_BOOL = [](const Json::Value* value,
cmJSONState* state) -> void {
JsonErrors::EXPECTED_TYPE("a bool")(value, state);
};
const auto INVALID_INT = [](const Json::Value* value,
cmJSONState* state) -> void {
JsonErrors::EXPECTED_TYPE("an integer")(value, state);
};
const auto INVALID_UINT = [](const Json::Value* value,
cmJSONState* state) -> void {
JsonErrors::EXPECTED_TYPE("an unsigned integer")(value, state);
};
const auto INVALID_NAMED_OBJECT =
[](const std::function<std::string(const Json::Value*, cmJSONState*)>&
nameGenerator) -> ObjectErrorGenerator {
return [nameGenerator](
ObjectError errorType,
const Json::Value::Members& extraFields) -> ErrorGenerator {
return [nameGenerator, errorType, extraFields](
const Json::Value* value, cmJSONState* state) -> void {
#if !defined(CMAKE_BOOTSTRAP)
std::string name = nameGenerator(value, state);
switch (errorType) {
case ObjectError::RequiredMissing:
state->AddErrorAtValue(cmStrCat("Invalid Required ", name), value);
break;
case ObjectError::InvalidObject:
state->AddErrorAtValue(cmStrCat("Invalid ", name), value);
break;
case ObjectError::ExtraField: {
for (auto const& member : extraFields) {
if (value) {
state->AddErrorAtValue(
cmStrCat("Invalid extra field \"", member, "\" in ", name),
&(*value)[member]);
} else {
state->AddError(
cmStrCat("Invalid extra field \"", member, "\" in ", name));
}
}
} break;
case ObjectError::MissingRequired:
state->AddErrorAtValue(cmStrCat("Missing required field \"",
state->key(), "\" in ", name),
value);
break;
}
#endif
};
};
};
const auto INVALID_OBJECT =
[](ObjectError errorType,
const Json::Value::Members& extraFields) -> ErrorGenerator {
return INVALID_NAMED_OBJECT(
[](const Json::Value*, cmJSONState*) -> std::string { return "Object"; })(
errorType, extraFields);
};
const auto INVALID_NAMED_OBJECT_KEY =
[](ObjectError errorType,
const Json::Value::Members& extraFields) -> ErrorGenerator {
return INVALID_NAMED_OBJECT(
[](const Json::Value*, cmJSONState* state) -> std::string {
for (auto it = state->parseStack.rbegin();
it != state->parseStack.rend(); ++it) {
if (it->first.rfind("$vector_item_", 0) == 0) {
continue;
}
return cmStrCat("\"", it->first, "\"");
}
return "root";
})(errorType, extraFields);
};
}
template <typename E, typename... CallState>
struct cmJSONHelperBuilder
{
template <typename T>
class Object
{
public:
Object(E&& success, E&& fail, bool allowExtra = true)
: Success(std::move(success))
, Fail(std::move(fail))
Object(JsonErrors::ObjectErrorGenerator error = JsonErrors::INVALID_OBJECT,
bool allowExtra = true)
: Error(std::move(error))
, AllowExtra(allowExtra)
{
}
@@ -38,8 +150,8 @@ struct cmJSONHelperBuilder
{
return this->BindPrivate(
name,
[func, member](T& out, const Json::Value* value, CallState&&... state)
-> E { return func(out.*member, value, std::forward(state)...); },
[func, member](T& out, const Json::Value* value, cmJSONState* state)
-> bool { return func(out.*member, value, state); },
required);
}
template <typename M, typename F>
@@ -49,9 +161,9 @@ struct cmJSONHelperBuilder
return this->BindPrivate(
name,
[func](T& /*out*/, const Json::Value* value,
CallState&&... state) -> E {
cmJSONState* state) -> bool {
M dummy;
return func(dummy, value, std::forward(state)...);
return func(dummy, value, state);
},
required);
}
@@ -61,46 +173,56 @@ struct cmJSONHelperBuilder
return this->BindPrivate(name, MemberFunction(func), required);
}
E operator()(T& out, const Json::Value* value, CallState&&... state) const
bool operator()(T& out, const Json::Value* value, cmJSONState* state) const
{
Json::Value::Members extraFields;
bool success = true;
if (!value && this->AnyRequired) {
return this->Fail;
Error(JsonErrors::ObjectError::RequiredMissing, extraFields)(value,
state);
return false;
}
if (value && !value->isObject()) {
return this->Fail;
Error(JsonErrors::ObjectError::InvalidObject, extraFields)(value,
state);
return false;
}
Json::Value::Members extraFields;
if (value) {
extraFields = value->getMemberNames();
}
for (auto const& m : this->Members) {
std::string name(m.Name.data(), m.Name.size());
state->push_stack(name, value);
if (value && value->isMember(name)) {
E result = m.Function(out, &(*value)[name], std::forward(state)...);
if (result != this->Success) {
return result;
if (!m.Function(out, &(*value)[name], state)) {
success = false;
}
extraFields.erase(
std::find(extraFields.begin(), extraFields.end(), name));
} else if (!m.Required) {
E result = m.Function(out, nullptr, std::forward(state)...);
if (result != this->Success) {
return result;
if (!m.Function(out, nullptr, state)) {
success = false;
}
} else {
return this->Fail;
Error(JsonErrors::ObjectError::MissingRequired, extraFields)(value,
state);
success = false;
}
state->pop_stack();
}
return this->AllowExtra || extraFields.empty() ? this->Success
: this->Fail;
if (!this->AllowExtra && !extraFields.empty()) {
Error(JsonErrors::ObjectError::ExtraField, extraFields)(value, state);
success = false;
}
return success;
}
private:
// Not a true cmJSONHelper, it just happens to match the signature
using MemberFunction =
std::function<E(T& out, const Json::Value* value, CallState&&... state)>;
using MemberFunction = std::function<bool(T& out, const Json::Value* value,
cmJSONState* state)>;
struct Member
{
cm::string_view Name;
@@ -109,8 +231,7 @@ struct cmJSONHelperBuilder
};
std::vector<Member> Members;
bool AnyRequired = false;
E Success;
E Fail;
JsonErrors::ObjectErrorGenerator Error;
bool AllowExtra;
Object& BindPrivate(const cm::string_view& name, MemberFunction&& func,
@@ -127,175 +248,218 @@ struct cmJSONHelperBuilder
return *this;
}
};
static cmJSONHelper<std::string, E, CallState...> String(
E success, E fail, const std::string& defval = "")
static cmJSONHelper<std::string> String(
const JsonErrors::ErrorGenerator& error = JsonErrors::INVALID_STRING,
const std::string& defval = "")
{
return [success, fail, defval](std::string& out, const Json::Value* value,
CallState&&... /*state*/) -> E {
return [error, defval](std::string& out, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
out = defval;
return success;
return true;
}
if (!value->isString()) {
return fail;
error(value, state);
;
return false;
}
out = value->asString();
return success;
return true;
};
}
};
static cmJSONHelper<int, E, CallState...> Int(E success, E fail,
int defval = 0)
static cmJSONHelper<std::string> String(const std::string& defval)
{
return [success, fail, defval](int& out, const Json::Value* value,
CallState&&... /*state*/) -> E {
return String(JsonErrors::INVALID_STRING, defval);
};
static cmJSONHelper<int> Int(
const JsonErrors::ErrorGenerator& error = JsonErrors::INVALID_INT,
int defval = 0)
{
return [error, defval](int& out, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
out = defval;
return success;
return true;
}
if (!value->isInt()) {
return fail;
error(value, state);
;
return false;
}
out = value->asInt();
return success;
return true;
};
}
static cmJSONHelper<unsigned int, E, CallState...> UInt(
E success, E fail, unsigned int defval = 0)
static cmJSONHelper<int> Int(int defval)
{
return [success, fail, defval](unsigned int& out, const Json::Value* value,
CallState&&... /*state*/) -> E {
return Int(JsonErrors::INVALID_INT, defval);
};
static cmJSONHelper<unsigned int> UInt(
const JsonErrors::ErrorGenerator& error = JsonErrors::INVALID_UINT,
unsigned int defval = 0)
{
return [error, defval](unsigned int& out, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
out = defval;
return success;
return true;
}
if (!value->isUInt()) {
return fail;
error(value, state);
;
return false;
}
out = value->asUInt();
return success;
return true;
};
}
static cmJSONHelper<bool, E, CallState...> Bool(E success, E fail,
bool defval = false)
static cmJSONHelper<unsigned int> UInt(unsigned int defval)
{
return [success, fail, defval](bool& out, const Json::Value* value,
CallState&&... /*state*/) -> E {
return UInt(JsonErrors::INVALID_UINT, defval);
}
static cmJSONHelper<bool> Bool(
const JsonErrors::ErrorGenerator& error = JsonErrors::INVALID_BOOL,
bool defval = false)
{
return [error, defval](bool& out, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
out = defval;
return success;
return true;
}
if (!value->isBool()) {
return fail;
error(value, state);
;
return false;
}
out = value->asBool();
return success;
return true;
};
}
static cmJSONHelper<bool> Bool(bool defval)
{
return Bool(JsonErrors::INVALID_BOOL, defval);
}
template <typename T, typename F, typename Filter>
static cmJSONHelper<std::vector<T>, E, CallState...> VectorFilter(
E success, E fail, F func, Filter filter)
static cmJSONHelper<std::vector<T>> VectorFilter(
const JsonErrors::ErrorGenerator& error, F func, Filter filter)
{
return [success, fail, func, filter](std::vector<T>& out,
const Json::Value* value,
CallState&&... state) -> E {
return [error, func, filter](std::vector<T>& out, const Json::Value* value,
cmJSONState* state) -> bool {
bool success = true;
if (!value) {
out.clear();
return success;
return true;
}
if (!value->isArray()) {
return fail;
error(value, state);
return false;
}
out.clear();
int index = 0;
for (auto const& item : *value) {
state->push_stack(cmStrCat("$vector_item_", index++), &item);
T t;
E result = func(t, &item, std::forward(state)...);
if (result != success) {
return result;
if (!func(t, &item, state)) {
success = false;
}
if (!filter(t)) {
state->pop_stack();
continue;
}
out.push_back(std::move(t));
state->pop_stack();
}
return success;
};
}
template <typename T, typename F>
static cmJSONHelper<std::vector<T>, E, CallState...> Vector(E success,
E fail, F func)
static cmJSONHelper<std::vector<T>> Vector(JsonErrors::ErrorGenerator error,
F func)
{
return VectorFilter<T, F>(success, fail, func,
return VectorFilter<T, F>(std::move(error), func,
[](const T&) { return true; });
}
template <typename T, typename F, typename Filter>
static cmJSONHelper<std::map<std::string, T>, E, CallState...> MapFilter(
E success, E fail, F func, Filter filter)
static cmJSONHelper<std::map<std::string, T>> MapFilter(
const JsonErrors::ErrorGenerator& error, F func, Filter filter)
{
return [success, fail, func, filter](std::map<std::string, T>& out,
const Json::Value* value,
CallState&&... state) -> E {
return [error, func, filter](std::map<std::string, T>& out,
const Json::Value* value,
cmJSONState* state) -> bool {
bool success = true;
if (!value) {
out.clear();
return success;
return true;
}
if (!value->isObject()) {
return fail;
error(value, state);
;
return false;
}
out.clear();
for (auto const& key : value->getMemberNames()) {
state->push_stack(cmStrCat(key, ""), &(*value)[key]);
if (!filter(key)) {
state->pop_stack();
continue;
}
T t;
E result = func(t, &(*value)[key], std::forward(state)...);
if (result != success) {
return result;
if (!func(t, &(*value)[key], state)) {
success = false;
}
out[key] = std::move(t);
state->pop_stack();
}
return success;
};
}
template <typename T, typename F>
static cmJSONHelper<std::map<std::string, T>, E, CallState...> Map(E success,
E fail,
F func)
static cmJSONHelper<std::map<std::string, T>> Map(
const JsonErrors::ErrorGenerator& error, F func)
{
return MapFilter<T, F>(success, fail, func,
return MapFilter<T, F>(error, func,
[](const std::string&) { return true; });
}
template <typename T, typename F>
static cmJSONHelper<cm::optional<T>, E, CallState...> Optional(E success,
F func)
static cmJSONHelper<cm::optional<T>> Optional(F func)
{
return [success, func](cm::optional<T>& out, const Json::Value* value,
CallState&&... state) -> E {
return [func](cm::optional<T>& out, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
out.reset();
return success;
return true;
}
out.emplace();
return func(*out, value, std::forward(state)...);
return func(*out, value, state);
};
}
template <typename T, typename F>
static cmJSONHelper<T, E, CallState...> Required(E fail, F func)
static cmJSONHelper<T> Required(const JsonErrors::ErrorGenerator& error,
F func)
{
return [fail, func](T& out, const Json::Value* value,
CallState&&... state) -> E {
return [error, func](T& out, const Json::Value* value,
cmJSONState* state) -> bool {
if (!value) {
return fail;
error(value, state);
;
return false;
}
return func(out, value, std::forward(state)...);
return func(out, value, state);
};
}
};
+163
View File
@@ -0,0 +1,163 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmJSONState.h"
#include <sstream>
#include <cm/memory>
#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
#include "cmsys/FStream.hxx"
#include "cmStringAlgorithms.h"
cmJSONState::cmJSONState(const std::string& filename, Json::Value* root)
{
cmsys::ifstream fin(filename.c_str(), std::ios::in | std::ios::binary);
if (!fin) {
this->AddError(cmStrCat("File not found: ", filename));
return;
}
// If there's a BOM, toss it.
cmsys::FStream::ReadBOM(fin);
// Save the entire document.
std::streampos finBegin = fin.tellg();
this->doc = std::string(std::istreambuf_iterator<char>(fin),
std::istreambuf_iterator<char>());
if (this->doc.empty()) {
this->AddError("A JSON document cannot be empty");
return;
}
fin.seekg(finBegin);
// Parse the document.
Json::CharReaderBuilder builder;
Json::CharReaderBuilder::strictMode(&builder.settings_);
std::string errMsg;
if (!Json::parseFromStream(builder, fin, root, &errMsg)) {
errMsg = cmStrCat("JSON Parse Error: ", filename, ":\n", errMsg);
this->AddError(errMsg);
}
}
void cmJSONState::AddError(std::string const& errMsg)
{
this->errors.push_back(Error(errMsg));
}
void cmJSONState::AddErrorAtValue(std::string const& errMsg,
const Json::Value* value)
{
if (value && !value->isNull()) {
this->AddErrorAtOffset(errMsg, value->getOffsetStart());
} else {
this->AddError(errMsg);
}
}
void cmJSONState::AddErrorAtOffset(std::string const& errMsg,
std::ptrdiff_t offset)
{
if (doc.empty()) {
this->AddError(errMsg);
} else {
Location loc = LocateInDocument(offset);
this->errors.push_back(Error(loc, errMsg));
}
}
std::string cmJSONState::GetErrorMessage(bool showContext)
{
std::string message;
for (auto const& error : this->errors) {
message = cmStrCat(message, error.GetErrorMessage(), "\n");
if (showContext) {
Location loc = error.GetLocation();
if (loc.column > 0) {
message = cmStrCat(message, GetJsonContext(loc), "\n");
}
}
}
message = cmStrCat("\n", message);
message.pop_back();
return message;
}
std::string cmJSONState::key()
{
if (!this->parseStack.empty()) {
return this->parseStack.back().first;
}
return "";
}
std::string cmJSONState::key_after(std::string const& k)
{
for (auto it = this->parseStack.begin(); it != this->parseStack.end();
++it) {
if (it->first == k && (++it) != this->parseStack.end()) {
return it->first;
}
}
return "";
}
const Json::Value* cmJSONState::value_after(std::string const& k)
{
for (auto it = this->parseStack.begin(); it != this->parseStack.end();
++it) {
if (it->first == k && (++it) != this->parseStack.end()) {
return it->second;
}
}
return nullptr;
}
void cmJSONState::push_stack(std::string const& k, const Json::Value* value)
{
this->parseStack.push_back(JsonPair(k, value));
}
void cmJSONState::pop_stack()
{
this->parseStack.pop_back();
}
std::string cmJSONState::GetJsonContext(Location loc)
{
std::string line;
std::stringstream sstream(doc);
for (int i = 0; i < loc.line; ++i) {
std::getline(sstream, line, '\n');
}
return cmStrCat(line, '\n', std::string(loc.column - 1, ' '), '^');
}
cmJSONState::Location cmJSONState::LocateInDocument(ptrdiff_t offset)
{
int line = 1;
int col = 1;
const char* beginDoc = doc.data();
const char* last = beginDoc + offset;
for (; beginDoc != last; ++beginDoc) {
switch (*beginDoc) {
case '\r':
if (beginDoc + 1 != last && beginDoc[1] == '\n') {
continue; // consume CRLF as a single token.
}
CM_FALLTHROUGH; // CR without a following LF is same as LF
case '\n':
col = 1;
++line;
break;
default:
++col;
break;
}
}
return { line, col };
}
+73
View File
@@ -0,0 +1,73 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <cstddef>
#include <string>
#include <utility>
#include <vector>
#include "cmJSONState.h"
#include "cmStringAlgorithms.h"
namespace Json {
class Value;
}
class cmJSONState
{
using Location = struct
{
int line;
int column;
};
public:
using JsonPair = std::pair<const std::string, const Json::Value*>;
cmJSONState() = default;
cmJSONState(const std::string& filename, Json::Value* root);
void AddError(std::string const& errMsg);
void AddErrorAtValue(std::string const& errMsg, const Json::Value* value);
void AddErrorAtOffset(std::string const& errMsg, std::ptrdiff_t offset);
std::string GetErrorMessage(bool showContext = true);
std::string key();
std::string key_after(std::string const& key);
const Json::Value* value_after(std::string const& key);
void push_stack(std::string const& key, const Json::Value* value);
void pop_stack();
class Error
{
public:
Error(Location loc, std::string errMsg)
: location(loc)
, message(std::move(errMsg)){};
Error(std::string errMsg)
: location({ -1, -1 })
, message(std::move(errMsg)){};
std::string GetErrorMessage() const
{
std::string output = message;
if (location.line > 0) {
output = cmStrCat("Error: @", location.line, ",", location.column,
": ", output);
}
return output;
}
Location GetLocation() const { return location; }
private:
Location location;
std::string message;
};
std::vector<JsonPair> parseStack;
std::vector<Error> errors;
std::string doc;
private:
std::string GetJsonContext(Location loc);
Location LocateInDocument(ptrdiff_t offset);
};
+11 -13
View File
@@ -52,6 +52,7 @@
#if !defined(CMAKE_BOOTSTRAP)
# include "cmMakefileProfilingData.h"
#endif
#include "cmJSONState.h"
#include "cmMessenger.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -1411,13 +1412,10 @@ void cmake::SetArgs(const std::vector<std::string>& args)
if (listPresets != ListPresets::None || !presetName.empty()) {
cmCMakePresetsGraph presetsGraph;
auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory());
if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
if (result != true) {
std::string errorMsg =
cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
": ", cmCMakePresetsGraph::ResultToString(result));
if (!presetsGraph.errors.empty()) {
errorMsg = cmStrCat(errorMsg, "\nErrors:\n", presetsGraph.errors);
}
cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ":",
presetsGraph.parseState.GetErrorMessage());
cmSystemTools::Error(errorMsg);
return;
}
@@ -3426,10 +3424,10 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
cmCMakePresetsGraph settingsFile;
auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
if (result != true) {
cmSystemTools::Error(
cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
": ", cmCMakePresetsGraph::ResultToString(result)));
cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ":",
settingsFile.parseState.GetErrorMessage()));
return 1;
}
@@ -3782,10 +3780,10 @@ int cmake::Workflow(const std::string& presetName,
cmCMakePresetsGraph settingsFile;
auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
cmSystemTools::Error(
cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ": ",
cmCMakePresetsGraph::ResultToString(result)));
if (result != true) {
cmSystemTools::Error(cmStrCat("Could not read presets from ",
this->GetHomeDirectory(), ":",
settingsFile.parseState.GetErrorMessage()));
return 1;
}
@@ -5,12 +5,16 @@
#include "cmCTestResourceAllocator.h"
#include "cmCTestResourceSpec.h"
#include "cmJSONState.h"
static const cmCTestResourceSpec spec{ { {
/* clang-format off */
{ "gpus", { { "0", 4 }, { "1", 8 }, { "2", 0 }, { "3", 8 } } },
/* clang-format on */
} } };
static const cmCTestResourceSpec spec{
{ {
/* clang-format off */
{ "gpus", { { "0", 4 }, { "1", 8 }, { "2", 0 }, { "3", 8 } }, },
/* clang-format on */
} },
cmJSONState()
};
static bool testInitializeFromResourceSpec()
{
+49 -66
View File
@@ -3,89 +3,72 @@
#include <vector>
#include "cmCTestResourceSpec.h"
#include "cmJSONState.h"
struct ExpectedSpec
{
std::string Path;
cmCTestResourceSpec::ReadFileResult ParseResult;
bool ParseResult;
cmCTestResourceSpec Expected;
};
static const std::vector<ExpectedSpec> expectedResourceSpecs = {
{ "spec1.json",
cmCTestResourceSpec::ReadFileResult::READ_OK,
true,
{ { {
{ "gpus",
{
{ "2", 4 },
{ "e", 1 },
} },
{ "threads", {} },
} } } },
{ "spec2.json", cmCTestResourceSpec::ReadFileResult::READ_OK, {} },
{ "spec3.json",
cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC,
{} },
{ "spec4.json",
cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC,
{} },
{ "spec5.json",
cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC,
{} },
{ "spec6.json",
cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC,
{} },
{ "spec7.json",
cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE,
{} },
{ "spec8.json", cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, {} },
{ "spec9.json", cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, {} },
{ "spec10.json", cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, {} },
{ "spec11.json", cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, {} },
{ "spec12.json", cmCTestResourceSpec::ReadFileResult::INVALID_ROOT, {} },
{ "spec13.json", cmCTestResourceSpec::ReadFileResult::JSON_PARSE_ERROR, {} },
{ "spec14.json", cmCTestResourceSpec::ReadFileResult::READ_OK, {} },
{ "spec15.json", cmCTestResourceSpec::ReadFileResult::READ_OK, {} },
{ "spec16.json", cmCTestResourceSpec::ReadFileResult::READ_OK, {} },
{ "spec17.json", cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, {} },
{ "spec18.json", cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, {} },
{ "spec19.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec20.json", cmCTestResourceSpec::ReadFileResult::READ_OK, {} },
{ "spec21.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec22.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec23.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec24.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec25.json",
cmCTestResourceSpec::ReadFileResult::UNSUPPORTED_VERSION,
{} },
{ "spec26.json",
cmCTestResourceSpec::ReadFileResult::UNSUPPORTED_VERSION,
{} },
{ "spec27.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec28.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec29.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec30.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec31.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec32.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec33.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec34.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec35.json", cmCTestResourceSpec::ReadFileResult::INVALID_VERSION, {} },
{ "spec36.json", cmCTestResourceSpec::ReadFileResult::NO_VERSION, {} },
{ "noexist.json", cmCTestResourceSpec::ReadFileResult::FILE_NOT_FOUND, {} },
{ "gpus",
{
{ "2", 4 },
{ "e", 1 },
} },
{ "threads", {} },
} },
cmJSONState() } },
{ "spec2.json", true, {} },
{ "spec3.json", false, {} },
{ "spec4.json", false, {} },
{ "spec5.json", false, {} },
{ "spec6.json", false, {} },
{ "spec7.json", false, {} },
{ "spec8.json", false, {} },
{ "spec9.json", false, {} },
{ "spec10.json", false, {} },
{ "spec11.json", false, {} },
{ "spec12.json", false, {} },
{ "spec13.json", false, {} },
{ "spec14.json", true, {} },
{ "spec15.json", true, {} },
{ "spec16.json", true, {} },
{ "spec17.json", false, {} },
{ "spec18.json", false, {} },
{ "spec19.json", false, {} },
{ "spec20.json", true, {} },
{ "spec21.json", false, {} },
{ "spec22.json", false, {} },
{ "spec23.json", false, {} },
{ "spec24.json", false, {} },
{ "spec25.json", false, {} },
{ "spec26.json", false, {} },
{ "spec27.json", false, {} },
{ "spec28.json", false, {} },
{ "spec29.json", false, {} },
{ "spec30.json", false, {} },
{ "spec31.json", false, {} },
{ "spec32.json", false, {} },
{ "spec33.json", false, {} },
{ "spec34.json", false, {} },
{ "spec35.json", false, {} },
{ "spec36.json", false, {} },
{ "noexist.json", false, {} },
};
static bool testSpec(const std::string& path,
cmCTestResourceSpec::ReadFileResult expectedResult,
static bool testSpec(const std::string& path, bool expectedResult,
const cmCTestResourceSpec& expected)
{
cmCTestResourceSpec actual;
auto result = actual.ReadFromJSONFile(path);
if (result != expectedResult) {
std::cout << "ReadFromJSONFile(\"" << path << "\") returned \""
<< cmCTestResourceSpec::ResultToString(result)
<< "\", should be \""
<< cmCTestResourceSpec::ResultToString(expectedResult) << "\""
<< std::endl;
std::cout << "ReadFromJSONFile(\"" << path << "\") failed \"" << std::endl;
return false;
}
+108 -95
View File
@@ -10,6 +10,7 @@
#include <cm3p/json/value.h>
#include "cmJSONHelpers.h"
#include "cmJSONState.h"
#define ASSERT_TRUE(x) \
do { \
@@ -31,59 +32,65 @@ struct InheritedStruct : public ObjectStruct
std::string Field3;
};
enum class ErrorCode
namespace ErrorMessages {
using ErrorGenerator =
std::function<void(const Json::Value*, cmJSONState* state)>;
ErrorGenerator ErrorGeneratorBuilder(std::string errorMessage)
{
Success,
InvalidInt,
InvalidBool,
InvalidString,
InvalidSubObject,
InvalidObject,
InvalidArray,
MissingRequired,
return [errorMessage](const Json::Value* value, cmJSONState* state) -> void {
state->AddErrorAtValue(errorMessage, value);
};
};
ErrorGenerator InvalidArray = ErrorGeneratorBuilder("Invalid Array");
ErrorGenerator MissingRequired = ErrorGeneratorBuilder("Missing Required");
ErrorGenerator InvalidMap = ErrorGeneratorBuilder("Invalid Map");
ErrorGenerator InvalidObject(JsonErrors::ObjectError /*errorType*/,
const Json::Value::Members& extraFields)
{
return [extraFields](const Json::Value* value, cmJSONState* state) -> void {
state->AddErrorAtValue("Invalid Object", value);
};
};
};
using JSONHelperBuilder = cmJSONHelperBuilder<ErrorCode>;
using JSONHelperBuilder = cmJSONHelperBuilder;
auto const IntHelper =
JSONHelperBuilder::Int(ErrorCode::Success, ErrorCode::InvalidInt, 1);
auto const IntHelper = JSONHelperBuilder::Int(1);
auto const RequiredIntHelper =
JSONHelperBuilder::Required<int>(ErrorCode::MissingRequired, IntHelper);
auto const UIntHelper =
JSONHelperBuilder::UInt(ErrorCode::Success, ErrorCode::InvalidInt, 1);
auto const BoolHelper =
JSONHelperBuilder::Bool(ErrorCode::Success, ErrorCode::InvalidBool, false);
auto const StringHelper = JSONHelperBuilder::String(
ErrorCode::Success, ErrorCode::InvalidString, "default");
JSONHelperBuilder::Required<int>(ErrorMessages::MissingRequired, IntHelper);
auto const UIntHelper = JSONHelperBuilder::UInt(1);
auto const BoolHelper = JSONHelperBuilder::Bool(false);
auto const StringHelper = JSONHelperBuilder::String("default");
auto const RequiredStringHelper = JSONHelperBuilder::Required<std::string>(
ErrorCode::MissingRequired, StringHelper);
ErrorMessages::MissingRequired, StringHelper);
auto const StringVectorHelper = JSONHelperBuilder::Vector<std::string>(
ErrorCode::Success, ErrorCode::InvalidArray, StringHelper);
ErrorMessages::InvalidArray, StringHelper);
auto const StringVectorFilterHelper =
JSONHelperBuilder::VectorFilter<std::string>(
ErrorCode::Success, ErrorCode::InvalidArray, StringHelper,
ErrorMessages::InvalidArray, StringHelper,
[](const std::string& value) { return value != "ignore"; });
auto const StringMapHelper = JSONHelperBuilder::Map<std::string>(
ErrorCode::Success, ErrorCode::InvalidObject, StringHelper);
auto const StringMapHelper =
JSONHelperBuilder::Map<std::string>(ErrorMessages::InvalidMap, StringHelper);
auto const StringMapFilterHelper = JSONHelperBuilder::MapFilter<std::string>(
ErrorCode::Success, ErrorCode::InvalidObject, StringHelper,
ErrorMessages::InvalidMap, StringHelper,
[](const std::string& key) { return key != "ignore"; });
auto const OptionalStringHelper =
JSONHelperBuilder::Optional<std::string>(ErrorCode::Success, StringHelper);
JSONHelperBuilder::Optional<std::string>(StringHelper);
bool testInt()
{
Json::Value v(2);
cmJSONState state;
int i = 0;
ASSERT_TRUE(IntHelper(i, &v) == ErrorCode::Success);
ASSERT_TRUE(IntHelper(i, &v, &state));
ASSERT_TRUE(i == 2);
i = 0;
v = Json::nullValue;
ASSERT_TRUE(IntHelper(i, &v) == ErrorCode::InvalidInt);
ASSERT_TRUE(!IntHelper(i, &v, &state));
i = 0;
ASSERT_TRUE(IntHelper(i, nullptr) == ErrorCode::Success);
ASSERT_TRUE(IntHelper(i, nullptr, &state));
ASSERT_TRUE(i == 1);
return true;
@@ -92,16 +99,16 @@ bool testInt()
bool testUInt()
{
Json::Value v(2);
cmJSONState state;
unsigned int i = 0;
ASSERT_TRUE(UIntHelper(i, &v) == ErrorCode::Success);
ASSERT_TRUE(UIntHelper(i, &v, &state));
ASSERT_TRUE(i == 2);
i = 0;
v = Json::nullValue;
ASSERT_TRUE(UIntHelper(i, &v) == ErrorCode::InvalidInt);
ASSERT_TRUE(!UIntHelper(i, &v, &state));
i = 0;
ASSERT_TRUE(UIntHelper(i, nullptr) == ErrorCode::Success);
ASSERT_TRUE(UIntHelper(i, nullptr, &state));
ASSERT_TRUE(i == 1);
return true;
@@ -110,21 +117,22 @@ bool testUInt()
bool testBool()
{
Json::Value v(true);
cmJSONState state;
bool b = false;
ASSERT_TRUE(BoolHelper(b, &v) == ErrorCode::Success);
ASSERT_TRUE(BoolHelper(b, &v, &state));
ASSERT_TRUE(b);
b = false;
v = false;
ASSERT_TRUE(BoolHelper(b, &v) == ErrorCode::Success);
ASSERT_TRUE(BoolHelper(b, &v, &state));
ASSERT_TRUE(!b);
b = false;
v = 4;
ASSERT_TRUE(BoolHelper(b, &v) == ErrorCode::InvalidBool);
ASSERT_TRUE(!BoolHelper(b, &v, &state));
b = true;
ASSERT_TRUE(BoolHelper(b, nullptr) == ErrorCode::Success);
ASSERT_TRUE(BoolHelper(b, nullptr, &state));
ASSERT_TRUE(!b);
return true;
@@ -133,16 +141,17 @@ bool testBool()
bool testString()
{
Json::Value v("str");
cmJSONState state;
std::string str = "";
ASSERT_TRUE(StringHelper(str, &v) == ErrorCode::Success);
ASSERT_TRUE(StringHelper(str, &v, &state));
ASSERT_TRUE(str == "str");
str = "";
v = Json::nullValue;
ASSERT_TRUE(StringHelper(str, &v) == ErrorCode::InvalidString);
ASSERT_TRUE(!StringHelper(str, &v, &state));
str = "";
ASSERT_TRUE(StringHelper(str, nullptr) == ErrorCode::Success);
ASSERT_TRUE(StringHelper(str, nullptr, &state));
ASSERT_TRUE(str == "default");
return true;
@@ -150,17 +159,15 @@ bool testString()
bool testObject()
{
auto const subhelper =
JSONHelperBuilder::Object<ObjectStruct>(ErrorCode::Success,
ErrorCode::InvalidSubObject)
.Bind("subfield"_s, &ObjectStruct::Field2, IntHelper);
auto const helper = JSONHelperBuilder::Object<ObjectStruct>(
ErrorCode::Success, ErrorCode::InvalidObject)
auto const subhelper = JSONHelperBuilder::Object<ObjectStruct>().Bind(
"subfield"_s, &ObjectStruct::Field2, IntHelper);
auto const helper = JSONHelperBuilder::Object<ObjectStruct>()
.Bind("field1"_s, &ObjectStruct::Field1, StringHelper)
.Bind("field2"_s, subhelper)
.Bind<std::string>("field3"_s, nullptr, StringHelper);
Json::Value v(Json::objectValue);
cmJSONState state;
v["field1"] = "Hello";
v["field2"] = Json::objectValue;
v["field2"]["subfield"] = 2;
@@ -168,38 +175,38 @@ bool testObject()
v["extra"] = "extra";
ObjectStruct s1;
ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success);
ASSERT_TRUE(helper(s1, &v, &state));
ASSERT_TRUE(s1.Field1 == "Hello");
ASSERT_TRUE(s1.Field2 == 2);
v["field2"]["subfield"] = "wrong";
ObjectStruct s2;
ASSERT_TRUE(helper(s2, &v) == ErrorCode::InvalidInt);
ASSERT_TRUE(!helper(s2, &v, &state));
v["field2"].removeMember("subfield");
ObjectStruct s3;
ASSERT_TRUE(helper(s3, &v) == ErrorCode::InvalidSubObject);
ASSERT_TRUE(!helper(s3, &v, &state));
v.removeMember("field2");
ObjectStruct s4;
ASSERT_TRUE(helper(s4, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s4, &v, &state));
v["field2"] = Json::objectValue;
v["field2"]["subfield"] = 2;
v["field3"] = 3;
ObjectStruct s5;
ASSERT_TRUE(helper(s5, &v) == ErrorCode::InvalidString);
ASSERT_TRUE(!helper(s5, &v, &state));
v.removeMember("field3");
ObjectStruct s6;
ASSERT_TRUE(helper(s6, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s6, &v, &state));
v = "Hello";
ObjectStruct s7;
ASSERT_TRUE(helper(s7, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s7, &v, &state));
ObjectStruct s8;
ASSERT_TRUE(helper(s8, nullptr) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s8, nullptr, &state));
return true;
}
@@ -207,47 +214,48 @@ bool testObject()
bool testObjectInherited()
{
auto const helper =
JSONHelperBuilder::Object<InheritedStruct>(ErrorCode::Success,
ErrorCode::InvalidObject)
JSONHelperBuilder::Object<InheritedStruct>(ErrorMessages::InvalidObject,
true)
.Bind("field1"_s, &InheritedStruct::Field1, StringHelper)
.Bind("field2"_s, &InheritedStruct::Field2, IntHelper)
.Bind("field3"_s, &InheritedStruct::Field3, StringHelper);
Json::Value v(Json::objectValue);
cmJSONState state;
v["field1"] = "Hello";
v["field2"] = 2;
v["field3"] = "world!";
v["extra"] = "extra";
InheritedStruct s1;
ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success);
ASSERT_TRUE(helper(s1, &v, &state));
ASSERT_TRUE(s1.Field1 == "Hello");
ASSERT_TRUE(s1.Field2 == 2);
ASSERT_TRUE(s1.Field3 == "world!");
v["field2"] = "wrong";
InheritedStruct s2;
ASSERT_TRUE(helper(s2, &v) == ErrorCode::InvalidInt);
ASSERT_TRUE(!helper(s2, &v, &state));
v.removeMember("field2");
InheritedStruct s3;
ASSERT_TRUE(helper(s3, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s3, &v, &state));
v["field2"] = 2;
v["field3"] = 3;
InheritedStruct s4;
ASSERT_TRUE(helper(s4, &v) == ErrorCode::InvalidString);
ASSERT_TRUE(!helper(s4, &v, &state));
v.removeMember("field3");
InheritedStruct s5;
ASSERT_TRUE(helper(s5, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s5, &v, &state));
v = "Hello";
InheritedStruct s6;
ASSERT_TRUE(helper(s6, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s6, &v, &state));
InheritedStruct s7;
ASSERT_TRUE(helper(s7, nullptr) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s7, nullptr, &state));
return true;
}
@@ -255,22 +263,23 @@ bool testObjectInherited()
bool testObjectNoExtra()
{
auto const helper = JSONHelperBuilder::Object<ObjectStruct>(
ErrorCode::Success, ErrorCode::InvalidObject, false)
ErrorMessages::InvalidObject, false)
.Bind("field1"_s, &ObjectStruct::Field1, StringHelper)
.Bind("field2"_s, &ObjectStruct::Field2, IntHelper);
Json::Value v(Json::objectValue);
cmJSONState state;
v["field1"] = "Hello";
v["field2"] = 2;
ObjectStruct s1;
ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success);
ASSERT_TRUE(helper(s1, &v, &state));
ASSERT_TRUE(s1.Field1 == "Hello");
ASSERT_TRUE(s1.Field2 == 2);
v["extra"] = "world!";
ObjectStruct s2;
ASSERT_TRUE(helper(s2, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!helper(s2, &v, &state));
return true;
}
@@ -278,31 +287,31 @@ bool testObjectNoExtra()
bool testObjectOptional()
{
auto const helper =
JSONHelperBuilder::Object<ObjectStruct>(ErrorCode::Success,
ErrorCode::InvalidObject)
JSONHelperBuilder::Object<ObjectStruct>(ErrorMessages::InvalidObject, true)
.Bind("field1"_s, &ObjectStruct::Field1, StringHelper, false)
.Bind("field2"_s, &ObjectStruct::Field2, IntHelper, false)
.Bind<std::string>("field3_s", nullptr, StringHelper, false);
Json::Value v(Json::objectValue);
cmJSONState state;
v["field1"] = "Hello";
v["field2"] = 2;
v["field3"] = "world!";
v["extra"] = "extra";
ObjectStruct s1;
ASSERT_TRUE(helper(s1, &v) == ErrorCode::Success);
ASSERT_TRUE(helper(s1, &v, &state));
ASSERT_TRUE(s1.Field1 == "Hello");
ASSERT_TRUE(s1.Field2 == 2);
v = Json::objectValue;
ObjectStruct s2;
ASSERT_TRUE(helper(s2, &v) == ErrorCode::Success);
ASSERT_TRUE(helper(s2, &v, &state));
ASSERT_TRUE(s2.Field1 == "default");
ASSERT_TRUE(s2.Field2 == 1);
ObjectStruct s3;
ASSERT_TRUE(helper(s3, nullptr) == ErrorCode::Success);
ASSERT_TRUE(helper(s3, nullptr, &state));
ASSERT_TRUE(s3.Field1 == "default");
ASSERT_TRUE(s3.Field2 == 1);
@@ -312,25 +321,26 @@ bool testObjectOptional()
bool testVector()
{
Json::Value v(Json::arrayValue);
cmJSONState state;
v.append("Hello");
v.append("world!");
v.append("ignore");
std::vector<std::string> l{ "default" };
std::vector<std::string> expected{ "Hello", "world!", "ignore" };
ASSERT_TRUE(StringVectorHelper(l, &v) == ErrorCode::Success);
ASSERT_TRUE(StringVectorHelper(l, &v, &state));
ASSERT_TRUE(l == expected);
v[1] = 2;
l = { "default" };
ASSERT_TRUE(StringVectorHelper(l, &v) == ErrorCode::InvalidString);
ASSERT_TRUE(!StringVectorHelper(l, &v, &state));
v = "Hello";
l = { "default" };
ASSERT_TRUE(StringVectorHelper(l, &v) == ErrorCode::InvalidArray);
ASSERT_TRUE(!StringVectorHelper(l, &v, &state));
l = { "default" };
ASSERT_TRUE(StringVectorHelper(l, nullptr) == ErrorCode::Success);
ASSERT_TRUE(StringVectorHelper(l, nullptr, &state));
ASSERT_TRUE(l.empty());
return true;
@@ -339,6 +349,7 @@ bool testVector()
bool testVectorFilter()
{
Json::Value v(Json::arrayValue);
cmJSONState state;
v.append("Hello");
v.append("world!");
v.append("ignore");
@@ -348,19 +359,19 @@ bool testVectorFilter()
"Hello",
"world!",
};
ASSERT_TRUE(StringVectorFilterHelper(l, &v) == ErrorCode::Success);
ASSERT_TRUE(StringVectorFilterHelper(l, &v, &state));
ASSERT_TRUE(l == expected);
v[1] = 2;
l = { "default" };
ASSERT_TRUE(StringVectorFilterHelper(l, &v) == ErrorCode::InvalidString);
ASSERT_TRUE(!StringVectorFilterHelper(l, &v, &state));
v = "Hello";
l = { "default" };
ASSERT_TRUE(StringVectorFilterHelper(l, &v) == ErrorCode::InvalidArray);
ASSERT_TRUE(!StringVectorFilterHelper(l, &v, &state));
l = { "default" };
ASSERT_TRUE(StringVectorFilterHelper(l, nullptr) == ErrorCode::Success);
ASSERT_TRUE(StringVectorFilterHelper(l, nullptr, &state));
ASSERT_TRUE(l.empty());
return true;
@@ -372,20 +383,21 @@ bool testMap()
v["field1"] = "Hello";
v["field2"] = "world!";
v["ignore"] = "ignore";
cmJSONState state;
std::map<std::string, std::string> m{ { "key", "default" } };
std::map<std::string, std::string> expected{ { "field1", "Hello" },
{ "field2", "world!" },
{ "ignore", "ignore" } };
ASSERT_TRUE(StringMapHelper(m, &v) == ErrorCode::Success);
ASSERT_TRUE(StringMapHelper(m, &v, &state));
ASSERT_TRUE(m == expected);
v = Json::arrayValue;
m = { { "key", "default" } };
ASSERT_TRUE(StringMapHelper(m, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!StringMapHelper(m, &v, &state));
m = { { "key", "default" } };
ASSERT_TRUE(StringMapHelper(m, nullptr) == ErrorCode::Success);
ASSERT_TRUE(StringMapHelper(m, nullptr, &state));
ASSERT_TRUE(m.empty());
return true;
@@ -394,6 +406,7 @@ bool testMap()
bool testMapFilter()
{
Json::Value v(Json::objectValue);
cmJSONState state;
v["field1"] = "Hello";
v["field2"] = "world!";
v["ignore"] = "ignore";
@@ -401,15 +414,15 @@ bool testMapFilter()
std::map<std::string, std::string> m{ { "key", "default" } };
std::map<std::string, std::string> expected{ { "field1", "Hello" },
{ "field2", "world!" } };
ASSERT_TRUE(StringMapFilterHelper(m, &v) == ErrorCode::Success);
ASSERT_TRUE(StringMapFilterHelper(m, &v, &state));
ASSERT_TRUE(m == expected);
v = Json::arrayValue;
m = { { "key", "default" } };
ASSERT_TRUE(StringMapFilterHelper(m, &v) == ErrorCode::InvalidObject);
ASSERT_TRUE(!StringMapFilterHelper(m, &v, &state));
m = { { "key", "default" } };
ASSERT_TRUE(StringMapFilterHelper(m, nullptr) == ErrorCode::Success);
ASSERT_TRUE(StringMapFilterHelper(m, nullptr, &state));
ASSERT_TRUE(m.empty());
return true;
@@ -418,13 +431,14 @@ bool testMapFilter()
bool testOptional()
{
Json::Value v = "Hello";
cmJSONState state;
cm::optional<std::string> str{ "default" };
ASSERT_TRUE(OptionalStringHelper(str, &v) == ErrorCode::Success);
ASSERT_TRUE(OptionalStringHelper(str, &v, &state));
ASSERT_TRUE(str == "Hello");
str.emplace("default");
ASSERT_TRUE(OptionalStringHelper(str, nullptr) == ErrorCode::Success);
ASSERT_TRUE(OptionalStringHelper(str, nullptr, &state));
ASSERT_TRUE(str == cm::nullopt);
return true;
@@ -433,25 +447,24 @@ bool testOptional()
bool testRequired()
{
Json::Value v = "Hello";
std::string str = "default";
int i = 1;
ASSERT_TRUE(RequiredStringHelper(str, &v) == ErrorCode::Success);
cmJSONState state;
ASSERT_TRUE(RequiredStringHelper(str, &v, &state));
ASSERT_TRUE(str == "Hello");
ASSERT_TRUE(RequiredIntHelper(i, &v) == ErrorCode::InvalidInt);
ASSERT_TRUE(!RequiredIntHelper(i, &v, &state));
v = 2;
str = "default";
i = 1;
ASSERT_TRUE(RequiredStringHelper(str, &v) == ErrorCode::InvalidString);
ASSERT_TRUE(RequiredIntHelper(i, &v) == ErrorCode::Success);
ASSERT_TRUE(!RequiredStringHelper(str, &v, &state));
ASSERT_TRUE(RequiredIntHelper(i, &v, &state));
ASSERT_TRUE(i == 2);
str = "default";
i = 1;
ASSERT_TRUE(RequiredStringHelper(str, nullptr) ==
ErrorCode::MissingRequired);
ASSERT_TRUE(RequiredIntHelper(i, nullptr) == ErrorCode::MissingRequired);
ASSERT_TRUE(!RequiredStringHelper(str, nullptr, &state));
ASSERT_TRUE(!RequiredIntHelper(i, nullptr, &state));
return true;
}
@@ -1,7 +1,6 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/Comment: JSON parse error
Errors:
[^
]*/Tests/RunCMake/CMakePresets/Comment:
JSON Parse Error: [^
]*Comment\/CMakePresets.json:
\* Line 1, Column 1
Syntax error: value, object or array expected\.
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/ConditionFuture: File version must be 3 or higher for condition support$
]*/Tests/RunCMake/CMakePresets/ConditionFuture:
File version must be 3 or higher for condition support$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/CyclicInheritance0: Cyclic preset inheritance$
]*/Tests/RunCMake/CMakePresets/CyclicInheritance0:
Cyclic preset inheritance for preset "CyclicInheritance0"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/CyclicInheritance1: Cyclic preset inheritance$
]*/Tests/RunCMake/CMakePresets/CyclicInheritance1:
Cyclic preset inheritance for preset "CyclicInheritance0"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/CyclicInheritance2: Cyclic preset inheritance$
]*/Tests/RunCMake/CMakePresets/CyclicInheritance2:
Cyclic preset inheritance for preset "CyclicInheritance0"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/DuplicatePresets: Duplicate presets$
]*/Tests/RunCMake/CMakePresets/DuplicatePresets:
Duplicate preset: "DuplicatePresets"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/EmptyCacheKey: Invalid preset$
]*/Tests/RunCMake/CMakePresets/EmptyCacheKey:
Invalid preset: "EmptyCacheKey"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/EmptyEnv: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/EmptyEnv:
Invalid macro expansion in "EmptyEnv"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/EmptyEnvKey: Invalid preset$
]*/Tests/RunCMake/CMakePresets/EmptyEnvKey:
Invalid preset: "EmptyEnvKey"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/EmptyPenv: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/EmptyPenv:
Invalid macro expansion in "EmptyPenv"$
@@ -1,5 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/EmptyPresetName: Invalid preset
Errors:
[^
]*/EmptyPresetName/CMakePresets.json$
]*/Tests/RunCMake/CMakePresets/EmptyPresetName:
Error: @5,15: Invalid Preset Name
"name": "",
\^$
@@ -1,2 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/EnvCycle: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/EnvCycle:
Invalid preset: "EnvCycle"
Invalid macro expansion in "EnvCycle"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated: Invalid preset$
]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated:
Invalid preset: "ErrorNoWarningDeprecated"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDev: Invalid preset$
]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDev:
Invalid preset: "ErrorNoWarningDev"$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/ExtraPresetField: Invalid preset$
]*/Tests/RunCMake/CMakePresets/ExtraPresetField:
Error: @8,18: Invalid extra field "invalid" in Preset
"invalid": true
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/ExtraRootField: Invalid root object$
]*/Tests/RunCMake/CMakePresets/ExtraRootField:
Error: @10,14: Invalid extra field "invalid" in root object
"invalid": true
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/ExtraVariableField: Invalid CMake variable definition$
]*/Tests/RunCMake/CMakePresets/ExtraVariableField:
Error: @11,22: Invalid extra field "invalid" in variable "EXTRA" for preset "ExtraVariableField"
"invalid": true
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/FileDirFuture: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/FileDirFuture:
Invalid macro expansion in "FileDirFuture"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField: File version must be 3 or higher for installDir preset support.$
]*/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField:
File version must be 3 or higher for installDir preset support$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/FuturePresetToolchainField: File version must be 3 or higher for toolchainFile preset support.$
]*/Tests/RunCMake/CMakePresets/FuturePresetToolchainField:
File version must be 3 or higher for toolchainFile preset support$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/HighVersion: Unrecognized "version" field$
]*/Tests/RunCMake/CMakePresets/HighVersion:
Error: @2,14: Unrecognized "version" field
"version": 1000,
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/HostSystemNameFuture: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/HostSystemNameFuture:
Invalid macro expansion in "HostSystemNameFuture"$
@@ -1,2 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/IncludeCycle: Cyclic include among preset files$
]*/Tests/RunCMake/CMakePresets/IncludeCycle:
Cyclic include among preset files: [^
]*/CMakeUserPresets.json$
@@ -1,2 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/IncludeCycle3Files: Cyclic include among preset files$
CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/IncludeCycle3Files:
Cyclic include among preset files: [^
]*/CMakePresets.json
@@ -1,5 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/IncludeNotFound: File not found
Errors:
[^
]*/IncludeNotFound/NotFound.json: Failed to read file$
]*/Tests/RunCMake/CMakePresets/IncludeNotFound:
File not found: [^
]*/IncludeNotFound/NotFound.json$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/IncludeV3: File version must be 4 or higher for include support$
]*/Tests/RunCMake/CMakePresets/IncludeV3:
File version must be 4 or higher for include support$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/IncludeV4V3: File version must be 4 or higher for include support$
]*/Tests/RunCMake/CMakePresets/IncludeV4V3:
File version must be 4 or higher for include support$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy:
Error: @9,21: Invalid preset
"strategy": {}
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidInheritance: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidInheritance:
Invalid preset: "InvalidInheritance"$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir:
Error: @7,20: "binaryDir" expected a string
"binaryDir": \[\]
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidPresetGenerator: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidPresetGenerator:
Error: @6,20: "generator" expected a string
"generator": \[\],
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidPresetName: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidPresetName:
Error: @5,15: Invalid Preset Name
"name": \[\],
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidPresetVendor: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidPresetVendor:
Error: @8,17: Invalid preset
"vendor": true
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidPresets: Invalid "configurePresets" field$
]*/Tests/RunCMake/CMakePresets/InvalidPresets:
Error: @3,23: Invalid "configurePresets" field
"configurePresets": {}
\^$
@@ -1,2 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidRegex: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/InvalidRegex:
Invalid preset: "InvalidRegex"
Invalid macro expansion in "InvalidRegex"$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidRoot: Invalid root object$
]*/Tests/RunCMake/CMakePresets/InvalidRoot:
Error: \@1\,1\: Invalid root object
\[\]
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy:
Error: @9,21: Invalid preset
"strategy": {}
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidVariableValue: Invalid CMake variable definition$
]*/Tests/RunCMake/CMakePresets/InvalidVariableValue:
Error: @10,20: "value" expected a string
"value": \[\]
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidVariables: Invalid preset$
]*/Tests/RunCMake/CMakePresets/InvalidVariables:
Error: @8,25: Invalid preset
"cacheVariables": \[\]
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidVendor: Invalid root object$
]*/Tests/RunCMake/CMakePresets/InvalidVendor:
Error: @3,13: Invalid root object
"vendor": true,
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/InvalidVersion: Invalid "version" field$
]*/Tests/RunCMake/CMakePresets/InvalidVersion:
Error: @2,14: Invalid "version" field
"version": "1.0",
\^$
@@ -1,9 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/JSONParseError: JSON parse error
Errors:
[^
]*JSONParseError/CMakePresets.json:
\* Line 1, Column 1
Syntax error: value, object or array expected\.
\* Line 1, Column 1
A valid JSON document must be either an array or an object value\.$
]*/Tests/RunCMake/CMakePresets/JSONParseError:
A JSON document cannot be empty
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/LowVersion: Unrecognized "version" field$
]*/Tests/RunCMake/CMakePresets/LowVersion:
Error: @2,14: Unrecognized "version" field
"version": 0,
\^
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid: Invalid "cmakeMinimumRequired" field$
]*/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid:
Error: @3,27: Invalid "cmakeMinimumRequired"
"cmakeMinimumRequired": "3.18",
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/MinimumRequiredMajor: "cmakeMinimumRequired" version too new$
]*/Tests/RunCMake/CMakePresets/MinimumRequiredMajor:
Error: @4,14: "cmakeMinimumRequired" major version 1000 must be less than [0-9]*
"major": 1000
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/MinimumRequiredMinor: "cmakeMinimumRequired" version too new$
]*/Tests/RunCMake/CMakePresets/MinimumRequiredMinor:
Error: @5,14: "cmakeMinimumRequired" minor version 1000 must be less than [0-9]*
"minor": 1000
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/MinimumRequiredPatch: "cmakeMinimumRequired" version too new$
]*/Tests/RunCMake/CMakePresets/MinimumRequiredPatch:
Error: @6,14: "cmakeMinimumRequired" patch version 50000000 must be less than [0-9]*
"patch": 50000000
\^$
@@ -1,2 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/NoCMakePresets: File not found$
]*/Tests/RunCMake/CMakePresets/NoCMakePresets:
File not found: [^
]*/CMakePresets.json$
@@ -1,2 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/NoPresetBinaryDir: Invalid preset$
]*/Tests/RunCMake/CMakePresets/NoPresetBinaryDir:
Preset "NoPresetBinaryDir" missing field "binaryDir"
Invalid preset: "NoPresetBinaryDir"$
@@ -1,2 +1,4 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/NoPresetGenerator: Invalid preset$
]*/Tests/RunCMake/CMakePresets/NoPresetGenerator:
Preset "NoPresetGenerator" missing field "generator"
Invalid preset: "NoPresetGenerator"$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/NoPresetName: Invalid preset$
]*/Tests/RunCMake/CMakePresets/NoPresetName:
Error: @4,5: Missing required field "name" in Preset
{
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/NoSuchMacro: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/NoSuchMacro:
Invalid macro expansion in "NoSuchMacro"$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/NoVariableValue: Invalid CMake variable definition$
]*/Tests/RunCMake/CMakePresets/NoVariableValue:
Error: @9,16: Missing required field "value" in variable "VAR" for preset "NoVariableValue"
"VAR": {}
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/NoVersion: No "version" field$
]*/Tests/RunCMake/CMakePresets/NoVersion:
No "version" field$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/PathListSepFuture: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/PathListSepFuture:
Invalid macro expansion in "PathListSepFuture"$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/PresetNotObject: Invalid preset$
]*/Tests/RunCMake/CMakePresets/PresetNotObject:
Error: @4,5: Invalid Preset
\[\]
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/SubConditionNull: Invalid preset condition$
]*/Tests/RunCMake/CMakePresets/SubConditionNull:
Invalid condition for preset "SubConditionNull"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/UnclosedMacro: Invalid macro expansion$
]*/Tests/RunCMake/CMakePresets/UnclosedMacro:
Invalid macro expansion in "UnclosedMacro"$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy: Invalid preset$
]*/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy:
Error: @9,21: Invalid preset
"strategy": "unknown"
\^$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy: Invalid preset$
]*/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy:
Error: @9,21: Invalid preset
"strategy": "unknown"
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/UserDuplicateCross: Duplicate presets$
]*/Tests/RunCMake/CMakePresets/UserDuplicateCross:
Duplicate preset: "UserDuplicateCross"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/UserDuplicateInUser: Duplicate presets$
]*/Tests/RunCMake/CMakePresets/UserDuplicateInUser:
Duplicate preset: "UserDuplicateInUser"$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/UserInheritance: Inherited preset is unreachable from preset's file$
]*/Tests/RunCMake/CMakePresets/UserInheritance:
Inherited preset "UserInheritance" is unreachable from preset's file$
@@ -1,2 +1,5 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresets/VariableNotObject: Invalid CMake variable definition$
]*/Tests/RunCMake/CMakePresets/VariableNotObject:
Error: @9,16: Invalid CMake variable "VAR" for preset "VariableNotObject"
"VAR": \[\]
\^$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsBuild/ConditionFuture: File version must be 3 or higher for condition support$
]*/Tests/RunCMake/CMakePresetsBuild/ConditionFuture:
File version must be 3 or higher for condition support$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsBuild/ConfigurePresetUnreachable: Configure preset is unreachable from preset's file$
]*/Tests/RunCMake/CMakePresetsBuild/ConfigurePresetUnreachable:
Configure preset "x" is unreachable from preset's file$
@@ -1,2 +1,3 @@
CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset: Invalid "configurePreset" field
]*/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset:
Invalid "configurePreset": "badConfigurePreset"$
@@ -1,2 +1,3 @@
CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset: Invalid "configurePreset" field
]*/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset:
Invalid "configurePreset": "badConfigurePreset"$
@@ -1,2 +1,3 @@
CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset: Invalid preset
]*/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset:
Invalid preset: "noConfigurePreset"$
@@ -1,2 +1,3 @@
CMake Error: Could not read presets from [^
]*Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported: File version must be 2 or higher for build and test preset support.
]*Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported:
File version must be 2 or higher for build and test preset support$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion: File version must be 6 or higher for package preset support$
]*/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion:
File version must be 6 or higher for package preset support$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsTest/ConditionFuture: File version must be 3 or higher for condition support$
]*/Tests/RunCMake/CMakePresetsTest/ConditionFuture:
File version must be 3 or higher for condition support$
@@ -1,2 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsTest/ConfigurePresetUnreachable: Configure preset is unreachable from preset's file$
]*/Tests/RunCMake/CMakePresetsTest/ConfigurePresetUnreachable:
Configure preset "x" is unreachable from preset's file

Some files were not shown because too many files have changed in this diff Show More