From 19305afd8a2a46925b1a880de68f7be0ad1f3091 Mon Sep 17 00:00:00 2001 From: Martin Duffy Date: Wed, 22 Mar 2023 13:11:21 -0400 Subject: presets: Improve JSON parser and error messages --- Source/CMakeLists.txt | 3 + Source/CPack/cpack.cxx | 7 +- Source/CTest/cmCTestResourceSpec.cxx | 148 ++----- Source/CTest/cmCTestResourceSpec.h | 59 ++- Source/CTest/cmCTestTestHandler.cxx | 6 +- Source/QtDialog/CMakeSetupDialog.cxx | 7 +- Source/QtDialog/CMakeSetupDialog.h | 3 +- Source/QtDialog/QCMake.cxx | 9 +- Source/QtDialog/QCMake.h | 7 +- Source/cmCMakePresetErrors.h | 242 ++++++++++++ Source/cmCMakePresetsGraph.cxx | 379 +++++++++--------- Source/cmCMakePresetsGraph.h | 92 ++--- Source/cmCMakePresetsGraphInternal.h | 69 ++-- Source/cmCMakePresetsGraphReadJSON.cxx | 426 +++++++++++---------- Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx | 45 ++- ...cmCMakePresetsGraphReadJSONConfigurePresets.cxx | 93 ++--- .../cmCMakePresetsGraphReadJSONPackagePresets.cxx | 37 +- Source/cmCMakePresetsGraphReadJSONTestPresets.cxx | 161 ++++---- .../cmCMakePresetsGraphReadJSONWorkflowPresets.cxx | 53 +-- Source/cmCTest.cxx | 9 +- Source/cmJSONHelpers.h | 352 ++++++++++++----- Source/cmJSONState.cxx | 163 ++++++++ Source/cmJSONState.h | 73 ++++ Source/cmake.cxx | 24 +- Tests/CMakeLib/testCTestResourceAllocator.cxx | 16 +- Tests/CMakeLib/testCTestResourceSpec.cxx | 115 +++--- Tests/CMakeLib/testJSONHelpers.cxx | 203 +++++----- Tests/RunCMake/CMakePresets/Comment-stderr.txt | 5 +- .../CMakePresets/ConditionFuture-stderr.txt | 3 +- .../CMakePresets/CyclicInheritance0-stderr.txt | 3 +- .../CMakePresets/CyclicInheritance1-stderr.txt | 3 +- .../CMakePresets/CyclicInheritance2-stderr.txt | 3 +- .../CMakePresets/DuplicatePresets-stderr.txt | 3 +- .../RunCMake/CMakePresets/EmptyCacheKey-stderr.txt | 3 +- Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt | 3 +- Tests/RunCMake/CMakePresets/EmptyEnvKey-stderr.txt | 3 +- Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt | 3 +- .../CMakePresets/EmptyPresetName-stderr.txt | 8 +- Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt | 4 +- .../ErrorNoWarningDeprecated-stderr.txt | 3 +- .../CMakePresets/ErrorNoWarningDev-stderr.txt | 3 +- .../CMakePresets/ExtraPresetField-stderr.txt | 5 +- .../CMakePresets/ExtraRootField-stderr.txt | 5 +- .../CMakePresets/ExtraVariableField-stderr.txt | 5 +- .../RunCMake/CMakePresets/FileDirFuture-stderr.txt | 3 +- .../FuturePresetInstallDirField-stderr.txt | 3 +- .../FuturePresetToolchainField-stderr.txt | 3 +- Tests/RunCMake/CMakePresets/HighVersion-stderr.txt | 5 +- .../CMakePresets/HostSystemNameFuture-stderr.txt | 3 +- .../RunCMake/CMakePresets/IncludeCycle-stderr.txt | 4 +- .../CMakePresets/IncludeCycle3Files-stderr.txt | 6 +- .../CMakePresets/IncludeNotFound-stderr.txt | 7 +- Tests/RunCMake/CMakePresets/IncludeV3-stderr.txt | 3 +- Tests/RunCMake/CMakePresets/IncludeV4V3-stderr.txt | 3 +- .../InvalidArchitectureStrategy-stderr.txt | 5 +- .../CMakePresets/InvalidInheritance-stderr.txt | 3 +- .../CMakePresets/InvalidPresetBinaryDir-stderr.txt | 5 +- .../CMakePresets/InvalidPresetGenerator-stderr.txt | 5 +- .../CMakePresets/InvalidPresetName-stderr.txt | 5 +- .../CMakePresets/InvalidPresetVendor-stderr.txt | 5 +- .../CMakePresets/InvalidPresets-stderr.txt | 5 +- .../RunCMake/CMakePresets/InvalidRegex-stderr.txt | 4 +- Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt | 5 +- .../CMakePresets/InvalidToolsetStrategy-stderr.txt | 5 +- .../CMakePresets/InvalidVariableValue-stderr.txt | 5 +- .../CMakePresets/InvalidVariables-stderr.txt | 5 +- .../RunCMake/CMakePresets/InvalidVendor-stderr.txt | 5 +- .../CMakePresets/InvalidVersion-stderr.txt | 5 +- .../CMakePresets/JSONParseError-stderr.txt | 10 +- Tests/RunCMake/CMakePresets/LowVersion-stderr.txt | 5 +- .../CMakePresets/MinimumRequiredInvalid-stderr.txt | 5 +- .../CMakePresets/MinimumRequiredMajor-stderr.txt | 5 +- .../CMakePresets/MinimumRequiredMinor-stderr.txt | 5 +- .../CMakePresets/MinimumRequiredPatch-stderr.txt | 5 +- .../CMakePresets/NoCMakePresets-stderr.txt | 4 +- .../CMakePresets/NoPresetBinaryDir-stderr.txt | 4 +- .../CMakePresets/NoPresetGenerator-stderr.txt | 4 +- .../RunCMake/CMakePresets/NoPresetName-stderr.txt | 5 +- Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt | 3 +- .../CMakePresets/NoVariableValue-stderr.txt | 5 +- Tests/RunCMake/CMakePresets/NoVersion-stderr.txt | 3 +- .../CMakePresets/PathListSepFuture-stderr.txt | 3 +- .../CMakePresets/PresetNotObject-stderr.txt | 5 +- .../CMakePresets/SubConditionNull-stderr.txt | 3 +- .../RunCMake/CMakePresets/UnclosedMacro-stderr.txt | 3 +- .../UnknownArchitectureStrategy-stderr.txt | 5 +- .../CMakePresets/UnknownToolsetStrategy-stderr.txt | 5 +- .../CMakePresets/UserDuplicateCross-stderr.txt | 3 +- .../CMakePresets/UserDuplicateInUser-stderr.txt | 3 +- .../CMakePresets/UserInheritance-stderr.txt | 3 +- .../CMakePresets/VariableNotObject-stderr.txt | 5 +- ...onditionFuture-build-conditionFuture-stderr.txt | 3 +- .../ConfigurePresetUnreachable-build-x-stderr.txt | 3 +- ...igurePreset-build-badConfigurePreset-stderr.txt | 3 +- ...lidConfigurePreset-configure-default-stderr.txt | 3 +- ...figurePreset-build-noConfigurePreset-stderr.txt | 3 +- .../PresetsUnsupported-build-x-stderr.txt | 3 +- .../UnsupportedVersion-configure-x-stderr.txt | 3 +- .../ConditionFuture-test-x-stderr.txt | 3 +- .../ConfigurePresetUnreachable-test-x-stderr.txt | 3 +- ...lidConfigurePreset-configure-default-stderr.txt | 3 +- ...figurePreset-test-badConfigurePreset-stderr.txt | 3 +- ...nfigurePreset-test-noConfigurePreset-stderr.txt | 3 +- .../OutputJUnitUnsupported-test-x-stderr.txt | 3 +- .../PresetsUnsupported-test-x-stderr.txt | 3 +- ...stOutputTruncationUnsupported-test-x-stderr.txt | 3 +- .../ConfigureStepMismatch-stderr.txt | 3 +- .../FirstStepNotConfigure-stderr.txt | 3 +- .../NoWorkflowSteps-stderr.txt | 3 +- .../NonexistentStep-stderr.txt | 3 +- .../SecondStepConfigure-stderr.txt | 3 +- .../UnreachableStep-stderr.txt | 3 +- .../UnsupportedVersion-stderr.txt | 3 +- .../CTestResourceAllocation/ctresalloc.cxx | 3 +- 114 files changed, 1930 insertions(+), 1213 deletions(-) create mode 100644 Source/cmCMakePresetErrors.h create mode 100644 Source/cmJSONState.cxx create mode 100644 Source/cmJSONState.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index e99da49..e3c69e6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -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 diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 2257118..234bc59 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.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; } diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx index 142b07d..0e81fa9 100644 --- a/Source/CTest/cmCTestResourceSpec.cxx +++ b/Source/CTest/cmCTestResourceSpec.cxx @@ -10,17 +10,14 @@ #include -#include #include -#include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" #include "cmJSONHelpers.h" namespace { -using JSONHelperBuilder = - cmJSONHelperBuilder; +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( - cmCTestResourceSpec::ReadFileResult::NO_VERSION, - JSONHelperBuilder::Object( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_VERSION) + cmCTestResourceSpecErrors::NO_VERSION, + JSONHelperBuilder::Object() .Bind("major"_s, &Version::Major, VersionFieldHelper) .Bind("minor"_s, &Version::Minor, VersionFieldHelper)); -auto const RootVersionHelper = - JSONHelperBuilder::Object( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) - .Bind("version"_s, &TopVersion::Version, VersionHelper, false); +auto const RootVersionHelper = JSONHelperBuilder::Object().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::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE) + JSONHelperBuilder::Object() .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::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE, - ResourceHelper); + cmCTestResourceSpecErrors::INVALID_RESOURCE_TYPE, ResourceHelper); auto const ResourceMapHelper = JSONHelperBuilder::MapFilter>( - 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>>( - 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>> 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::ReadFileResult::INVALID_SOCKET_SPEC, SocketHelper); + cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC, SocketHelper); -auto const RootHelper = JSONHelperBuilder::Object( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) - .Bind("local", &cmCTestResourceSpec::LocalSocket, - LocalRequiredHelper, false); +auto const RootHelper = JSONHelperBuilder::Object().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 diff --git a/Source/CTest/cmCTestResourceSpec.h b/Source/CTest/cmCTestResourceSpec.h index 72628a3..37ccd72 100644 --- a/Source/CTest/cmCTestResourceSpec.h +++ b/Source/CTest/cmCTestResourceSpec.h @@ -8,6 +8,12 @@ #include #include +#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); +}; +} diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 1d509cf..f693ace 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -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& 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; } diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 1effdd3..ab77818 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -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() diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index 8aee70d..d4c72cb 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -59,8 +59,7 @@ protected slots: void updateBinaryDirectory(const QString& dir); void updatePresets(const QVector& 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(); diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index ea02f98..6ed24ca 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -33,7 +33,6 @@ QCMake::QCMake(QObject* p) qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType>(); - qRegisterMetaType(); 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; diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index 8a7e4cb..0890558 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -60,7 +60,6 @@ using QCMakePropertyList = QList; 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 AvailableGenerators; cmCMakePresetsGraph CMakePresetsGraph; - cmCMakePresetsGraph::ReadFileResult LastLoadPresetsResult = - cmCMakePresetsGraph::ReadFileResult::READ_OK; + bool LastLoadPresetsResult = true; QString PresetName; QString CMakeExecutable; QAtomicInt InterruptFlag; diff --git a/Source/cmCMakePresetErrors.h b/Source/cmCMakePresetErrors.h new file mode 100644 index 0000000..c669cb1 --- /dev/null +++ b/Source/cmCMakePresetErrors.h @@ -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 + +#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, "\"")); +}; +} diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx index 7325e44..13e8bad 100644 --- a/Source/cmCMakePresetsGraph.cxx +++ b/Source/cmCMakePresetsGraph.cxx @@ -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& child, const std::vector& parent) * inheritance. */ template -ReadFileResult VisitPreset( +bool VisitPreset( T& preset, std::map>& presets, - std::map cycleStatus, - const cmCMakePresetsGraph& graph) + std::map 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 -ReadFileResult ComputePresetInheritance( +bool ComputePresetInheritance( std::map>& presets, - const cmCMakePresetsGraph& graph) + cmCMakePresetsGraph& graph) { std::map cycleStatus; for (auto const& it : presets) { @@ -153,13 +172,12 @@ ReadFileResult ComputePresetInheritance( for (auto& it : presets) { auto& preset = it.second.Unexpanded; - auto result = VisitPreset(preset, presets, cycleStatus, graph); - if (result != ReadFileResult::READ_OK) { - return result; + if (!VisitPreset(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 -bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset, +bool ExpandMacros(cmCMakePresetsGraph& graph, const T& preset, cm::optional& 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 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 -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( - const ConfigurePreset& preset, const ConfigurePreset*& configurePreset) +bool SetupWorkflowConfigurePreset( + const ConfigurePreset& preset, const ConfigurePreset*& configurePreset, + cmJSONState*) { configurePreset = &preset; - return ReadFileResult::READ_OK; + return true; } template -ReadFileResult TryReachPresetFromWorkflow( +bool TryReachPresetFromWorkflow( const WorkflowPreset& origin, const std::map>& 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(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 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() diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h index 17c902b..9d7e5fa 100644 --- a/Source/cmCMakePresetsGraph.h +++ b/Source/cmCMakePresetsGraph.h @@ -14,6 +14,8 @@ #include +#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> 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 DebugTryCompile; cm::optional 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 NativeToolOptions; cm::optional 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 Filter; cm::optional 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 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 @@ -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& inProgressFiles, File*& file, - std::string& errMsg); + bool ReadProjectPresetsInternal(bool allowNoFiles); + bool ReadJSONFile(const std::string& filename, RootType rootType, + ReadReason readReason, std::vector& inProgressFiles, + File*& file, std::string& errMsg); void ClearPresets(); }; diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h index 2726e92..db784c3 100644 --- a/Source/cmCMakePresetsGraphInternal.h +++ b/Source/cmCMakePresetsGraphInternal.h @@ -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 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& 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& out, + const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper( - cm::optional& 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& out, + const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper( - cm::optional& out, const Json::Value* value); +bool PresetIntHelper(int& out, const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper( - std::vector& out, const Json::Value* value); +bool PresetOptionalIntHelper(cm::optional& out, const Json::Value* value, + cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult ConfigurePresetsHelper( +bool PresetVectorIntHelper(std::vector& out, const Json::Value* value, + cmJSONState* state); + +bool ConfigurePresetsHelper( std::vector& out, - const Json::Value* value); + const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult BuildPresetsHelper( - std::vector& out, - const Json::Value* value); +bool BuildPresetsHelper(std::vector& out, + const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult TestPresetsHelper( - std::vector& out, const Json::Value* value); +bool TestPresetsHelper(std::vector& out, + const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper( - std::vector& out, - const Json::Value* value); +bool PackagePresetsHelper(std::vector& out, + const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper( +bool WorkflowPresetsHelper( std::vector& out, - const Json::Value* value); + const Json::Value* value, cmJSONState* state); -cmJSONHelper VendorHelper( - cmCMakePresetsGraph::ReadFileResult error); +cmJSONHelper VendorHelper(const ErrorGenerator& error); -cmCMakePresetsGraph::ReadFileResult PresetConditionHelper( +bool PresetConditionHelper( std::shared_ptr& out, - const Json::Value* value); + const Json::Value* value, cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult PresetVectorOneOrMoreStringHelper( - std::vector& out, const Json::Value* value); +bool PresetVectorOneOrMoreStringHelper(std::vector& out, + const Json::Value* value, + cmJSONState* state); -cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper( +bool EnvironmentMapHelper( std::map>& out, - const Json::Value* value); + const Json::Value* value, cmJSONState* state); } diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index a96ab58..93c5f7d 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -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 +#include #include #include #include @@ -12,20 +13,18 @@ #include #include -#include #include -#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; +using JSONHelperBuilder = cmJSONHelperBuilder; constexpr int MIN_VERSION = 1; constexpr int MAX_VERSION = 6; @@ -64,26 +63,23 @@ std::unique_ptr 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( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, - ConditionStringHelper); + cmCMakePresetErrors::INVALID_CONDITION, ConditionStringHelper); auto const ConstConditionHelper = JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false) .Bind("type"_s, nullptr, ConditionStringHelper, true) .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value, ConditionBoolHelper, true); auto const EqualsConditionHelper = JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false) .Bind("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( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false) .Bind("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( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false) .Bind("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& out, - const Json::Value* value); +bool SubConditionHelper(std::unique_ptr& out, + const Json::Value* value, cmJSONState* state); auto const ListConditionVectorHelper = JSONHelperBuilder::Vector>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, - SubConditionHelper); + cmCMakePresetErrors::INVALID_CONDITION, SubConditionHelper); auto const AnyAllOfConditionHelper = JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false) .Bind("type"_s, nullptr, ConditionStringHelper, true) .Bind("conditions"_s, &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions, @@ -126,158 +120,160 @@ auto const AnyAllOfConditionHelper = auto const NotConditionHelper = JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + cmCMakePresetErrors::INVALID_CONDITION_OBJECT, false) .Bind("type"_s, nullptr, ConditionStringHelper, true) .Bind("condition"_s, &cmCMakePresetsGraphInternal::NotCondition::SubCondition, SubConditionHelper); -ReadFileResult ConditionHelper( - std::unique_ptr& out, - const Json::Value* value) +bool ConditionHelper(std::unique_ptr& 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(); c->Value = value->asBool(); out = std::move(c); - return ReadFileResult::READ_OK; + return true; } if (value->isNull()) { out = cm::make_unique(); - 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(); - 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(); - 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(); - 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(); - 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(); 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(); - 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& out, - const Json::Value* value) +bool SubConditionHelper(std::unique_ptr& out, + const Json::Value* value, cmJSONState* state) { std::unique_ptr 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& out, - const Json::Value* value) +bool EnvironmentHelper(cm::optional& 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( - ReadFileResult::NO_VERSION, VersionIntHelper); + cmCMakePresetErrors::NO_VERSION, VersionIntHelper); auto const RootVersionHelper = - JSONHelperBuilder::Object(ReadFileResult::READ_OK, - ReadFileResult::INVALID_ROOT) + JSONHelperBuilder::Object(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( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false) + JSONHelperBuilder::Object(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( - ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper); + cmCMakePresetErrors::INVALID_INCLUDE, IncludeHelper); auto const RootPresetsHelper = - JSONHelperBuilder::Object(ReadFileResult::READ_OK, - ReadFileResult::INVALID_ROOT, false) + JSONHelperBuilder::Object( + cmCMakePresetErrors::INVALID_ROOT_OBJECT, false) .Bind("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( - "vendor"_s, nullptr, - cmCMakePresetsGraphInternal::VendorHelper(ReadFileResult::INVALID_ROOT), - false); + .Bind("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); + static auto const helper = JSONHelperBuilder::String(); + return helper(out, value, state); +} - return helper(out, 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; } -cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper( - std::vector& out, const Json::Value* value) +bool PresetVectorStringHelper(std::vector& out, + const Json::Value* value, cmJSONState* state) { static auto const helper = JSONHelperBuilder::Vector( - 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& out, const Json::Value* value) +bool PresetOptionalBoolHelper(cm::optional& out, + const Json::Value* value, cmJSONState* state) { - static auto const helper = JSONHelperBuilder::Optional( - ReadFileResult::READ_OK, PresetBoolHelper); - - return helper(out, value); + static auto const helper = + JSONHelperBuilder::Optional(PresetBoolHelper); + return helper(out, value, state); } -cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out, - const Json::Value* value) +bool PresetIntHelper(int& out, const Json::Value* value, cmJSONState* state) { - static auto const helper = JSONHelperBuilder::Int( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); - - return helper(out, value); + static auto const helper = JSONHelperBuilder::Int(); + return helper(out, value, state); } -cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper( - cm::optional& out, const Json::Value* value) +bool PresetOptionalIntHelper(cm::optional& out, const Json::Value* value, + cmJSONState* state) { - static auto const helper = - JSONHelperBuilder::Optional(ReadFileResult::READ_OK, PresetIntHelper); - - return helper(out, value); + static auto const helper = JSONHelperBuilder::Optional(PresetIntHelper); + return helper(out, value, state); } -cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper( - std::vector& out, const Json::Value* value) +bool PresetVectorIntHelper(std::vector& out, const Json::Value* value, + cmJSONState* state) { static auto const helper = JSONHelperBuilder::Vector( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper); - - return helper(out, value); + cmCMakePresetErrors::INVALID_PRESET, PresetIntHelper); + return helper(out, value, state); } -cmJSONHelper VendorHelper(ReadFileResult error) +cmJSONHelper 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& out, - const Json::Value* value) + const Json::Value* value, cmJSONState* state) { std::unique_ptr ptr; - auto result = ConditionHelper(ptr, value); + auto result = ConditionHelper(ptr, value, state); out = std::move(ptr); return result; } -ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector& out, - const Json::Value* value) +bool PresetVectorOneOrMoreStringHelper(std::vector& 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>& out, - const Json::Value* value) + const Json::Value* value, cmJSONState* state) { static auto const helper = JSONHelperBuilder::Map>( - 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& inProgressFiles, File*& file, std::string& errMsg) +bool cmCMakePresetsGraph::ReadJSONFile(const std::string& filename, + RootType rootType, + ReadReason readReason, + std::vector& 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(); @@ -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 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 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 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 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 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; } diff --git a/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx index 430d7ee..07f2bc3 100644 --- a/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx @@ -13,25 +13,27 @@ #include #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; +using JSONHelperBuilder = cmJSONHelperBuilder; -ReadFileResult PackageResolveModeHelper(cm::optional& out, - const Json::Value* value) +bool PackageResolveModeHelper(cm::optional& 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& 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 const - ResolvePackageReferencesHelper = - [](BuildPreset& out, const Json::Value* value) -> ReadFileResult { - return PackageResolveModeHelper(out.ResolvePackageReferences, value); +std::function const + ResolvePackageReferencesHelper = [](BuildPreset& out, + const Json::Value* value, + cmJSONState* state) -> bool { + return PackageResolveModeHelper(out.ResolvePackageReferences, value, state); }; auto const BuildPresetHelper = - JSONHelperBuilder::Object(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET, false) + JSONHelperBuilder::Object( + 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("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& out, - const Json::Value* value) +bool BuildPresetsHelper(std::vector& out, + const Json::Value* value, cmJSONState* state) { static auto const helper = JSONHelperBuilder::Vector( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - BuildPresetHelper); + cmCMakePresetErrors::INVALID_PRESETS, BuildPresetHelper); - return helper(out, value); + return helper(out, value, state); } } diff --git a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx index 7cff55a..a1774be 100644 --- a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx @@ -12,72 +12,77 @@ #include +#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; +using JSONHelperBuilder = cmJSONHelperBuilder; -ReadFileResult ArchToolsetStrategyHelper( - cm::optional& out, const Json::Value* value) +bool ArchToolsetStrategyHelper(cm::optional& 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 +std::function ArchToolsetHelper( std::string ConfigurePreset::*valueField, cm::optional ConfigurePreset::*strategyField) { auto const objectHelper = - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + JSONHelperBuilder::Object(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( - 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& out, - const Json::Value* value) +bool VariableHelper(cm::optional& 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>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); + cmCMakePresetErrors::INVALID_PRESET, VariableHelper); auto const PresetWarningsHelper = JSONHelperBuilder::Object( - 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( - 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( - 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( - 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("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& out, - const Json::Value* value) +bool ConfigurePresetsHelper(std::vector& out, + const Json::Value* value, cmJSONState* state) { static auto const helper = JSONHelperBuilder::Vector( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - ConfigurePresetHelper); + cmCMakePresetErrors::INVALID_PRESETS, ConfigurePresetHelper); - return helper(out, value); + return helper(out, value, state); } } diff --git a/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx b/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx index 4ae51b1..7290d4d 100644 --- a/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx @@ -12,34 +12,34 @@ #include +#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::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + cmJSONHelperBuilder::Object( + 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::String( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); +auto const VariableHelper = + cmJSONHelperBuilder::String(cmCMakePresetErrors::INVALID_VARIABLE); -auto const VariablesHelper = - cmJSONHelperBuilder::Map( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); +auto const VariablesHelper = cmJSONHelperBuilder::Map( + cmCMakePresetErrors::INVALID_VARIABLE, VariableHelper); auto const PackagePresetHelper = - cmJSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + cmJSONHelperBuilder::Object( + 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("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& out, - const Json::Value* value) +bool PackagePresetsHelper(std::vector& out, + const Json::Value* value, cmJSONState* state) { - static auto const helper = - cmJSONHelperBuilder::Vector( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - PackagePresetHelper); + static auto const helper = cmJSONHelperBuilder::Vector( + cmCMakePresetErrors::INVALID_PRESETS, PackagePresetHelper); - return helper(out, value); + return helper(out, value, state); } } diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx index 3856f63..791be04 100644 --- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx @@ -12,86 +12,93 @@ #include +#include "cmCMakePresetErrors.h" #include "cmCMakePresetsGraph.h" #include "cmCMakePresetsGraphInternal.h" #include "cmJSONHelpers.h" #include "CTest/cmCTestTypes.h" +class cmJSONState; + namespace { -using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using TestPreset = cmCMakePresetsGraph::TestPreset; -using JSONHelperBuilder = cmJSONHelperBuilder; +using JSONHelperBuilder = cmJSONHelperBuilder; -ReadFileResult TestPresetOutputVerbosityHelper( - TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) +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( - ReadFileResult::READ_OK, TestPresetOutputVerbosityHelper); + TestPresetOutputVerbosityHelper); -ReadFileResult TestPresetOutputTruncationHelper( - cm::optional& out, const Json::Value* value) +bool TestPresetOutputTruncationHelper( + cm::optional& 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( - ReadFileResult::READ_OK, JSONHelperBuilder::Object( - 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( - ReadFileResult::READ_OK, - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object() .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& 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( - ReadFileResult::READ_OK, - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object() .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( - ReadFileResult::READ_OK, - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object() .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( - ReadFileResult::READ_OK, - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object() .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( - 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( - ReadFileResult::READ_OK, - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object() .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( - ReadFileResult::READ_OK, TestPresetExecutionNoTestsActionHelper); + TestPresetExecutionNoTestsActionHelper); auto const TestPresetExecutionHelper = JSONHelperBuilder::Optional( - ReadFileResult::READ_OK, - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object() .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( - ReadFileResult::READ_OK, - JSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object() .Bind("include"_s, &TestPreset::FilterOptions::Include, TestPresetOptionalFilterIncludeHelper, false) .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude, TestPresetOptionalFilterExcludeHelper, false)); auto const TestPresetHelper = - JSONHelperBuilder::Object(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET, false) + JSONHelperBuilder::Object( + 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("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& out, const Json::Value* value) +bool TestPresetsHelper(std::vector& out, + const Json::Value* value, cmJSONState* state) { static auto const helper = JSONHelperBuilder::Vector( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - TestPresetHelper); + cmCMakePresetErrors::INVALID_PRESETS, TestPresetHelper); - return helper(out, value); + return helper(out, value, state); } } diff --git a/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx index 33680a1..7224e17 100644 --- a/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx @@ -9,69 +9,72 @@ #include +#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::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + cmJSONHelperBuilder::Object( + JsonErrors::INVALID_OBJECT, false) .Bind("type"_s, &WorkflowPreset::WorkflowStep::PresetType, WorkflowStepTypeHelper) .Bind("name"_s, &WorkflowPreset::WorkflowStep::PresetName, cmCMakePresetsGraphInternal::PresetStringHelper); auto const WorkflowStepsHelper = - cmJSONHelperBuilder::Vector( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, - WorkflowStepHelper); + cmJSONHelperBuilder::Vector( + cmCMakePresetErrors::INVALID_PRESET, WorkflowStepHelper); auto const WorkflowPresetHelper = - cmJSONHelperBuilder::Object( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + cmJSONHelperBuilder::Object( + cmCMakePresetErrors::INVALID_PRESET_OBJECT, false) .Bind("name"_s, &WorkflowPreset::Name, - cmCMakePresetsGraphInternal::PresetStringHelper) + cmCMakePresetsGraphInternal::PresetNameHelper) .Bind("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& out, - const Json::Value* value) + const Json::Value* value, cmJSONState* state) { - static auto const helper = - cmJSONHelperBuilder::Vector( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - WorkflowPresetHelper); + static auto const helper = cmJSONHelperBuilder::Vector( + cmCMakePresetErrors::INVALID_PRESETS, WorkflowPresetHelper); - return helper(out, value); + return helper(out, value, state); } } diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 5899a61..c8eea38 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -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; } diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h index f7151b5..94641de 100644 --- a/Source/cmJSONHelpers.h +++ b/Source/cmJSONHelpers.h @@ -2,9 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include "cmConfigure.h" // IWYU pragma: keep + #include #include #include +#include #include #include #include @@ -14,20 +17,129 @@ #include -template +#include "cmJSONState.h" + +template using cmJSONHelper = - std::function; + std::function; + +using ErrorGenerator = std::function; + +namespace JsonErrors { +enum ObjectError +{ + RequiredMissing, + InvalidObject, + ExtraField, + MissingRequired +}; +using ErrorGenerator = std::function; +using ObjectErrorGenerator = + std::function; +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& + 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 struct cmJSONHelperBuilder { + template 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 @@ -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; + using MemberFunction = std::function; struct Member { cm::string_view Name; @@ -109,8 +231,7 @@ struct cmJSONHelperBuilder }; std::vector 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 String( - E success, E fail, const std::string& defval = "") + + static cmJSONHelper 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 String(const std::string& defval) + { + return String(JsonErrors::INVALID_STRING, defval); + }; - static cmJSONHelper Int(E success, E fail, - int defval = 0) + static cmJSONHelper Int( + const JsonErrors::ErrorGenerator& error = JsonErrors::INVALID_INT, + int defval = 0) { - return [success, fail, defval](int& out, const Json::Value* value, - CallState&&... /*state*/) -> E { + 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 UInt( - E success, E fail, unsigned int defval = 0) + static cmJSONHelper Int(int defval) + { + return Int(JsonErrors::INVALID_INT, defval); + }; + + static cmJSONHelper UInt( + const JsonErrors::ErrorGenerator& error = JsonErrors::INVALID_UINT, + unsigned int defval = 0) { - return [success, fail, defval](unsigned int& out, const Json::Value* value, - CallState&&... /*state*/) -> E { + 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 success, E fail, - bool defval = false) + static cmJSONHelper UInt(unsigned int defval) + { + return UInt(JsonErrors::INVALID_UINT, defval); + } + + static cmJSONHelper Bool( + const JsonErrors::ErrorGenerator& error = JsonErrors::INVALID_BOOL, + bool defval = false) { - return [success, fail, defval](bool& out, const Json::Value* value, - CallState&&... /*state*/) -> E { + 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 defval) + { + return Bool(JsonErrors::INVALID_BOOL, defval); + } + template - static cmJSONHelper, E, CallState...> VectorFilter( - E success, E fail, F func, Filter filter) + static cmJSONHelper> VectorFilter( + const JsonErrors::ErrorGenerator& error, F func, Filter filter) { - return [success, fail, func, filter](std::vector& out, - const Json::Value* value, - CallState&&... state) -> E { + return [error, func, filter](std::vector& 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 - static cmJSONHelper, E, CallState...> Vector(E success, - E fail, F func) + static cmJSONHelper> Vector(JsonErrors::ErrorGenerator error, + F func) { - return VectorFilter(success, fail, func, + return VectorFilter(std::move(error), func, [](const T&) { return true; }); } template - static cmJSONHelper, E, CallState...> MapFilter( - E success, E fail, F func, Filter filter) + static cmJSONHelper> MapFilter( + const JsonErrors::ErrorGenerator& error, F func, Filter filter) { - return [success, fail, func, filter](std::map& out, - const Json::Value* value, - CallState&&... state) -> E { + return [error, func, filter](std::map& 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 - static cmJSONHelper, E, CallState...> Map(E success, - E fail, - F func) + static cmJSONHelper> Map( + const JsonErrors::ErrorGenerator& error, F func) { - return MapFilter(success, fail, func, + return MapFilter(error, func, [](const std::string&) { return true; }); } template - static cmJSONHelper, E, CallState...> Optional(E success, - F func) + static cmJSONHelper> Optional(F func) { - return [success, func](cm::optional& out, const Json::Value* value, - CallState&&... state) -> E { + return [func](cm::optional& 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 - static cmJSONHelper Required(E fail, F func) + static cmJSONHelper 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); }; } }; diff --git a/Source/cmJSONState.cxx b/Source/cmJSONState.cxx new file mode 100644 index 0000000..92bde77 --- /dev/null +++ b/Source/cmJSONState.cxx @@ -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 + +#include + +#include +#include + +#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(fin), + std::istreambuf_iterator()); + 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 }; +} diff --git a/Source/cmJSONState.h b/Source/cmJSONState.h new file mode 100644 index 0000000..4984c81 --- /dev/null +++ b/Source/cmJSONState.h @@ -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 +#include +#include +#include + +#include "cmJSONState.h" +#include "cmStringAlgorithms.h" + +namespace Json { +class Value; +} + +class cmJSONState +{ + using Location = struct + { + int line; + int column; + }; + +public: + using JsonPair = std::pair; + 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 parseStack; + std::vector errors; + std::string doc; + +private: + std::string GetJsonContext(Location loc); + Location LocateInDocument(ptrdiff_t offset); +}; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index dbf961d..db47e43 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -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& 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 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; } diff --git a/Tests/CMakeLib/testCTestResourceAllocator.cxx b/Tests/CMakeLib/testCTestResourceAllocator.cxx index 72e06e5..3a2e524 100644 --- a/Tests/CMakeLib/testCTestResourceAllocator.cxx +++ b/Tests/CMakeLib/testCTestResourceAllocator.cxx @@ -5,12 +5,16 @@ #include "cmCTestResourceAllocator.h" #include "cmCTestResourceSpec.h" - -static const cmCTestResourceSpec spec{ { { - /* clang-format off */ - { "gpus", { { "0", 4 }, { "1", 8 }, { "2", 0 }, { "3", 8 } } }, - /* clang-format on */ -} } }; +#include "cmJSONState.h" + +static const cmCTestResourceSpec spec{ + { { + /* clang-format off */ + { "gpus", { { "0", 4 }, { "1", 8 }, { "2", 0 }, { "3", 8 } }, }, + /* clang-format on */ + } }, + cmJSONState() +}; static bool testInitializeFromResourceSpec() { diff --git a/Tests/CMakeLib/testCTestResourceSpec.cxx b/Tests/CMakeLib/testCTestResourceSpec.cxx index b49f8ff..4a0021f 100644 --- a/Tests/CMakeLib/testCTestResourceSpec.cxx +++ b/Tests/CMakeLib/testCTestResourceSpec.cxx @@ -3,89 +3,72 @@ #include #include "cmCTestResourceSpec.h" +#include "cmJSONState.h" struct ExpectedSpec { std::string Path; - cmCTestResourceSpec::ReadFileResult ParseResult; + bool ParseResult; cmCTestResourceSpec Expected; }; static const std::vector 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; } diff --git a/Tests/CMakeLib/testJSONHelpers.cxx b/Tests/CMakeLib/testJSONHelpers.cxx index 053c163..50f0386 100644 --- a/Tests/CMakeLib/testJSONHelpers.cxx +++ b/Tests/CMakeLib/testJSONHelpers.cxx @@ -10,6 +10,7 @@ #include #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; +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; +using JSONHelperBuilder = cmJSONHelperBuilder; -auto const IntHelper = - JSONHelperBuilder::Int(ErrorCode::Success, ErrorCode::InvalidInt, 1); +auto const IntHelper = JSONHelperBuilder::Int(1); auto const RequiredIntHelper = - JSONHelperBuilder::Required(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(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( - ErrorCode::MissingRequired, StringHelper); + ErrorMessages::MissingRequired, StringHelper); auto const StringVectorHelper = JSONHelperBuilder::Vector( - ErrorCode::Success, ErrorCode::InvalidArray, StringHelper); + ErrorMessages::InvalidArray, StringHelper); auto const StringVectorFilterHelper = JSONHelperBuilder::VectorFilter( - ErrorCode::Success, ErrorCode::InvalidArray, StringHelper, + ErrorMessages::InvalidArray, StringHelper, [](const std::string& value) { return value != "ignore"; }); -auto const StringMapHelper = JSONHelperBuilder::Map( - ErrorCode::Success, ErrorCode::InvalidObject, StringHelper); +auto const StringMapHelper = + JSONHelperBuilder::Map(ErrorMessages::InvalidMap, StringHelper); auto const StringMapFilterHelper = JSONHelperBuilder::MapFilter( - ErrorCode::Success, ErrorCode::InvalidObject, StringHelper, + ErrorMessages::InvalidMap, StringHelper, [](const std::string& key) { return key != "ignore"; }); auto const OptionalStringHelper = - JSONHelperBuilder::Optional(ErrorCode::Success, StringHelper); + JSONHelperBuilder::Optional(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(ErrorCode::Success, - ErrorCode::InvalidSubObject) - .Bind("subfield"_s, &ObjectStruct::Field2, IntHelper); - auto const helper = JSONHelperBuilder::Object( - ErrorCode::Success, ErrorCode::InvalidObject) + auto const subhelper = JSONHelperBuilder::Object().Bind( + "subfield"_s, &ObjectStruct::Field2, IntHelper); + auto const helper = JSONHelperBuilder::Object() .Bind("field1"_s, &ObjectStruct::Field1, StringHelper) .Bind("field2"_s, subhelper) .Bind("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(ErrorCode::Success, - ErrorCode::InvalidObject) + JSONHelperBuilder::Object(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( - 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(ErrorCode::Success, - ErrorCode::InvalidObject) + JSONHelperBuilder::Object(ErrorMessages::InvalidObject, true) .Bind("field1"_s, &ObjectStruct::Field1, StringHelper, false) .Bind("field2"_s, &ObjectStruct::Field2, IntHelper, false) .Bind("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 l{ "default" }; std::vector 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 m{ { "key", "default" } }; std::map 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 m{ { "key", "default" } }; std::map 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 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; } diff --git a/Tests/RunCMake/CMakePresets/Comment-stderr.txt b/Tests/RunCMake/CMakePresets/Comment-stderr.txt index b3b6b66..8619cf5 100644 --- a/Tests/RunCMake/CMakePresets/Comment-stderr.txt +++ b/Tests/RunCMake/CMakePresets/Comment-stderr.txt @@ -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\. diff --git a/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt b/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt index ea5f47f..31ebbc1 100644 --- a/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt +++ b/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt index 895afcb..2d5b477 100644 --- a/Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt +++ b/Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt index 1e59e92..596fcf8 100644 --- a/Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt +++ b/Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt index 56e630b..a6b83c8 100644 --- a/Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt +++ b/Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt b/Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt index c9361ae..ebb9a2d 100644 --- a/Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt +++ b/Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/DuplicatePresets: Duplicate presets$ +]*/Tests/RunCMake/CMakePresets/DuplicatePresets: +Duplicate preset: "DuplicatePresets"$ diff --git a/Tests/RunCMake/CMakePresets/EmptyCacheKey-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyCacheKey-stderr.txt index 749d306..cb9e545 100644 --- a/Tests/RunCMake/CMakePresets/EmptyCacheKey-stderr.txt +++ b/Tests/RunCMake/CMakePresets/EmptyCacheKey-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/EmptyCacheKey: Invalid preset$ +]*/Tests/RunCMake/CMakePresets/EmptyCacheKey: +Invalid preset: "EmptyCacheKey"$ diff --git a/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt index 723ac21..7774fee 100644 --- a/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt +++ b/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/EmptyEnvKey-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyEnvKey-stderr.txt index 365f537..bc0f866 100644 --- a/Tests/RunCMake/CMakePresets/EmptyEnvKey-stderr.txt +++ b/Tests/RunCMake/CMakePresets/EmptyEnvKey-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/EmptyEnvKey: Invalid preset$ +]*/Tests/RunCMake/CMakePresets/EmptyEnvKey: +Invalid preset: "EmptyEnvKey"$ diff --git a/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt index 880cee6..b3bfe21 100644 --- a/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt +++ b/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt index 0d3c500..6f84690 100644 --- a/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt +++ b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt @@ -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": "", + \^$ diff --git a/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt b/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt index 1d22b87..8e19c69 100644 --- a/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt +++ b/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt index 3221345..5c02d5b 100644 --- a/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt +++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated: Invalid preset$ +]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated: +Invalid preset: "ErrorNoWarningDeprecated"$ diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt index d2ddb90..4640b1e 100644 --- a/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt +++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDev: Invalid preset$ +]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDev: +Invalid preset: "ErrorNoWarningDev"$ diff --git a/Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt b/Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt index 559e3c2..2e94831 100644 --- a/Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt +++ b/Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt @@ -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 + \^$ diff --git a/Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt b/Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt index bb281be..554cd4a 100644 --- a/Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt +++ b/Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt @@ -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 + \^$ diff --git a/Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt b/Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt index 9b346e7..5cb777c 100644 --- a/Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt +++ b/Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt @@ -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 + \^$ diff --git a/Tests/RunCMake/CMakePresets/FileDirFuture-stderr.txt b/Tests/RunCMake/CMakePresets/FileDirFuture-stderr.txt index ba85f0f..b49df79 100644 --- a/Tests/RunCMake/CMakePresets/FileDirFuture-stderr.txt +++ b/Tests/RunCMake/CMakePresets/FileDirFuture-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt index 36123bd..ca481c6 100644 --- a/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt +++ b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt index 9382423..7aedc6d 100644 --- a/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt +++ b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt index d8622f2..598478f 100644 --- a/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt +++ b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt @@ -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, + \^$ diff --git a/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt index 7f4bb9a..a1dae4c 100644 --- a/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt +++ b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/IncludeCycle-stderr.txt b/Tests/RunCMake/CMakePresets/IncludeCycle-stderr.txt index 3343204..fc6292d 100644 --- a/Tests/RunCMake/CMakePresets/IncludeCycle-stderr.txt +++ b/Tests/RunCMake/CMakePresets/IncludeCycle-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/IncludeCycle3Files-stderr.txt b/Tests/RunCMake/CMakePresets/IncludeCycle3Files-stderr.txt index 35aea4c..1bc402a 100644 --- a/Tests/RunCMake/CMakePresets/IncludeCycle3Files-stderr.txt +++ b/Tests/RunCMake/CMakePresets/IncludeCycle3Files-stderr.txt @@ -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 diff --git a/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt b/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt index 85a2d78..fba5b01 100644 --- a/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt +++ b/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/IncludeV3-stderr.txt b/Tests/RunCMake/CMakePresets/IncludeV3-stderr.txt index 1869b6d..7e975a7 100644 --- a/Tests/RunCMake/CMakePresets/IncludeV3-stderr.txt +++ b/Tests/RunCMake/CMakePresets/IncludeV3-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/IncludeV4V3-stderr.txt b/Tests/RunCMake/CMakePresets/IncludeV4V3-stderr.txt index 89e3e3d..f14c583 100644 --- a/Tests/RunCMake/CMakePresets/IncludeV4V3-stderr.txt +++ b/Tests/RunCMake/CMakePresets/IncludeV4V3-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-stderr.txt index 4a4d4ce..5df075d 100644 --- a/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-stderr.txt @@ -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": {} + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt index 97f3876..216f308 100644 --- a/Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/InvalidInheritance: Invalid preset$ +]*/Tests/RunCMake/CMakePresets/InvalidInheritance: +Invalid preset: "InvalidInheritance"$ diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt index 2fe8c66..deb35b4 100644 --- a/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt @@ -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": \[\] + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt index 9572875..7f19412 100644 --- a/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt @@ -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": \[\], + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt index 8f6ff7c..4cceb73 100644 --- a/Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt @@ -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": \[\], + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt index 89a424a..f92c48e 100644 --- a/Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt @@ -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 + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt index 2b0f560..d7081af 100644 --- a/Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt @@ -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": {} + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt index 5b500e4..86cd861 100644 --- a/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt index e5c434d..5f2dcc1 100644 --- a/Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt @@ -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 +\[\] +\^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-stderr.txt index fab3766..d0974ac 100644 --- a/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-stderr.txt @@ -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": {} + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt index 0ab07c3..fdb7072 100644 --- a/Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt @@ -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": \[\] + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt index 6d9102a..f329d97 100644 --- a/Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt @@ -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": \[\] + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt index af923f0..fc6534e 100644 --- a/Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt @@ -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, + \^$ diff --git a/Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt index 7e0fcfd..97fe9d6 100644 --- a/Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt +++ b/Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt @@ -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", + \^$ diff --git a/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt index 89eff9f..92a1b2b 100644 --- a/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt +++ b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt @@ -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 diff --git a/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt index 92b3723..e933100 100644 --- a/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt +++ b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt @@ -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, + \^ diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt index 6548caf..30ab9ce 100644 --- a/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt +++ b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt @@ -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", + \^$ diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt index 6036fe3..c9001ea 100644 --- a/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt +++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt @@ -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 + \^$ diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt index bdee4cd..3911c84 100644 --- a/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt +++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt @@ -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 + \^$ diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt index b5d3a39..e989fa8 100644 --- a/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt +++ b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt @@ -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 + \^$ diff --git a/Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt b/Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt index c807ffc..afc5887 100644 --- a/Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt +++ b/Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt index b525fc3..bae9794 100644 --- a/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt +++ b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt index 6c0c9f7..c7e5b5e 100644 --- a/Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt +++ b/Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt index 0ee338a..9aff07f 100644 --- a/Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt +++ b/Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt @@ -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 + { + \^$ diff --git a/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt b/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt index 7dafe62..8c7ca6e 100644 --- a/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt +++ b/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt b/Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt index cdab32f..630c288 100644 --- a/Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt +++ b/Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt @@ -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": {} + \^$ diff --git a/Tests/RunCMake/CMakePresets/NoVersion-stderr.txt b/Tests/RunCMake/CMakePresets/NoVersion-stderr.txt index d4f07e4..f7c95db 100644 --- a/Tests/RunCMake/CMakePresets/NoVersion-stderr.txt +++ b/Tests/RunCMake/CMakePresets/NoVersion-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/PathListSepFuture-stderr.txt b/Tests/RunCMake/CMakePresets/PathListSepFuture-stderr.txt index b961aaf..7652ddc 100644 --- a/Tests/RunCMake/CMakePresets/PathListSepFuture-stderr.txt +++ b/Tests/RunCMake/CMakePresets/PathListSepFuture-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt b/Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt index 6604a14..62e9248 100644 --- a/Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt +++ b/Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt @@ -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 + \[\] + \^$ diff --git a/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt b/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt index 42b74d6..520b473 100644 --- a/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt +++ b/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt b/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt index f9481f0..abdbb81 100644 --- a/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt +++ b/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-stderr.txt index cf17881..6063762 100644 --- a/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-stderr.txt +++ b/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-stderr.txt @@ -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" + \^$ diff --git a/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-stderr.txt index 8f9be29..55f9c7a 100644 --- a/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-stderr.txt +++ b/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-stderr.txt @@ -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" + \^$ diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt b/Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt index 125265f..8b4139f 100644 --- a/Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt +++ b/Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/UserDuplicateCross: Duplicate presets$ +]*/Tests/RunCMake/CMakePresets/UserDuplicateCross: +Duplicate preset: "UserDuplicateCross"$ diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt b/Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt index 1071b17..15c46f4 100644 --- a/Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt +++ b/Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/UserDuplicateInUser: Duplicate presets$ +]*/Tests/RunCMake/CMakePresets/UserDuplicateInUser: +Duplicate preset: "UserDuplicateInUser"$ diff --git a/Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt b/Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt index 5ad8b4b..2ce1316 100644 --- a/Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt +++ b/Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt b/Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt index 8cacb0a..ce1aa20 100644 --- a/Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt +++ b/Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt @@ -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": \[\] + \^$ diff --git a/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt index f08f4c1..aea1dce 100644 --- a/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt +++ b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresetsBuild/ConfigurePresetUnreachable-build-x-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/ConfigurePresetUnreachable-build-x-stderr.txt index 05695d9..13b4158 100644 --- a/Tests/RunCMake/CMakePresetsBuild/ConfigurePresetUnreachable-build-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsBuild/ConfigurePresetUnreachable-build-x-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt index 303632e..b62fd16 100644 --- a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt +++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt index 303632e..b62fd16 100644 --- a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt +++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt index fcb37bc..9ce6ea5 100644 --- a/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt +++ b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt @@ -1,2 +1,3 @@ CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset: Invalid preset +]*/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset: +Invalid preset: "noConfigurePreset"$ diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt index d6ae62d..48a5bd3 100644 --- a/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt index 4c461e3..38ec6bf 100644 --- a/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt index b814bbb..3f1a506 100644 --- a/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt @@ -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$ diff --git a/Tests/RunCMake/CMakePresetsTest/ConfigurePresetUnreachable-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/ConfigurePresetUnreachable-test-x-stderr.txt index d49148d..0be98ef 100644 --- a/Tests/RunCMake/CMakePresetsTest/ConfigurePresetUnreachable-test-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/ConfigurePresetUnreachable-test-x-stderr.txt @@ -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 diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt index 3d7cdd0..c427e42 100644 --- a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt @@ -1,2 +1,3 @@ CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset: Invalid "configurePreset" field +]*/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset: +Invalid "configurePreset": "badConfigurePreset"$ diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt index 3d7cdd0..c427e42 100644 --- a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt @@ -1,2 +1,3 @@ CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset: Invalid "configurePreset" field +]*/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset: +Invalid "configurePreset": "badConfigurePreset"$ diff --git a/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt index b167f68..a70497f 100644 --- a/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt @@ -1,2 +1,3 @@ CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset: Invalid preset +]*/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset: +Invalid preset: "noConfigurePreset"$ diff --git a/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt index acd5785..da94c3a 100644 --- a/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported: File version must be 6 or higher for CTest JUnit output support$ +]*/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported: +File version must be 6 or higher for CTest JUnit output support$ diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt index eb0ec1a..74c0740 100644 --- a/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt @@ -1,2 +1,3 @@ CMake Error: Could not read presets from [^ -]*Tests/RunCMake/CMakePresetsTest/PresetsUnsupported: File version must be 2 or higher for build and test preset support. +]*Tests/RunCMake/CMakePresetsTest/PresetsUnsupported: +File version must be 2 or higher for build and test preset support diff --git a/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt index 90ea7c3..4deb755 100644 --- a/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt +++ b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported: File version must be 5 or higher for testOutputTruncation preset support\.$ +]*/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported: +File version must be 5 or higher for testOutputTruncation preset support$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt index 22ca94d..33fe914 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch: Invalid workflow steps$ +]*/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch: +Invalid workflow step "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt index cbfee5a..776257b 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure: Invalid workflow steps$ +]*/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure: +First workflow step "default" must be a configure step$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt index 049ed6b..f34a605 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps: Invalid workflow steps$ +]*/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps: +No workflow steps specified for "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt index c522b84..a9029e1 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep: Invalid workflow steps$ +]*/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep: +Invalid workflow step "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt index b0ad7d5..35eac16 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure: Invalid workflow steps$ +]*/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure: +Configure workflow step "default" must be the first step diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt index 425e719..f0a36f8 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep: Workflow step is unreachable from preset's file$ +]*/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep: +Workflow step "default" is unreachable from preset's file$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt index 5cf01aa..93e31eb 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt @@ -1,2 +1,3 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion: File version must be 6 or higher for workflow preset support$ +]*/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion: +File version must be 6 or higher for workflow preset support$ diff --git a/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx b/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx index 5c6c8d8..65f17b6 100644 --- a/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx +++ b/Tests/RunCMake/CTestResourceAllocation/ctresalloc.cxx @@ -286,8 +286,7 @@ static int doVerify(int argc, char const* const* argv) std::set testNameSet(testNameList.begin(), testNameList.end()); cmCTestResourceSpec spec; - if (spec.ReadFromJSONFile(resFile) != - cmCTestResourceSpec::ReadFileResult::READ_OK) { + if (spec.ReadFromJSONFile(resFile) != true) { std::cout << "Could not read resource spec " << resFile << std::endl; return 1; } -- cgit v0.12