mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-28 04:09:35 +03:00
presets: Improve JSON parser and error messages
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
@@ -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
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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$
|
||||
|
||||
+2
-1
@@ -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"$
|
||||
|
||||
+2
-1
@@ -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"$
|
||||
|
||||
+2
-1
@@ -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
Reference in New Issue
Block a user