From 87d86bfba64d8b88537a4a85c1d71f521986b614 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 20 Feb 2024 14:23:58 +0100 Subject: [PATCH] Replace internal JSON library jsoncpp with nlohmann::json. --- CMakeLists.txt | 10 +- Changelog.md | 2 + cmake/jsoncpp.cmake | 72 --- cmake/nlohmann-json.cmake | 21 + libevmasm/AbstractAssemblyStack.h | 2 +- libevmasm/Assembly.cpp | 117 ++-- libevmasm/Assembly.h | 11 +- libevmasm/EVMAssemblyStack.cpp | 6 +- libevmasm/EVMAssemblyStack.h | 4 +- libsolidity/ast/AST.h | 3 +- libsolidity/ast/ASTJsonExporter.cpp | 223 ++++--- libsolidity/ast/ASTJsonExporter.h | 46 +- libsolidity/ast/ASTJsonImporter.cpp | 402 ++++++------ libsolidity/ast/ASTJsonImporter.h | 154 ++--- libsolidity/codegen/ir/IRGenerationContext.h | 1 + libsolidity/codegen/ir/IRGenerator.cpp | 3 +- libsolidity/codegen/ir/IRGenerator.h | 4 +- .../experimental/codegen/IRGenerator.h | 2 +- libsolidity/formal/BMC.h | 1 + libsolidity/interface/ABI.cpp | 54 +- libsolidity/interface/ABI.h | 8 +- libsolidity/interface/CompilerStack.cpp | 86 ++- libsolidity/interface/CompilerStack.h | 49 +- libsolidity/interface/Natspec.cpp | 64 +- libsolidity/interface/Natspec.h | 14 +- libsolidity/interface/StandardCompiler.cpp | 611 +++++++++--------- libsolidity/interface/StandardCompiler.h | 20 +- libsolidity/interface/StorageLayout.cpp | 22 +- libsolidity/interface/StorageLayout.h | 9 +- libsolidity/lsp/DocumentHoverHandler.cpp | 6 +- libsolidity/lsp/DocumentHoverHandler.h | 2 +- libsolidity/lsp/GotoDefinition.cpp | 6 +- libsolidity/lsp/GotoDefinition.h | 2 +- libsolidity/lsp/HandlerBase.cpp | 11 +- libsolidity/lsp/HandlerBase.h | 6 +- libsolidity/lsp/LanguageServer.cpp | 273 ++++---- libsolidity/lsp/LanguageServer.h | 32 +- libsolidity/lsp/RenameSymbol.cpp | 18 +- libsolidity/lsp/RenameSymbol.h | 2 +- libsolidity/lsp/SemanticTokensBuilder.cpp | 16 +- libsolidity/lsp/SemanticTokensBuilder.h | 6 +- libsolidity/lsp/Transport.cpp | 29 +- libsolidity/lsp/Transport.h | 15 +- libsolidity/lsp/Utils.cpp | 20 +- libsolidity/lsp/Utils.h | 10 +- libsolutil/CMakeLists.txt | 2 +- libsolutil/Exceptions.h | 1 + libsolutil/JSON.cpp | 248 ++++--- libsolutil/JSON.h | 98 ++- libyul/AsmJsonConverter.cpp | 84 ++- libyul/AsmJsonConverter.h | 42 +- libyul/AsmJsonImporter.cpp | 98 +-- libyul/AsmJsonImporter.h | 48 +- libyul/Object.cpp | 14 +- libyul/Object.h | 8 +- libyul/YulStack.cpp | 2 +- libyul/YulStack.h | 5 +- libyul/backends/evm/StackLayoutGenerator.cpp | 2 +- solc/CommandLineInterface.cpp | 78 +-- solc/CommandLineInterface.h | 2 +- test/Metadata.cpp | 28 +- test/Metadata.h | 2 +- .../standard_import_with_comments/input.json | 95 +++ .../standard_import_with_comments/output.json | 97 +++ .../input.json | 85 +++ .../output.json | 97 +++ .../input.json | 29 + .../output.json | 12 + .../standard_non_utf8_filename/input.json | 17 + .../standard_non_utf8_filename/output.json | 12 + .../standard_non_utf8_filename2/input.json | 17 + .../standard_non_utf8_filename2/output.json | 12 + .../standard_raw_utf16_filename/input.json | Bin 0 -> 297 bytes .../standard_raw_utf16_filename/output.json | 12 + test/libevmasm/Assembler.cpp | 2 +- test/libsolidity/ASTPropertyTest.cpp | 36 +- test/libsolidity/ASTPropertyTest.h | 2 +- test/libsolidity/GasTest.cpp | 18 +- test/libsolidity/LibSolc.cpp | 32 +- test/libsolidity/Metadata.cpp | 56 +- test/libsolidity/NatspecJSONTest.cpp | 4 +- test/libsolidity/NatspecJSONTest.h | 2 +- test/libsolidity/SemanticTest.cpp | 2 +- test/libsolidity/StandardCompiler.cpp | 610 ++++++++--------- test/libsolidity/util/ContractABIUtils.cpp | 16 +- test/libsolidity/util/ContractABIUtils.h | 7 +- test/libsolidity/util/TestFunctionCall.cpp | 2 +- test/libsolidity/util/TestFunctionCall.h | 6 +- test/libsolutil/JSON.cpp | 278 ++++---- test/solc/CommandLineInterface.cpp | 11 +- test/tools/fuzzer_common.cpp | 18 +- .../tools/ossfuzz/SolidityEvmoneInterface.cpp | 6 +- test/tools/ossfuzz/SolidityEvmoneInterface.h | 4 +- test/yulPhaser/Program.cpp | 2 +- tools/yulPhaser/Program.cpp | 2 +- 95 files changed, 2734 insertions(+), 2104 deletions(-) delete mode 100644 cmake/jsoncpp.cmake create mode 100644 cmake/nlohmann-json.cmake create mode 100644 test/cmdlineTests/standard_import_with_comments/input.json create mode 100644 test/cmdlineTests/standard_import_with_comments/output.json create mode 100644 test/cmdlineTests/standard_import_with_comments_simple/input.json create mode 100644 test/cmdlineTests/standard_import_with_comments_simple/output.json create mode 100644 test/cmdlineTests/standard_import_with_invalid_utf8/input.json create mode 100644 test/cmdlineTests/standard_import_with_invalid_utf8/output.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename/input.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename/output.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename2/input.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename2/output.json create mode 100644 test/cmdlineTests/standard_raw_utf16_filename/input.json create mode 100644 test/cmdlineTests/standard_raw_utf16_filename/output.json diff --git a/CMakeLists.txt b/CMakeLists.txt index b9f2ddc36cad..3e2332b9220b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warni option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) -option(STRICT_JSONCPP_VERSION "Strictly check installed jsoncpp version" ON) +option(STRICT_NLOHMANN_JSON_VERSION "Strictly check installed nlohmann json version" ON) # Setup cccache. include(EthCcache) @@ -48,9 +48,8 @@ include(EthCcache) include(EthDependencies) if (NOT USE_SYSTEM_LIBRARIES) include(fmtlib) - include(jsoncpp) + include(nlohmann-json) include(range-v3) - include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR}) endif() find_package(Threads) @@ -63,8 +62,8 @@ if (PROFILE_OPTIMIZER_STEPS) add_definitions(-DPROFILE_OPTIMIZER_STEPS) endif() -if (STRICT_JSONCPP_VERSION) - add_definitions(-DSTRICT_JSONCPP_VERSION_CHECK) +if (STRICT_NLOHMANN_JSON_VERSION) + add_definitions(-DSTRICT_NLOHMANN_JSON_VERSION_CHECK) endif() # Figure out what compiler and system are we using @@ -162,4 +161,3 @@ if (NOT ONLY_BUILD_SOLIDITY_LIBRARIES) add_subdirectory(test) endif() endif() - diff --git a/Changelog.md b/Changelog.md index c118e9f248a4..0f26cacfc90a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -32,6 +32,8 @@ Bugfixes: * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. * SMTChecker: Run Eldarica only when explicitly requested with `--model-checker-solvers eld`, even when it is present on the system. +Build System: + * Replace internal JSON library jsoncpp with nlohmann::json. ### 0.8.24 (2024-01-25) diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake deleted file mode 100644 index c47c2697a3dc..000000000000 --- a/cmake/jsoncpp.cmake +++ /dev/null @@ -1,72 +0,0 @@ -include(ExternalProject) - -if (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") - set(JSONCPP_CMAKE_COMMAND emcmake cmake) -else() - set(JSONCPP_CMAKE_COMMAND ${CMAKE_COMMAND}) -endif() - -set(prefix "${PROJECT_BINARY_DIR}/deps") -set(JSONCPP_LIBRARY "${prefix}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") -set(JSONCPP_INCLUDE_DIR "${prefix}/include") - -# TODO: Investigate why this breaks some emscripten builds and -# check whether this can be removed after updating the emscripten -# versions used in the CI runs. -if(EMSCRIPTEN) - # Do not include all flags in CMAKE_CXX_FLAGS for emscripten, - # but only use -std=c++17. Using all flags causes build failures - # at the moment. - set(JSONCPP_CXX_FLAGS -std=c++17) -else() - # jsoncpp uses implicit casts for comparing integer and - # floating point numbers. This causes clang-10 (used by ossfuzz builder) - # to error on the implicit conversions. Here, we request jsoncpp - # to unconditionally use static casts for these conversions by defining the - # JSON_USE_INT64_DOUBLE_CONVERSION preprocessor macro. Doing so, - # not only gets rid of the implicit conversion error that clang-10 produces - # but also forces safer behavior in general. - set(JSONCPP_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJSON_USE_INT64_DOUBLE_CONVERSION") -endif() - -set(byproducts "") -if(CMAKE_VERSION VERSION_GREATER 3.1) - set(byproducts BUILD_BYPRODUCTS "${JSONCPP_LIBRARY}") -endif() - -# Propagate CMAKE_MSVC_RUNTIME_LIBRARY on Windows builds, if set. -if (WIN32 AND POLICY CMP0091 AND CMAKE_MSVC_RUNTIME_LIBRARY) - list(APPEND JSONCPP_CMAKE_ARGS "-DCMAKE_POLICY_DEFAULT_CMP0091:STRING=NEW") - list(APPEND JSONCPP_CMAKE_ARGS "-DCMAKE_MSVC_RUNTIME_LIBRARY=${CMAKE_MSVC_RUNTIME_LIBRARY}") -endif() - -string(REPLACE ";" "$" CMAKE_OSX_ARCHITECTURES_ "${CMAKE_OSX_ARCHITECTURES}") -ExternalProject_Add(jsoncpp-project - PREFIX "${prefix}" - DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads" - DOWNLOAD_NAME jsoncpp-1.9.3.tar.gz - URL https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz - URL_HASH SHA256=8593c1d69e703563d94d8c12244e2e18893eeb9a8a9f8aa3d09a327aa45c8f7d - CMAKE_COMMAND ${JSONCPP_CMAKE_COMMAND} - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DCMAKE_INSTALL_LIBDIR=lib - # Build static lib but suitable to be included in a shared lib. - -DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS} - -DJSONCPP_WITH_EXAMPLE=OFF - -DJSONCPP_WITH_TESTS=OFF - -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF - -DCMAKE_CXX_FLAGS=${JSONCPP_CXX_FLAGS} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES_} - ${JSONCPP_CMAKE_ARGS} - ${byproducts} -) - -# Create jsoncpp imported library -add_library(jsoncpp STATIC IMPORTED) -file(MAKE_DIRECTORY ${JSONCPP_INCLUDE_DIR}) # Must exist. -set_property(TARGET jsoncpp PROPERTY IMPORTED_LOCATION ${JSONCPP_LIBRARY}) -set_property(TARGET jsoncpp PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${JSONCPP_INCLUDE_DIR}) -set_property(TARGET jsoncpp PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${JSONCPP_INCLUDE_DIR}) -add_dependencies(jsoncpp jsoncpp-project) diff --git a/cmake/nlohmann-json.cmake b/cmake/nlohmann-json.cmake new file mode 100644 index 000000000000..02891e6a7ba6 --- /dev/null +++ b/cmake/nlohmann-json.cmake @@ -0,0 +1,21 @@ +include(ExternalProject) + +ExternalProject_Add(nlohmann-json-project + DOWNLOAD_DIR "${CMAKE_SOURCE_DIR}/deps/nlohmann/nlohmann" + DOWNLOAD_NAME json.hpp + DOWNLOAD_NO_EXTRACT 1 + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp + URL_HASH SHA256=9bea4c8066ef4a1c206b2be5a36302f8926f7fdc6087af5d20b417d0cf103ea6 + CMAKE_COMMAND true + BUILD_COMMAND true + INSTALL_COMMAND true +) + +# Create nlohmann-json imported library +add_library(nlohmann-json INTERFACE IMPORTED) +file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/nlohmann) # Must exist. +set_target_properties(nlohmann-json PROPERTIES + INTERFACE_COMPILE_OPTIONS "\$<\$:/permissive->" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/nlohmann + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/nlohmann) +add_dependencies(nlohmann-json nlohmann-json-project) \ No newline at end of file diff --git a/libevmasm/AbstractAssemblyStack.h b/libevmasm/AbstractAssemblyStack.h index 6be78cbc7cac..278edf5c273b 100644 --- a/libevmasm/AbstractAssemblyStack.h +++ b/libevmasm/AbstractAssemblyStack.h @@ -40,7 +40,7 @@ class AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const = 0; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const = 0; - virtual Json::Value assemblyJSON(std::string const& _contractName) const = 0; + virtual Json assemblyJSON(std::string const& _contractName) const = 0; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0; virtual std::string const filesystemFriendlyName(std::string const& _contractName) const = 0; diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 067e230343d0..356a2818a4cd 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -80,10 +80,10 @@ unsigned Assembly::codeSize(unsigned subTagSize) const } } -void Assembly::importAssemblyItemsFromJSON(Json::Value const& _code, std::vector const& _sourceList) +void Assembly::importAssemblyItemsFromJSON(Json const& _code, std::vector const& _sourceList) { solAssert(m_items.empty()); - solRequire(_code.isArray(), AssemblyImportException, "Supplied JSON is not an array."); + solRequire(_code.is_array(), AssemblyImportException, "Supplied JSON is not an array."); for (auto jsonItemIter = std::begin(_code); jsonItemIter != std::end(_code); ++jsonItemIter) { AssemblyItem const& newItem = m_items.emplace_back(createAssemblyItemFromJSON(*jsonItemIter, _sourceList)); @@ -98,11 +98,11 @@ void Assembly::importAssemblyItemsFromJSON(Json::Value const& _code, std::vector } } -AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std::vector const& _sourceList) +AssemblyItem Assembly::createAssemblyItemFromJSON(Json const& _json, std::vector const& _sourceList) { - solRequire(_json.isObject(), AssemblyImportException, "Supplied JSON is not an object."); + solRequire(_json.is_object(), AssemblyImportException, "Supplied JSON is not an object."); static std::set const validMembers{"name", "begin", "end", "source", "value", "modifierDepth", "jumpType"}; - for (std::string const& member: _json.getMemberNames()) + for (auto const& [member, _]: _json.items()) solRequire( validMembers.count(member), AssemblyImportException, @@ -124,14 +124,14 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std: solRequire(!name.empty(), AssemblyImportException, "Member 'name' is empty."); SourceLocation location; - if (_json.isMember("begin")) + if (_json.contains("begin")) location.start = get(_json["begin"]); - if (_json.isMember("end")) + if (_json.contains("end")) location.end = get(_json["end"]); - int srcIndex = getOrDefault(_json["source"], -1); - size_t modifierDepth = static_cast(getOrDefault(_json["modifierDepth"], 0)); - std::string value = getOrDefault(_json["value"], ""); - std::string jumpType = getOrDefault(_json["jumpType"], ""); + int srcIndex = getOrDefault(_json, "source", -1); + size_t modifierDepth = static_cast(getOrDefault(_json, "modifierDepth", 0)); + std::string value = getOrDefault(_json, "value", ""); + std::string jumpType = getOrDefault(_json, "jumpType", ""); auto updateUsedTags = [&](u256 const& data) { @@ -429,11 +429,11 @@ std::string Assembly::assemblyString( return tmp.str(); } -Json::Value Assembly::assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList) const +Json Assembly::assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList) const { - Json::Value root; - root[".code"] = Json::arrayValue; - Json::Value& code = root[".code"]; + Json root; + root[".code"] = Json::array(); + Json& code = root[".code"]; for (AssemblyItem const& item: m_items) { int sourceIndex = -1; @@ -445,7 +445,7 @@ Json::Value Assembly::assemblyJSON(std::map const& _sourc } auto [name, data] = item.nameAndData(m_evmVersion); - Json::Value jsonItem; + Json jsonItem; jsonItem["name"] = name; jsonItem["begin"] = item.location().start; jsonItem["end"] = item.location().end; @@ -461,32 +461,32 @@ Json::Value Assembly::assemblyJSON(std::map const& _sourc if (!data.empty()) jsonItem["value"] = data; jsonItem["source"] = sourceIndex; - code.append(std::move(jsonItem)); + code.emplace_back(std::move(jsonItem)); if (item.type() == AssemblyItemType::Tag) { - Json::Value jumpdest; + Json jumpdest; jumpdest["name"] = "JUMPDEST"; jumpdest["begin"] = item.location().start; jumpdest["end"] = item.location().end; jumpdest["source"] = sourceIndex; if (item.m_modifierDepth != 0) jumpdest["modifierDepth"] = static_cast(item.m_modifierDepth); - code.append(std::move(jumpdest)); + code.emplace_back(std::move(jumpdest)); } } if (_includeSourceList) { - root["sourceList"] = Json::arrayValue; - Json::Value& jsonSourceList = root["sourceList"]; + root["sourceList"] = Json::array(); + Json& jsonSourceList = root["sourceList"]; for (auto const& [name, index]: _sourceIndices) jsonSourceList[index] = name; } if (!m_data.empty() || !m_subs.empty()) { - root[".data"] = Json::objectValue; - Json::Value& data = root[".data"]; + root[".data"] = Json::object(); + Json& data = root[".data"]; for (auto const& i: m_data) if (u256(i.first) >= m_subs.size()) data[util::toHex(toBigEndian((u256)i.first), util::HexPrefix::DontAdd, util::HexCase::Upper)] = util::toHex(i.second); @@ -506,110 +506,107 @@ Json::Value Assembly::assemblyJSON(std::map const& _sourc } std::pair, std::vector> Assembly::fromJSON( - Json::Value const& _json, + Json const& _json, std::vector const& _sourceList, size_t _level ) { - solRequire(_json.isObject(), AssemblyImportException, "Supplied JSON is not an object."); + solRequire(_json.is_object(), AssemblyImportException, "Supplied JSON is not an object."); static std::set const validMembers{".code", ".data", ".auxdata", "sourceList"}; - for (std::string const& attribute: _json.getMemberNames()) + for (auto const& [attribute, _]: _json.items()) solRequire(validMembers.count(attribute), AssemblyImportException, "Unknown attribute '" + attribute + "'."); if (_level == 0) { - if (_json.isMember("sourceList")) + if (_json.contains("sourceList")) { - solRequire(_json["sourceList"].isArray(), AssemblyImportException, "Optional member 'sourceList' is not an array."); - for (Json::Value const& sourceName: _json["sourceList"]) - solRequire(sourceName.isString(), AssemblyImportException, "The 'sourceList' array contains an item that is not a string."); + solRequire(_json["sourceList"].is_array(), AssemblyImportException, "Optional member 'sourceList' is not an array."); + for (Json const& sourceName: _json["sourceList"]) + solRequire(sourceName.is_string(), AssemblyImportException, "The 'sourceList' array contains an item that is not a string."); } } else solRequire( - !_json.isMember("sourceList"), + !_json.contains("sourceList"), AssemblyImportException, "Member 'sourceList' may only be present in the root JSON object." ); auto result = std::make_shared(EVMVersion{}, _level == 0 /* _creation */, "" /* _name */); std::vector parsedSourceList; - if (_json.isMember("sourceList")) + if (_json.contains("sourceList")) { solAssert(_level == 0); solAssert(_sourceList.empty()); - for (Json::Value const& sourceName: _json["sourceList"]) + for (Json const& sourceName: _json["sourceList"]) { solRequire( - std::find(parsedSourceList.begin(), parsedSourceList.end(), sourceName.asString()) == parsedSourceList.end(), + std::find(parsedSourceList.begin(), parsedSourceList.end(), sourceName.get()) == parsedSourceList.end(), AssemblyImportException, "Items in 'sourceList' array are not unique." ); - parsedSourceList.emplace_back(sourceName.asString()); + parsedSourceList.emplace_back(sourceName.get()); } } - solRequire(_json.isMember(".code"), AssemblyImportException, "Member '.code' is missing."); - solRequire(_json[".code"].isArray(), AssemblyImportException, "Member '.code' is not an array."); - for (Json::Value const& codeItem: _json[".code"]) - solRequire(codeItem.isObject(), AssemblyImportException, "The '.code' array contains an item that is not an object."); + solRequire(_json.contains(".code"), AssemblyImportException, "Member '.code' is missing."); + solRequire(_json[".code"].is_array(), AssemblyImportException, "Member '.code' is not an array."); + for (Json const& codeItem: _json[".code"]) + solRequire(codeItem.is_object(), AssemblyImportException, "The '.code' array contains an item that is not an object."); result->importAssemblyItemsFromJSON(_json[".code"], _level == 0 ? parsedSourceList : _sourceList); - if (_json.isMember(".auxdata")) + if (_json.contains(".auxdata")) { - solRequire(_json[".auxdata"].isString(), AssemblyImportException, "Optional member '.auxdata' is not a string."); - result->m_auxiliaryData = fromHex(_json[".auxdata"].asString()); + solRequire(_json[".auxdata"].is_string(), AssemblyImportException, "Optional member '.auxdata' is not a string."); + result->m_auxiliaryData = fromHex(_json[".auxdata"].get()); solRequire(!result->m_auxiliaryData.empty(), AssemblyImportException, "Optional member '.auxdata' is not a valid hexadecimal string."); } - if (_json.isMember(".data")) + if (_json.contains(".data")) { - solRequire(_json[".data"].isObject(), AssemblyImportException, "Optional member '.data' is not an object."); - Json::Value const& data = _json[".data"]; + solRequire(_json[".data"].is_object(), AssemblyImportException, "Optional member '.data' is not an object."); + Json const& data = _json[".data"]; std::map> subAssemblies; - for (Json::ValueConstIterator dataIter = data.begin(); dataIter != data.end(); dataIter++) + for (auto const& [key, value] : data.items()) { - solAssert(dataIter.key().isString()); - std::string dataItemID = dataIter.key().asString(); - Json::Value const& dataItem = data[dataItemID]; - if (dataItem.isString()) + if (value.is_string()) { solRequire( - dataItem.asString().empty() || !fromHex(dataItem.asString()).empty(), + value.get().empty() || !fromHex(value.get()).empty(), AssemblyImportException, - "The value for key '" + dataItemID + "' inside '.data' is not a valid hexadecimal string." + "The value for key '" + key + "' inside '.data' is not a valid hexadecimal string." ); - result->m_data[h256(fromHex(dataItemID))] = fromHex(dataItem.asString()); + result->m_data[h256(fromHex(key))] = fromHex(value.get()); } - else if (dataItem.isObject()) + else if (value.is_object()) { size_t index{}; try { // Using signed variant because stoul() still accepts negative numbers and // just lets them wrap around. - int parsedDataItemID = std::stoi(dataItemID, nullptr, 16); - solRequire(parsedDataItemID >= 0, AssemblyImportException, "The key '" + dataItemID + "' inside '.data' is out of the supported integer range."); + int parsedDataItemID = std::stoi(key, nullptr, 16); + solRequire(parsedDataItemID >= 0, AssemblyImportException, "The key '" + key + "' inside '.data' is out of the supported integer range."); index = static_cast(parsedDataItemID); } catch (std::invalid_argument const&) { - solThrow(AssemblyImportException, "The key '" + dataItemID + "' inside '.data' is not an integer."); + solThrow(AssemblyImportException, "The key '" + key + "' inside '.data' is not an integer."); } catch (std::out_of_range const&) { - solThrow(AssemblyImportException, "The key '" + dataItemID + "' inside '.data' is out of the supported integer range."); + solThrow(AssemblyImportException, "The key '" + key + "' inside '.data' is out of the supported integer range."); } - auto [subAssembly, emptySourceList] = Assembly::fromJSON(dataItem, _level == 0 ? parsedSourceList : _sourceList, _level + 1); + auto [subAssembly, emptySourceList] = Assembly::fromJSON(value, _level == 0 ? parsedSourceList : _sourceList, _level + 1); solAssert(subAssembly); solAssert(emptySourceList.empty()); solAssert(subAssemblies.count(index) == 0); subAssemblies[index] = subAssembly; } else - solThrow(AssemblyImportException, "The value of key '" + dataItemID + "' inside '.data' is neither a hex string nor an object."); + solThrow(AssemblyImportException, "The value of key '" + key + "' inside '.data' is neither a hex string nor an object."); } if (!subAssemblies.empty()) diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 6e900282569b..123d7f3ddd8c 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -30,11 +30,10 @@ #include #include #include +#include #include -#include - #include #include #include @@ -150,7 +149,7 @@ class Assembly ) const; /// Create a JSON representation of the assembly. - Json::Value assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList = true) const; + Json assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList = true) const; /// Constructs an @a Assembly from the serialized JSON representation. /// @param _json JSON object containing assembly in the format produced by assemblyJSON(). @@ -163,7 +162,7 @@ class Assembly /// @returns Created @a Assembly and the source list read from the 'sourceList' field of the root /// assembly or an empty list (in recursive calls). static std::pair, std::vector> fromJSON( - Json::Value const& _json, + Json const& _json, std::vector const& _sourceList = {}, size_t _level = 0 ); @@ -188,13 +187,13 @@ class Assembly /// the code array. This method only works on clean Assembly objects that don't have any items defined yet. /// @param _json JSON array that contains assembly items (e.g. json['.code']) /// @param _sourceList List of source names. - void importAssemblyItemsFromJSON(Json::Value const& _code, std::vector const& _sourceList); + void importAssemblyItemsFromJSON(Json const& _code, std::vector const& _sourceList); /// Creates an AssemblyItem from a given JSON representation. /// @param _json JSON object that consists a single assembly item /// @param _sourceList List of source names. /// @returns AssemblyItem of _json argument. - AssemblyItem createAssemblyItemFromJSON(Json::Value const& _json, std::vector const& _sourceList); + AssemblyItem createAssemblyItemFromJSON(Json const& _json, std::vector const& _sourceList); private: bool m_invalid = false; diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index a06044256faf..20605ee354a0 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -36,12 +36,12 @@ namespace solidity::evmasm void EVMAssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string const& _source) { - Json::Value assemblyJson; + Json assemblyJson; solRequire(jsonParseStrict(_source, assemblyJson), AssemblyImportException, "Could not parse JSON file."); analyze(_sourceName, assemblyJson); } -void EVMAssemblyStack::analyze(std::string const& _sourceName, Json::Value const& _assemblyJson) +void EVMAssemblyStack::analyze(std::string const& _sourceName, Json const& _assemblyJson) { solAssert(!m_evmAssembly); m_name = _sourceName; @@ -99,7 +99,7 @@ std::string const* EVMAssemblyStack::runtimeSourceMapping(std::string const& _co return &m_runtimeSourceMapping; } -Json::Value EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const +Json EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const { solAssert(_contractName == m_name); solAssert(m_evmAssembly); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index 7fe77e7d208b..f2516c0b8a0a 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -43,7 +43,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack /// Runs analysis steps. /// Multiple calls overwrite the previous state. /// @throws AssemblyImportException, if JSON could not be validated. - void analyze(std::string const& _sourceName, Json::Value const& _assemblyJson); + void analyze(std::string const& _sourceName, Json const& _assemblyJson); void assemble(); @@ -58,7 +58,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const override; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override; - virtual Json::Value assemblyJSON(std::string const& _contractName) const override; + virtual Json assemblyJSON(std::string const& _contractName) const override; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 27926721aa6f..d8b178377bd8 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -34,8 +34,7 @@ #include #include #include - -#include +#include #include #include diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index c54a2d013ad0..f94b91674bcb 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -46,12 +46,13 @@ using namespace std::string_literals; using namespace solidity::langutil; +using namespace solidity; namespace { template typename C> -void addIfSet(std::vector>& _attributes, std::string const& _name, C const& _value) +void addIfSet(std::vector>& _attributes, std::string const& _name, C const& _value) { if constexpr (std::is_same_v, solidity::util::SetOnce>) { @@ -82,23 +83,23 @@ ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, std::map>&& _attributes + std::initializer_list>&& _attributes ) { ASTJsonExporter::setJsonNode( _node, _nodeName, - std::vector>(std::move(_attributes)) + std::vector>(std::move(_attributes)) ); } void ASTJsonExporter::setJsonNode( ASTNode const& _node, std::string const& _nodeType, - std::vector>&& _attributes + std::vector>&& _attributes ) { - m_currentValue = Json::objectValue; + m_currentValue = Json::object(); m_currentValue["id"] = nodeId(_node); m_currentValue["src"] = sourceLocationToString(_node.location()); if (auto const* documented = dynamic_cast(&_node)) @@ -126,12 +127,12 @@ std::string ASTJsonExporter::sourceLocationToString(SourceLocation const& _locat return std::to_string(_location.start) + ":" + std::to_string(length) + ":" + (sourceIndexOpt.has_value() ? std::to_string(sourceIndexOpt.value()) : "-1"); } -Json::Value ASTJsonExporter::sourceLocationsToJson(std::vector const& _sourceLocations) const +Json ASTJsonExporter::sourceLocationsToJson(std::vector const& _sourceLocations) const { - Json::Value locations = Json::arrayValue; + Json locations = Json::array(); for (SourceLocation const& location: _sourceLocations) - locations.append(sourceLocationToString(location)); + locations.emplace_back(sourceLocationToString(location)); return locations; } @@ -141,33 +142,33 @@ std::string ASTJsonExporter::namePathToString(std::vector const& _nam return boost::algorithm::join(_namePath, "."s); } -Json::Value ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation) +Json ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation) { - Json::Value typeDescriptions(Json::objectValue); - typeDescriptions["typeString"] = _tp ? Json::Value(_tp->toString(_withoutDataLocation)) : Json::nullValue; - typeDescriptions["typeIdentifier"] = _tp ? Json::Value(_tp->identifier()) : Json::nullValue; + Json typeDescriptions; + typeDescriptions["typeString"] = _tp ? Json(_tp->toString(_withoutDataLocation)) : Json(); + typeDescriptions["typeIdentifier"] = _tp ? Json(_tp->identifier()) : Json(); return typeDescriptions; } -Json::Value ASTJsonExporter::typePointerToJson(std::optional const& _tps) +Json ASTJsonExporter::typePointerToJson(std::optional const& _tps) { if (_tps) { - Json::Value arguments(Json::arrayValue); + Json arguments = Json::array(); for (auto const& tp: _tps->types) appendMove(arguments, typePointerToJson(tp)); return arguments; } else - return Json::nullValue; + return Json(); } void ASTJsonExporter::appendExpressionAttributes( - std::vector>& _attributes, + std::vector>& _attributes, ExpressionAnnotation const& _annotation ) { - std::vector> exprAttributes = { + std::vector> exprAttributes = { std::make_pair("typeDescriptions", typePointerToJson(_annotation.type)), std::make_pair("argumentTypes", typePointerToJson(_annotation.arguments)) }; @@ -182,18 +183,18 @@ void ASTJsonExporter::appendExpressionAttributes( _attributes += exprAttributes; } -Json::Value ASTJsonExporter::inlineAssemblyIdentifierToJson(std::pair _info) const +Json ASTJsonExporter::inlineAssemblyIdentifierToJson(std::pair _info) const { - Json::Value tuple(Json::objectValue); + Json tuple; tuple["src"] = sourceLocationToString(nativeLocationOf(*_info.first)); tuple["declaration"] = idOrNull(_info.second.declaration); - tuple["isSlot"] = Json::Value(_info.second.suffix == "slot"); - tuple["isOffset"] = Json::Value(_info.second.suffix == "offset"); + tuple["isSlot"] = Json(_info.second.suffix == "slot"); + tuple["isOffset"] = Json(_info.second.suffix == "offset"); if (!_info.second.suffix.empty()) - tuple["suffix"] = Json::Value(_info.second.suffix); + tuple["suffix"] = Json(_info.second.suffix); - tuple["valueSize"] = Json::Value(Json::LargestUInt(_info.second.valueSize)); + tuple["valueSize"] = Json(static_cast(_info.second.valueSize)); return tuple; } @@ -203,7 +204,7 @@ void ASTJsonExporter::print(std::ostream& _stream, ASTNode const& _node, util::J _stream << util::jsonPrint(toJson(_node), _format); } -Json::Value ASTJsonExporter::toJson(ASTNode const& _node) +Json ASTJsonExporter::toJson(ASTNode const& _node) { _node.accept(*this); return util::removeNullMembers(std::move(m_currentValue)); @@ -211,22 +212,22 @@ Json::Value ASTJsonExporter::toJson(ASTNode const& _node) bool ASTJsonExporter::visit(SourceUnit const& _node) { - std::vector> attributes = { - std::make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue), + std::vector> attributes = { + std::make_pair("license", _node.licenseString() ? Json(*_node.licenseString()) : Json()), std::make_pair("nodes", toJson(_node.nodes())), }; if (_node.experimentalSolidity()) - attributes.emplace_back("experimentalSolidity", Json::Value(_node.experimentalSolidity())); + attributes.emplace_back("experimentalSolidity", Json(_node.experimentalSolidity())); if (_node.annotation().exportedSymbols.set()) { - Json::Value exportedSymbols = Json::objectValue; + Json exportedSymbols = Json::object(); for (auto const& sym: *_node.annotation().exportedSymbols) { - exportedSymbols[sym.first] = Json::arrayValue; + exportedSymbols[sym.first] = Json::array(); for (Declaration const* overload: sym.second) - exportedSymbols[sym.first].append(nodeId(*overload)); + exportedSymbols[sym.first].emplace_back(nodeId(*overload)); } attributes.emplace_back("exportedSymbols", exportedSymbols); @@ -241,9 +242,9 @@ bool ASTJsonExporter::visit(SourceUnit const& _node) bool ASTJsonExporter::visit(PragmaDirective const& _node) { - Json::Value literals(Json::arrayValue); + Json literals = Json::array(); for (auto const& literal: _node.literals()) - literals.append(literal); + literals.emplace_back(literal); setJsonNode(_node, "PragmaDirective", { std::make_pair("literals", std::move(literals)) }); @@ -252,7 +253,7 @@ bool ASTJsonExporter::visit(PragmaDirective const& _node) bool ASTJsonExporter::visit(ImportDirective const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("file", _node.path()), std::make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)), std::make_pair("scope", idOrNull(_node.scope())) @@ -261,17 +262,17 @@ bool ASTJsonExporter::visit(ImportDirective const& _node) addIfSet(attributes, "absolutePath", _node.annotation().absolutePath); attributes.emplace_back("unitAlias", _node.name()); - attributes.emplace_back("nameLocation", Json::Value(sourceLocationToString(_node.nameLocation()))); + attributes.emplace_back("nameLocation", Json(sourceLocationToString(_node.nameLocation()))); - Json::Value symbolAliases(Json::arrayValue); + Json symbolAliases = Json::array(); for (auto const& symbolAlias: _node.symbolAliases()) { - Json::Value tuple(Json::objectValue); + Json tuple; solAssert(symbolAlias.symbol, ""); tuple["foreign"] = toJson(*symbolAlias.symbol); - tuple["local"] = symbolAlias.alias ? Json::Value(*symbolAlias.alias) : Json::nullValue; + tuple["local"] = symbolAlias.alias ? Json(*symbolAlias.alias) : Json(); tuple["nameLocation"] = sourceLocationToString(_node.nameLocation()); - symbolAliases.append(tuple); + symbolAliases.emplace_back(tuple); } attributes.emplace_back("symbolAliases", std::move(symbolAliases)); setJsonNode(_node, "ImportDirective", std::move(attributes)); @@ -280,10 +281,10 @@ bool ASTJsonExporter::visit(ImportDirective const& _node) bool ASTJsonExporter::visit(ContractDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("contractKind", contractKind(_node.contractKind())), std::make_pair("abstract", _node.abstract()), std::make_pair("baseContracts", toJson(_node.baseContracts())), @@ -303,7 +304,7 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node) if (!_node.annotation().internalFunctionIDs.empty()) { - Json::Value internalFunctionIDs(Json::objectValue); + Json internalFunctionIDs; for (auto const& [functionDefinition, internalFunctionID]: _node.annotation().internalFunctionIDs) internalFunctionIDs[std::to_string(functionDefinition->id())] = internalFunctionID; attributes.emplace_back("internalFunctionIDs", std::move(internalFunctionIDs)); @@ -315,10 +316,10 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node) bool ASTJsonExporter::visit(IdentifierPath const& _node) { - Json::Value nameLocations = Json::arrayValue; + Json nameLocations = Json::array(); for (SourceLocation location: _node.pathLocations()) - nameLocations.append(sourceLocationToString(location)); + nameLocations.emplace_back(sourceLocationToString(location)); setJsonNode(_node, "IdentifierPath", { std::make_pair("name", namePathToString(_node.path())), @@ -332,23 +333,23 @@ bool ASTJsonExporter::visit(InheritanceSpecifier const& _node) { setJsonNode(_node, "InheritanceSpecifier", { std::make_pair("baseName", toJson(_node.name())), - std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue) + std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json()) }); return false; } bool ASTJsonExporter::visit(UsingForDirective const& _node) { - std::vector> attributes = { - std::make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue) + std::vector> attributes = { + std::make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json()) }; if (_node.usesBraces()) { - Json::Value functionList; + Json functionList = Json::array(); for (auto&& [function, op]: _node.functionsAndOperators()) { - Json::Value functionNode; + Json functionNode; if (!op.has_value()) functionNode["function"] = toJson(*function); else @@ -356,7 +357,7 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node) functionNode["definition"] = toJson(*function); functionNode["operator"] = std::string(TokenTraits::toString(*op)); } - functionList.append(std::move(functionNode)); + functionList.emplace_back(std::move(functionNode)); } attributes.emplace_back("functionList", std::move(functionList)); } @@ -376,10 +377,10 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node) bool ASTJsonExporter::visit(StructDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())), std::make_pair("members", toJson(_node.members())), std::make_pair("scope", idOrNull(_node.scope())) @@ -394,10 +395,10 @@ bool ASTJsonExporter::visit(StructDefinition const& _node) bool ASTJsonExporter::visit(EnumDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("members", toJson(_node.members())) }; @@ -420,7 +421,7 @@ bool ASTJsonExporter::visit(EnumValue const& _node) bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node) { solAssert(_node.underlyingType(), ""); - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), std::make_pair("underlyingType", toJson(*_node.underlyingType())) @@ -450,18 +451,18 @@ bool ASTJsonExporter::visit(OverrideSpecifier const& _node) bool ASTJsonExporter::visit(FunctionDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())), std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())), std::make_pair("virtual", _node.markedVirtual()), - std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), + std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()), std::make_pair("parameters", toJson(_node.parameterList())), std::make_pair("returnParameters", toJson(*_node.returnParameterList())), std::make_pair("modifiers", toJson(_node.modifiers())), - std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue), + std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json()), std::make_pair("implemented", _node.isImplemented()), std::make_pair("scope", idOrNull(_node.scope())) }; @@ -489,7 +490,7 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node) bool ASTJsonExporter::visit(VariableDeclaration const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), std::make_pair("typeName", toJson(_node.typeName())), @@ -497,9 +498,9 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node) std::make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())), std::make_pair("stateVariable", _node.isStateVariable()), std::make_pair("storageLocation", location(_node.referenceLocation())), - std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), + std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()), std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())), - std::make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue), + std::make_pair("value", _node.value() ? toJson(*_node.value()) : Json()), std::make_pair("scope", idOrNull(_node.scope())), std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }; @@ -517,15 +518,15 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node) bool ASTJsonExporter::visit(ModifierDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())), std::make_pair("parameters", toJson(_node.parameterList())), std::make_pair("virtual", _node.markedVirtual()), - std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), - std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue) + std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()), + std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json()) }; if (!_node.annotation().baseFunctions.empty()) attributes.emplace_back(std::make_pair("baseModifiers", getContainerIds(_node.annotation().baseFunctions, true))); @@ -535,9 +536,9 @@ bool ASTJsonExporter::visit(ModifierDefinition const& _node) bool ASTJsonExporter::visit(ModifierInvocation const& _node) { - std::vector> attributes{ + std::vector> attributes{ std::make_pair("modifierName", toJson(_node.name())), - std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue) + std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json()) }; if (Declaration const* declaration = _node.name().annotation().referencedDeclaration) { @@ -553,10 +554,10 @@ bool ASTJsonExporter::visit(ModifierInvocation const& _node) bool ASTJsonExporter::visit(EventDefinition const& _node) { m_inEvent = true; - std::vector> _attributes = { + std::vector> _attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("parameters", toJson(_node.parameterList())), std::make_pair("anonymous", _node.isAnonymous()) }; @@ -573,10 +574,10 @@ bool ASTJsonExporter::visit(EventDefinition const& _node) bool ASTJsonExporter::visit(ErrorDefinition const& _node) { - std::vector> _attributes = { + std::vector> _attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("parameters", toJson(_node.parameterList())) }; if (m_stackState >= CompilerStack::State::AnalysisSuccessful) @@ -588,7 +589,7 @@ bool ASTJsonExporter::visit(ErrorDefinition const& _node) bool ASTJsonExporter::visit(ElementaryTypeName const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.typeName().toString()), std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }; @@ -648,7 +649,7 @@ bool ASTJsonExporter::visit(ArrayTypeName const& _node) bool ASTJsonExporter::visit(InlineAssembly const& _node) { - std::vector> externalReferences; + std::vector> externalReferences; for (auto const& it: _node.annotation().externalReferences) if (it.first) @@ -657,26 +658,26 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) inlineAssemblyIdentifierToJson(it) )); - Json::Value externalReferencesJson = Json::arrayValue; + Json externalReferencesJson = Json::array(); std::sort(externalReferences.begin(), externalReferences.end()); - for (Json::Value& it: externalReferences | ranges::views::values) - externalReferencesJson.append(std::move(it)); + for (Json& it: externalReferences | ranges::views::values) + externalReferencesJson.emplace_back(std::move(it)); - std::vector> attributes = { - std::make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), + std::vector> attributes = { + std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), std::make_pair("evmVersion", dynamic_cast(_node.dialect()).evmVersion().name()) }; if (_node.flags()) { - Json::Value flags(Json::arrayValue); + Json flags = Json::array(); for (auto const& flag: *_node.flags()) if (flag) - flags.append(*flag); + flags.emplace_back(*flag); else - flags.append(Json::nullValue); + flags.emplace_back(Json()); attributes.emplace_back(std::make_pair("flags", std::move(flags))); } setJsonNode(_node, "InlineAssembly", std::move(attributes)); @@ -743,7 +744,7 @@ bool ASTJsonExporter::visit(WhileStatement const& _node) bool ASTJsonExporter::visit(ForStatement const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())), std::make_pair("condition", toJsonOrNull(_node.condition())), std::make_pair("loopExpression", toJsonOrNull(_node.loopExpression())), @@ -802,7 +803,7 @@ bool ASTJsonExporter::visit(RevertStatement const& _node) bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node) { - Json::Value varDecs(Json::arrayValue); + Json varDecs = Json::array(); for (auto const& v: _node.declarations()) appendMove(varDecs, idOrNull(v.get())); setJsonNode(_node, "VariableDeclarationStatement", { @@ -823,7 +824,7 @@ bool ASTJsonExporter::visit(ExpressionStatement const& _node) bool ASTJsonExporter::visit(Conditional const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("condition", toJson(_node.condition())), std::make_pair("trueExpression", toJson(_node.trueExpression())), std::make_pair("falseExpression", toJson(_node.falseExpression())) @@ -835,7 +836,7 @@ bool ASTJsonExporter::visit(Conditional const& _node) bool ASTJsonExporter::visit(Assignment const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("operator", TokenTraits::toString(_node.assignmentOperator())), std::make_pair("leftHandSide", toJson(_node.leftHandSide())), std::make_pair("rightHandSide", toJson(_node.rightHandSide())) @@ -847,8 +848,8 @@ bool ASTJsonExporter::visit(Assignment const& _node) bool ASTJsonExporter::visit(TupleExpression const& _node) { - std::vector> attributes = { - std::make_pair("isInlineArray", Json::Value(_node.isInlineArray())), + std::vector> attributes = { + std::make_pair("isInlineArray", Json(_node.isInlineArray())), std::make_pair("components", toJson(_node.components())), }; appendExpressionAttributes(attributes, _node.annotation()); @@ -858,7 +859,7 @@ bool ASTJsonExporter::visit(TupleExpression const& _node) bool ASTJsonExporter::visit(UnaryOperation const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("prefix", _node.isPrefixOperation()), std::make_pair("operator", TokenTraits::toString(_node.getOperator())), std::make_pair("subExpression", toJson(_node.subExpression())) @@ -873,7 +874,7 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node) bool ASTJsonExporter::visit(BinaryOperation const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("operator", TokenTraits::toString(_node.getOperator())), std::make_pair("leftExpression", toJson(_node.leftExpression())), std::make_pair("rightExpression", toJson(_node.rightExpression())), @@ -889,10 +890,10 @@ bool ASTJsonExporter::visit(BinaryOperation const& _node) bool ASTJsonExporter::visit(FunctionCall const& _node) { - Json::Value names(Json::arrayValue); + Json names = Json::array(); for (auto const& name: _node.names()) - names.append(Json::Value(*name)); - std::vector> attributes = { + names.push_back(Json(*name)); + std::vector> attributes = { std::make_pair("expression", toJson(_node.expression())), std::make_pair("names", std::move(names)), std::make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())), @@ -913,11 +914,11 @@ bool ASTJsonExporter::visit(FunctionCall const& _node) bool ASTJsonExporter::visit(FunctionCallOptions const& _node) { - Json::Value names(Json::arrayValue); + Json names = Json::array(); for (auto const& name: _node.names()) - names.append(Json::Value(*name)); + names.emplace_back(Json(*name)); - std::vector> attributes = { + std::vector> attributes = { std::make_pair("expression", toJson(_node.expression())), std::make_pair("names", std::move(names)), std::make_pair("options", toJson(_node.options())), @@ -930,7 +931,7 @@ bool ASTJsonExporter::visit(FunctionCallOptions const& _node) bool ASTJsonExporter::visit(NewExpression const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("typeName", toJson(_node.typeName())) }; appendExpressionAttributes(attributes, _node.annotation()); @@ -940,9 +941,9 @@ bool ASTJsonExporter::visit(NewExpression const& _node) bool ASTJsonExporter::visit(MemberAccess const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("memberName", _node.memberName()), - std::make_pair("memberLocation", Json::Value(sourceLocationToString(_node.memberLocation()))), + std::make_pair("memberLocation", Json(sourceLocationToString(_node.memberLocation()))), std::make_pair("expression", toJson(_node.expression())), std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), }; @@ -953,7 +954,7 @@ bool ASTJsonExporter::visit(MemberAccess const& _node) bool ASTJsonExporter::visit(IndexAccess const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("baseExpression", toJson(_node.baseExpression())), std::make_pair("indexExpression", toJsonOrNull(_node.indexExpression())), }; @@ -964,7 +965,7 @@ bool ASTJsonExporter::visit(IndexAccess const& _node) bool ASTJsonExporter::visit(IndexRangeAccess const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("baseExpression", toJson(_node.baseExpression())), std::make_pair("startExpression", toJsonOrNull(_node.startExpression())), std::make_pair("endExpression", toJsonOrNull(_node.endExpression())), @@ -976,9 +977,9 @@ bool ASTJsonExporter::visit(IndexRangeAccess const& _node) bool ASTJsonExporter::visit(Identifier const& _node) { - Json::Value overloads(Json::arrayValue); + Json overloads = Json::array(); for (auto const& dec: _node.annotation().overloadedDeclarations) - overloads.append(nodeId(*dec)); + overloads.emplace_back(nodeId(*dec)); setJsonNode(_node, "Identifier", { std::make_pair("name", _node.name()), std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), @@ -991,7 +992,7 @@ bool ASTJsonExporter::visit(Identifier const& _node) bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("typeName", toJson(_node.type())) }; appendExpressionAttributes(attributes, _node.annotation()); @@ -1001,19 +1002,19 @@ bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node) bool ASTJsonExporter::visit(Literal const& _node) { - Json::Value value{_node.value()}; + Json value = _node.value(); if (!util::validateUTF8(_node.value())) - value = Json::nullValue; + value = Json(); Token subdenomination = Token(_node.subDenomination()); - std::vector> attributes = { + std::vector> attributes = { std::make_pair("kind", literalTokenKind(_node.token())), std::make_pair("value", value), std::make_pair("hexValue", util::toHex(util::asBytes(_node.value()))), std::make_pair( "subdenomination", subdenomination == Token::Illegal ? - Json::nullValue : - Json::Value{TokenTraits::toString(subdenomination)} + Json() : + Json(TokenTraits::toString(subdenomination)) ) }; appendExpressionAttributes(attributes, _node.annotation()); @@ -1023,16 +1024,14 @@ bool ASTJsonExporter::visit(Literal const& _node) bool ASTJsonExporter::visit(StructuredDocumentation const& _node) { - Json::Value text{*_node.text()}; - std::vector> attributes = { + Json text = *_node.text(); + std::vector> attributes = { std::make_pair("text", text) }; setJsonNode(_node, "StructuredDocumentation", std::move(attributes)); return false; } - - void ASTJsonExporter::endVisit(EventDefinition const&) { m_inEvent = false; diff --git a/libsolidity/ast/ASTJsonExporter.h b/libsolidity/ast/ASTJsonExporter.h index ff3b94fa28de..c7933120a974 100644 --- a/libsolidity/ast/ASTJsonExporter.h +++ b/libsolidity/ast/ASTJsonExporter.h @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -60,16 +59,16 @@ class ASTJsonExporter: public ASTConstVisitor ); /// Output the json representation of the AST to _stream. void print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format); - Json::Value toJson(ASTNode const& _node); + Json toJson(ASTNode const& _node); template - Json::Value toJson(std::vector> const& _nodes) + Json toJson(std::vector> const& _nodes) { - Json::Value ret(Json::arrayValue); + Json ret = Json::array(); for (auto const& n: _nodes) if (n) appendMove(ret, toJson(*n)); else - ret.append(Json::nullValue); + ret.emplace_back(Json()); return ret; } bool visit(SourceUnit const& _node) override; @@ -135,27 +134,27 @@ class ASTJsonExporter: public ASTConstVisitor void setJsonNode( ASTNode const& _node, std::string const& _nodeName, - std::initializer_list>&& _attributes + std::initializer_list>&& _attributes ); void setJsonNode( ASTNode const& _node, std::string const& _nodeName, - std::vector>&& _attributes + std::vector>&& _attributes ); /// Maps source location to an index, if source is valid and a mapping does exist, otherwise returns std::nullopt. std::optional sourceIndexFromLocation(langutil::SourceLocation const& _location) const; std::string sourceLocationToString(langutil::SourceLocation const& _location) const; - Json::Value sourceLocationsToJson(std::vector const& _sourceLocations) const; + Json sourceLocationsToJson(std::vector const& _sourceLocations) const; static std::string namePathToString(std::vector const& _namePath); - static Json::Value idOrNull(ASTNode const* _pt) + static Json idOrNull(ASTNode const* _pt) { - return _pt ? Json::Value(nodeId(*_pt)) : Json::nullValue; + return _pt ? Json(nodeId(*_pt)) : Json(); } - Json::Value toJsonOrNull(ASTNode const* _node) + Json toJsonOrNull(ASTNode const* _node) { - return _node ? toJson(*_node) : Json::nullValue; + return _node ? toJson(*_node) : Json(); } - Json::Value inlineAssemblyIdentifierToJson(std::pair _info) const; + Json inlineAssemblyIdentifierToJson(std::pair _info) const; static std::string location(VariableDeclaration::Location _location); static std::string contractKind(ContractKind _kind); static std::string functionCallKind(FunctionCallKind _kind); @@ -167,7 +166,7 @@ class ASTJsonExporter: public ASTConstVisitor return _node.id(); } template - static Json::Value getContainerIds(Container const& _container, bool _order = false) + static Json getContainerIds(Container const& _container, bool _order = false) { std::vector tmp; @@ -178,28 +177,27 @@ class ASTJsonExporter: public ASTConstVisitor } if (_order) std::sort(tmp.begin(), tmp.end()); - Json::Value json(Json::arrayValue); + Json json = Json::array(); for (int64_t val: tmp) - json.append(val); - + json.emplace_back(val); return json; } - static Json::Value typePointerToJson(Type const* _tp, bool _withoutDataLocation = false); - static Json::Value typePointerToJson(std::optional const& _tps); + static Json typePointerToJson(Type const* _tp, bool _withoutDataLocation = false); + static Json typePointerToJson(std::optional const& _tps); void appendExpressionAttributes( - std::vector> &_attributes, + std::vector> &_attributes, ExpressionAnnotation const& _annotation ); - static void appendMove(Json::Value& _array, Json::Value&& _value) + static void appendMove(Json& _array, Json&& _value) { - solAssert(_array.isArray(), ""); - _array.append(std::move(_value)); + solAssert(_array.is_array(), ""); + _array.emplace_back(std::move(_value)); } CompilerStack::State m_stackState = CompilerStack::State::Empty; ///< Used to only access information that already exists bool m_inEvent = false; ///< whether we are currently inside an event or not - Json::Value m_currentValue; + Json m_currentValue; std::map m_sourceIndices; }; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 6e6dd9eb5eeb..5c1d4bdc0c30 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -43,9 +43,9 @@ namespace solidity::frontend using SourceLocation = langutil::SourceLocation; template -ASTPointer ASTJsonImporter::nullOrCast(Json::Value const& _json) +ASTPointer ASTJsonImporter::nullOrCast(Json const& _json) { - if (_json.isNull()) + if (_json.is_null()) return nullptr; else return std::dynamic_pointer_cast(convertJsonToASTNode(_json)); @@ -54,13 +54,13 @@ ASTPointer ASTJsonImporter::nullOrCast(Json::Value const& _json) // ============ public =========================== -std::map> ASTJsonImporter::jsonToSourceUnit(std::map const& _sourceList) +std::map> ASTJsonImporter::jsonToSourceUnit(std::map const& _sourceList) { for (auto const& src: _sourceList) m_sourceNames.emplace_back(std::make_shared(src.first)); for (auto const& srcPair: _sourceList) { - astAssert(!srcPair.second.isNull()); + astAssert(!srcPair.second.is_null()); astAssert(member(srcPair.second,"nodeType") == "SourceUnit", "The 'nodeType' of the highest node must be 'SourceUnit'."); m_sourceUnits[srcPair.first] = createSourceUnit(srcPair.second, srcPair.first); } @@ -71,11 +71,12 @@ std::map> ASTJsonImporter::jsonToSourceUnit( // =========== general creation functions ============== template -ASTPointer ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&... _args) +ASTPointer ASTJsonImporter::createASTNode(Json const& _node, Args&&... _args) { - astAssert(member(_node, "id").isInt64(), "'id'-field must be 64bit integer."); + static_assert(std::is_same_v); + astAssert(member(_node, "id").is_number_integer(), "'id'-field must be 64bit integer."); - int64_t id = _node["id"].asInt64(); + int64_t id = static_cast(_node["id"]); astAssert(m_usedIDs.insert(id).second, "Found duplicate node ID!"); @@ -87,50 +88,50 @@ ASTPointer ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&... return n; } -SourceLocation const ASTJsonImporter::createSourceLocation(Json::Value const& _node) +SourceLocation const ASTJsonImporter::createSourceLocation(Json const& _node) { - astAssert(member(_node, "src").isString(), "'src' must be a string"); + astAssert(member(_node, "src").is_string(), "'src' must be a string"); - return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["src"].get(), m_sourceNames); } -std::optional> ASTJsonImporter::createSourceLocations(Json::Value const& _node) const +std::optional> ASTJsonImporter::createSourceLocations(Json const& _node) const { std::vector locations; - if (_node.isMember("nameLocations") && _node["nameLocations"].isArray()) + if (_node.contains("nameLocations") && _node["nameLocations"].is_array()) { for (auto const& val: _node["nameLocations"]) - locations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames)); + locations.emplace_back(langutil::parseSourceLocation(val.get(), m_sourceNames)); return locations; } return std::nullopt; } -SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _node) +SourceLocation ASTJsonImporter::createNameSourceLocation(Json const& _node) { - astAssert(member(_node, "nameLocation").isString(), "'nameLocation' must be a string"); + astAssert(member(_node, "nameLocation").is_string(), "'nameLocation' must be a string"); - return solidity::langutil::parseSourceLocation(_node["nameLocation"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["nameLocation"].get(), m_sourceNames); } -SourceLocation ASTJsonImporter::createKeyNameSourceLocation(Json::Value const& _node) +SourceLocation ASTJsonImporter::createKeyNameSourceLocation(Json const& _node) { - astAssert(member(_node, "keyNameLocation").isString(), "'keyNameLocation' must be a string"); + astAssert(member(_node, "keyNameLocation").is_string(), "'keyNameLocation' must be a string"); - return solidity::langutil::parseSourceLocation(_node["keyNameLocation"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["keyNameLocation"].get(), m_sourceNames); } -SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json::Value const& _node) +SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json const& _node) { - astAssert(member(_node, "valueNameLocation").isString(), "'valueNameLocation' must be a string"); + astAssert(member(_node, "valueNameLocation").is_string(), "'valueNameLocation' must be a string"); - return solidity::langutil::parseSourceLocation(_node["valueNameLocation"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["valueNameLocation"].get(), m_sourceNames); } template -ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node) +ASTPointer ASTJsonImporter::convertJsonToASTNode(Json const& _node) { ASTPointer ret = std::dynamic_pointer_cast(convertJsonToASTNode(_node)); astAssert(ret, "cast of converted json-node must not be nullptr"); @@ -138,10 +139,10 @@ ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node) } -ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _json) +ASTPointer ASTJsonImporter::convertJsonToASTNode(Json const& _json) { - astAssert(_json["nodeType"].isString() && _json.isMember("id"), "JSON-Node needs to have 'nodeType' and 'id' fields."); - std::string nodeType = _json["nodeType"].asString(); + astAssert(_json["nodeType"].is_string() && _json.contains("id"), "JSON-Node needs to have 'nodeType' and 'id' fields."); + std::string nodeType = _json["nodeType"].get(); if (nodeType == "PragmaDirective") return createPragmaDirective(_json); if (nodeType == "ImportDirective") @@ -263,15 +264,15 @@ ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js // ============ functions to instantiate the AST-Nodes from Json-Nodes ============== -ASTPointer ASTJsonImporter::createSourceUnit(Json::Value const& _node, std::string const& _srcName) +ASTPointer ASTJsonImporter::createSourceUnit(Json const& _node, std::string const& _srcName) { std::optional license; - if (_node.isMember("license") && !_node["license"].isNull()) - license = _node["license"].asString(); + if (_node.contains("license") && !_node["license"].is_null()) + license = _node["license"].get(); bool experimentalSolidity = false; - if (_node.isMember("experimentalSolidity") && !_node["experimentalSolidity"].isNull()) - experimentalSolidity = _node["experimentalSolidity"].asBool(); + if (_node.contains("experimentalSolidity") && !_node["experimentalSolidity"].is_null()) + experimentalSolidity = _node["experimentalSolidity"].get(); std::vector> nodes; for (auto& child: member(_node, "nodes")) @@ -282,20 +283,20 @@ ASTPointer ASTJsonImporter::createSourceUnit(Json::Value const& _nod return tmp; } -ASTPointer ASTJsonImporter::createPragmaDirective(Json::Value const& _node) +ASTPointer ASTJsonImporter::createPragmaDirective(Json const& _node) { std::vector tokens; std::vector literals; for (auto const& lit: member(_node, "literals")) { - std::string l = lit.asString(); + std::string l = lit.get(); literals.push_back(l); tokens.push_back(scanSingleToken(l)); } return createASTNode(_node, tokens, literals); } -ASTPointer ASTJsonImporter::createImportDirective(Json::Value const& _node) +ASTPointer ASTJsonImporter::createImportDirective(Json const& _node) { ASTPointer unitAlias = memberAsASTString(_node, "unitAlias"); ASTPointer path = memberAsASTString(_node, "file"); @@ -303,11 +304,11 @@ ASTPointer ASTJsonImporter::createImportDirective(Json::Value c for (auto& tuple: member(_node, "symbolAliases")) { - astAssert(tuple["local"].isNull() || tuple["local"].isString(), "expected 'local' to be a string or null!"); + astAssert(tuple["local"].is_null() || tuple["local"].is_string(), "expected 'local' to be a string or null!"); symbolAliases.push_back({ createIdentifier(tuple["foreign"]), - tuple["local"].isNull() ? nullptr : std::make_shared(tuple["local"].asString()), + tuple["local"].is_null() ? nullptr : std::make_shared(tuple["local"].get()), createSourceLocation(tuple["foreign"])} ); } @@ -319,15 +320,15 @@ ASTPointer ASTJsonImporter::createImportDirective(Json::Value c std::move(symbolAliases) ); - astAssert(_node["absolutePath"].isString(), "Expected 'absolutePath' to be a string!"); + astAssert(_node["absolutePath"].is_string(), "Expected 'absolutePath' to be a string!"); - tmp->annotation().absolutePath = _node["absolutePath"].asString(); + tmp->annotation().absolutePath = _node["absolutePath"].get(); return tmp; } -ASTPointer ASTJsonImporter::createContractDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createContractDefinition(Json const& _node) { - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); std::vector> baseContracts; @@ -341,9 +342,9 @@ ASTPointer ASTJsonImporter::createContractDefinition(Json::V return createASTNode( _node, - std::make_shared(_node["name"].asString()), + std::make_shared(_node["name"].get()), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, baseContracts, subNodes, contractKind(_node), @@ -351,14 +352,14 @@ ASTPointer ASTJsonImporter::createContractDefinition(Json::V ); } -ASTPointer ASTJsonImporter::createIdentifierPath(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIdentifierPath(Json const& _node) { - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); std::vector namePath; std::vector namePathLocations; std::vector strs; - std::string nameString = member(_node, "name").asString(); + std::string nameString = member(_node, "name").get(); boost::algorithm::split(strs, nameString, boost::is_any_of(".")); astAssert(!strs.empty(), "Expected at least one element in IdentifierPath."); for (std::string s: strs) @@ -367,9 +368,9 @@ ASTPointer ASTJsonImporter::createIdentifierPath(Json::Value con namePath.emplace_back(s); } - if (_node.isMember("nameLocations") && _node["nameLocations"].isArray()) + if (_node.contains("nameLocations") && _node["nameLocations"].is_array()) for (auto const& val: _node["nameLocations"]) - namePathLocations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames)); + namePathLocations.emplace_back(langutil::parseSourceLocation(val.get(), m_sourceNames)); else namePathLocations.resize(namePath.size()); @@ -385,7 +386,7 @@ ASTPointer ASTJsonImporter::createIdentifierPath(Json::Value con ); } -ASTPointer ASTJsonImporter::createInheritanceSpecifier(Json::Value const& _node) +ASTPointer ASTJsonImporter::createInheritanceSpecifier(Json const& _node) { std::vector> arguments; for (auto& arg: member(_node, "arguments")) @@ -393,36 +394,36 @@ ASTPointer ASTJsonImporter::createInheritanceSpecifier(Jso return createASTNode( _node, createIdentifierPath(member(_node, "baseName")), - member(_node, "arguments").isNull() ? nullptr : std::make_unique>>(arguments) + member(_node, "arguments").is_null() ? nullptr : std::make_unique>>(arguments) ); } -ASTPointer ASTJsonImporter::createUsingForDirective(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUsingForDirective(Json const& _node) { std::vector> functions; std::vector> operators; - if (_node.isMember("libraryName")) + if (_node.contains("libraryName")) { - astAssert(!_node["libraryName"].isArray()); - astAssert(!_node["libraryName"]["operator"]); + astAssert(!_node["libraryName"].is_array()); + astAssert(!_node["libraryName"].contains("operator")); functions.emplace_back(createIdentifierPath(_node["libraryName"])); operators.emplace_back(std::nullopt); } - else if (_node.isMember("functionList")) - for (Json::Value const& function: _node["functionList"]) + else if (_node.contains("functionList")) + for (Json const& function: _node["functionList"]) { - if (function.isMember("function")) + if (function.contains("function")) { - astAssert(!function.isMember("operator")); - astAssert(!function.isMember("definition")); + astAssert(!function.contains("operator")); + astAssert(!function.contains("definition")); functions.emplace_back(createIdentifierPath(function["function"])); operators.emplace_back(std::nullopt); } else { - astAssert(function.isMember("operator")); - astAssert(function.isMember("definition")); + astAssert(function.contains("operator")); + astAssert(function.contains("definition")); Token const operatorName = scanSingleToken(function["operator"]); astAssert(util::contains(frontend::userDefinableOperators, operatorName)); @@ -436,13 +437,13 @@ ASTPointer ASTJsonImporter::createUsingForDirective(Json::Val _node, std::move(functions), std::move(operators), - !_node.isMember("libraryName"), - _node["typeName"].isNull() ? nullptr : convertJsonToASTNode(_node["typeName"]), + !_node.contains("libraryName"), + (_node.contains("typeName") && !_node["typeName"].is_null()) ? convertJsonToASTNode(_node["typeName"]) : nullptr, memberAsBool(_node, "global") ); } -ASTPointer ASTJsonImporter::createStructDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createStructDefinition(Json const& _node) { std::vector> members; for (auto& member: _node["members"]) @@ -452,11 +453,11 @@ ASTPointer ASTJsonImporter::createStructDefinition(Json::Value const& _ memberAsASTString(_node, "name"), createNameSourceLocation(_node), members, - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")) + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr ); } -ASTPointer ASTJsonImporter::createEnumDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEnumDefinition(Json const& _node) { std::vector> members; for (auto& member: _node["members"]) @@ -466,11 +467,11 @@ ASTPointer ASTJsonImporter::createEnumDefinition(Json::Value con memberAsASTString(_node, "name"), createNameSourceLocation(_node), members, - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")) + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr ); } -ASTPointer ASTJsonImporter::createEnumValue(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEnumValue(Json const& _node) { return createASTNode( _node, @@ -478,7 +479,7 @@ ASTPointer ASTJsonImporter::createEnumValue(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createUserDefinedValueTypeDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUserDefinedValueTypeDefinition(Json const& _node) { return createASTNode( _node, @@ -488,7 +489,7 @@ ASTPointer ASTJsonImporter::createUserDefinedVal ); } -ASTPointer ASTJsonImporter::createParameterList(Json::Value const& _node) +ASTPointer ASTJsonImporter::createParameterList(Json const& _node) { std::vector> parameters; for (auto& param: _node["parameters"]) @@ -499,12 +500,13 @@ ASTPointer ASTJsonImporter::createParameterList(Json::Value const ); } -ASTPointer ASTJsonImporter::createOverrideSpecifier(Json::Value const& _node) +ASTPointer ASTJsonImporter::createOverrideSpecifier(Json const& _node) { std::vector> overrides; - for (auto& param: _node["overrides"]) - overrides.push_back(createIdentifierPath(param)); + if ( _node.contains("overrides")) + for (auto& param: _node["overrides"]) + overrides.push_back(createIdentifierPath(param)); return createASTNode( _node, @@ -512,13 +514,13 @@ ASTPointer ASTJsonImporter::createOverrideSpecifier(Json::Val ); } -ASTPointer ASTJsonImporter::createFunctionDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionDefinition(Json const& _node) { - astAssert(_node["kind"].isString(), "Expected 'kind' to be a string!"); + astAssert(_node["kind"].is_string(), "Expected 'kind' to be a string!"); Token kind; bool freeFunction = false; - std::string kindStr = member(_node, "kind").asString(); + std::string kindStr = member(_node, "kind").get(); if (kindStr == "constructor") kind = Token::Constructor; @@ -555,8 +557,8 @@ ASTPointer ASTJsonImporter::createFunctionDefinition(Json::V freeFunction, kind, memberAsBool(_node, "virtual"), - _node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("overrides") && !_node["overrides"].is_null()) ? createOverrideSpecifier(member(_node, "overrides")) : nullptr, + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")), modifiers, createParameterList(member(_node, "returnParameters")), @@ -564,13 +566,13 @@ ASTPointer ASTJsonImporter::createFunctionDefinition(Json::V ); } -ASTPointer ASTJsonImporter::createVariableDeclaration(Json::Value const& _node) +ASTPointer ASTJsonImporter::createVariableDeclaration(Json const& _node) { - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); VariableDeclaration::Mutability mutability{}; - astAssert(member(_node, "mutability").isString(), "'mutability' expected to be string."); - std::string const mutabilityStr = member(_node, "mutability").asString(); + astAssert(member(_node, "mutability").is_string(), "'mutability' expected to be string."); + std::string const mutabilityStr = member(_node, "mutability").get(); if (mutabilityStr == "constant") { mutability = VariableDeclaration::Mutability::Constant; @@ -590,33 +592,33 @@ ASTPointer ASTJsonImporter::createVariableDeclaration(Json: return createASTNode( _node, nullOrCast(member(_node, "typeName")), - std::make_shared(member(_node, "name").asString()), + std::make_shared(member(_node, "name").get()), createNameSourceLocation(_node), nullOrCast(member(_node, "value")), visibility(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), - _node.isMember("indexed") ? memberAsBool(_node, "indexed") : false, + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, + (_node.contains("indexed") && !_node["indexed"].is_null()) ? memberAsBool(_node, "indexed") : false, mutability, - _node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), + (_node.contains("overrides") && !_node["overrides"].is_null()) ? createOverrideSpecifier(member(_node, "overrides")) : nullptr, location(_node) ); } -ASTPointer ASTJsonImporter::createModifierDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createModifierDefinition(Json const& _node) { return createASTNode( _node, memberAsASTString(_node, "name"), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")), memberAsBool(_node, "virtual"), - _node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), - _node["body"].isNull() ? nullptr: createBlock(member(_node, "body"), false) + (_node.contains("overrides") && !_node["overrides"].is_null()) ? createOverrideSpecifier(member(_node, "overrides")) : nullptr, + (_node.contains("body") && !_node["body"].is_null()) ? createBlock(member(_node, "body"), false) : nullptr ); } -ASTPointer ASTJsonImporter::createModifierInvocation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createModifierInvocation(Json const& _node) { std::vector> arguments; for (auto& arg: member(_node, "arguments")) @@ -624,53 +626,53 @@ ASTPointer ASTJsonImporter::createModifierInvocation(Json::V return createASTNode( _node, createIdentifierPath(member(_node, "modifierName")), - member(_node, "arguments").isNull() ? nullptr : std::make_unique>>(arguments) + member(_node, "arguments").is_null() ? nullptr : std::make_unique>>(arguments) ); } -ASTPointer ASTJsonImporter::createEventDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEventDefinition(Json const& _node) { return createASTNode( _node, memberAsASTString(_node, "name"), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")), memberAsBool(_node, "anonymous") ); } -ASTPointer ASTJsonImporter::createErrorDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createErrorDefinition(Json const& _node) { return createASTNode( _node, memberAsASTString(_node, "name"), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")) ); } -ASTPointer ASTJsonImporter::createElementaryTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createElementaryTypeName(Json const& _node) { unsigned short firstNum; unsigned short secondNum; - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); - std::string name = member(_node, "name").asString(); + std::string name = member(_node, "name").get(); Token token; std::tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name); ElementaryTypeNameToken elem(token, firstNum, secondNum); std::optional mutability = {}; - if (_node.isMember("stateMutability")) + if (_node.contains("stateMutability")) mutability = stateMutability(_node); return createASTNode(_node, elem, mutability); } -ASTPointer ASTJsonImporter::createUserDefinedTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUserDefinedTypeName(Json const& _node) { return createASTNode( _node, @@ -678,7 +680,7 @@ ASTPointer ASTJsonImporter::createUserDefinedTypeName(Json: ); } -ASTPointer ASTJsonImporter::createFunctionTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionTypeName(Json const& _node) { return createASTNode( _node, @@ -689,7 +691,7 @@ ASTPointer ASTJsonImporter::createFunctionTypeName(Json::Value ); } -ASTPointer ASTJsonImporter::createMapping(Json::Value const& _node) +ASTPointer ASTJsonImporter::createMapping(Json const& _node) { return createASTNode( _node, @@ -702,7 +704,7 @@ ASTPointer ASTJsonImporter::createMapping(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createArrayTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createArrayTypeName(Json const& _node) { return createASTNode( _node, @@ -711,24 +713,24 @@ ASTPointer ASTJsonImporter::createArrayTypeName(Json::Value const ); } -ASTPointer ASTJsonImporter::createInlineAssembly(Json::Value const& _node) +ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _node) { - astAssert(_node["evmVersion"].isString(), "Expected evmVersion to be a string!"); - auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].asString()); + astAssert(_node["evmVersion"].is_string(), "Expected evmVersion to be a string!"); + auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].get()); astAssert(evmVersion.has_value(), "Invalid EVM version!"); astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!"); yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value()); ASTPointer>> flags; - if (_node.isMember("flags")) + if (_node.contains("flags")) { flags = std::make_shared>>(); - Json::Value const& flagsNode = _node["flags"]; - astAssert(flagsNode.isArray(), "Assembly flags must be an array."); - for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i) + Json const& flagsNode = _node["flags"]; + astAssert(flagsNode.is_array(), "Assembly flags must be an array."); + for (auto const& flag: flagsNode) { - astAssert(flagsNode[i].isString(), "Assembly flag must be a string."); - flags->emplace_back(std::make_shared(flagsNode[i].asString())); + astAssert(flag.is_string(), "Assembly flag must be a string."); + flags->emplace_back(std::make_shared(flag.get())); } } std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST"))); @@ -741,7 +743,7 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json::Value con ); } -ASTPointer ASTJsonImporter::createBlock(Json::Value const& _node, bool _unchecked) +ASTPointer ASTJsonImporter::createBlock(Json const& _node, bool _unchecked) { std::vector> statements; for (auto& stat: member(_node, "statements")) @@ -754,7 +756,7 @@ ASTPointer ASTJsonImporter::createBlock(Json::Value const& _node, bool _u ); } -ASTPointer ASTJsonImporter::createPlaceholderStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createPlaceholderStatement(Json const& _node) { return createASTNode( _node, @@ -762,7 +764,7 @@ ASTPointer ASTJsonImporter::createPlaceholderStatement(Jso ); } -ASTPointer ASTJsonImporter::createIfStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIfStatement(Json const& _node) { return createASTNode( _node, @@ -773,7 +775,7 @@ ASTPointer ASTJsonImporter::createIfStatement(Json::Value const& _ ); } -ASTPointer ASTJsonImporter::createTryCatchClause(Json::Value const& _node) +ASTPointer ASTJsonImporter::createTryCatchClause(Json const& _node) { return createASTNode( _node, @@ -783,7 +785,7 @@ ASTPointer ASTJsonImporter::createTryCatchClause(Json::Value con ); } -ASTPointer ASTJsonImporter::createTryStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createTryStatement(Json const& _node) { std::vector> clauses; @@ -798,7 +800,7 @@ ASTPointer ASTJsonImporter::createTryStatement(Json::Value const& ); } -ASTPointer ASTJsonImporter::createWhileStatement(Json::Value const& _node, bool _isDoWhile=false) +ASTPointer ASTJsonImporter::createWhileStatement(Json const& _node, bool _isDoWhile=false) { return createASTNode( _node, @@ -809,7 +811,7 @@ ASTPointer ASTJsonImporter::createWhileStatement(Json::Value con ); } -ASTPointer ASTJsonImporter::createForStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createForStatement(Json const& _node) { return createASTNode( _node, @@ -821,7 +823,7 @@ ASTPointer ASTJsonImporter::createForStatement(Json::Value const& ); } -ASTPointer ASTJsonImporter::createContinue(Json::Value const& _node) +ASTPointer ASTJsonImporter::createContinue(Json const& _node) { return createASTNode( _node, @@ -829,7 +831,7 @@ ASTPointer ASTJsonImporter::createContinue(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createBreak(Json::Value const& _node) +ASTPointer ASTJsonImporter::createBreak(Json const& _node) { return createASTNode( _node, @@ -837,7 +839,7 @@ ASTPointer ASTJsonImporter::createBreak(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createReturn(Json::Value const& _node) +ASTPointer ASTJsonImporter::createReturn(Json const& _node) { return createASTNode( _node, @@ -846,7 +848,7 @@ ASTPointer ASTJsonImporter::createReturn(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createThrow(Json::Value const& _node) +ASTPointer ASTJsonImporter::createThrow(Json const& _node) { return createASTNode( _node, @@ -854,7 +856,7 @@ ASTPointer ASTJsonImporter::createThrow(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createEmitStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEmitStatement(Json const& _node) { return createASTNode( _node, @@ -863,7 +865,7 @@ ASTPointer ASTJsonImporter::createEmitStatement(Json::Value const ); } -ASTPointer ASTJsonImporter::createRevertStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createRevertStatement(Json const& _node) { return createASTNode( _node, @@ -872,11 +874,11 @@ ASTPointer ASTJsonImporter::createRevertStatement(Json::Value c ); } -ASTPointer ASTJsonImporter::createVariableDeclarationStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createVariableDeclarationStatement(Json const& _node) { std::vector> variables; for (auto& var: member(_node, "declarations")) - variables.push_back(var.isNull() ? nullptr : createVariableDeclaration(var)); //unnamed components are empty pointers + variables.push_back(var.is_null() ? nullptr : createVariableDeclaration(var)); //unnamed components are empty pointers return createASTNode( _node, nullOrASTString(_node, "documentation"), @@ -885,7 +887,7 @@ ASTPointer ASTJsonImporter::createVariableDeclarat ); } -ASTPointer ASTJsonImporter::createExpressionStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createExpressionStatement(Json const& _node) { return createASTNode( _node, @@ -894,7 +896,7 @@ ASTPointer ASTJsonImporter::createExpressionStatement(Json: ); } -ASTPointer ASTJsonImporter::createConditional(Json::Value const& _node) +ASTPointer ASTJsonImporter::createConditional(Json const& _node) { return createASTNode( _node, @@ -904,7 +906,7 @@ ASTPointer ASTJsonImporter::createConditional(Json::Value const& _ ); } -ASTPointer ASTJsonImporter::createAssignment(Json::Value const& _node) +ASTPointer ASTJsonImporter::createAssignment(Json const& _node) { return createASTNode( _node, @@ -914,7 +916,7 @@ ASTPointer ASTJsonImporter::createAssignment(Json::Value const& _no ); } -ASTPointer ASTJsonImporter::createTupleExpression(Json::Value const& _node) +ASTPointer ASTJsonImporter::createTupleExpression(Json const& _node) { std::vector> components; for (auto& comp: member(_node, "components")) @@ -926,7 +928,7 @@ ASTPointer ASTJsonImporter::createTupleExpression(Json::Value c ); } -ASTPointer ASTJsonImporter::createUnaryOperation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUnaryOperation(Json const& _node) { return createASTNode( _node, @@ -936,7 +938,7 @@ ASTPointer ASTJsonImporter::createUnaryOperation(Json::Value con ); } -ASTPointer ASTJsonImporter::createBinaryOperation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createBinaryOperation(Json const& _node) { return createASTNode( _node, @@ -946,7 +948,7 @@ ASTPointer ASTJsonImporter::createBinaryOperation(Json::Value c ); } -ASTPointer ASTJsonImporter::createFunctionCall(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionCall(Json const& _node) { std::vector> arguments; for (auto& arg: member(_node, "arguments")) @@ -954,8 +956,8 @@ ASTPointer ASTJsonImporter::createFunctionCall(Json::Value const& std::vector> names; for (auto& name: member(_node, "names")) { - astAssert(name.isString(), "Expected 'names' members to be strings!"); - names.push_back(std::make_shared(name.asString())); + astAssert(name.is_string(), "Expected 'names' members to be strings!"); + names.push_back(std::make_shared(name.get())); } std::optional> sourceLocations = createSourceLocations(_node); @@ -971,7 +973,7 @@ ASTPointer ASTJsonImporter::createFunctionCall(Json::Value const& ); } -ASTPointer ASTJsonImporter::createFunctionCallOptions(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionCallOptions(Json const& _node) { std::vector> options; for (auto& option: member(_node, "options")) @@ -979,8 +981,8 @@ ASTPointer ASTJsonImporter::createFunctionCallOptions(Json: std::vector> names; for (auto& name: member(_node, "names")) { - astAssert(name.isString(), "Expected 'names' members to be strings!"); - names.push_back(std::make_shared(name.asString())); + astAssert(name.is_string(), "Expected 'names' members to be strings!"); + names.push_back(std::make_shared(name.get())); } return createASTNode( @@ -991,7 +993,7 @@ ASTPointer ASTJsonImporter::createFunctionCallOptions(Json: ); } -ASTPointer ASTJsonImporter::createNewExpression(Json::Value const& _node) +ASTPointer ASTJsonImporter::createNewExpression(Json const& _node) { return createASTNode( _node, @@ -999,11 +1001,11 @@ ASTPointer ASTJsonImporter::createNewExpression(Json::Value const ); } -ASTPointer ASTJsonImporter::createMemberAccess(Json::Value const& _node) +ASTPointer ASTJsonImporter::createMemberAccess(Json const& _node) { SourceLocation memberLocation; - if (member(_node, "memberLocation").isString()) - memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].asString(), m_sourceNames); + if (member(_node, "memberLocation").is_string()) + memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].get(), m_sourceNames); return createASTNode( _node, @@ -1013,7 +1015,7 @@ ASTPointer ASTJsonImporter::createMemberAccess(Json::Value const& ); } -ASTPointer ASTJsonImporter::createIndexAccess(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIndexAccess(Json const& _node) { return createASTNode( _node, @@ -1022,7 +1024,7 @@ ASTPointer ASTJsonImporter::createIndexAccess(Json::Value const& _n ); } -ASTPointer ASTJsonImporter::createIndexRangeAccess(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIndexRangeAccess(Json const& _node) { return createASTNode( _node, @@ -1032,12 +1034,12 @@ ASTPointer ASTJsonImporter::createIndexRangeAccess(Json::Value ); } -ASTPointer ASTJsonImporter::createIdentifier(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIdentifier(Json const& _node) { return createASTNode(_node, memberAsASTString(_node, "name")); } -ASTPointer ASTJsonImporter::createElementaryTypeNameExpression(Json::Value const& _node) +ASTPointer ASTJsonImporter::createElementaryTypeNameExpression(Json const& _node) { return createASTNode( _node, @@ -1045,116 +1047,116 @@ ASTPointer ASTJsonImporter::createElementaryTypeNa ); } -ASTPointer ASTJsonImporter::createLiteral(Json::Value const& _node) +ASTPointer ASTJsonImporter::createLiteral(Json const& _node) { static std::string const valStr = "value"; static std::string const hexValStr = "hexValue"; - astAssert(member(_node, valStr).isString() || member(_node, hexValStr).isString(), "Literal-value is unset."); + astAssert(member(_node, valStr).is_string() || member(_node, hexValStr).is_string(), "Literal-value is unset."); - ASTPointer value = _node.isMember(hexValStr) ? - std::make_shared(util::asString(util::fromHex(_node[hexValStr].asString()))) : - std::make_shared(_node[valStr].asString()); + ASTPointer value = _node.contains(hexValStr) ? + std::make_shared(util::asString(util::fromHex(_node[hexValStr].get()))) : + std::make_shared(_node[valStr].get()); return createASTNode( _node, literalTokenKind(_node), value, - member(_node, "subdenomination").isNull() ? Literal::SubDenomination::None : subdenomination(_node) + member(_node, "subdenomination").is_null() ? Literal::SubDenomination::None : subdenomination(_node) ); } -ASTPointer ASTJsonImporter::createDocumentation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createDocumentation(Json const& _node) { static std::string const textString = "text"; - astAssert(member(_node, textString).isString(), "'text' must be a string"); + astAssert(member(_node, textString).is_string(), "'text' must be a string"); return createASTNode( _node, - std::make_shared(_node[textString].asString()) + std::make_shared(_node[textString].get()) ); } // ===== helper functions ========== -Json::Value ASTJsonImporter::member(Json::Value const& _node, std::string const& _name) +Json ASTJsonImporter::member(Json const& _node, std::string const& _name) { - if (!_node.isMember(_name)) - return Json::nullValue; + if (!_node.contains(_name)) + return Json(); return _node[_name]; } -Token ASTJsonImporter::scanSingleToken(Json::Value const& _node) +Token ASTJsonImporter::scanSingleToken(Json const& _node) { - langutil::CharStream charStream(_node.asString(), ""); + langutil::CharStream charStream(_node.get(), ""); langutil::Scanner scanner{charStream}; astAssert(scanner.peekNextToken() == Token::EOS, "Token string is too long."); return scanner.currentToken(); } -ASTPointer ASTJsonImporter::nullOrASTString(Json::Value const& _json, std::string const& _name) +ASTPointer ASTJsonImporter::nullOrASTString(Json const& _json, std::string const& _name) { - return _json[_name].isString() ? memberAsASTString(_json, _name) : nullptr; + return (_json.contains(_name) && (_json[_name].is_string())) ? memberAsASTString(_json, _name) : nullptr; } -ASTPointer ASTJsonImporter::memberAsASTString(Json::Value const& _node, std::string const& _name) +ASTPointer ASTJsonImporter::memberAsASTString(Json const& _node, std::string const& _name) { - Json::Value value = member(_node, _name); - astAssert(value.isString(), "field " + _name + " must be of type string."); - return std::make_shared(_node[_name].asString()); + Json value = member(_node, _name); + astAssert(value.is_string(), "field " + _name + " must be of type string."); + return std::make_shared(_node[_name].get()); } -bool ASTJsonImporter::memberAsBool(Json::Value const& _node, std::string const& _name) +bool ASTJsonImporter::memberAsBool(Json const& _node, std::string const& _name) { - Json::Value value = member(_node, _name); - astAssert(value.isBool(), "field " + _name + " must be of type boolean."); - return _node[_name].asBool(); + Json value = member(_node, _name); + astAssert(value.is_boolean(), "field " + _name + " must be of type boolean."); + return _node[_name].get(); } // =========== JSON to definition helpers ======================= -ContractKind ASTJsonImporter::contractKind(Json::Value const& _node) +ContractKind ASTJsonImporter::contractKind(Json const& _node) { ContractKind kind; - astAssert(!member(_node, "contractKind").isNull(), "'Contract-kind' can not be null."); - if (_node["contractKind"].asString() == "interface") + astAssert(!member(_node, "contractKind").is_null(), "'Contract-kind' can not be null."); + if (_node["contractKind"].get() == "interface") kind = ContractKind::Interface; - else if (_node["contractKind"].asString() == "contract") + else if (_node["contractKind"].get() == "contract") kind = ContractKind::Contract; - else if (_node["contractKind"].asString() == "library") + else if (_node["contractKind"].get() == "library") kind = ContractKind::Library; else astAssert(false, "Unknown ContractKind"); return kind; } -Token ASTJsonImporter::literalTokenKind(Json::Value const& _node) +Token ASTJsonImporter::literalTokenKind(Json const& _node) { - astAssert(member(_node, "kind").isString(), "Token-'kind' expected to be a string."); + astAssert(member(_node, "kind").is_string(), "Token-'kind' expected to be a string."); Token tok; - if (_node["kind"].asString() == "number") + if (_node["kind"].get() == "number") tok = Token::Number; - else if (_node["kind"].asString() == "string") + else if (_node["kind"].get() == "string") tok = Token::StringLiteral; - else if (_node["kind"].asString() == "unicodeString") + else if (_node["kind"].get() == "unicodeString") tok = Token::UnicodeStringLiteral; - else if (_node["kind"].asString() == "hexString") + else if (_node["kind"].get() == "hexString") tok = Token::HexStringLiteral; - else if (_node["kind"].asString() == "bool") - tok = (member(_node, "value").asString() == "true") ? Token::TrueLiteral : Token::FalseLiteral; + else if (_node["kind"].get() == "bool") + tok = (member(_node, "value").get() == "true") ? Token::TrueLiteral : Token::FalseLiteral; else astAssert(false, "Unknown kind of literalString"); return tok; } -Visibility ASTJsonImporter::visibility(Json::Value const& _node) +Visibility ASTJsonImporter::visibility(Json const& _node) { - Json::Value visibility = member(_node, "visibility"); - astAssert(visibility.isString(), "'visibility' expected to be a string."); + Json visibility = member(_node, "visibility"); + astAssert(visibility.is_string(), "'visibility' expected to be a string."); - std::string const visibilityStr = visibility.asString(); + std::string const visibilityStr = visibility.get(); if (visibilityStr == "default") return Visibility::Default; @@ -1173,12 +1175,12 @@ Visibility ASTJsonImporter::visibility(Json::Value const& _node) util::unreachable(); } -VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node) +VariableDeclaration::Location ASTJsonImporter::location(Json const& _node) { - Json::Value storageLoc = member(_node, "storageLocation"); - astAssert(storageLoc.isString(), "'storageLocation' expected to be a string."); + Json storageLoc = member(_node, "storageLocation"); + astAssert(storageLoc.is_string(), "'storageLocation' expected to be a string."); - std::string const storageLocStr = storageLoc.asString(); + std::string const storageLocStr = storageLoc.get(); if (storageLocStr == "default") return VariableDeclaration::Location::Unspecified; @@ -1195,16 +1197,16 @@ VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node util::unreachable(); } -Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _node) +Literal::SubDenomination ASTJsonImporter::subdenomination(Json const& _node) { - Json::Value subDen = member(_node, "subdenomination"); + Json subDen = member(_node, "subdenomination"); - if (subDen.isNull()) + if (subDen.is_null()) return Literal::SubDenomination::None; - astAssert(subDen.isString(), "'subDenomination' expected to be string."); + astAssert(subDen.is_string(), "'subDenomination' expected to be string."); - std::string const subDenStr = subDen.asString(); + std::string const subDenStr = subDen.get(); if (subDenStr == "wei") return Literal::SubDenomination::Wei; @@ -1231,10 +1233,10 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no util::unreachable(); } -StateMutability ASTJsonImporter::stateMutability(Json::Value const& _node) +StateMutability ASTJsonImporter::stateMutability(Json const& _node) { - astAssert(member(_node, "stateMutability").isString(), "StateMutability' expected to be string."); - std::string const mutabilityStr = member(_node, "stateMutability").asString(); + astAssert(member(_node, "stateMutability").is_string(), "StateMutability' expected to be string."); + std::string const mutabilityStr = member(_node, "stateMutability").get(); if (mutabilityStr == "pure") return StateMutability::Pure; diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index b9a4d4950569..943415df93ca 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -24,8 +24,8 @@ #pragma once #include +#include #include -#include #include #include #include @@ -47,7 +47,7 @@ class ASTJsonImporter /// Converts the AST from JSON-format to ASTPointer /// @a _sourceList used to provide source names for the ASTs /// @returns map of sourcenames to their respective ASTs - std::map> jsonToSourceUnit(std::map const& _sourceList); + std::map> jsonToSourceUnit(std::map const& _sourceList); private: @@ -56,105 +56,105 @@ class ASTJsonImporter /// Sets the source location and nodeID /// @returns the ASTNode Object class of the respective JSON node, template - ASTPointer createASTNode(Json::Value const& _node, Args&&... _args); + ASTPointer createASTNode(Json const& _node, Args&&... _args); /// @returns the sourceLocation-object created from the string in the JSON node - langutil::SourceLocation const createSourceLocation(Json::Value const& _node); - std::optional> createSourceLocations(Json::Value const& _node) const; + langutil::SourceLocation const createSourceLocation(Json const& _node); + std::optional> createSourceLocations(Json const& _node) const; /// Creates an ASTNode for a given JSON-ast of unknown type /// @returns Pointer to a new created ASTNode - ASTPointer convertJsonToASTNode(Json::Value const& _ast); + ASTPointer convertJsonToASTNode(Json const& _ast); /// @returns a pointer to the more specific subclass of ASTNode /// as indicated by the nodeType field of the json template - ASTPointer convertJsonToASTNode(Json::Value const& _node); + ASTPointer convertJsonToASTNode(Json const& _node); - langutil::SourceLocation createNameSourceLocation(Json::Value const& _node); + langutil::SourceLocation createNameSourceLocation(Json const& _node); /// @returns source location of a mapping key name - langutil::SourceLocation createKeyNameSourceLocation(Json::Value const& _node); + langutil::SourceLocation createKeyNameSourceLocation(Json const& _node); /// @returns source location of a mapping value name - langutil::SourceLocation createValueNameSourceLocation(Json::Value const& _node); + langutil::SourceLocation createValueNameSourceLocation(Json const& _node); /// \defgroup nodeCreators JSON to AST-Nodes ///@{ - ASTPointer createSourceUnit(Json::Value const& _node, std::string const& _srcName); - ASTPointer createPragmaDirective(Json::Value const& _node); - ASTPointer createImportDirective(Json::Value const& _node); - ASTPointer createContractDefinition(Json::Value const& _node); - ASTPointer createIdentifierPath(Json::Value const& _node); - ASTPointer createInheritanceSpecifier(Json::Value const& _node); - ASTPointer createUsingForDirective(Json::Value const& _node); - ASTPointer createStructDefinition(Json::Value const& _node); - ASTPointer createEnumDefinition(Json::Value const& _node); - ASTPointer createEnumValue(Json::Value const& _node); - ASTPointer createUserDefinedValueTypeDefinition(Json::Value const& _node); - ASTPointer createParameterList(Json::Value const& _node); - ASTPointer createOverrideSpecifier(Json::Value const& _node); - ASTPointer createFunctionDefinition(Json::Value const& _node); - ASTPointer createVariableDeclaration(Json::Value const& _node); - ASTPointer createModifierDefinition(Json::Value const& _node); - ASTPointer createModifierInvocation(Json::Value const& _node); - ASTPointer createEventDefinition(Json::Value const& _node); - ASTPointer createErrorDefinition(Json::Value const& _node); - ASTPointer createElementaryTypeName(Json::Value const& _node); - ASTPointer createUserDefinedTypeName(Json::Value const& _node); - ASTPointer createFunctionTypeName(Json::Value const& _node); - ASTPointer createMapping(Json::Value const& _node); - ASTPointer createArrayTypeName(Json::Value const& _node); - ASTPointer createInlineAssembly(Json::Value const& _node); - ASTPointer createBlock(Json::Value const& _node, bool _unchecked); - ASTPointer createPlaceholderStatement(Json::Value const& _node); - ASTPointer createIfStatement(Json::Value const& _node); - ASTPointer createTryCatchClause(Json::Value const& _node); - ASTPointer createTryStatement(Json::Value const& _node); - ASTPointer createWhileStatement(Json::Value const& _node, bool _isDoWhile); - ASTPointer createForStatement(Json::Value const& _node); - ASTPointer createContinue(Json::Value const& _node); - ASTPointer createBreak(Json::Value const& _node); - ASTPointer createReturn(Json::Value const& _node); - ASTPointer createThrow(Json::Value const& _node); - ASTPointer createEmitStatement(Json::Value const& _node); - ASTPointer createRevertStatement(Json::Value const& _node); - ASTPointer createVariableDeclarationStatement(Json::Value const& _node); - ASTPointer createExpressionStatement(Json::Value const& _node); - ASTPointer createConditional(Json::Value const& _node); - ASTPointer createAssignment(Json::Value const& _node); - ASTPointer createTupleExpression(Json::Value const& _node); - ASTPointer createUnaryOperation(Json::Value const& _node); - ASTPointer createBinaryOperation(Json::Value const& _node); - ASTPointer createFunctionCall(Json::Value const& _node); - ASTPointer createFunctionCallOptions(Json::Value const& _node); - ASTPointer createNewExpression(Json::Value const& _node); - ASTPointer createMemberAccess(Json::Value const& _node); - ASTPointer createIndexAccess(Json::Value const& _node); - ASTPointer createIndexRangeAccess(Json::Value const& _node); - ASTPointer createIdentifier(Json::Value const& _node); - ASTPointer createElementaryTypeNameExpression(Json::Value const& _node); - ASTPointer createLiteral(Json::Value const& _node); - ASTPointer createDocumentation(Json::Value const& _node); + ASTPointer createSourceUnit(Json const& _node, std::string const& _srcName); + ASTPointer createPragmaDirective(Json const& _node); + ASTPointer createImportDirective(Json const& _node); + ASTPointer createContractDefinition(Json const& _node); + ASTPointer createIdentifierPath(Json const& _node); + ASTPointer createInheritanceSpecifier(Json const& _node); + ASTPointer createUsingForDirective(Json const& _node); + ASTPointer createStructDefinition(Json const& _node); + ASTPointer createEnumDefinition(Json const& _node); + ASTPointer createEnumValue(Json const& _node); + ASTPointer createUserDefinedValueTypeDefinition(Json const& _node); + ASTPointer createParameterList(Json const& _node); + ASTPointer createOverrideSpecifier(Json const& _node); + ASTPointer createFunctionDefinition(Json const& _node); + ASTPointer createVariableDeclaration(Json const& _node); + ASTPointer createModifierDefinition(Json const& _node); + ASTPointer createModifierInvocation(Json const& _node); + ASTPointer createEventDefinition(Json const& _node); + ASTPointer createErrorDefinition(Json const& _node); + ASTPointer createElementaryTypeName(Json const& _node); + ASTPointer createUserDefinedTypeName(Json const& _node); + ASTPointer createFunctionTypeName(Json const& _node); + ASTPointer createMapping(Json const& _node); + ASTPointer createArrayTypeName(Json const& _node); + ASTPointer createInlineAssembly(Json const& _node); + ASTPointer createBlock(Json const& _node, bool _unchecked); + ASTPointer createPlaceholderStatement(Json const& _node); + ASTPointer createIfStatement(Json const& _node); + ASTPointer createTryCatchClause(Json const& _node); + ASTPointer createTryStatement(Json const& _node); + ASTPointer createWhileStatement(Json const& _node, bool _isDoWhile); + ASTPointer createForStatement(Json const& _node); + ASTPointer createContinue(Json const& _node); + ASTPointer createBreak(Json const& _node); + ASTPointer createReturn(Json const& _node); + ASTPointer createThrow(Json const& _node); + ASTPointer createEmitStatement(Json const& _node); + ASTPointer createRevertStatement(Json const& _node); + ASTPointer createVariableDeclarationStatement(Json const& _node); + ASTPointer createExpressionStatement(Json const& _node); + ASTPointer createConditional(Json const& _node); + ASTPointer createAssignment(Json const& _node); + ASTPointer createTupleExpression(Json const& _node); + ASTPointer createUnaryOperation(Json const& _node); + ASTPointer createBinaryOperation(Json const& _node); + ASTPointer createFunctionCall(Json const& _node); + ASTPointer createFunctionCallOptions(Json const& _node); + ASTPointer createNewExpression(Json const& _node); + ASTPointer createMemberAccess(Json const& _node); + ASTPointer createIndexAccess(Json const& _node); + ASTPointer createIndexRangeAccess(Json const& _node); + ASTPointer createIdentifier(Json const& _node); + ASTPointer createElementaryTypeNameExpression(Json const& _node); + ASTPointer createLiteral(Json const& _node); + ASTPointer createDocumentation(Json const& _node); ///@} // =============== general helper functions =================== /// @returns the member of a given JSON object, throws if member does not exist - Json::Value member(Json::Value const& _node, std::string const& _name); + Json member(Json const& _node, std::string const& _name); /// @returns the appropriate TokenObject used in parsed Strings (pragma directive or operator) - Token scanSingleToken(Json::Value const& _node); + Token scanSingleToken(Json const& _node); template ///@returns nullptr or an ASTPointer cast to a specific Class - ASTPointer nullOrCast(Json::Value const& _json); + ASTPointer nullOrCast(Json const& _json); /// @returns nullptr or ASTString, given an JSON string or an empty field - ASTPointer nullOrASTString(Json::Value const& _json, std::string const& _name); + ASTPointer nullOrASTString(Json const& _json, std::string const& _name); // ============== JSON to definition helpers =============== /// \defgroup typeHelpers Json to ast-datatype helpers /// {@ - ASTPointer memberAsASTString(Json::Value const& _node, std::string const& _name); - bool memberAsBool(Json::Value const& _node, std::string const& _name); - Visibility visibility(Json::Value const& _node); - StateMutability stateMutability(Json::Value const& _node); - VariableDeclaration::Location location(Json::Value const& _node); - ContractKind contractKind(Json::Value const& _node); - Token literalTokenKind(Json::Value const& _node); - Literal::SubDenomination subdenomination(Json::Value const& _node); + ASTPointer memberAsASTString(Json const& _node, std::string const& _name); + bool memberAsBool(Json const& _node, std::string const& _name); + Visibility visibility(Json const& _node); + StateMutability stateMutability(Json const& _node); + VariableDeclaration::Location location(Json const& _node); + ContractKind contractKind(Json const& _node); + Token literalTokenKind(Json const& _node); + Literal::SubDenomination subdenomination(Json const& _node); ///@} // =========== member variables =============== diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index a80a18a62a10..8e03a378b302 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace solidity::frontend { diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index b84fbc357345..59585c762eec 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -37,8 +37,7 @@ #include #include #include - -#include +#include #include #include diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 9026954d6100..9f01b74fc246 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -23,6 +23,8 @@ #pragma once +#include + #include #include #include @@ -32,8 +34,6 @@ #include #include -#include - #include namespace solidity::frontend diff --git a/libsolidity/experimental/codegen/IRGenerator.h b/libsolidity/experimental/codegen/IRGenerator.h index 7d3baf8f954e..5da6f9f6fd6a 100644 --- a/libsolidity/experimental/codegen/IRGenerator.h +++ b/libsolidity/experimental/codegen/IRGenerator.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include diff --git a/libsolidity/formal/BMC.h b/libsolidity/formal/BMC.h index 9daa1683721c..1f97cbeef480 100644 --- a/libsolidity/formal/BMC.h +++ b/libsolidity/formal/BMC.h @@ -41,6 +41,7 @@ #include #include #include +#include using solidity::util::h256; diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index cf6e863bbbf2..e06f4b5828cc 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -38,12 +38,14 @@ bool anyDataStoredInStorage(TypePointers const& _pointers) } } -Json::Value ABI::generate(ContractDefinition const& _contractDef) +Json ABI::generate(ContractDefinition const& _contractDef) { - auto compare = [](Json::Value const& _a, Json::Value const& _b) -> bool { - return std::make_tuple(_a["type"], _a["name"]) < std::make_tuple(_b["type"], _b["name"]); + auto compare = [](Json const& _a, Json const& _b) -> bool + { + return std::make_tuple(_a.value("type", Json()), _a.value("name", Json())) < + std::make_tuple(_b.value("type", Json()), _b.value("name", Json())); }; - std::multiset abi(compare); + std::multiset abi(compare); for (auto it: _contractDef.interfaceFunctions()) { @@ -55,7 +57,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) FunctionType const* externalFunctionType = it.second->interfaceFunctionType(); solAssert(!!externalFunctionType, ""); - Json::Value method{Json::objectValue}; + Json method; method["type"] = "function"; method["name"] = it.second->declaration().name(); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); @@ -79,7 +81,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) FunctionType constrType(*constructor); FunctionType const* externalFunctionType = constrType.interfaceFunctionType(); solAssert(!!externalFunctionType, ""); - Json::Value method{Json::objectValue}; + Json method; method["type"] = "constructor"; method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["inputs"] = formatTypeList( @@ -95,25 +97,25 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) { auto const* externalFunctionType = FunctionType(*fallbackOrReceive).interfaceFunctionType(); solAssert(!!externalFunctionType, ""); - Json::Value method{Json::objectValue}; + Json method; method["type"] = TokenTraits::toString(fallbackOrReceive->kind()); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); abi.emplace(std::move(method)); } for (auto const& it: _contractDef.interfaceEvents()) { - Json::Value event{Json::objectValue}; + Json event; event["type"] = "event"; event["name"] = it->name(); event["anonymous"] = it->isAnonymous(); - Json::Value params{Json::arrayValue}; + Json params = Json::array(); for (auto const& p: it->parameters()) { Type const* type = p->annotation().type->interfaceType(false); solAssert(type, ""); auto param = formatType(p->name(), *type, *p->annotation().type, false); param["indexed"] = p->isIndexed(); - params.append(std::move(param)); + params.emplace_back(param); } event["inputs"] = std::move(params); abi.emplace(std::move(event)); @@ -121,53 +123,53 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) for (ErrorDefinition const* error: _contractDef.interfaceErrors()) { - Json::Value errorJson{Json::objectValue}; + Json errorJson; errorJson["type"] = "error"; errorJson["name"] = error->name(); - errorJson["inputs"] = Json::arrayValue; + errorJson["inputs"] = Json::array(); for (auto const& p: error->parameters()) { Type const* type = p->annotation().type->interfaceType(false); solAssert(type, ""); - errorJson["inputs"].append( + errorJson["inputs"].emplace_back( formatType(p->name(), *type, *p->annotation().type, false) ); } abi.emplace(std::move(errorJson)); } - Json::Value abiJson{Json::arrayValue}; + Json abiJson = Json::array(); for (auto& f: abi) - abiJson.append(std::move(f)); + abiJson.emplace_back(std::move(f)); return abiJson; } -Json::Value ABI::formatTypeList( +Json ABI::formatTypeList( std::vector const& _names, std::vector const& _encodingTypes, std::vector const& _solidityTypes, bool _forLibrary ) { - Json::Value params{Json::arrayValue}; + Json params = Json::array(); solAssert(_names.size() == _encodingTypes.size(), "Names and types vector size does not match"); solAssert(_names.size() == _solidityTypes.size(), ""); for (unsigned i = 0; i < _names.size(); ++i) { solAssert(_encodingTypes[i], ""); - params.append(formatType(_names[i], *_encodingTypes[i], *_solidityTypes[i], _forLibrary)); + params.emplace_back(formatType(_names[i], *_encodingTypes[i], *_solidityTypes[i], _forLibrary)); } return params; } -Json::Value ABI::formatType( +Json ABI::formatType( std::string const& _name, Type const& _encodingType, Type const& _solidityType, bool _forLibrary ) { - Json::Value ret{Json::objectValue}; + Json ret; ret["name"] = _name; ret["internalType"] = _solidityType.toString(true); std::string suffix = (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage)) ? " storage" : ""; @@ -185,31 +187,31 @@ Json::Value ABI::formatType( else suffix = std::string("[") + arrayType->length().str() + "]"; solAssert(arrayType->baseType(), ""); - Json::Value subtype = formatType( + Json subtype = formatType( "", *arrayType->baseType(), *dynamic_cast(_solidityType).baseType(), _forLibrary ); - if (subtype.isMember("components")) + if (subtype.contains("components")) { - ret["type"] = subtype["type"].asString() + suffix; + ret["type"] = subtype["type"].get() + suffix; ret["components"] = subtype["components"]; } else - ret["type"] = subtype["type"].asString() + suffix; + ret["type"] = subtype["type"].get() + suffix; } } else if (StructType const* structType = dynamic_cast(&_encodingType)) { ret["type"] = "tuple"; - ret["components"] = Json::arrayValue; + ret["components"] = Json::array(); for (auto const& member: structType->members(nullptr)) { solAssert(member.type, ""); Type const* t = member.type->interfaceType(_forLibrary); solAssert(t, ""); - ret["components"].append(formatType(member.name, *t, *member.type, _forLibrary)); + ret["components"].emplace_back(formatType(member.name, *t, *member.type, _forLibrary)); } } else diff --git a/libsolidity/interface/ABI.h b/libsolidity/interface/ABI.h index e956614497db..22e306c4322b 100644 --- a/libsolidity/interface/ABI.h +++ b/libsolidity/interface/ABI.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include @@ -38,14 +38,14 @@ class ABI /// Get the ABI Interface of the contract /// @param _contractDef The contract definition /// @return A JSONrepresentation of the contract's ABI Interface - static Json::Value generate(ContractDefinition const& _contractDef); + static Json generate(ContractDefinition const& _contractDef); private: /// @returns a json value suitable for a list of types in function input or output /// parameters or other places. If @a _forLibrary is true, complex types are referenced /// by name, otherwise they are anonymously expanded. /// @a _solidityTypes is the list of original Solidity types where @a _encodingTypes is the list of /// ABI types used for the actual encoding. - static Json::Value formatTypeList( + static Json formatTypeList( std::vector const& _names, std::vector const& _encodingTypes, std::vector const& _solidityTypes, @@ -56,7 +56,7 @@ class ABI /// If it is possible to express the type as a single string, it is allowed to return a single string. /// @a _solidityType is the original Solidity type and @a _encodingTypes is the /// ABI type used for the actual encoding. - static Json::Value formatType( + static Json formatType( std::string const& _name, Type const& _encodingType, Type const& _solidityType, diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 2d1fd10743a3..2a9005680678 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -85,8 +85,6 @@ #include #include -#include - #include #include @@ -426,7 +424,7 @@ bool CompilerStack::parse() return true; } -void CompilerStack::importASTs(std::map const& _sources) +void CompilerStack::importASTs(std::map const& _sources) { if (m_stackState != Empty) solThrow(CompilerError, "Must call importASTs only before the SourcesSet state."); @@ -843,18 +841,18 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(std::string con return currentContract.evmRuntimeAssembly ? ¤tContract.evmRuntimeAssembly->items() : nullptr; } -Json::Value CompilerStack::generatedSources(std::string const& _contractName, bool _runtime) const +Json CompilerStack::generatedSources(std::string const& _contractName, bool _runtime) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); Contract const& c = contract(_contractName); - util::LazyInit const& sources = + util::LazyInit const& sources = _runtime ? c.runtimeGeneratedSources : c.generatedSources; return sources.init([&]{ - Json::Value sources{Json::arrayValue}; + Json sources = Json::array(); // If there is no compiler, then no bytecode was generated and thus no // sources were generated (or we compiled "via IR"). if (c.compiler) @@ -947,7 +945,7 @@ std::string const& CompilerStack::yulIR(std::string const& _contractName) const return contract(_contractName).yulIR; } -Json::Value const& CompilerStack::yulIRAst(std::string const& _contractName) const +Json const& CompilerStack::yulIRAst(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -965,7 +963,7 @@ std::string const& CompilerStack::yulIROptimized(std::string const& _contractNam return contract(_contractName).yulIROptimized; } -Json::Value const& CompilerStack::yulIROptimizedAst(std::string const& _contractName) const +Json const& CompilerStack::yulIROptimizedAst(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -1005,7 +1003,7 @@ std::string CompilerStack::assemblyString(std::string const& _contractName, Stri } /// TODO: cache the JSON -Json::Value CompilerStack::assemblyJSON(std::string const& _contractName) const +Json CompilerStack::assemblyJSON(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -1016,7 +1014,7 @@ Json::Value CompilerStack::assemblyJSON(std::string const& _contractName) const if (currentContract.evmAssembly) return currentContract.evmAssembly->assemblyJSON(sourceIndices()); else - return Json::Value(); + return Json(); } std::vector CompilerStack::sourceNames() const @@ -1035,7 +1033,7 @@ std::map CompilerStack::sourceIndices() const return indices; } -Json::Value const& CompilerStack::contractABI(std::string const& _contractName) const +Json const& CompilerStack::contractABI(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1043,7 +1041,7 @@ Json::Value const& CompilerStack::contractABI(std::string const& _contractName) return contractABI(contract(_contractName)); } -Json::Value const& CompilerStack::contractABI(Contract const& _contract) const +Json const& CompilerStack::contractABI(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1054,7 +1052,7 @@ Json::Value const& CompilerStack::contractABI(Contract const& _contract) const return _contract.abi.init([&]{ return ABI::generate(*_contract.contract); }); } -Json::Value const& CompilerStack::storageLayout(std::string const& _contractName) const +Json const& CompilerStack::storageLayout(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1062,7 +1060,7 @@ Json::Value const& CompilerStack::storageLayout(std::string const& _contractName return storageLayout(contract(_contractName)); } -Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const +Json const& CompilerStack::storageLayout(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1073,7 +1071,7 @@ Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract); }); } -Json::Value const& CompilerStack::natspecUser(std::string const& _contractName) const +Json const& CompilerStack::natspecUser(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1081,7 +1079,7 @@ Json::Value const& CompilerStack::natspecUser(std::string const& _contractName) return natspecUser(contract(_contractName)); } -Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const +Json const& CompilerStack::natspecUser(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1092,7 +1090,7 @@ Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const return _contract.userDocumentation.init([&]{ return Natspec::userDocumentation(*_contract.contract); }); } -Json::Value const& CompilerStack::natspecDev(std::string const& _contractName) const +Json const& CompilerStack::natspecDev(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1100,7 +1098,7 @@ Json::Value const& CompilerStack::natspecDev(std::string const& _contractName) c return natspecDev(contract(_contractName)); } -Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const +Json const& CompilerStack::natspecDev(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1112,16 +1110,16 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); }); } -Json::Value CompilerStack::interfaceSymbols(std::string const& _contractName) const +Json CompilerStack::interfaceSymbols(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - Json::Value interfaceSymbols(Json::objectValue); + Json interfaceSymbols; // Always have a methods object - interfaceSymbols["methods"] = Json::objectValue; + interfaceSymbols["methods"] = Json::object(); for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) interfaceSymbols["methods"][it.second->externalSignature()] = it.first.hex(); @@ -1650,7 +1648,7 @@ CompilerStack::Source const& CompilerStack::source(std::string const& _sourceNam std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) const { - Json::Value meta{Json::objectValue}; + Json meta; meta["version"] = 1; std::string sourceType; switch (m_compilationSourceType) @@ -1671,7 +1669,7 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR for (auto const sourceUnit: _contract.contract->sourceUnit().referencedSourceUnits(true)) referencedSources.insert(*sourceUnit->annotation().path); - meta["sources"] = Json::objectValue; + meta["sources"] = Json::object(); for (auto const& s: m_sources) { if (!referencedSources.count(s.first)) @@ -1685,15 +1683,15 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR meta["sources"][s.first]["content"] = s.second.charStream->source(); else { - meta["sources"][s.first]["urls"] = Json::arrayValue; - meta["sources"][s.first]["urls"].append("bzz-raw://" + util::toHex(s.second.swarmHash().asBytes())); - meta["sources"][s.first]["urls"].append(s.second.ipfsUrl()); + meta["sources"][s.first]["urls"] = Json::array(); + meta["sources"][s.first]["urls"].emplace_back("bzz-raw://" + util::toHex(s.second.swarmHash().asBytes())); + meta["sources"][s.first]["urls"].emplace_back(s.second.ipfsUrl()); } } - static_assert(sizeof(m_optimiserSettings.expectedExecutionsPerDeployment) <= sizeof(Json::LargestUInt), "Invalid word size."); - solAssert(static_cast(m_optimiserSettings.expectedExecutionsPerDeployment) < std::numeric_limits::max(), ""); - meta["settings"]["optimizer"]["runs"] = Json::Value(Json::LargestUInt(m_optimiserSettings.expectedExecutionsPerDeployment)); + static_assert(sizeof(m_optimiserSettings.expectedExecutionsPerDeployment) <= sizeof(Json::number_integer_t), "Invalid word size."); + solAssert(static_cast(m_optimiserSettings.expectedExecutionsPerDeployment) < std::numeric_limits::max(), ""); + meta["settings"]["optimizer"]["runs"] = Json::number_integer_t(m_optimiserSettings.expectedExecutionsPerDeployment); /// Backwards compatibility: If set to one of the default settings, do not provide details. OptimiserSettings settingsWithoutRuns = m_optimiserSettings; @@ -1705,7 +1703,7 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR meta["settings"]["optimizer"]["enabled"] = true; else { - Json::Value details{Json::objectValue}; + Json details = Json::object(); details["orderLiterals"] = m_optimiserSettings.runOrderLiterals; details["inliner"] = m_optimiserSettings.runInliner; @@ -1718,14 +1716,14 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR details["yul"] = m_optimiserSettings.runYulOptimiser; if (m_optimiserSettings.runYulOptimiser) { - details["yulDetails"] = Json::objectValue; + details["yulDetails"] = Json::object(); details["yulDetails"]["stackAllocation"] = m_optimiserSettings.optimizeStackAllocation; details["yulDetails"]["optimizerSteps"] = m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps; } else if (OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps)) { solAssert(m_optimiserSettings.optimizeStackAllocation == false); - details["yulDetails"] = Json::objectValue; + details["yulDetails"] = Json::object(); details["yulDetails"]["optimizerSteps"] = ":"; } else @@ -1758,14 +1756,14 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] = *_contract.contract->annotation().canonicalName; - meta["settings"]["remappings"] = Json::arrayValue; + meta["settings"]["remappings"] = Json::array(); std::set remappings; for (auto const& r: m_importRemapper.remappings()) remappings.insert(r.context + ":" + r.prefix + "=" + r.target); for (auto const& r: remappings) - meta["settings"]["remappings"].append(r); + meta["settings"]["remappings"].emplace_back(r); - meta["settings"]["libraries"] = Json::objectValue; + meta["settings"]["libraries"] = Json::object(); for (auto const& library: m_libraries) meta["settings"]["libraries"][library.first] = "0x" + util::toHex(library.second.asBytes()); @@ -1897,17 +1895,17 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR) namespace { -Json::Value gasToJson(GasEstimator::GasConsumption const& _gas) +Json gasToJson(GasEstimator::GasConsumption const& _gas) { if (_gas.isInfinite) - return Json::Value("infinite"); + return Json("infinite"); else - return Json::Value(util::toString(_gas.value)); + return Json(util::toString(_gas.value)); } } -Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const +Json CompilerStack::gasEstimates(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -1915,18 +1913,18 @@ Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const solUnimplementedAssert(!isExperimentalSolidity()); if (!assemblyItems(_contractName) && !runtimeAssemblyItems(_contractName)) - return Json::Value(); + return Json(); using Gas = GasEstimator::GasConsumption; GasEstimator gasEstimator(m_evmVersion); - Json::Value output(Json::objectValue); + Json output = Json::object(); if (evmasm::AssemblyItems const* items = assemblyItems(_contractName)) { Gas executionGas = gasEstimator.functionalEstimation(*items); Gas codeDepositGas{evmasm::GasMeter::dataGas(runtimeObject(_contractName).bytecode, false, m_evmVersion)}; - Json::Value creation(Json::objectValue); + Json creation = Json::object(); creation["codeDepositCost"] = gasToJson(codeDepositGas); creation["executionCost"] = gasToJson(executionGas); /// TODO: implement + overload to avoid the need of += @@ -1939,7 +1937,7 @@ Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const { /// External functions ContractDefinition const& contract = contractDefinition(_contractName); - Json::Value externalFunctions(Json::objectValue); + Json externalFunctions = Json::object(); for (auto it: contract.interfaceFunctions()) { std::string sig = it.second->externalSignature(); @@ -1956,7 +1954,7 @@ Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const output["external"] = externalFunctions; /// Internal functions - Json::Value internalFunctions(Json::objectValue); + Json internalFunctions = Json::object(); for (auto const& it: contract.definedFunctions()) { /// Exclude externally visible functions, constructor, fallback and receive ether function diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 57d30e602d1d..ef76764faf70 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -47,8 +47,7 @@ #include #include #include - -#include +#include #include #include @@ -221,7 +220,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Imports given SourceUnits so they can be analyzed. Leads to the same internal state as parse(). /// Will throw errors if the import fails - void importASTs(std::map const& _sources); + void importASTs(std::map const& _sources); /// Performs the analysis steps (imports, scopesetting, syntaxCheck, referenceResolving, /// typechecking, staticAnalysis) on previously parsed sources. @@ -277,13 +276,13 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::string const& yulIR(std::string const& _contractName) const; /// @returns the IR representation of a contract AST in format. - Json::Value const& yulIRAst(std::string const& _contractName) const; + Json const& yulIRAst(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract. std::string const& yulIROptimized(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract AST in JSON format. - Json::Value const& yulIROptimizedAst(std::string const& _contractName) const; + Json const& yulIROptimizedAst(std::string const& _contractName) const; /// @returns the assembled object for a contract. virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override; @@ -299,7 +298,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns an array containing all utility sources generated during compilation. /// Format: [ { name: string, id: number, language: "Yul", contents: string }, ... ] - Json::Value generatedSources(std::string const& _contractName, bool _runtime = false) const; + Json generatedSources(std::string const& _contractName, bool _runtime = false) const; /// @returns the string that provides a mapping between bytecode and sourcecode or a nullptr /// if the contract does not (yet) have bytecode. @@ -317,26 +316,26 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns a JSON representation of the assembly. /// @arg _sourceCodes is the map of input files to source code strings /// Prerequisite: Successful compilation. - virtual Json::Value assemblyJSON(std::string const& _contractName) const override; + virtual Json assemblyJSON(std::string const& _contractName) const override; /// @returns a JSON representing the contract ABI. /// Prerequisite: Successful call to parse or compile. - Json::Value const& contractABI(std::string const& _contractName) const; + Json const& contractABI(std::string const& _contractName) const; /// @returns a JSON representing the storage layout of the contract. /// Prerequisite: Successful call to parse or compile. - Json::Value const& storageLayout(std::string const& _contractName) const; + Json const& storageLayout(std::string const& _contractName) const; /// @returns a JSON representing the contract's user documentation. /// Prerequisite: Successful call to parse or compile. - Json::Value const& natspecUser(std::string const& _contractName) const; + Json const& natspecUser(std::string const& _contractName) const; /// @returns a JSON representing the contract's developer documentation. /// Prerequisite: Successful call to parse or compile. - Json::Value const& natspecDev(std::string const& _contractName) const; + Json const& natspecDev(std::string const& _contractName) const; /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. - Json::Value interfaceSymbols(std::string const& _contractName) const; + Json interfaceSymbols(std::string const& _contractName) const; /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } @@ -350,7 +349,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac bytes cborMetadata(std::string const& _contractName, bool _forIR) const; /// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions - Json::Value gasEstimates(std::string const& _contractName) const; + Json gasEstimates(std::string const& _contractName) const; /// Changes the format of the metadata appended at the end of the bytecode. void setMetadataFormat(MetadataFormat _metadataFormat) { m_metadataFormat = _metadataFormat; } @@ -390,15 +389,15 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac evmasm::LinkerObject runtimeObject; ///< Runtime object. std::string yulIR; ///< Yul IR code. std::string yulIROptimized; ///< Optimized Yul IR code. - Json::Value yulIRAst; ///< JSON AST of Yul IR code. - Json::Value yulIROptimizedAst; ///< JSON AST of optimized Yul IR code. + Json yulIRAst; ///< JSON AST of Yul IR code. + Json yulIROptimizedAst; ///< JSON AST of optimized Yul IR code. util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. - util::LazyInit abi; - util::LazyInit storageLayout; - util::LazyInit userDocumentation; - util::LazyInit devDocumentation; - util::LazyInit generatedSources; - util::LazyInit runtimeGeneratedSources; + util::LazyInit abi; + util::LazyInit storageLayout; + util::LazyInit userDocumentation; + util::LazyInit devDocumentation; + util::LazyInit generatedSources; + util::LazyInit runtimeGeneratedSources; mutable std::optional sourceMapping; mutable std::optional runtimeSourceMapping; }; @@ -479,19 +478,19 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns the contract ABI as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& contractABI(Contract const&) const; + Json const& contractABI(Contract const&) const; /// @returns the storage layout of the contract as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& storageLayout(Contract const&) const; + Json const& storageLayout(Contract const&) const; /// @returns the Natspec User documentation as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& natspecUser(Contract const&) const; + Json const& natspecUser(Contract const&) const; /// @returns the Natspec Developer documentation as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& natspecDev(Contract const&) const; + Json const& natspecDev(Contract const&) const; /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. /// This will generate the metadata and store it in the Contract object if it is not present yet. diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp index 539a3573f50b..a0da7b54bb5e 100644 --- a/libsolidity/interface/Natspec.cpp +++ b/libsolidity/interface/Natspec.cpp @@ -33,13 +33,13 @@ using namespace solidity; using namespace solidity::frontend; -Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) +Json Natspec::userDocumentation(ContractDefinition const& _contractDef) { - Json::Value doc{Json::objectValue}; + Json doc; - doc["version"] = Json::Value(c_natspecVersion); - doc["kind"] = Json::Value("user"); - doc["methods"] = Json::objectValue; + doc["version"] = Json(c_natspecVersion); + doc["kind"] = Json("user"); + doc["methods"] = Json::object(); auto constructorDefinition(_contractDef.constructor()); if (constructorDefinition) @@ -48,15 +48,15 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) if (!value.empty()) { // add the constructor, only if we have any documentation to add - Json::Value user{Json::objectValue}; - user["notice"] = Json::Value(value); + Json user; + user["notice"] = Json(value); doc["methods"]["constructor"] = user; } } std::string notice = extractDoc(_contractDef.annotation().docTags, "notice"); if (!notice.empty()) - doc["notice"] = Json::Value(notice); + doc["notice"] = Json(notice); for (auto const& it: _contractDef.interfaceFunctions()) if (it.second->hasDeclaration()) @@ -88,21 +88,21 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) std::string value = extractDoc(error->annotation().docTags, "notice"); if (!value.empty()) { - Json::Value errorDoc{Json::objectValue}; + Json errorDoc; errorDoc["notice"] = value; - doc["errors"][error->functionType(true)->externalSignature()].append(std::move(errorDoc)); + doc["errors"][error->functionType(true)->externalSignature()].emplace_back(std::move(errorDoc)); } } return doc; } -Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) +Json Natspec::devDocumentation(ContractDefinition const& _contractDef) { - Json::Value doc = extractCustomDoc(_contractDef.annotation().docTags); + Json doc = extractCustomDoc(_contractDef.annotation().docTags); - doc["version"] = Json::Value(c_natspecVersion); - doc["kind"] = Json::Value("dev"); + doc["version"] = Json(c_natspecVersion); + doc["kind"] = Json("dev"); auto author = extractDoc(_contractDef.annotation().docTags, "author"); if (!author.empty()) @@ -112,13 +112,13 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) doc["title"] = title; auto dev = extractDoc(_contractDef.annotation().docTags, "dev"); if (!dev.empty()) - doc["details"] = Json::Value(dev); + doc["details"] = Json(dev); - doc["methods"] = Json::objectValue; + doc["methods"] = Json::object(); auto constructorDefinition(_contractDef.constructor()); if (constructorDefinition) { - Json::Value constructor(devDocumentation(constructorDefinition->annotation().docTags)); + Json constructor(devDocumentation(constructorDefinition->annotation().docTags)); if (!constructor.empty()) // add the constructor, only if we have any documentation to add doc["methods"]["constructor"] = constructor; @@ -130,9 +130,9 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) continue; if (auto fun = dynamic_cast(&it.second->declaration())) { - Json::Value method(devDocumentation(fun->annotation().docTags)); + Json method(devDocumentation(fun->annotation().docTags)); // add the function, only if we have any documentation to add - Json::Value jsonReturn = extractReturnParameterDocs( + Json jsonReturn = extractReturnParameterDocs( fun->annotation().docTags, fun->functionType(false)->returnParameterNames() ); @@ -150,7 +150,7 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) if (auto devDoc = devDocumentation(varDecl->annotation().docTags); !devDoc.empty()) doc["stateVariables"][varDecl->name()] = devDoc; - auto const assignIfNotEmpty = [&](std::string const& _name, Json::Value const& _content) + auto const assignIfNotEmpty = [&](std::string const& _name, Json const& _content) { if (!_content.empty()) doc["stateVariables"][varDecl->name()][_name] = _content; @@ -171,14 +171,14 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) doc["events"][event->functionType(true)->externalSignature()] = devDoc; for (auto const& error: _contractDef.interfaceErrors()) if (auto devDoc = devDocumentation(error->annotation().docTags); !devDoc.empty()) - doc["errors"][error->functionType(true)->externalSignature()].append(devDoc); + doc["errors"][error->functionType(true)->externalSignature()].emplace_back(devDoc); return doc; } -Json::Value Natspec::extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames) +Json Natspec::extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames) { - Json::Value jsonReturn{Json::objectValue}; + Json jsonReturn; auto returnDocs = _tags.equal_range("return"); if (!_returnParameterNames.empty()) @@ -199,7 +199,7 @@ Json::Value Natspec::extractReturnParameterDocs(std::multimap const& _tags, return value; } -Json::Value Natspec::extractCustomDoc(std::multimap const& _tags) +Json Natspec::extractCustomDoc(std::multimap const& _tags) { std::map concatenated; for (auto const& [tag, value]: _tags) @@ -224,28 +224,28 @@ Json::Value Natspec::extractCustomDoc(std::multimap const& concatenated[tag] += value.content; // We do not want to create an object if there are no custom tags found. if (concatenated.empty()) - return Json::nullValue; - Json::Value result{Json::objectValue}; + return Json(); + Json result; for (auto& [tag, value]: concatenated) result[tag] = std::move(value); return result; } -Json::Value Natspec::devDocumentation(std::multimap const& _tags) +Json Natspec::devDocumentation(std::multimap const& _tags) { - Json::Value json = extractCustomDoc(_tags); + Json json = extractCustomDoc(_tags); auto dev = extractDoc(_tags, "dev"); if (!dev.empty()) - json["details"] = Json::Value(dev); + json["details"] = Json(dev); auto author = extractDoc(_tags, "author"); if (!author.empty()) json["author"] = author; - Json::Value params(Json::objectValue); + Json params; auto paramRange = _tags.equal_range("param"); for (auto i = paramRange.first; i != paramRange.second; ++i) - params[i->second.paramName] = Json::Value(i->second.content); + params[i->second.paramName] = Json(i->second.content); if (!params.empty()) json["params"] = params; diff --git a/libsolidity/interface/Natspec.h b/libsolidity/interface/Natspec.h index e75485097def..994f1350cb87 100644 --- a/libsolidity/interface/Natspec.h +++ b/libsolidity/interface/Natspec.h @@ -26,10 +26,10 @@ #pragma once -#include +#include +#include #include #include -#include namespace solidity::frontend { @@ -46,32 +46,32 @@ class Natspec /// Get the User documentation of the contract /// @param _contractDef The contract definition /// @return A JSON representation of the contract's user documentation - static Json::Value userDocumentation(ContractDefinition const& _contractDef); + static Json userDocumentation(ContractDefinition const& _contractDef); /// Generates the Developer's documentation of the contract /// @param _contractDef The contract definition /// @return A JSON representation /// of the contract's developer documentation - static Json::Value devDocumentation(ContractDefinition const& _contractDef); + static Json devDocumentation(ContractDefinition const& _contractDef); private: /// @returns concatenation of all content under the given tag name. static std::string extractDoc(std::multimap const& _tags, std::string const& _name); /// Extract all custom tags from @a _tags. - static Json::Value extractCustomDoc(std::multimap const& _tags); + static Json extractCustomDoc(std::multimap const& _tags); /// Helper-function that will create a json object with dev specific annotations, if present. /// @param _tags docTags that are used. /// @return A JSON representation /// of the contract's developer documentation - static Json::Value devDocumentation(std::multimap const& _tags); + static Json devDocumentation(std::multimap const& _tags); /// Helper-function that will create a json object for the "returns" field for a given function definition. /// @param _tags docTags that are used. /// @param _returnParameterNames names of the return parameters /// @return A JSON representation /// of a method's return notice documentation - static Json::Value extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames); + static Json extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames); /// Temporary function until https://github.com/ethereum/solidity/issues/11114 is implemented. /// @return all events defined in the contract and its base contracts and all events diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 1f7b3fa758b8..a54a9aa10720 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -54,64 +54,64 @@ using namespace std::string_literals; namespace { -Json::Value formatError( +Json formatError( Error::Type _type, std::string const& _component, std::string const& _message, std::string const& _formattedMessage = "", - Json::Value const& _sourceLocation = Json::Value(), - Json::Value const& _secondarySourceLocation = Json::Value() + Json const& _sourceLocation = Json(), + Json const& _secondarySourceLocation = Json() ) { - Json::Value error{Json::objectValue}; + Json error; error["type"] = Error::formatErrorType(_type); error["component"] = _component; error["severity"] = Error::formatErrorSeverityLowercase(Error::errorSeverity(_type)); error["message"] = _message; error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message; - if (_sourceLocation.isObject()) + if (_sourceLocation.is_object()) error["sourceLocation"] = _sourceLocation; - if (_secondarySourceLocation.isArray()) + if (_secondarySourceLocation.is_array()) error["secondarySourceLocations"] = _secondarySourceLocation; return error; } -Json::Value formatFatalError(Error::Type _type, std::string const& _message) +Json formatFatalError(Error::Type _type, std::string const& _message) { - Json::Value output{Json::objectValue}; - output["errors"] = Json::arrayValue; - output["errors"].append(formatError(_type, "general", _message)); + Json output; + output["errors"] = Json::array(); + output["errors"].emplace_back(formatError(_type, "general", _message)); return output; } -Json::Value formatSourceLocation(SourceLocation const* location) +Json formatSourceLocation(SourceLocation const* location) { if (!location || !location->sourceName) - return Json::nullValue; + return Json(); - Json::Value sourceLocation{Json::objectValue}; + Json sourceLocation; sourceLocation["file"] = *location->sourceName; sourceLocation["start"] = location->start; sourceLocation["end"] = location->end; return sourceLocation; } -Json::Value formatSecondarySourceLocation(SecondarySourceLocation const* _secondaryLocation) +Json formatSecondarySourceLocation(SecondarySourceLocation const* _secondaryLocation) { if (!_secondaryLocation) - return Json::nullValue; + return Json(); - Json::Value secondarySourceLocation{Json::arrayValue}; + Json secondarySourceLocation = Json::array(); for (auto const& location: _secondaryLocation->infos) { - Json::Value msg = formatSourceLocation(&location.second); + Json msg = formatSourceLocation(&location.second); msg["message"] = location.first; - secondarySourceLocation.append(msg); + secondarySourceLocation.emplace_back(msg); } return secondarySourceLocation; } -Json::Value formatErrorWithException( +Json formatErrorWithException( CharStreamProvider const& _charStreamProvider, util::Exception const& _exception, Error::Type _type, @@ -134,7 +134,7 @@ Json::Value formatErrorWithException( else message = _message; - Json::Value error = formatError( + Json error = formatError( _type, _component, message, @@ -149,13 +149,13 @@ Json::Value formatErrorWithException( return error; } -std::map> requestedContractNames(Json::Value const& _outputSelection) +std::map> requestedContractNames(Json const& _outputSelection) { std::map> contracts; - for (auto const& sourceName: _outputSelection.getMemberNames()) + for (auto const& [sourceName, _]: _outputSelection.items()) { std::string key = (sourceName == "*") ? "" : sourceName; - for (auto const& contractName: _outputSelection[sourceName].getMemberNames()) + for (auto const& [contractName, _]: _outputSelection[sourceName].items()) { std::string value = (contractName == "*") ? "" : contractName; contracts[key].insert(value); @@ -177,12 +177,12 @@ bool hashMatchesContent(std::string const& _hash, std::string const& _content) } } -bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) +bool isArtifactRequested(Json const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) { static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst"}; for (auto const& selectedArtifactJson: _outputSelection) { - std::string const& selectedArtifact = selectedArtifactJson.asString(); + std::string const& selectedArtifact = selectedArtifactJson.get(); if ( _artifact == selectedArtifact || boost::algorithm::starts_with(_artifact, selectedArtifact + ".") @@ -211,13 +211,13 @@ bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& /// /// @TODO optimise this. Perhaps flatten the structure upfront. /// -bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _file, std::string const& _contract, std::string const& _artifact, bool _wildcardMatchesExperimental) +bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, std::string const& _contract, std::string const& _artifact, bool _wildcardMatchesExperimental) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; for (auto const& file: { _file, std::string("*") }) - if (_outputSelection.isMember(file) && _outputSelection[file].isObject()) + if (_outputSelection.contains(file) && _outputSelection[file].is_object()) { /// For SourceUnit-level targets (such as AST) only allow empty name, otherwise /// for Contract-level targets try both contract name and wildcard @@ -226,8 +226,8 @@ bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& contracts.emplace_back("*"); for (auto const& contract: contracts) if ( - _outputSelection[file].isMember(contract) && - _outputSelection[file][contract].isArray() && + _outputSelection[file].contains(contract) && + _outputSelection[file][contract].is_array() && isArtifactRequested(_outputSelection[file][contract], _artifact, _wildcardMatchesExperimental) ) return true; @@ -236,7 +236,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& return false; } -bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _file, std::string const& _contract, std::vector const& _artifacts, bool _wildcardMatchesExperimental) +bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, std::string const& _contract, std::vector const& _artifacts, bool _wildcardMatchesExperimental) { for (auto const& artifact: _artifacts) if (isArtifactRequested(_outputSelection, _file, _contract, artifact, _wildcardMatchesExperimental)) @@ -255,9 +255,9 @@ std::vector evmObjectComponents(std::string const& _objectKind) } /// @returns true if any binary was requested, i.e. we actually have to perform compilation. -bool isBinaryRequested(Json::Value const& _outputSelection) +bool isBinaryRequested(Json const& _outputSelection) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; // This does not include "evm.methodIdentifiers" on purpose! @@ -276,9 +276,9 @@ bool isBinaryRequested(Json::Value const& _outputSelection) } /// @returns true if EVM bytecode was requested, i.e. we have to run the old code generator. -bool isEvmBytecodeRequested(Json::Value const& _outputSelection) +bool isEvmBytecodeRequested(Json const& _outputSelection) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; static std::vector const outputsThatRequireEvmBinaries = std::vector{ @@ -296,9 +296,9 @@ bool isEvmBytecodeRequested(Json::Value const& _outputSelection) /// @returns true if any Yul IR was requested. Note that as an exception, '*' does not /// yet match "ir", "irAst", "irOptimized" or "irOptimizedAst" -bool isIRRequested(Json::Value const& _outputSelection) +bool isIRRequested(Json const& _outputSelection) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; for (auto const& fileRequests: _outputSelection) @@ -315,9 +315,9 @@ bool isIRRequested(Json::Value const& _outputSelection) return false; } -Json::Value formatLinkReferences(std::map const& linkReferences) +Json formatLinkReferences(std::map const& linkReferences) { - Json::Value ret{Json::objectValue}; + Json ret = Json::object(); for (auto const& ref: linkReferences) { @@ -329,14 +329,14 @@ Json::Value formatLinkReferences(std::map const& linkRefere std::string file = (colon != std::string::npos ? fullname.substr(0, colon) : ""); std::string name = (colon != std::string::npos ? fullname.substr(colon + 1) : fullname); - Json::Value fileObject = ret.get(file, Json::objectValue); - Json::Value libraryArray = fileObject.get(name, Json::arrayValue); + Json fileObject = ret.value(file, Json::object()); + Json libraryArray = fileObject.value(name, Json::array()); - Json::Value entry{Json::objectValue}; - entry["start"] = Json::UInt(ref.first); + Json entry; + entry["start"] = Json(ref.first); entry["length"] = 20; - libraryArray.append(entry); + libraryArray.emplace_back(entry); fileObject[name] = libraryArray; ret[file] = fileObject; } @@ -344,20 +344,20 @@ Json::Value formatLinkReferences(std::map const& linkRefere return ret; } -Json::Value formatImmutableReferences(std::map>> const& _immutableReferences) +Json formatImmutableReferences(std::map>> const& _immutableReferences) { - Json::Value ret{Json::objectValue}; + Json ret = Json::object(); for (auto const& immutableReference: _immutableReferences) { auto const& [identifier, byteOffsets] = immutableReference.second; - Json::Value array(Json::arrayValue); + Json array = Json::array(); for (size_t byteOffset: byteOffsets) { - Json::Value byteRange{Json::objectValue}; - byteRange["start"] = Json::UInt(byteOffset); - byteRange["length"] = Json::UInt(32); // immutable references are currently always 32 bytes wide - array.append(byteRange); + Json byteRange; + byteRange["start"] = Json::number_unsigned_t(byteOffset); + byteRange["length"] = Json::number_unsigned_t(32); // immutable references are currently always 32 bytes wide + array.emplace_back(byteRange); } ret[identifier] = array; } @@ -365,16 +365,16 @@ Json::Value formatImmutableReferences(std::map const& _artifactRequested ) { - Json::Value output{Json::objectValue}; + Json output; if (_artifactRequested("object")) output["object"] = _object.toHex(); if (_artifactRequested("opcodes")) @@ -392,78 +392,78 @@ Json::Value collectEVMObject( return output; } -std::optional checkKeys(Json::Value const& _input, std::set const& _keys, std::string const& _name) +std::optional checkKeys(Json const& _input, std::set const& _keys, std::string const& _name) { - if (!!_input && !_input.isObject()) + if (!_input.empty() && !_input.is_object()) return formatFatalError(Error::Type::JSONError, "\"" + _name + "\" must be an object"); - for (auto const& member: _input.getMemberNames()) + for (auto const& [member, _]: _input.items()) if (!_keys.count(member)) return formatFatalError(Error::Type::JSONError, "Unknown key \"" + member + "\""); return std::nullopt; } -std::optional checkRootKeys(Json::Value const& _input) +std::optional checkRootKeys(Json const& _input) { static std::set keys{"auxiliaryInput", "language", "settings", "sources"}; return checkKeys(_input, keys, "root"); } -std::optional checkSourceKeys(Json::Value const& _input, std::string const& _name) +std::optional checkSourceKeys(Json const& _input, std::string const& _name) { static std::set keys{"content", "keccak256", "urls"}; return checkKeys(_input, keys, "sources." + _name); } -std::optional checkAuxiliaryInputKeys(Json::Value const& _input) +std::optional checkAuxiliaryInputKeys(Json const& _input) { static std::set keys{"smtlib2responses"}; return checkKeys(_input, keys, "auxiliaryInput"); } -std::optional checkSettingsKeys(Json::Value const& _input) +std::optional checkSettingsKeys(Json const& _input) { static std::set keys{"debug", "evmVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; return checkKeys(_input, keys, "settings"); } -std::optional checkModelCheckerSettingsKeys(Json::Value const& _input) +std::optional checkModelCheckerSettingsKeys(Json const& _input) { static std::set keys{"bmcLoopIterations", "contracts", "divModNoSlacks", "engine", "extCalls", "invariants", "printQuery", "showProvedSafe", "showUnproved", "showUnsupported", "solvers", "targets", "timeout"}; return checkKeys(_input, keys, "modelChecker"); } -std::optional checkOptimizerKeys(Json::Value const& _input) +std::optional checkOptimizerKeys(Json const& _input) { static std::set keys{"details", "enabled", "runs"}; return checkKeys(_input, keys, "settings.optimizer"); } -std::optional checkOptimizerDetailsKeys(Json::Value const& _input) +std::optional checkOptimizerDetailsKeys(Json const& _input) { static std::set keys{"peephole", "inliner", "jumpdestRemover", "orderLiterals", "deduplicate", "cse", "constantOptimizer", "yul", "yulDetails", "simpleCounterForLoopUncheckedIncrement"}; return checkKeys(_input, keys, "settings.optimizer.details"); } -std::optional checkOptimizerDetail(Json::Value const& _details, std::string const& _name, bool& _setting) +std::optional checkOptimizerDetail(Json const& _details, std::string const& _name, bool& _setting) { - if (_details.isMember(_name)) + if (_details.contains(_name)) { - if (!_details[_name].isBool()) + if (!_details[_name].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.optimizer.details." + _name + "\" must be Boolean"); - _setting = _details[_name].asBool(); + _setting = _details[_name].get(); } return {}; } -std::optional checkOptimizerDetailSteps(Json::Value const& _details, std::string const& _name, std::string& _optimiserSetting, std::string& _cleanupSetting, bool _runYulOptimizer) +std::optional checkOptimizerDetailSteps(Json const& _details, std::string const& _name, std::string& _optimiserSetting, std::string& _cleanupSetting, bool _runYulOptimizer) { - if (_details.isMember(_name)) + if (_details.contains(_name)) { - if (_details[_name].isString()) + if (_details[_name].is_string()) { - std::string const fullSequence = _details[_name].asString(); + std::string const fullSequence = _details[_name].get(); if (!_runYulOptimizer && !OptimiserSuite::isEmptyOptimizerSequence(fullSequence)) { std::string errorMessage = @@ -474,7 +474,7 @@ std::optional checkOptimizerDetailSteps(Json::Value const& _details try { - yul::OptimiserSuite::validateSequence(_details[_name].asString()); + yul::OptimiserSuite::validateSequence(_details[_name].get()); } catch (yul::OptimizerException const& _exception) { @@ -499,43 +499,39 @@ std::optional checkOptimizerDetailSteps(Json::Value const& _details return {}; } -std::optional checkMetadataKeys(Json::Value const& _input) +std::optional checkMetadataKeys(Json const& _input) { - if (_input.isObject()) + if (_input.is_object()) { - if (_input.isMember("appendCBOR") && !_input["appendCBOR"].isBool()) + if (_input.contains("appendCBOR") && !_input["appendCBOR"].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.metadata.appendCBOR\" must be Boolean"); - if (_input.isMember("useLiteralContent") && !_input["useLiteralContent"].isBool()) + if (_input.contains("useLiteralContent") && !_input["useLiteralContent"].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.metadata.useLiteralContent\" must be Boolean"); static std::set hashes{"ipfs", "bzzr1", "none"}; - if (_input.isMember("bytecodeHash") && !hashes.count(_input["bytecodeHash"].asString())) + if (_input.contains("bytecodeHash") && !hashes.count(_input["bytecodeHash"].get())) return formatFatalError(Error::Type::JSONError, "\"settings.metadata.bytecodeHash\" must be \"ipfs\", \"bzzr1\" or \"none\""); } static std::set keys{"appendCBOR", "useLiteralContent", "bytecodeHash"}; return checkKeys(_input, keys, "settings.metadata"); } -std::optional checkOutputSelection(Json::Value const& _outputSelection) +std::optional checkOutputSelection(Json const& _outputSelection) { - if (!!_outputSelection && !_outputSelection.isObject()) + if (!_outputSelection.empty() && !_outputSelection.is_object()) return formatFatalError(Error::Type::JSONError, "\"settings.outputSelection\" must be an object"); - for (auto const& sourceName: _outputSelection.getMemberNames()) + for (auto const& [sourceName, sourceVal]: _outputSelection.items()) { - auto const& sourceVal = _outputSelection[sourceName]; - - if (!sourceVal.isObject()) + if (!sourceVal.is_object()) return formatFatalError( Error::Type::JSONError, "\"settings.outputSelection." + sourceName + "\" must be an object" ); - for (auto const& contractName: sourceVal.getMemberNames()) + for (auto const& [contractName, contractVal]: sourceVal.items()) { - auto const& contractVal = sourceVal[contractName]; - - if (!contractVal.isArray()) + if (!contractVal.is_array()) return formatFatalError( Error::Type::JSONError, "\"settings.outputSelection." + @@ -546,7 +542,7 @@ std::optional checkOutputSelection(Json::Value const& _outputSelect ); for (auto const& output: contractVal) - if (!output.isString()) + if (!output.is_string()) return formatFatalError( Error::Type::JSONError, "\"settings.outputSelection." + @@ -563,32 +559,32 @@ std::optional checkOutputSelection(Json::Value const& _outputSelect /// Validates the optimizer settings and returns them in a parsed object. /// On error returns the json-formatted error message. -std::variant parseOptimizerSettings(Json::Value const& _jsonInput) +std::variant parseOptimizerSettings(Json const& _jsonInput) { if (auto result = checkOptimizerKeys(_jsonInput)) return *result; OptimiserSettings settings = OptimiserSettings::minimal(); - if (_jsonInput.isMember("enabled")) + if (_jsonInput.contains("enabled")) { - if (!_jsonInput["enabled"].isBool()) + if (!_jsonInput["enabled"].is_boolean()) return formatFatalError(Error::Type::JSONError, "The \"enabled\" setting must be a Boolean."); - if (_jsonInput["enabled"].asBool()) + if (_jsonInput["enabled"].get()) settings = OptimiserSettings::standard(); } - if (_jsonInput.isMember("runs")) + if (_jsonInput.contains("runs")) { - if (!_jsonInput["runs"].isUInt()) + if (!_jsonInput["runs"].is_number_unsigned()) return formatFatalError(Error::Type::JSONError, "The \"runs\" setting must be an unsigned number."); - settings.expectedExecutionsPerDeployment = _jsonInput["runs"].asUInt(); + settings.expectedExecutionsPerDeployment = _jsonInput["runs"].get(); } - if (_jsonInput.isMember("details")) + if (_jsonInput.contains("details")) { - Json::Value const& details = _jsonInput["details"]; + Json const& details = _jsonInput["details"]; if (auto result = checkOptimizerDetailsKeys(details)) return *result; @@ -611,7 +607,7 @@ std::variant parseOptimizerSettings(Json::Value if (auto error = checkOptimizerDetail(details, "simpleCounterForLoopUncheckedIncrement", settings.simpleCounterForLoopUncheckedIncrement)) return *error; settings.optimizeStackAllocation = settings.runYulOptimiser; - if (details.isMember("yulDetails")) + if (details.contains("yulDetails")) { if (!settings.runYulOptimiser) { @@ -635,45 +631,46 @@ std::variant parseOptimizerSettings(Json::Value } -std::variant StandardCompiler::parseInput(Json::Value const& _input) +std::variant StandardCompiler::parseInput(Json const& _input) { InputsAndSettings ret; - if (!_input.isObject()) + if (!_input.is_object()) return formatFatalError(Error::Type::JSONError, "Input is not a JSON object."); if (auto result = checkRootKeys(_input)) return *result; - ret.language = _input["language"].asString(); + ret.language = _input.value("language", ""); - Json::Value const& sources = _input["sources"]; + Json const& sources = _input.value("sources", Json()); - if (!sources.isObject() && !sources.isNull()) + if (!sources.is_object() && !sources.is_null()) return formatFatalError(Error::Type::JSONError, "\"sources\" is not a JSON object."); if (sources.empty()) return formatFatalError(Error::Type::JSONError, "No input sources specified."); - ret.errors = Json::arrayValue; + ret.errors = Json::array(); + ret.sources = Json::object(); if (ret.language == "Solidity" || ret.language == "Yul") { - for (auto const& sourceName: sources.getMemberNames()) + for (auto const& [sourceName, sourceValue]: sources.items()) { std::string hash; - if (auto result = checkSourceKeys(sources[sourceName], sourceName)) + if (auto result = checkSourceKeys(sourceValue, sourceName)) return *result; - if (sources[sourceName]["keccak256"].isString()) - hash = sources[sourceName]["keccak256"].asString(); + if (sourceValue.contains("keccak256") && sourceValue["keccak256"].is_string()) + hash = sourceValue["keccak256"].get(); - if (sources[sourceName]["content"].isString()) + if (sourceValue.contains("content") && sourceValue["content"].is_string()) { - std::string content = sources[sourceName]["content"].asString(); + std::string content = sourceValue["content"].get(); if (!hash.empty() && !hashMatchesContent(hash, content)) - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( Error::Type::IOError, "general", "Mismatch between content and supplied hash for \"" + sourceName + "\"" @@ -681,7 +678,7 @@ std::variant StandardCompiler: else ret.sources[sourceName] = content; } - else if (sources[sourceName]["urls"].isArray()) + else if (sourceValue["urls"].is_array()) { if (!m_readFile) return formatFatalError( @@ -691,18 +688,18 @@ std::variant StandardCompiler: std::vector failures; bool found = false; - for (auto const& url: sources[sourceName]["urls"]) + for (auto const& url: sourceValue["urls"]) { - if (!url.isString()) + if (!url.is_string()) return formatFatalError(Error::Type::JSONError, "URL must be a string."); - ReadCallback::Result result = m_readFile(ReadCallback::kindString(ReadCallback::Kind::ReadFile), url.asString()); + ReadCallback::Result result = m_readFile(ReadCallback::kindString(ReadCallback::Kind::ReadFile), url.get()); if (result.success) { if (!hash.empty() && !hashMatchesContent(hash, result.responseOrErrorMessage)) - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( Error::Type::IOError, "general", - "Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.asString() + "\"" + "Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.get() + "\"" )); else { @@ -713,14 +710,14 @@ std::variant StandardCompiler: } else failures.push_back( - "Cannot import url (\"" + url.asString() + "\"): " + result.responseOrErrorMessage + "Cannot import url (\"" + url.get() + "\"): " + result.responseOrErrorMessage ); } for (auto const& failure: failures) { /// If the import succeeded, let mark all the others as warnings, otherwise all of them are errors. - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( found ? Error::Type::Warning : Error::Type::IOError, "general", failure @@ -733,25 +730,25 @@ std::variant StandardCompiler: } else if (ret.language == "SolidityAST") { - for (auto const& sourceName: sources.getMemberNames()) - ret.sources[sourceName] = util::jsonCompactPrint(sources[sourceName]); + for (auto const& [sourceName, sourceValue]: sources.items()) + ret.sources[sourceName] = util::jsonCompactPrint(sourceValue); } else if (ret.language == "EVMAssembly") { - for (std::string const& sourceName: sources.getMemberNames()) + for (auto const& [sourceName, sourceValue]: sources.items()) { - solAssert(sources.isMember(sourceName)); + solAssert(sources.contains(sourceName)); if ( - !sources[sourceName].isMember("assemblyJson") || - !sources[sourceName]["assemblyJson"].isObject() || - sources[sourceName].size() != 1 + !sourceValue.contains("assemblyJson") || + !sourceValue["assemblyJson"].is_object() || + sourceValue.size() != 1 ) return formatFatalError( Error::Type::JSONError, "Invalid input source specified. Expected exactly one object, named 'assemblyJson', inside $.sources." + sourceName ); - ret.jsonSources[sourceName] = sources[sourceName]["assemblyJson"]; + ret.jsonSources[sourceName] = sourceValue["assemblyJson"]; } if (ret.jsonSources.size() != 1) return formatFatalError( @@ -759,20 +756,20 @@ std::variant StandardCompiler: "EVMAssembly import only supports exactly one input file." ); } - Json::Value const& auxInputs = _input["auxiliaryInput"]; + Json const& auxInputs = _input.value("auxiliaryInput", Json::object()); if (auto result = checkAuxiliaryInputKeys(auxInputs)) return *result; - if (!!auxInputs) + if (!auxInputs.empty()) { - Json::Value const& smtlib2Responses = auxInputs["smtlib2responses"]; - if (!!smtlib2Responses) + Json const& smtlib2Responses = auxInputs.value("smtlib2responses", Json::object()); + if (!smtlib2Responses.empty()) { - if (!smtlib2Responses.isObject()) + if (!smtlib2Responses.is_object()) return formatFatalError(Error::Type::JSONError, "\"auxiliaryInput.smtlib2responses\" must be an object."); - for (auto const& hashString: smtlib2Responses.getMemberNames()) + for (auto const& [hashString, response]: smtlib2Responses.items()) { util::h256 hash; try @@ -784,49 +781,49 @@ std::variant StandardCompiler: return formatFatalError(Error::Type::JSONError, "Invalid hex encoding of SMTLib2 auxiliary input."); } - if (!smtlib2Responses[hashString].isString()) + if (!response.is_string()) return formatFatalError( Error::Type::JSONError, "\"smtlib2Responses." + hashString + "\" must be a string." ); - ret.smtLib2Responses[hash] = smtlib2Responses[hashString].asString(); + ret.smtLib2Responses[hash] = response.get(); } } } - Json::Value const& settings = _input.get("settings", Json::Value()); + Json const& settings = _input.value("settings", Json::object()); if (auto result = checkSettingsKeys(settings)) return *result; - if (settings.isMember("stopAfter")) + if (settings.contains("stopAfter")) { - if (!settings["stopAfter"].isString()) + if (!settings["stopAfter"].is_string()) return formatFatalError(Error::Type::JSONError, "\"settings.stopAfter\" must be a string."); - if (settings["stopAfter"].asString() != "parsing") + if (settings["stopAfter"].get() != "parsing") return formatFatalError(Error::Type::JSONError, "Invalid value for \"settings.stopAfter\". Only valid value is \"parsing\"."); ret.stopAfter = CompilerStack::State::Parsed; } - if (settings.isMember("viaIR")) + if (settings.contains("viaIR")) { - if (!settings["viaIR"].isBool()) + if (!settings["viaIR"].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.viaIR\" must be a Boolean."); - ret.viaIR = settings["viaIR"].asBool(); + ret.viaIR = settings["viaIR"].get(); } - if (settings.isMember("evmVersion")) + if (settings.contains("evmVersion")) { - if (!settings["evmVersion"].isString()) + if (!settings["evmVersion"].is_string()) return formatFatalError(Error::Type::JSONError, "evmVersion must be a string."); - std::optional version = langutil::EVMVersion::fromString(settings["evmVersion"].asString()); + std::optional version = langutil::EVMVersion::fromString(settings["evmVersion"].get()); if (!version) return formatFatalError(Error::Type::JSONError, "Invalid EVM version requested."); if (version < EVMVersion::constantinople()) - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( Error::Type::Warning, "general", "Support for EVM versions older than constantinople is deprecated and will be removed in the future." @@ -834,26 +831,26 @@ std::variant StandardCompiler: ret.evmVersion = *version; } - if (settings.isMember("eofVersion")) + if (settings.contains("eofVersion")) { - if (!settings["eofVersion"].isUInt()) + if (!settings["eofVersion"].is_number_unsigned()) return formatFatalError(Error::Type::JSONError, "eofVersion must be an unsigned integer."); - auto eofVersion = settings["evmVersion"].asUInt(); + auto eofVersion = settings["evmVersion"].get(); if (eofVersion != 1) return formatFatalError(Error::Type::JSONError, "Invalid EOF version requested."); ret.eofVersion = 1; } - if (settings.isMember("debug")) + if (settings.contains("debug")) { if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug")) return *result; - if (settings["debug"].isMember("revertStrings")) + if (settings["debug"].contains("revertStrings")) { - if (!settings["debug"]["revertStrings"].isString()) + if (!settings["debug"]["revertStrings"].is_string()) return formatFatalError(Error::Type::JSONError, "settings.debug.revertStrings must be a string."); - std::optional revertStrings = revertStringsFromString(settings["debug"]["revertStrings"].asString()); + std::optional revertStrings = revertStringsFromString(settings["debug"]["revertStrings"].get()); if (!revertStrings) return formatFatalError(Error::Type::JSONError, "Invalid value for settings.debug.revertStrings."); if (*revertStrings == RevertStrings::VerboseDebug) @@ -864,14 +861,14 @@ std::variant StandardCompiler: ret.revertStrings = *revertStrings; } - if (settings["debug"].isMember("debugInfo")) + if (settings["debug"].contains("debugInfo")) { - if (!settings["debug"]["debugInfo"].isArray()) + if (!settings["debug"]["debugInfo"].is_array()) return formatFatalError(Error::Type::JSONError, "settings.debug.debugInfo must be an array."); std::vector components; - for (Json::Value const& arrayValue: settings["debug"]["debugInfo"]) - components.push_back(arrayValue.asString()); + for (Json const& arrayValue: settings["debug"]["debugInfo"]) + components.push_back(arrayValue.get()); std::optional debugInfoSelection = DebugInfoSelection::fromComponents( components, @@ -890,41 +887,40 @@ std::variant StandardCompiler: } } - if (settings.isMember("remappings") && !settings["remappings"].isArray()) + if (settings.contains("remappings") && !settings["remappings"].is_array()) return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings."); - for (auto const& remapping: settings.get("remappings", Json::Value())) + for (auto const& remapping: settings.value("remappings", Json::object())) { - if (!remapping.isString()) + if (!remapping.is_string()) return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings"); - if (auto r = ImportRemapper::parseRemapping(remapping.asString())) + if (auto r = ImportRemapper::parseRemapping(remapping.get())) ret.remappings.emplace_back(std::move(*r)); else - return formatFatalError(Error::Type::JSONError, "Invalid remapping: \"" + remapping.asString() + "\""); + return formatFatalError(Error::Type::JSONError, "Invalid remapping: \"" + remapping.get() + "\""); } - if (settings.isMember("optimizer")) + if (settings.contains("optimizer")) { auto optimiserSettings = parseOptimizerSettings(settings["optimizer"]); - if (std::holds_alternative(optimiserSettings)) - return std::get(std::move(optimiserSettings)); // was an error + if (std::holds_alternative(optimiserSettings)) + return std::get(std::move(optimiserSettings)); // was an error else ret.optimiserSettings = std::get(std::move(optimiserSettings)); } - Json::Value jsonLibraries = settings.get("libraries", Json::Value(Json::objectValue)); - if (!jsonLibraries.isObject()) + Json const& jsonLibraries = settings.value("libraries", Json::object()); + if (!jsonLibraries.is_object()) return formatFatalError(Error::Type::JSONError, "\"libraries\" is not a JSON object."); - for (auto const& sourceName: jsonLibraries.getMemberNames()) + for (auto const& [sourceName, jsonSourceName]: jsonLibraries.items()) { - auto const& jsonSourceName = jsonLibraries[sourceName]; - if (!jsonSourceName.isObject()) + if (!jsonSourceName.is_object()) return formatFatalError(Error::Type::JSONError, "Library entry is not a JSON object."); - for (auto const& library: jsonSourceName.getMemberNames()) + for (auto const& [library, libraryValue]: jsonSourceName.items()) { - if (!jsonSourceName[library].isString()) + if (!libraryValue.is_string()) return formatFatalError(Error::Type::JSONError, "Library address must be a string."); - std::string address = jsonSourceName[library].asString(); + std::string address = libraryValue.get(); if (!boost::starts_with(address, "0x")) return formatFatalError( @@ -952,21 +948,24 @@ std::variant StandardCompiler: } } - Json::Value metadataSettings = settings.get("metadata", Json::Value()); + Json const& metadataSettings = settings.value("metadata", Json::object()); if (auto result = checkMetadataKeys(metadataSettings)) return *result; solAssert(CompilerStack::defaultMetadataFormat() != CompilerStack::MetadataFormat::NoMetadata, ""); ret.metadataFormat = - metadataSettings.get("appendCBOR", Json::Value(true)).asBool() ? + metadataSettings.value("appendCBOR", Json(true)) ? CompilerStack::defaultMetadataFormat() : CompilerStack::MetadataFormat::NoMetadata; - ret.metadataLiteralSources = metadataSettings.get("useLiteralContent", Json::Value(false)).asBool(); - if (metadataSettings.isMember("bytecodeHash")) + ret.metadataLiteralSources = + metadataSettings.contains("useLiteralContent") && + metadataSettings["useLiteralContent"].is_boolean() && + metadataSettings["useLiteralContent"].get(); + if (metadataSettings.contains("bytecodeHash")) { - auto metadataHash = metadataSettings["bytecodeHash"].asString(); + auto metadataHash = metadataSettings["bytecodeHash"].get(); ret.metadataHash = metadataHash == "ipfs" ? CompilerStack::MetadataHash::IPFS : @@ -982,12 +981,12 @@ std::variant StandardCompiler: ); } - Json::Value outputSelection = settings.get("outputSelection", Json::Value()); + Json const& outputSelection = settings.value("outputSelection", Json::object()); if (auto jsonError = checkOutputSelection(outputSelection)) return *jsonError; - ret.outputSelection = std::move(outputSelection); + ret.outputSelection = outputSelection; if (ret.stopAfter != CompilerStack::State::CompilationSuccessful && isBinaryRequested(ret.outputSelection)) return formatFatalError( @@ -995,34 +994,33 @@ std::variant StandardCompiler: "Requested output selection conflicts with \"settings.stopAfter\"." ); - Json::Value const& modelCheckerSettings = settings.get("modelChecker", Json::Value()); + Json const& modelCheckerSettings = settings.value("modelChecker", Json::object()); if (auto result = checkModelCheckerSettingsKeys(modelCheckerSettings)) return *result; - if (modelCheckerSettings.isMember("contracts")) + if (modelCheckerSettings.contains("contracts")) { auto const& sources = modelCheckerSettings["contracts"]; - if (!sources.isObject() && !sources.isNull()) + if (!sources.is_object() && !sources.is_null()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.contracts is not a JSON object."); std::map> sourceContracts; - for (auto const& source: sources.getMemberNames()) + for (auto const& [source, contracts]: sources.items()) { if (source.empty()) return formatFatalError(Error::Type::JSONError, "Source name cannot be empty."); - auto const& contracts = sources[source]; - if (!contracts.isArray()) + if (!contracts.is_array()) return formatFatalError(Error::Type::JSONError, "Source contracts must be an array."); for (auto const& contract: contracts) { - if (!contract.isString()) + if (!contract.is_string()) return formatFatalError(Error::Type::JSONError, "Every contract in settings.modelChecker.contracts must be a string."); - if (contract.asString().empty()) + if (contract.get().empty()) return formatFatalError(Error::Type::JSONError, "Contract name cannot be empty."); - sourceContracts[source].insert(contract.asString()); + sourceContracts[source].insert(contract.get()); } if (sourceContracts[source].empty()) @@ -1031,56 +1029,56 @@ std::variant StandardCompiler: ret.modelCheckerSettings.contracts = {std::move(sourceContracts)}; } - if (modelCheckerSettings.isMember("divModNoSlacks")) + if (modelCheckerSettings.contains("divModNoSlacks")) { auto const& divModNoSlacks = modelCheckerSettings["divModNoSlacks"]; - if (!divModNoSlacks.isBool()) + if (!divModNoSlacks.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.divModNoSlacks must be a Boolean."); - ret.modelCheckerSettings.divModNoSlacks = divModNoSlacks.asBool(); + ret.modelCheckerSettings.divModNoSlacks = divModNoSlacks.get(); } - if (modelCheckerSettings.isMember("engine")) + if (modelCheckerSettings.contains("engine")) { - if (!modelCheckerSettings["engine"].isString()) + if (!modelCheckerSettings["engine"].is_string()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.engine must be a string."); - std::optional engine = ModelCheckerEngine::fromString(modelCheckerSettings["engine"].asString()); + std::optional engine = ModelCheckerEngine::fromString(modelCheckerSettings["engine"].get()); if (!engine) return formatFatalError(Error::Type::JSONError, "Invalid model checker engine requested."); ret.modelCheckerSettings.engine = *engine; } - if (modelCheckerSettings.isMember("bmcLoopIterations")) + if (modelCheckerSettings.contains("bmcLoopIterations")) { if (!ret.modelCheckerSettings.engine.bmc) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.bmcLoopIterations requires the BMC engine to be enabled."); - if (modelCheckerSettings["bmcLoopIterations"].isUInt()) - ret.modelCheckerSettings.bmcLoopIterations = modelCheckerSettings["bmcLoopIterations"].asUInt(); + if (modelCheckerSettings["bmcLoopIterations"].is_number_unsigned()) + ret.modelCheckerSettings.bmcLoopIterations = modelCheckerSettings["bmcLoopIterations"].get(); else return formatFatalError(Error::Type::JSONError, "settings.modelChecker.bmcLoopIterations must be an unsigned integer."); } - if (modelCheckerSettings.isMember("extCalls")) + if (modelCheckerSettings.contains("extCalls")) { - if (!modelCheckerSettings["extCalls"].isString()) + if (!modelCheckerSettings["extCalls"].is_string()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.extCalls must be a string."); - std::optional extCalls = ModelCheckerExtCalls::fromString(modelCheckerSettings["extCalls"].asString()); + std::optional extCalls = ModelCheckerExtCalls::fromString(modelCheckerSettings["extCalls"].get()); if (!extCalls) return formatFatalError(Error::Type::JSONError, "Invalid model checker extCalls requested."); ret.modelCheckerSettings.externalCalls = *extCalls; } - if (modelCheckerSettings.isMember("invariants")) + if (modelCheckerSettings.contains("invariants")) { auto const& invariantsArray = modelCheckerSettings["invariants"]; - if (!invariantsArray.isArray()) + if (!invariantsArray.is_array()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.invariants must be an array."); ModelCheckerInvariants invariants; for (auto const& i: invariantsArray) { - if (!i.isString()) + if (!i.is_string()) return formatFatalError(Error::Type::JSONError, "Every invariant type in settings.modelChecker.invariants must be a string."); - if (!invariants.setFromString(i.asString())) + if (!invariants.setFromString(i.get())) return formatFatalError(Error::Type::JSONError, "Invalid model checker invariants requested."); } @@ -1090,72 +1088,72 @@ std::variant StandardCompiler: ret.modelCheckerSettings.invariants = invariants; } - if (modelCheckerSettings.isMember("showProvedSafe")) + if (modelCheckerSettings.contains("showProvedSafe")) { auto const& showProvedSafe = modelCheckerSettings["showProvedSafe"]; - if (!showProvedSafe.isBool()) + if (!showProvedSafe.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.showProvedSafe must be a Boolean value."); - ret.modelCheckerSettings.showProvedSafe = showProvedSafe.asBool(); + ret.modelCheckerSettings.showProvedSafe = showProvedSafe.get(); } - if (modelCheckerSettings.isMember("showUnproved")) + if (modelCheckerSettings.contains("showUnproved")) { auto const& showUnproved = modelCheckerSettings["showUnproved"]; - if (!showUnproved.isBool()) + if (!showUnproved.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.showUnproved must be a Boolean value."); - ret.modelCheckerSettings.showUnproved = showUnproved.asBool(); + ret.modelCheckerSettings.showUnproved = showUnproved.get(); } - if (modelCheckerSettings.isMember("showUnsupported")) + if (modelCheckerSettings.contains("showUnsupported")) { auto const& showUnsupported = modelCheckerSettings["showUnsupported"]; - if (!showUnsupported.isBool()) + if (!showUnsupported.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.showUnsupported must be a Boolean value."); - ret.modelCheckerSettings.showUnsupported = showUnsupported.asBool(); + ret.modelCheckerSettings.showUnsupported = showUnsupported.get(); } - if (modelCheckerSettings.isMember("solvers")) + if (modelCheckerSettings.contains("solvers")) { auto const& solversArray = modelCheckerSettings["solvers"]; - if (!solversArray.isArray()) + if (!solversArray.is_array()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.solvers must be an array."); smtutil::SMTSolverChoice solvers; for (auto const& s: solversArray) { - if (!s.isString()) + if (!s.is_string()) return formatFatalError(Error::Type::JSONError, "Every target in settings.modelChecker.solvers must be a string."); - if (!solvers.setSolver(s.asString())) + if (!solvers.setSolver(s.get())) return formatFatalError(Error::Type::JSONError, "Invalid model checker solvers requested."); } ret.modelCheckerSettings.solvers = solvers; } - if (modelCheckerSettings.isMember("printQuery")) + if (modelCheckerSettings.contains("printQuery")) { auto const& printQuery = modelCheckerSettings["printQuery"]; - if (!printQuery.isBool()) + if (!printQuery.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.printQuery must be a Boolean value."); if (!(ret.modelCheckerSettings.solvers == smtutil::SMTSolverChoice::SMTLIB2())) return formatFatalError(Error::Type::JSONError, "Only SMTLib2 solver can be enabled to print queries"); - ret.modelCheckerSettings.printQuery = printQuery.asBool(); + ret.modelCheckerSettings.printQuery = printQuery.get(); } - if (modelCheckerSettings.isMember("targets")) + if (modelCheckerSettings.contains("targets")) { auto const& targetsArray = modelCheckerSettings["targets"]; - if (!targetsArray.isArray()) + if (!targetsArray.is_array()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.targets must be an array."); ModelCheckerTargets targets; for (auto const& t: targetsArray) { - if (!t.isString()) + if (!t.is_string()) return formatFatalError(Error::Type::JSONError, "Every target in settings.modelChecker.targets must be a string."); - if (!targets.setFromString(t.asString())) + if (!targets.setFromString(t.get())) return formatFatalError(Error::Type::JSONError, "Invalid model checker targets requested."); } @@ -1165,45 +1163,45 @@ std::variant StandardCompiler: ret.modelCheckerSettings.targets = targets; } - if (modelCheckerSettings.isMember("timeout")) + if (modelCheckerSettings.contains("timeout")) { - if (!modelCheckerSettings["timeout"].isUInt()) + if (!modelCheckerSettings["timeout"].is_number_unsigned()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.timeout must be an unsigned integer."); - ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].asUInt(); + ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].get(); } return {std::move(ret)}; } -std::map StandardCompiler::parseAstFromInput(StringMap const& _sources) +std::map StandardCompiler::parseAstFromInput(StringMap const& _sources) { - std::map sourceJsons; + std::map sourceJsons; for (auto const& [sourceName, sourceCode]: _sources) { - Json::Value ast; + Json ast; astAssert(util::jsonParseStrict(sourceCode, ast), "Input file could not be parsed to JSON"); - std::string astKey = ast.isMember("ast") ? "ast" : "AST"; + std::string astKey = ast.contains("ast") ? "ast" : "AST"; - astAssert(ast.isMember(astKey), "astkey is not member"); - astAssert(ast[astKey]["nodeType"].asString() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); + astAssert(ast.contains(astKey), "astkey is not member"); + astAssert(ast[astKey]["nodeType"].get() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); astAssert(sourceJsons.count(sourceName) == 0, "All sources must have unique names"); sourceJsons.emplace(sourceName, std::move(ast[astKey])); } return sourceJsons; } -Json::Value StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _inputsAndSettings) +Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _inputsAndSettings) { solAssert(_inputsAndSettings.language == "EVMAssembly"); solAssert(_inputsAndSettings.sources.empty()); solAssert(_inputsAndSettings.jsonSources.size() == 1); if (!isBinaryRequested(_inputsAndSettings.outputSelection)) - return Json::objectValue; + return Json::object(); evmasm::EVMAssemblyStack stack(_inputsAndSettings.evmVersion); std::string const& sourceName = _inputsAndSettings.jsonSources.begin()->first; // result of structured binding can only be used within lambda from C++20 on. - Json::Value const& sourceJson = _inputsAndSettings.jsonSources.begin()->second; + Json const& sourceJson = _inputsAndSettings.jsonSources.begin()->second; try { stack.analyze(sourceName, sourceJson); @@ -1226,11 +1224,11 @@ Json::Value StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSetti ); } if (!stack.compilationSuccessful()) - return Json::objectValue; + return Json::object(); // EVM bool const wildcardMatchesExperimental = false; - Json::Value evmData = Json::objectValue; + Json evmData; if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.assembly", wildcardMatchesExperimental)) evmData["assembly"] = stack.assemblyString(sourceName, {}); if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.legacyAssembly", wildcardMatchesExperimental)) @@ -1284,18 +1282,18 @@ Json::Value StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSetti } ); - Json::Value contractData = Json::objectValue; + Json contractData; if (!evmData.empty()) contractData["evm"] = evmData; - Json::Value contractsOutput = Json::objectValue; + Json contractsOutput; contractsOutput[sourceName][""] = contractData; - Json::Value output = Json::objectValue; + Json output; output["contracts"] = contractsOutput; return util::removeNullMembers(output); } -Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inputsAndSettings) +Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inputsAndSettings) { solAssert(_inputsAndSettings.jsonSources.empty()); @@ -1323,7 +1321,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting compilerStack.enableEvmBytecodeGeneration(isEvmBytecodeRequested(_inputsAndSettings.outputSelection)); compilerStack.enableIRGeneration(isIRRequested(_inputsAndSettings.outputSelection)); - Json::Value errors = std::move(_inputsAndSettings.errors); + Json errors = std::move(_inputsAndSettings.errors); bool const binariesRequested = isBinaryRequested(_inputsAndSettings.outputSelection); @@ -1335,7 +1333,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting { compilerStack.importASTs(parseAstFromInput(sourceList)); if (!compilerStack.analyze()) - errors.append(formatError(Error::Type::FatalError, "general", "Analysis of the AST failed.")); + errors.emplace_back(formatError(Error::Type::FatalError, "general", "Analysis of the AST failed.")); if (binariesRequested) compilerStack.compile(); } @@ -1352,7 +1350,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting compilerStack.parseAndAnalyze(_inputsAndSettings.stopAfter); for (auto const& error: compilerStack.errors()) - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, *error, error->type(), @@ -1365,7 +1363,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting /// This is only thrown in a very few locations. catch (Error const& _error) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _error, _error.type(), @@ -1376,7 +1374,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting /// This should not be leaked from compile(). catch (FatalError const& _exception) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::FatalError, "general", "Uncaught fatal error: " + boost::diagnostic_information(_exception) @@ -1384,7 +1382,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (CompilerError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::CompilerError, @@ -1394,7 +1392,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (InternalCompilerError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::InternalCompilerError, @@ -1404,7 +1402,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (UnimplementedFeatureError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::UnimplementedFeatureError, @@ -1414,7 +1412,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (yul::YulException const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::YulException, @@ -1424,7 +1422,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (smtutil::SMTLogicError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::SMTLogicException, @@ -1434,7 +1432,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (util::Exception const& _exception) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::Exception, "general", "Exception during compilation: " + boost::diagnostic_information(_exception) @@ -1442,7 +1440,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (std::exception const& _exception) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::Exception, "general", "Unknown exception during compilation: " + boost::diagnostic_information(_exception) @@ -1450,7 +1448,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (...) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::Exception, "general", "Unknown exception during compilation: " + boost::current_exception_diagnostic_information() @@ -1473,7 +1471,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting ) return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed."); - Json::Value output = Json::objectValue; + Json output; if (errors.size() > 0) output["errors"] = std::move(errors); @@ -1484,21 +1482,21 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting bool const wildcardMatchesExperimental = false; - output["sources"] = Json::objectValue; + output["sources"] = Json::object(); unsigned sourceIndex = 0; // NOTE: A case that will pass `parsingSuccess && !analysisFailed` but not `analysisSuccess` is // stopAfter: parsing with no parsing errors. if (parsingSuccess && !analysisFailed) for (std::string const& sourceName: compilerStack.sourceNames()) { - Json::Value sourceResult = Json::objectValue; + Json sourceResult; sourceResult["id"] = sourceIndex++; if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "ast", wildcardMatchesExperimental)) sourceResult["ast"] = ASTJsonExporter(compilerStack.state(), compilerStack.sourceIndices()).toJson(compilerStack.ast(sourceName)); output["sources"][sourceName] = sourceResult; } - Json::Value contractsOutput = Json::objectValue; + Json contractsOutput; for (std::string const& contractName: analysisSuccess ? compilerStack.contractNames() : std::vector()) { size_t colon = contractName.rfind(':'); @@ -1507,7 +1505,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting std::string name = contractName.substr(colon + 1); // ABI, storage layout, documentation and metadata - Json::Value contractData(Json::objectValue); + Json contractData; if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "abi", wildcardMatchesExperimental)) contractData["abi"] = compilerStack.contractABI(contractName); if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "storageLayout", false)) @@ -1530,7 +1528,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName); // EVM - Json::Value evmData(Json::objectValue); + Json evmData; if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.assembly", wildcardMatchesExperimental)) evmData["assembly"] = compilerStack.assemblyString(contractName, sourceList); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental)) @@ -1589,8 +1587,8 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting if (!contractData.empty()) { - if (!contractsOutput.isMember(file)) - contractsOutput[file] = Json::objectValue; + if (!contractsOutput.contains(file)) + contractsOutput[file] = Json::object(); contractsOutput[file][name] = contractData; } } @@ -1601,16 +1599,16 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } -Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) +Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) { solAssert(_inputsAndSettings.jsonSources.empty()); - Json::Value output = Json::objectValue; + Json output; output["errors"] = std::move(_inputsAndSettings.errors); if (_inputsAndSettings.sources.size() != 1) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Yul mode only supports exactly one input file." @@ -1619,7 +1617,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) } if (!_inputsAndSettings.smtLib2Responses.empty()) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Yul mode does not support smtlib2responses." @@ -1628,7 +1626,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) } if (!_inputsAndSettings.remappings.empty()) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Field \"settings.remappings\" cannot be used for Yul." @@ -1637,7 +1635,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) } if (_inputsAndSettings.revertStrings != RevertStrings::Default) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Field \"settings.debug.revertStrings\" cannot be used for Yul." @@ -1660,7 +1658,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) // Inconsistent state - stop here to receive error reports from users if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty()) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::InternalCompilerError, "general", "No error reported, but compilation failed." @@ -1674,7 +1672,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) { auto err = std::dynamic_pointer_cast(error); - output["errors"].append(formatErrorWithException( + output["errors"].emplace_back(formatErrorWithException( stack, *error, err->type(), @@ -1693,7 +1691,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental)) { - Json::Value sourceResult = Json::objectValue; + Json sourceResult; sourceResult["id"] = 0; sourceResult["ast"] = stack.astJson(); output["sources"][sourceName] = sourceResult; @@ -1725,7 +1723,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) _inputsAndSettings.evmVersion, *o.bytecode, o.sourceMappings.get(), - Json::arrayValue, + Json::array(), isDeployed, [&, kind = kind](std::string const& _element) { return isArtifactRequested( _inputsAndSettings.outputSelection, @@ -1745,16 +1743,15 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) return output; } - -Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept +Json StandardCompiler::compile(Json const& _input) noexcept { YulStringRepository::reset(); try { auto parsed = parseInput(_input); - if (std::holds_alternative(parsed)) - return std::get(std::move(parsed)); + if (std::holds_alternative(parsed)) + return std::get(std::move(parsed)); InputsAndSettings settings = std::get(std::move(parsed)); if (settings.language == "Solidity") return compileSolidity(std::move(settings)); @@ -1767,13 +1764,29 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept else return formatFatalError(Error::Type::JSONError, "Only \"Solidity\", \"Yul\", \"SolidityAST\" or \"EVMAssembly\" is supported as a language."); } - catch (Json::LogicError const& _exception) + catch (Json::parse_error const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON parse_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::invalid_iterator const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON invalid_iterator exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::type_error const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON type_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::out_of_range const& _exception) { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON logic exception: ") + _exception.what()); + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON out_of_range exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); } - catch (Json::RuntimeError const& _exception) + catch (Json::other_error const& _exception) { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + _exception.what()); + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON other_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::exception const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); } catch (util::Exception const& _exception) { @@ -1787,7 +1800,7 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept std::string StandardCompiler::compile(std::string const& _input) noexcept { - Json::Value input; + Json input; std::string errors; try { @@ -1796,12 +1809,15 @@ std::string StandardCompiler::compile(std::string const& _input) noexcept } catch (...) { - return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error parsing input JSON.\"}]}"; + if (errors.empty()) + return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error parsing input JSON.\"}]}"; + else + return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error parsing input JSON: " + errors + "\"}]}"; } - // cout << "Input: " << input.toStyledString() << endl; - Json::Value output = compile(input); - // cout << "Output: " << output.toStyledString() << endl; +// std::cout << "Input: " << solidity::util::jsonPrettyPrint(input) << std::endl; + Json output = compile(input); +// std::cout << "Output: " << solidity::util::jsonPrettyPrint(output) << std::endl; try { @@ -1813,24 +1829,25 @@ std::string StandardCompiler::compile(std::string const& _input) noexcept } } -Json::Value StandardCompiler::formatFunctionDebugData( +Json StandardCompiler::formatFunctionDebugData( std::map const& _debugInfo ) { - Json::Value ret(Json::objectValue); + static_assert(std::is_same_v); + Json ret = Json::object(); for (auto const& [name, info]: _debugInfo) { - Json::Value fun; + Json fun = Json::object(); if (info.sourceID) - fun["id"] = Json::UInt64(*info.sourceID); + fun["id"] = Json::number_unsigned_t(*info.sourceID); else - fun["id"] = Json::nullValue; + fun["id"] = Json(); if (info.bytecodeOffset) - fun["entryPoint"] = Json::UInt64(*info.bytecodeOffset); + fun["entryPoint"] = Json::number_unsigned_t(*info.bytecodeOffset); else - fun["entryPoint"] = Json::nullValue; - fun["parameterSlots"] = Json::UInt64(info.params); - fun["returnSlots"] = Json::UInt64(info.returns); + fun["entryPoint"] = Json(); + fun["parameterSlots"] = Json::number_unsigned_t(info.params); + fun["returnSlots"] = Json::number_unsigned_t(info.returns); ret[name] = std::move(fun); } diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 03bdc7f12bd2..590d96b9c191 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -58,12 +58,12 @@ class StandardCompiler /// Sets all input parameters according to @a _input which conforms to the standardized input /// format, performs compilation and returns a standardized output. - Json::Value compile(Json::Value const& _input) noexcept; + Json compile(Json const& _input) noexcept; /// Parses input as JSON and performs the above processing steps, returning a serialized JSON /// output. Parsing errors are returned as regular errors. std::string compile(std::string const& _input) noexcept; - static Json::Value formatFunctionDebugData( + static Json formatFunctionDebugData( std::map const& _debugInfo ); @@ -71,10 +71,10 @@ class StandardCompiler struct InputsAndSettings { std::string language; - Json::Value errors; + Json errors; CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful; std::map sources; - std::map jsonSources; + std::map jsonSources; std::map smtLib2Responses; langutil::EVMVersion evmVersion; std::optional eofVersion; @@ -86,19 +86,19 @@ class StandardCompiler bool metadataLiteralSources = false; CompilerStack::MetadataFormat metadataFormat = CompilerStack::defaultMetadataFormat(); CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS; - Json::Value outputSelection; + Json outputSelection; ModelCheckerSettings modelCheckerSettings = ModelCheckerSettings{}; bool viaIR = false; }; /// Parses the input json (and potentially invokes the read callback) and either returns /// it in condensed form or an error as a json object. - std::variant parseInput(Json::Value const& _input); + std::variant parseInput(Json const& _input); - std::map parseAstFromInput(StringMap const& _sources); - Json::Value importEVMAssembly(InputsAndSettings _inputsAndSettings); - Json::Value compileSolidity(InputsAndSettings _inputsAndSettings); - Json::Value compileYul(InputsAndSettings _inputsAndSettings); + std::map parseAstFromInput(StringMap const& _sources); + Json importEVMAssembly(InputsAndSettings _inputsAndSettings); + Json compileSolidity(InputsAndSettings _inputsAndSettings); + Json compileYul(InputsAndSettings _inputsAndSettings); ReadCallback::Callback m_readFile; diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index 8e1d0eed101d..7f344f6edf65 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -23,7 +23,7 @@ using namespace solidity; using namespace solidity::frontend; -Json::Value StorageLayout::generate(ContractDefinition const& _contractDef) +Json StorageLayout::generate(ContractDefinition const& _contractDef) { solAssert(!m_contract, ""); m_contract = &_contractDef; @@ -34,19 +34,19 @@ Json::Value StorageLayout::generate(ContractDefinition const& _contractDef) auto contractType = dynamic_cast(typeType->actualType()); solAssert(contractType, ""); - Json::Value variables(Json::arrayValue); + Json variables = Json::array(); for (auto [var, slot, offset]: contractType->stateVariables()) - variables.append(generate(*var, slot, offset)); + variables.emplace_back(generate(*var, slot, offset)); - Json::Value layout; + Json layout; layout["storage"] = std::move(variables); layout["types"] = std::move(m_types); return layout; } -Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset) +Json StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset) { - Json::Value varEntry; + Json varEntry; Type const* varType = _var.type(); varEntry["label"] = _var.name(); @@ -63,22 +63,22 @@ Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const& void StorageLayout::generate(Type const* _type) { - if (m_types.isMember(typeKeyName(_type))) + if (m_types.contains(typeKeyName(_type))) return; // Register it now to cut recursive visits. - Json::Value& typeInfo = m_types[typeKeyName(_type)]; + Json& typeInfo = m_types[typeKeyName(_type)]; typeInfo["label"] = _type->toString(true); typeInfo["numberOfBytes"] = u256(_type->storageBytes() * _type->storageSize()).str(); if (auto structType = dynamic_cast(_type)) { - Json::Value members(Json::arrayValue); + Json members = Json::array(); auto const& structDef = structType->structDefinition(); for (auto const& member: structDef.members()) { auto const& offsets = structType->storageOffsetsOfMember(member->name()); - members.append(generate(*member, offsets.first, offsets.second)); + members.emplace_back(generate(*member, offsets.first, offsets.second)); } typeInfo["members"] = std::move(members); typeInfo["encoding"] = "inplace"; @@ -108,7 +108,7 @@ void StorageLayout::generate(Type const* _type) typeInfo["encoding"] = "inplace"; } - solAssert(typeInfo.isMember("encoding"), ""); + solAssert(typeInfo.contains("encoding"), ""); } std::string StorageLayout::typeKeyName(Type const* _type) diff --git a/libsolidity/interface/StorageLayout.h b/libsolidity/interface/StorageLayout.h index ffe8e6b5a0c6..b0b2d70b6df5 100644 --- a/libsolidity/interface/StorageLayout.h +++ b/libsolidity/interface/StorageLayout.h @@ -21,11 +21,10 @@ #pragma once +#include #include #include -#include - namespace solidity::frontend { @@ -35,11 +34,11 @@ class StorageLayout /// Generates the storage layout of the contract /// @param _contractDef The contract definition /// @return A JSON representation of the contract's storage layout. - Json::Value generate(ContractDefinition const& _contractDef); + Json generate(ContractDefinition const& _contractDef); private: /// Generates the JSON information for a variable and its storage location. - Json::Value generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset); + Json generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset); /// Generates the JSON information for @param _type void generate(Type const* _type); @@ -47,7 +46,7 @@ class StorageLayout /// The key for the JSON object describing a type. std::string typeKeyName(Type const* _type); - Json::Value m_types; + Json m_types; /// Current analyzed contract ContractDefinition const* m_contract = nullptr; diff --git a/libsolidity/lsp/DocumentHoverHandler.cpp b/libsolidity/lsp/DocumentHoverHandler.cpp index 39d1d72c331c..e5991b765a66 100644 --- a/libsolidity/lsp/DocumentHoverHandler.cpp +++ b/libsolidity/lsp/DocumentHoverHandler.cpp @@ -55,7 +55,7 @@ struct MarkdownBuilder } -void DocumentHoverHandler::operator()(MessageID _id, Json::Value const& _args) +void DocumentHoverHandler::operator()(MessageID _id, Json const& _args) { auto const [sourceUnitName, lineColumn] = HandlerBase(*this).extractSourceUnitNameAndLineColumn(_args); auto const [sourceNode, sourceOffset] = m_server.astNodeAndOffsetAtSourceLocation(sourceUnitName, lineColumn); @@ -108,11 +108,11 @@ void DocumentHoverHandler::operator()(MessageID _id, Json::Value const& _args) if (tooltipText.empty()) { - client().reply(_id, Json::nullValue); + client().reply(_id, Json()); return; } - Json::Value reply = Json::objectValue; + Json reply; reply["range"] = rangeToHighlight; reply["contents"]["kind"] = "markdown"; reply["contents"]["value"] = std::move(tooltipText); diff --git a/libsolidity/lsp/DocumentHoverHandler.h b/libsolidity/lsp/DocumentHoverHandler.h index 9bb4084c261e..e35e856098f0 100644 --- a/libsolidity/lsp/DocumentHoverHandler.h +++ b/libsolidity/lsp/DocumentHoverHandler.h @@ -26,7 +26,7 @@ class DocumentHoverHandler: public HandlerBase public: using HandlerBase::HandlerBase; - void operator()(MessageID, Json::Value const&); + void operator()(MessageID, Json const&); }; } diff --git a/libsolidity/lsp/GotoDefinition.cpp b/libsolidity/lsp/GotoDefinition.cpp index 136e4d7c391b..07b0c6f0be3c 100644 --- a/libsolidity/lsp/GotoDefinition.cpp +++ b/libsolidity/lsp/GotoDefinition.cpp @@ -31,7 +31,7 @@ using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::lsp; -void GotoDefinition::operator()(MessageID _id, Json::Value const& _args) +void GotoDefinition::operator()(MessageID _id, Json const& _args) { auto const [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args); @@ -58,8 +58,8 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args) locations.emplace_back(SourceLocation{0, 0, std::make_shared(path)}); } - Json::Value reply = Json::arrayValue; + Json reply = Json::array(); for (SourceLocation const& location: locations) - reply.append(toJson(location)); + reply.emplace_back(toJson(location)); client().reply(_id, reply); } diff --git a/libsolidity/lsp/GotoDefinition.h b/libsolidity/lsp/GotoDefinition.h index 453da3f1561c..4ffd64e7ff22 100644 --- a/libsolidity/lsp/GotoDefinition.h +++ b/libsolidity/lsp/GotoDefinition.h @@ -25,7 +25,7 @@ class GotoDefinition: public HandlerBase public: explicit GotoDefinition(LanguageServer& _server): HandlerBase(_server) {} - void operator()(MessageID, Json::Value const&); + void operator()(MessageID, Json const&); }; } diff --git a/libsolidity/lsp/HandlerBase.cpp b/libsolidity/lsp/HandlerBase.cpp index a23e43a83ce1..c49bce1dd697 100644 --- a/libsolidity/lsp/HandlerBase.cpp +++ b/libsolidity/lsp/HandlerBase.cpp @@ -29,8 +29,9 @@ using namespace solidity::langutil; using namespace solidity::lsp; using namespace solidity::util; +using namespace solidity; -Json::Value HandlerBase::toRange(SourceLocation const& _location) const +Json HandlerBase::toRange(SourceLocation const& _location) const { if (!_location.hasText()) return toJsonRange({}, {}); @@ -42,18 +43,18 @@ Json::Value HandlerBase::toRange(SourceLocation const& _location) const return toJsonRange(start, end); } -Json::Value HandlerBase::toJson(SourceLocation const& _location) const +Json HandlerBase::toJson(SourceLocation const& _location) const { solAssert(_location.sourceName); - Json::Value item = Json::objectValue; + Json item; item["uri"] = fileRepository().sourceUnitNameToUri(*_location.sourceName); item["range"] = toRange(_location); return item; } -std::pair HandlerBase::extractSourceUnitNameAndLineColumn(Json::Value const& _args) const +std::pair HandlerBase::extractSourceUnitNameAndLineColumn(Json const& _args) const { - std::string const uri = _args["textDocument"]["uri"].asString(); + std::string const uri = _args["textDocument"]["uri"].get(); std::string const sourceUnitName = fileRepository().uriToSourceUnitName(uri); if (!fileRepository().sourceUnits().count(sourceUnitName)) BOOST_THROW_EXCEPTION( diff --git a/libsolidity/lsp/HandlerBase.h b/libsolidity/lsp/HandlerBase.h index e2ccb88d82ec..718d15c5f631 100644 --- a/libsolidity/lsp/HandlerBase.h +++ b/libsolidity/lsp/HandlerBase.h @@ -38,12 +38,12 @@ class HandlerBase public: explicit HandlerBase(LanguageServer& _server): m_server{_server} {} - Json::Value toRange(langutil::SourceLocation const& _location) const; - Json::Value toJson(langutil::SourceLocation const& _location) const; + Json toRange(langutil::SourceLocation const& _location) const; + Json toJson(langutil::SourceLocation const& _location) const; /// @returns source unit name and the line column position as extracted /// from the JSON-RPC parameters. - std::pair extractSourceUnitNameAndLineColumn(Json::Value const& _params) const; + std::pair extractSourceUnitNameAndLineColumn(Json const& _params) const; langutil::CharStreamProvider const& charStreamProvider() const noexcept { return m_server.compilerStack(); } FileRepository& fileRepository() const noexcept { return m_server.fileRepository(); } diff --git a/libsolidity/lsp/LanguageServer.cpp b/libsolidity/lsp/LanguageServer.cpp index 2b8b62706d50..d726139e3a73 100644 --- a/libsolidity/lsp/LanguageServer.cpp +++ b/libsolidity/lsp/LanguageServer.cpp @@ -52,6 +52,7 @@ using namespace std::placeholders; using namespace solidity::lsp; using namespace solidity::langutil; using namespace solidity::frontend; +using namespace solidity; namespace fs = boost::filesystem; @@ -85,44 +86,44 @@ int toDiagnosticSeverity(Error::Type _errorType) return -1; } -Json::Value semanticTokensLegend() +Json semanticTokensLegend() { - Json::Value legend = Json::objectValue; + Json legend; // NOTE! The (alphabetical) order and items must match exactly the items of // their respective enum class members. - Json::Value tokenTypes = Json::arrayValue; - tokenTypes.append("class"); - tokenTypes.append("comment"); - tokenTypes.append("enum"); - tokenTypes.append("enumMember"); - tokenTypes.append("event"); - tokenTypes.append("function"); - tokenTypes.append("interface"); - tokenTypes.append("keyword"); - tokenTypes.append("macro"); - tokenTypes.append("method"); - tokenTypes.append("modifier"); - tokenTypes.append("number"); - tokenTypes.append("operator"); - tokenTypes.append("parameter"); - tokenTypes.append("property"); - tokenTypes.append("std::string"); - tokenTypes.append("struct"); - tokenTypes.append("type"); - tokenTypes.append("typeParameter"); - tokenTypes.append("variable"); + Json tokenTypes = Json::array(); + tokenTypes.emplace_back("class"); + tokenTypes.emplace_back("comment"); + tokenTypes.emplace_back("enum"); + tokenTypes.emplace_back("enumMember"); + tokenTypes.emplace_back("event"); + tokenTypes.emplace_back("function"); + tokenTypes.emplace_back("interface"); + tokenTypes.emplace_back("keyword"); + tokenTypes.emplace_back("macro"); + tokenTypes.emplace_back("method"); + tokenTypes.emplace_back("modifier"); + tokenTypes.emplace_back("number"); + tokenTypes.emplace_back("operator"); + tokenTypes.emplace_back("parameter"); + tokenTypes.emplace_back("property"); + tokenTypes.emplace_back("std::string"); + tokenTypes.emplace_back("struct"); + tokenTypes.emplace_back("type"); + tokenTypes.emplace_back("typeParameter"); + tokenTypes.emplace_back("variable"); legend["tokenTypes"] = tokenTypes; - Json::Value tokenModifiers = Json::arrayValue; - tokenModifiers.append("abstract"); - tokenModifiers.append("declaration"); - tokenModifiers.append("definition"); - tokenModifiers.append("deprecated"); - tokenModifiers.append("documentation"); - tokenModifiers.append("modification"); - tokenModifiers.append("readonly"); + Json tokenModifiers = Json::array(); + tokenModifiers.emplace_back("abstract"); + tokenModifiers.emplace_back("declaration"); + tokenModifiers.emplace_back("definition"); + tokenModifiers.emplace_back("deprecated"); + tokenModifiers.emplace_back("documentation"); + tokenModifiers.emplace_back("modification"); + tokenModifiers.emplace_back("readonly"); legend["tokenModifiers"] = tokenModifiers; return legend; @@ -138,7 +139,7 @@ LanguageServer::LanguageServer(Transport& _transport): {"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }}, {"initialize", std::bind(&LanguageServer::handleInitialize, this, _1, _2)}, {"initialized", std::bind(&LanguageServer::handleInitialized, this, _1, _2)}, - {"$/setTrace", [this](auto, Json::Value const& args) { setTrace(args["value"]); }}, + {"$/setTrace", [this](auto, Json const& args) { setTrace(args["value"]); }}, {"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }}, {"textDocument/definition", GotoDefinition(*this) }, {"textDocument/didOpen", std::bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)}, @@ -155,17 +156,17 @@ LanguageServer::LanguageServer(Transport& _transport): { } -Json::Value LanguageServer::toRange(SourceLocation const& _location) +Json LanguageServer::toRange(SourceLocation const& _location) { return HandlerBase(*this).toRange(_location); } -Json::Value LanguageServer::toJson(SourceLocation const& _location) +Json LanguageServer::toJson(SourceLocation const& _location) { return HandlerBase(*this).toJson(_location); } -void LanguageServer::changeConfiguration(Json::Value const& _settings) +void LanguageServer::changeConfiguration(Json const& _settings) { // The settings item: "file-load-strategy" (enum) defaults to "project-directory" if not (or not correctly) set. // It can be overridden during client's handshake or at runtime, as usual. @@ -176,9 +177,9 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings) // // If this value is set to "directly-opened-and-on-import", then only currently directly opened files and // those files being imported directly or indirectly will be included in operations. - if (_settings["file-load-strategy"]) + if (_settings.contains("file-load-strategy")) { - auto const text = _settings["file-load-strategy"].asString(); + auto const text = _settings["file-load-strategy"].get(); if (text == "project-directory") m_fileLoadStrategy = FileLoadStrategy::ProjectDirectory; else if (text == "directly-opened-and-on-import") @@ -188,18 +189,18 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings) } m_settingsObject = _settings; - Json::Value jsonIncludePaths = _settings["include-paths"]; + Json jsonIncludePaths = _settings.contains("include-paths") ? _settings["include-paths"] : Json::object(); - if (jsonIncludePaths) + if (!jsonIncludePaths.empty()) { int typeFailureCount = 0; - if (jsonIncludePaths.isArray()) + if (jsonIncludePaths.is_array()) { std::vector includePaths; - for (Json::Value const& jsonPath: jsonIncludePaths) + for (Json const& jsonPath: jsonIncludePaths) { - if (jsonPath.isString()) - includePaths.emplace_back(boost::filesystem::path(jsonPath.asString())); + if (jsonPath.is_string()) + includePaths.emplace_back(jsonPath.get()); else typeFailureCount++; } @@ -274,11 +275,11 @@ void LanguageServer::compileAndUpdateDiagnostics() // These are the source units we will sent diagnostics to the client for sure, // even if it is just to clear previous diagnostics. - std::map diagnosticsBySourceUnit; + std::map diagnosticsBySourceUnit; for (std::string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys) - diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; + diagnosticsBySourceUnit[sourceUnitName] = Json::array(); for (std::string const& sourceUnitName: m_nonemptyDiagnostics) - diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; + diagnosticsBySourceUnit[sourceUnitName] = Json::array(); for (std::shared_ptr const& error: m_compilerStack.errors()) { @@ -287,10 +288,10 @@ void LanguageServer::compileAndUpdateDiagnostics() // LSP only has diagnostics applied to individual files. continue; - Json::Value jsonDiag; + Json jsonDiag; jsonDiag["source"] = "solc"; jsonDiag["severity"] = toDiagnosticSeverity(error->type()); - jsonDiag["code"] = Json::UInt64{error->errorId().error}; + jsonDiag["code"] = Json(error->errorId().error); std::string message = Error::formatErrorType(error->type()) + ":"; if (std::string const* comment = error->comment()) message += " " + *comment; @@ -300,26 +301,26 @@ void LanguageServer::compileAndUpdateDiagnostics() if (auto const* secondary = error->secondarySourceLocation()) for (auto&& [secondaryMessage, secondaryLocation]: secondary->infos) { - Json::Value jsonRelated; + Json jsonRelated; jsonRelated["message"] = secondaryMessage; jsonRelated["location"] = toJson(secondaryLocation); - jsonDiag["relatedInformation"].append(jsonRelated); + jsonDiag["relatedInformation"].emplace_back(jsonRelated); } - diagnosticsBySourceUnit[*location->sourceName].append(jsonDiag); + diagnosticsBySourceUnit[*location->sourceName].emplace_back(jsonDiag); } if (m_client.traceValue() != TraceValue::Off) { - Json::Value extra; - extra["openFileCount"] = Json::UInt64(diagnosticsBySourceUnit.size()); + Json extra; + extra["openFileCount"] = Json(diagnosticsBySourceUnit.size()); m_client.trace("Number of currently open files: " + std::to_string(diagnosticsBySourceUnit.size()), extra); } m_nonemptyDiagnostics.clear(); for (auto&& [sourceUnitName, diagnostics]: diagnosticsBySourceUnit) { - Json::Value params; + Json params; params["uri"] = m_fileRepository.sourceUnitNameToUri(sourceUnitName); if (!diagnostics.empty()) m_nonemptyDiagnostics.insert(sourceUnitName); @@ -335,14 +336,15 @@ bool LanguageServer::run() MessageID id; try { - std::optional const jsonMessage = m_client.receive(); + std::optional const jsonMessage = m_client.receive(); if (!jsonMessage) continue; - if ((*jsonMessage)["method"].isString()) + if ((*jsonMessage).contains("method") && (*jsonMessage)["method"].is_string()) { - std::string const methodName = (*jsonMessage)["method"].asString(); - id = (*jsonMessage)["id"]; + std::string const methodName = (*jsonMessage)["method"].get(); + if ((*jsonMessage).contains("id")) + id = (*jsonMessage)["id"]; lspDebug(fmt::format("received method call: {}", methodName)); if (auto handler = util::valueOrDefault(m_handlers, methodName)) @@ -353,7 +355,7 @@ bool LanguageServer::run() else m_client.error({}, ErrorCode::ParseError, "\"method\" has to be a string."); } - catch (Json::Exception const&) + catch (Json::exception const&) { m_client.error(id, ErrorCode::InvalidParams, "JSON object access error. Most likely due to a badly formatted JSON request message."s); } @@ -378,7 +380,7 @@ void LanguageServer::requireServerInitialized() ); } -void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) +void LanguageServer::handleInitialize(MessageID _id, Json const& _args) { lspRequire( m_state == State::Started, @@ -391,9 +393,9 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) // The default of FileReader is to use `.`, but the path from where the LSP was started // should not matter. std::string rootPath("/"); - if (Json::Value uri = _args["rootUri"]) + if (_args.contains("rootUri") && _args["rootUri"].is_string()) { - rootPath = uri.asString(); + rootPath = _args["rootUri"].get(); lspRequire( boost::starts_with(rootPath, "file://"), ErrorCode::InvalidParams, @@ -401,17 +403,17 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) ); rootPath = stripFileUriSchemePrefix(rootPath); } - else if (Json::Value rootPath = _args["rootPath"]) - rootPath = rootPath.asString(); + else if (_args.contains("rootPath")) + rootPath = _args["rootPath"].get(); - if (_args["trace"]) + if (_args.contains("trace")) setTrace(_args["trace"]); m_fileRepository = FileRepository(rootPath, {}); - if (_args["initializationOptions"].isObject()) + if (_args.contains("initializationOptions") && _args["initializationOptions"].is_object()) changeConfiguration(_args["initializationOptions"]); - Json::Value replyArgs; + Json replyArgs; replyArgs["serverInfo"]["name"] = "solc"; replyArgs["serverInfo"]["version"] = std::string(VersionNumber); replyArgs["capabilities"]["definitionProvider"] = true; @@ -427,44 +429,49 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) m_client.reply(_id, std::move(replyArgs)); } -void LanguageServer::handleInitialized(MessageID, Json::Value const&) +void LanguageServer::handleInitialized(MessageID, Json const&) { if (m_fileLoadStrategy == FileLoadStrategy::ProjectDirectory) compileAndUpdateDiagnostics(); } -void LanguageServer::semanticTokensFull(MessageID _id, Json::Value const& _args) +void LanguageServer::semanticTokensFull(MessageID _id, Json const& _args) { - auto uri = _args["textDocument"]["uri"]; + if (_args.contains("textDocument") && _args["textDocument"].contains("uri")) + { + auto uri = _args["textDocument"]["uri"]; - compile(); + compile(); - auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as()); - SourceUnit const& ast = m_compilerStack.ast(sourceName); - m_compilerStack.charStream(sourceName); - Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName)); + auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.get()); + SourceUnit const& ast = m_compilerStack.ast(sourceName); + m_compilerStack.charStream(sourceName); + Json data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName)); - Json::Value reply = Json::objectValue; - reply["data"] = data; + Json reply; + reply["data"] = data; - m_client.reply(_id, std::move(reply)); + m_client.reply(_id, std::move(reply)); + } + else + m_client.error(_id, ErrorCode::InvalidParams, "Invalid parameter: textDocument.uri expected."); } -void LanguageServer::handleWorkspaceDidChangeConfiguration(Json::Value const& _args) +void LanguageServer::handleWorkspaceDidChangeConfiguration(Json const& _args) { requireServerInitialized(); - if (_args["settings"].isObject()) + if (_args.contains("settings") && _args["settings"].is_object()) changeConfiguration(_args["settings"]); } -void LanguageServer::setTrace(Json::Value const& _args) +void LanguageServer::setTrace(Json const& _args) { - if (!_args.isString()) + if (!_args.is_string()) // Simply ignore invalid parameter. return; - std::string const stringValue = _args.asString(); + std::string const stringValue = _args.get(); if (stringValue == "off") m_client.setTrace(TraceValue::Off); else if (stringValue == "messages") @@ -473,78 +480,90 @@ void LanguageServer::setTrace(Json::Value const& _args) m_client.setTrace(TraceValue::Verbose); } -void LanguageServer::handleTextDocumentDidOpen(Json::Value const& _args) +void LanguageServer::handleTextDocumentDidOpen(Json const& _args) { requireServerInitialized(); lspRequire( - _args["textDocument"], + _args.contains("textDocument"), ErrorCode::RequestFailed, "Text document parameter missing." ); - std::string text = _args["textDocument"]["text"].asString(); - std::string uri = _args["textDocument"]["uri"].asString(); - m_openFiles.insert(uri); - m_fileRepository.setSourceByUri(uri, std::move(text)); - compileAndUpdateDiagnostics(); + if (_args["textDocument"].contains("text") && _args["textDocument"].contains("uri")) + { + std::string text = _args["textDocument"]["text"].get(); + std::string uri = _args["textDocument"]["uri"].get(); + m_openFiles.insert(uri); + m_fileRepository.setSourceByUri(uri, std::move(text)); + compileAndUpdateDiagnostics(); + } } -void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args) +void LanguageServer::handleTextDocumentDidChange(Json const& _args) { requireServerInitialized(); - std::string const uri = _args["textDocument"]["uri"].asString(); - - for (Json::Value jsonContentChange: _args["contentChanges"]) + if (_args.contains("textDocument") && _args["textDocument"].contains("uri")) { - lspRequire( - jsonContentChange.isObject(), - ErrorCode::RequestFailed, - "Invalid content reference." - ); - - std::string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri); - lspRequire( - m_fileRepository.sourceUnits().count(sourceUnitName), - ErrorCode::RequestFailed, - "Unknown file: " + uri - ); + std::string const uri = _args["textDocument"]["uri"].get(); - std::string text = jsonContentChange["text"].asString(); - if (jsonContentChange["range"].isObject()) // otherwise full content update - { - std::optional change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]); - lspRequire( - change && change->hasText(), - ErrorCode::RequestFailed, - "Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"]) - ); + if (_args.contains("contentChanges")) + for (auto const& [_, jsonContentChange]: _args["contentChanges"].items()) + { + lspRequire(jsonContentChange.is_object(), ErrorCode::RequestFailed, "Invalid content reference."); + + std::string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri); + lspRequire( + m_fileRepository.sourceUnits().count(sourceUnitName), + ErrorCode::RequestFailed, + "Unknown file: " + uri); + + if (jsonContentChange.contains("text")) + { + std::string text = jsonContentChange["text"].get(); + if (jsonContentChange.contains("range") + && jsonContentChange["range"].is_object()) // otherwise full content update + { + std::optional change + = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]); + lspRequire( + change && change->hasText(), + ErrorCode::RequestFailed, + "Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"])); + + std::string buffer = m_fileRepository.sourceUnits().at(sourceUnitName); + buffer.replace( + static_cast(change->start), + static_cast(change->end - change->start), + std::move(text)); + text = std::move(buffer); + } + m_fileRepository.setSourceByUri(uri, std::move(text)); + } + } - std::string buffer = m_fileRepository.sourceUnits().at(sourceUnitName); - buffer.replace(static_cast(change->start), static_cast(change->end - change->start), std::move(text)); - text = std::move(buffer); - } - m_fileRepository.setSourceByUri(uri, std::move(text)); + compileAndUpdateDiagnostics(); } - - compileAndUpdateDiagnostics(); } -void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args) +void LanguageServer::handleTextDocumentDidClose(Json const& _args) { requireServerInitialized(); lspRequire( - _args["textDocument"], + _args.contains("textDocument"), ErrorCode::RequestFailed, "Text document parameter missing." ); - std::string uri = _args["textDocument"]["uri"].asString(); - m_openFiles.erase(uri); + if (_args["textDocument"].contains("uri")) + { + std::string uri = _args["textDocument"]["uri"].get(); + m_openFiles.erase(uri); - compileAndUpdateDiagnostics(); + compileAndUpdateDiagnostics(); + } } ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos) diff --git a/libsolidity/lsp/LanguageServer.h b/libsolidity/lsp/LanguageServer.h index d80f8e879c7a..4bea5809fa45 100644 --- a/libsolidity/lsp/LanguageServer.h +++ b/libsolidity/lsp/LanguageServer.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -85,29 +85,29 @@ class LanguageServer /// Checks if the server is initialized (to be used by messages that need it to be initialized). /// Reports an error and returns false if not. void requireServerInitialized(); - void handleInitialize(MessageID _id, Json::Value const& _args); - void handleInitialized(MessageID _id, Json::Value const& _args); - void handleWorkspaceDidChangeConfiguration(Json::Value const& _args); - void setTrace(Json::Value const& _args); - void handleTextDocumentDidOpen(Json::Value const& _args); - void handleTextDocumentDidChange(Json::Value const& _args); - void handleTextDocumentDidClose(Json::Value const& _args); - void handleRename(Json::Value const& _args); - void handleGotoDefinition(MessageID _id, Json::Value const& _args); - void semanticTokensFull(MessageID _id, Json::Value const& _args); + void handleInitialize(MessageID _id, Json const& _args); + void handleInitialized(MessageID _id, Json const& _args); + void handleWorkspaceDidChangeConfiguration(Json const& _args); + void setTrace(Json const& _args); + void handleTextDocumentDidOpen(Json const& _args); + void handleTextDocumentDidChange(Json const& _args); + void handleTextDocumentDidClose(Json const& _args); + void handleRename(Json const& _args); + void handleGotoDefinition(MessageID _id, Json const& _args); + void semanticTokensFull(MessageID _id, Json const& _args); /// Invoked when the server user-supplied configuration changes (initiated by the client). - void changeConfiguration(Json::Value const&); + void changeConfiguration(Json const&); /// Compile everything until after analysis phase. void compile(); std::vector allSolidityFilesFromProject() const; - using MessageHandler = std::function; + using MessageHandler = std::function; - Json::Value toRange(langutil::SourceLocation const& _location); - Json::Value toJson(langutil::SourceLocation const& _location); + Json toRange(langutil::SourceLocation const& _location); + Json toJson(langutil::SourceLocation const& _location); // LSP related member fields @@ -127,7 +127,7 @@ class LanguageServer frontend::CompilerStack m_compilerStack; /// User-supplied custom configuration settings (such as EVM version). - Json::Value m_settingsObject; + Json m_settingsObject; }; } diff --git a/libsolidity/lsp/RenameSymbol.cpp b/libsolidity/lsp/RenameSymbol.cpp index 75f032fcca47..497ee50fb451 100644 --- a/libsolidity/lsp/RenameSymbol.cpp +++ b/libsolidity/lsp/RenameSymbol.cpp @@ -47,11 +47,11 @@ CallableDeclaration const* extractCallableDeclaration(FunctionCall const& _funct } -void RenameSymbol::operator()(MessageID _id, Json::Value const& _args) +void RenameSymbol::operator()(MessageID _id, Json const& _args) { auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args); - std::string const newName = _args["newName"].asString(); - std::string const uri = _args["textDocument"]["uri"].asString(); + std::string const newName = _args["newName"].get(); + std::string const uri = _args["textDocument"]["uri"].get(); ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn); @@ -90,10 +90,10 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args) // Apply changes in reverse order (will iterate in reverse) sort(m_locations.begin(), m_locations.end()); - Json::Value reply = Json::objectValue; - reply["changes"] = Json::objectValue; + Json reply; + reply["changes"] = Json::object(); - Json::Value edits = Json::arrayValue; + Json edits = Json::array(); for (auto i = m_locations.rbegin(); i != m_locations.rend(); i++) { @@ -105,16 +105,16 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args) buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName); fileRepository().setSourceByUri(uri, std::move(buffer)); - Json::Value edit = Json::objectValue; + Json edit; edit["range"] = toRange(*i); edit["newText"] = newName; // Record changes for the client - edits.append(edit); + edits.emplace_back(edit); if (i + 1 == m_locations.rend() || (i + 1)->sourceName != i->sourceName) { reply["changes"][uri] = edits; - edits = Json::arrayValue; + edits = Json::array(); // Reset. } } diff --git a/libsolidity/lsp/RenameSymbol.h b/libsolidity/lsp/RenameSymbol.h index cafa8c067a25..c4a2ac98f359 100644 --- a/libsolidity/lsp/RenameSymbol.h +++ b/libsolidity/lsp/RenameSymbol.h @@ -27,7 +27,7 @@ class RenameSymbol: public HandlerBase public: explicit RenameSymbol(LanguageServer& _server): HandlerBase(_server) {} - void operator()(MessageID, Json::Value const&); + void operator()(MessageID, Json const&); protected: // Nested class because otherwise `RenameSymbol` couldn't be easily used // with LanguageServer::m_handlers as `ASTConstVisitor` deletes required diff --git a/libsolidity/lsp/SemanticTokensBuilder.cpp b/libsolidity/lsp/SemanticTokensBuilder.cpp index 2f44354184ef..be0796860cb9 100644 --- a/libsolidity/lsp/SemanticTokensBuilder.cpp +++ b/libsolidity/lsp/SemanticTokensBuilder.cpp @@ -70,7 +70,7 @@ SemanticTokenType semanticTokenTypeForExpression(frontend::Type const* _type) } // end namespace -Json::Value SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStream const& _charStream) +Json SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStream const& _charStream) { reset(&_charStream); _sourceUnit.accept(*this); @@ -79,7 +79,7 @@ Json::Value SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStre void SemanticTokensBuilder::reset(CharStream const* _charStream) { - m_encodedTokens = Json::arrayValue; + m_encodedTokens = Json::array(); m_charStream = _charStream; m_lastLine = 0; m_lastStartChar = 0; @@ -120,14 +120,14 @@ void SemanticTokensBuilder::encode( lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, static_cast(_tokenType))); - m_encodedTokens.append(line - m_lastLine); + m_encodedTokens.emplace_back(line - m_lastLine); if (line == m_lastLine) - m_encodedTokens.append(startChar - m_lastStartChar); + m_encodedTokens.emplace_back(startChar - m_lastStartChar); else - m_encodedTokens.append(startChar); - m_encodedTokens.append(length); - m_encodedTokens.append(static_cast(_tokenType)); - m_encodedTokens.append(static_cast(_modifiers)); + m_encodedTokens.emplace_back(startChar); + m_encodedTokens.emplace_back(length); + m_encodedTokens.emplace_back(static_cast(_tokenType)); + m_encodedTokens.emplace_back(static_cast(_modifiers)); m_lastLine = line; m_lastStartChar = startChar; diff --git a/libsolidity/lsp/SemanticTokensBuilder.h b/libsolidity/lsp/SemanticTokensBuilder.h index ca3c48d1c68d..3facb99e2bae 100644 --- a/libsolidity/lsp/SemanticTokensBuilder.h +++ b/libsolidity/lsp/SemanticTokensBuilder.h @@ -17,7 +17,7 @@ // SPDX-License-Identifier: GPL-3.0 #include #include -#include +#include #include @@ -87,7 +87,7 @@ constexpr SemanticTokenModifiers operator|(SemanticTokenModifiers a, SemanticTok class SemanticTokensBuilder: public frontend::ASTConstVisitor { public: - Json::Value build(frontend::SourceUnit const& _sourceUnit, langutil::CharStream const& _charStream); + Json build(frontend::SourceUnit const& _sourceUnit, langutil::CharStream const& _charStream); void reset(langutil::CharStream const* _charStream); void encode( @@ -114,7 +114,7 @@ class SemanticTokensBuilder: public frontend::ASTConstVisitor bool visit(frontend::VariableDeclaration const&) override; private: - Json::Value m_encodedTokens; + Json m_encodedTokens; langutil::CharStream const* m_charStream; int m_lastLine; int m_lastStartChar; diff --git a/libsolidity/lsp/Transport.cpp b/libsolidity/lsp/Transport.cpp index 7f8eb2283488..743ad6d66955 100644 --- a/libsolidity/lsp/Transport.cpp +++ b/libsolidity/lsp/Transport.cpp @@ -38,9 +38,10 @@ #endif using namespace solidity::lsp; +using namespace solidity; // {{{ Transport -std::optional Transport::receive() +std::optional Transport::receive() { auto const headers = parseHeaders(); if (!headers) @@ -57,10 +58,10 @@ std::optional Transport::receive() std::string const data = readBytes(stoul(headers->at("content-length"))); - Json::Value jsonMessage; + Json jsonMessage; std::string jsonParsingErrors; solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors); - if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject()) + if (!jsonParsingErrors.empty() || jsonMessage.empty() || !jsonMessage.is_object()) { error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors); return std::nullopt; @@ -69,12 +70,12 @@ std::optional Transport::receive() return {std::move(jsonMessage)}; } -void Transport::trace(std::string _message, Json::Value _extra) +void Transport::trace(std::string _message, Json _extra) { if (m_logTrace != TraceValue::Off) { - Json::Value params; - if (_extra.isObject()) + Json params; + if (_extra.is_object()) params = std::move(_extra); params["message"] = std::move(_message); notify("$/logTrace", std::move(params)); @@ -103,34 +104,34 @@ std::optional> Transport::parseHeaders() return {std::move(headers)}; } -void Transport::notify(std::string _method, Json::Value _message) +void Transport::notify(std::string _method, Json _message) { - Json::Value json; + Json json; json["method"] = std::move(_method); json["params"] = std::move(_message); send(std::move(json)); } -void Transport::reply(MessageID _id, Json::Value _message) +void Transport::reply(MessageID _id, Json _message) { - Json::Value json; + Json json; json["result"] = std::move(_message); send(std::move(json), _id); } void Transport::error(MessageID _id, ErrorCode _code, std::string _message) { - Json::Value json; + Json json; json["error"]["code"] = static_cast(_code); json["error"]["message"] = std::move(_message); send(std::move(json), _id); } -void Transport::send(Json::Value _json, MessageID _id) +void Transport::send(Json _json, MessageID _id) { - solAssert(_json.isObject()); + solAssert(_json.is_object()); _json["jsonrpc"] = "2.0"; - if (_id != Json::nullValue) + if (_id != Json()) _json["id"] = _id; // Trailing CRLF only for easier readability. diff --git a/libsolidity/lsp/Transport.h b/libsolidity/lsp/Transport.h index e3b03bcc7f2f..e76cb5f7da5d 100644 --- a/libsolidity/lsp/Transport.h +++ b/libsolidity/lsp/Transport.h @@ -18,8 +18,7 @@ #pragma once #include - -#include +#include #include #include @@ -32,7 +31,7 @@ namespace solidity::lsp { -using MessageID = Json::Value; +using MessageID = Json; enum class TraceValue { @@ -98,14 +97,14 @@ class Transport public: virtual ~Transport() = default; - std::optional receive(); - void notify(std::string _method, Json::Value _params); - void reply(MessageID _id, Json::Value _result); + std::optional receive(); + void notify(std::string _method, Json _params); + void reply(MessageID _id, Json _result); void error(MessageID _id, ErrorCode _code, std::string _message); virtual bool closed() const noexcept = 0; - void trace(std::string _message, Json::Value _extra = Json::nullValue); + void trace(std::string _message, Json _extra = Json{}); TraceValue traceValue() const noexcept { return m_logTrace; } void setTrace(TraceValue _value) noexcept { m_logTrace = _value; } @@ -135,7 +134,7 @@ class Transport /// Sends an arbitrary raw message to the client. /// /// Used by the notify/reply/error function family. - virtual void send(Json::Value _message, MessageID _id = Json::nullValue); + virtual void send(Json _message, MessageID _id = Json{}); }; /** diff --git a/libsolidity/lsp/Utils.cpp b/libsolidity/lsp/Utils.cpp index 85e27a4fda5f..7667ce688ecd 100644 --- a/libsolidity/lsp/Utils.cpp +++ b/libsolidity/lsp/Utils.cpp @@ -31,26 +31,26 @@ namespace solidity::lsp using namespace frontend; using namespace langutil; -std::optional parseLineColumn(Json::Value const& _lineColumn) +std::optional parseLineColumn(Json const& _lineColumn) { - if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt()) - return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()}; + if (_lineColumn.is_object() && _lineColumn["line"].is_number_integer() && _lineColumn["character"].is_number_integer()) + return LineColumn{_lineColumn["line"].get(), _lineColumn["character"].get()}; else return std::nullopt; } -Json::Value toJson(LineColumn const& _pos) +Json toJson(LineColumn const& _pos) { - Json::Value json = Json::objectValue; + Json json; json["line"] = std::max(_pos.line, 0); json["character"] = std::max(_pos.column, 0); return json; } -Json::Value toJsonRange(LineColumn const& _start, LineColumn const& _end) +Json toJsonRange(LineColumn const& _start, LineColumn const& _end) { - Json::Value json; + Json json; json["start"] = toJson(_start); json["end"] = toJson(_end); return json; @@ -86,7 +86,7 @@ std::optional declarationLocation(Declaration const* _declaratio std::optional parsePosition( FileRepository const& _fileRepository, std::string const& _sourceUnitName, - Json::Value const& _position + Json const& _position ) { if (!_fileRepository.sourceUnits().count(_sourceUnitName)) @@ -101,9 +101,9 @@ std::optional parsePosition( return std::nullopt; } -std::optional parseRange(FileRepository const& _fileRepository, std::string const& _sourceUnitName, Json::Value const& _range) +std::optional parseRange(FileRepository const& _fileRepository, std::string const& _sourceUnitName, Json const& _range) { - if (!_range.isObject()) + if (!_range.is_object()) return std::nullopt; std::optional start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]); std::optional end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]); diff --git a/libsolidity/lsp/Utils.h b/libsolidity/lsp/Utils.h index c6d40213e6d3..318cdc87d6fc 100644 --- a/libsolidity/lsp/Utils.h +++ b/libsolidity/lsp/Utils.h @@ -44,16 +44,16 @@ namespace solidity::lsp class FileRepository; -std::optional parseLineColumn(Json::Value const& _lineColumn); -Json::Value toJson(langutil::LineColumn const& _pos); -Json::Value toJsonRange(langutil::LineColumn const& _start, langutil::LineColumn const& _end); +std::optional parseLineColumn(Json const& _lineColumn); +Json toJson(langutil::LineColumn const& _pos); +Json toJsonRange(langutil::LineColumn const& _start, langutil::LineColumn const& _end); /// @returns the source location given a source unit name and an LSP Range object, /// or nullopt on failure. std::optional parsePosition( FileRepository const& _fileRepository, std::string const& _sourceUnitName, - Json::Value const& _position + Json const& _position ); /// @returns the source location given a source unit name and an LSP Range object, @@ -61,7 +61,7 @@ std::optional parsePosition( std::optional parseRange( FileRepository const& _fileRepository, std::string const& _sourceUnitName, - Json::Value const& _range + Json const& _range ); /// Strips the file:// URI prefix off the given path, if present, diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index f97d61b671c1..0fdb23b0445f 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -43,7 +43,7 @@ set(sources ) add_library(solutil ${sources}) -target_link_libraries(solutil PUBLIC jsoncpp Boost::boost Boost::filesystem Boost::system range-v3 fmt::fmt-header-only) +target_link_libraries(solutil PUBLIC Boost::boost Boost::filesystem Boost::system range-v3 fmt::fmt-header-only nlohmann-json) target_include_directories(solutil PUBLIC "${PROJECT_SOURCE_DIR}") add_dependencies(solutil solidity_BuildInfo.h) diff --git a/libsolutil/Exceptions.h b/libsolutil/Exceptions.h index 9d73a0012eb4..7dd9b6769ad4 100644 --- a/libsolutil/Exceptions.h +++ b/libsolutil/Exceptions.h @@ -76,6 +76,7 @@ DEV_SIMPLE_EXCEPTION(FileNotFound); DEV_SIMPLE_EXCEPTION(NotAFile); DEV_SIMPLE_EXCEPTION(DataTooLong); DEV_SIMPLE_EXCEPTION(StringTooLong); +DEV_SIMPLE_EXCEPTION(InvalidType); // error information to be added to exceptions using errinfo_comment = boost::error_info; diff --git a/libsolutil/JSON.cpp b/libsolutil/JSON.cpp index 3a2570d47ec1..63746c86531a 100644 --- a/libsolutil/JSON.cpp +++ b/libsolutil/JSON.cpp @@ -22,19 +22,18 @@ #include -#include +#include -#include +#include +#include -#include #include -#include +#include -#ifdef STRICT_JSONCPP_VERSION_CHECK +#ifdef STRICT_NLOHMANN_JSON_VERSION_CHECK static_assert( - (JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 3), - "Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.3." -); + (NLOHMANN_JSON_VERSION_MAJOR == 3) && (NLOHMANN_JSON_VERSION_MINOR == 11) && (NLOHMANN_JSON_VERSION_PATCH == 3), + "Unexpected nlohmann-json version. Expecting 3.11.3."); #endif namespace solidity::util @@ -43,116 +42,209 @@ namespace solidity::util namespace { -/// StreamWriterBuilder that can be constructed with specific settings -class StreamWriterBuilder: public Json::StreamWriterBuilder +/// Takes a JSON value (@ _json) and removes all its members with value 'null' recursively. +void removeNullMembersHelper(Json& _json) { -public: - explicit StreamWriterBuilder(std::map const& _settings) + if (_json.is_array()) { - for (auto const& iter: _settings) - this->settings_[iter.first] = iter.second; + for (auto& child: _json) + removeNullMembersHelper(child); } -}; - -/// CharReaderBuilder with strict-mode settings -class StrictModeCharReaderBuilder: public Json::CharReaderBuilder -{ -public: - StrictModeCharReaderBuilder() + else if (_json.is_object()) { - Json::CharReaderBuilder::strictMode(&this->settings_); + for (auto it = _json.begin(); it != _json.end();) + { + if (it->is_null()) + it = _json.erase(it); + else + { + removeNullMembersHelper(*it); + ++it; + } + } } -}; +} -/// Serialise the JSON object (@a _input) with specific builder (@a _builder) -/// \param _input JSON input string -/// \param _builder StreamWriterBuilder that is used to create new Json::StreamWriter -/// \return serialized json object -std::string print(Json::Value const& _input, Json::StreamWriterBuilder const& _builder) +std::string trimRightAllLines(std::string const& input) { - std::stringstream stream; - std::unique_ptr writer(_builder.newStreamWriter()); - writer->write(_input, &stream); - return stream.str(); + std::vector lines; + std::string output; + boost::split(lines, input, boost::is_any_of("\n")); + for (auto& line: lines) + { + boost::trim_right(line); + if (!line.empty()) + output += line + "\n"; + } + return boost::trim_right_copy(output); } -/// Parse a JSON string (@a _input) with specified builder (@ _builder) and writes resulting JSON object to (@a _json) -/// \param _builder CharReaderBuilder that is used to create new Json::CharReaders -/// \param _input JSON input string -/// \param _json [out] resulting JSON object -/// \param _errs [out] Formatted error messages -/// \return \c true if the document was successfully parsed, \c false if an error occurred. -bool parse(Json::CharReaderBuilder& _builder, std::string const& _input, Json::Value& _json, std::string* _errs) +std::string formatLikeJsoncpp(std::string const& _dumped, JsonFormat const& _format) { - std::unique_ptr reader(_builder.newCharReader()); - return reader->parse(_input.c_str(), _input.c_str() + _input.length(), &_json, _errs); + uint32_t indentLevel = 0; + std::stringstream reformatted; + bool inQuotes = false; + for (size_t i = 0; i < _dumped.size(); ++i) + { + char c = _dumped[i]; + bool emptyThing = false; + + if (c == '"' && (i == 0 || _dumped[i - 1] != '\\')) + inQuotes = !inQuotes; + + if (!inQuotes) + { + if (i < _dumped.size() - 1) + { + char nc = _dumped[i + 1]; + if ((c == '[' && nc == ']') || (c == '{' && nc == '}')) + emptyThing = true; + } + if (c == '[' || c == '{') + { + if (i > 0 && _dumped[i - 1] != '\n') + if (!emptyThing) + reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); + indentLevel++; + } + else if (c == ']' || c == '}') + { + indentLevel--; + if (i + 1 < _dumped.size() && _dumped[i + 1] != '\n' + && (_dumped[i + 1] == ']' || _dumped[i + 1] == '}')) + reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); + } + } + reformatted << c; + if (!emptyThing && !inQuotes && (c == '[' || c == '{') && indentLevel > 0 && i + 1 < _dumped.size() + && _dumped[i + 1] != '\n') + reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); + } + return trimRightAllLines(reformatted.str()); } -/// Takes a JSON value (@ _json) and removes all its members with value 'null' recursively. -void removeNullMembersHelper(Json::Value& _json) +std::string escapeNewlinesAndTabsWithinStringLiterals(std::string const& _json) { - if (_json.type() == Json::ValueType::arrayValue) - for (auto& child: _json) - removeNullMembersHelper(child); - else if (_json.type() == Json::ValueType::objectValue) - for (auto const& key: _json.getMemberNames()) + std::stringstream fixed; + bool inQuotes = false; + for (size_t i = 0; i < _json.size(); ++i) + { + char c = _json[i]; + + // Originally we had just this here: + // if (c == '"' && (i == 0 || _json[i - 1] != '\\')) + // inQuotes = !inQuotes; + // However, this is not working if the escape character itself was escaped. e.g. "\n\r'\"\\". + + if (c == '"') + { + size_t backslashCount = 0; + size_t j = i; + while (j > 0 && _json[j - 1] == '\\') + { + backslashCount++; + j--; + } + if (backslashCount % 2 == 0) + { + inQuotes = !inQuotes; + fixed << c; + continue; + } + } + + if (inQuotes) { - Json::Value& value = _json[key]; - if (value.isNull()) - _json.removeMember(key); + if (c == '\n') + fixed << "\\n"; + else if (c == '\t') + fixed << "\\t"; else - removeNullMembersHelper(value); + fixed << c; } + else + fixed << c; + } + return fixed.str(); } } // end anonymous namespace -Json::Value removeNullMembers(Json::Value _json) +Json removeNullMembers(Json _json) { removeNullMembersHelper(_json); return _json; } -std::string jsonPrettyPrint(Json::Value const& _input) +std::string removeNlohmannInternalErrorIdentifier(std::string const& _input) { - return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty }); -} + std::string result = _input; + std::size_t startPos = result.find('['); + std::size_t endPos = result.find(']', startPos); -std::string jsonCompactPrint(Json::Value const& _input) -{ - return jsonPrint(_input, JsonFormat{ JsonFormat::Compact }); + if (startPos != std::string::npos && endPos != std::string::npos) + result.erase(startPos, endPos - startPos + 1); + + return boost::trim_copy(result); } -std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format) +std::string jsonPrettyPrint(Json const& _input) { return jsonPrint(_input, JsonFormat{JsonFormat::Pretty}); } + +std::string jsonCompactPrint(Json const& _input) { return jsonPrint(_input, JsonFormat{JsonFormat::Compact}); } + +std::string jsonPrint(Json const& _input, JsonFormat const& _format) { - std::map settings; - if (_format.format == JsonFormat::Pretty) - { - settings["indentation"] = std::string(_format.indent, ' '); - settings["enableYAMLCompatibility"] = true; - } - else - settings["indentation"] = ""; - StreamWriterBuilder writerBuilder(settings); - std::string result = print(_input, writerBuilder); + // NOTE: -1 here means no new lines (it is also the default setting) + std::string dumped = _input.dump( + /* indent */ (_format.format == JsonFormat::Pretty) ? static_cast(_format.indent) : -1, + /* indent_char */ ' ', + /* ensure_ascii */ true + ); + + // let's remove this once all test-cases having the correct output. if (_format.format == JsonFormat::Pretty) - boost::replace_all(result, " \n", "\n"); - return result; + dumped = formatLikeJsoncpp(dumped, _format); + + return dumped; } -bool jsonParseStrict(std::string const& _input, Json::Value& _json, std::string* _errs /* = nullptr */) +bool jsonParseStrict(std::string const& _input, Json& _json, std::string* _errs /* = nullptr */) { - static StrictModeCharReaderBuilder readerBuilder; - return parse(readerBuilder, _input, _json, _errs); + try + { + _json = Json::parse( + // TODO: remove this in the next breaking release? + escapeNewlinesAndTabsWithinStringLiterals(_input), + /* callback */ nullptr, + /* allow exceptions */ true, + /* ignore_comments */true + ); + _errs = {}; + return true; + } + catch (Json::parse_error const& e) + { + if (_errs) + { + std::stringstream escaped; + for (char c: removeNlohmannInternalErrorIdentifier(e.what())) + if (std::isprint(c)) + escaped << c; + else + escaped << "\\x" + toHex(static_cast(c)); + *_errs = escaped.str(); + } + return false; + } } -std::optional jsonValueByPath(Json::Value const& _node, std::string_view _jsonPath) +std::optional jsonValueByPath(Json const& _node, std::string_view _jsonPath) { - if (!_node.isObject() || _jsonPath.empty()) + if (!_node.is_object() || _jsonPath.empty()) return {}; std::string memberName = std::string(_jsonPath.substr(0, _jsonPath.find_first_of('.'))); - if (!_node.isMember(memberName)) + if (!_node.contains(memberName)) return {}; if (memberName == _jsonPath) diff --git a/libsolutil/JSON.h b/libsolutil/JSON.h index f368739e1a99..2cdac70c7857 100644 --- a/libsolutil/JSON.h +++ b/libsolutil/JSON.h @@ -23,17 +23,26 @@ #pragma once -#include +#include +#include #include #include #include +#include + +namespace solidity +{ + +using Json = nlohmann::json; + +} // namespace solidity namespace solidity::util { /// Removes members with null value recursively from (@a _json). -Json::Value removeNullMembers(Json::Value _json); +Json removeNullMembers(Json _json); /// JSON printing format. struct JsonFormat @@ -54,27 +63,29 @@ struct JsonFormat }; /// Serialise the JSON object (@a _input) with indentation -std::string jsonPrettyPrint(Json::Value const& _input); +std::string jsonPrettyPrint(Json const& _input); /// Serialise the JSON object (@a _input) without indentation -std::string jsonCompactPrint(Json::Value const& _input); +std::string jsonCompactPrint(Json const& _input); /// Serialise the JSON object (@a _input) using specified format (@a _format) -std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format); +std::string jsonPrint(Json const& _input, JsonFormat const& _format); /// Parse a JSON string (@a _input) with enabled strict-mode and writes resulting JSON object to (@a _json) /// \param _input JSON input string /// \param _json [out] resulting JSON object /// \param _errs [out] Formatted error messages /// \return \c true if the document was successfully parsed, \c false if an error occurred. -bool jsonParseStrict(std::string const& _input, Json::Value& _json, std::string* _errs = nullptr); +bool jsonParseStrict(std::string const& _input, Json& _json, std::string* _errs = nullptr); /// Retrieves the value specified by @p _jsonPath by from a series of nested JSON dictionaries. /// @param _jsonPath A dot-separated series of dictionary keys. /// @param _node The node representing the start of the path. /// @returns The value of the last key on the path. @a nullptr if any node on the path descends /// into something that is not a dictionary or the key is not present. -std::optional jsonValueByPath(Json::Value const& _node, std::string_view _jsonPath); +std::optional jsonValueByPath(Json const& _node, std::string_view _jsonPath); + +std::string removeNlohmannInternalErrorIdentifier(std::string const& _input); namespace detail { @@ -82,60 +93,95 @@ namespace detail template struct helper; -template +template struct helper_impl { - static bool isOfType(Json::Value const& _input) + static bool isOfType(Json const& _input) { return (_input.*checkMember)(); } - static T get(Json::Value const& _input) + static T get(Json const& _input) { + assertThrow(isOfType(_input), InvalidType, ""); return (_input.*convertMember)(); } - static T getOrDefault(Json::Value const& _input, T _default = {}) + static T getOrDefault(Json const& _input, std::string const& _name, T _default = {}) { T result = _default; - if (isOfType(_input)) - result = (_input.*convertMember)(); + if (_input.contains(_name) && isOfType(_input[_name])) + result = (_input[_name].*convertMember)(); return result; } }; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; +template +struct helper_impl_with_range_check +{ + static bool isOfType(Json const& _input) + { + if ( (_input.*checkMember)()) + { + T value = (_input.*convertMember)(); + return (value >= std::numeric_limits::min() && value <= std::numeric_limits::max()); + } + return false; + } + + static RT get(Json const& _input) + { + assertThrow(isOfType(_input), InvalidType, ""); + return static_cast((_input.*convertMember)()); + } + + static RT getOrDefault(Json const& _input, std::string const& _name, RT _default = {}) + { + RT value = _default; + if (_input.contains(_name) && isOfType(_input[_name])) + value = static_cast((_input[_name].*convertMember)()); + return value; + } +}; + +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; + +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; } // namespace detail template -bool isOfType(Json::Value const& _input) +bool isOfType(Json const& _input) { return detail::helper::isOfType(_input); } template -bool isOfTypeIfExists(Json::Value const& _input, std::string const& _name) +bool isOfTypeIfExists(Json const& _input, std::string const& _name) { - if (_input.isMember(_name)) + if (_input.contains(_name)) return isOfType(_input[_name]); return true; } template -T get(Json::Value const& _input) +T get(Json const& _input) { return detail::helper::get(_input); } template -T getOrDefault(Json::Value const& _input, T _default = {}) +T getOrDefault(Json const& _input, std::string const& _name, T _default = {}) { - return detail::helper::getOrDefault(_input, _default); + return detail::helper::getOrDefault(_input, _name, _default); } } // namespace solidity::util diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index bf2468b4e4bb..a89e4967aa4e 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -29,25 +29,25 @@ namespace solidity::yul { -Json::Value AsmJsonConverter::operator()(Block const& _node) const +Json AsmJsonConverter::operator()(Block const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulBlock"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulBlock"); ret["statements"] = vectorOfVariantsToJson(_node.statements); return ret; } -Json::Value AsmJsonConverter::operator()(TypedName const& _node) const +Json AsmJsonConverter::operator()(TypedName const& _node) const { yulAssert(!_node.name.empty(), "Invalid variable name."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); ret["name"] = _node.name.str(); ret["type"] = _node.type.str(); return ret; } -Json::Value AsmJsonConverter::operator()(Literal const& _node) const +Json AsmJsonConverter::operator()(Literal const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulLiteral"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulLiteral"); switch (_node.kind) { case LiteralKind::Number: @@ -71,94 +71,92 @@ Json::Value AsmJsonConverter::operator()(Literal const& _node) const return ret; } -Json::Value AsmJsonConverter::operator()(Identifier const& _node) const +Json AsmJsonConverter::operator()(Identifier const& _node) const { yulAssert(!_node.name.empty(), "Invalid identifier"); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); ret["name"] = _node.name.str(); return ret; } -Json::Value AsmJsonConverter::operator()(Assignment const& _node) const +Json AsmJsonConverter::operator()(Assignment const& _node) const { yulAssert(_node.variableNames.size() >= 1, "Invalid assignment syntax"); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulAssignment"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulAssignment"); for (auto const& var: _node.variableNames) - ret["variableNames"].append((*this)(var)); - ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue; + ret["variableNames"].emplace_back((*this)(var)); + ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json(); return ret; } -Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const +Json AsmJsonConverter::operator()(FunctionCall const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionCall"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionCall"); ret["functionName"] = (*this)(_node.functionName); ret["arguments"] = vectorOfVariantsToJson(_node.arguments); return ret; } -Json::Value AsmJsonConverter::operator()(ExpressionStatement const& _node) const +Json AsmJsonConverter::operator()(ExpressionStatement const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulExpressionStatement"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulExpressionStatement"); ret["expression"] = std::visit(*this, _node.expression); return ret; } -Json::Value AsmJsonConverter::operator()(VariableDeclaration const& _node) const +Json AsmJsonConverter::operator()(VariableDeclaration const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulVariableDeclaration"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulVariableDeclaration"); for (auto const& var: _node.variables) - ret["variables"].append((*this)(var)); - - ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue; - + ret["variables"].emplace_back((*this)(var)); + ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json(); return ret; } -Json::Value AsmJsonConverter::operator()(FunctionDefinition const& _node) const +Json AsmJsonConverter::operator()(FunctionDefinition const& _node) const { yulAssert(!_node.name.empty(), "Invalid function name."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionDefinition"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionDefinition"); ret["name"] = _node.name.str(); for (auto const& var: _node.parameters) - ret["parameters"].append((*this)(var)); + ret["parameters"].emplace_back((*this)(var)); for (auto const& var: _node.returnVariables) - ret["returnVariables"].append((*this)(var)); + ret["returnVariables"].emplace_back((*this)(var)); ret["body"] = (*this)(_node.body); return ret; } -Json::Value AsmJsonConverter::operator()(If const& _node) const +Json AsmJsonConverter::operator()(If const& _node) const { yulAssert(_node.condition, "Invalid if condition."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIf"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIf"); ret["condition"] = std::visit(*this, *_node.condition); ret["body"] = (*this)(_node.body); return ret; } -Json::Value AsmJsonConverter::operator()(Switch const& _node) const +Json AsmJsonConverter::operator()(Switch const& _node) const { yulAssert(_node.expression, "Invalid expression pointer."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulSwitch"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulSwitch"); ret["expression"] = std::visit(*this, *_node.expression); for (auto const& var: _node.cases) - ret["cases"].append((*this)(var)); + ret["cases"].emplace_back((*this)(var)); return ret; } -Json::Value AsmJsonConverter::operator()(Case const& _node) const +Json AsmJsonConverter::operator()(Case const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulCase"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulCase"); ret["value"] = _node.value ? (*this)(*_node.value) : "default"; ret["body"] = (*this)(_node.body); return ret; } -Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const +Json AsmJsonConverter::operator()(ForLoop const& _node) const { yulAssert(_node.condition, "Invalid for loop condition."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulForLoop"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulForLoop"); ret["pre"] = (*this)(_node.pre); ret["condition"] = std::visit(*this, *_node.condition); ret["post"] = (*this)(_node.post); @@ -166,24 +164,24 @@ Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const return ret; } -Json::Value AsmJsonConverter::operator()(Break const& _node) const +Json AsmJsonConverter::operator()(Break const& _node) const { return createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulBreak"); } -Json::Value AsmJsonConverter::operator()(Continue const& _node) const +Json AsmJsonConverter::operator()(Continue const& _node) const { return createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulContinue"); } -Json::Value AsmJsonConverter::operator()(Leave const& _node) const +Json AsmJsonConverter::operator()(Leave const& _node) const { return createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulLeave"); } -Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const +Json AsmJsonConverter::createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const { - Json::Value ret{Json::objectValue}; + Json ret; ret["nodeType"] = std::move(_nodeType); auto srcLocation = [&](int start, int end) -> std::string { @@ -196,11 +194,11 @@ Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _ori } template -Json::Value AsmJsonConverter::vectorOfVariantsToJson(std::vector const& _vec) const +Json AsmJsonConverter::vectorOfVariantsToJson(std::vector const& _vec) const { - Json::Value ret{Json::arrayValue}; + Json ret = Json::array(); for (auto const& var: _vec) - ret.append(std::visit(*this, var)); + ret.emplace_back(std::visit(*this, var)); return ret; } diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 236ecbba579c..9c4b5d5e8ebc 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -36,35 +36,35 @@ namespace solidity::yul /** * Converter of the yul AST into JSON format */ -class AsmJsonConverter: public boost::static_visitor +class AsmJsonConverter: public boost::static_visitor { public: /// Create a converter to JSON for any block of inline assembly /// @a _sourceIndex to be used to abbreviate source name in the source locations explicit AsmJsonConverter(std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} - Json::Value operator()(Block const& _node) const; - Json::Value operator()(TypedName const& _node) const; - Json::Value operator()(Literal const& _node) const; - Json::Value operator()(Identifier const& _node) const; - Json::Value operator()(Assignment const& _node) const; - Json::Value operator()(VariableDeclaration const& _node) const; - Json::Value operator()(FunctionDefinition const& _node) const; - Json::Value operator()(FunctionCall const& _node) const; - Json::Value operator()(If const& _node) const; - Json::Value operator()(Switch const& _node) const; - Json::Value operator()(Case const& _node) const; - Json::Value operator()(ForLoop const& _node) const; - Json::Value operator()(Break const& _node) const; - Json::Value operator()(Continue const& _node) const; - Json::Value operator()(Leave const& _node) const; - Json::Value operator()(ExpressionStatement const& _node) const; - Json::Value operator()(Label const& _node) const; + Json operator()(Block const& _node) const; + Json operator()(TypedName const& _node) const; + Json operator()(Literal const& _node) const; + Json operator()(Identifier const& _node) const; + Json operator()(Assignment const& _node) const; + Json operator()(VariableDeclaration const& _node) const; + Json operator()(FunctionDefinition const& _node) const; + Json operator()(FunctionCall const& _node) const; + Json operator()(If const& _node) const; + Json operator()(Switch const& _node) const; + Json operator()(Case const& _node) const; + Json operator()(ForLoop const& _node) const; + Json operator()(Break const& _node) const; + Json operator()(Continue const& _node) const; + Json operator()(Leave const& _node) const; + Json operator()(ExpressionStatement const& _node) const; + Json operator()(Label const& _node) const; private: - Json::Value createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const; + Json createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const; template - Json::Value vectorOfVariantsToJson(std::vector const& vec) const; + Json vectorOfVariantsToJson(std::vector const& vec) const; std::optional const m_sourceIndex; }; diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 190dcda21d05..41e065853517 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -41,15 +41,15 @@ namespace solidity::yul using SourceLocation = langutil::SourceLocation; -SourceLocation const AsmJsonImporter::createSourceLocation(Json::Value const& _node) +SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node) { - yulAssert(member(_node, "src").isString(), "'src' must be a string"); + yulAssert(member(_node, "src").is_string(), "'src' must be a string"); - return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["src"].get(), m_sourceNames); } template -T AsmJsonImporter::createAsmNode(Json::Value const& _node) +T AsmJsonImporter::createAsmNode(Json const& _node) { T r; SourceLocation nativeLocation = createSourceLocation(_node); @@ -61,26 +61,26 @@ T AsmJsonImporter::createAsmNode(Json::Value const& _node) return r; } -Json::Value AsmJsonImporter::member(Json::Value const& _node, std::string const& _name) +Json AsmJsonImporter::member(Json const& _node, std::string const& _name) { - if (!_node.isMember(_name)) - return Json::nullValue; + if (!_node.contains(_name)) + return Json(); return _node[_name]; } -TypedName AsmJsonImporter::createTypedName(Json::Value const& _node) +TypedName AsmJsonImporter::createTypedName(Json const& _node) { auto typedName = createAsmNode(_node); - typedName.type = YulString{member(_node, "type").asString()}; - typedName.name = YulString{member(_node, "name").asString()}; + typedName.type = YulString{member(_node, "type").get()}; + typedName.name = YulString{member(_node, "name").get()}; return typedName; } -Statement AsmJsonImporter::createStatement(Json::Value const& _node) +Statement AsmJsonImporter::createStatement(Json const& _node) { - Json::Value jsonNodeType = member(_node, "nodeType"); - yulAssert(jsonNodeType.isString(), "Expected \"nodeType\" to be of type string!"); - std::string nodeType = jsonNodeType.asString(); + Json jsonNodeType = member(_node, "nodeType"); + yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!"); + std::string nodeType = jsonNodeType.get(); yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix"); nodeType = nodeType.substr(3); @@ -114,11 +114,11 @@ Statement AsmJsonImporter::createStatement(Json::Value const& _node) util::unreachable(); } -Expression AsmJsonImporter::createExpression(Json::Value const& _node) +Expression AsmJsonImporter::createExpression(Json const& _node) { - Json::Value jsonNodeType = member(_node, "nodeType"); - yulAssert(jsonNodeType.isString(), "Expected \"nodeType\" to be of type string!"); - std::string nodeType = jsonNodeType.asString(); + Json jsonNodeType = member(_node, "nodeType"); + yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!"); + std::string nodeType = jsonNodeType.get(); yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix"); nodeType = nodeType.substr(3); @@ -136,7 +136,7 @@ Expression AsmJsonImporter::createExpression(Json::Value const& _node) util::unreachable(); } -std::vector AsmJsonImporter::createExpressionVector(Json::Value const& _array) +std::vector AsmJsonImporter::createExpressionVector(Json const& _array) { std::vector ret; for (auto& var: _array) @@ -144,7 +144,7 @@ std::vector AsmJsonImporter::createExpressionVector(Json::Value cons return ret; } -std::vector AsmJsonImporter::createStatementVector(Json::Value const& _array) +std::vector AsmJsonImporter::createStatementVector(Json const& _array) { std::vector ret; for (auto& var: _array) @@ -152,25 +152,25 @@ std::vector AsmJsonImporter::createStatementVector(Json::Value const& return ret; } -Block AsmJsonImporter::createBlock(Json::Value const& _node) +Block AsmJsonImporter::createBlock(Json const& _node) { auto block = createAsmNode(_node); block.statements = createStatementVector(_node["statements"]); return block; } -Literal AsmJsonImporter::createLiteral(Json::Value const& _node) +Literal AsmJsonImporter::createLiteral(Json const& _node) { auto lit = createAsmNode(_node); - std::string kind = member(_node, "kind").asString(); + std::string kind = member(_node, "kind").get(); - solAssert(member(_node, "hexValue").isString() || member(_node, "value").isString(), ""); - if (_node.isMember("hexValue")) - lit.value = YulString{util::asString(util::fromHex(member(_node, "hexValue").asString()))}; + solAssert(member(_node, "hexValue").is_string() || member(_node, "value").is_string(), ""); + if (_node.contains("hexValue")) + lit.value = YulString{util::asString(util::fromHex(member(_node, "hexValue").get()))}; else - lit.value = YulString{member(_node, "value").asString()}; + lit.value = YulString{member(_node, "value").get()}; - lit.type= YulString{member(_node, "type").asString()}; + lit.type= YulString{member(_node, "type").get()}; if (kind == "number") { @@ -207,23 +207,23 @@ Literal AsmJsonImporter::createLiteral(Json::Value const& _node) return lit; } -Leave AsmJsonImporter::createLeave(Json::Value const& _node) +Leave AsmJsonImporter::createLeave(Json const& _node) { return createAsmNode(_node); } -Identifier AsmJsonImporter::createIdentifier(Json::Value const& _node) +Identifier AsmJsonImporter::createIdentifier(Json const& _node) { auto identifier = createAsmNode(_node); - identifier.name = YulString(member(_node, "name").asString()); + identifier.name = YulString(member(_node, "name").get()); return identifier; } -Assignment AsmJsonImporter::createAssignment(Json::Value const& _node) +Assignment AsmJsonImporter::createAssignment(Json const& _node) { auto assignment = createAsmNode(_node); - if (_node.isMember("variableNames")) + if (_node.contains("variableNames")) for (auto const& var: member(_node, "variableNames")) assignment.variableNames.emplace_back(createIdentifier(var)); @@ -231,7 +231,7 @@ Assignment AsmJsonImporter::createAssignment(Json::Value const& _node) return assignment; } -FunctionCall AsmJsonImporter::createFunctionCall(Json::Value const& _node) +FunctionCall AsmJsonImporter::createFunctionCall(Json const& _node) { auto functionCall = createAsmNode(_node); @@ -243,35 +243,35 @@ FunctionCall AsmJsonImporter::createFunctionCall(Json::Value const& _node) return functionCall; } -ExpressionStatement AsmJsonImporter::createExpressionStatement(Json::Value const& _node) +ExpressionStatement AsmJsonImporter::createExpressionStatement(Json const& _node) { auto statement = createAsmNode(_node); statement.expression = createExpression(member(_node, "expression")); return statement; } -VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json::Value const& _node) +VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node) { auto varDec = createAsmNode(_node); for (auto const& var: member(_node, "variables")) varDec.variables.emplace_back(createTypedName(var)); - if (_node.isMember("value")) + if (_node.contains("value")) varDec.value = std::make_unique(createExpression(member(_node, "value"))); return varDec; } -FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json::Value const& _node) +FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node) { auto funcDef = createAsmNode(_node); - funcDef.name = YulString{member(_node, "name").asString()}; + funcDef.name = YulString{member(_node, "name").get()}; - if (_node.isMember("parameters")) + if (_node.contains("parameters")) for (auto const& var: member(_node, "parameters")) funcDef.parameters.emplace_back(createTypedName(var)); - if (_node.isMember("returnVariables")) + if (_node.contains("returnVariables")) for (auto const& var: member(_node, "returnVariables")) funcDef.returnVariables.emplace_back(createTypedName(var)); @@ -279,7 +279,7 @@ FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json::Value const& return funcDef; } -If AsmJsonImporter::createIf(Json::Value const& _node) +If AsmJsonImporter::createIf(Json const& _node) { auto ifStatement = createAsmNode(_node); ifStatement.condition = std::make_unique(createExpression(member(_node, "condition"))); @@ -287,19 +287,19 @@ If AsmJsonImporter::createIf(Json::Value const& _node) return ifStatement; } -Case AsmJsonImporter::createCase(Json::Value const& _node) +Case AsmJsonImporter::createCase(Json const& _node) { auto caseStatement = createAsmNode(_node); auto const& value = member(_node, "value"); - if (value.isString()) - yulAssert(value.asString() == "default", "Expected default case"); + if (value.is_string()) + yulAssert(value.get() == "default", "Expected default case"); else caseStatement.value = std::make_unique(createLiteral(value)); caseStatement.body = createBlock(member(_node, "body")); return caseStatement; } -Switch AsmJsonImporter::createSwitch(Json::Value const& _node) +Switch AsmJsonImporter::createSwitch(Json const& _node) { auto switchStatement = createAsmNode(_node); switchStatement.expression = std::make_unique(createExpression(member(_node, "expression"))); @@ -308,7 +308,7 @@ Switch AsmJsonImporter::createSwitch(Json::Value const& _node) return switchStatement; } -ForLoop AsmJsonImporter::createForLoop(Json::Value const& _node) +ForLoop AsmJsonImporter::createForLoop(Json const& _node) { auto forLoop = createAsmNode(_node); forLoop.pre = createBlock(member(_node, "pre")); @@ -318,12 +318,12 @@ ForLoop AsmJsonImporter::createForLoop(Json::Value const& _node) return forLoop; } -Break AsmJsonImporter::createBreak(Json::Value const& _node) +Break AsmJsonImporter::createBreak(Json const& _node) { return createAsmNode(_node); } -Continue AsmJsonImporter::createContinue(Json::Value const& _node) +Continue AsmJsonImporter::createContinue(Json const& _node) { return createAsmNode(_node); } diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index 506352fa4811..87933761a654 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -23,7 +23,7 @@ #pragma once -#include +#include #include #include @@ -41,36 +41,36 @@ class AsmJsonImporter explicit AsmJsonImporter(std::vector> const& _sourceNames): m_sourceNames(_sourceNames) {} - yul::Block createBlock(Json::Value const& _node); + yul::Block createBlock(Json const& _node); private: - langutil::SourceLocation const createSourceLocation(Json::Value const& _node); + langutil::SourceLocation const createSourceLocation(Json const& _node); template - T createAsmNode(Json::Value const& _node); + T createAsmNode(Json const& _node); /// helper function to access member functions of the JSON /// and throw an error if it does not exist - Json::Value member(Json::Value const& _node, std::string const& _name); + Json member(Json const& _node, std::string const& _name); - yul::Statement createStatement(Json::Value const& _node); - yul::Expression createExpression(Json::Value const& _node); - std::vector createStatementVector(Json::Value const& _array); - std::vector createExpressionVector(Json::Value const& _array); + yul::Statement createStatement(Json const& _node); + yul::Expression createExpression(Json const& _node); + std::vector createStatementVector(Json const& _array); + std::vector createExpressionVector(Json const& _array); - yul::TypedName createTypedName(Json::Value const& _node); - yul::Literal createLiteral(Json::Value const& _node); - yul::Leave createLeave(Json::Value const& _node); - yul::Identifier createIdentifier(Json::Value const& _node); - yul::Assignment createAssignment(Json::Value const& _node); - yul::FunctionCall createFunctionCall(Json::Value const& _node); - yul::ExpressionStatement createExpressionStatement(Json::Value const& _node); - yul::VariableDeclaration createVariableDeclaration(Json::Value const& _node); - yul::FunctionDefinition createFunctionDefinition(Json::Value const& _node); - yul::If createIf(Json::Value const& _node); - yul::Case createCase(Json::Value const& _node); - yul::Switch createSwitch(Json::Value const& _node); - yul::ForLoop createForLoop(Json::Value const& _node); - yul::Break createBreak(Json::Value const& _node); - yul::Continue createContinue(Json::Value const& _node); + yul::TypedName createTypedName(Json const& _node); + yul::Literal createLiteral(Json const& _node); + yul::Leave createLeave(Json const& _node); + yul::Identifier createIdentifier(Json const& _node); + yul::Assignment createAssignment(Json const& _node); + yul::FunctionCall createFunctionCall(Json const& _node); + yul::ExpressionStatement createExpressionStatement(Json const& _node); + yul::VariableDeclaration createVariableDeclaration(Json const& _node); + yul::FunctionDefinition createFunctionDefinition(Json const& _node); + yul::If createIf(Json const& _node); + yul::Case createCase(Json const& _node); + yul::Switch createSwitch(Json const& _node); + yul::ForLoop createForLoop(Json const& _node); + yul::Break createBreak(Json const& _node); + yul::Continue createContinue(Json const& _node); std::vector> const& m_sourceNames; }; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 0d3d66c8e5f2..260cb733011f 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -75,27 +75,27 @@ std::string Object::toString( return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; } -Json::Value Data::toJson() const +Json Data::toJson() const { - Json::Value ret{Json::objectValue}; + Json ret; ret["nodeType"] = "YulData"; ret["value"] = util::toHex(data); return ret; } -Json::Value Object::toJson() const +Json Object::toJson() const { yulAssert(code, "No code"); - Json::Value codeJson{Json::objectValue}; + Json codeJson; codeJson["nodeType"] = "YulCode"; codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(*code); - Json::Value subObjectsJson{Json::arrayValue}; + Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) - subObjectsJson.append(subObject->toJson()); + subObjectsJson.emplace_back(subObject->toJson()); - Json::Value ret{Json::objectValue}; + Json ret; ret["nodeType"] = "YulObject"; ret["name"] = name.str(); ret["code"] = codeJson; diff --git a/libyul/Object.h b/libyul/Object.h index 5f88d3bc7ff6..54a8080d08c0 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -28,11 +28,11 @@ #include #include +#include #include #include #include -#include namespace solidity::yul { @@ -58,7 +58,7 @@ struct ObjectNode langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const = 0; - virtual Json::Value toJson() const = 0; + virtual Json toJson() const = 0; }; /** @@ -75,7 +75,7 @@ struct Data: public ObjectNode langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const override; - Json::Value toJson() const override; + Json toJson() const override; }; @@ -98,7 +98,7 @@ struct Object: public ObjectNode langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const; /// @returns a compact JSON representation of the AST. - Json::Value toJson() const; + Json toJson() const; /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 6c89cadbdfd9..a4341cba308c 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -312,7 +312,7 @@ std::string YulStack::print( return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n"; } -Json::Value YulStack::astJson() const +Json YulStack::astJson() const { yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 700fd2b3baa3..27f530b44c4a 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -33,8 +34,6 @@ #include -#include - #include #include @@ -132,7 +131,7 @@ class YulStack: public langutil::CharStreamProvider std::string print( langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const; - Json::Value astJson() const; + Json astJson() const; /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 51db3a14d5b3..954c9f2af7af 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -771,7 +771,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi yulAssert(util::contains(m_currentFunctionInfo->returnVariables, std::get(_slot))); // Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference // will not matter here. - opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion());; + opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion()); } } }; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 4c08efb51a00..514f84c209df 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -353,23 +353,23 @@ void CommandLineInterface::handleSignatureHashes(std::string const& _contract) if (!m_options.compiler.outputs.signatureHashes) return; - Json::Value interfaceSymbols = m_compiler->interfaceSymbols(_contract); + Json interfaceSymbols = m_compiler->interfaceSymbols(_contract); std::string out = "Function signatures:\n"; - for (auto const& name: interfaceSymbols["methods"].getMemberNames()) - out += interfaceSymbols["methods"][name].asString() + ": " + name + "\n"; + for (auto const& [name, value]: interfaceSymbols["methods"].items()) + out += value.get() + ": " + name + "\n"; - if (interfaceSymbols.isMember("errors")) + if (interfaceSymbols.contains("errors")) { out += "\nError signatures:\n"; - for (auto const& name: interfaceSymbols["errors"].getMemberNames()) - out += interfaceSymbols["errors"][name].asString() + ": " + name + "\n"; + for (auto const& [name, value]: interfaceSymbols["errors"].items()) + out += value.get() + ": " + name + "\n"; } - if (interfaceSymbols.isMember("events")) + if (interfaceSymbols.contains("events")) { out += "\nEvent signatures:\n"; - for (auto const& name: interfaceSymbols["events"].getMemberNames()) - out += interfaceSymbols["events"][name].asString() + ": " + name + "\n"; + for (auto const& [name, value]: interfaceSymbols["events"].items()) + out += value.get() + ": " + name + "\n"; } if (!m_options.output.dir.empty()) @@ -467,40 +467,40 @@ void CommandLineInterface::handleGasEstimation(std::string const& _contract) { solAssert(CompilerInputModes.count(m_options.input.mode) == 1); - Json::Value estimates = m_compiler->gasEstimates(_contract); + Json estimates = m_compiler->gasEstimates(_contract); sout() << "Gas estimation:" << std::endl; - if (estimates["creation"].isObject()) + if (estimates["creation"].is_object()) { - Json::Value creation = estimates["creation"]; + Json creation = estimates["creation"]; sout() << "construction:" << std::endl; - sout() << " " << creation["executionCost"].asString(); - sout() << " + " << creation["codeDepositCost"].asString(); - sout() << " = " << creation["totalCost"].asString() << std::endl; + sout() << " " << creation["executionCost"].get(); + sout() << " + " << creation["codeDepositCost"].get(); + sout() << " = " << creation["totalCost"].get() << std::endl; } - if (estimates["external"].isObject()) + if (estimates["external"].is_object()) { - Json::Value externalFunctions = estimates["external"]; + Json externalFunctions = estimates["external"]; sout() << "external:" << std::endl; - for (auto const& name: externalFunctions.getMemberNames()) + for (auto const& [name, value]: externalFunctions.items()) { if (name.empty()) sout() << " fallback:\t"; else sout() << " " << name << ":\t"; - sout() << externalFunctions[name].asString() << std::endl; + sout() << value.get() << std::endl; } } - if (estimates["internal"].isObject()) + if (estimates["internal"].is_object()) { - Json::Value internalFunctions = estimates["internal"]; + Json internalFunctions = estimates["internal"]; sout() << "internal:" << std::endl; - for (auto const& name: internalFunctions.getMemberNames()) + for (auto const& [name, value]: internalFunctions.items()) { sout() << " " << name << ":\t"; - sout() << internalFunctions[name].asString() << std::endl; + sout() << value.get() << std::endl; } } } @@ -613,27 +613,27 @@ void CommandLineInterface::readInputFiles() solThrow(CommandLineValidationError, "All specified input files either do not exist or are not regular files."); } -std::map CommandLineInterface::parseAstFromInput() +std::map CommandLineInterface::parseAstFromInput() { solAssert(m_options.input.mode == InputMode::CompilerWithASTImport); - std::map sourceJsons; + std::map sourceJsons; std::map tmpSources; for (SourceCode const& sourceCode: m_fileReader.sourceUnits() | ranges::views::values) { - Json::Value ast; + Json ast; astAssert(jsonParseStrict(sourceCode, ast), "Input file could not be parsed to JSON"); - astAssert(ast.isMember("sources"), "Invalid Format for import-JSON: Must have 'sources'-object"); + astAssert(ast.contains("sources"), "Invalid Format for import-JSON: Must have 'sources'-object"); - for (auto& src: ast["sources"].getMemberNames()) + for (auto const& [src, value]: ast["sources"].items()) { - std::string astKey = ast["sources"][src].isMember("ast") ? "ast" : "AST"; + std::string astKey = value.contains("ast") ? "ast" : "AST"; - astAssert(ast["sources"][src].isMember(astKey), "astkey is not member"); - astAssert(ast["sources"][src][astKey]["nodeType"].asString() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); + astAssert(ast["sources"][src].contains(astKey), "astkey is not member"); + astAssert(ast["sources"][src][astKey]["nodeType"].get() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); astAssert(sourceJsons.count(src) == 0, "All sources must have unique names"); - sourceJsons.emplace(src, std::move(ast["sources"][src][astKey])); + sourceJsons.emplace(src, std::move(value[astKey])); tmpSources[src] = util::jsonCompactPrint(ast); } } @@ -942,16 +942,16 @@ void CommandLineInterface::handleCombinedJSON() if (!m_options.compiler.combinedJsonRequests.has_value()) return; - Json::Value output(Json::objectValue); + Json output; output[g_strVersion] = frontend::VersionString; std::vector contracts = m_assemblyStack->contractNames(); if (!contracts.empty()) - output[g_strContracts] = Json::Value(Json::objectValue); + output[g_strContracts] = Json::object(); for (std::string const& contractName: contracts) { - Json::Value& contractData = output[g_strContracts][contractName] = Json::objectValue; + Json& contractData = output[g_strContracts][contractName] = Json::object(); // NOTE: The state checks here are more strict that in Standard JSON. There we allow // requesting certain outputs even if compilation fails as long as analysis went ok. @@ -1013,19 +1013,19 @@ void CommandLineInterface::handleCombinedJSON() if (needsSourceList) { // Indices into this array are used to abbreviate source names in source locations. - output[g_strSourceList] = Json::Value(Json::arrayValue); + output[g_strSourceList] = Json::array(); for (auto const& source: m_assemblyStack->sourceNames()) - output[g_strSourceList].append(source); + output[g_strSourceList].emplace_back(source); } if (m_options.compiler.combinedJsonRequests->ast) { solAssert(m_compiler); - output[g_strSources] = Json::Value(Json::objectValue); + output[g_strSources] = Json::object(); for (auto const& sourceCode: m_fileReader.sourceUnits()) { - output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue); + output[g_strSources][sourceCode.first] = Json::object(); output[g_strSources][sourceCode.first]["AST"] = ASTJsonExporter( m_compiler->state(), m_compiler->sourceIndices() diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 1fb4ac00bcb1..bcebcbcfd3be 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -120,7 +120,7 @@ class CommandLineInterface /// such that they can be imported into the compiler (importASTs()) /// (produced by --combined-json ast /// or standard-json output - std::map parseAstFromInput(); + std::map parseAstFromInput(); /// Create a file in the given directory /// @arg _fileName the name of the file diff --git a/test/Metadata.cpp b/test/Metadata.cpp index 2fea65c65be0..cdfcdfb19c48 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -172,33 +172,33 @@ std::optional> parseCBORMetadata(bytes const& bool isValidMetadata(std::string const& _serialisedMetadata) { - Json::Value metadata; + Json metadata; if (!util::jsonParseStrict(_serialisedMetadata, metadata)) return false; return isValidMetadata(metadata); } -bool isValidMetadata(Json::Value const& _metadata) +bool isValidMetadata(Json const& _metadata) { if ( - !_metadata.isObject() || - !_metadata.isMember("version") || - !_metadata.isMember("language") || - !_metadata.isMember("compiler") || - !_metadata.isMember("settings") || - !_metadata.isMember("sources") || - !_metadata.isMember("output") || - !_metadata["settings"].isMember("evmVersion") || - !_metadata["settings"].isMember("metadata") || - !_metadata["settings"]["metadata"].isMember("bytecodeHash") + !_metadata.is_object() || + !_metadata.contains("version") || + !_metadata.contains("language") || + !_metadata.contains("compiler") || + !_metadata.contains("settings") || + !_metadata.contains("sources") || + !_metadata.contains("output") || + !_metadata["settings"].contains("evmVersion") || + !_metadata["settings"].contains("metadata") || + !_metadata["settings"]["metadata"].contains("bytecodeHash") ) return false; - if (!_metadata["version"].isNumeric() || _metadata["version"] != 1) + if (!_metadata["version"].is_number() || _metadata["version"] != 1) return false; - if (!_metadata["language"].isString() || _metadata["language"].asString() != "Solidity") + if (!_metadata["language"].is_string() || _metadata["language"].get() != "Solidity") return false; /// @TODO add more strict checks diff --git a/test/Metadata.h b/test/Metadata.h index 86b43e245f18..f3dae0cbdea0 100644 --- a/test/Metadata.h +++ b/test/Metadata.h @@ -53,6 +53,6 @@ std::optional> parseCBORMetadata(bytes const& bool isValidMetadata(std::string const& _serialisedMetadata); /// Expects a deserialised metadata JSON and returns true if the content is valid metadata. -bool isValidMetadata(Json::Value const& _metadata); +bool isValidMetadata(Json const& _metadata); } // end namespaces diff --git a/test/cmdlineTests/standard_import_with_comments/input.json b/test/cmdlineTests/standard_import_with_comments/input.json new file mode 100644 index 000000000000..4ed88177cf1f --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments/input.json @@ -0,0 +1,95 @@ +{ + "language": "SolidityAST", + "sources": { // this is a comment + "A": { + "ast": { + "absolutePath": "A", + "exportedSymbols": { + "C": [ + 6 /* and this another comment */ + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": /* and this is a comment too */[ + // this is a comment + { + /*this is a comment*/"id"/* and this is another comment too*/: 1, + "literals": [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": [ + 6 + ], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + }, + "settings": { + "outputSelection": { + "*": { + "": [ + "ast" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_with_comments/output.json b/test/cmdlineTests/standard_import_with_comments/output.json new file mode 100644 index 000000000000..6ecac5ca364d --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments/output.json @@ -0,0 +1,97 @@ +{ + "sources": + { + "A": + { + "ast": + { + "absolutePath": "A", + "exportedSymbols": + { + "C": + [ + 6 + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": + [ + { + "id": 1, + "literals": + [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": + [ + 6 + ], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": + [ + { + "body": + { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": + { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": + { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_import_with_comments_simple/input.json b/test/cmdlineTests/standard_import_with_comments_simple/input.json new file mode 100644 index 000000000000..21faca8c624e --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments_simple/input.json @@ -0,0 +1,85 @@ +{ + "language": "SolidityAST", + "sources": { + // this is a comment + "A": { + "ast": { + "absolutePath": "A", + "exportedSymbols": { + "C": [6 /* and this another comment */] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": ["solidity", ">=", "0.0"], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": [6], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["ast"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_with_comments_simple/output.json b/test/cmdlineTests/standard_import_with_comments_simple/output.json new file mode 100644 index 000000000000..6ecac5ca364d --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments_simple/output.json @@ -0,0 +1,97 @@ +{ + "sources": + { + "A": + { + "ast": + { + "absolutePath": "A", + "exportedSymbols": + { + "C": + [ + 6 + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": + [ + { + "id": 1, + "literals": + [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": + [ + 6 + ], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": + [ + { + "body": + { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": + { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": + { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_import_with_invalid_utf8/input.json b/test/cmdlineTests/standard_import_with_invalid_utf8/input.json new file mode 100644 index 000000000000..7b54aebfbb66 --- /dev/null +++ b/test/cmdlineTests/standard_import_with_invalid_utf8/input.json @@ -0,0 +1,29 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 36, + "end": 51, + "name": "PUSH", + "source": 0, + "value": "\ud800" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": [ + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_with_invalid_utf8/output.json b/test/cmdlineTests/standard_import_with_invalid_utf8/output.json new file mode 100644 index 000000000000..057e4fe169c6 --- /dev/null +++ b/test/cmdlineTests/standard_import_with_invalid_utf8/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "parse error at line 12, column 23: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\ud800\"'", + "message": "parse error at line 12, column 23: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\ud800\"'", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_non_utf8_filename/input.json b/test/cmdlineTests/standard_non_utf8_filename/input.json new file mode 100644 index 000000000000..b0f7d595768a --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename/input.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": + { + "ÿ": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; pragma abicoder v2; contract C { function f() public pure {} }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["ir"] } + } + } +} diff --git a/test/cmdlineTests/standard_non_utf8_filename/output.json b/test/cmdlineTests/standard_non_utf8_filename/output.json new file mode 100644 index 000000000000..a74a83a98975 --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "message": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_non_utf8_filename2/input.json b/test/cmdlineTests/standard_non_utf8_filename2/input.json new file mode 100644 index 000000000000..7310c1472397 --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename2/input.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": + { + "ÿý": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; pragma abicoder v2; contract C { function f() public pure {} }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["ir"] } + } + } +} diff --git a/test/cmdlineTests/standard_non_utf8_filename2/output.json b/test/cmdlineTests/standard_non_utf8_filename2/output.json new file mode 100644 index 000000000000..a74a83a98975 --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename2/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "message": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_raw_utf16_filename/input.json b/test/cmdlineTests/standard_raw_utf16_filename/input.json new file mode 100644 index 0000000000000000000000000000000000000000..1c4a1b3232cf6ae00d16546bd94afcc8ee2d4fd6 GIT binary patch literal 297 zcmYk1O-sZu5QckAe#I~+mF;fPTNk~opu!#&dQeag*>qY4Vp7sXkkG%qXVX$phGCcw zo_XIS1sY}hsCvR0uyKZ44nMfbi_t}|X~bHJB!$4@xwsT2$EA2()90?850(po+Sx!h z%&6TCn$zQ3d1Os?r1GWB3+|YF4Ns?IdAF@T?BG@ZrC?m&!oz*Ft@f~v)tR+x$;0>U z9%i&xI=}%EbkXX-&O&!}4MRK|*133sG{J;f&LqXOc%Ts2_J1Z^3_}bJ8Cn4UwBKaa R32-j&$R0l-Ll%&n'; expected string literal", + "message": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"'; expected string literal", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 2b01ae03c7ec..afad9d13ddc5 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) "{\"begin\":8,\"end\":18,\"name\":\"MSTORE\",\"source\":2}" "]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"},\"sourceList\":[\"root.asm\",\"sub.asm\",\"verbatim.asm\"]}" }; - Json::Value jsonValue; + Json jsonValue; BOOST_CHECK(util::jsonParseStrict(json, jsonValue)); BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue)); } diff --git a/test/libsolidity/ASTPropertyTest.cpp b/test/libsolidity/ASTPropertyTest.cpp index 8dc2c2930bfc..05c9b8786db8 100644 --- a/test/libsolidity/ASTPropertyTest.cpp +++ b/test/libsolidity/ASTPropertyTest.cpp @@ -108,20 +108,20 @@ void ASTPropertyTest::readExpectations() m_expectation = formatExpectations(false /* _obtainedResult */); } -void ASTPropertyTest::extractTestsFromAST(Json::Value const& _astJson) +void ASTPropertyTest::extractTestsFromAST(Json const& _astJson) { - std::queue nodesToVisit; + std::queue nodesToVisit; nodesToVisit.push(_astJson); while (!nodesToVisit.empty()) { - Json::Value& node = nodesToVisit.front(); + Json& node = nodesToVisit.front(); - if (node.isArray()) + if (node.is_array()) for (auto&& member: node) nodesToVisit.push(member); - else if (node.isObject()) - for (std::string const& memberName: node.getMemberNames()) + else if (node.is_object()) + for (auto const& [memberName, value]: node.items()) { if (memberName != "documentation") { @@ -129,9 +129,8 @@ void ASTPropertyTest::extractTestsFromAST(Json::Value const& _astJson) continue; } - std::string nodeDocstring = node["documentation"].isObject() ? - node["documentation"]["text"].asString() : - node["documentation"].asString(); + std::string nodeDocstring = value.is_object() ? + value["text"].get() : value.get(); soltestAssert(!nodeDocstring.empty()); std::vector pairs = readKeyValuePairs(nodeDocstring); @@ -150,17 +149,22 @@ void ASTPropertyTest::extractTestsFromAST(Json::Value const& _astJson) ); m_tests[testId].property = testedProperty; - soltestAssert(node.isMember("nodeType")); - std::optional propertyNode = jsonValueByPath(node, testedProperty); + soltestAssert(node.contains("nodeType")); + std::optional propertyNode = jsonValueByPath(node, testedProperty); soltestAssert( propertyNode.has_value(), - node["nodeType"].asString() + " node does not have a property named \""s + testedProperty + "\"" + node["nodeType"].get() + " node does not have a property named \""s + testedProperty + "\"" ); soltestAssert( - !propertyNode->isObject() && !propertyNode->isArray(), + !propertyNode->is_object() && !propertyNode->is_array(), "Property \"" + testedProperty + "\" is an object or an array." ); - m_tests[testId].obtainedValue = propertyNode->asString(); + if (propertyNode->is_string()) + m_tests[testId].obtainedValue = propertyNode->get(); + else if (propertyNode->is_boolean()) + m_tests[testId].obtainedValue = fmt::format("{}", propertyNode->get()); + else + soltestAssert(false); } } @@ -195,8 +199,8 @@ TestCase::TestResult ASTPropertyTest::run(std::ostream& _stream, std::string con SourceReferenceFormatter::formatErrorInformation(compiler.errors(), compiler, _formatted) )); - Json::Value astJson = ASTJsonExporter(compiler.state()).toJson(compiler.ast("A")); - soltestAssert(astJson); + Json astJson = ASTJsonExporter(compiler.state()).toJson(compiler.ast("A")); + soltestAssert(!astJson.empty()); extractTestsFromAST(astJson); diff --git a/test/libsolidity/ASTPropertyTest.h b/test/libsolidity/ASTPropertyTest.h index e4cec05280b5..6130cedb299e 100644 --- a/test/libsolidity/ASTPropertyTest.h +++ b/test/libsolidity/ASTPropertyTest.h @@ -56,7 +56,7 @@ class ASTPropertyTest: public TestCase void readExpectations(); std::vector readKeyValuePairs(std::string const& _input); - void extractTestsFromAST(Json::Value const& _astJson); + void extractTestsFromAST(Json const& _astJson); std::string formatExpectations(bool _obtainedResult = true); std::vector m_testOrder; diff --git a/test/libsolidity/GasTest.cpp b/test/libsolidity/GasTest.cpp index 4786a2a86327..14722535e446 100644 --- a/test/libsolidity/GasTest.cpp +++ b/test/libsolidity/GasTest.cpp @@ -82,18 +82,18 @@ void GasTest::parseExpectations(std::istream& _stream) void GasTest::printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const { - Json::Value estimates = compiler().gasEstimates(compiler().lastContractName()); - for (auto groupIt = estimates.begin(); groupIt != estimates.end(); ++groupIt) + Json estimates = compiler().gasEstimates(compiler().lastContractName()); + for (auto& [key, group] : estimates.items()) { - _stream << _linePrefix << groupIt.key().asString() << ":" << std::endl; - for (auto it = groupIt->begin(); it != groupIt->end(); ++it) + _stream << _linePrefix << key << ":" << std::endl; + for (auto& [elementKey, value] : group.items()) { _stream << _linePrefix << " "; - if (it.key().asString().empty()) + if (elementKey.empty()) _stream << "fallback"; else - _stream << it.key().asString(); - _stream << ": " << it->asString() << std::endl; + _stream << elementKey; + _stream << ": " << value.get() << std::endl; } } } @@ -128,14 +128,14 @@ TestCase::TestResult GasTest::run(std::ostream& _stream, std::string const& _lin return TestResult::FatalError; } - Json::Value estimateGroups = compiler().gasEstimates(compiler().lastContractName()); + Json estimateGroups = compiler().gasEstimates(compiler().lastContractName()); if ( m_expectations.size() == estimateGroups.size() && boost::all(m_expectations, [&](auto const& expectations) { auto const& estimates = estimateGroups[expectations.first]; return estimates.size() == expectations.second.size() && boost::all(expectations.second, [&](auto const& entry) { - return entry.second == estimates[entry.first].asString(); + return entry.second == estimates[entry.first].template get(); }); }) ) diff --git a/test/libsolidity/LibSolc.cpp b/test/libsolidity/LibSolc.cpp index 1a7a6ba69633..f7a434dcfd25 100644 --- a/test/libsolidity/LibSolc.cpp +++ b/test/libsolidity/LibSolc.cpp @@ -36,30 +36,30 @@ namespace /// TODO: share this between StandardCompiler.cpp /// Helper to match a specific error type and message -bool containsError(Json::Value const& _compilerResult, std::string const& _type, std::string const& _message) +bool containsError(Json const& _compilerResult, std::string const& _type, std::string const& _message) { - if (!_compilerResult.isMember("errors")) + if (!_compilerResult.contains("errors")) return false; for (auto const& error: _compilerResult["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["type"].isString()); - BOOST_REQUIRE(error["message"].isString()); - if ((error["type"].asString() == _type) && (error["message"].asString() == _message)) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["type"].is_string()); + BOOST_REQUIRE(error["message"].is_string()); + if ((error["type"].get() == _type) && (error["message"].get() == _message)) return true; } return false; } -Json::Value compile(std::string const& _input, CStyleReadFileCallback _callback = nullptr) +Json compile(std::string const& _input, CStyleReadFileCallback _callback = nullptr) { char* output_ptr = solidity_compile(_input.c_str(), _callback, nullptr); std::string output(output_ptr); solidity_free(output_ptr); solidity_reset(); - Json::Value ret; + Json ret; BOOST_REQUIRE(util::jsonParseStrict(output, ret)); return ret; } @@ -100,14 +100,14 @@ BOOST_AUTO_TEST_CASE(standard_compilation) } } )"; - Json::Value result = compile(input); - BOOST_REQUIRE(result.isObject()); + Json result = compile(input); + BOOST_REQUIRE(result.is_object()); // Only tests some assumptions. The StandardCompiler is tested properly in another suite. - BOOST_CHECK(result.isMember("sources")); + BOOST_CHECK(result.contains("sources")); // This used to test that it is a member, but we did not actually request any output, // so there should not be a contract member. - BOOST_CHECK(!result.isMember("contracts")); + BOOST_CHECK(!result.contains("contracts")); } BOOST_AUTO_TEST_CASE(missing_callback) @@ -122,8 +122,8 @@ BOOST_AUTO_TEST_CASE(missing_callback) } } )"; - Json::Value result = compile(input); - BOOST_REQUIRE(result.isObject()); + Json result = compile(input); + BOOST_REQUIRE(result.is_object()); BOOST_CHECK(containsError(result, "ParserError", "Source \"missing.sol\" not found: File not supplied initially.")); } @@ -168,8 +168,8 @@ BOOST_AUTO_TEST_CASE(with_callback) } }; - Json::Value result = compile(input, callback); - BOOST_REQUIRE(result.isObject()); + Json result = compile(input, callback); + BOOST_REQUIRE(result.is_object()); // This ensures that "found.sol" was properly loaded which triggered the second import statement. BOOST_CHECK(containsError(result, "ParserError", "Source \"missing.sol\" not found: Missing file.")); diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 029419af11c5..94687f99006d 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -57,17 +57,17 @@ std::optional compileAndCheckLicenseMetadata(std::string const& _co BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata(_contractName); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK_EQUAL(metadata["sources"].size(), 1); - BOOST_REQUIRE(metadata["sources"].isMember("A.sol")); + BOOST_REQUIRE(metadata["sources"].contains("A.sol")); - if (metadata["sources"]["A.sol"].isMember("license")) + if (metadata["sources"]["A.sol"].contains("license")) { - BOOST_REQUIRE(metadata["sources"]["A.sol"]["license"].isString()); - return metadata["sources"]["A.sol"]["license"].asString(); + BOOST_REQUIRE(metadata["sources"]["A.sol"]["license"].is_string()); + return metadata["sources"]["A.sol"]["license"].get(); } else return std::nullopt; @@ -288,12 +288,12 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("A"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK_EQUAL(metadata["sources"].size(), 1); - BOOST_CHECK(metadata["sources"].isMember("A")); + BOOST_CHECK(metadata["sources"].contains("A")); } BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) @@ -329,14 +329,14 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("C"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK_EQUAL(metadata["sources"].size(), 3); - BOOST_CHECK(metadata["sources"].isMember("A")); - BOOST_CHECK(metadata["sources"].isMember("B")); - BOOST_CHECK(metadata["sources"].isMember("C")); + BOOST_CHECK(metadata["sources"].contains("A")); + BOOST_CHECK(metadata["sources"].contains("B")); + BOOST_CHECK(metadata["sources"].contains("C")); } BOOST_AUTO_TEST_CASE(metadata_useLiteralContent) @@ -357,16 +357,16 @@ BOOST_AUTO_TEST_CASE(metadata_useLiteralContent) compilerStack.useMetadataLiteralSources(_literal); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string metadata_str = compilerStack.metadata("test"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(metadata_str, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata.isMember("settings")); - BOOST_CHECK(metadata["settings"].isMember("metadata")); - BOOST_CHECK(metadata["settings"]["metadata"].isMember("bytecodeHash")); + BOOST_CHECK(metadata.contains("settings")); + BOOST_CHECK(metadata["settings"].contains("metadata")); + BOOST_CHECK(metadata["settings"]["metadata"].contains("bytecodeHash")); if (_literal) { - BOOST_CHECK(metadata["settings"]["metadata"].isMember("useLiteralContent")); - BOOST_CHECK(metadata["settings"]["metadata"]["useLiteralContent"].asBool()); + BOOST_CHECK(metadata["settings"]["metadata"].contains("useLiteralContent")); + BOOST_CHECK(metadata["settings"]["metadata"]["useLiteralContent"].get()); } }; @@ -391,17 +391,17 @@ BOOST_AUTO_TEST_CASE(metadata_viair) compilerStack.setViaIR(_viaIR); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(compilerStack.metadata("test"), metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata.isMember("settings")); + BOOST_CHECK(metadata.contains("settings")); if (_viaIR) { - BOOST_CHECK(metadata["settings"].isMember("viaIR")); - BOOST_CHECK(metadata["settings"]["viaIR"].asBool()); + BOOST_CHECK(metadata["settings"].contains("viaIR")); + BOOST_CHECK(metadata["settings"]["viaIR"].get()); } else - BOOST_CHECK(!metadata["settings"].isMember("viaIR")); + BOOST_CHECK(!metadata["settings"].contains("viaIR")); BOOST_CHECK(compilerStack.cborMetadata("test") == compilerStack.cborMetadata("test", _viaIR)); BOOST_CHECK(compilerStack.cborMetadata("test") != compilerStack.cborMetadata("test", !_viaIR)); @@ -431,7 +431,7 @@ BOOST_AUTO_TEST_CASE(metadata_revert_strings) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("A"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); @@ -469,14 +469,14 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("C"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata["settings"]["optimizer"].isMember("details")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"].isMember("yulDetails")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].isMember("optimizerSteps")); + BOOST_CHECK(metadata["settings"]["optimizer"].contains("details")); + BOOST_CHECK(metadata["settings"]["optimizer"]["details"].contains("yulDetails")); + BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps")); - std::string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].asString(); + std::string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get(); std::string const expectedMetadataOptimiserSteps = _optimizerSequence + ":" + _optimizerCleanupSequence; BOOST_CHECK_EQUAL(metadataOptimizerSteps, expectedMetadataOptimiserSteps); }; diff --git a/test/libsolidity/NatspecJSONTest.cpp b/test/libsolidity/NatspecJSONTest.cpp index 9f1ba1d7de00..7dff638f0de5 100644 --- a/test/libsolidity/NatspecJSONTest.cpp +++ b/test/libsolidity/NatspecJSONTest.cpp @@ -67,7 +67,7 @@ void NatspecJSONTest::parseCustomExpectations(std::istream& _stream) std::string rawJSON = extractExpectationJSON(_stream); std::string jsonErrors; - Json::Value parsedJSON; + Json parsedJSON; bool jsonParsingSuccessful = jsonParseStrict(rawJSON, parsedJSON, &jsonErrors); if (!jsonParsingSuccessful) BOOST_THROW_EXCEPTION(std::runtime_error(fmt::format( @@ -86,7 +86,7 @@ void NatspecJSONTest::parseCustomExpectations(std::istream& _stream) bool NatspecJSONTest::expectationsMatch() { - // NOTE: Comparing pretty printed Json::Values to avoid using its operator==, which fails to + // NOTE: Comparing pretty printed Jsons to avoid using its operator==, which fails to // compare equal numbers as equal. For example, for 'version' field the value is sometimes int, // sometimes uint and they compare as different even when both are 1. return diff --git a/test/libsolidity/NatspecJSONTest.h b/test/libsolidity/NatspecJSONTest.h index 762b88d10659..619ece83b165 100644 --- a/test/libsolidity/NatspecJSONTest.h +++ b/test/libsolidity/NatspecJSONTest.h @@ -44,7 +44,7 @@ enum class NatspecJSONKind std::ostream& operator<<(std::ostream& _output, NatspecJSONKind _kind); -using NatspecMap = std::map>; +using NatspecMap = std::map>; using SerializedNatspecMap = std::map>; class NatspecJSONTest: public SyntaxTest diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 63e8a924abca..b0bdb95cb9c4 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -429,7 +429,7 @@ TestCase::TestResult SemanticTest::runTest( { soltestAssert( m_allowNonExistingFunctions || - m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].isMember(test.call().signature), + m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].contains(test.call().signature), "The function " + test.call().signature + " is not known to the compiler" ); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 22db222ea5af..cdb6c5bd2d9d 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -55,97 +56,97 @@ langutil::Error::Severity str2Severity(std::string const& _cat) } /// Helper to match a specific error type and message -bool containsError(Json::Value const& _compilerResult, std::string const& _type, std::string const& _message) +bool containsError(Json const& _compilerResult, std::string const& _type, std::string const& _message) { - if (!_compilerResult.isMember("errors")) + if (!_compilerResult.contains("errors")) return false; for (auto const& error: _compilerResult["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["type"].isString()); - BOOST_REQUIRE(error["message"].isString()); - if ((error["type"].asString() == _type) && (error["message"].asString() == _message)) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["type"].is_string()); + BOOST_REQUIRE(error["message"].is_string()); + if ((error["type"].get() == _type) && (error["message"].get() == _message)) return true; } return false; } -bool containsAtMostWarnings(Json::Value const& _compilerResult) +bool containsAtMostWarnings(Json const& _compilerResult) { - if (!_compilerResult.isMember("errors")) + if (!_compilerResult.contains("errors")) return true; for (auto const& error: _compilerResult["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["severity"].isString()); - if (langutil::Error::isError(str2Severity(error["severity"].asString()))) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["severity"].is_string()); + if (langutil::Error::isError(str2Severity(error["severity"].get()))) return false; } return true; } -Json::Value getContractResult(Json::Value const& _compilerResult, std::string const& _file, std::string const& _name) +Json getContractResult(Json const& _compilerResult, std::string const& _file, std::string const& _name) { - if ( - !_compilerResult["contracts"].isObject() || - !_compilerResult["contracts"][_file].isObject() || - !_compilerResult["contracts"][_file][_name].isObject() + if (!_compilerResult.contains("contracts") || + !_compilerResult["contracts"].is_object() || + !_compilerResult["contracts"][_file].is_object() || + !_compilerResult["contracts"][_file][_name].is_object() ) - return Json::Value(); + return Json(); return _compilerResult["contracts"][_file][_name]; } -void checkLinkReferencesSchema(Json::Value const& _contractResult) +void checkLinkReferencesSchema(Json const& _contractResult) { - BOOST_TEST_REQUIRE(_contractResult.isObject()); - BOOST_TEST_REQUIRE(_contractResult["evm"]["bytecode"].isObject()); + BOOST_TEST_REQUIRE(_contractResult.is_object()); + BOOST_TEST_REQUIRE(_contractResult["evm"]["bytecode"].is_object()); - Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; - BOOST_TEST_REQUIRE(linkReferenceResult.isObject()); + Json const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; + BOOST_TEST_REQUIRE(linkReferenceResult.is_object()); - for (std::string const& fileName: linkReferenceResult.getMemberNames()) + for (auto const& [fileName, references]: linkReferenceResult.items()) { - BOOST_TEST_REQUIRE(linkReferenceResult[fileName].isObject()); - for (std::string const& libraryName: linkReferenceResult[fileName].getMemberNames()) + BOOST_TEST_REQUIRE(references.is_object()); + for (auto const& [libraryName, libraryValue]: references.items()) { - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName].isArray()); - BOOST_TEST_REQUIRE(!linkReferenceResult[fileName][libraryName].empty()); - for (int i = 0; i < static_cast(linkReferenceResult.size()); ++i) + BOOST_TEST_REQUIRE(libraryValue.is_array()); + BOOST_TEST_REQUIRE(!libraryValue.empty()); + for (size_t i = 0; i < static_cast(linkReferenceResult.size()); ++i) { - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].isObject()); - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].size() == 2); - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["length"].isUInt()); - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["start"].isUInt()); + BOOST_TEST_REQUIRE(libraryValue[i].is_object()); + BOOST_TEST_REQUIRE(libraryValue[i].size() == 2); + BOOST_TEST_REQUIRE(libraryValue[i]["length"].is_number_unsigned()); + BOOST_TEST_REQUIRE(libraryValue[i]["start"].is_number_unsigned()); } } } } -void expectLinkReferences(Json::Value const& _contractResult, std::map> const& _expectedLinkReferences) +void expectLinkReferences(Json const& _contractResult, std::map> const& _expectedLinkReferences) { checkLinkReferencesSchema(_contractResult); - Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; + Json const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; BOOST_TEST(linkReferenceResult.size() == _expectedLinkReferences.size()); for (auto const& [fileName, libraries]: _expectedLinkReferences) { - BOOST_TEST(linkReferenceResult.isMember(fileName)); + BOOST_TEST(linkReferenceResult.contains(fileName)); BOOST_TEST(linkReferenceResult[fileName].size() == libraries.size()); for (std::string const& libraryName: libraries) - BOOST_TEST(linkReferenceResult[fileName].isMember(libraryName)); + BOOST_TEST(linkReferenceResult[fileName].contains(libraryName)); } } -Json::Value compile(std::string _input) +Json compile(std::string _input) { StandardCompiler compiler; std::string output = compiler.compile(std::move(_input)); - Json::Value ret; + Json ret; BOOST_REQUIRE(util::jsonParseStrict(output, ret)); return ret; } @@ -156,25 +157,24 @@ BOOST_AUTO_TEST_SUITE(StandardCompiler) BOOST_AUTO_TEST_CASE(assume_object_input) { - Json::Value result; + Json result; /// Use the native JSON interface of StandardCompiler to trigger these frontend::StandardCompiler compiler; - result = compiler.compile(Json::Value()); + result = compiler.compile(Json()); BOOST_CHECK(containsError(result, "JSONError", "Input is not a JSON object.")); - result = compiler.compile(Json::Value("INVALID")); + result = compiler.compile(Json("INVALID")); BOOST_CHECK(containsError(result, "JSONError", "Input is not a JSON object.")); /// Use the string interface of StandardCompiler to trigger these result = compile(""); - BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 1\n A valid JSON document must be either an array or an object value.\n")); + BOOST_CHECK(containsError(result, "JSONError", "parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON")); result = compile("invalid"); - BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 2\n Extra non-whitespace after JSON value.\n")); + BOOST_CHECK(containsError(result, "JSONError", "parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'i'")); result = compile("\"invalid\""); - BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n A valid JSON document must be either an array or an object value.\n")); - BOOST_CHECK(!containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n")); + BOOST_CHECK(containsError(result, "JSONError", "Input is not a JSON object.")); result = compile("{}"); - BOOST_CHECK(!containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n")); + BOOST_CHECK(containsError(result, "JSONError", "No input sources specified.")); BOOST_CHECK(!containsAtMostWarnings(result)); } @@ -186,7 +186,7 @@ BOOST_AUTO_TEST_CASE(invalid_language) "sources": { "name": { "content": "abc" } } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Only \"Solidity\", \"Yul\", \"SolidityAST\" or \"EVMAssembly\" is supported as a language.")); } @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(valid_language) "language": "Solidity" } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(!containsError(result, "JSONError", "Only \"Solidity\" or \"Yul\" is supported as a language.")); } @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(no_sources) "language": "Solidity" } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "No input sources specified.")); } @@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(no_sources_empty_object) "sources": {} } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "No input sources specified.")); } @@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(no_sources_empty_array) "sources": [] } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"sources\" is not a JSON object.")); } @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(sources_is_array) "sources": ["aa", "bb"] } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"sources\" is not a JSON object.")); } @@ -262,8 +262,8 @@ BOOST_AUTO_TEST_CASE(unexpected_trailing_test) } } )"; - Json::Value result = compile(input); - BOOST_CHECK(containsError(result, "JSONError", "* Line 10, Column 2\n Extra non-whitespace after JSON value.\n")); + Json result = compile(input); + BOOST_CHECK(containsError(result, "JSONError", "parse error at line 10, column 2: syntax error while parsing value - unexpected '}'; expected end of input")); } BOOST_AUTO_TEST_CASE(smoke_test) @@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); } @@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(optimizer_enabled_not_boolean) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "The \"enabled\" setting must be a Boolean.")); } @@ -321,7 +321,7 @@ BOOST_AUTO_TEST_CASE(optimizer_runs_not_a_number) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number.")); } @@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(optimizer_runs_not_an_unsigned_number) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number.")); } @@ -367,28 +367,28 @@ BOOST_AUTO_TEST_CASE(basic_compilation) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); - BOOST_CHECK(contract["devdoc"].isObject()); + BOOST_CHECK(contract["devdoc"].is_object()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["devdoc"]), R"({"kind":"dev","methods":{},"version":1})"); - BOOST_CHECK(contract["userdoc"].isObject()); + BOOST_CHECK(contract["userdoc"].is_object()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["userdoc"]), R"({"kind":"user","methods":{},"version":1})"); - BOOST_CHECK(contract["evm"].isObject()); + BOOST_CHECK(contract["evm"].is_object()); /// @TODO check evm.methodIdentifiers, legacyAssembly, bytecode, deployedBytecode - BOOST_CHECK(contract["evm"]["bytecode"].isObject()); - BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); + BOOST_CHECK(contract["evm"]["bytecode"].is_object()); + BOOST_CHECK(contract["evm"]["bytecode"]["object"].is_string()); BOOST_CHECK_EQUAL( - solidity::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()), + solidity::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].get()), std::string("6080604052348015600e575f80fd5b5060") + (VersionIsRelease ? "3e" : util::toHex(bytes{uint8_t(60 + VersionStringStrict.size())})) + "80601a5f395ff3fe60806040525f80fdfe" ); - BOOST_CHECK(contract["evm"]["assembly"].isString()); - BOOST_CHECK(contract["evm"]["assembly"].asString().find( + BOOST_CHECK(contract["evm"]["assembly"].is_string()); + BOOST_CHECK(contract["evm"]["assembly"].get().find( " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n " "callvalue\n dup1\n " "iszero\n tag_1\n jumpi\n " @@ -400,22 +400,22 @@ BOOST_AUTO_TEST_CASE(basic_compilation) "0x00\n " "dup1\n revert\n\n auxdata: 0xa26469706673582212" ) == 0); - BOOST_CHECK(contract["evm"]["gasEstimates"].isObject()); + BOOST_CHECK(contract["evm"]["gasEstimates"].is_object()); BOOST_CHECK_EQUAL(contract["evm"]["gasEstimates"].size(), 1); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"].isObject()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"].is_object()); BOOST_CHECK_EQUAL(contract["evm"]["gasEstimates"]["creation"].size(), 3); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].isString()); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["executionCost"].isString()); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["totalCost"].isString()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].is_string()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["executionCost"].is_string()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["totalCost"].is_string()); BOOST_CHECK_EQUAL( - u256(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].asString()) + - u256(contract["evm"]["gasEstimates"]["creation"]["executionCost"].asString()), - u256(contract["evm"]["gasEstimates"]["creation"]["totalCost"].asString()) + u256(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].get()) + + u256(contract["evm"]["gasEstimates"]["creation"]["executionCost"].get()), + u256(contract["evm"]["gasEstimates"]["creation"]["totalCost"].get()) ); // Lets take the top level `.code` section (the "deployer code"), that should expose most of the features of // the assembly JSON. What we want to check here is Operation, Push, PushTag, PushSub, PushSubSize and Tag. - BOOST_CHECK(contract["evm"]["legacyAssembly"].isObject()); - BOOST_CHECK(contract["evm"]["legacyAssembly"][".code"].isArray()); + BOOST_CHECK(contract["evm"]["legacyAssembly"].is_object()); + BOOST_CHECK(contract["evm"]["legacyAssembly"][".code"].is_array()); BOOST_CHECK_EQUAL( util::jsonCompactPrint(contract["evm"]["legacyAssembly"][".code"]), "[{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"source\":0,\"value\":\"80\"}," @@ -440,11 +440,11 @@ BOOST_AUTO_TEST_CASE(basic_compilation) "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"source\":0,\"value\":\"0\"}," "{\"begin\":0,\"end\":14,\"name\":\"RETURN\",\"source\":0}]" ); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].asString())); - BOOST_CHECK(result["sources"].isObject()); - BOOST_CHECK(result["sources"]["fileA"].isObject()); - BOOST_CHECK(result["sources"]["fileA"]["ast"].isObject()); + BOOST_CHECK(contract["metadata"].is_string()); + BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].get())); + BOOST_CHECK(result["sources"].is_object()); + BOOST_CHECK(result["sources"]["fileA"].is_object()); + BOOST_CHECK(result["sources"]["fileA"]["ast"].is_object()); BOOST_CHECK_EQUAL( util::jsonCompactPrint(result["sources"]["fileA"]["ast"]), "{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]},\"id\":2,\"nodeType\":\"SourceUnit\",\"nodes\":[{\"abstract\":false," @@ -476,14 +476,14 @@ BOOST_AUTO_TEST_CASE(compilation_error) } } )"; - Json::Value result = compile(input); - BOOST_CHECK(result.isMember("errors")); + Json result = compile(input); + BOOST_CHECK(result.contains("errors")); BOOST_CHECK(result["errors"].size() >= 1); for (auto const& error: result["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["message"].isString()); - if (error["message"].asString().find("pre-release compiler") == std::string::npos) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["message"].is_string()); + if (error["message"].get().find("pre-release compiler") == std::string::npos) { BOOST_CHECK_EQUAL( util::jsonCompactPrint(error), @@ -516,11 +516,11 @@ BOOST_AUTO_TEST_CASE(output_selection_explicit) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -545,11 +545,11 @@ BOOST_AUTO_TEST_CASE(output_selection_all_contracts) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -574,11 +574,11 @@ BOOST_AUTO_TEST_CASE(output_selection_all_files_single_contract) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -603,11 +603,11 @@ BOOST_AUTO_TEST_CASE(output_selection_all_files_all_contracts) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -632,11 +632,11 @@ BOOST_AUTO_TEST_CASE(output_selection_dependent_contract) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[{\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); } @@ -664,11 +664,11 @@ BOOST_AUTO_TEST_CASE(output_selection_dependent_contract_with_import) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[{\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); } @@ -693,11 +693,11 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "http://github.com/ethereum/solidity/std/StandardToken.sol", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "http://github.com/ethereum/solidity/std/StandardToken.sol", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -725,10 +725,10 @@ BOOST_AUTO_TEST_CASE(library_filename_with_colon) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); expectLinkReferences(contract, {{"git:library.sol", {"L"}}}); } @@ -747,7 +747,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_top_level) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"libraries\" is not a JSON object.")); } @@ -768,7 +768,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_entry) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Library entry is not a JSON object.")); } @@ -791,7 +791,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_hex) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Invalid library address (\"0x4200000000000000000000000000000000000xx1\") supplied.")); } @@ -815,7 +815,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_length) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Library address is of invalid length.")); } @@ -838,7 +838,7 @@ BOOST_AUTO_TEST_CASE(libraries_missing_hex_prefix) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Library address is not prefixed with \"0x\".")); } @@ -874,9 +874,9 @@ BOOST_AUTO_TEST_CASE(library_linking) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "A"); + Json contractResult = getContractResult(result, "fileA", "A"); expectLinkReferences(contractResult, {{"library2.sol", {"L2"}}}); } @@ -906,9 +906,9 @@ BOOST_AUTO_TEST_CASE(linking_yul) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {}); } @@ -938,9 +938,9 @@ BOOST_AUTO_TEST_CASE(linking_yul_empty_link_reference) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {{"", {""}}}); } @@ -970,9 +970,9 @@ BOOST_AUTO_TEST_CASE(linking_yul_no_filename_in_link_reference) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {{"", {"L"}}}); } @@ -1002,9 +1002,9 @@ BOOST_AUTO_TEST_CASE(linking_yul_same_library_name_different_files) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {{"fileC", {"L"}}}); } @@ -1027,37 +1027,37 @@ BOOST_AUTO_TEST_CASE(evm_version) } )"; }; - Json::Value result; + Json result; result = compile(inputForVersion("\"evmVersion\": \"homestead\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"homestead\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"homestead\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"tangerineWhistle\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"tangerineWhistle\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"tangerineWhistle\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"spuriousDragon\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"spuriousDragon\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"spuriousDragon\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"byzantium\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"byzantium\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"byzantium\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"constantinople\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"constantinople\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"constantinople\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"petersburg\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"petersburg\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"petersburg\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"istanbul\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"istanbul\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"istanbul\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"berlin\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"berlin\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"berlin\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"london\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"london\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"london\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"paris\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"paris\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"paris\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"shanghai\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"shanghai\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"shanghai\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"cancun\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test default result = compile(inputForVersion("")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test invalid result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); - BOOST_CHECK(result["errors"][0]["message"].asString() == "Invalid EVM version requested."); + BOOST_CHECK(result["errors"][0]["message"].get() == "Invalid EVM version requested."); } BOOST_AUTO_TEST_CASE(optimizer_settings_default_disabled) @@ -1077,19 +1077,19 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_default_disabled) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(optimizer.isMember("enabled")); - BOOST_CHECK(optimizer["enabled"].asBool() == false); - BOOST_CHECK(!optimizer.isMember("details")); - BOOST_CHECK(optimizer["runs"].asUInt() == 200); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(optimizer.contains("enabled")); + BOOST_CHECK(optimizer["enabled"].get() == false); + BOOST_CHECK(!optimizer.contains("details")); + BOOST_CHECK(optimizer["runs"].get() == 200); } BOOST_AUTO_TEST_CASE(optimizer_settings_default_enabled) @@ -1110,19 +1110,19 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_default_enabled) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(optimizer.isMember("enabled")); - BOOST_CHECK(optimizer["enabled"].asBool() == true); - BOOST_CHECK(!optimizer.isMember("details")); - BOOST_CHECK(optimizer["runs"].asUInt() == 200); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(optimizer.contains("enabled")); + BOOST_CHECK(optimizer["enabled"].get() == true); + BOOST_CHECK(!optimizer.contains("details")); + BOOST_CHECK(optimizer["runs"].get() == 200); } BOOST_AUTO_TEST_CASE(optimizer_settings_details_exactly_as_default_disabled) @@ -1150,20 +1150,20 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_exactly_as_default_disabled) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(optimizer.isMember("enabled")); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(optimizer.contains("enabled")); // enabled is switched to false instead! - BOOST_CHECK(optimizer["enabled"].asBool() == false); - BOOST_CHECK(!optimizer.isMember("details")); - BOOST_CHECK(optimizer["runs"].asUInt() == 200); + BOOST_CHECK(optimizer["enabled"].get() == false); + BOOST_CHECK(!optimizer.contains("details")); + BOOST_CHECK(optimizer["runs"].get() == 200); } BOOST_AUTO_TEST_CASE(optimizer_settings_details_different) @@ -1193,36 +1193,36 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_different) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(!optimizer.isMember("enabled")); - BOOST_CHECK(optimizer.isMember("details")); - BOOST_CHECK(optimizer["details"]["constantOptimizer"].asBool() == true); - BOOST_CHECK(optimizer["details"]["cse"].asBool() == false); - BOOST_CHECK(optimizer["details"]["deduplicate"].asBool() == true); - BOOST_CHECK(optimizer["details"]["jumpdestRemover"].asBool() == true); - BOOST_CHECK(optimizer["details"]["orderLiterals"].asBool() == false); - BOOST_CHECK(optimizer["details"]["peephole"].asBool() == true); - BOOST_CHECK(optimizer["details"]["yul"].asBool() == true); - BOOST_CHECK(optimizer["details"]["yulDetails"].isObject()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(!optimizer.contains("enabled")); + BOOST_CHECK(optimizer.contains("details")); + BOOST_CHECK(optimizer["details"]["constantOptimizer"].get() == true); + BOOST_CHECK(optimizer["details"]["cse"].get() == false); + BOOST_CHECK(optimizer["details"]["deduplicate"].get() == true); + BOOST_CHECK(optimizer["details"]["jumpdestRemover"].get() == true); + BOOST_CHECK(optimizer["details"]["orderLiterals"].get() == false); + BOOST_CHECK(optimizer["details"]["peephole"].get() == true); + BOOST_CHECK(optimizer["details"]["yul"].get() == true); + BOOST_CHECK(optimizer["details"]["yulDetails"].is_object()); +// BOOST_CHECK( +// util::convertContainer>(optimizer["details"]["yulDetails"].getMemberNames()) == +// (std::set{"stackAllocation", "optimizerSteps"}) +// ); + BOOST_CHECK(optimizer["details"]["yulDetails"]["stackAllocation"].get() == true); BOOST_CHECK( - util::convertContainer>(optimizer["details"]["yulDetails"].getMemberNames()) == - (std::set{"stackAllocation", "optimizerSteps"}) - ); - BOOST_CHECK(optimizer["details"]["yulDetails"]["stackAllocation"].asBool() == true); - BOOST_CHECK( - optimizer["details"]["yulDetails"]["optimizerSteps"].asString() == + optimizer["details"]["yulDetails"]["optimizerSteps"].get() == OptimiserSettings::DefaultYulOptimiserSteps + ":"s + OptimiserSettings::DefaultYulOptimiserCleanupSteps - ); - BOOST_CHECK_EQUAL(optimizer["details"].getMemberNames().size(), 10); - BOOST_CHECK(optimizer["runs"].asUInt() == 600); + ); + BOOST_CHECK_EQUAL(optimizer["details"].size(), 10); + BOOST_CHECK(optimizer["runs"].get() == 600); } BOOST_AUTO_TEST_CASE(metadata_without_compilation) @@ -1250,12 +1250,12 @@ BOOST_AUTO_TEST_CASE(metadata_without_compilation) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].asString())); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].get())); } @@ -1281,13 +1281,13 @@ BOOST_AUTO_TEST_CASE(license_in_metadata) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_REQUIRE(util::jsonParseStrict(contract["metadata"].asString(), metadata)); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_REQUIRE(util::jsonParseStrict(contract["metadata"].get(), metadata)); BOOST_CHECK_EQUAL(metadata["sources"]["fileA"]["license"], "GPL-3.0"); BOOST_CHECK_EQUAL(metadata["sources"]["fileB"]["license"], "MIT"); BOOST_CHECK_EQUAL(metadata["sources"]["fileC"]["license"], "MIT AND GPL-3.0"); @@ -1317,14 +1317,14 @@ BOOST_AUTO_TEST_CASE(common_pattern) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].asString())); - BOOST_CHECK(contract["evm"]["bytecode"].isObject()); - BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].get())); + BOOST_CHECK(contract["evm"]["bytecode"].is_object()); + BOOST_CHECK(contract["evm"]["bytecode"]["object"].is_string()); } BOOST_AUTO_TEST_CASE(use_stack_optimization) @@ -1375,17 +1375,17 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_REQUIRE(contract.isObject()); - BOOST_REQUIRE(contract["evm"]["bytecode"]["object"].isString()); - BOOST_CHECK(contract["evm"]["bytecode"]["object"].asString().length() > 20); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_REQUIRE(contract.is_object()); + BOOST_REQUIRE(contract["evm"]["bytecode"]["object"].is_string()); + BOOST_CHECK(contract["evm"]["bytecode"]["object"].get().length() > 20); // Now disable stack optimizations and UnusedFunctionParameterPruner (p) // results in "stack too deep" @@ -1398,10 +1398,10 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization) parsedInput["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"] = optimiserSteps; result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["errors"].isArray()); + BOOST_REQUIRE(result["errors"].is_array()); BOOST_CHECK(result["errors"][0]["severity"] == "error"); - BOOST_REQUIRE(result["errors"][0]["message"].isString()); - BOOST_CHECK(result["errors"][0]["message"].asString().find("When compiling inline assembly") != std::string::npos); + BOOST_REQUIRE(result["errors"][0]["message"].is_string()); + BOOST_CHECK(result["errors"][0]["message"].get().find("When compiling inline assembly") != std::string::npos); BOOST_CHECK(result["errors"][0]["type"] == "CompilerError"); } @@ -1427,22 +1427,22 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A"].isObject()); + BOOST_REQUIRE(result["contracts"]["A"].is_object()); BOOST_REQUIRE(result["contracts"]["A"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A"]["C"].isObject()); - BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"]["A"]["C"].is_object()); + BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); - BOOST_REQUIRE(result["sources"]["A"].isObject()); + BOOST_REQUIRE(result["sources"]["A"].is_object()); } @@ -1468,22 +1468,22 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_colon_source) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"][":A"].isObject()); + BOOST_REQUIRE(result["contracts"][":A"].is_object()); BOOST_REQUIRE(result["contracts"][":A"].size() == 1); - BOOST_REQUIRE(result["contracts"][":A"]["C"].isObject()); - BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"][":A"]["C"].is_object()); + BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); - BOOST_REQUIRE(result["sources"][":A"].isObject()); + BOOST_REQUIRE(result["sources"][":A"].is_object()); } BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_empty_source) @@ -1508,22 +1508,22 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_empty_source) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"][""].isObject()); + BOOST_REQUIRE(result["contracts"][""].is_object()); BOOST_REQUIRE(result["contracts"][""].size() == 1); - BOOST_REQUIRE(result["contracts"][""]["C"].isObject()); - BOOST_REQUIRE(result["contracts"][""]["C"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"][""]["C"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"][""]["C"].is_object()); + BOOST_REQUIRE(result["contracts"][""]["C"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"][""]["C"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); - BOOST_REQUIRE(result["sources"][""].isObject()); + BOOST_REQUIRE(result["sources"][""].is_object()); } BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_multiple_sources) @@ -1552,23 +1552,23 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_multiple_sources) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["B"].isObject()); + BOOST_REQUIRE(result["contracts"]["B"].is_object()); BOOST_REQUIRE(result["contracts"]["B"].size() == 1); - BOOST_REQUIRE(result["contracts"]["B"]["D"].isObject()); - BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"]["B"]["D"].is_object()); + BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 2); - BOOST_REQUIRE(result["sources"]["A"].isObject()); - BOOST_REQUIRE(result["sources"]["B"].isObject()); + BOOST_REQUIRE(result["sources"]["A"].is_object()); + BOOST_REQUIRE(result["sources"]["B"].is_object()); } BOOST_AUTO_TEST_CASE(stopAfter_invalid_value) @@ -1588,7 +1588,7 @@ BOOST_AUTO_TEST_CASE(stopAfter_invalid_value) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Invalid value for \"settings.stopAfter\". Only valid value is \"parsing\".")); } @@ -1609,7 +1609,7 @@ BOOST_AUTO_TEST_CASE(stopAfter_invalid_type) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"settings.stopAfter\" must be a string.")); } @@ -1630,7 +1630,7 @@ BOOST_AUTO_TEST_CASE(stopAfter_bin_conflict) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Requested output selection conflicts with \"settings.stopAfter\".")); } @@ -1650,10 +1650,10 @@ BOOST_AUTO_TEST_CASE(stopAfter_ast_output) } } )"; - Json::Value result = compile(input); - BOOST_CHECK(result["sources"].isObject()); - BOOST_CHECK(result["sources"]["a.sol"].isObject()); - BOOST_CHECK(result["sources"]["a.sol"]["ast"].isObject()); + Json result = compile(input); + BOOST_CHECK(result["sources"].is_object()); + BOOST_CHECK(result["sources"]["a.sol"].is_object()); + BOOST_CHECK(result["sources"]["a.sol"]["ast"].is_object()); } BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract) @@ -1679,21 +1679,21 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"].isObject()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"].is_object()); BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"].size() == 1); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"].isObject()); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["ir"].isString()); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"].is_object()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["ir"].is_string()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 2); } @@ -1717,20 +1717,20 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract_yul) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A.sol"].isObject()); + BOOST_REQUIRE(result["contracts"]["A.sol"].is_object()); BOOST_REQUIRE(result["contracts"]["A.sol"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A.sol"]["C"].isObject()); - BOOST_REQUIRE(result["contracts"]["A.sol"]["C"]["ir"].isString()); + BOOST_REQUIRE(result["contracts"]["A.sol"]["C"].is_object()); + BOOST_REQUIRE(result["contracts"]["A.sol"]["C"]["ir"].is_string()); - const std::string& irCode = result["contracts"]["A.sol"]["C"]["ir"].asString(); + const std::string& irCode = result["contracts"]["A.sol"]["C"]["ir"].get(); // Make sure C and B contracts are deployed BOOST_REQUIRE(irCode.find("object \"C") != std::string::npos); @@ -1742,7 +1742,7 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract_yul) BOOST_REQUIRE(irCode.find("object \"D") == std::string::npos); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); } @@ -1766,13 +1766,13 @@ BOOST_AUTO_TEST_CASE(source_location_of_bare_block) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - std::string sourceMap = result["contracts"]["A.sol"]["A"]["evm"]["bytecode"]["sourceMap"].asString(); + std::string sourceMap = result["contracts"]["A.sol"]["A"]["evm"]["bytecode"]["sourceMap"].get(); // Check that the bare block's source location is referenced. std::string sourceRef = diff --git a/test/libsolidity/util/ContractABIUtils.cpp b/test/libsolidity/util/ContractABIUtils.cpp index 641c9107d69b..fb2f4eb62679 100644 --- a/test/libsolidity/util/ContractABIUtils.cpp +++ b/test/libsolidity/util/ContractABIUtils.cpp @@ -140,16 +140,16 @@ std::optional isFixedPoint(std::string const& type) return fixedPointType; } -std::string functionSignatureFromABI(Json::Value const& _functionABI) +std::string functionSignatureFromABI(Json const& _functionABI) { auto inputs = _functionABI["inputs"]; - std::string signature = {_functionABI["name"].asString() + "("}; + std::string signature = {_functionABI["name"].get() + "("}; size_t parameterCount = 0; for (auto const& input: inputs) { parameterCount++; - signature += input["type"].asString(); + signature += input["type"].get(); if (parameterCount < inputs.size()) signature += ","; } @@ -161,11 +161,11 @@ std::string functionSignatureFromABI(Json::Value const& _functionABI) std::optional ContractABIUtils::parametersFromJsonOutputs( ErrorReporter& _errorReporter, - Json::Value const& _contractABI, + Json const& _contractABI, std::string const& _functionSignature ) { - if (!_contractABI) + if (_contractABI.empty()) return std::nullopt; for (auto const& function: _contractABI) @@ -177,7 +177,7 @@ std::optional ContractABIUtils::paramet for (auto const& output: function["outputs"]) { - std::string type = output["type"].asString(); + std::string type = output["type"].get(); ABITypes inplaceTypes; ABITypes dynamicTypes; @@ -209,13 +209,13 @@ std::optional ContractABIUtils::paramet } bool ContractABIUtils::appendTypesFromName( - Json::Value const& _functionOutput, + Json const& _functionOutput, ABITypes& _inplaceTypes, ABITypes& _dynamicTypes, bool _isCompoundType ) { - std::string type = _functionOutput["type"].asString(); + std::string type = _functionOutput["type"].get(); if (isBool(type)) _inplaceTypes.push_back(ABIType{ABIType::Boolean}); else if (isUint(type)) diff --git a/test/libsolidity/util/ContractABIUtils.h b/test/libsolidity/util/ContractABIUtils.h index 209eca4232ba..3f0b1b04e283 100644 --- a/test/libsolidity/util/ContractABIUtils.h +++ b/test/libsolidity/util/ContractABIUtils.h @@ -19,8 +19,7 @@ #include #include - -#include +#include namespace solidity::frontend::test { @@ -40,7 +39,7 @@ class ContractABIUtils /// auto-correction during interactive update routine. static std::optional parametersFromJsonOutputs( ErrorReporter& _errorReporter, - Json::Value const& _contractABI, + Json const& _contractABI, std::string const& _functionSignature ); @@ -86,7 +85,7 @@ class ContractABIUtils /// `bytes` -> [`Unsigned`, `Unsigned`, `HexString`] /// ... static bool appendTypesFromName( - Json::Value const& _functionOutput, + Json const& _functionOutput, ABITypes& _inplaceTypes, ABITypes& _dynamicTypes, bool _isCompoundType = false diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index dd74d4035c68..3e0d3e873708 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -413,7 +413,7 @@ void TestFunctionCall::reset() { m_rawBytes = bytes{}; m_failure = true; - m_contractABI = Json::Value{}; + m_contractABI = Json(); m_calledNonExistingFunction = false; } diff --git a/test/libsolidity/util/TestFunctionCall.h b/test/libsolidity/util/TestFunctionCall.h index 724cb8286c19..9a63262cc2eb 100644 --- a/test/libsolidity/util/TestFunctionCall.h +++ b/test/libsolidity/util/TestFunctionCall.h @@ -23,8 +23,6 @@ #include #include -#include - #include #include #include @@ -99,7 +97,7 @@ class TestFunctionCall void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; } void setGasCostExcludingCode(std::string const& _runType, u256 const& _gasCost) { m_gasCostsExcludingCode[_runType] = _gasCost; } void setCodeDepositGasCost(std::string const& _runType, u256 const& _gasCost) { m_codeDepositGasCosts[_runType] = _gasCost; } - void setContractABI(Json::Value _contractABI) { m_contractABI = std::move(_contractABI); } + void setContractABI(Json _contractABI) { m_contractABI = std::move(_contractABI); } void setSideEffects(std::vector _sideEffects) { m_call.actualSideEffects = _sideEffects; } private: @@ -154,7 +152,7 @@ class TestFunctionCall bool m_failure = true; /// JSON object which holds the contract ABI and that is used to set the output formatting /// in the interactive update routine. - Json::Value m_contractABI = Json::Value{}; + Json m_contractABI = Json{}; /// Flags that the test failed because the called function is not known to exist on the contract. bool m_calledNonExistingFunction = false; }; diff --git a/test/libsolutil/JSON.cpp b/test/libsolutil/JSON.cpp index da10c0b3c6a9..91e6771acc90 100644 --- a/test/libsolutil/JSON.cpp +++ b/test/libsolutil/JSON.cpp @@ -34,50 +34,50 @@ BOOST_AUTO_TEST_SUITE(JsonTest, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(json_types) { - auto check = [](Json::Value value, std::string const& expectation) { + auto check = [](Json value, std::string const& expectation) { BOOST_CHECK(jsonCompactPrint(value) == expectation); }; - Json::Value value; + Json value; BOOST_CHECK(value.empty()); value = {}; BOOST_CHECK(value.empty()); - value = Json::Value(); + value = Json(); BOOST_CHECK(value.empty()); - value = Json::nullValue; + value = Json(); BOOST_CHECK(value.empty()); check(value, "null"); check({}, "null"); - check(Json::Value(), "null"); - check(Json::nullValue, "null"); - check(Json::objectValue, "{}"); - check(Json::arrayValue, "[]"); - check(Json::UInt(1), "1"); - check(Json::UInt(-1), "4294967295"); - check(Json::UInt64(1), "1"); - check(Json::UInt64(-1), "18446744073709551615"); - check(Json::LargestUInt(1), "1"); - check(Json::LargestUInt(-1), "18446744073709551615"); - check(Json::LargestUInt(0xffffffff), "4294967295"); - check(Json::Value("test"), "\"test\""); + check(Json(), "null"); + check(Json(), "null"); + check(Json::object(), "{}"); + check(Json::array(), "[]"); + check(1, "1"); + check(static_cast(-1), "4294967295"); + check(1, "1"); + check(static_cast(-1), "18446744073709551615"); + check(1, "1"); + check(static_cast(-1), "18446744073709551615"); + check(0xffffffff, "4294967295"); + check(Json("test"), "\"test\""); check("test", "\"test\""); check(true, "true"); - value = Json::objectValue; + value = Json::object(); value["key"] = "value"; check(value, "{\"key\":\"value\"}"); - value = Json::arrayValue; - value.append(1); - value.append(2); + value = Json::array(); + value.push_back(1); + value.push_back(2); check(value, "[1,2]"); } BOOST_AUTO_TEST_CASE(json_pretty_print) { - Json::Value json; - Json::Value jsonChild; + Json json; + Json jsonChild; jsonChild["3.1"] = "3.1"; jsonChild["3.2"] = 2; @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(json_pretty_print) json["2"] = "2"; json["3"] = jsonChild; json["4"] = "ऑ ऒ ओ औ क ख"; - json["5"] = "\xff"; + json["5"] = "\\xff\\xfe"; BOOST_CHECK( "{\n" @@ -97,14 +97,14 @@ BOOST_AUTO_TEST_CASE(json_pretty_print) " \"3.2\": 2\n" " },\n" " \"4\": \"\\u0911 \\u0912 \\u0913 \\u0914 \\u0915 \\u0916\",\n" - " \"5\": \"\\ufffd\"\n" + " \"5\": \"\\\\xff\\\\xfe\"\n" "}" == jsonPrettyPrint(json)); } BOOST_AUTO_TEST_CASE(json_compact_print) { - Json::Value json; - Json::Value jsonChild; + Json json; + Json jsonChild; jsonChild["3.1"] = "3.1"; jsonChild["3.2"] = 2; @@ -112,9 +112,10 @@ BOOST_AUTO_TEST_CASE(json_compact_print) json["2"] = "2"; json["3"] = jsonChild; json["4"] = "ऑ ऒ ओ औ क ख"; - json["5"] = "\xff"; + json["5"] = "\x10"; + json["6"] = "\u4e2d"; - BOOST_CHECK("{\"1\":1,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":2},\"4\":\"\\u0911 \\u0912 \\u0913 \\u0914 \\u0915 \\u0916\",\"5\":\"\\ufffd\"}" == jsonCompactPrint(json)); + BOOST_CHECK(R"({"1":1,"2":"2","3":{"3.1":"3.1","3.2":2},"4":"\u0911 \u0912 \u0913 \u0914 \u0915 \u0916","5":"\u0010","6":"\u4e2d"})" == jsonCompactPrint(json)); } BOOST_AUTO_TEST_CASE(parse_json_strict) @@ -122,7 +123,7 @@ BOOST_AUTO_TEST_CASE(parse_json_strict) // In this test we check conformance against JSON.parse (https://tc39.es/ecma262/multipage/structured-data.html#sec-json.parse) // and ECMA-404 (https://www.ecma-international.org/publications-and-standards/standards/ecma-404/) - Json::Value json; + Json json; std::string errors; // Just parse a valid json input @@ -135,179 +136,202 @@ BOOST_AUTO_TEST_CASE(parse_json_strict) // Trailing garbage is not allowed in ECMA-262 BOOST_CHECK(!jsonParseStrict("{\"1\":2,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":3}}}}}}}}}}", json, &errors)); - // Comments are not allowed in ECMA-262 - // ... but JSONCPP allows them - BOOST_CHECK(jsonParseStrict( - "{\"1\":3, // awesome comment\n\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":5}}", json, &errors - )); - BOOST_CHECK(json["1"] == 3); - BOOST_CHECK(json["2"] == "2"); - BOOST_CHECK(json["3"]["3.1"] == "3.1"); - BOOST_CHECK(json["3"]["3.2"] == 5); - // According to ECMA-404 object, array, number, string, true, false, null are allowed // ... but JSONCPP disallows value types BOOST_CHECK(jsonParseStrict("[]", json, &errors)); - BOOST_CHECK(json.isArray()); + BOOST_CHECK(json.is_array()); BOOST_CHECK(jsonParseStrict("{}", json, &errors)); - BOOST_CHECK(json.isObject()); - BOOST_CHECK(!jsonParseStrict("1", json, &errors)); - // BOOST_CHECK(json.isNumeric()); - BOOST_CHECK(!jsonParseStrict("\"hello\"", json, &errors)); - // BOOST_CHECK(json.isString()); - BOOST_CHECK(!jsonParseStrict("true", json, &errors)); - // BOOST_CHECK(json.isBool()); - BOOST_CHECK(!jsonParseStrict("null", json, &errors)); - // BOOST_CHECK(json.isNull()); + BOOST_CHECK(json.is_object()); + BOOST_CHECK(jsonParseStrict("1", json, &errors)); + BOOST_CHECK(json.is_number()); + BOOST_CHECK(jsonParseStrict("\"hello\"", json, &errors)); + BOOST_CHECK(json.is_string()); + BOOST_CHECK(jsonParseStrict("true", json, &errors)); + BOOST_CHECK(json.is_boolean()); + BOOST_CHECK(jsonParseStrict("null", json, &errors)); + BOOST_CHECK(json.is_null()); // Single quotes are also disallowed by ECMA-404 BOOST_CHECK(!jsonParseStrict("'hello'", json, &errors)); - // BOOST_CHECK(json.isString()); + // BOOST_CHECK(json.is_string()); // Only string keys in objects are allowed in ECMA-404 BOOST_CHECK(!jsonParseStrict("{ 42: \"hello\" }", json, &errors)); // According to ECMA-404 hex escape sequences are not allowed, only unicode (\uNNNN) and // a few control characters (\b, \f, \n, \r, \t) - // - // More lenient parsers allow hex escapes as long as they translate to a valid UTF-8 encoding. - // - // ... but JSONCPP allows any hex escapes - BOOST_CHECK(jsonParseStrict("[ \"\x80\xec\x80\" ]", json, &errors)); - BOOST_CHECK(json.isArray()); - BOOST_CHECK(json[0] == "\x80\xec\x80"); - - // This would be valid more lenient parsers. + BOOST_CHECK(jsonParseStrict("[ \"\xF0\x9F\x98\x8A\" ]", json, &errors)); - BOOST_CHECK(json.isArray()); + BOOST_CHECK(json.is_array()); BOOST_CHECK(json[0] == "😊"); + BOOST_CHECK(json[0] == "\xF0\x9F\x98\x8A"); } BOOST_AUTO_TEST_CASE(json_isOfType) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; + json["int64"] = 0x4000000000000000; json["string"] = "Hello World!"; BOOST_CHECK(isOfType(json["float"])); BOOST_CHECK(isOfType(json["double"])); BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int64"])); - BOOST_CHECK(isOfType(json["int64"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int64"])); + BOOST_CHECK(isOfType(json["int64"])); + BOOST_CHECK(isOfType(json["int64"])); BOOST_CHECK(isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["int64"])); + BOOST_CHECK(!isOfType(json["int64"])); BOOST_CHECK(!isOfType(json["double"])); BOOST_CHECK(!isOfType(json["string"])); BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); } BOOST_AUTO_TEST_CASE(json_isisOfTypeIfExists) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; + json["uint"] = 2u; + json["int64"] = 0x4000000000000000; + json["uint64"] = 0x4000000000000000u; json["string"] = "Hello World!"; BOOST_CHECK(isOfTypeIfExists(json, "float")); BOOST_CHECK(isOfTypeIfExists(json, "double")); BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int64")); - BOOST_CHECK(isOfTypeIfExists(json, "int64")); + BOOST_CHECK(isOfTypeIfExists(json, "int")); + BOOST_CHECK(isOfTypeIfExists(json, "uint")); + BOOST_CHECK(isOfTypeIfExists(json, "int")); + BOOST_CHECK(isOfTypeIfExists(json, "int64")); + BOOST_CHECK(isOfTypeIfExists(json, "uint64")); BOOST_CHECK(isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "int64")); + BOOST_CHECK(!isOfTypeIfExists(json, "int64")); BOOST_CHECK(!isOfTypeIfExists(json, "double")); BOOST_CHECK(!isOfTypeIfExists(json, "string")); BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(isOfTypeIfExists(json, "NOT_EXISTING")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(isOfTypeIfExists(json, "NOT_EXISTING")); } BOOST_AUTO_TEST_CASE(json_getOrDefault) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; - json["uint64"] = Json::UInt64{0x5000000000000000}; + json["int64"] = 0x4000000000000000; + json["uint64"] = 0x5000000000000000; json["string"] = "Hello World!"; - BOOST_CHECK(getOrDefault(json["float"]) == 3.1f); - BOOST_CHECK(getOrDefault(json["float"], -1.1f) == 3.1f); - BOOST_CHECK(getOrDefault(json["no_float"], -1.1f) == -1.1f); - BOOST_CHECK(getOrDefault(json["double"]) == 3.1); - BOOST_CHECK(getOrDefault(json["double"], -1) == 3.1); - BOOST_CHECK(getOrDefault(json["no_double"], -1.1) == -1.1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], -1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], -1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], 1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], 1) == 1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], -1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["int64"], -1) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["no_int64"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["int64"], 1) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["no_int64"], 1) == 1); - BOOST_CHECK(getOrDefault(json["uint64"]) == 0x5000000000000000); - BOOST_CHECK(getOrDefault(json["uint64"], 1) == 0x5000000000000000); - BOOST_CHECK(getOrDefault(json["no_uint64"], 1) == 1); - BOOST_CHECK(getOrDefault(json["string"], "ERROR") == "Hello World!"); - BOOST_CHECK(getOrDefault(json["no_string"]).empty()); - BOOST_CHECK(getOrDefault(json["no_string"], "ERROR") == "ERROR"); + BOOST_CHECK(getOrDefault(json, "float") == 3.1f); + BOOST_CHECK(getOrDefault(json, "float", -1.1f) == 3.1f); + BOOST_CHECK(getOrDefault(json, "no_float", -1.1f) == -1.1f); + BOOST_CHECK(getOrDefault(json, "double") == 3.1); + BOOST_CHECK(getOrDefault(json, "double", -1) == 3.1); + BOOST_CHECK(getOrDefault(json, "no_double", -1.1) == -1.1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", -1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", -1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", 1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", 1) == 1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", -1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int64") == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "int64", -1) == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "no_int64", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int64") == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "int64", 1) == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "no_int64", 1) == 1); + BOOST_CHECK(getOrDefault(json, "uint64") == 0x5000000000000000); + BOOST_CHECK(getOrDefault(json, "uint64", 1) == 0x5000000000000000); + BOOST_CHECK(getOrDefault(json, "no_uint64", 1) == 1); + BOOST_CHECK(getOrDefault(json, "string", "ERROR") == "Hello World!"); + BOOST_CHECK(getOrDefault(json, "no_string").empty()); + BOOST_CHECK(getOrDefault(json, "no_string", "ERROR") == "ERROR"); } BOOST_AUTO_TEST_CASE(json_get) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; - json["uint64"] = Json::UInt64{0x5000000000000000}; + json["int64"] = 0x4000000000000000; + json["uint64"] = 0x5000000000000000; json["string"] = "Hello World!"; BOOST_CHECK(get(json["float"]) == 3.1f); BOOST_CHECK(get(json["double"]) == 3.1); BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(get(json["uint64"]) == 0x5000000000000000); + BOOST_CHECK(get(json["int"]) == 2); + BOOST_CHECK(get(json["int"]) == 2); + BOOST_CHECK(get(json["int"]) == 2); + BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); + BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); + BOOST_CHECK(get(json["uint64"]) == 0x5000000000000000); BOOST_CHECK(get(json["string"]) == "Hello World!"); } +template +void json_test_int_range() +{ + Json max = {{"v", std::numeric_limits::max()}}; + Json min = {{"v", std::numeric_limits::min()}}; + Json overflow = {{"v", static_cast(std::numeric_limits::max()) + 1}}; + Json underflow = {{"v", static_cast(std::numeric_limits::min()) - 1}}; + BOOST_CHECK(getOrDefault(max, "v", 0) == std::numeric_limits::max()); + BOOST_CHECK(getOrDefault(min, "v", 0) == std::numeric_limits::min()); + BOOST_CHECK(getOrDefault(overflow, "v", 0) == 0); + BOOST_CHECK(getOrDefault(underflow, "v", 0) == 0); + BOOST_CHECK(get(max["v"]) == std::numeric_limits::max()); + BOOST_CHECK(get(min["v"]) == std::numeric_limits::min()); + BOOST_CHECK_THROW(get(overflow["v"]), InvalidType); + BOOST_CHECK_THROW(get(underflow["v"]), InvalidType); +} + +BOOST_AUTO_TEST_CASE(json_range_checks) +{ + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + + Json overflow = {{"v", static_cast(std::numeric_limits::max()) * 2}}; + Json underflow = {{"v", static_cast(std::numeric_limits::min()) / 2}}; + BOOST_CHECK(getOrDefault({{"v", std::numeric_limits::max()}}, "v", 0) == std::numeric_limits::max()); + BOOST_CHECK(getOrDefault({{"v", std::numeric_limits::min()}}, "v", 0) == std::numeric_limits::min()); + BOOST_CHECK(getOrDefault(overflow, "v", 0) == 0); + BOOST_CHECK(getOrDefault(underflow, "v", 0) == 0); + BOOST_CHECK_THROW(get(overflow["v"]), InvalidType); + BOOST_CHECK_THROW(get(underflow["v"]), InvalidType); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 73ebb2c54089..b3b93cb3aa11 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1180,15 +1180,20 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths) OptionsReaderAndMessages result = runCLI(commandLine, standardJsonInput); - Json::Value parsedStdout; + Json parsedStdout; std::string jsonParsingErrors; BOOST_TEST(util::jsonParseStrict(result.stdoutContent, parsedStdout, &jsonParsingErrors)); BOOST_TEST(jsonParsingErrors == ""); - for (Json::Value const& errorDict: parsedStdout["errors"]) + for (Json const& errorDict: parsedStdout["errors"]) // The error list might contain pre-release compiler warning BOOST_TEST(errorDict["severity"] != "error"); + // we might be able to use ranges again, but the nlohmann::json support is not yet fully there. + // (parsedStdout["sources"].items() | ranges::views::keys | ranges::to) + std::set sources; + for (auto const& [key, _]: parsedStdout["sources"].items()) + sources.insert(key); BOOST_TEST( - (parsedStdout["sources"].getMemberNames() | ranges::to) == + sources == (expectedSources | ranges::views::keys | ranges::to) + std::set{"main.sol"} ); diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 1bb04bf66aad..c7e94f40b779 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -58,13 +58,13 @@ void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize, if (!_quiet) cout << "Testing compiler " << (_optimize ? "with" : "without") << " optimizer." << endl; - Json::Value config = Json::objectValue; + Json config; config["language"] = "Solidity"; - config["sources"] = Json::objectValue; - config["sources"][""] = Json::objectValue; + config["sources"] = Json::object(); + config["sources"][""] = Json::object(); config["sources"][""]["content"] = _input; - config["settings"] = Json::objectValue; - config["settings"]["optimizer"] = Json::objectValue; + config["settings"] = Json::object(); + config["settings"]["optimizer"] = Json::object(); config["settings"]["optimizer"]["enabled"] = _optimize; config["settings"]["optimizer"]["runs"] = static_cast(OptimiserSettings{}.expectedExecutionsPerDeployment); config["settings"]["evmVersion"] = "berlin"; @@ -155,23 +155,23 @@ void FuzzerUtil::runCompiler(string const& _input, bool _quiet) // This should be safe given the above copies the output. solidity_reset(); - Json::Value output; + Json output; if (!jsonParseStrict(outputString, output)) { string msg{"Compiler produced invalid JSON output."}; cout << msg << endl; BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); } - if (output.isMember("errors")) + if (output.contains("errors")) for (auto const& error: output["errors"]) { - string invalid = findAnyOf(error["type"].asString(), vector{ + string invalid = findAnyOf(error["type"].get(), vector{ "Exception", "InternalCompilerError" }); if (!invalid.empty()) { - string msg = "Invalid error: \"" + error["type"].asString() + "\""; + string msg = "Invalid error: \"" + error["type"].get() + "\""; cout << msg << endl; BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); } diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp index 34147090882c..9d98190ddacf 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp @@ -57,7 +57,7 @@ optional SolidityCompilationFramework::compileContract() else contractName = m_compilerInput.contractName; evmasm::LinkerObject obj = m_compiler.object(contractName); - Json::Value methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"]; + Json methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"]; return CompilerOutput{obj.bytecode, methodIdentifiers}; } } @@ -164,10 +164,10 @@ evmc::Result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle) // isabelle test entry point. At the moment, we are sure that the // entry point is the second method in the contract (hence the ++) // but not its name. - methodName = (++cOutput->methodIdentifiersInContract.begin())->asString() + + methodName = (++cOutput->methodIdentifiersInContract.begin())->get() + _fuzzIsabelle.substr(2, _fuzzIsabelle.size()); else - methodName = cOutput->methodIdentifiersInContract[m_methodName].asString(); + methodName = cOutput->methodIdentifiersInContract[m_methodName].get(); return deployAndExecute( cOutput->byteCode, diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.h b/test/tools/ossfuzz/SolidityEvmoneInterface.h index ea684ea72332..00582c681e62 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.h +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.h @@ -35,7 +35,7 @@ struct CompilerOutput /// EVM bytecode returned by compiler solidity::bytes byteCode; /// Method identifiers in a contract - Json::Value methodIdentifiersInContract; + Json methodIdentifiersInContract; }; struct CompilerInput @@ -89,7 +89,7 @@ class SolidityCompilationFramework m_compilerInput.libraryAddresses = std::move(_libraryAddresses); } /// @returns method identifiers in contract called @param _contractName. - Json::Value methodIdentifiers(std::string const& _contractName) + Json methodIdentifiers(std::string const& _contractName) { return m_compiler.interfaceSymbols(_contractName)["methods"]; } diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index a54bf09af146..018de32ee2e7 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -380,7 +380,7 @@ BOOST_AUTO_TEST_CASE(toJson) CharStream sourceStream(sourceCode, current_test_case().p_name); Program program = get(Program::load(sourceStream)); - Json::Value parsingResult; + Json parsingResult; std::string errors; BOOST_TEST(jsonParseStrict(program.toJson(), parsingResult, &errors)); BOOST_TEST(errors.empty()); diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 3089591ed8ba..f24f5e03f4bb 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -111,7 +111,7 @@ ostream& phaser::operator<<(ostream& _stream, Program const& _program) string Program::toJson() const { - Json::Value serializedAst = AsmJsonConverter(0)(*m_ast); + Json serializedAst = AsmJsonConverter(0)(*m_ast); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); }