Basic nlohmann-json integration.

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
This commit is contained in:
Alexander Arlt 2018-07-20 10:46:50 +02:00 committed by Alex Beregszaszi
parent 2cc6610e40
commit 5c66718295
65 changed files with 1681 additions and 1812 deletions

View File

@ -43,9 +43,8 @@ include(EthCcache)
# Let's find our dependencies # Let's find our dependencies
include(EthDependencies) include(EthDependencies)
include(fmtlib) include(fmtlib)
include(jsoncpp) include(nlohmann-json)
include(range-v3) include(range-v3)
include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR})
find_package(Threads) find_package(Threads)

View File

@ -1,70 +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 "${CMAKE_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()
ExternalProject_Add(jsoncpp-project
PREFIX "${prefix}"
DOWNLOAD_DIR "${CMAKE_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=<INSTALL_DIR>
-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}
${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)

14
cmake/nlohmann-json.cmake Normal file
View File

@ -0,0 +1,14 @@
include(ExternalProject)
ExternalProject_Add(nlohmann-json
DOWNLOAD_DIR "${CMAKE_SOURCE_DIR}/deps/nlohmann/json"
DOWNLOAD_NAME json.hpp
DOWNLOAD_NO_EXTRACT 1
URL https://github.com/nlohmann/json/releases/download/v3.10.2/json.hpp
URL_HASH SHA256=059743e48b37e41579ee3a92e82e984bfa0d2a9a2b20b175d04db8089f46f047
CMAKE_COMMAND true
BUILD_COMMAND true
INSTALL_COMMAND true
)
include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/deps/nlohmann)

View File

@ -34,62 +34,33 @@ picosha2:
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
jsoncpp: nlohmann-json:
The JsonCpp library's source code, including accompanying documentation, __ _____ _____ _____
tests and demonstration applications, are licensed under the following __| | __| | | | JSON for Modern C++
conditions... | | |__ | | | | | | version 3.10.2
|_____|_____|_____|_|___| https://github.com/nlohmann/json
The JsonCpp Authors explicitly disclaim copyright in all Licensed under the MIT License <http://opensource.org/licenses/MIT>.
jurisdictions which recognize such a disclaimer. In such jurisdictions, SPDX-License-Identifier: MIT
this software is released into the Public Domain. Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of Permission is hereby granted, free of charge, to any person obtaining a copy
2010), this software is Copyright (c) 2007-2010 by The JsonCpp Authors, and is of this software and associated documentation files (the "Software"), to deal
released under the terms of the MIT License (see below). in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
In jurisdictions which recognize Public Domain property, the user of this copies of the Software, and to permit persons to whom the Software is
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
Copyright (c) 2007-2010 The JsonCpp Authors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be included in all
included in all copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
========================================================================
(END LICENSE TEXT)
The MIT license is compatible with both the GPL and commercial
software, affording one all of the rights of Public Domain with the
minor nuisance of being required to keep the above copyright notice
and license text in the source code. Note also that by accepting the
Public Domain "license" you can re-license your copy using whatever
license you like.
scanner/token: scanner/token:
The liblangutil/{CharStream,Scanner,Token}.{h,cpp} files are derived from The liblangutil/{CharStream,Scanner,Token}.{h,cpp} files are derived from

View File

@ -34,8 +34,6 @@
#include <liblangutil/CharStream.h> #include <liblangutil/CharStream.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
#include <json/json.h>
#include <range/v3/algorithm/any_of.hpp> #include <range/v3/algorithm/any_of.hpp>
#include <range/v3/view/enumerate.hpp> #include <range/v3/view/enumerate.hpp>
@ -222,11 +220,12 @@ string Assembly::assemblyString(
return tmp.str(); return tmp.str();
} }
Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices, bool _includeSourceList) const Json Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices, bool _includeSourceList) const
{ {
Json::Value root; Json root{Json::object()};
root[".code"] = Json::arrayValue; root[".code"] = Json::array();
Json::Value& code = root[".code"];
Json& code = root[".code"];
for (AssemblyItem const& item: m_items) for (AssemblyItem const& item: m_items)
{ {
int sourceIndex = -1; int sourceIndex = -1;
@ -238,7 +237,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
} }
auto [name, data] = item.nameAndData(); auto [name, data] = item.nameAndData();
Json::Value jsonItem; Json jsonItem;
jsonItem["name"] = name; jsonItem["name"] = name;
jsonItem["begin"] = item.location().start; jsonItem["begin"] = item.location().start;
jsonItem["end"] = item.location().end; jsonItem["end"] = item.location().end;
@ -254,32 +253,32 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
if (!data.empty()) if (!data.empty())
jsonItem["value"] = data; jsonItem["value"] = data;
jsonItem["source"] = sourceIndex; jsonItem["source"] = sourceIndex;
code.append(std::move(jsonItem)); code.emplace_back(std::move(jsonItem));
if (item.type() == AssemblyItemType::Tag) if (item.type() == AssemblyItemType::Tag)
{ {
Json::Value jumpdest; Json jumpdest;
jumpdest["name"] = "JUMPDEST"; jumpdest["name"] = "JUMPDEST";
jumpdest["begin"] = item.location().start; jumpdest["begin"] = item.location().start;
jumpdest["end"] = item.location().end; jumpdest["end"] = item.location().end;
jumpdest["source"] = sourceIndex; jumpdest["source"] = sourceIndex;
if (item.m_modifierDepth != 0) if (item.m_modifierDepth != 0)
jumpdest["modifierDepth"] = static_cast<int>(item.m_modifierDepth); jumpdest["modifierDepth"] = static_cast<int>(item.m_modifierDepth);
code.append(std::move(jumpdest)); code.emplace_back(std::move(jumpdest));
} }
} }
if (_includeSourceList) if (_includeSourceList)
{ {
root["sourceList"] = Json::arrayValue; root["sourceList"] = Json::array();
Json::Value& jsonSourceList = root["sourceList"]; Json& jsonSourceList = root["sourceList"];
for (auto const& [name, index]: _sourceIndices) for (auto const& [name, index]: _sourceIndices)
jsonSourceList[index] = name; jsonSourceList[index] = name;
} }
if (!m_data.empty() || !m_subs.empty()) if (!m_data.empty() || !m_subs.empty())
{ {
root[".data"] = Json::objectValue; root[".data"] = Json::object();
Json::Value& data = root[".data"]; Json& data = root[".data"];
for (auto const& i: m_data) for (auto const& i: m_data)
if (u256(i.first) >= m_subs.size()) if (u256(i.first) >= m_subs.size())
data[util::toHex(toBigEndian((u256)i.first), util::HexPrefix::DontAdd, util::HexCase::Upper)] = util::toHex(i.second); data[util::toHex(toBigEndian((u256)i.first), util::HexPrefix::DontAdd, util::HexCase::Upper)] = util::toHex(i.second);

View File

@ -29,12 +29,11 @@
#include <libsolutil/Common.h> #include <libsolutil/Common.h>
#include <libsolutil/Assertions.h> #include <libsolutil/Assertions.h>
#include <libsolutil/JSON.h>
#include <libsolutil/Keccak256.h> #include <libsolutil/Keccak256.h>
#include <libsolidity/interface/OptimiserSettings.h> #include <libsolidity/interface/OptimiserSettings.h>
#include <json/json.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <memory> #include <memory>
@ -149,7 +148,7 @@ public:
) const; ) const;
/// Create a JSON representation of the assembly. /// Create a JSON representation of the assembly.
Json::Value assemblyJSON( Json assemblyJSON(
std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>(), std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>(),
bool _includeSourceList = true bool _includeSourceList = true
) const; ) const;

View File

@ -32,11 +32,10 @@
#include <liblangutil/SourceLocation.h> #include <liblangutil/SourceLocation.h>
#include <libevmasm/Instruction.h> #include <libevmasm/Instruction.h>
#include <libsolutil/FixedHash.h> #include <libsolutil/FixedHash.h>
#include <libsolutil/JSON.h>
#include <libsolutil/LazyInit.h> #include <libsolutil/LazyInit.h>
#include <libsolutil/Visitor.h> #include <libsolutil/Visitor.h>
#include <json/json.h>
#include <range/v3/view/subrange.hpp> #include <range/v3/view/subrange.hpp>
#include <range/v3/view/map.hpp> #include <range/v3/view/map.hpp>

View File

@ -51,7 +51,7 @@ namespace
{ {
template<typename V, template<typename> typename C> template<typename V, template<typename> typename C>
void addIfSet(std::vector<pair<string, Json::Value>>& _attributes, string const& _name, C<V> const& _value) void addIfSet(std::vector<pair<string, Json>>& _attributes, string const& _name, C<V> const& _value)
{ {
if constexpr (std::is_same_v<C<V>, solidity::util::SetOnce<V>>) if constexpr (std::is_same_v<C<V>, solidity::util::SetOnce<V>>)
{ {
@ -82,23 +82,23 @@ ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, map<string, u
void ASTJsonExporter::setJsonNode( void ASTJsonExporter::setJsonNode(
ASTNode const& _node, ASTNode const& _node,
string const& _nodeName, string const& _nodeName,
initializer_list<pair<string, Json::Value>>&& _attributes initializer_list<pair<string, Json>>&& _attributes
) )
{ {
ASTJsonExporter::setJsonNode( ASTJsonExporter::setJsonNode(
_node, _node,
_nodeName, _nodeName,
std::vector<pair<string, Json::Value>>(std::move(_attributes)) std::vector<pair<string, Json>>(std::move(_attributes))
); );
} }
void ASTJsonExporter::setJsonNode( void ASTJsonExporter::setJsonNode(
ASTNode const& _node, ASTNode const& _node,
string const& _nodeType, string const& _nodeType,
std::vector<pair<string, Json::Value>>&& _attributes std::vector<pair<string, Json>>&& _attributes
) )
{ {
m_currentValue = Json::objectValue; m_currentValue = Json::object();
m_currentValue["id"] = nodeId(_node); m_currentValue["id"] = nodeId(_node);
m_currentValue["src"] = sourceLocationToString(_node.location()); m_currentValue["src"] = sourceLocationToString(_node.location());
if (auto const* documented = dynamic_cast<Documented const*>(&_node)) if (auto const* documented = dynamic_cast<Documented const*>(&_node))
@ -126,12 +126,12 @@ string ASTJsonExporter::sourceLocationToString(SourceLocation const& _location)
return to_string(_location.start) + ":" + to_string(length) + ":" + (sourceIndexOpt.has_value() ? to_string(sourceIndexOpt.value()) : "-1"); return to_string(_location.start) + ":" + to_string(length) + ":" + (sourceIndexOpt.has_value() ? to_string(sourceIndexOpt.value()) : "-1");
} }
Json::Value ASTJsonExporter::sourceLocationsToJson(vector<SourceLocation> const& _sourceLocations) const Json ASTJsonExporter::sourceLocationsToJson(vector<SourceLocation> const& _sourceLocations) const
{ {
Json::Value locations = Json::arrayValue; Json locations = Json::array();
for (SourceLocation const& location: _sourceLocations) for (SourceLocation const& location: _sourceLocations)
locations.append(sourceLocationToString(location)); locations.emplace_back(sourceLocationToString(location));
return locations; return locations;
} }
@ -141,33 +141,33 @@ string ASTJsonExporter::namePathToString(std::vector<ASTString> const& _namePath
return boost::algorithm::join(_namePath, "."); return boost::algorithm::join(_namePath, ".");
} }
Json::Value ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation) Json ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation)
{ {
Json::Value typeDescriptions(Json::objectValue); Json typeDescriptions(Json::object());
typeDescriptions["typeString"] = _tp ? Json::Value(_tp->toString(_withoutDataLocation)) : Json::nullValue; typeDescriptions["typeString"] = _tp ? Json(_tp->toString(_withoutDataLocation)) : Json{};
typeDescriptions["typeIdentifier"] = _tp ? Json::Value(_tp->identifier()) : Json::nullValue; typeDescriptions["typeIdentifier"] = _tp ? Json(_tp->identifier()) : Json{};
return typeDescriptions; return typeDescriptions;
} }
Json::Value ASTJsonExporter::typePointerToJson(std::optional<FuncCallArguments> const& _tps) Json ASTJsonExporter::typePointerToJson(std::optional<FuncCallArguments> const& _tps)
{ {
if (_tps) if (_tps)
{ {
Json::Value arguments(Json::arrayValue); Json arguments(Json::array());
for (auto const& tp: _tps->types) for (auto const& tp: _tps->types)
appendMove(arguments, typePointerToJson(tp)); appendMove(arguments, typePointerToJson(tp));
return arguments; return arguments;
} }
else else
return Json::nullValue; return Json{};
} }
void ASTJsonExporter::appendExpressionAttributes( void ASTJsonExporter::appendExpressionAttributes(
std::vector<pair<string, Json::Value>>& _attributes, std::vector<pair<string, Json>>& _attributes,
ExpressionAnnotation const& _annotation ExpressionAnnotation const& _annotation
) )
{ {
std::vector<pair<string, Json::Value>> exprAttributes = { std::vector<pair<string, Json>> exprAttributes = {
make_pair("typeDescriptions", typePointerToJson(_annotation.type)), make_pair("typeDescriptions", typePointerToJson(_annotation.type)),
make_pair("argumentTypes", typePointerToJson(_annotation.arguments)) make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
}; };
@ -182,18 +182,19 @@ void ASTJsonExporter::appendExpressionAttributes(
_attributes += exprAttributes; _attributes += exprAttributes;
} }
Json::Value ASTJsonExporter::inlineAssemblyIdentifierToJson(pair<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const Json ASTJsonExporter::inlineAssemblyIdentifierToJson(pair<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
{ {
Json::Value tuple(Json::objectValue); Json tuple(Json::object());
tuple["src"] = sourceLocationToString(nativeLocationOf(*_info.first)); tuple["src"] = sourceLocationToString(nativeLocationOf(*_info.first));
tuple["declaration"] = idOrNull(_info.second.declaration); tuple["declaration"] = idOrNull(_info.second.declaration);
tuple["isSlot"] = Json::Value(_info.second.suffix == "slot"); tuple["isSlot"] = Json(_info.second.suffix == "slot");
tuple["isOffset"] = Json::Value(_info.second.suffix == "offset"); tuple["isOffset"] = Json(_info.second.suffix == "offset");
if (!_info.second.suffix.empty()) 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)); // TODO: assert?
tuple["valueSize"] = Json(static_cast<Json::number_integer_t>(_info.second.valueSize));
return tuple; return tuple;
} }
@ -203,7 +204,7 @@ void ASTJsonExporter::print(ostream& _stream, ASTNode const& _node, util::JsonFo
_stream << util::jsonPrint(toJson(_node), _format); _stream << util::jsonPrint(toJson(_node), _format);
} }
Json::Value ASTJsonExporter::toJson(ASTNode const& _node) Json ASTJsonExporter::toJson(ASTNode const& _node)
{ {
_node.accept(*this); _node.accept(*this);
return util::removeNullMembers(std::move(m_currentValue)); return util::removeNullMembers(std::move(m_currentValue));
@ -211,19 +212,19 @@ Json::Value ASTJsonExporter::toJson(ASTNode const& _node)
bool ASTJsonExporter::visit(SourceUnit const& _node) bool ASTJsonExporter::visit(SourceUnit const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue), make_pair("license", _node.licenseString() ? Json(*_node.licenseString()) : Json{}),
make_pair("nodes", toJson(_node.nodes())) make_pair("nodes", toJson(_node.nodes()))
}; };
if (_node.annotation().exportedSymbols.set()) if (_node.annotation().exportedSymbols.set())
{ {
Json::Value exportedSymbols = Json::objectValue; Json exportedSymbols{Json::object()};
for (auto const& sym: *_node.annotation().exportedSymbols) for (auto const& sym: *_node.annotation().exportedSymbols)
{ {
exportedSymbols[sym.first] = Json::arrayValue; exportedSymbols[sym.first] = Json::array();
for (Declaration const* overload: sym.second) for (Declaration const* overload: sym.second)
exportedSymbols[sym.first].append(nodeId(*overload)); exportedSymbols[sym.first].emplace_back(nodeId(*overload));
} }
attributes.emplace_back("exportedSymbols", exportedSymbols); attributes.emplace_back("exportedSymbols", exportedSymbols);
@ -238,9 +239,9 @@ bool ASTJsonExporter::visit(SourceUnit const& _node)
bool ASTJsonExporter::visit(PragmaDirective const& _node) bool ASTJsonExporter::visit(PragmaDirective const& _node)
{ {
Json::Value literals(Json::arrayValue); Json literals(Json::array());
for (auto const& literal: _node.literals()) for (auto const& literal: _node.literals())
literals.append(literal); literals.emplace_back(literal);
setJsonNode(_node, "PragmaDirective", { setJsonNode(_node, "PragmaDirective", {
make_pair("literals", std::move(literals)) make_pair("literals", std::move(literals))
}); });
@ -249,7 +250,7 @@ bool ASTJsonExporter::visit(PragmaDirective const& _node)
bool ASTJsonExporter::visit(ImportDirective const& _node) bool ASTJsonExporter::visit(ImportDirective const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("file", _node.path()), make_pair("file", _node.path()),
make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)), make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)),
make_pair("scope", idOrNull(_node.scope())) make_pair("scope", idOrNull(_node.scope()))
@ -258,17 +259,17 @@ bool ASTJsonExporter::visit(ImportDirective const& _node)
addIfSet(attributes, "absolutePath", _node.annotation().absolutePath); addIfSet(attributes, "absolutePath", _node.annotation().absolutePath);
attributes.emplace_back("unitAlias", _node.name()); 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()) for (auto const& symbolAlias: _node.symbolAliases())
{ {
Json::Value tuple(Json::objectValue); Json tuple(Json::object());
solAssert(symbolAlias.symbol, ""); solAssert(symbolAlias.symbol, "");
tuple["foreign"] = toJson(*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()); tuple["nameLocation"] = sourceLocationToString(_node.nameLocation());
symbolAliases.append(tuple); symbolAliases.emplace_back(tuple);
} }
attributes.emplace_back("symbolAliases", std::move(symbolAliases)); attributes.emplace_back("symbolAliases", std::move(symbolAliases));
setJsonNode(_node, "ImportDirective", std::move(attributes)); setJsonNode(_node, "ImportDirective", std::move(attributes));
@ -277,10 +278,10 @@ bool ASTJsonExporter::visit(ImportDirective const& _node)
bool ASTJsonExporter::visit(ContractDefinition const& _node) bool ASTJsonExporter::visit(ContractDefinition const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json{}),
make_pair("contractKind", contractKind(_node.contractKind())), make_pair("contractKind", contractKind(_node.contractKind())),
make_pair("abstract", _node.abstract()), make_pair("abstract", _node.abstract()),
make_pair("baseContracts", toJson(_node.baseContracts())), make_pair("baseContracts", toJson(_node.baseContracts())),
@ -302,10 +303,10 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node)
bool ASTJsonExporter::visit(IdentifierPath const& _node) bool ASTJsonExporter::visit(IdentifierPath const& _node)
{ {
Json::Value nameLocations = Json::arrayValue; Json nameLocations = Json::array();
for (SourceLocation location: _node.pathLocations()) for (SourceLocation location: _node.pathLocations())
nameLocations.append(sourceLocationToString(location)); nameLocations.emplace_back(sourceLocationToString(location));
setJsonNode(_node, "IdentifierPath", { setJsonNode(_node, "IdentifierPath", {
make_pair("name", namePathToString(_node.path())), make_pair("name", namePathToString(_node.path())),
@ -319,24 +320,24 @@ bool ASTJsonExporter::visit(InheritanceSpecifier const& _node)
{ {
setJsonNode(_node, "InheritanceSpecifier", { setJsonNode(_node, "InheritanceSpecifier", {
make_pair("baseName", toJson(_node.name())), make_pair("baseName", toJson(_node.name())),
make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue) make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json{})
}); });
return false; return false;
} }
bool ASTJsonExporter::visit(UsingForDirective const& _node) bool ASTJsonExporter::visit(UsingForDirective const& _node)
{ {
vector<pair<string, Json::Value>> attributes = { vector<pair<string, Json>> attributes = {
make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue) make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json{})
}; };
if (_node.usesBraces()) if (_node.usesBraces())
{ {
Json::Value functionList; Json functionList;
for (auto const& function: _node.functionsOrLibrary()) for (auto const& function: _node.functionsOrLibrary())
{ {
Json::Value functionNode; Json functionNode;
functionNode["function"] = toJson(*function); functionNode["function"] = toJson(*function);
functionList.append(std::move(functionNode)); functionList.emplace_back(std::move(functionNode));
} }
attributes.emplace_back("functionList", std::move(functionList)); attributes.emplace_back("functionList", std::move(functionList));
} }
@ -351,7 +352,7 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node)
bool ASTJsonExporter::visit(StructDefinition const& _node) bool ASTJsonExporter::visit(StructDefinition const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())), make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
@ -368,7 +369,7 @@ bool ASTJsonExporter::visit(StructDefinition const& _node)
bool ASTJsonExporter::visit(EnumDefinition const& _node) bool ASTJsonExporter::visit(EnumDefinition const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("members", toJson(_node.members())) make_pair("members", toJson(_node.members()))
@ -393,7 +394,7 @@ bool ASTJsonExporter::visit(EnumValue const& _node)
bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node) bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node)
{ {
solAssert(_node.underlyingType(), ""); solAssert(_node.underlyingType(), "");
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("underlyingType", toJson(*_node.underlyingType())) make_pair("underlyingType", toJson(*_node.underlyingType()))
@ -423,18 +424,18 @@ bool ASTJsonExporter::visit(OverrideSpecifier const& _node)
bool ASTJsonExporter::visit(FunctionDefinition const& _node) bool ASTJsonExporter::visit(FunctionDefinition const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json{}),
make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())), make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())),
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())), make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
make_pair("virtual", _node.markedVirtual()), make_pair("virtual", _node.markedVirtual()),
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json{}),
make_pair("parameters", toJson(_node.parameterList())), make_pair("parameters", toJson(_node.parameterList())),
make_pair("returnParameters", toJson(*_node.returnParameterList())), make_pair("returnParameters", toJson(*_node.returnParameterList())),
make_pair("modifiers", toJson(_node.modifiers())), make_pair("modifiers", toJson(_node.modifiers())),
make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue), make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json{}),
make_pair("implemented", _node.isImplemented()), make_pair("implemented", _node.isImplemented()),
make_pair("scope", idOrNull(_node.scope())) make_pair("scope", idOrNull(_node.scope()))
}; };
@ -461,7 +462,7 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node)
bool ASTJsonExporter::visit(VariableDeclaration const& _node) bool ASTJsonExporter::visit(VariableDeclaration const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("typeName", toJson(_node.typeName())), make_pair("typeName", toJson(_node.typeName())),
@ -469,9 +470,9 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node)
make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())), make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
make_pair("stateVariable", _node.isStateVariable()), make_pair("stateVariable", _node.isStateVariable()),
make_pair("storageLocation", location(_node.referenceLocation())), make_pair("storageLocation", location(_node.referenceLocation())),
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json{}),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())), make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue), make_pair("value", _node.value() ? toJson(*_node.value()) : Json{}),
make_pair("scope", idOrNull(_node.scope())), make_pair("scope", idOrNull(_node.scope())),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
}; };
@ -489,15 +490,15 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node)
bool ASTJsonExporter::visit(ModifierDefinition const& _node) bool ASTJsonExporter::visit(ModifierDefinition const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json{}),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())), make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("parameters", toJson(_node.parameterList())), make_pair("parameters", toJson(_node.parameterList())),
make_pair("virtual", _node.markedVirtual()), make_pair("virtual", _node.markedVirtual()),
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json{}),
make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue) make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json{})
}; };
if (!_node.annotation().baseFunctions.empty()) if (!_node.annotation().baseFunctions.empty())
attributes.emplace_back(make_pair("baseModifiers", getContainerIds(_node.annotation().baseFunctions, true))); attributes.emplace_back(make_pair("baseModifiers", getContainerIds(_node.annotation().baseFunctions, true)));
@ -507,9 +508,9 @@ bool ASTJsonExporter::visit(ModifierDefinition const& _node)
bool ASTJsonExporter::visit(ModifierInvocation const& _node) bool ASTJsonExporter::visit(ModifierInvocation const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes{ std::vector<pair<string, Json>> attributes{
make_pair("modifierName", toJson(_node.name())), make_pair("modifierName", toJson(_node.name())),
make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue) make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json{})
}; };
if (Declaration const* declaration = _node.name().annotation().referencedDeclaration) if (Declaration const* declaration = _node.name().annotation().referencedDeclaration)
{ {
@ -525,10 +526,10 @@ bool ASTJsonExporter::visit(ModifierInvocation const& _node)
bool ASTJsonExporter::visit(EventDefinition const& _node) bool ASTJsonExporter::visit(EventDefinition const& _node)
{ {
m_inEvent = true; m_inEvent = true;
std::vector<pair<string, Json::Value>> _attributes = { std::vector<pair<string, Json>> _attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json{}),
make_pair("parameters", toJson(_node.parameterList())), make_pair("parameters", toJson(_node.parameterList())),
make_pair("anonymous", _node.isAnonymous()) make_pair("anonymous", _node.isAnonymous())
}; };
@ -545,10 +546,10 @@ bool ASTJsonExporter::visit(EventDefinition const& _node)
bool ASTJsonExporter::visit(ErrorDefinition const& _node) bool ASTJsonExporter::visit(ErrorDefinition const& _node)
{ {
std::vector<pair<string, Json::Value>> _attributes = { std::vector<pair<string, Json>> _attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json{}),
make_pair("parameters", toJson(_node.parameterList())) make_pair("parameters", toJson(_node.parameterList()))
}; };
if (m_stackState >= CompilerStack::State::AnalysisPerformed) if (m_stackState >= CompilerStack::State::AnalysisPerformed)
@ -560,7 +561,7 @@ bool ASTJsonExporter::visit(ErrorDefinition const& _node)
bool ASTJsonExporter::visit(ElementaryTypeName const& _node) bool ASTJsonExporter::visit(ElementaryTypeName const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("name", _node.typeName().toString()), make_pair("name", _node.typeName().toString()),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
}; };
@ -616,7 +617,7 @@ bool ASTJsonExporter::visit(ArrayTypeName const& _node)
bool ASTJsonExporter::visit(InlineAssembly const& _node) bool ASTJsonExporter::visit(InlineAssembly const& _node)
{ {
vector<pair<string, Json::Value>> externalReferences; vector<pair<string, Json>> externalReferences;
for (auto const& it: _node.annotation().externalReferences) for (auto const& it: _node.annotation().externalReferences)
if (it.first) if (it.first)
@ -625,26 +626,26 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
inlineAssemblyIdentifierToJson(it) inlineAssemblyIdentifierToJson(it)
)); ));
Json::Value externalReferencesJson = Json::arrayValue; Json externalReferencesJson{Json::array()};
std::sort(externalReferences.begin(), externalReferences.end()); std::sort(externalReferences.begin(), externalReferences.end());
for (Json::Value& it: externalReferences | ranges::views::values) for (Json& it: externalReferences | ranges::views::values)
externalReferencesJson.append(std::move(it)); externalReferencesJson.emplace_back(std::move(it));
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
make_pair("externalReferences", std::move(externalReferencesJson)), make_pair("externalReferences", std::move(externalReferencesJson)),
make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name()) make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
}; };
if (_node.flags()) if (_node.flags())
{ {
Json::Value flags(Json::arrayValue); Json flags(Json::array());
for (auto const& flag: *_node.flags()) for (auto const& flag: *_node.flags())
if (flag) if (flag)
flags.append(*flag); flags.emplace_back(*flag);
else else
flags.append(Json::nullValue); flags.emplace_back(Json{});
attributes.emplace_back(make_pair("flags", std::move(flags))); attributes.emplace_back(make_pair("flags", std::move(flags)));
} }
setJsonNode(_node, "InlineAssembly", std::move(attributes)); setJsonNode(_node, "InlineAssembly", std::move(attributes));
@ -764,7 +765,7 @@ bool ASTJsonExporter::visit(RevertStatement const& _node)
bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node) bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node)
{ {
Json::Value varDecs(Json::arrayValue); Json varDecs(Json::array());
for (auto const& v: _node.declarations()) for (auto const& v: _node.declarations())
appendMove(varDecs, idOrNull(v.get())); appendMove(varDecs, idOrNull(v.get()));
setJsonNode(_node, "VariableDeclarationStatement", { setJsonNode(_node, "VariableDeclarationStatement", {
@ -785,7 +786,7 @@ bool ASTJsonExporter::visit(ExpressionStatement const& _node)
bool ASTJsonExporter::visit(Conditional const& _node) bool ASTJsonExporter::visit(Conditional const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("condition", toJson(_node.condition())), make_pair("condition", toJson(_node.condition())),
make_pair("trueExpression", toJson(_node.trueExpression())), make_pair("trueExpression", toJson(_node.trueExpression())),
make_pair("falseExpression", toJson(_node.falseExpression())) make_pair("falseExpression", toJson(_node.falseExpression()))
@ -797,7 +798,7 @@ bool ASTJsonExporter::visit(Conditional const& _node)
bool ASTJsonExporter::visit(Assignment const& _node) bool ASTJsonExporter::visit(Assignment const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("operator", TokenTraits::toString(_node.assignmentOperator())), make_pair("operator", TokenTraits::toString(_node.assignmentOperator())),
make_pair("leftHandSide", toJson(_node.leftHandSide())), make_pair("leftHandSide", toJson(_node.leftHandSide())),
make_pair("rightHandSide", toJson(_node.rightHandSide())) make_pair("rightHandSide", toJson(_node.rightHandSide()))
@ -809,8 +810,8 @@ bool ASTJsonExporter::visit(Assignment const& _node)
bool ASTJsonExporter::visit(TupleExpression const& _node) bool ASTJsonExporter::visit(TupleExpression const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("isInlineArray", Json::Value(_node.isInlineArray())), make_pair("isInlineArray", Json(_node.isInlineArray())),
make_pair("components", toJson(_node.components())), make_pair("components", toJson(_node.components())),
}; };
appendExpressionAttributes(attributes, _node.annotation()); appendExpressionAttributes(attributes, _node.annotation());
@ -820,7 +821,7 @@ bool ASTJsonExporter::visit(TupleExpression const& _node)
bool ASTJsonExporter::visit(UnaryOperation const& _node) bool ASTJsonExporter::visit(UnaryOperation const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("prefix", _node.isPrefixOperation()), make_pair("prefix", _node.isPrefixOperation()),
make_pair("operator", TokenTraits::toString(_node.getOperator())), make_pair("operator", TokenTraits::toString(_node.getOperator())),
make_pair("subExpression", toJson(_node.subExpression())) make_pair("subExpression", toJson(_node.subExpression()))
@ -832,7 +833,7 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node)
bool ASTJsonExporter::visit(BinaryOperation const& _node) bool ASTJsonExporter::visit(BinaryOperation const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("operator", TokenTraits::toString(_node.getOperator())), make_pair("operator", TokenTraits::toString(_node.getOperator())),
make_pair("leftExpression", toJson(_node.leftExpression())), make_pair("leftExpression", toJson(_node.leftExpression())),
make_pair("rightExpression", toJson(_node.rightExpression())), make_pair("rightExpression", toJson(_node.rightExpression())),
@ -845,10 +846,10 @@ bool ASTJsonExporter::visit(BinaryOperation const& _node)
bool ASTJsonExporter::visit(FunctionCall const& _node) bool ASTJsonExporter::visit(FunctionCall const& _node)
{ {
Json::Value names(Json::arrayValue); Json names(Json::array());
for (auto const& name: _node.names()) for (auto const& name: _node.names())
names.append(Json::Value(*name)); names.emplace_back(*name);
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("expression", toJson(_node.expression())), make_pair("expression", toJson(_node.expression())),
make_pair("names", std::move(names)), make_pair("names", std::move(names)),
make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())), make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())),
@ -869,11 +870,11 @@ bool ASTJsonExporter::visit(FunctionCall const& _node)
bool ASTJsonExporter::visit(FunctionCallOptions const& _node) bool ASTJsonExporter::visit(FunctionCallOptions const& _node)
{ {
Json::Value names(Json::arrayValue); Json names(Json::array());
for (auto const& name: _node.names()) for (auto const& name: _node.names())
names.append(Json::Value(*name)); names.emplace_back(Json(*name));
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("expression", toJson(_node.expression())), make_pair("expression", toJson(_node.expression())),
make_pair("names", std::move(names)), make_pair("names", std::move(names)),
make_pair("options", toJson(_node.options())), make_pair("options", toJson(_node.options())),
@ -886,7 +887,7 @@ bool ASTJsonExporter::visit(FunctionCallOptions const& _node)
bool ASTJsonExporter::visit(NewExpression const& _node) bool ASTJsonExporter::visit(NewExpression const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("typeName", toJson(_node.typeName())) make_pair("typeName", toJson(_node.typeName()))
}; };
appendExpressionAttributes(attributes, _node.annotation()); appendExpressionAttributes(attributes, _node.annotation());
@ -896,9 +897,9 @@ bool ASTJsonExporter::visit(NewExpression const& _node)
bool ASTJsonExporter::visit(MemberAccess const& _node) bool ASTJsonExporter::visit(MemberAccess const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("memberName", _node.memberName()), make_pair("memberName", _node.memberName()),
make_pair("memberLocation", Json::Value(sourceLocationToString(_node.memberLocation()))), make_pair("memberLocation", Json(sourceLocationToString(_node.memberLocation()))),
make_pair("expression", toJson(_node.expression())), make_pair("expression", toJson(_node.expression())),
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
}; };
@ -909,7 +910,7 @@ bool ASTJsonExporter::visit(MemberAccess const& _node)
bool ASTJsonExporter::visit(IndexAccess const& _node) bool ASTJsonExporter::visit(IndexAccess const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("baseExpression", toJson(_node.baseExpression())), make_pair("baseExpression", toJson(_node.baseExpression())),
make_pair("indexExpression", toJsonOrNull(_node.indexExpression())), make_pair("indexExpression", toJsonOrNull(_node.indexExpression())),
}; };
@ -920,7 +921,7 @@ bool ASTJsonExporter::visit(IndexAccess const& _node)
bool ASTJsonExporter::visit(IndexRangeAccess const& _node) bool ASTJsonExporter::visit(IndexRangeAccess const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("baseExpression", toJson(_node.baseExpression())), make_pair("baseExpression", toJson(_node.baseExpression())),
make_pair("startExpression", toJsonOrNull(_node.startExpression())), make_pair("startExpression", toJsonOrNull(_node.startExpression())),
make_pair("endExpression", toJsonOrNull(_node.endExpression())), make_pair("endExpression", toJsonOrNull(_node.endExpression())),
@ -932,9 +933,9 @@ bool ASTJsonExporter::visit(IndexRangeAccess const& _node)
bool ASTJsonExporter::visit(Identifier const& _node) bool ASTJsonExporter::visit(Identifier const& _node)
{ {
Json::Value overloads(Json::arrayValue); Json overloads(Json::array());
for (auto const& dec: _node.annotation().overloadedDeclarations) for (auto const& dec: _node.annotation().overloadedDeclarations)
overloads.append(nodeId(*dec)); overloads.emplace_back(nodeId(*dec));
setJsonNode(_node, "Identifier", { setJsonNode(_node, "Identifier", {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
@ -947,7 +948,7 @@ bool ASTJsonExporter::visit(Identifier const& _node)
bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node) bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node)
{ {
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("typeName", toJson(_node.type())) make_pair("typeName", toJson(_node.type()))
}; };
appendExpressionAttributes(attributes, _node.annotation()); appendExpressionAttributes(attributes, _node.annotation());
@ -957,19 +958,19 @@ bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node)
bool ASTJsonExporter::visit(Literal const& _node) bool ASTJsonExporter::visit(Literal const& _node)
{ {
Json::Value value{_node.value()}; Json value{_node.value()};
if (!util::validateUTF8(_node.value())) if (!util::validateUTF8(_node.value()))
value = Json::nullValue; value = Json{};
Token subdenomination = Token(_node.subDenomination()); Token subdenomination = Token(_node.subDenomination());
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("kind", literalTokenKind(_node.token())), make_pair("kind", literalTokenKind(_node.token())),
make_pair("value", value), make_pair("value", value),
make_pair("hexValue", util::toHex(util::asBytes(_node.value()))), make_pair("hexValue", util::toHex(util::asBytes(_node.value()))),
make_pair( make_pair(
"subdenomination", "subdenomination",
subdenomination == Token::Illegal ? subdenomination == Token::Illegal ?
Json::nullValue : Json{} :
Json::Value{TokenTraits::toString(subdenomination)} Json{TokenTraits::toString(subdenomination)}
) )
}; };
appendExpressionAttributes(attributes, _node.annotation()); appendExpressionAttributes(attributes, _node.annotation());
@ -979,8 +980,8 @@ bool ASTJsonExporter::visit(Literal const& _node)
bool ASTJsonExporter::visit(StructuredDocumentation const& _node) bool ASTJsonExporter::visit(StructuredDocumentation const& _node)
{ {
Json::Value text{*_node.text()}; Json text{*_node.text()};
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json>> attributes = {
make_pair("text", text) make_pair("text", text)
}; };
setJsonNode(_node, "StructuredDocumentation", std::move(attributes)); setJsonNode(_node, "StructuredDocumentation", std::move(attributes));

View File

@ -26,10 +26,8 @@
#include <libsolidity/ast/ASTAnnotations.h> #include <libsolidity/ast/ASTAnnotations.h>
#include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/CompilerStack.h>
#include <liblangutil/Exceptions.h>
#include <json/json.h>
#include <libsolutil/JSON.h> #include <libsolutil/JSON.h>
#include <liblangutil/Exceptions.h>
#include <algorithm> #include <algorithm>
#include <optional> #include <optional>
@ -60,16 +58,16 @@ public:
); );
/// Output the json representation of the AST to _stream. /// Output the json representation of the AST to _stream.
void print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format); void print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format);
Json::Value toJson(ASTNode const& _node); Json toJson(ASTNode const& _node);
template <class T> template <class T>
Json::Value toJson(std::vector<ASTPointer<T>> const& _nodes) Json toJson(std::vector<ASTPointer<T>> const& _nodes)
{ {
Json::Value ret(Json::arrayValue); Json ret{Json::array()};
for (auto const& n: _nodes) for (auto const& n: _nodes)
if (n) if (n)
appendMove(ret, toJson(*n)); appendMove(ret, toJson(*n));
else else
ret.append(Json::nullValue); ret.emplace_back(Json{});
return ret; return ret;
} }
bool visit(SourceUnit const& _node) override; bool visit(SourceUnit const& _node) override;
@ -134,27 +132,27 @@ private:
void setJsonNode( void setJsonNode(
ASTNode const& _node, ASTNode const& _node,
std::string const& _nodeName, std::string const& _nodeName,
std::initializer_list<std::pair<std::string, Json::Value>>&& _attributes std::initializer_list<std::pair<std::string, Json>>&& _attributes
); );
void setJsonNode( void setJsonNode(
ASTNode const& _node, ASTNode const& _node,
std::string const& _nodeName, std::string const& _nodeName,
std::vector<std::pair<std::string, Json::Value>>&& _attributes std::vector<std::pair<std::string, Json>>&& _attributes
); );
/// Maps source location to an index, if source is valid and a mapping does exist, otherwise returns std::nullopt. /// Maps source location to an index, if source is valid and a mapping does exist, otherwise returns std::nullopt.
std::optional<size_t> sourceIndexFromLocation(langutil::SourceLocation const& _location) const; std::optional<size_t> sourceIndexFromLocation(langutil::SourceLocation const& _location) const;
std::string sourceLocationToString(langutil::SourceLocation const& _location) const; std::string sourceLocationToString(langutil::SourceLocation const& _location) const;
Json::Value sourceLocationsToJson(std::vector<langutil::SourceLocation> const& _sourceLocations) const; Json sourceLocationsToJson(std::vector<langutil::SourceLocation> const& _sourceLocations) const;
static std::string namePathToString(std::vector<ASTString> const& _namePath); static std::string namePathToString(std::vector<ASTString> 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<yul::Identifier const* , InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const; Json inlineAssemblyIdentifierToJson(std::pair<yul::Identifier const* , InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const;
static std::string location(VariableDeclaration::Location _location); static std::string location(VariableDeclaration::Location _location);
static std::string contractKind(ContractKind _kind); static std::string contractKind(ContractKind _kind);
static std::string functionCallKind(FunctionCallKind _kind); static std::string functionCallKind(FunctionCallKind _kind);
@ -166,7 +164,7 @@ private:
return _node.id(); return _node.id();
} }
template<class Container> template<class Container>
static Json::Value getContainerIds(Container const& _container, bool _order = false) static Json getContainerIds(Container const& _container, bool _order = false)
{ {
std::vector<int64_t> tmp; std::vector<int64_t> tmp;
@ -177,28 +175,27 @@ private:
} }
if (_order) if (_order)
std::sort(tmp.begin(), tmp.end()); std::sort(tmp.begin(), tmp.end());
Json::Value json(Json::arrayValue);
Json json{Json::array()};
for (int64_t val: tmp) for (int64_t val: tmp)
json.append(val); json.emplace_back(val);
return json; return json;
} }
static Json::Value typePointerToJson(Type const* _tp, bool _withoutDataLocation = false); static Json typePointerToJson(Type const* _tp, bool _withoutDataLocation = false);
static Json::Value typePointerToJson(std::optional<FuncCallArguments> const& _tps); static Json typePointerToJson(std::optional<FuncCallArguments> const& _tps);
void appendExpressionAttributes( void appendExpressionAttributes(
std::vector<std::pair<std::string, Json::Value>> &_attributes, std::vector<std::pair<std::string, Json>> &_attributes,
ExpressionAnnotation const& _annotation ExpressionAnnotation const& _annotation
); );
static void appendMove(Json::Value& _array, Json::Value&& _value) static void appendMove(Json& _array, Json&& _value)
{ {
solAssert(_array.isArray(), ""); solAssert(_array.is_array(), "");
_array.append(std::move(_value)); _array.emplace_back(std::move(_value));
} }
CompilerStack::State m_stackState = CompilerStack::State::Empty; ///< Used to only access information that already exists 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 bool m_inEvent = false; ///< whether we are currently inside an event or not
Json::Value m_currentValue; Json m_currentValue;
std::map<std::string, unsigned> m_sourceIndices; std::map<std::string, unsigned> m_sourceIndices;
}; };

View File

@ -44,9 +44,9 @@ namespace solidity::frontend
using SourceLocation = langutil::SourceLocation; using SourceLocation = langutil::SourceLocation;
template<class T> template<class T>
ASTPointer<T> ASTJsonImporter::nullOrCast(Json::Value const& _json) ASTPointer<T> ASTJsonImporter::nullOrCast(Json const& _json)
{ {
if (_json.isNull()) if (_json.is_null())
return nullptr; return nullptr;
else else
return dynamic_pointer_cast<T>(convertJsonToASTNode(_json)); return dynamic_pointer_cast<T>(convertJsonToASTNode(_json));
@ -55,13 +55,13 @@ ASTPointer<T> ASTJsonImporter::nullOrCast(Json::Value const& _json)
// ============ public =========================== // ============ public ===========================
map<string, ASTPointer<SourceUnit>> ASTJsonImporter::jsonToSourceUnit(map<string, Json::Value> const& _sourceList) map<string, ASTPointer<SourceUnit>> ASTJsonImporter::jsonToSourceUnit(map<string, Json> const& _sourceList)
{ {
for (auto const& src: _sourceList) for (auto const& src: _sourceList)
m_sourceNames.emplace_back(make_shared<string const>(src.first)); m_sourceNames.emplace_back(make_shared<string const>(src.first));
for (auto const& srcPair: _sourceList) 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'."); astAssert(member(srcPair.second,"nodeType") == "SourceUnit", "The 'nodeType' of the highest node must be 'SourceUnit'.");
m_sourceUnits[srcPair.first] = createSourceUnit(srcPair.second, srcPair.first); m_sourceUnits[srcPair.first] = createSourceUnit(srcPair.second, srcPair.first);
} }
@ -72,11 +72,11 @@ map<string, ASTPointer<SourceUnit>> ASTJsonImporter::jsonToSourceUnit(map<string
// =========== general creation functions ============== // =========== general creation functions ==============
template <typename T, typename... Args> template <typename T, typename... Args>
ASTPointer<T> ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&... _args) ASTPointer<T> ASTJsonImporter::createASTNode(Json const& _node, Args&&... _args)
{ {
astAssert(member(_node, "id").isInt64(), "'id'-field must be 64bit integer."); astAssert(member(_node, "id").is_number_integer(), "'id'-field must be 64bit integer.");
int64_t id = _node["id"].asInt64(); int64_t id = static_cast<Json::number_integer_t>(_node["id"]);
astAssert(m_usedIDs.insert(id).second, "Found duplicate node ID!"); astAssert(m_usedIDs.insert(id).second, "Found duplicate node ID!");
@ -88,36 +88,36 @@ ASTPointer<T> ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&...
return n; 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<string>(), m_sourceNames);
} }
optional<vector<SourceLocation>> ASTJsonImporter::createSourceLocations(Json::Value const& _node) const optional<vector<SourceLocation>> ASTJsonImporter::createSourceLocations(Json const& _node) const
{ {
vector<SourceLocation> locations; vector<SourceLocation> locations;
if (_node.isMember("nameLocations") && _node["nameLocations"].isArray()) if (_node.contains("nameLocations") && _node["nameLocations"].is_array())
{ {
for (auto const& val: _node["nameLocations"]) for (auto const& val: _node["nameLocations"])
locations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames)); locations.emplace_back(langutil::parseSourceLocation(val.get<string>(), m_sourceNames));
return locations; return locations;
} }
return nullopt; return 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<string>(), m_sourceNames);
} }
template<class T> template<class T>
ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node) ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json const& _node)
{ {
ASTPointer<T> ret = dynamic_pointer_cast<T>(convertJsonToASTNode(_node)); ASTPointer<T> ret = dynamic_pointer_cast<T>(convertJsonToASTNode(_node));
astAssert(ret, "cast of converted json-node must not be nullptr"); astAssert(ret, "cast of converted json-node must not be nullptr");
@ -125,10 +125,10 @@ ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node)
} }
ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _json) ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json const& _json)
{ {
astAssert(_json["nodeType"].isString() && _json.isMember("id"), "JSON-Node needs to have 'nodeType' and 'id' fields."); astAssert(_json["nodeType"].is_string() && _json.contains("id"), "JSON-Node needs to have 'nodeType' and 'id' fields.");
string nodeType = _json["nodeType"].asString(); string nodeType = _json["nodeType"].get<string>();
if (nodeType == "PragmaDirective") if (nodeType == "PragmaDirective")
return createPragmaDirective(_json); return createPragmaDirective(_json);
if (nodeType == "ImportDirective") if (nodeType == "ImportDirective")
@ -250,11 +250,11 @@ ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js
// ============ functions to instantiate the AST-Nodes from Json-Nodes ============== // ============ functions to instantiate the AST-Nodes from Json-Nodes ==============
ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _node, string const& _srcName) ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json const& _node, string const& _srcName)
{ {
optional<string> license; optional<string> license;
if (_node.isMember("license") && !_node["license"].isNull()) if (_node.contains("license") && !_node["license"].is_null())
license = _node["license"].asString(); license = _node["license"].get<string>();
vector<ASTPointer<ASTNode>> nodes; vector<ASTPointer<ASTNode>> nodes;
for (auto& child: member(_node, "nodes")) for (auto& child: member(_node, "nodes"))
@ -265,20 +265,20 @@ ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _nod
return tmp; return tmp;
} }
ASTPointer<PragmaDirective> ASTJsonImporter::createPragmaDirective(Json::Value const& _node) ASTPointer<PragmaDirective> ASTJsonImporter::createPragmaDirective(Json const& _node)
{ {
vector<Token> tokens; vector<Token> tokens;
vector<ASTString> literals; vector<ASTString> literals;
for (auto const& lit: member(_node, "literals")) for (auto const& lit: member(_node, "literals"))
{ {
string l = lit.asString(); string l = lit.get<string>();
literals.push_back(l); literals.push_back(l);
tokens.push_back(scanSingleToken(l)); tokens.push_back(scanSingleToken(l));
} }
return createASTNode<PragmaDirective>(_node, tokens, literals); return createASTNode<PragmaDirective>(_node, tokens, literals);
} }
ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json::Value const& _node) ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json const& _node)
{ {
ASTPointer<ASTString> unitAlias = memberAsASTString(_node, "unitAlias"); ASTPointer<ASTString> unitAlias = memberAsASTString(_node, "unitAlias");
ASTPointer<ASTString> path = memberAsASTString(_node, "file"); ASTPointer<ASTString> path = memberAsASTString(_node, "file");
@ -286,11 +286,11 @@ ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json::Value c
for (auto& tuple: member(_node, "symbolAliases")) 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({ symbolAliases.push_back({
createIdentifier(tuple["foreign"]), createIdentifier(tuple["foreign"]),
tuple["local"].isNull() ? nullptr : make_shared<ASTString>(tuple["local"].asString()), tuple["local"].is_null() ? nullptr : make_shared<ASTString>(tuple["local"].get<string>()),
createSourceLocation(tuple["foreign"])} createSourceLocation(tuple["foreign"])}
); );
} }
@ -302,15 +302,15 @@ ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json::Value c
std::move(symbolAliases) 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<string>();
return tmp; return tmp;
} }
ASTPointer<ContractDefinition> ASTJsonImporter::createContractDefinition(Json::Value const& _node) ASTPointer<ContractDefinition> 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<ASTPointer<InheritanceSpecifier>> baseContracts; std::vector<ASTPointer<InheritanceSpecifier>> baseContracts;
@ -324,9 +324,9 @@ ASTPointer<ContractDefinition> ASTJsonImporter::createContractDefinition(Json::V
return createASTNode<ContractDefinition>( return createASTNode<ContractDefinition>(
_node, _node,
make_shared<ASTString>(_node["name"].asString()), make_shared<ASTString>(_node["name"].get<string>()),
createNameSourceLocation(_node), createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), _node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
baseContracts, baseContracts,
subNodes, subNodes,
contractKind(_node), contractKind(_node),
@ -334,14 +334,14 @@ ASTPointer<ContractDefinition> ASTJsonImporter::createContractDefinition(Json::V
); );
} }
ASTPointer<IdentifierPath> ASTJsonImporter::createIdentifierPath(Json::Value const& _node) ASTPointer<IdentifierPath> 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!");
vector<ASTString> namePath; vector<ASTString> namePath;
vector<SourceLocation> namePathLocations; vector<SourceLocation> namePathLocations;
vector<string> strs; vector<string> strs;
string nameString = member(_node, "name").asString(); string nameString = member(_node, "name").get<string>();
boost::algorithm::split(strs, nameString, boost::is_any_of(".")); boost::algorithm::split(strs, nameString, boost::is_any_of("."));
astAssert(!strs.empty(), "Expected at least one element in IdentifierPath."); astAssert(!strs.empty(), "Expected at least one element in IdentifierPath.");
for (string s: strs) for (string s: strs)
@ -350,9 +350,9 @@ ASTPointer<IdentifierPath> ASTJsonImporter::createIdentifierPath(Json::Value con
namePath.emplace_back(s); 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"]) for (auto const& val: _node["nameLocations"])
namePathLocations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames)); namePathLocations.emplace_back(langutil::parseSourceLocation(val.get<string>(), m_sourceNames));
else else
namePathLocations.resize(namePath.size()); namePathLocations.resize(namePath.size());
@ -368,7 +368,7 @@ ASTPointer<IdentifierPath> ASTJsonImporter::createIdentifierPath(Json::Value con
); );
} }
ASTPointer<InheritanceSpecifier> ASTJsonImporter::createInheritanceSpecifier(Json::Value const& _node) ASTPointer<InheritanceSpecifier> ASTJsonImporter::createInheritanceSpecifier(Json const& _node)
{ {
std::vector<ASTPointer<Expression>> arguments; std::vector<ASTPointer<Expression>> arguments;
for (auto& arg: member(_node, "arguments")) for (auto& arg: member(_node, "arguments"))
@ -376,29 +376,29 @@ ASTPointer<InheritanceSpecifier> ASTJsonImporter::createInheritanceSpecifier(Jso
return createASTNode<InheritanceSpecifier>( return createASTNode<InheritanceSpecifier>(
_node, _node,
createIdentifierPath(member(_node, "baseName")), createIdentifierPath(member(_node, "baseName")),
member(_node, "arguments").isNull() ? nullptr : make_unique<std::vector<ASTPointer<Expression>>>(arguments) member(_node, "arguments").is_null() ? nullptr : make_unique<std::vector<ASTPointer<Expression>>>(arguments)
); );
} }
ASTPointer<UsingForDirective> ASTJsonImporter::createUsingForDirective(Json::Value const& _node) ASTPointer<UsingForDirective> ASTJsonImporter::createUsingForDirective(Json const& _node)
{ {
vector<ASTPointer<IdentifierPath>> functions; vector<ASTPointer<IdentifierPath>> functions;
if (_node.isMember("libraryName")) if (_node.contains("libraryName"))
functions.emplace_back(createIdentifierPath(_node["libraryName"])); functions.emplace_back(createIdentifierPath(_node["libraryName"]));
else if (_node.isMember("functionList")) else if (_node.contains("functionList"))
for (Json::Value const& function: _node["functionList"]) for (Json const& function: _node["functionList"])
functions.emplace_back(createIdentifierPath(function["function"])); functions.emplace_back(createIdentifierPath(function["function"]));
return createASTNode<UsingForDirective>( return createASTNode<UsingForDirective>(
_node, _node,
std::move(functions), std::move(functions),
!_node.isMember("libraryName"), !_node.contains("libraryName"),
_node["typeName"].isNull() ? nullptr : convertJsonToASTNode<TypeName>(_node["typeName"]), _node["typeName"].is_null() ? nullptr : convertJsonToASTNode<TypeName>(_node["typeName"]),
memberAsBool(_node, "global") memberAsBool(_node, "global")
); );
} }
ASTPointer<ASTNode> ASTJsonImporter::createStructDefinition(Json::Value const& _node) ASTPointer<ASTNode> ASTJsonImporter::createStructDefinition(Json const& _node)
{ {
std::vector<ASTPointer<VariableDeclaration>> members; std::vector<ASTPointer<VariableDeclaration>> members;
for (auto& member: _node["members"]) for (auto& member: _node["members"])
@ -411,7 +411,7 @@ ASTPointer<ASTNode> ASTJsonImporter::createStructDefinition(Json::Value const& _
); );
} }
ASTPointer<EnumDefinition> ASTJsonImporter::createEnumDefinition(Json::Value const& _node) ASTPointer<EnumDefinition> ASTJsonImporter::createEnumDefinition(Json const& _node)
{ {
std::vector<ASTPointer<EnumValue>> members; std::vector<ASTPointer<EnumValue>> members;
for (auto& member: _node["members"]) for (auto& member: _node["members"])
@ -424,7 +424,7 @@ ASTPointer<EnumDefinition> ASTJsonImporter::createEnumDefinition(Json::Value con
); );
} }
ASTPointer<EnumValue> ASTJsonImporter::createEnumValue(Json::Value const& _node) ASTPointer<EnumValue> ASTJsonImporter::createEnumValue(Json const& _node)
{ {
return createASTNode<EnumValue>( return createASTNode<EnumValue>(
_node, _node,
@ -432,7 +432,7 @@ ASTPointer<EnumValue> ASTJsonImporter::createEnumValue(Json::Value const& _node)
); );
} }
ASTPointer<UserDefinedValueTypeDefinition> ASTJsonImporter::createUserDefinedValueTypeDefinition(Json::Value const& _node) ASTPointer<UserDefinedValueTypeDefinition> ASTJsonImporter::createUserDefinedValueTypeDefinition(Json const& _node)
{ {
return createASTNode<UserDefinedValueTypeDefinition>( return createASTNode<UserDefinedValueTypeDefinition>(
_node, _node,
@ -442,7 +442,7 @@ ASTPointer<UserDefinedValueTypeDefinition> ASTJsonImporter::createUserDefinedVal
); );
} }
ASTPointer<ParameterList> ASTJsonImporter::createParameterList(Json::Value const& _node) ASTPointer<ParameterList> ASTJsonImporter::createParameterList(Json const& _node)
{ {
std::vector<ASTPointer<VariableDeclaration>> parameters; std::vector<ASTPointer<VariableDeclaration>> parameters;
for (auto& param: _node["parameters"]) for (auto& param: _node["parameters"])
@ -453,7 +453,7 @@ ASTPointer<ParameterList> ASTJsonImporter::createParameterList(Json::Value const
); );
} }
ASTPointer<OverrideSpecifier> ASTJsonImporter::createOverrideSpecifier(Json::Value const& _node) ASTPointer<OverrideSpecifier> ASTJsonImporter::createOverrideSpecifier(Json const& _node)
{ {
std::vector<ASTPointer<IdentifierPath>> overrides; std::vector<ASTPointer<IdentifierPath>> overrides;
@ -466,13 +466,13 @@ ASTPointer<OverrideSpecifier> ASTJsonImporter::createOverrideSpecifier(Json::Val
); );
} }
ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::Value const& _node) ASTPointer<FunctionDefinition> 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; Token kind;
bool freeFunction = false; bool freeFunction = false;
string kindStr = member(_node, "kind").asString(); string kindStr = member(_node, "kind").get<string>();
if (kindStr == "constructor") if (kindStr == "constructor")
kind = Token::Constructor; kind = Token::Constructor;
@ -509,8 +509,8 @@ ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::V
freeFunction, freeFunction,
kind, kind,
memberAsBool(_node, "virtual"), memberAsBool(_node, "virtual"),
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), _node["overrides"].is_null() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), _node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters")), createParameterList(member(_node, "parameters")),
modifiers, modifiers,
createParameterList(member(_node, "returnParameters")), createParameterList(member(_node, "returnParameters")),
@ -518,13 +518,13 @@ ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::V
); );
} }
ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json::Value const& _node) ASTPointer<VariableDeclaration> 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{}; VariableDeclaration::Mutability mutability{};
astAssert(member(_node, "mutability").isString(), "'mutability' expected to be string."); astAssert(member(_node, "mutability").is_string(), "'mutability' expected to be string.");
string const mutabilityStr = member(_node, "mutability").asString(); string const mutabilityStr = member(_node, "mutability").get<string>();
if (mutabilityStr == "constant") if (mutabilityStr == "constant")
{ {
mutability = VariableDeclaration::Mutability::Constant; mutability = VariableDeclaration::Mutability::Constant;
@ -544,33 +544,33 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
return createASTNode<VariableDeclaration>( return createASTNode<VariableDeclaration>(
_node, _node,
nullOrCast<TypeName>(member(_node, "typeName")), nullOrCast<TypeName>(member(_node, "typeName")),
make_shared<ASTString>(member(_node, "name").asString()), make_shared<ASTString>(member(_node, "name").get<string>()),
createNameSourceLocation(_node), createNameSourceLocation(_node),
nullOrCast<Expression>(member(_node, "value")), nullOrCast<Expression>(member(_node, "value")),
visibility(_node), visibility(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), _node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
_node.isMember("indexed") ? memberAsBool(_node, "indexed") : false, _node.contains("indexed") ? memberAsBool(_node, "indexed") : false,
mutability, mutability,
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), _node["overrides"].is_null() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
location(_node) location(_node)
); );
} }
ASTPointer<ModifierDefinition> ASTJsonImporter::createModifierDefinition(Json::Value const& _node) ASTPointer<ModifierDefinition> ASTJsonImporter::createModifierDefinition(Json const& _node)
{ {
return createASTNode<ModifierDefinition>( return createASTNode<ModifierDefinition>(
_node, _node,
memberAsASTString(_node, "name"), memberAsASTString(_node, "name"),
createNameSourceLocation(_node), createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), _node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters")), createParameterList(member(_node, "parameters")),
memberAsBool(_node, "virtual"), memberAsBool(_node, "virtual"),
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), _node["overrides"].is_null() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
_node["body"].isNull() ? nullptr: createBlock(member(_node, "body"), false) _node["body"].is_null() ? nullptr: createBlock(member(_node, "body"), false)
); );
} }
ASTPointer<ModifierInvocation> ASTJsonImporter::createModifierInvocation(Json::Value const& _node) ASTPointer<ModifierInvocation> ASTJsonImporter::createModifierInvocation(Json const& _node)
{ {
std::vector<ASTPointer<Expression>> arguments; std::vector<ASTPointer<Expression>> arguments;
for (auto& arg: member(_node, "arguments")) for (auto& arg: member(_node, "arguments"))
@ -578,53 +578,53 @@ ASTPointer<ModifierInvocation> ASTJsonImporter::createModifierInvocation(Json::V
return createASTNode<ModifierInvocation>( return createASTNode<ModifierInvocation>(
_node, _node,
createIdentifierPath(member(_node, "modifierName")), createIdentifierPath(member(_node, "modifierName")),
member(_node, "arguments").isNull() ? nullptr : make_unique<std::vector<ASTPointer<Expression>>>(arguments) member(_node, "arguments").is_null() ? nullptr : make_unique<std::vector<ASTPointer<Expression>>>(arguments)
); );
} }
ASTPointer<EventDefinition> ASTJsonImporter::createEventDefinition(Json::Value const& _node) ASTPointer<EventDefinition> ASTJsonImporter::createEventDefinition(Json const& _node)
{ {
return createASTNode<EventDefinition>( return createASTNode<EventDefinition>(
_node, _node,
memberAsASTString(_node, "name"), memberAsASTString(_node, "name"),
createNameSourceLocation(_node), createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), _node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters")), createParameterList(member(_node, "parameters")),
memberAsBool(_node, "anonymous") memberAsBool(_node, "anonymous")
); );
} }
ASTPointer<ErrorDefinition> ASTJsonImporter::createErrorDefinition(Json::Value const& _node) ASTPointer<ErrorDefinition> ASTJsonImporter::createErrorDefinition(Json const& _node)
{ {
return createASTNode<ErrorDefinition>( return createASTNode<ErrorDefinition>(
_node, _node,
memberAsASTString(_node, "name"), memberAsASTString(_node, "name"),
createNameSourceLocation(_node), createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), _node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters")) createParameterList(member(_node, "parameters"))
); );
} }
ASTPointer<ElementaryTypeName> ASTJsonImporter::createElementaryTypeName(Json::Value const& _node) ASTPointer<ElementaryTypeName> ASTJsonImporter::createElementaryTypeName(Json const& _node)
{ {
unsigned short firstNum; unsigned short firstNum;
unsigned short secondNum; unsigned short secondNum;
astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); astAssert(_node["name"].is_string(), "Expected 'name' to be a string!");
string name = member(_node, "name").asString(); string name = member(_node, "name").get<string>();
Token token; Token token;
tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name); tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name);
ElementaryTypeNameToken elem(token, firstNum, secondNum); ElementaryTypeNameToken elem(token, firstNum, secondNum);
std::optional<StateMutability> mutability = {}; std::optional<StateMutability> mutability = {};
if (_node.isMember("stateMutability")) if (_node.contains("stateMutability"))
mutability = stateMutability(_node); mutability = stateMutability(_node);
return createASTNode<ElementaryTypeName>(_node, elem, mutability); return createASTNode<ElementaryTypeName>(_node, elem, mutability);
} }
ASTPointer<UserDefinedTypeName> ASTJsonImporter::createUserDefinedTypeName(Json::Value const& _node) ASTPointer<UserDefinedTypeName> ASTJsonImporter::createUserDefinedTypeName(Json const& _node)
{ {
return createASTNode<UserDefinedTypeName>( return createASTNode<UserDefinedTypeName>(
_node, _node,
@ -632,7 +632,7 @@ ASTPointer<UserDefinedTypeName> ASTJsonImporter::createUserDefinedTypeName(Json:
); );
} }
ASTPointer<FunctionTypeName> ASTJsonImporter::createFunctionTypeName(Json::Value const& _node) ASTPointer<FunctionTypeName> ASTJsonImporter::createFunctionTypeName(Json const& _node)
{ {
return createASTNode<FunctionTypeName>( return createASTNode<FunctionTypeName>(
_node, _node,
@ -643,7 +643,7 @@ ASTPointer<FunctionTypeName> ASTJsonImporter::createFunctionTypeName(Json::Value
); );
} }
ASTPointer<Mapping> ASTJsonImporter::createMapping(Json::Value const& _node) ASTPointer<Mapping> ASTJsonImporter::createMapping(Json const& _node)
{ {
return createASTNode<Mapping>( return createASTNode<Mapping>(
_node, _node,
@ -652,7 +652,7 @@ ASTPointer<Mapping> ASTJsonImporter::createMapping(Json::Value const& _node)
); );
} }
ASTPointer<ArrayTypeName> ASTJsonImporter::createArrayTypeName(Json::Value const& _node) ASTPointer<ArrayTypeName> ASTJsonImporter::createArrayTypeName(Json const& _node)
{ {
return createASTNode<ArrayTypeName>( return createASTNode<ArrayTypeName>(
_node, _node,
@ -661,24 +661,24 @@ ASTPointer<ArrayTypeName> ASTJsonImporter::createArrayTypeName(Json::Value const
); );
} }
ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json::Value const& _node) ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json const& _node)
{ {
astAssert(_node["evmVersion"].isString(), "Expected evmVersion to be a string!"); astAssert(_node["evmVersion"].is_string(), "Expected evmVersion to be a string!");
auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].asString()); auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].get<string>());
astAssert(evmVersion.has_value(), "Invalid EVM version!"); astAssert(evmVersion.has_value(), "Invalid EVM version!");
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!"); astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value()); yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
ASTPointer<vector<ASTPointer<ASTString>>> flags; ASTPointer<vector<ASTPointer<ASTString>>> flags;
if (_node.isMember("flags")) if (_node.contains("flags"))
{ {
flags = make_shared<vector<ASTPointer<ASTString>>>(); flags = make_shared<vector<ASTPointer<ASTString>>>();
Json::Value const& flagsNode = _node["flags"]; Json const& flagsNode = _node["flags"];
astAssert(flagsNode.isArray(), "Assembly flags must be an array."); astAssert(flagsNode.is_array(), "Assembly flags must be an array.");
for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i) for (Json const& flag: flagsNode)
{ {
astAssert(flagsNode[i].isString(), "Assembly flag must be a string."); astAssert(flag.is_string(), "Assembly flag must be a string.");
flags->emplace_back(make_shared<ASTString>(flagsNode[i].asString())); flags->emplace_back(make_shared<ASTString>(flag.get<string>()));
} }
} }
shared_ptr<yul::Block> operations = make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST"))); shared_ptr<yul::Block> operations = make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST")));
@ -691,7 +691,7 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json::Value con
); );
} }
ASTPointer<Block> ASTJsonImporter::createBlock(Json::Value const& _node, bool _unchecked) ASTPointer<Block> ASTJsonImporter::createBlock(Json const& _node, bool _unchecked)
{ {
std::vector<ASTPointer<Statement>> statements; std::vector<ASTPointer<Statement>> statements;
for (auto& stat: member(_node, "statements")) for (auto& stat: member(_node, "statements"))
@ -704,7 +704,7 @@ ASTPointer<Block> ASTJsonImporter::createBlock(Json::Value const& _node, bool _u
); );
} }
ASTPointer<PlaceholderStatement> ASTJsonImporter::createPlaceholderStatement(Json::Value const& _node) ASTPointer<PlaceholderStatement> ASTJsonImporter::createPlaceholderStatement(Json const& _node)
{ {
return createASTNode<PlaceholderStatement>( return createASTNode<PlaceholderStatement>(
_node, _node,
@ -712,7 +712,7 @@ ASTPointer<PlaceholderStatement> ASTJsonImporter::createPlaceholderStatement(Jso
); );
} }
ASTPointer<IfStatement> ASTJsonImporter::createIfStatement(Json::Value const& _node) ASTPointer<IfStatement> ASTJsonImporter::createIfStatement(Json const& _node)
{ {
return createASTNode<IfStatement>( return createASTNode<IfStatement>(
_node, _node,
@ -723,7 +723,7 @@ ASTPointer<IfStatement> ASTJsonImporter::createIfStatement(Json::Value const& _
); );
} }
ASTPointer<TryCatchClause> ASTJsonImporter::createTryCatchClause(Json::Value const& _node) ASTPointer<TryCatchClause> ASTJsonImporter::createTryCatchClause(Json const& _node)
{ {
return createASTNode<TryCatchClause>( return createASTNode<TryCatchClause>(
_node, _node,
@ -733,7 +733,7 @@ ASTPointer<TryCatchClause> ASTJsonImporter::createTryCatchClause(Json::Value con
); );
} }
ASTPointer<TryStatement> ASTJsonImporter::createTryStatement(Json::Value const& _node) ASTPointer<TryStatement> ASTJsonImporter::createTryStatement(Json const& _node)
{ {
vector<ASTPointer<TryCatchClause>> clauses; vector<ASTPointer<TryCatchClause>> clauses;
@ -748,7 +748,7 @@ ASTPointer<TryStatement> ASTJsonImporter::createTryStatement(Json::Value const&
); );
} }
ASTPointer<WhileStatement> ASTJsonImporter::createWhileStatement(Json::Value const& _node, bool _isDoWhile=false) ASTPointer<WhileStatement> ASTJsonImporter::createWhileStatement(Json const& _node, bool _isDoWhile=false)
{ {
return createASTNode<WhileStatement>( return createASTNode<WhileStatement>(
_node, _node,
@ -759,7 +759,7 @@ ASTPointer<WhileStatement> ASTJsonImporter::createWhileStatement(Json::Value con
); );
} }
ASTPointer<ForStatement> ASTJsonImporter::createForStatement(Json::Value const& _node) ASTPointer<ForStatement> ASTJsonImporter::createForStatement(Json const& _node)
{ {
return createASTNode<ForStatement>( return createASTNode<ForStatement>(
_node, _node,
@ -771,7 +771,7 @@ ASTPointer<ForStatement> ASTJsonImporter::createForStatement(Json::Value const&
); );
} }
ASTPointer<Continue> ASTJsonImporter::createContinue(Json::Value const& _node) ASTPointer<Continue> ASTJsonImporter::createContinue(Json const& _node)
{ {
return createASTNode<Continue>( return createASTNode<Continue>(
_node, _node,
@ -779,7 +779,7 @@ ASTPointer<Continue> ASTJsonImporter::createContinue(Json::Value const& _node)
); );
} }
ASTPointer<Break> ASTJsonImporter::createBreak(Json::Value const& _node) ASTPointer<Break> ASTJsonImporter::createBreak(Json const& _node)
{ {
return createASTNode<Break>( return createASTNode<Break>(
_node, _node,
@ -787,7 +787,7 @@ ASTPointer<Break> ASTJsonImporter::createBreak(Json::Value const& _node)
); );
} }
ASTPointer<Return> ASTJsonImporter::createReturn(Json::Value const& _node) ASTPointer<Return> ASTJsonImporter::createReturn(Json const& _node)
{ {
return createASTNode<Return>( return createASTNode<Return>(
_node, _node,
@ -796,7 +796,7 @@ ASTPointer<Return> ASTJsonImporter::createReturn(Json::Value const& _node)
); );
} }
ASTPointer<Throw> ASTJsonImporter::createThrow(Json::Value const& _node) ASTPointer<Throw> ASTJsonImporter::createThrow(Json const& _node)
{ {
return createASTNode<Throw>( return createASTNode<Throw>(
_node, _node,
@ -804,7 +804,7 @@ ASTPointer<Throw> ASTJsonImporter::createThrow(Json::Value const& _node)
); );
} }
ASTPointer<EmitStatement> ASTJsonImporter::createEmitStatement(Json::Value const& _node) ASTPointer<EmitStatement> ASTJsonImporter::createEmitStatement(Json const& _node)
{ {
return createASTNode<EmitStatement>( return createASTNode<EmitStatement>(
_node, _node,
@ -813,7 +813,7 @@ ASTPointer<EmitStatement> ASTJsonImporter::createEmitStatement(Json::Value const
); );
} }
ASTPointer<RevertStatement> ASTJsonImporter::createRevertStatement(Json::Value const& _node) ASTPointer<RevertStatement> ASTJsonImporter::createRevertStatement(Json const& _node)
{ {
return createASTNode<RevertStatement>( return createASTNode<RevertStatement>(
_node, _node,
@ -822,11 +822,11 @@ ASTPointer<RevertStatement> ASTJsonImporter::createRevertStatement(Json::Value c
); );
} }
ASTPointer<VariableDeclarationStatement> ASTJsonImporter::createVariableDeclarationStatement(Json::Value const& _node) ASTPointer<VariableDeclarationStatement> ASTJsonImporter::createVariableDeclarationStatement(Json const& _node)
{ {
std::vector<ASTPointer<VariableDeclaration>> variables; std::vector<ASTPointer<VariableDeclaration>> variables;
for (auto& var: member(_node, "declarations")) 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<VariableDeclarationStatement>( return createASTNode<VariableDeclarationStatement>(
_node, _node,
nullOrASTString(_node, "documentation"), nullOrASTString(_node, "documentation"),
@ -835,7 +835,7 @@ ASTPointer<VariableDeclarationStatement> ASTJsonImporter::createVariableDeclarat
); );
} }
ASTPointer<ExpressionStatement> ASTJsonImporter::createExpressionStatement(Json::Value const& _node) ASTPointer<ExpressionStatement> ASTJsonImporter::createExpressionStatement(Json const& _node)
{ {
return createASTNode<ExpressionStatement>( return createASTNode<ExpressionStatement>(
_node, _node,
@ -844,7 +844,7 @@ ASTPointer<ExpressionStatement> ASTJsonImporter::createExpressionStatement(Json:
); );
} }
ASTPointer<Conditional> ASTJsonImporter::createConditional(Json::Value const& _node) ASTPointer<Conditional> ASTJsonImporter::createConditional(Json const& _node)
{ {
return createASTNode<Conditional>( return createASTNode<Conditional>(
_node, _node,
@ -854,7 +854,7 @@ ASTPointer<Conditional> ASTJsonImporter::createConditional(Json::Value const& _
); );
} }
ASTPointer<Assignment> ASTJsonImporter::createAssignment(Json::Value const& _node) ASTPointer<Assignment> ASTJsonImporter::createAssignment(Json const& _node)
{ {
return createASTNode<Assignment>( return createASTNode<Assignment>(
_node, _node,
@ -864,7 +864,7 @@ ASTPointer<Assignment> ASTJsonImporter::createAssignment(Json::Value const& _no
); );
} }
ASTPointer<TupleExpression> ASTJsonImporter::createTupleExpression(Json::Value const& _node) ASTPointer<TupleExpression> ASTJsonImporter::createTupleExpression(Json const& _node)
{ {
std::vector<ASTPointer<Expression>> components; std::vector<ASTPointer<Expression>> components;
for (auto& comp: member(_node, "components")) for (auto& comp: member(_node, "components"))
@ -876,7 +876,7 @@ ASTPointer<TupleExpression> ASTJsonImporter::createTupleExpression(Json::Value c
); );
} }
ASTPointer<UnaryOperation> ASTJsonImporter::createUnaryOperation(Json::Value const& _node) ASTPointer<UnaryOperation> ASTJsonImporter::createUnaryOperation(Json const& _node)
{ {
return createASTNode<UnaryOperation>( return createASTNode<UnaryOperation>(
_node, _node,
@ -886,7 +886,7 @@ ASTPointer<UnaryOperation> ASTJsonImporter::createUnaryOperation(Json::Value con
); );
} }
ASTPointer<BinaryOperation> ASTJsonImporter::createBinaryOperation(Json::Value const& _node) ASTPointer<BinaryOperation> ASTJsonImporter::createBinaryOperation(Json const& _node)
{ {
return createASTNode<BinaryOperation>( return createASTNode<BinaryOperation>(
_node, _node,
@ -896,7 +896,7 @@ ASTPointer<BinaryOperation> ASTJsonImporter::createBinaryOperation(Json::Value c
); );
} }
ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const& _node) ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json const& _node)
{ {
std::vector<ASTPointer<Expression>> arguments; std::vector<ASTPointer<Expression>> arguments;
for (auto& arg: member(_node, "arguments")) for (auto& arg: member(_node, "arguments"))
@ -904,8 +904,8 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
std::vector<ASTPointer<ASTString>> names; std::vector<ASTPointer<ASTString>> names;
for (auto& name: member(_node, "names")) for (auto& name: member(_node, "names"))
{ {
astAssert(name.isString(), "Expected 'names' members to be strings!"); astAssert(name.is_string(), "Expected 'names' members to be strings!");
names.push_back(make_shared<ASTString>(name.asString())); names.push_back(make_shared<ASTString>(name.get<string>()));
} }
optional<vector<SourceLocation>> sourceLocations = createSourceLocations(_node); optional<vector<SourceLocation>> sourceLocations = createSourceLocations(_node);
@ -921,7 +921,7 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
); );
} }
ASTPointer<FunctionCallOptions> ASTJsonImporter::createFunctionCallOptions(Json::Value const& _node) ASTPointer<FunctionCallOptions> ASTJsonImporter::createFunctionCallOptions(Json const& _node)
{ {
std::vector<ASTPointer<Expression>> options; std::vector<ASTPointer<Expression>> options;
for (auto& option: member(_node, "options")) for (auto& option: member(_node, "options"))
@ -929,8 +929,8 @@ ASTPointer<FunctionCallOptions> ASTJsonImporter::createFunctionCallOptions(Json:
std::vector<ASTPointer<ASTString>> names; std::vector<ASTPointer<ASTString>> names;
for (auto& name: member(_node, "names")) for (auto& name: member(_node, "names"))
{ {
astAssert(name.isString(), "Expected 'names' members to be strings!"); astAssert(name.is_string(), "Expected 'names' members to be strings!");
names.push_back(make_shared<ASTString>(name.asString())); names.push_back(make_shared<ASTString>(name.get<string>()));
} }
return createASTNode<FunctionCallOptions>( return createASTNode<FunctionCallOptions>(
@ -941,7 +941,7 @@ ASTPointer<FunctionCallOptions> ASTJsonImporter::createFunctionCallOptions(Json:
); );
} }
ASTPointer<NewExpression> ASTJsonImporter::createNewExpression(Json::Value const& _node) ASTPointer<NewExpression> ASTJsonImporter::createNewExpression(Json const& _node)
{ {
return createASTNode<NewExpression>( return createASTNode<NewExpression>(
_node, _node,
@ -949,11 +949,11 @@ ASTPointer<NewExpression> ASTJsonImporter::createNewExpression(Json::Value const
); );
} }
ASTPointer<MemberAccess> ASTJsonImporter::createMemberAccess(Json::Value const& _node) ASTPointer<MemberAccess> ASTJsonImporter::createMemberAccess(Json const& _node)
{ {
SourceLocation memberLocation; SourceLocation memberLocation;
if (member(_node, "memberLocation").isString()) if (member(_node, "memberLocation").is_string())
memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].asString(), m_sourceNames); memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].get<string>(), m_sourceNames);
return createASTNode<MemberAccess>( return createASTNode<MemberAccess>(
_node, _node,
@ -963,7 +963,7 @@ ASTPointer<MemberAccess> ASTJsonImporter::createMemberAccess(Json::Value const&
); );
} }
ASTPointer<IndexAccess> ASTJsonImporter::createIndexAccess(Json::Value const& _node) ASTPointer<IndexAccess> ASTJsonImporter::createIndexAccess(Json const& _node)
{ {
return createASTNode<IndexAccess>( return createASTNode<IndexAccess>(
_node, _node,
@ -972,7 +972,7 @@ ASTPointer<IndexAccess> ASTJsonImporter::createIndexAccess(Json::Value const& _n
); );
} }
ASTPointer<IndexRangeAccess> ASTJsonImporter::createIndexRangeAccess(Json::Value const& _node) ASTPointer<IndexRangeAccess> ASTJsonImporter::createIndexRangeAccess(Json const& _node)
{ {
return createASTNode<IndexRangeAccess>( return createASTNode<IndexRangeAccess>(
_node, _node,
@ -982,12 +982,12 @@ ASTPointer<IndexRangeAccess> ASTJsonImporter::createIndexRangeAccess(Json::Value
); );
} }
ASTPointer<Identifier> ASTJsonImporter::createIdentifier(Json::Value const& _node) ASTPointer<Identifier> ASTJsonImporter::createIdentifier(Json const& _node)
{ {
return createASTNode<Identifier>(_node, memberAsASTString(_node, "name")); return createASTNode<Identifier>(_node, memberAsASTString(_node, "name"));
} }
ASTPointer<ElementaryTypeNameExpression> ASTJsonImporter::createElementaryTypeNameExpression(Json::Value const& _node) ASTPointer<ElementaryTypeNameExpression> ASTJsonImporter::createElementaryTypeNameExpression(Json const& _node)
{ {
return createASTNode<ElementaryTypeNameExpression>( return createASTNode<ElementaryTypeNameExpression>(
_node, _node,
@ -995,116 +995,116 @@ ASTPointer<ElementaryTypeNameExpression> ASTJsonImporter::createElementaryTypeNa
); );
} }
ASTPointer<ASTNode> ASTJsonImporter::createLiteral(Json::Value const& _node) ASTPointer<ASTNode> ASTJsonImporter::createLiteral(Json const& _node)
{ {
static string const valStr = "value"; static string const valStr = "value";
static string const hexValStr = "hexValue"; static 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<ASTString> value = _node.isMember(hexValStr) ? ASTPointer<ASTString> value = _node.contains(hexValStr) ?
make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].asString()))) : make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].get<string>()))) :
make_shared<ASTString>(_node[valStr].asString()); make_shared<ASTString>(_node[valStr].get<string>());
return createASTNode<Literal>( return createASTNode<Literal>(
_node, _node,
literalTokenKind(_node), literalTokenKind(_node),
value, value,
member(_node, "subdenomination").isNull() ? Literal::SubDenomination::None : subdenomination(_node) member(_node, "subdenomination").is_null() ? Literal::SubDenomination::None : subdenomination(_node)
); );
} }
ASTPointer<StructuredDocumentation> ASTJsonImporter::createDocumentation(Json::Value const& _node) ASTPointer<StructuredDocumentation> ASTJsonImporter::createDocumentation(Json const& _node)
{ {
static string const textString = "text"; static 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<StructuredDocumentation>( return createASTNode<StructuredDocumentation>(
_node, _node,
make_shared<ASTString>(_node[textString].asString()) make_shared<ASTString>(_node[textString].get<string>())
); );
} }
// ===== helper functions ========== // ===== helper functions ==========
Json::Value ASTJsonImporter::member(Json::Value const& _node, string const& _name) Json ASTJsonImporter::member(Json const& _node, string const& _name)
{ {
if (!_node.isMember(_name)) if (!_node.contains(_name))
return Json::nullValue; return Json{};
return _node[_name]; 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<string>(), "");
langutil::Scanner scanner{charStream}; langutil::Scanner scanner{charStream};
astAssert(scanner.peekNextToken() == Token::EOS, "Token string is too long."); astAssert(scanner.peekNextToken() == Token::EOS, "Token string is too long.");
return scanner.currentToken(); return scanner.currentToken();
} }
ASTPointer<ASTString> ASTJsonImporter::nullOrASTString(Json::Value const& _json, string const& _name) ASTPointer<ASTString> ASTJsonImporter::nullOrASTString(Json const& _json, string const& _name)
{ {
return _json[_name].isString() ? memberAsASTString(_json, _name) : nullptr; return _json[_name].is_string() ? memberAsASTString(_json, _name) : nullptr;
} }
ASTPointer<ASTString> ASTJsonImporter::memberAsASTString(Json::Value const& _node, string const& _name) ASTPointer<ASTString> ASTJsonImporter::memberAsASTString(Json const& _node, string const& _name)
{ {
Json::Value value = member(_node, _name); Json value = member(_node, _name);
astAssert(value.isString(), "field " + _name + " must be of type string."); astAssert(value.is_string(), "field " + _name + " must be of type string.");
return make_shared<ASTString>(_node[_name].asString()); return make_shared<ASTString>(_node[_name].get<string>());
} }
bool ASTJsonImporter::memberAsBool(Json::Value const& _node, string const& _name) bool ASTJsonImporter::memberAsBool(Json const& _node, string const& _name)
{ {
Json::Value value = member(_node, _name); Json value = member(_node, _name);
astAssert(value.isBool(), "field " + _name + " must be of type boolean."); astAssert(value.is_boolean(), "field " + _name + " must be of type boolean.");
return _node[_name].asBool(); return _node[_name].get<bool>();
} }
// =========== JSON to definition helpers ======================= // =========== JSON to definition helpers =======================
ContractKind ASTJsonImporter::contractKind(Json::Value const& _node) ContractKind ASTJsonImporter::contractKind(Json const& _node)
{ {
ContractKind kind; ContractKind kind;
astAssert(!member(_node, "contractKind").isNull(), "'Contract-kind' can not be null."); astAssert(!member(_node, "contractKind").is_null(), "'Contract-kind' can not be null.");
if (_node["contractKind"].asString() == "interface") if (_node["contractKind"].get<string>() == "interface")
kind = ContractKind::Interface; kind = ContractKind::Interface;
else if (_node["contractKind"].asString() == "contract") else if (_node["contractKind"].get<string>() == "contract")
kind = ContractKind::Contract; kind = ContractKind::Contract;
else if (_node["contractKind"].asString() == "library") else if (_node["contractKind"].get<string>() == "library")
kind = ContractKind::Library; kind = ContractKind::Library;
else else
astAssert(false, "Unknown ContractKind"); astAssert(false, "Unknown ContractKind");
return kind; 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; Token tok;
if (_node["kind"].asString() == "number") if (_node["kind"].get<string>() == "number")
tok = Token::Number; tok = Token::Number;
else if (_node["kind"].asString() == "string") else if (_node["kind"].get<string>() == "string")
tok = Token::StringLiteral; tok = Token::StringLiteral;
else if (_node["kind"].asString() == "unicodeString") else if (_node["kind"].get<string>() == "unicodeString")
tok = Token::UnicodeStringLiteral; tok = Token::UnicodeStringLiteral;
else if (_node["kind"].asString() == "hexString") else if (_node["kind"].get<string>() == "hexString")
tok = Token::HexStringLiteral; tok = Token::HexStringLiteral;
else if (_node["kind"].asString() == "bool") else if (_node["kind"].get<string>() == "bool")
tok = (member(_node, "value").asString() == "true") ? Token::TrueLiteral : Token::FalseLiteral; tok = (member(_node, "value").get<string>() == "true") ? Token::TrueLiteral : Token::FalseLiteral;
else else
astAssert(false, "Unknown kind of literalString"); astAssert(false, "Unknown kind of literalString");
return tok; return tok;
} }
Visibility ASTJsonImporter::visibility(Json::Value const& _node) Visibility ASTJsonImporter::visibility(Json const& _node)
{ {
Json::Value visibility = member(_node, "visibility"); Json visibility = member(_node, "visibility");
astAssert(visibility.isString(), "'visibility' expected to be a string."); astAssert(visibility.is_string(), "'visibility' expected to be a string.");
string const visibilityStr = visibility.asString(); string const visibilityStr = visibility.get<string>();
if (visibilityStr == "default") if (visibilityStr == "default")
return Visibility::Default; return Visibility::Default;
@ -1123,12 +1123,12 @@ Visibility ASTJsonImporter::visibility(Json::Value const& _node)
util::unreachable(); util::unreachable();
} }
VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node) VariableDeclaration::Location ASTJsonImporter::location(Json const& _node)
{ {
Json::Value storageLoc = member(_node, "storageLocation"); Json storageLoc = member(_node, "storageLocation");
astAssert(storageLoc.isString(), "'storageLocation' expected to be a string."); astAssert(storageLoc.is_string(), "'storageLocation' expected to be a string.");
string const storageLocStr = storageLoc.asString(); string const storageLocStr = storageLoc.get<string>();
if (storageLocStr == "default") if (storageLocStr == "default")
return VariableDeclaration::Location::Unspecified; return VariableDeclaration::Location::Unspecified;
@ -1145,16 +1145,16 @@ VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node
util::unreachable(); 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; return Literal::SubDenomination::None;
astAssert(subDen.isString(), "'subDenomination' expected to be string."); astAssert(subDen.is_string(), "'subDenomination' expected to be string.");
string const subDenStr = subDen.asString(); string const subDenStr = subDen.get<string>();
if (subDenStr == "wei") if (subDenStr == "wei")
return Literal::SubDenomination::Wei; return Literal::SubDenomination::Wei;
@ -1181,10 +1181,10 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no
util::unreachable(); 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."); astAssert(member(_node, "stateMutability").is_string(), "StateMutability' expected to be string.");
string const mutabilityStr = member(_node, "stateMutability").asString(); string const mutabilityStr = member(_node, "stateMutability").get<string>();
if (mutabilityStr == "pure") if (mutabilityStr == "pure")
return StateMutability::Pure; return StateMutability::Pure;

View File

@ -25,7 +25,7 @@
#include <vector> #include <vector>
#include <libsolidity/ast/AST.h> #include <libsolidity/ast/AST.h>
#include <json/json.h> #include <libsolutil/JSON.h>
#include <libsolidity/ast/ASTAnnotations.h> #include <libsolidity/ast/ASTAnnotations.h>
#include <liblangutil/EVMVersion.h> #include <liblangutil/EVMVersion.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
@ -47,7 +47,7 @@ public:
/// Converts the AST from JSON-format to ASTPointer /// Converts the AST from JSON-format to ASTPointer
/// @a _sourceList used to provide source names for the ASTs /// @a _sourceList used to provide source names for the ASTs
/// @returns map of sourcenames to their respective ASTs /// @returns map of sourcenames to their respective ASTs
std::map<std::string, ASTPointer<SourceUnit>> jsonToSourceUnit(std::map<std::string, Json::Value> const& _sourceList); std::map<std::string, ASTPointer<SourceUnit>> jsonToSourceUnit(std::map<std::string, Json> const& _sourceList);
private: private:
@ -56,101 +56,101 @@ private:
/// Sets the source location and nodeID /// Sets the source location and nodeID
/// @returns the ASTNode Object class of the respective JSON node, /// @returns the ASTNode Object class of the respective JSON node,
template <typename T, typename... Args> template <typename T, typename... Args>
ASTPointer<T> createASTNode(Json::Value const& _node, Args&&... _args); ASTPointer<T> createASTNode(Json const& _node, Args&&... _args);
/// @returns the sourceLocation-object created from the string in the JSON node /// @returns the sourceLocation-object created from the string in the JSON node
langutil::SourceLocation const createSourceLocation(Json::Value const& _node); langutil::SourceLocation const createSourceLocation(Json const& _node);
std::optional<std::vector<langutil::SourceLocation>> createSourceLocations(Json::Value const& _node) const; std::optional<std::vector<langutil::SourceLocation>> createSourceLocations(Json const& _node) const;
/// Creates an ASTNode for a given JSON-ast of unknown type /// Creates an ASTNode for a given JSON-ast of unknown type
/// @returns Pointer to a new created ASTNode /// @returns Pointer to a new created ASTNode
ASTPointer<ASTNode> convertJsonToASTNode(Json::Value const& _ast); ASTPointer<ASTNode> convertJsonToASTNode(Json const& _ast);
/// @returns a pointer to the more specific subclass of ASTNode /// @returns a pointer to the more specific subclass of ASTNode
/// as indicated by the nodeType field of the json /// as indicated by the nodeType field of the json
template<class T> template<class T>
ASTPointer<T> convertJsonToASTNode(Json::Value const& _node); ASTPointer<T> convertJsonToASTNode(Json const& _node);
langutil::SourceLocation createNameSourceLocation(Json::Value const& _node); langutil::SourceLocation createNameSourceLocation(Json const& _node);
/// \defgroup nodeCreators JSON to AST-Nodes /// \defgroup nodeCreators JSON to AST-Nodes
///@{ ///@{
ASTPointer<SourceUnit> createSourceUnit(Json::Value const& _node, std::string const& _srcName); ASTPointer<SourceUnit> createSourceUnit(Json const& _node, std::string const& _srcName);
ASTPointer<PragmaDirective> createPragmaDirective(Json::Value const& _node); ASTPointer<PragmaDirective> createPragmaDirective(Json const& _node);
ASTPointer<ImportDirective> createImportDirective(Json::Value const& _node); ASTPointer<ImportDirective> createImportDirective(Json const& _node);
ASTPointer<ContractDefinition> createContractDefinition(Json::Value const& _node); ASTPointer<ContractDefinition> createContractDefinition(Json const& _node);
ASTPointer<IdentifierPath> createIdentifierPath(Json::Value const& _node); ASTPointer<IdentifierPath> createIdentifierPath(Json const& _node);
ASTPointer<InheritanceSpecifier> createInheritanceSpecifier(Json::Value const& _node); ASTPointer<InheritanceSpecifier> createInheritanceSpecifier(Json const& _node);
ASTPointer<UsingForDirective> createUsingForDirective(Json::Value const& _node); ASTPointer<UsingForDirective> createUsingForDirective(Json const& _node);
ASTPointer<ASTNode> createStructDefinition(Json::Value const& _node); ASTPointer<ASTNode> createStructDefinition(Json const& _node);
ASTPointer<EnumDefinition> createEnumDefinition(Json::Value const& _node); ASTPointer<EnumDefinition> createEnumDefinition(Json const& _node);
ASTPointer<EnumValue> createEnumValue(Json::Value const& _node); ASTPointer<EnumValue> createEnumValue(Json const& _node);
ASTPointer<UserDefinedValueTypeDefinition> createUserDefinedValueTypeDefinition(Json::Value const& _node); ASTPointer<UserDefinedValueTypeDefinition> createUserDefinedValueTypeDefinition(Json const& _node);
ASTPointer<ParameterList> createParameterList(Json::Value const& _node); ASTPointer<ParameterList> createParameterList(Json const& _node);
ASTPointer<OverrideSpecifier> createOverrideSpecifier(Json::Value const& _node); ASTPointer<OverrideSpecifier> createOverrideSpecifier(Json const& _node);
ASTPointer<FunctionDefinition> createFunctionDefinition(Json::Value const& _node); ASTPointer<FunctionDefinition> createFunctionDefinition(Json const& _node);
ASTPointer<VariableDeclaration> createVariableDeclaration(Json::Value const& _node); ASTPointer<VariableDeclaration> createVariableDeclaration(Json const& _node);
ASTPointer<ModifierDefinition> createModifierDefinition(Json::Value const& _node); ASTPointer<ModifierDefinition> createModifierDefinition(Json const& _node);
ASTPointer<ModifierInvocation> createModifierInvocation(Json::Value const& _node); ASTPointer<ModifierInvocation> createModifierInvocation(Json const& _node);
ASTPointer<EventDefinition> createEventDefinition(Json::Value const& _node); ASTPointer<EventDefinition> createEventDefinition(Json const& _node);
ASTPointer<ErrorDefinition> createErrorDefinition(Json::Value const& _node); ASTPointer<ErrorDefinition> createErrorDefinition(Json const& _node);
ASTPointer<ElementaryTypeName> createElementaryTypeName(Json::Value const& _node); ASTPointer<ElementaryTypeName> createElementaryTypeName(Json const& _node);
ASTPointer<UserDefinedTypeName> createUserDefinedTypeName(Json::Value const& _node); ASTPointer<UserDefinedTypeName> createUserDefinedTypeName(Json const& _node);
ASTPointer<FunctionTypeName> createFunctionTypeName(Json::Value const& _node); ASTPointer<FunctionTypeName> createFunctionTypeName(Json const& _node);
ASTPointer<Mapping> createMapping(Json::Value const& _node); ASTPointer<Mapping> createMapping(Json const& _node);
ASTPointer<ArrayTypeName> createArrayTypeName(Json::Value const& _node); ASTPointer<ArrayTypeName> createArrayTypeName(Json const& _node);
ASTPointer<InlineAssembly> createInlineAssembly(Json::Value const& _node); ASTPointer<InlineAssembly> createInlineAssembly(Json const& _node);
ASTPointer<Block> createBlock(Json::Value const& _node, bool _unchecked); ASTPointer<Block> createBlock(Json const& _node, bool _unchecked);
ASTPointer<PlaceholderStatement> createPlaceholderStatement(Json::Value const& _node); ASTPointer<PlaceholderStatement> createPlaceholderStatement(Json const& _node);
ASTPointer<IfStatement> createIfStatement(Json::Value const& _node); ASTPointer<IfStatement> createIfStatement(Json const& _node);
ASTPointer<TryCatchClause> createTryCatchClause(Json::Value const& _node); ASTPointer<TryCatchClause> createTryCatchClause(Json const& _node);
ASTPointer<TryStatement> createTryStatement(Json::Value const& _node); ASTPointer<TryStatement> createTryStatement(Json const& _node);
ASTPointer<WhileStatement> createWhileStatement(Json::Value const& _node, bool _isDoWhile); ASTPointer<WhileStatement> createWhileStatement(Json const& _node, bool _isDoWhile);
ASTPointer<ForStatement> createForStatement(Json::Value const& _node); ASTPointer<ForStatement> createForStatement(Json const& _node);
ASTPointer<Continue> createContinue(Json::Value const& _node); ASTPointer<Continue> createContinue(Json const& _node);
ASTPointer<Break> createBreak(Json::Value const& _node); ASTPointer<Break> createBreak(Json const& _node);
ASTPointer<Return> createReturn(Json::Value const& _node); ASTPointer<Return> createReturn(Json const& _node);
ASTPointer<Throw> createThrow(Json::Value const& _node); ASTPointer<Throw> createThrow(Json const& _node);
ASTPointer<EmitStatement> createEmitStatement(Json::Value const& _node); ASTPointer<EmitStatement> createEmitStatement(Json const& _node);
ASTPointer<RevertStatement> createRevertStatement(Json::Value const& _node); ASTPointer<RevertStatement> createRevertStatement(Json const& _node);
ASTPointer<VariableDeclarationStatement> createVariableDeclarationStatement(Json::Value const& _node); ASTPointer<VariableDeclarationStatement> createVariableDeclarationStatement(Json const& _node);
ASTPointer<ExpressionStatement> createExpressionStatement(Json::Value const& _node); ASTPointer<ExpressionStatement> createExpressionStatement(Json const& _node);
ASTPointer<Conditional> createConditional(Json::Value const& _node); ASTPointer<Conditional> createConditional(Json const& _node);
ASTPointer<Assignment> createAssignment(Json::Value const& _node); ASTPointer<Assignment> createAssignment(Json const& _node);
ASTPointer<TupleExpression> createTupleExpression(Json::Value const& _node); ASTPointer<TupleExpression> createTupleExpression(Json const& _node);
ASTPointer<UnaryOperation> createUnaryOperation(Json::Value const& _node); ASTPointer<UnaryOperation> createUnaryOperation(Json const& _node);
ASTPointer<BinaryOperation> createBinaryOperation(Json::Value const& _node); ASTPointer<BinaryOperation> createBinaryOperation(Json const& _node);
ASTPointer<FunctionCall> createFunctionCall(Json::Value const& _node); ASTPointer<FunctionCall> createFunctionCall(Json const& _node);
ASTPointer<FunctionCallOptions> createFunctionCallOptions(Json::Value const& _node); ASTPointer<FunctionCallOptions> createFunctionCallOptions(Json const& _node);
ASTPointer<NewExpression> createNewExpression(Json::Value const& _node); ASTPointer<NewExpression> createNewExpression(Json const& _node);
ASTPointer<MemberAccess> createMemberAccess(Json::Value const& _node); ASTPointer<MemberAccess> createMemberAccess(Json const& _node);
ASTPointer<IndexAccess> createIndexAccess(Json::Value const& _node); ASTPointer<IndexAccess> createIndexAccess(Json const& _node);
ASTPointer<IndexRangeAccess> createIndexRangeAccess(Json::Value const& _node); ASTPointer<IndexRangeAccess> createIndexRangeAccess(Json const& _node);
ASTPointer<Identifier> createIdentifier(Json::Value const& _node); ASTPointer<Identifier> createIdentifier(Json const& _node);
ASTPointer<ElementaryTypeNameExpression> createElementaryTypeNameExpression(Json::Value const& _node); ASTPointer<ElementaryTypeNameExpression> createElementaryTypeNameExpression(Json const& _node);
ASTPointer<ASTNode> createLiteral(Json::Value const& _node); ASTPointer<ASTNode> createLiteral(Json const& _node);
ASTPointer<StructuredDocumentation> createDocumentation(Json::Value const& _node); ASTPointer<StructuredDocumentation> createDocumentation(Json const& _node);
///@} ///@}
// =============== general helper functions =================== // =============== general helper functions ===================
/// @returns the member of a given JSON object, throws if member does not exist /// @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) /// @returns the appropriate TokenObject used in parsed Strings (pragma directive or operator)
Token scanSingleToken(Json::Value const& _node); Token scanSingleToken(Json const& _node);
template<class T> template<class T>
///@returns nullptr or an ASTPointer cast to a specific Class ///@returns nullptr or an ASTPointer cast to a specific Class
ASTPointer<T> nullOrCast(Json::Value const& _json); ASTPointer<T> nullOrCast(Json const& _json);
/// @returns nullptr or ASTString, given an JSON string or an empty field /// @returns nullptr or ASTString, given an JSON string or an empty field
ASTPointer<ASTString> nullOrASTString(Json::Value const& _json, std::string const& _name); ASTPointer<ASTString> nullOrASTString(Json const& _json, std::string const& _name);
// ============== JSON to definition helpers =============== // ============== JSON to definition helpers ===============
/// \defgroup typeHelpers Json to ast-datatype helpers /// \defgroup typeHelpers Json to ast-datatype helpers
/// {@ /// {@
ASTPointer<ASTString> memberAsASTString(Json::Value const& _node, std::string const& _name); ASTPointer<ASTString> memberAsASTString(Json const& _node, std::string const& _name);
bool memberAsBool(Json::Value const& _node, std::string const& _name); bool memberAsBool(Json const& _node, std::string const& _name);
Visibility visibility(Json::Value const& _node); Visibility visibility(Json const& _node);
StateMutability stateMutability(Json::Value const& _node); StateMutability stateMutability(Json const& _node);
VariableDeclaration::Location location(Json::Value const& _node); VariableDeclaration::Location location(Json const& _node);
ContractKind contractKind(Json::Value const& _node); ContractKind contractKind(Json const& _node);
Token literalTokenKind(Json::Value const& _node); Token literalTokenKind(Json const& _node);
Literal::SubDenomination subdenomination(Json::Value const& _node); Literal::SubDenomination subdenomination(Json const& _node);
///@} ///@}
// =========== member variables =============== // =========== member variables ===============

View File

@ -39,12 +39,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 { // TODO: consider using nlohmann_json::ordered_json instead
return make_tuple(_a["type"], _a["name"]) < make_tuple(_b["type"], _b["name"]); auto compare = [](Json const& _a, Json const& _b) -> bool {
// NOTE: some cases, like the constructor, don't contain a `name` entry
return make_tuple(_a["type"], _a.value("name", Json())) < make_tuple(_b["type"], _b.value("name", Json()));
}; };
multiset<Json::Value, decltype(compare)> abi(compare); multiset<Json, decltype(compare)> abi(compare);
for (auto it: _contractDef.interfaceFunctions()) for (auto it: _contractDef.interfaceFunctions())
{ {
@ -56,7 +58,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
FunctionType const* externalFunctionType = it.second->interfaceFunctionType(); FunctionType const* externalFunctionType = it.second->interfaceFunctionType();
solAssert(!!externalFunctionType, ""); solAssert(!!externalFunctionType, "");
Json::Value method{Json::objectValue}; Json method{Json::object()};
method["type"] = "function"; method["type"] = "function";
method["name"] = it.second->declaration().name(); method["name"] = it.second->declaration().name();
method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability());
@ -80,7 +82,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
FunctionType constrType(*constructor); FunctionType constrType(*constructor);
FunctionType const* externalFunctionType = constrType.interfaceFunctionType(); FunctionType const* externalFunctionType = constrType.interfaceFunctionType();
solAssert(!!externalFunctionType, ""); solAssert(!!externalFunctionType, "");
Json::Value method{Json::objectValue}; Json method{Json::object()};
method["type"] = "constructor"; method["type"] = "constructor";
method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability());
method["inputs"] = formatTypeList( method["inputs"] = formatTypeList(
@ -96,25 +98,25 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
{ {
auto const* externalFunctionType = FunctionType(*fallbackOrReceive).interfaceFunctionType(); auto const* externalFunctionType = FunctionType(*fallbackOrReceive).interfaceFunctionType();
solAssert(!!externalFunctionType, ""); solAssert(!!externalFunctionType, "");
Json::Value method{Json::objectValue}; Json method{Json::object()};
method["type"] = TokenTraits::toString(fallbackOrReceive->kind()); method["type"] = TokenTraits::toString(fallbackOrReceive->kind());
method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability());
abi.emplace(std::move(method)); abi.emplace(std::move(method));
} }
for (auto const& it: _contractDef.definedInterfaceEvents()) for (auto const& it: _contractDef.definedInterfaceEvents())
{ {
Json::Value event{Json::objectValue}; Json event{Json::object()};
event["type"] = "event"; event["type"] = "event";
event["name"] = it->name(); event["name"] = it->name();
event["anonymous"] = it->isAnonymous(); event["anonymous"] = it->isAnonymous();
Json::Value params{Json::arrayValue}; Json params{Json::array()};
for (auto const& p: it->parameters()) for (auto const& p: it->parameters())
{ {
Type const* type = p->annotation().type->interfaceType(false); Type const* type = p->annotation().type->interfaceType(false);
solAssert(type, ""); solAssert(type, "");
auto param = formatType(p->name(), *type, *p->annotation().type, false); auto param = formatType(p->name(), *type, *p->annotation().type, false);
param["indexed"] = p->isIndexed(); param["indexed"] = p->isIndexed();
params.append(std::move(param)); params.emplace_back(param);
} }
event["inputs"] = std::move(params); event["inputs"] = std::move(params);
abi.emplace(std::move(event)); abi.emplace(std::move(event));
@ -122,53 +124,53 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
for (ErrorDefinition const* error: _contractDef.interfaceErrors()) for (ErrorDefinition const* error: _contractDef.interfaceErrors())
{ {
Json::Value errorJson{Json::objectValue}; Json errorJson{Json::object()};
errorJson["type"] = "error"; errorJson["type"] = "error";
errorJson["name"] = error->name(); errorJson["name"] = error->name();
errorJson["inputs"] = Json::arrayValue; errorJson["inputs"] = Json::array();
for (auto const& p: error->parameters()) for (auto const& p: error->parameters())
{ {
Type const* type = p->annotation().type->interfaceType(false); Type const* type = p->annotation().type->interfaceType(false);
solAssert(type, ""); solAssert(type, "");
errorJson["inputs"].append( errorJson["inputs"].emplace_back(
formatType(p->name(), *type, *p->annotation().type, false) formatType(p->name(), *type, *p->annotation().type, false)
); );
} }
abi.emplace(std::move(errorJson)); abi.emplace(std::move(errorJson));
} }
Json::Value abiJson{Json::arrayValue}; Json abiJson{Json::array()};
for (auto& f: abi) for (auto& f: abi)
abiJson.append(std::move(f)); abiJson.emplace_back(std::move(f));
return abiJson; return abiJson;
} }
Json::Value ABI::formatTypeList( Json ABI::formatTypeList(
vector<string> const& _names, vector<string> const& _names,
vector<Type const*> const& _encodingTypes, vector<Type const*> const& _encodingTypes,
vector<Type const*> const& _solidityTypes, vector<Type const*> const& _solidityTypes,
bool _forLibrary 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() == _encodingTypes.size(), "Names and types vector size does not match");
solAssert(_names.size() == _solidityTypes.size(), ""); solAssert(_names.size() == _solidityTypes.size(), "");
for (unsigned i = 0; i < _names.size(); ++i) for (unsigned i = 0; i < _names.size(); ++i)
{ {
solAssert(_encodingTypes[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; return params;
} }
Json::Value ABI::formatType( Json ABI::formatType(
string const& _name, string const& _name,
Type const& _encodingType, Type const& _encodingType,
Type const& _solidityType, Type const& _solidityType,
bool _forLibrary bool _forLibrary
) )
{ {
Json::Value ret{Json::objectValue}; Json ret{Json::object()};
ret["name"] = _name; ret["name"] = _name;
ret["internalType"] = _solidityType.toString(true); ret["internalType"] = _solidityType.toString(true);
string suffix = (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage)) ? " storage" : ""; string suffix = (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage)) ? " storage" : "";
@ -186,31 +188,31 @@ Json::Value ABI::formatType(
else else
suffix = string("[") + arrayType->length().str() + "]"; suffix = string("[") + arrayType->length().str() + "]";
solAssert(arrayType->baseType(), ""); solAssert(arrayType->baseType(), "");
Json::Value subtype = formatType( Json subtype = formatType(
"", "",
*arrayType->baseType(), *arrayType->baseType(),
*dynamic_cast<ArrayType const&>(_solidityType).baseType(), *dynamic_cast<ArrayType const&>(_solidityType).baseType(),
_forLibrary _forLibrary
); );
if (subtype.isMember("components")) if (subtype.contains("components"))
{ {
ret["type"] = subtype["type"].asString() + suffix; ret["type"] = subtype["type"].get<string>() + suffix;
ret["components"] = subtype["components"]; ret["components"] = subtype["components"];
} }
else else
ret["type"] = subtype["type"].asString() + suffix; ret["type"] = subtype["type"].get<string>() + suffix;
} }
} }
else if (StructType const* structType = dynamic_cast<StructType const*>(&_encodingType)) else if (StructType const* structType = dynamic_cast<StructType const*>(&_encodingType))
{ {
ret["type"] = "tuple"; ret["type"] = "tuple";
ret["components"] = Json::arrayValue; ret["components"] = Json::array();
for (auto const& member: structType->members(nullptr)) for (auto const& member: structType->members(nullptr))
{ {
solAssert(member.type, ""); solAssert(member.type, "");
Type const* t = member.type->interfaceType(_forLibrary); Type const* t = member.type->interfaceType(_forLibrary);
solAssert(t, ""); solAssert(t, "");
ret["components"].append(formatType(member.name, *t, *member.type, _forLibrary)); ret["components"].emplace_back(formatType(member.name, *t, *member.type, _forLibrary));
} }
} }
else else

View File

@ -21,9 +21,9 @@
#pragma once #pragma once
#include <json/json.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <libsolutil/JSON.h>
namespace solidity::frontend namespace solidity::frontend
{ {
@ -38,14 +38,14 @@ public:
/// Get the ABI Interface of the contract /// Get the ABI Interface of the contract
/// @param _contractDef The contract definition /// @param _contractDef The contract definition
/// @return A JSONrepresentation of the contract's ABI Interface /// @return A JSONrepresentation of the contract's ABI Interface
static Json::Value generate(ContractDefinition const& _contractDef); static Json generate(ContractDefinition const& _contractDef);
private: private:
/// @returns a json value suitable for a list of types in function input or output /// @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 /// parameters or other places. If @a _forLibrary is true, complex types are referenced
/// by name, otherwise they are anonymously expanded. /// by name, otherwise they are anonymously expanded.
/// @a _solidityTypes is the list of original Solidity types where @a _encodingTypes is the list of /// @a _solidityTypes is the list of original Solidity types where @a _encodingTypes is the list of
/// ABI types used for the actual encoding. /// ABI types used for the actual encoding.
static Json::Value formatTypeList( static Json formatTypeList(
std::vector<std::string> const& _names, std::vector<std::string> const& _names,
std::vector<Type const*> const& _encodingTypes, std::vector<Type const*> const& _encodingTypes,
std::vector<Type const*> const& _solidityTypes, std::vector<Type const*> const& _solidityTypes,
@ -56,7 +56,7 @@ private:
/// If it is possible to express the type as a single string, it is allowed to return a single string. /// 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 /// @a _solidityType is the original Solidity type and @a _encodingTypes is the
/// ABI type used for the actual encoding. /// ABI type used for the actual encoding.
static Json::Value formatType( static Json formatType(
std::string const& _name, std::string const& _name,
Type const& _encodingType, Type const& _encodingType,
Type const& _solidityType, Type const& _solidityType,

View File

@ -77,8 +77,6 @@
#include <libsolutil/Algorithms.h> #include <libsolutil/Algorithms.h>
#include <libsolutil/FunctionSelector.h> #include <libsolutil/FunctionSelector.h>
#include <json/json.h>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <range/v3/view/concat.hpp> #include <range/v3/view/concat.hpp>
@ -392,7 +390,7 @@ bool CompilerStack::parse()
return !m_hasError; return !m_hasError;
} }
void CompilerStack::importASTs(map<string, Json::Value> const& _sources) void CompilerStack::importASTs(map<string, Json> const& _sources)
{ {
if (m_stackState != Empty) if (m_stackState != Empty)
solThrow(CompilerError, "Must call importASTs only before the SourcesSet state."); solThrow(CompilerError, "Must call importASTs only before the SourcesSet state.");
@ -759,18 +757,18 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _
return currentContract.evmRuntimeAssembly ? &currentContract.evmRuntimeAssembly->items() : nullptr; return currentContract.evmRuntimeAssembly ? &currentContract.evmRuntimeAssembly->items() : nullptr;
} }
Json::Value CompilerStack::generatedSources(string const& _contractName, bool _runtime) const Json CompilerStack::generatedSources(string const& _contractName, bool _runtime) const
{ {
if (m_stackState != CompilationSuccessful) if (m_stackState != CompilationSuccessful)
solThrow(CompilerError, "Compilation was not successful."); solThrow(CompilerError, "Compilation was not successful.");
Contract const& c = contract(_contractName); Contract const& c = contract(_contractName);
util::LazyInit<Json::Value const> const& sources = util::LazyInit<Json const> const& sources =
_runtime ? _runtime ?
c.runtimeGeneratedSources : c.runtimeGeneratedSources :
c.generatedSources; c.generatedSources;
return sources.init([&]{ 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 // If there is no compiler, then no bytecode was generated and thus no
// sources were generated (or we compiled "via IR"). // sources were generated (or we compiled "via IR").
if (c.compiler) if (c.compiler)
@ -918,7 +916,7 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap cons
} }
/// TODO: cache the JSON /// TODO: cache the JSON
Json::Value CompilerStack::assemblyJSON(string const& _contractName) const Json CompilerStack::assemblyJSON(string const& _contractName) const
{ {
if (m_stackState != CompilationSuccessful) if (m_stackState != CompilationSuccessful)
solThrow(CompilerError, "Compilation was not successful."); solThrow(CompilerError, "Compilation was not successful.");
@ -927,7 +925,7 @@ Json::Value CompilerStack::assemblyJSON(string const& _contractName) const
if (currentContract.evmAssembly) if (currentContract.evmAssembly)
return currentContract.evmAssembly->assemblyJSON(sourceIndices()); return currentContract.evmAssembly->assemblyJSON(sourceIndices());
else else
return Json::Value(); return Json();
} }
vector<string> CompilerStack::sourceNames() const vector<string> CompilerStack::sourceNames() const
@ -949,7 +947,7 @@ map<string, unsigned> CompilerStack::sourceIndices() const
return indices; return indices;
} }
Json::Value const& CompilerStack::contractABI(string const& _contractName) const Json const& CompilerStack::contractABI(string const& _contractName) const
{ {
if (m_stackState < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -957,7 +955,7 @@ Json::Value const& CompilerStack::contractABI(string const& _contractName) const
return contractABI(contract(_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 < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -967,7 +965,7 @@ Json::Value const& CompilerStack::contractABI(Contract const& _contract) const
return _contract.abi.init([&]{ return ABI::generate(*_contract.contract); }); return _contract.abi.init([&]{ return ABI::generate(*_contract.contract); });
} }
Json::Value const& CompilerStack::storageLayout(string const& _contractName) const Json const& CompilerStack::storageLayout(string const& _contractName) const
{ {
if (m_stackState < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -975,7 +973,7 @@ Json::Value const& CompilerStack::storageLayout(string const& _contractName) con
return storageLayout(contract(_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 < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -985,7 +983,7 @@ Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const
return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract); }); return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract); });
} }
Json::Value const& CompilerStack::natspecUser(string const& _contractName) const Json const& CompilerStack::natspecUser(string const& _contractName) const
{ {
if (m_stackState < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -993,7 +991,7 @@ Json::Value const& CompilerStack::natspecUser(string const& _contractName) const
return natspecUser(contract(_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 < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -1003,7 +1001,7 @@ Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const
return _contract.userDocumentation.init([&]{ return Natspec::userDocumentation(*_contract.contract); }); return _contract.userDocumentation.init([&]{ return Natspec::userDocumentation(*_contract.contract); });
} }
Json::Value const& CompilerStack::natspecDev(string const& _contractName) const Json const& CompilerStack::natspecDev(string const& _contractName) const
{ {
if (m_stackState < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -1011,7 +1009,7 @@ Json::Value const& CompilerStack::natspecDev(string const& _contractName) const
return natspecDev(contract(_contractName)); return natspecDev(contract(_contractName));
} }
Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const Json const& CompilerStack::natspecDev(Contract const& _contract) const
{ {
if (m_stackState < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
@ -1021,14 +1019,14 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const
return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); }); return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); });
} }
Json::Value CompilerStack::interfaceSymbols(string const& _contractName) const Json CompilerStack::interfaceSymbols(string const& _contractName) const
{ {
if (m_stackState < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
Json::Value interfaceSymbols(Json::objectValue); Json interfaceSymbols(Json::object());
// Always have a methods object // Always have a methods object
interfaceSymbols["methods"] = Json::objectValue; interfaceSymbols["methods"] = Json::object();
for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) for (auto const& it: contractDefinition(_contractName).interfaceFunctions())
interfaceSymbols["methods"][it.second->externalSignature()] = it.first.hex(); interfaceSymbols["methods"][it.second->externalSignature()] = it.first.hex();
@ -1481,7 +1479,7 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co
string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) const string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) const
{ {
Json::Value meta{Json::objectValue}; Json meta{Json::object()};
meta["version"] = 1; meta["version"] = 1;
string sourceType; string sourceType;
switch (m_compilationSourceType) switch (m_compilationSourceType)
@ -1502,7 +1500,7 @@ string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) con
for (auto const sourceUnit: _contract.contract->sourceUnit().referencedSourceUnits(true)) for (auto const sourceUnit: _contract.contract->sourceUnit().referencedSourceUnits(true))
referencedSources.insert(*sourceUnit->annotation().path); referencedSources.insert(*sourceUnit->annotation().path);
meta["sources"] = Json::objectValue; meta["sources"] = Json::object();
for (auto const& s: m_sources) for (auto const& s: m_sources)
{ {
if (!referencedSources.count(s.first)) if (!referencedSources.count(s.first))
@ -1516,15 +1514,15 @@ string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) con
meta["sources"][s.first]["content"] = s.second.charStream->source(); meta["sources"][s.first]["content"] = s.second.charStream->source();
else else
{ {
meta["sources"][s.first]["urls"] = Json::arrayValue; meta["sources"][s.first]["urls"] = Json::array();
meta["sources"][s.first]["urls"].append("bzz-raw://" + util::toHex(s.second.swarmHash().asBytes())); meta["sources"][s.first]["urls"].emplace_back("bzz-raw://" + util::toHex(s.second.swarmHash().asBytes()));
meta["sources"][s.first]["urls"].append(s.second.ipfsUrl()); meta["sources"][s.first]["urls"].emplace_back(s.second.ipfsUrl());
} }
} }
static_assert(sizeof(m_optimiserSettings.expectedExecutionsPerDeployment) <= sizeof(Json::LargestUInt), "Invalid word size."); static_assert(sizeof(m_optimiserSettings.expectedExecutionsPerDeployment) <= sizeof(Json::number_integer_t), "Invalid word size.");
solAssert(static_cast<Json::LargestUInt>(m_optimiserSettings.expectedExecutionsPerDeployment) < std::numeric_limits<Json::LargestUInt>::max(), ""); solAssert(static_cast<Json::number_integer_t>(m_optimiserSettings.expectedExecutionsPerDeployment) < std::numeric_limits<Json::number_integer_t>::max(), "");
meta["settings"]["optimizer"]["runs"] = Json::Value(Json::LargestUInt(m_optimiserSettings.expectedExecutionsPerDeployment)); 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. /// Backwards compatibility: If set to one of the default settings, do not provide details.
OptimiserSettings settingsWithoutRuns = m_optimiserSettings; OptimiserSettings settingsWithoutRuns = m_optimiserSettings;
@ -1536,7 +1534,7 @@ string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) con
meta["settings"]["optimizer"]["enabled"] = true; meta["settings"]["optimizer"]["enabled"] = true;
else else
{ {
Json::Value details{Json::objectValue}; Json details{Json::object()};
details["orderLiterals"] = m_optimiserSettings.runOrderLiterals; details["orderLiterals"] = m_optimiserSettings.runOrderLiterals;
details["inliner"] = m_optimiserSettings.runInliner; details["inliner"] = m_optimiserSettings.runInliner;
@ -1548,7 +1546,7 @@ string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) con
details["yul"] = m_optimiserSettings.runYulOptimiser; details["yul"] = m_optimiserSettings.runYulOptimiser;
if (m_optimiserSettings.runYulOptimiser) if (m_optimiserSettings.runYulOptimiser)
{ {
details["yulDetails"] = Json::objectValue; details["yulDetails"] = Json::object();
details["yulDetails"]["stackAllocation"] = m_optimiserSettings.optimizeStackAllocation; details["yulDetails"]["stackAllocation"] = m_optimiserSettings.optimizeStackAllocation;
details["yulDetails"]["optimizerSteps"] = m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps; details["yulDetails"]["optimizerSteps"] = m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps;
} }
@ -1574,14 +1572,14 @@ string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) con
meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] = meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] =
*_contract.contract->annotation().canonicalName; *_contract.contract->annotation().canonicalName;
meta["settings"]["remappings"] = Json::arrayValue; meta["settings"]["remappings"] = Json::array();
set<string> remappings; set<string> remappings;
for (auto const& r: m_importRemapper.remappings()) for (auto const& r: m_importRemapper.remappings())
remappings.insert(r.context + ":" + r.prefix + "=" + r.target); remappings.insert(r.context + ":" + r.prefix + "=" + r.target);
for (auto const& r: remappings) 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) for (auto const& library: m_libraries)
meta["settings"]["libraries"][library.first] = "0x" + util::toHex(library.second.asBytes()); meta["settings"]["libraries"][library.first] = "0x" + util::toHex(library.second.asBytes());
@ -1713,34 +1711,35 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR)
namespace namespace
{ {
Json::Value gasToJson(GasEstimator::GasConsumption const& _gas) Json gasToJson(GasEstimator::GasConsumption const& _gas)
{ {
if (_gas.isInfinite) if (_gas.isInfinite)
return Json::Value("infinite"); return Json("infinite");
else else
return Json::Value(util::toString(_gas.value)); // TODO use _gas.value.str()?
return Json(util::toString(_gas.value));
} }
} }
Json::Value CompilerStack::gasEstimates(string const& _contractName) const Json CompilerStack::gasEstimates(string const& _contractName) const
{ {
if (m_stackState != CompilationSuccessful) if (m_stackState != CompilationSuccessful)
solThrow(CompilerError, "Compilation was not successful."); solThrow(CompilerError, "Compilation was not successful.");
if (!assemblyItems(_contractName) && !runtimeAssemblyItems(_contractName)) if (!assemblyItems(_contractName) && !runtimeAssemblyItems(_contractName))
return Json::Value(); return Json();
using Gas = GasEstimator::GasConsumption; using Gas = GasEstimator::GasConsumption;
GasEstimator gasEstimator(m_evmVersion); GasEstimator gasEstimator(m_evmVersion);
Json::Value output(Json::objectValue); Json output(Json::object());
if (evmasm::AssemblyItems const* items = assemblyItems(_contractName)) if (evmasm::AssemblyItems const* items = assemblyItems(_contractName))
{ {
Gas executionGas = gasEstimator.functionalEstimation(*items); Gas executionGas = gasEstimator.functionalEstimation(*items);
Gas codeDepositGas{evmasm::GasMeter::dataGas(runtimeObject(_contractName).bytecode, false, m_evmVersion)}; 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["codeDepositCost"] = gasToJson(codeDepositGas);
creation["executionCost"] = gasToJson(executionGas); creation["executionCost"] = gasToJson(executionGas);
/// TODO: implement + overload to avoid the need of += /// TODO: implement + overload to avoid the need of +=
@ -1753,7 +1752,7 @@ Json::Value CompilerStack::gasEstimates(string const& _contractName) const
{ {
/// External functions /// External functions
ContractDefinition const& contract = contractDefinition(_contractName); ContractDefinition const& contract = contractDefinition(_contractName);
Json::Value externalFunctions(Json::objectValue); Json externalFunctions(Json::object());
for (auto it: contract.interfaceFunctions()) for (auto it: contract.interfaceFunctions())
{ {
string sig = it.second->externalSignature(); string sig = it.second->externalSignature();
@ -1770,7 +1769,7 @@ Json::Value CompilerStack::gasEstimates(string const& _contractName) const
output["external"] = externalFunctions; output["external"] = externalFunctions;
/// Internal functions /// Internal functions
Json::Value internalFunctions(Json::objectValue); Json internalFunctions(Json::object());
for (auto const& it: contract.definedFunctions()) for (auto const& it: contract.definedFunctions())
{ {
/// Exclude externally visible functions, constructor, fallback and receive ether function /// Exclude externally visible functions, constructor, fallback and receive ether function

View File

@ -45,10 +45,9 @@
#include <libsolutil/Common.h> #include <libsolutil/Common.h>
#include <libsolutil/FixedHash.h> #include <libsolutil/FixedHash.h>
#include <libsolutil/JSON.h>
#include <libsolutil/LazyInit.h> #include <libsolutil/LazyInit.h>
#include <json/json.h>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
@ -227,7 +226,7 @@ public:
/// Imports given SourceUnits so they can be analyzed. Leads to the same internal state as parse(). /// Imports given SourceUnits so they can be analyzed. Leads to the same internal state as parse().
/// Will throw errors if the import fails /// Will throw errors if the import fails
void importASTs(std::map<std::string, Json::Value> const& _sources); void importASTs(std::map<std::string, Json> const& _sources);
/// Performs the analysis steps (imports, scopesetting, syntaxCheck, referenceResolving, /// Performs the analysis steps (imports, scopesetting, syntaxCheck, referenceResolving,
/// typechecking, staticAnalysis) on previously parsed sources. /// typechecking, staticAnalysis) on previously parsed sources.
@ -298,7 +297,7 @@ public:
/// @returns an array containing all utility sources generated during compilation. /// @returns an array containing all utility sources generated during compilation.
/// Format: [ { name: string, id: number, language: "Yul", contents: string }, ... ] /// 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 /// @returns the string that provides a mapping between bytecode and sourcecode or a nullptr
/// if the contract does not (yet) have bytecode. /// if the contract does not (yet) have bytecode.
@ -316,26 +315,26 @@ public:
/// @returns a JSON representation of the assembly. /// @returns a JSON representation of the assembly.
/// @arg _sourceCodes is the map of input files to source code strings /// @arg _sourceCodes is the map of input files to source code strings
/// Prerequisite: Successful compilation. /// Prerequisite: Successful compilation.
Json::Value assemblyJSON(std::string const& _contractName) const; Json assemblyJSON(std::string const& _contractName) const;
/// @returns a JSON representing the contract ABI. /// @returns a JSON representing the contract ABI.
/// Prerequisite: Successful call to parse or compile. /// 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. /// @returns a JSON representing the storage layout of the contract.
/// Prerequisite: Successful call to parse or compile. /// 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. /// @returns a JSON representing the contract's user documentation.
/// Prerequisite: Successful call to parse or compile. /// 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. /// @returns a JSON representing the contract's developer documentation.
/// Prerequisite: Successful call to parse or compile. /// 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. /// @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. /// @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)); } std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); }
@ -349,7 +348,7 @@ public:
bytes cborMetadata(std::string const& _contractName, bool _forIR) const; bytes cborMetadata(std::string const& _contractName, bool _forIR) const;
/// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions /// @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. /// Changes the format of the metadata appended at the end of the bytecode.
void setMetadataFormat(MetadataFormat _metadataFormat) { m_metadataFormat = _metadataFormat; } void setMetadataFormat(MetadataFormat _metadataFormat) { m_metadataFormat = _metadataFormat; }
@ -388,12 +387,12 @@ private:
std::string ewasm; ///< Experimental Ewasm text representation std::string ewasm; ///< Experimental Ewasm text representation
evmasm::LinkerObject ewasmObject; ///< Experimental Ewasm code evmasm::LinkerObject ewasmObject; ///< Experimental Ewasm code
util::LazyInit<std::string const> metadata; ///< The metadata json that will be hashed into the chain. util::LazyInit<std::string const> metadata; ///< The metadata json that will be hashed into the chain.
util::LazyInit<Json::Value const> abi; util::LazyInit<Json const> abi;
util::LazyInit<Json::Value const> storageLayout; util::LazyInit<Json const> storageLayout;
util::LazyInit<Json::Value const> userDocumentation; util::LazyInit<Json const> userDocumentation;
util::LazyInit<Json::Value const> devDocumentation; util::LazyInit<Json const> devDocumentation;
util::LazyInit<Json::Value const> generatedSources; util::LazyInit<Json const> generatedSources;
util::LazyInit<Json::Value const> runtimeGeneratedSources; util::LazyInit<Json const> runtimeGeneratedSources;
mutable std::optional<std::string const> sourceMapping; mutable std::optional<std::string const> sourceMapping;
mutable std::optional<std::string const> runtimeSourceMapping; mutable std::optional<std::string const> runtimeSourceMapping;
}; };
@ -467,19 +466,19 @@ private:
/// @returns the contract ABI as a JSON object. /// @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. /// 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. /// @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. /// 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. /// @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. /// 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. /// @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. /// 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. /// @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. /// This will generate the metadata and store it in the Contract object if it is not present yet.
@ -507,7 +506,7 @@ private:
ImportRemapper m_importRemapper; ImportRemapper m_importRemapper;
std::map<std::string const, Source> m_sources; std::map<std::string const, Source> m_sources;
// if imported, store AST-JSONS for each filename // if imported, store AST-JSONS for each filename
std::map<std::string, Json::Value> m_sourceJsons; std::map<std::string, Json> m_sourceJsons;
std::vector<std::string> m_unhandledSMTLib2Queries; std::vector<std::string> m_unhandledSMTLib2Queries;
std::map<util::h256, std::string> m_smtlib2Responses; std::map<util::h256, std::string> m_smtlib2Responses;
std::shared_ptr<GlobalContext> m_globalContext; std::shared_ptr<GlobalContext> m_globalContext;

View File

@ -35,13 +35,13 @@ using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::frontend; using namespace solidity::frontend;
Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) Json Natspec::userDocumentation(ContractDefinition const& _contractDef)
{ {
Json::Value doc{Json::objectValue}; Json doc{Json::object()};
doc["version"] = Json::Value(c_natspecVersion); doc["version"] = Json(c_natspecVersion);
doc["kind"] = Json::Value("user"); doc["kind"] = Json("user");
doc["methods"] = Json::objectValue; doc["methods"] = Json::object();
auto constructorDefinition(_contractDef.constructor()); auto constructorDefinition(_contractDef.constructor());
if (constructorDefinition) if (constructorDefinition)
@ -50,15 +50,15 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
if (!value.empty()) if (!value.empty())
{ {
// add the constructor, only if we have any documentation to add // add the constructor, only if we have any documentation to add
Json::Value user{Json::objectValue}; Json user{Json::object()};
user["notice"] = Json::Value(value); user["notice"] = Json(value);
doc["methods"]["constructor"] = user; doc["methods"]["constructor"] = user;
} }
} }
string notice = extractDoc(_contractDef.annotation().docTags, "notice"); string notice = extractDoc(_contractDef.annotation().docTags, "notice");
if (!notice.empty()) if (!notice.empty())
doc["notice"] = Json::Value(notice); doc["notice"] = Json(notice);
for (auto const& it: _contractDef.interfaceFunctions()) for (auto const& it: _contractDef.interfaceFunctions())
if (it.second->hasDeclaration()) if (it.second->hasDeclaration())
@ -90,21 +90,21 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
string value = extractDoc(error->annotation().docTags, "notice"); string value = extractDoc(error->annotation().docTags, "notice");
if (!value.empty()) if (!value.empty())
{ {
Json::Value errorDoc{Json::objectValue}; Json errorDoc{Json::object()};
errorDoc["notice"] = value; 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; 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["version"] = Json(c_natspecVersion);
doc["kind"] = Json::Value("dev"); doc["kind"] = Json("dev");
auto author = extractDoc(_contractDef.annotation().docTags, "author"); auto author = extractDoc(_contractDef.annotation().docTags, "author");
if (!author.empty()) if (!author.empty())
@ -114,13 +114,13 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
doc["title"] = title; doc["title"] = title;
auto dev = extractDoc(_contractDef.annotation().docTags, "dev"); auto dev = extractDoc(_contractDef.annotation().docTags, "dev");
if (!dev.empty()) if (!dev.empty())
doc["details"] = Json::Value(dev); doc["details"] = Json(dev);
doc["methods"] = Json::objectValue; doc["methods"] = Json::object();
auto constructorDefinition(_contractDef.constructor()); auto constructorDefinition(_contractDef.constructor());
if (constructorDefinition) if (constructorDefinition)
{ {
Json::Value constructor(devDocumentation(constructorDefinition->annotation().docTags)); Json constructor(devDocumentation(constructorDefinition->annotation().docTags));
if (!constructor.empty()) if (!constructor.empty())
// add the constructor, only if we have any documentation to add // add the constructor, only if we have any documentation to add
doc["methods"]["constructor"] = constructor; doc["methods"]["constructor"] = constructor;
@ -132,9 +132,9 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
continue; continue;
if (auto fun = dynamic_cast<FunctionDefinition const*>(&it.second->declaration())) if (auto fun = dynamic_cast<FunctionDefinition const*>(&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 // add the function, only if we have any documentation to add
Json::Value jsonReturn = extractReturnParameterDocs( Json jsonReturn = extractReturnParameterDocs(
fun->annotation().docTags, fun->annotation().docTags,
fun->functionType(false)->returnParameterNames() fun->functionType(false)->returnParameterNames()
); );
@ -152,7 +152,7 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
if (auto devDoc = devDocumentation(varDecl->annotation().docTags); !devDoc.empty()) if (auto devDoc = devDocumentation(varDecl->annotation().docTags); !devDoc.empty())
doc["stateVariables"][varDecl->name()] = devDoc; doc["stateVariables"][varDecl->name()] = devDoc;
auto const assignIfNotEmpty = [&](string const& _name, Json::Value const& _content) auto const assignIfNotEmpty = [&](string const& _name, Json const& _content)
{ {
if (!_content.empty()) if (!_content.empty())
doc["stateVariables"][varDecl->name()][_name] = _content; doc["stateVariables"][varDecl->name()][_name] = _content;
@ -174,14 +174,14 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
for (auto const& error: _contractDef.interfaceErrors()) for (auto const& error: _contractDef.interfaceErrors())
if (auto devDoc = devDocumentation(error->annotation().docTags); !devDoc.empty()) 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; return doc;
} }
Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTag> const& _tags, vector<string> const& _returnParameterNames) Json Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTag> const& _tags, vector<string> const& _returnParameterNames)
{ {
Json::Value jsonReturn{Json::objectValue}; Json jsonReturn{Json::object()};
auto returnDocs = _tags.equal_range("return"); auto returnDocs = _tags.equal_range("return");
if (!_returnParameterNames.empty()) if (!_returnParameterNames.empty())
@ -202,7 +202,7 @@ Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTa
content = content.substr(nameEndPos+1); content = content.substr(nameEndPos+1);
} }
jsonReturn[paramName] = Json::Value(content); jsonReturn[paramName] = Json(content);
n++; n++;
} }
} }
@ -219,7 +219,7 @@ string Natspec::extractDoc(multimap<string, DocTag> const& _tags, string const&
return value; return value;
} }
Json::Value Natspec::extractCustomDoc(multimap<string, DocTag> const& _tags) Json Natspec::extractCustomDoc(multimap<string, DocTag> const& _tags)
{ {
std::map<string, string> concatenated; std::map<string, string> concatenated;
for (auto const& [tag, value]: _tags) for (auto const& [tag, value]: _tags)
@ -227,28 +227,28 @@ Json::Value Natspec::extractCustomDoc(multimap<string, DocTag> const& _tags)
concatenated[tag] += value.content; concatenated[tag] += value.content;
// We do not want to create an object if there are no custom tags found. // We do not want to create an object if there are no custom tags found.
if (concatenated.empty()) if (concatenated.empty())
return Json::nullValue; return Json{};
Json::Value result{Json::objectValue}; Json result{Json::object()};
for (auto& [tag, value]: concatenated) for (auto& [tag, value]: concatenated)
result[tag] = std::move(value); result[tag] = std::move(value);
return result; return result;
} }
Json::Value Natspec::devDocumentation(std::multimap<std::string, DocTag> const& _tags) Json Natspec::devDocumentation(std::multimap<std::string, DocTag> const& _tags)
{ {
Json::Value json = extractCustomDoc(_tags); Json json = extractCustomDoc(_tags);
auto dev = extractDoc(_tags, "dev"); auto dev = extractDoc(_tags, "dev");
if (!dev.empty()) if (!dev.empty())
json["details"] = Json::Value(dev); json["details"] = Json(dev);
auto author = extractDoc(_tags, "author"); auto author = extractDoc(_tags, "author");
if (!author.empty()) if (!author.empty())
json["author"] = author; json["author"] = author;
Json::Value params(Json::objectValue); Json params(Json::object());
auto paramRange = _tags.equal_range("param"); auto paramRange = _tags.equal_range("param");
for (auto i = paramRange.first; i != paramRange.second; ++i) 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()) if (!params.empty())
json["params"] = params; json["params"] = params;

View File

@ -26,10 +26,10 @@
#pragma once #pragma once
#include <json/json.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <libsolidity/ast/AST.h> #include <libsolidity/ast/AST.h>
#include <libsolutil/JSON.h>
namespace solidity::frontend namespace solidity::frontend
{ {
@ -46,32 +46,32 @@ public:
/// Get the User documentation of the contract /// Get the User documentation of the contract
/// @param _contractDef The contract definition /// @param _contractDef The contract definition
/// @return A JSON representation of the contract's user documentation /// @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 /// Generates the Developer's documentation of the contract
/// @param _contractDef The contract definition /// @param _contractDef The contract definition
/// @return A JSON representation /// @return A JSON representation
/// of the contract's developer documentation /// of the contract's developer documentation
static Json::Value devDocumentation(ContractDefinition const& _contractDef); static Json devDocumentation(ContractDefinition const& _contractDef);
private: private:
/// @returns concatenation of all content under the given tag name. /// @returns concatenation of all content under the given tag name.
static std::string extractDoc(std::multimap<std::string, DocTag> const& _tags, std::string const& _name); static std::string extractDoc(std::multimap<std::string, DocTag> const& _tags, std::string const& _name);
/// Extract all custom tags from @a _tags. /// Extract all custom tags from @a _tags.
static Json::Value extractCustomDoc(std::multimap<std::string, DocTag> const& _tags); static Json extractCustomDoc(std::multimap<std::string, DocTag> const& _tags);
/// Helper-function that will create a json object with dev specific annotations, if present. /// Helper-function that will create a json object with dev specific annotations, if present.
/// @param _tags docTags that are used. /// @param _tags docTags that are used.
/// @return A JSON representation /// @return A JSON representation
/// of the contract's developer documentation /// of the contract's developer documentation
static Json::Value devDocumentation(std::multimap<std::string, DocTag> const& _tags); static Json devDocumentation(std::multimap<std::string, DocTag> const& _tags);
/// Helper-function that will create a json object for the "returns" field for a given function definition. /// Helper-function that will create a json object for the "returns" field for a given function definition.
/// @param _tags docTags that are used. /// @param _tags docTags that are used.
/// @param _returnParameterNames names of the return parameters /// @param _returnParameterNames names of the return parameters
/// @return A JSON representation /// @return A JSON representation
/// of a method's return notice documentation /// of a method's return notice documentation
static Json::Value extractReturnParameterDocs(std::multimap<std::string, DocTag> const& _tags, std::vector<std::string> const& _returnParameterNames); static Json extractReturnParameterDocs(std::multimap<std::string, DocTag> const& _tags, std::vector<std::string> const& _returnParameterNames);
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@ -58,12 +58,12 @@ public:
/// Sets all input parameters according to @a _input which conforms to the standardized input /// Sets all input parameters according to @a _input which conforms to the standardized input
/// format, performs compilation and returns a standardized output. /// 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 peforms the above processing steps, returning a serialized JSON /// Parses input as JSON and peforms the above processing steps, returning a serialized JSON
/// output. Parsing errors are returned as regular errors. /// output. Parsing errors are returned as regular errors.
std::string compile(std::string const& _input) noexcept; std::string compile(std::string const& _input) noexcept;
static Json::Value formatFunctionDebugData( static Json formatFunctionDebugData(
std::map<std::string, evmasm::LinkerObject::FunctionDebugData> const& _debugInfo std::map<std::string, evmasm::LinkerObject::FunctionDebugData> const& _debugInfo
); );
@ -71,7 +71,7 @@ private:
struct InputsAndSettings struct InputsAndSettings
{ {
std::string language; std::string language;
Json::Value errors; Json errors;
bool parserErrorRecovery = false; bool parserErrorRecovery = false;
CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful; CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful;
std::map<std::string, std::string> sources; std::map<std::string, std::string> sources;
@ -85,17 +85,17 @@ private:
bool metadataLiteralSources = false; bool metadataLiteralSources = false;
CompilerStack::MetadataFormat metadataFormat = CompilerStack::defaultMetadataFormat(); CompilerStack::MetadataFormat metadataFormat = CompilerStack::defaultMetadataFormat();
CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS; CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS;
Json::Value outputSelection; Json outputSelection;
ModelCheckerSettings modelCheckerSettings = ModelCheckerSettings{}; ModelCheckerSettings modelCheckerSettings = ModelCheckerSettings{};
bool viaIR = false; bool viaIR = false;
}; };
/// Parses the input json (and potentially invokes the read callback) and either returns /// Parses the input json (and potentially invokes the read callback) and either returns
/// it in condensed form or an error as a json object. /// it in condensed form or an error as a json object.
std::variant<InputsAndSettings, Json::Value> parseInput(Json::Value const& _input); std::variant<InputsAndSettings, Json> parseInput(Json const& _input);
Json::Value compileSolidity(InputsAndSettings _inputsAndSettings); Json compileSolidity(InputsAndSettings _inputsAndSettings);
Json::Value compileYul(InputsAndSettings _inputsAndSettings); Json compileYul(InputsAndSettings _inputsAndSettings);
ReadCallback::Callback m_readFile; ReadCallback::Callback m_readFile;

View File

@ -24,7 +24,7 @@ using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::frontend; using namespace solidity::frontend;
Json::Value StorageLayout::generate(ContractDefinition const& _contractDef) Json StorageLayout::generate(ContractDefinition const& _contractDef)
{ {
solAssert(!m_contract, ""); solAssert(!m_contract, "");
m_contract = &_contractDef; m_contract = &_contractDef;
@ -35,19 +35,19 @@ Json::Value StorageLayout::generate(ContractDefinition const& _contractDef)
auto contractType = dynamic_cast<ContractType const*>(typeType->actualType()); auto contractType = dynamic_cast<ContractType const*>(typeType->actualType());
solAssert(contractType, ""); solAssert(contractType, "");
Json::Value variables(Json::arrayValue); Json variables(Json::array());
for (auto [var, slot, offset]: contractType->stateVariables()) 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["storage"] = std::move(variables);
layout["types"] = std::move(m_types); layout["types"] = std::move(m_types);
return layout; 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(); Type const* varType = _var.type();
varEntry["label"] = _var.name(); varEntry["label"] = _var.name();
@ -64,22 +64,22 @@ Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const&
void StorageLayout::generate(Type const* _type) void StorageLayout::generate(Type const* _type)
{ {
if (m_types.isMember(typeKeyName(_type))) if (m_types.contains(typeKeyName(_type)))
return; return;
// Register it now to cut recursive visits. // 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["label"] = _type->toString(true);
typeInfo["numberOfBytes"] = u256(_type->storageBytes() * _type->storageSize()).str(); typeInfo["numberOfBytes"] = u256(_type->storageBytes() * _type->storageSize()).str();
if (auto structType = dynamic_cast<StructType const*>(_type)) if (auto structType = dynamic_cast<StructType const*>(_type))
{ {
Json::Value members(Json::arrayValue); Json members(Json::array());
auto const& structDef = structType->structDefinition(); auto const& structDef = structType->structDefinition();
for (auto const& member: structDef.members()) for (auto const& member: structDef.members())
{ {
auto const& offsets = structType->storageOffsetsOfMember(member->name()); 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["members"] = std::move(members);
typeInfo["encoding"] = "inplace"; typeInfo["encoding"] = "inplace";
@ -109,7 +109,7 @@ void StorageLayout::generate(Type const* _type)
typeInfo["encoding"] = "inplace"; typeInfo["encoding"] = "inplace";
} }
solAssert(typeInfo.isMember("encoding"), ""); solAssert(typeInfo.contains("encoding"), "");
} }
string StorageLayout::typeKeyName(Type const* _type) string StorageLayout::typeKeyName(Type const* _type)

View File

@ -24,7 +24,7 @@
#include <libsolidity/ast/AST.h> #include <libsolidity/ast/AST.h>
#include <libsolidity/ast/Types.h> #include <libsolidity/ast/Types.h>
#include <json/json.h> #include <libsolutil/JSON.h>
namespace solidity::frontend namespace solidity::frontend
{ {
@ -35,11 +35,11 @@ public:
/// Generates the storage layout of the contract /// Generates the storage layout of the contract
/// @param _contractDef The contract definition /// @param _contractDef The contract definition
/// @return A JSON representation of the contract's storage layout. /// @return A JSON representation of the contract's storage layout.
Json::Value generate(ContractDefinition const& _contractDef); Json generate(ContractDefinition const& _contractDef);
private: private:
/// Generates the JSON information for a variable and its storage location. /// 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 /// Generates the JSON information for @param _type
void generate(Type const* _type); void generate(Type const* _type);
@ -47,7 +47,7 @@ private:
/// The key for the JSON object describing a type. /// The key for the JSON object describing a type.
std::string typeKeyName(Type const* _type); std::string typeKeyName(Type const* _type);
Json::Value m_types; Json m_types;
/// Current analyzed contract /// Current analyzed contract
ContractDefinition const* m_contract = nullptr; ContractDefinition const* m_contract = nullptr;

View File

@ -32,7 +32,7 @@ using namespace solidity::langutil;
using namespace solidity::lsp; using namespace solidity::lsp;
using namespace std; using namespace std;
void GotoDefinition::operator()(MessageID _id, Json::Value const& _args) void GotoDefinition::operator()(MessageID _id, Json const& _args)
{ {
auto const [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args); auto const [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args);
@ -59,8 +59,8 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
locations.emplace_back(SourceLocation{0, 0, make_shared<string const>(path)}); locations.emplace_back(SourceLocation{0, 0, make_shared<string const>(path)});
} }
Json::Value reply = Json::arrayValue; Json reply = Json::array();
for (SourceLocation const& location: locations) for (SourceLocation const& location: locations)
reply.append(toJson(location)); reply.emplace_back(toJson(location));
client().reply(_id, reply); client().reply(_id, reply);
} }

View File

@ -25,7 +25,7 @@ class GotoDefinition: public HandlerBase
public: public:
explicit GotoDefinition(LanguageServer& _server): HandlerBase(_server) {} explicit GotoDefinition(LanguageServer& _server): HandlerBase(_server) {}
void operator()(MessageID, Json::Value const&); void operator()(MessageID, Json const&);
}; };
} }

View File

@ -31,7 +31,7 @@ using namespace solidity::lsp;
using namespace solidity::util; using namespace solidity::util;
using namespace std; using namespace std;
Json::Value HandlerBase::toRange(SourceLocation const& _location) const Json HandlerBase::toRange(SourceLocation const& _location) const
{ {
if (!_location.hasText()) if (!_location.hasText())
return toJsonRange({}, {}); return toJsonRange({}, {});
@ -43,18 +43,18 @@ Json::Value HandlerBase::toRange(SourceLocation const& _location) const
return toJsonRange(start, end); return toJsonRange(start, end);
} }
Json::Value HandlerBase::toJson(SourceLocation const& _location) const Json HandlerBase::toJson(SourceLocation const& _location) const
{ {
solAssert(_location.sourceName); solAssert(_location.sourceName);
Json::Value item = Json::objectValue; Json item = Json::object();
item["uri"] = fileRepository().sourceUnitNameToUri(*_location.sourceName); item["uri"] = fileRepository().sourceUnitNameToUri(*_location.sourceName);
item["range"] = toRange(_location); item["range"] = toRange(_location);
return item; return item;
} }
pair<string, LineColumn> HandlerBase::extractSourceUnitNameAndLineColumn(Json::Value const& _args) const pair<string, LineColumn> HandlerBase::extractSourceUnitNameAndLineColumn(Json const& _args) const
{ {
string const uri = _args["textDocument"]["uri"].asString(); string const uri = _args["textDocument"]["uri"].get<string>();
string const sourceUnitName = fileRepository().uriToSourceUnitName(uri); string const sourceUnitName = fileRepository().uriToSourceUnitName(uri);
if (!fileRepository().sourceUnits().count(sourceUnitName)) if (!fileRepository().sourceUnits().count(sourceUnitName))
BOOST_THROW_EXCEPTION( BOOST_THROW_EXCEPTION(

View File

@ -38,12 +38,12 @@ class HandlerBase
public: public:
explicit HandlerBase(LanguageServer& _server): m_server{_server} {} explicit HandlerBase(LanguageServer& _server): m_server{_server} {}
Json::Value toRange(langutil::SourceLocation const& _location) const; Json toRange(langutil::SourceLocation const& _location) const;
Json::Value toJson(langutil::SourceLocation const& _location) const; Json toJson(langutil::SourceLocation const& _location) const;
/// @returns source unit name and the line column position as extracted /// @returns source unit name and the line column position as extracted
/// from the JSON-RPC parameters. /// from the JSON-RPC parameters.
std::pair<std::string, langutil::LineColumn> extractSourceUnitNameAndLineColumn(Json::Value const& _params) const; std::pair<std::string, langutil::LineColumn> extractSourceUnitNameAndLineColumn(Json const& _params) const;
langutil::CharStreamProvider const& charStreamProvider() const noexcept { return m_server.compilerStack(); } langutil::CharStreamProvider const& charStreamProvider() const noexcept { return m_server.compilerStack(); }
FileRepository& fileRepository() const noexcept { return m_server.fileRepository(); } FileRepository& fileRepository() const noexcept { return m_server.fileRepository(); }

View File

@ -86,44 +86,44 @@ int toDiagnosticSeverity(Error::Type _errorType)
return -1; return -1;
} }
Json::Value semanticTokensLegend() Json semanticTokensLegend()
{ {
Json::Value legend = Json::objectValue; Json legend = Json::object();
// NOTE! The (alphabetical) order and items must match exactly the items of // NOTE! The (alphabetical) order and items must match exactly the items of
// their respective enum class members. // their respective enum class members.
Json::Value tokenTypes = Json::arrayValue; Json tokenTypes = Json::array();
tokenTypes.append("class"); tokenTypes.emplace_back("class");
tokenTypes.append("comment"); tokenTypes.emplace_back("comment");
tokenTypes.append("enum"); tokenTypes.emplace_back("enum");
tokenTypes.append("enumMember"); tokenTypes.emplace_back("enumMember");
tokenTypes.append("event"); tokenTypes.emplace_back("event");
tokenTypes.append("function"); tokenTypes.emplace_back("function");
tokenTypes.append("interface"); tokenTypes.emplace_back("interface");
tokenTypes.append("keyword"); tokenTypes.emplace_back("keyword");
tokenTypes.append("macro"); tokenTypes.emplace_back("macro");
tokenTypes.append("method"); tokenTypes.emplace_back("method");
tokenTypes.append("modifier"); tokenTypes.emplace_back("modifier");
tokenTypes.append("number"); tokenTypes.emplace_back("number");
tokenTypes.append("operator"); tokenTypes.emplace_back("operator");
tokenTypes.append("parameter"); tokenTypes.emplace_back("parameter");
tokenTypes.append("property"); tokenTypes.emplace_back("property");
tokenTypes.append("string"); tokenTypes.emplace_back("string");
tokenTypes.append("struct"); tokenTypes.emplace_back("struct");
tokenTypes.append("type"); tokenTypes.emplace_back("type");
tokenTypes.append("typeParameter"); tokenTypes.emplace_back("typeParameter");
tokenTypes.append("variable"); tokenTypes.emplace_back("variable");
legend["tokenTypes"] = tokenTypes; legend["tokenTypes"] = tokenTypes;
Json::Value tokenModifiers = Json::arrayValue; Json tokenModifiers = Json::array();
tokenModifiers.append("abstract"); tokenModifiers.emplace_back("abstract");
tokenModifiers.append("declaration"); tokenModifiers.emplace_back("declaration");
tokenModifiers.append("definition"); tokenModifiers.emplace_back("definition");
tokenModifiers.append("deprecated"); tokenModifiers.emplace_back("deprecated");
tokenModifiers.append("documentation"); tokenModifiers.emplace_back("documentation");
tokenModifiers.append("modification"); tokenModifiers.emplace_back("modification");
tokenModifiers.append("readonly"); tokenModifiers.emplace_back("readonly");
legend["tokenModifiers"] = tokenModifiers; legend["tokenModifiers"] = tokenModifiers;
return legend; return legend;
@ -139,7 +139,7 @@ LanguageServer::LanguageServer(Transport& _transport):
{"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }}, {"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }},
{"initialize", bind(&LanguageServer::handleInitialize, this, _1, _2)}, {"initialize", bind(&LanguageServer::handleInitialize, this, _1, _2)},
{"initialized", bind(&LanguageServer::handleInitialized, this, _1, _2)}, {"initialized", 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; }}, {"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }},
{"textDocument/definition", GotoDefinition(*this) }, {"textDocument/definition", GotoDefinition(*this) },
{"textDocument/didOpen", bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)}, {"textDocument/didOpen", bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)},
@ -156,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); return HandlerBase(*this).toRange(_location);
} }
Json::Value LanguageServer::toJson(SourceLocation const& _location) Json LanguageServer::toJson(SourceLocation const& _location)
{ {
return HandlerBase(*this).toJson(_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. // 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. // It can be overridden during client's handshake or at runtime, as usual.
@ -179,7 +179,7 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings)
// those files being imported directly or indirectly will be included in operations. // those files being imported directly or indirectly will be included in operations.
if (_settings["file-load-strategy"]) if (_settings["file-load-strategy"])
{ {
auto const text = _settings["file-load-strategy"].asString(); auto const text = _settings["file-load-strategy"].get<string>();
if (text == "project-directory") if (text == "project-directory")
m_fileLoadStrategy = FileLoadStrategy::ProjectDirectory; m_fileLoadStrategy = FileLoadStrategy::ProjectDirectory;
else if (text == "directly-opened-and-on-import") else if (text == "directly-opened-and-on-import")
@ -189,18 +189,18 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings)
} }
m_settingsObject = _settings; m_settingsObject = _settings;
Json::Value jsonIncludePaths = _settings["include-paths"]; Json jsonIncludePaths = _settings["include-paths"];
if (jsonIncludePaths) if (jsonIncludePaths)
{ {
int typeFailureCount = 0; int typeFailureCount = 0;
if (jsonIncludePaths.isArray()) if (jsonIncludePaths.is_array())
{ {
vector<boost::filesystem::path> includePaths; vector<boost::filesystem::path> includePaths;
for (Json::Value const& jsonPath: jsonIncludePaths) for (Json const& jsonPath: jsonIncludePaths)
{ {
if (jsonPath.isString()) if (jsonPath.is_string())
includePaths.emplace_back(boost::filesystem::path(jsonPath.asString())); includePaths.emplace_back(boost::filesystem::path(jsonPath.get<string>()));
else else
typeFailureCount++; typeFailureCount++;
} }
@ -271,11 +271,11 @@ void LanguageServer::compileAndUpdateDiagnostics()
// These are the source units we will sent diagnostics to the client for sure, // These are the source units we will sent diagnostics to the client for sure,
// even if it is just to clear previous diagnostics. // even if it is just to clear previous diagnostics.
map<string, Json::Value> diagnosticsBySourceUnit; map<string, Json> diagnosticsBySourceUnit;
for (string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys) for (string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys)
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; diagnosticsBySourceUnit[sourceUnitName] = Json::array();
for (string const& sourceUnitName: m_nonemptyDiagnostics) for (string const& sourceUnitName: m_nonemptyDiagnostics)
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; diagnosticsBySourceUnit[sourceUnitName] = Json::array();
for (shared_ptr<Error const> const& error: m_compilerStack.errors()) for (shared_ptr<Error const> const& error: m_compilerStack.errors())
{ {
@ -284,10 +284,10 @@ void LanguageServer::compileAndUpdateDiagnostics()
// LSP only has diagnostics applied to individual files. // LSP only has diagnostics applied to individual files.
continue; continue;
Json::Value jsonDiag; Json jsonDiag;
jsonDiag["source"] = "solc"; jsonDiag["source"] = "solc";
jsonDiag["severity"] = toDiagnosticSeverity(error->type()); jsonDiag["severity"] = toDiagnosticSeverity(error->type());
jsonDiag["code"] = Json::UInt64{error->errorId().error}; jsonDiag["code"] = Json{error->errorId().error};
string message = Error::formatErrorType(error->type()) + ":"; string message = Error::formatErrorType(error->type()) + ":";
if (string const* comment = error->comment()) if (string const* comment = error->comment())
message += " " + *comment; message += " " + *comment;
@ -297,26 +297,26 @@ void LanguageServer::compileAndUpdateDiagnostics()
if (auto const* secondary = error->secondarySourceLocation()) if (auto const* secondary = error->secondarySourceLocation())
for (auto&& [secondaryMessage, secondaryLocation]: secondary->infos) for (auto&& [secondaryMessage, secondaryLocation]: secondary->infos)
{ {
Json::Value jsonRelated; Json jsonRelated;
jsonRelated["message"] = secondaryMessage; jsonRelated["message"] = secondaryMessage;
jsonRelated["location"] = toJson(secondaryLocation); 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) if (m_client.traceValue() != TraceValue::Off)
{ {
Json::Value extra; Json extra;
extra["openFileCount"] = Json::UInt64(diagnosticsBySourceUnit.size()); extra["openFileCount"] = Json{diagnosticsBySourceUnit.size()};
m_client.trace("Number of currently open files: " + to_string(diagnosticsBySourceUnit.size()), extra); m_client.trace("Number of currently open files: " + to_string(diagnosticsBySourceUnit.size()), extra);
} }
m_nonemptyDiagnostics.clear(); m_nonemptyDiagnostics.clear();
for (auto&& [sourceUnitName, diagnostics]: diagnosticsBySourceUnit) for (auto&& [sourceUnitName, diagnostics]: diagnosticsBySourceUnit)
{ {
Json::Value params; Json params;
params["uri"] = m_fileRepository.sourceUnitNameToUri(sourceUnitName); params["uri"] = m_fileRepository.sourceUnitNameToUri(sourceUnitName);
if (!diagnostics.empty()) if (!diagnostics.empty())
m_nonemptyDiagnostics.insert(sourceUnitName); m_nonemptyDiagnostics.insert(sourceUnitName);
@ -332,13 +332,13 @@ bool LanguageServer::run()
MessageID id; MessageID id;
try try
{ {
optional<Json::Value> const jsonMessage = m_client.receive(); optional<Json> const jsonMessage = m_client.receive();
if (!jsonMessage) if (!jsonMessage)
continue; continue;
if ((*jsonMessage)["method"].isString()) if ((*jsonMessage)["method"].is_string())
{ {
string const methodName = (*jsonMessage)["method"].asString(); string const methodName = (*jsonMessage)["method"].get<string>();
id = (*jsonMessage)["id"]; id = (*jsonMessage)["id"];
lspDebug(fmt::format("received method call: {}", methodName)); lspDebug(fmt::format("received method call: {}", methodName));
@ -350,7 +350,7 @@ bool LanguageServer::run()
else else
m_client.error({}, ErrorCode::ParseError, "\"method\" has to be a string."); 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); m_client.error(id, ErrorCode::InvalidParams, "JSON object access error. Most likely due to a badly formatted JSON request message."s);
} }
@ -375,7 +375,7 @@ void LanguageServer::requireServerInitialized()
); );
} }
void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) void LanguageServer::handleInitialize(MessageID _id, Json const& _args)
{ {
lspRequire( lspRequire(
m_state == State::Started, m_state == State::Started,
@ -388,9 +388,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 // The default of FileReader is to use `.`, but the path from where the LSP was started
// should not matter. // should not matter.
string rootPath("/"); string rootPath("/");
if (Json::Value uri = _args["rootUri"]) if (Json uri = _args["rootUri"])
{ {
rootPath = uri.asString(); rootPath = uri.get<string>();
lspRequire( lspRequire(
boost::starts_with(rootPath, "file://"), boost::starts_with(rootPath, "file://"),
ErrorCode::InvalidParams, ErrorCode::InvalidParams,
@ -398,17 +398,17 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
); );
rootPath = stripFileUriSchemePrefix(rootPath); rootPath = stripFileUriSchemePrefix(rootPath);
} }
else if (Json::Value rootPath = _args["rootPath"]) else if (Json rootPath = _args["rootPath"])
rootPath = rootPath.asString(); rootPath = rootPath.get<string>();
if (_args["trace"]) if (_args["trace"])
setTrace(_args["trace"]); setTrace(_args["trace"]);
m_fileRepository = FileRepository(rootPath, {}); m_fileRepository = FileRepository(rootPath, {});
if (_args["initializationOptions"].isObject()) if (_args["initializationOptions"].is_object())
changeConfiguration(_args["initializationOptions"]); changeConfiguration(_args["initializationOptions"]);
Json::Value replyArgs; Json replyArgs;
replyArgs["serverInfo"]["name"] = "solc"; replyArgs["serverInfo"]["name"] = "solc";
replyArgs["serverInfo"]["version"] = string(VersionNumber); replyArgs["serverInfo"]["version"] = string(VersionNumber);
replyArgs["capabilities"]["definitionProvider"] = true; replyArgs["capabilities"]["definitionProvider"] = true;
@ -424,44 +424,44 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
m_client.reply(_id, std::move(replyArgs)); 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) if (m_fileLoadStrategy == FileLoadStrategy::ProjectDirectory)
compileAndUpdateDiagnostics(); compileAndUpdateDiagnostics();
} }
void LanguageServer::semanticTokensFull(MessageID _id, Json::Value const& _args) void LanguageServer::semanticTokensFull(MessageID _id, Json const& _args)
{ {
auto uri = _args["textDocument"]["uri"]; auto uri = _args["textDocument"]["uri"];
compile(); compile();
auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as<string>()); auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.get<string>());
SourceUnit const& ast = m_compilerStack.ast(sourceName); SourceUnit const& ast = m_compilerStack.ast(sourceName);
m_compilerStack.charStream(sourceName); m_compilerStack.charStream(sourceName);
Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName)); Json data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName));
Json::Value reply = Json::objectValue; Json reply = Json::object();
reply["data"] = data; reply["data"] = data;
m_client.reply(_id, std::move(reply)); m_client.reply(_id, std::move(reply));
} }
void LanguageServer::handleWorkspaceDidChangeConfiguration(Json::Value const& _args) void LanguageServer::handleWorkspaceDidChangeConfiguration(Json const& _args)
{ {
requireServerInitialized(); requireServerInitialized();
if (_args["settings"].isObject()) if (_args["settings"].is_object())
changeConfiguration(_args["settings"]); 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. // Simply ignore invalid parameter.
return; return;
string const stringValue = _args.asString(); string const stringValue = _args.get<string>();
if (stringValue == "off") if (stringValue == "off")
m_client.setTrace(TraceValue::Off); m_client.setTrace(TraceValue::Off);
else if (stringValue == "messages") else if (stringValue == "messages")
@ -470,7 +470,7 @@ void LanguageServer::setTrace(Json::Value const& _args)
m_client.setTrace(TraceValue::Verbose); m_client.setTrace(TraceValue::Verbose);
} }
void LanguageServer::handleTextDocumentDidOpen(Json::Value const& _args) void LanguageServer::handleTextDocumentDidOpen(Json const& _args)
{ {
requireServerInitialized(); requireServerInitialized();
@ -480,23 +480,23 @@ void LanguageServer::handleTextDocumentDidOpen(Json::Value const& _args)
"Text document parameter missing." "Text document parameter missing."
); );
string text = _args["textDocument"]["text"].asString(); string text = _args["textDocument"]["text"].get<string>();
string uri = _args["textDocument"]["uri"].asString(); string uri = _args["textDocument"]["uri"].get<string>();
m_openFiles.insert(uri); m_openFiles.insert(uri);
m_fileRepository.setSourceByUri(uri, std::move(text)); m_fileRepository.setSourceByUri(uri, std::move(text));
compileAndUpdateDiagnostics(); compileAndUpdateDiagnostics();
} }
void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args) void LanguageServer::handleTextDocumentDidChange(Json const& _args)
{ {
requireServerInitialized(); requireServerInitialized();
string const uri = _args["textDocument"]["uri"].asString(); string const uri = _args["textDocument"]["uri"].get<string>();
for (Json::Value jsonContentChange: _args["contentChanges"]) for (Json jsonContentChange: _args["contentChanges"])
{ {
lspRequire( lspRequire(
jsonContentChange.isObject(), jsonContentChange.is_object(),
ErrorCode::RequestFailed, ErrorCode::RequestFailed,
"Invalid content reference." "Invalid content reference."
); );
@ -508,8 +508,8 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
"Unknown file: " + uri "Unknown file: " + uri
); );
string text = jsonContentChange["text"].asString(); string text = jsonContentChange["text"].get<string>();
if (jsonContentChange["range"].isObject()) // otherwise full content update if (jsonContentChange["range"].is_object()) // otherwise full content update
{ {
optional<SourceLocation> change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]); optional<SourceLocation> change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]);
lspRequire( lspRequire(
@ -528,7 +528,7 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
compileAndUpdateDiagnostics(); compileAndUpdateDiagnostics();
} }
void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args) void LanguageServer::handleTextDocumentDidClose(Json const& _args)
{ {
requireServerInitialized(); requireServerInitialized();
@ -538,7 +538,7 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
"Text document parameter missing." "Text document parameter missing."
); );
string uri = _args["textDocument"]["uri"].asString(); string uri = _args["textDocument"]["uri"].get<string>();
m_openFiles.erase(uri); m_openFiles.erase(uri);
compileAndUpdateDiagnostics(); compileAndUpdateDiagnostics();

View File

@ -22,7 +22,7 @@
#include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/CompilerStack.h>
#include <libsolidity/interface/FileReader.h> #include <libsolidity/interface/FileReader.h>
#include <json/value.h> #include <libsolutil/JSON.h>
#include <functional> #include <functional>
#include <map> #include <map>
@ -85,29 +85,29 @@ private:
/// Checks if the server is initialized (to be used by messages that need it to be initialized). /// 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. /// Reports an error and returns false if not.
void requireServerInitialized(); void requireServerInitialized();
void handleInitialize(MessageID _id, Json::Value const& _args); void handleInitialize(MessageID _id, Json const& _args);
void handleInitialized(MessageID _id, Json::Value const& _args); void handleInitialized(MessageID _id, Json const& _args);
void handleWorkspaceDidChangeConfiguration(Json::Value const& _args); void handleWorkspaceDidChangeConfiguration(Json const& _args);
void setTrace(Json::Value const& _args); void setTrace(Json const& _args);
void handleTextDocumentDidOpen(Json::Value const& _args); void handleTextDocumentDidOpen(Json const& _args);
void handleTextDocumentDidChange(Json::Value const& _args); void handleTextDocumentDidChange(Json const& _args);
void handleTextDocumentDidClose(Json::Value const& _args); void handleTextDocumentDidClose(Json const& _args);
void handleRename(Json::Value const& _args); void handleRename(Json const& _args);
void handleGotoDefinition(MessageID _id, Json::Value const& _args); void handleGotoDefinition(MessageID _id, Json const& _args);
void semanticTokensFull(MessageID _id, Json::Value const& _args); void semanticTokensFull(MessageID _id, Json const& _args);
/// Invoked when the server user-supplied configuration changes (initiated by the client). /// 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. /// Compile everything until after analysis phase.
void compile(); void compile();
std::vector<boost::filesystem::path> allSolidityFilesFromProject() const; std::vector<boost::filesystem::path> allSolidityFilesFromProject() const;
using MessageHandler = std::function<void(MessageID, Json::Value const&)>; using MessageHandler = std::function<void(MessageID, Json const&)>;
Json::Value toRange(langutil::SourceLocation const& _location); Json toRange(langutil::SourceLocation const& _location);
Json::Value toJson(langutil::SourceLocation const& _location); Json toJson(langutil::SourceLocation const& _location);
// LSP related member fields // LSP related member fields
@ -127,7 +127,7 @@ private:
frontend::CompilerStack m_compilerStack; frontend::CompilerStack m_compilerStack;
/// User-supplied custom configuration settings (such as EVM version). /// User-supplied custom configuration settings (such as EVM version).
Json::Value m_settingsObject; Json m_settingsObject;
}; };
} }

View File

@ -48,11 +48,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); auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args);
string const newName = _args["newName"].asString(); string const newName = _args["newName"].get<string>();
string const uri = _args["textDocument"]["uri"].asString(); string const uri = _args["textDocument"]["uri"].get<string>();
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn); ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
@ -91,10 +91,10 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
// Apply changes in reverse order (will iterate in reverse) // Apply changes in reverse order (will iterate in reverse)
sort(m_locations.begin(), m_locations.end()); sort(m_locations.begin(), m_locations.end());
Json::Value reply = Json::objectValue; Json reply = Json::object();
reply["changes"] = Json::objectValue; reply["changes"] = Json::object();
Json::Value edits = Json::arrayValue; Json edits = Json::array();
for (auto i = m_locations.rbegin(); i != m_locations.rend(); i++) for (auto i = m_locations.rbegin(); i != m_locations.rend(); i++)
{ {
@ -106,16 +106,16 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName); buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName);
fileRepository().setSourceByUri(uri, std::move(buffer)); fileRepository().setSourceByUri(uri, std::move(buffer));
Json::Value edit = Json::objectValue; Json edit = Json::object();
edit["range"] = toRange(*i); edit["range"] = toRange(*i);
edit["newText"] = newName; edit["newText"] = newName;
// Record changes for the client // Record changes for the client
edits.append(edit); edits.emplace_back(edit);
if (i + 1 == m_locations.rend() || (i + 1)->sourceName != i->sourceName) if (i + 1 == m_locations.rend() || (i + 1)->sourceName != i->sourceName)
{ {
reply["changes"][uri] = edits; reply["changes"][uri] = edits;
edits = Json::arrayValue; edits = Json::array();
} }
} }

View File

@ -27,7 +27,7 @@ class RenameSymbol: public HandlerBase
public: public:
explicit RenameSymbol(LanguageServer& _server): HandlerBase(_server) {} explicit RenameSymbol(LanguageServer& _server): HandlerBase(_server) {}
void operator()(MessageID, Json::Value const&); void operator()(MessageID, Json const&);
protected: protected:
// Nested class because otherwise `RenameSymbol` couldn't be easily used // Nested class because otherwise `RenameSymbol` couldn't be easily used
// with LanguageServer::m_handlers as `ASTConstVisitor` deletes required // with LanguageServer::m_handlers as `ASTConstVisitor` deletes required

View File

@ -71,7 +71,7 @@ SemanticTokenType semanticTokenTypeForExpression(frontend::Type const* _type)
} // end namespace } // end namespace
Json::Value SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStream const& _charStream) Json SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStream const& _charStream)
{ {
reset(&_charStream); reset(&_charStream);
_sourceUnit.accept(*this); _sourceUnit.accept(*this);
@ -80,7 +80,7 @@ Json::Value SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStre
void SemanticTokensBuilder::reset(CharStream const* _charStream) void SemanticTokensBuilder::reset(CharStream const* _charStream)
{ {
m_encodedTokens = Json::arrayValue; m_encodedTokens = Json::array();
m_charStream = _charStream; m_charStream = _charStream;
m_lastLine = 0; m_lastLine = 0;
m_lastStartChar = 0; m_lastStartChar = 0;
@ -121,14 +121,14 @@ void SemanticTokensBuilder::encode(
lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, _tokenType)); lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, _tokenType));
m_encodedTokens.append(line - m_lastLine); m_encodedTokens.emplace_back(line - m_lastLine);
if (line == m_lastLine) if (line == m_lastLine)
m_encodedTokens.append(startChar - m_lastStartChar); m_encodedTokens.emplace_back(startChar - m_lastStartChar);
else else
m_encodedTokens.append(startChar); m_encodedTokens.emplace_back(startChar);
m_encodedTokens.append(length); m_encodedTokens.emplace_back(length);
m_encodedTokens.append(static_cast<int>(_tokenType)); m_encodedTokens.emplace_back(static_cast<int>(_tokenType));
m_encodedTokens.append(static_cast<int>(_modifiers)); m_encodedTokens.emplace_back(static_cast<int>(_modifiers));
m_lastLine = line; m_lastLine = line;
m_lastStartChar = startChar; m_lastStartChar = startChar;

View File

@ -17,7 +17,8 @@
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
#include <libsolidity/ast/AST.h> #include <libsolidity/ast/AST.h>
#include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/ast/ASTVisitor.h>
#include <json/json.h>
#include <libsolutil/JSON.h>
#include <fmt/format.h> #include <fmt/format.h>
@ -87,7 +88,7 @@ constexpr SemanticTokenModifiers operator|(SemanticTokenModifiers a, SemanticTok
class SemanticTokensBuilder: public frontend::ASTConstVisitor class SemanticTokensBuilder: public frontend::ASTConstVisitor
{ {
public: 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 reset(langutil::CharStream const* _charStream);
void encode( void encode(
@ -114,7 +115,7 @@ public:
bool visit(frontend::VariableDeclaration const&) override; bool visit(frontend::VariableDeclaration const&) override;
private: private:
Json::Value m_encodedTokens; Json m_encodedTokens;
langutil::CharStream const* m_charStream; langutil::CharStream const* m_charStream;
int m_lastLine; int m_lastLine;
int m_lastStartChar; int m_lastStartChar;

View File

@ -41,7 +41,7 @@ using namespace std;
using namespace solidity::lsp; using namespace solidity::lsp;
// {{{ Transport // {{{ Transport
optional<Json::Value> Transport::receive() optional<Json> Transport::receive()
{ {
auto const headers = parseHeaders(); auto const headers = parseHeaders();
if (!headers) if (!headers)
@ -58,10 +58,10 @@ optional<Json::Value> Transport::receive()
string const data = readBytes(stoul(headers->at("content-length"))); string const data = readBytes(stoul(headers->at("content-length")));
Json::Value jsonMessage; Json jsonMessage;
string jsonParsingErrors; string jsonParsingErrors;
solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors); solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors);
if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject()) if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.is_object())
{ {
error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors); error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors);
return nullopt; return nullopt;
@ -70,12 +70,12 @@ optional<Json::Value> Transport::receive()
return {std::move(jsonMessage)}; 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) if (m_logTrace != TraceValue::Off)
{ {
Json::Value params; Json params;
if (_extra.isObject()) if (_extra.is_object())
params = std::move(_extra); params = std::move(_extra);
params["message"] = std::move(_message); params["message"] = std::move(_message);
notify("$/logTrace", std::move(params)); notify("$/logTrace", std::move(params));
@ -104,34 +104,34 @@ optional<map<string, string>> Transport::parseHeaders()
return {std::move(headers)}; return {std::move(headers)};
} }
void Transport::notify(string _method, Json::Value _message) void Transport::notify(string _method, Json _message)
{ {
Json::Value json; Json json;
json["method"] = std::move(_method); json["method"] = std::move(_method);
json["params"] = std::move(_message); json["params"] = std::move(_message);
send(std::move(json)); 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); json["result"] = std::move(_message);
send(std::move(json), _id); send(std::move(json), _id);
} }
void Transport::error(MessageID _id, ErrorCode _code, string _message) void Transport::error(MessageID _id, ErrorCode _code, string _message)
{ {
Json::Value json; Json json;
json["error"]["code"] = static_cast<int>(_code); json["error"]["code"] = static_cast<int>(_code);
json["error"]["message"] = std::move(_message); json["error"]["message"] = std::move(_message);
send(std::move(json), _id); 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"; _json["jsonrpc"] = "2.0";
if (_id != Json::nullValue) if (_id != Json{})
_json["id"] = _id; _json["id"] = _id;
// Trailing CRLF only for easier readability. // Trailing CRLF only for easier readability.

View File

@ -19,7 +19,7 @@
#include <libsolutil/Exceptions.h> #include <libsolutil/Exceptions.h>
#include <json/value.h> #include <libsolutil/JSON.h>
#include <functional> #include <functional>
#include <iosfwd> #include <iosfwd>
@ -32,7 +32,7 @@
namespace solidity::lsp namespace solidity::lsp
{ {
using MessageID = Json::Value; using MessageID = nlohmann::json;
enum class TraceValue enum class TraceValue
{ {
@ -98,14 +98,14 @@ class Transport
public: public:
virtual ~Transport() = default; virtual ~Transport() = default;
std::optional<Json::Value> receive(); std::optional<Json> receive();
void notify(std::string _method, Json::Value _params); void notify(std::string _method, Json _params);
void reply(MessageID _id, Json::Value _result); void reply(MessageID _id, Json _result);
void error(MessageID _id, ErrorCode _code, std::string _message); void error(MessageID _id, ErrorCode _code, std::string _message);
virtual bool closed() const noexcept = 0; 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; } TraceValue traceValue() const noexcept { return m_logTrace; }
void setTrace(TraceValue _value) noexcept { m_logTrace = _value; } void setTrace(TraceValue _value) noexcept { m_logTrace = _value; }
@ -135,7 +135,7 @@ protected:
/// Sends an arbitrary raw message to the client. /// Sends an arbitrary raw message to the client.
/// ///
/// Used by the notify/reply/error function family. /// 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{});
}; };
/** /**

View File

@ -32,26 +32,26 @@ using namespace frontend;
using namespace langutil; using namespace langutil;
using namespace std; using namespace std;
optional<LineColumn> parseLineColumn(Json::Value const& _lineColumn) optional<LineColumn> parseLineColumn(Json const& _lineColumn)
{ {
if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt()) if (_lineColumn.is_object() && _lineColumn["line"].is_number_integer() && _lineColumn["character"].is_number_integer())
return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()}; return LineColumn{_lineColumn["line"].get<int>(), _lineColumn["character"].get<int>()};
else else
return nullopt; return nullopt;
} }
Json::Value toJson(LineColumn const& _pos) Json toJson(LineColumn const& _pos)
{ {
Json::Value json = Json::objectValue; Json json = Json::object();
json["line"] = max(_pos.line, 0); json["line"] = max(_pos.line, 0);
json["character"] = max(_pos.column, 0); json["character"] = max(_pos.column, 0);
return json; 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["start"] = toJson(_start);
json["end"] = toJson(_end); json["end"] = toJson(_end);
return json; return json;
@ -87,7 +87,7 @@ optional<SourceLocation> declarationLocation(Declaration const* _declaration)
optional<SourceLocation> parsePosition( optional<SourceLocation> parsePosition(
FileRepository const& _fileRepository, FileRepository const& _fileRepository,
string const& _sourceUnitName, string const& _sourceUnitName,
Json::Value const& _position Json const& _position
) )
{ {
if (!_fileRepository.sourceUnits().count(_sourceUnitName)) if (!_fileRepository.sourceUnits().count(_sourceUnitName))
@ -102,9 +102,9 @@ optional<SourceLocation> parsePosition(
return nullopt; return nullopt;
} }
optional<SourceLocation> parseRange(FileRepository const& _fileRepository, string const& _sourceUnitName, Json::Value const& _range) optional<SourceLocation> parseRange(FileRepository const& _fileRepository, string const& _sourceUnitName, Json const& _range)
{ {
if (!_range.isObject()) if (!_range.is_object())
return nullopt; return nullopt;
optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]); optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]);
optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]); optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]);

View File

@ -44,16 +44,16 @@ namespace solidity::lsp
class FileRepository; class FileRepository;
std::optional<langutil::LineColumn> parseLineColumn(Json::Value const& _lineColumn); std::optional<langutil::LineColumn> parseLineColumn(Json const& _lineColumn);
Json::Value toJson(langutil::LineColumn const& _pos); Json toJson(langutil::LineColumn const& _pos);
Json::Value toJsonRange(langutil::LineColumn const& _start, langutil::LineColumn const& _end); Json toJsonRange(langutil::LineColumn const& _start, langutil::LineColumn const& _end);
/// @returns the source location given a source unit name and an LSP Range object, /// @returns the source location given a source unit name and an LSP Range object,
/// or nullopt on failure. /// or nullopt on failure.
std::optional<langutil::SourceLocation> parsePosition( std::optional<langutil::SourceLocation> parsePosition(
FileRepository const& _fileRepository, FileRepository const& _fileRepository,
std::string const& _sourceUnitName, 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, /// @returns the source location given a source unit name and an LSP Range object,
@ -61,7 +61,7 @@ std::optional<langutil::SourceLocation> parsePosition(
std::optional<langutil::SourceLocation> parseRange( std::optional<langutil::SourceLocation> parseRange(
FileRepository const& _fileRepository, FileRepository const& _fileRepository,
std::string const& _sourceUnitName, std::string const& _sourceUnitName,
Json::Value const& _range Json const& _range
); );
/// Strips the file:// URI prefix off the given path, if present, /// Strips the file:// URI prefix off the given path, if present,

View File

@ -43,7 +43,7 @@ set(sources
) )
add_library(solutil ${sources}) add_library(solutil ${sources})
target_link_libraries(solutil PUBLIC jsoncpp Boost::boost Boost::filesystem Boost::system range-v3) target_link_libraries(solutil PUBLIC Boost::boost Boost::filesystem Boost::system range-v3)
target_include_directories(solutil PUBLIC "${CMAKE_SOURCE_DIR}") target_include_directories(solutil PUBLIC "${CMAKE_SOURCE_DIR}")
add_dependencies(solutil solidity_BuildInfo.h) add_dependencies(solutil solidity_BuildInfo.h)

View File

@ -33,8 +33,8 @@
using namespace std; using namespace std;
static_assert( static_assert(
(JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 3), (NLOHMANN_JSON_VERSION_MAJOR == 3) && (NLOHMANN_JSON_VERSION_MINOR == 10) && (NLOHMANN_JSON_VERSION_PATCH == 2),
"Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.3." "Unexpected nlohmann-json version. Expecting 3.10.2."
); );
namespace solidity::util namespace solidity::util
@ -43,53 +43,9 @@ namespace solidity::util
namespace namespace
{ {
/// StreamWriterBuilder that can be constructed with specific settings #if 0
class StreamWriterBuilder: public Json::StreamWriterBuilder
{
public:
explicit StreamWriterBuilder(map<string, Json::Value> const& _settings)
{
for (auto const& iter: _settings)
this->settings_[iter.first] = iter.second;
}
};
/// CharReaderBuilder with strict-mode settings
class StrictModeCharReaderBuilder: public Json::CharReaderBuilder
{
public:
StrictModeCharReaderBuilder()
{
Json::CharReaderBuilder::strictMode(&this->settings_);
}
};
/// 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
string print(Json::Value const& _input, Json::StreamWriterBuilder const& _builder)
{
stringstream stream;
unique_ptr<Json::StreamWriter> writer(_builder.newStreamWriter());
writer->write(_input, &stream);
return stream.str();
}
/// 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, string const& _input, Json::Value& _json, string* _errs)
{
unique_ptr<Json::CharReader> reader(_builder.newCharReader());
return reader->parse(_input.c_str(), _input.c_str() + _input.length(), &_json, _errs);
}
/// Takes a JSON value (@ _json) and removes all its members with value 'null' recursively. /// Takes a JSON value (@ _json) and removes all its members with value 'null' recursively.
void removeNullMembersHelper(Json::Value& _json) void removeNullMembersHelper(Json& _json)
{ {
if (_json.type() == Json::ValueType::arrayValue) if (_json.type() == Json::ValueType::arrayValue)
for (auto& child: _json) for (auto& child: _json)
@ -104,46 +60,54 @@ void removeNullMembersHelper(Json::Value& _json)
removeNullMembersHelper(value); removeNullMembersHelper(value);
} }
} }
#endif
} // end anonymous namespace } // end anonymous namespace
Json::Value removeNullMembers(Json::Value _json) Json removeNullMembers(Json _json)
{ {
removeNullMembersHelper(_json); // TODO: Support this.
// removeNullMembersHelper(_json);
return _json; return _json;
} }
string jsonPrettyPrint(Json::Value const& _input) string jsonPrettyPrint(Json const& _input)
{ {
return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty }); return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty });
} }
string jsonCompactPrint(Json::Value const& _input) string jsonCompactPrint(Json const& _input)
{ {
return jsonPrint(_input, JsonFormat{ JsonFormat::Compact }); return jsonPrint(_input, JsonFormat{ JsonFormat::Compact });
} }
string jsonPrint(Json::Value const& _input, JsonFormat const& _format) string jsonPrint(Json const& _input, JsonFormat const& _format)
{ {
map<string, Json::Value> settings; // NOTE: -1 here means no new lines (it is also the default setting)
if (_format.format == JsonFormat::Pretty) return _input.dump(
{ /* indent */ (_format.format == JsonFormat::Pretty) ? static_cast<int>(_format.indent) : -1,
settings["indentation"] = string(_format.indent, ' '); /* indent_char */ ' ',
settings["enableYAMLCompatibility"] = true; /* ensure_ascii */ true
} );
else
settings["indentation"] = "";
StreamWriterBuilder writerBuilder(settings);
string result = print(_input, writerBuilder);
if (_format.format == JsonFormat::Pretty)
boost::replace_all(result, " \n", "\n");
return result;
} }
bool jsonParseStrict(string const& _input, Json::Value& _json, string* _errs /* = nullptr */) bool jsonParseStrict(string const& _input, Json& _json, string* _errs /* = nullptr */)
{ {
static StrictModeCharReaderBuilder readerBuilder; try
return parse(readerBuilder, _input, _json, _errs); {
_json = Json::parse(_input);
_errs = {};
return true;
}
catch (Json::parse_error const& e)
{
// NOTE: e.id() gives the code and e.byte() gives the byte offset
if (_errs)
{
*_errs = e.what();
}
return false;
}
} }
} // namespace solidity::util } // namespace solidity::util

View File

@ -23,15 +23,17 @@
#pragma once #pragma once
#include <json/json.h> #include <json/json.hpp>
#include <string> #include <string>
using Json = nlohmann::json;
namespace solidity::util namespace solidity::util
{ {
/// Removes members with null value recursively from (@a _json). /// Removes members with null value recursively from (@a _json).
Json::Value removeNullMembers(Json::Value _json); Json removeNullMembers(Json _json);
/// JSON printing format. /// JSON printing format.
struct JsonFormat struct JsonFormat
@ -52,20 +54,20 @@ struct JsonFormat
}; };
/// Serialise the JSON object (@a _input) with indentation /// 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 /// 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) /// 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) /// Parse a JSON string (@a _input) with enabled strict-mode and writes resulting JSON object to (@a _json)
/// \param _input JSON input string /// \param _input JSON input string
/// \param _json [out] resulting JSON object /// \param _json [out] resulting JSON object
/// \param _errs [out] Formatted error messages /// \param _errs [out] Formatted error messages
/// \return \c true if the document was successfully parsed, \c false if an error occurred. /// \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);
namespace detail namespace detail
{ {

View File

@ -31,25 +31,25 @@ using namespace std;
namespace solidity::yul namespace solidity::yul
{ {
Json::Value AsmJsonConverter::operator()(Block const& _node) const Json AsmJsonConverter::operator()(Block const& _node) const
{ {
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulBlock"); Json ret = createAstNode(nativeLocationOf(_node), "YulBlock");
ret["statements"] = vectorOfVariantsToJson(_node.statements); ret["statements"] = vectorOfVariantsToJson(_node.statements);
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(TypedName const& _node) const Json AsmJsonConverter::operator()(TypedName const& _node) const
{ {
yulAssert(!_node.name.empty(), "Invalid variable name."); yulAssert(!_node.name.empty(), "Invalid variable name.");
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulTypedName"); Json ret = createAstNode(nativeLocationOf(_node), "YulTypedName");
ret["name"] = _node.name.str(); ret["name"] = _node.name.str();
ret["type"] = _node.type.str(); ret["type"] = _node.type.str();
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(Literal const& _node) const Json AsmJsonConverter::operator()(Literal const& _node) const
{ {
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulLiteral"); Json ret = createAstNode(nativeLocationOf(_node), "YulLiteral");
switch (_node.kind) switch (_node.kind)
{ {
case LiteralKind::Number: case LiteralKind::Number:
@ -73,94 +73,92 @@ Json::Value AsmJsonConverter::operator()(Literal const& _node) const
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(Identifier const& _node) const Json AsmJsonConverter::operator()(Identifier const& _node) const
{ {
yulAssert(!_node.name.empty(), "Invalid identifier"); yulAssert(!_node.name.empty(), "Invalid identifier");
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulIdentifier"); Json ret = createAstNode(nativeLocationOf(_node), "YulIdentifier");
ret["name"] = _node.name.str(); ret["name"] = _node.name.str();
return ret; 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"); yulAssert(_node.variableNames.size() >= 1, "Invalid assignment syntax");
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulAssignment"); Json ret = createAstNode(nativeLocationOf(_node), "YulAssignment");
for (auto const& var: _node.variableNames) for (auto const& var: _node.variableNames)
ret["variableNames"].append((*this)(var)); ret["variableNames"].emplace_back((*this)(var));
ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue; ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json{};
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const Json AsmJsonConverter::operator()(FunctionCall const& _node) const
{ {
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulFunctionCall"); Json ret = createAstNode(nativeLocationOf(_node), "YulFunctionCall");
ret["functionName"] = (*this)(_node.functionName); ret["functionName"] = (*this)(_node.functionName);
ret["arguments"] = vectorOfVariantsToJson(_node.arguments); ret["arguments"] = vectorOfVariantsToJson(_node.arguments);
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(ExpressionStatement const& _node) const Json AsmJsonConverter::operator()(ExpressionStatement const& _node) const
{ {
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulExpressionStatement"); Json ret = createAstNode(nativeLocationOf(_node), "YulExpressionStatement");
ret["expression"] = std::visit(*this, _node.expression); ret["expression"] = std::visit(*this, _node.expression);
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(VariableDeclaration const& _node) const Json AsmJsonConverter::operator()(VariableDeclaration const& _node) const
{ {
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulVariableDeclaration"); Json ret = createAstNode(nativeLocationOf(_node), "YulVariableDeclaration");
for (auto const& var: _node.variables) for (auto const& var: _node.variables)
ret["variables"].append((*this)(var)); ret["variables"].emplace_back((*this)(var));
ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json{};
ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue;
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(FunctionDefinition const& _node) const Json AsmJsonConverter::operator()(FunctionDefinition const& _node) const
{ {
yulAssert(!_node.name.empty(), "Invalid function name."); yulAssert(!_node.name.empty(), "Invalid function name.");
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulFunctionDefinition"); Json ret = createAstNode(nativeLocationOf(_node), "YulFunctionDefinition");
ret["name"] = _node.name.str(); ret["name"] = _node.name.str();
for (auto const& var: _node.parameters) for (auto const& var: _node.parameters)
ret["parameters"].append((*this)(var)); ret["parameters"].emplace_back((*this)(var));
for (auto const& var: _node.returnVariables) for (auto const& var: _node.returnVariables)
ret["returnVariables"].append((*this)(var)); ret["returnVariables"].emplace_back((*this)(var));
ret["body"] = (*this)(_node.body); ret["body"] = (*this)(_node.body);
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(If const& _node) const Json AsmJsonConverter::operator()(If const& _node) const
{ {
yulAssert(_node.condition, "Invalid if condition."); yulAssert(_node.condition, "Invalid if condition.");
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulIf"); Json ret = createAstNode(nativeLocationOf(_node), "YulIf");
ret["condition"] = std::visit(*this, *_node.condition); ret["condition"] = std::visit(*this, *_node.condition);
ret["body"] = (*this)(_node.body); ret["body"] = (*this)(_node.body);
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(Switch const& _node) const Json AsmJsonConverter::operator()(Switch const& _node) const
{ {
yulAssert(_node.expression, "Invalid expression pointer."); yulAssert(_node.expression, "Invalid expression pointer.");
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulSwitch"); Json ret = createAstNode(nativeLocationOf(_node), "YulSwitch");
ret["expression"] = std::visit(*this, *_node.expression); ret["expression"] = std::visit(*this, *_node.expression);
for (auto const& var: _node.cases) for (auto const& var: _node.cases)
ret["cases"].append((*this)(var)); ret["cases"].emplace_back((*this)(var));
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(Case const& _node) const Json AsmJsonConverter::operator()(Case const& _node) const
{ {
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulCase"); Json ret = createAstNode(nativeLocationOf(_node), "YulCase");
ret["value"] = _node.value ? (*this)(*_node.value) : "default"; ret["value"] = _node.value ? (*this)(*_node.value) : "default";
ret["body"] = (*this)(_node.body); ret["body"] = (*this)(_node.body);
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const Json AsmJsonConverter::operator()(ForLoop const& _node) const
{ {
yulAssert(_node.condition, "Invalid for loop condition."); yulAssert(_node.condition, "Invalid for loop condition.");
Json::Value ret = createAstNode(nativeLocationOf(_node), "YulForLoop"); Json ret = createAstNode(nativeLocationOf(_node), "YulForLoop");
ret["pre"] = (*this)(_node.pre); ret["pre"] = (*this)(_node.pre);
ret["condition"] = std::visit(*this, *_node.condition); ret["condition"] = std::visit(*this, *_node.condition);
ret["post"] = (*this)(_node.post); ret["post"] = (*this)(_node.post);
@ -168,24 +166,24 @@ Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const
return ret; return ret;
} }
Json::Value AsmJsonConverter::operator()(Break const& _node) const Json AsmJsonConverter::operator()(Break const& _node) const
{ {
return createAstNode(nativeLocationOf(_node), "YulBreak"); return createAstNode(nativeLocationOf(_node), "YulBreak");
} }
Json::Value AsmJsonConverter::operator()(Continue const& _node) const Json AsmJsonConverter::operator()(Continue const& _node) const
{ {
return createAstNode(nativeLocationOf(_node), "YulContinue"); return createAstNode(nativeLocationOf(_node), "YulContinue");
} }
Json::Value AsmJsonConverter::operator()(Leave const& _node) const Json AsmJsonConverter::operator()(Leave const& _node) const
{ {
return createAstNode(nativeLocationOf(_node), "YulLeave"); return createAstNode(nativeLocationOf(_node), "YulLeave");
} }
Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _location, string _nodeType) const Json AsmJsonConverter::createAstNode(langutil::SourceLocation const& _location, string _nodeType) const
{ {
Json::Value ret{Json::objectValue}; Json ret{Json::object()};
ret["nodeType"] = std::move(_nodeType); ret["nodeType"] = std::move(_nodeType);
int length = -1; int length = -1;
if (_location.start >= 0 && _location.end >= 0) if (_location.start >= 0 && _location.end >= 0)
@ -195,11 +193,11 @@ Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _loc
} }
template <class T> template <class T>
Json::Value AsmJsonConverter::vectorOfVariantsToJson(vector<T> const& _vec) const Json AsmJsonConverter::vectorOfVariantsToJson(vector<T> const& _vec) const
{ {
Json::Value ret{Json::arrayValue}; Json ret{Json::array()};
for (auto const& var: _vec) for (auto const& var: _vec)
ret.append(std::visit(*this, var)); ret.emplace_back(std::visit(*this, var));
return ret; return ret;
} }

View File

@ -25,7 +25,7 @@
#include <libyul/ASTForward.h> #include <libyul/ASTForward.h>
#include <liblangutil/SourceLocation.h> #include <liblangutil/SourceLocation.h>
#include <json/json.h> #include <libsolutil/JSON.h>
#include <boost/variant/static_visitor.hpp> #include <boost/variant/static_visitor.hpp>
#include <optional> #include <optional>
#include <vector> #include <vector>
@ -36,35 +36,35 @@ namespace solidity::yul
/** /**
* Converter of the yul AST into JSON format * Converter of the yul AST into JSON format
*/ */
class AsmJsonConverter: public boost::static_visitor<Json::Value> class AsmJsonConverter: public boost::static_visitor<Json>
{ {
public: public:
/// Create a converter to JSON for any block of inline assembly /// Create a converter to JSON for any block of inline assembly
/// @a _sourceIndex to be used to abbreviate source name in the source locations /// @a _sourceIndex to be used to abbreviate source name in the source locations
explicit AsmJsonConverter(std::optional<size_t> _sourceIndex): m_sourceIndex(_sourceIndex) {} explicit AsmJsonConverter(std::optional<size_t> _sourceIndex): m_sourceIndex(_sourceIndex) {}
Json::Value operator()(Block const& _node) const; Json operator()(Block const& _node) const;
Json::Value operator()(TypedName const& _node) const; Json operator()(TypedName const& _node) const;
Json::Value operator()(Literal const& _node) const; Json operator()(Literal const& _node) const;
Json::Value operator()(Identifier const& _node) const; Json operator()(Identifier const& _node) const;
Json::Value operator()(Assignment const& _node) const; Json operator()(Assignment const& _node) const;
Json::Value operator()(VariableDeclaration const& _node) const; Json operator()(VariableDeclaration const& _node) const;
Json::Value operator()(FunctionDefinition const& _node) const; Json operator()(FunctionDefinition const& _node) const;
Json::Value operator()(FunctionCall const& _node) const; Json operator()(FunctionCall const& _node) const;
Json::Value operator()(If const& _node) const; Json operator()(If const& _node) const;
Json::Value operator()(Switch const& _node) const; Json operator()(Switch const& _node) const;
Json::Value operator()(Case const& _node) const; Json operator()(Case const& _node) const;
Json::Value operator()(ForLoop const& _node) const; Json operator()(ForLoop const& _node) const;
Json::Value operator()(Break const& _node) const; Json operator()(Break const& _node) const;
Json::Value operator()(Continue const& _node) const; Json operator()(Continue const& _node) const;
Json::Value operator()(Leave const& _node) const; Json operator()(Leave const& _node) const;
Json::Value operator()(ExpressionStatement const& _node) const; Json operator()(ExpressionStatement const& _node) const;
Json::Value operator()(Label const& _node) const; Json operator()(Label const& _node) const;
private: private:
Json::Value createAstNode(langutil::SourceLocation const& _location, std::string _nodeType) const; Json createAstNode(langutil::SourceLocation const& _location, std::string _nodeType) const;
template <class T> template <class T>
Json::Value vectorOfVariantsToJson(std::vector<T> const& vec) const; Json vectorOfVariantsToJson(std::vector<T> const& vec) const;
std::optional<size_t> const m_sourceIndex; std::optional<size_t> const m_sourceIndex;
}; };

View File

@ -42,15 +42,15 @@ namespace solidity::yul
using SourceLocation = langutil::SourceLocation; 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<string>(), m_sourceNames);
} }
template <class T> template <class T>
T AsmJsonImporter::createAsmNode(Json::Value const& _node) T AsmJsonImporter::createAsmNode(Json const& _node)
{ {
T r; T r;
SourceLocation nativeLocation = createSourceLocation(_node); SourceLocation nativeLocation = createSourceLocation(_node);
@ -62,26 +62,26 @@ T AsmJsonImporter::createAsmNode(Json::Value const& _node)
return r; return r;
} }
Json::Value AsmJsonImporter::member(Json::Value const& _node, string const& _name) Json AsmJsonImporter::member(Json const& _node, string const& _name)
{ {
if (!_node.isMember(_name)) if (!_node.contains(_name))
return Json::nullValue; return Json{};
return _node[_name]; return _node[_name];
} }
TypedName AsmJsonImporter::createTypedName(Json::Value const& _node) TypedName AsmJsonImporter::createTypedName(Json const& _node)
{ {
auto typedName = createAsmNode<TypedName>(_node); auto typedName = createAsmNode<TypedName>(_node);
typedName.type = YulString{member(_node, "type").asString()}; typedName.type = YulString{member(_node, "type").get<string>()};
typedName.name = YulString{member(_node, "name").asString()}; typedName.name = YulString{member(_node, "name").get<string>()};
return typedName; return typedName;
} }
Statement AsmJsonImporter::createStatement(Json::Value const& _node) Statement AsmJsonImporter::createStatement(Json const& _node)
{ {
Json::Value jsonNodeType = member(_node, "nodeType"); Json jsonNodeType = member(_node, "nodeType");
yulAssert(jsonNodeType.isString(), "Expected \"nodeType\" to be of type string!"); yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!");
string nodeType = jsonNodeType.asString(); string nodeType = jsonNodeType.get<string>();
yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix"); yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix");
nodeType = nodeType.substr(3); nodeType = nodeType.substr(3);
@ -115,11 +115,11 @@ Statement AsmJsonImporter::createStatement(Json::Value const& _node)
util::unreachable(); util::unreachable();
} }
Expression AsmJsonImporter::createExpression(Json::Value const& _node) Expression AsmJsonImporter::createExpression(Json const& _node)
{ {
Json::Value jsonNodeType = member(_node, "nodeType"); Json jsonNodeType = member(_node, "nodeType");
yulAssert(jsonNodeType.isString(), "Expected \"nodeType\" to be of type string!"); yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!");
string nodeType = jsonNodeType.asString(); string nodeType = jsonNodeType.get<string>();
yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix"); yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix");
nodeType = nodeType.substr(3); nodeType = nodeType.substr(3);
@ -137,7 +137,7 @@ Expression AsmJsonImporter::createExpression(Json::Value const& _node)
util::unreachable(); util::unreachable();
} }
vector<Expression> AsmJsonImporter::createExpressionVector(Json::Value const& _array) vector<Expression> AsmJsonImporter::createExpressionVector(Json const& _array)
{ {
vector<Expression> ret; vector<Expression> ret;
for (auto& var: _array) for (auto& var: _array)
@ -145,7 +145,7 @@ vector<Expression> AsmJsonImporter::createExpressionVector(Json::Value const& _a
return ret; return ret;
} }
vector<Statement> AsmJsonImporter::createStatementVector(Json::Value const& _array) vector<Statement> AsmJsonImporter::createStatementVector(Json const& _array)
{ {
vector<Statement> ret; vector<Statement> ret;
for (auto& var: _array) for (auto& var: _array)
@ -153,25 +153,25 @@ vector<Statement> AsmJsonImporter::createStatementVector(Json::Value const& _arr
return ret; return ret;
} }
Block AsmJsonImporter::createBlock(Json::Value const& _node) Block AsmJsonImporter::createBlock(Json const& _node)
{ {
auto block = createAsmNode<Block>(_node); auto block = createAsmNode<Block>(_node);
block.statements = createStatementVector(_node["statements"]); block.statements = createStatementVector(_node["statements"]);
return block; return block;
} }
Literal AsmJsonImporter::createLiteral(Json::Value const& _node) Literal AsmJsonImporter::createLiteral(Json const& _node)
{ {
auto lit = createAsmNode<Literal>(_node); auto lit = createAsmNode<Literal>(_node);
string kind = member(_node, "kind").asString(); string kind = member(_node, "kind").get<string>();
solAssert(member(_node, "hexValue").isString() || member(_node, "value").isString(), ""); solAssert(member(_node, "hexValue").is_string() || member(_node, "value").is_string(), "");
if (_node.isMember("hexValue")) if (_node.contains("hexValue"))
lit.value = YulString{util::asString(util::fromHex(member(_node, "hexValue").asString()))}; lit.value = YulString{util::asString(util::fromHex(member(_node, "hexValue").get<string>()))};
else else
lit.value = YulString{member(_node, "value").asString()}; lit.value = YulString{member(_node, "value").get<string>()};
lit.type= YulString{member(_node, "type").asString()}; lit.type= YulString{member(_node, "type").get<string>()};
if (kind == "number") if (kind == "number")
{ {
@ -208,23 +208,23 @@ Literal AsmJsonImporter::createLiteral(Json::Value const& _node)
return lit; return lit;
} }
Leave AsmJsonImporter::createLeave(Json::Value const& _node) Leave AsmJsonImporter::createLeave(Json const& _node)
{ {
return createAsmNode<Leave>(_node); return createAsmNode<Leave>(_node);
} }
Identifier AsmJsonImporter::createIdentifier(Json::Value const& _node) Identifier AsmJsonImporter::createIdentifier(Json const& _node)
{ {
auto identifier = createAsmNode<Identifier>(_node); auto identifier = createAsmNode<Identifier>(_node);
identifier.name = YulString(member(_node, "name").asString()); identifier.name = YulString(member(_node, "name").get<string>());
return identifier; return identifier;
} }
Assignment AsmJsonImporter::createAssignment(Json::Value const& _node) Assignment AsmJsonImporter::createAssignment(Json const& _node)
{ {
auto assignment = createAsmNode<Assignment>(_node); auto assignment = createAsmNode<Assignment>(_node);
if (_node.isMember("variableNames")) if (_node.contains("variableNames"))
for (auto const& var: member(_node, "variableNames")) for (auto const& var: member(_node, "variableNames"))
assignment.variableNames.emplace_back(createIdentifier(var)); assignment.variableNames.emplace_back(createIdentifier(var));
@ -232,7 +232,7 @@ Assignment AsmJsonImporter::createAssignment(Json::Value const& _node)
return assignment; return assignment;
} }
FunctionCall AsmJsonImporter::createFunctionCall(Json::Value const& _node) FunctionCall AsmJsonImporter::createFunctionCall(Json const& _node)
{ {
auto functionCall = createAsmNode<FunctionCall>(_node); auto functionCall = createAsmNode<FunctionCall>(_node);
@ -244,14 +244,14 @@ FunctionCall AsmJsonImporter::createFunctionCall(Json::Value const& _node)
return functionCall; return functionCall;
} }
ExpressionStatement AsmJsonImporter::createExpressionStatement(Json::Value const& _node) ExpressionStatement AsmJsonImporter::createExpressionStatement(Json const& _node)
{ {
auto statement = createAsmNode<ExpressionStatement>(_node); auto statement = createAsmNode<ExpressionStatement>(_node);
statement.expression = createExpression(member(_node, "expression")); statement.expression = createExpression(member(_node, "expression"));
return statement; return statement;
} }
VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json::Value const& _node) VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node)
{ {
auto varDec = createAsmNode<VariableDeclaration>(_node); auto varDec = createAsmNode<VariableDeclaration>(_node);
for (auto const& var: member(_node, "variables")) for (auto const& var: member(_node, "variables"))
@ -260,16 +260,16 @@ VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json::Value const
return varDec; return varDec;
} }
FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json::Value const& _node) FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node)
{ {
auto funcDef = createAsmNode<FunctionDefinition>(_node); auto funcDef = createAsmNode<FunctionDefinition>(_node);
funcDef.name = YulString{member(_node, "name").asString()}; funcDef.name = YulString{member(_node, "name").get<string>()};
if (_node.isMember("parameters")) if (_node.contains("parameters"))
for (auto const& var: member(_node, "parameters")) for (auto const& var: member(_node, "parameters"))
funcDef.parameters.emplace_back(createTypedName(var)); funcDef.parameters.emplace_back(createTypedName(var));
if (_node.isMember("returnVariables")) if (_node.contains("returnVariables"))
for (auto const& var: member(_node, "returnVariables")) for (auto const& var: member(_node, "returnVariables"))
funcDef.returnVariables.emplace_back(createTypedName(var)); funcDef.returnVariables.emplace_back(createTypedName(var));
@ -277,7 +277,7 @@ FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json::Value const&
return funcDef; return funcDef;
} }
If AsmJsonImporter::createIf(Json::Value const& _node) If AsmJsonImporter::createIf(Json const& _node)
{ {
auto ifStatement = createAsmNode<If>(_node); auto ifStatement = createAsmNode<If>(_node);
ifStatement.condition = make_unique<Expression>(createExpression(member(_node, "condition"))); ifStatement.condition = make_unique<Expression>(createExpression(member(_node, "condition")));
@ -285,19 +285,19 @@ If AsmJsonImporter::createIf(Json::Value const& _node)
return ifStatement; return ifStatement;
} }
Case AsmJsonImporter::createCase(Json::Value const& _node) Case AsmJsonImporter::createCase(Json const& _node)
{ {
auto caseStatement = createAsmNode<Case>(_node); auto caseStatement = createAsmNode<Case>(_node);
auto const& value = member(_node, "value"); auto const& value = member(_node, "value");
if (value.isString()) if (value.is_string())
yulAssert(value.asString() == "default", "Expected default case"); yulAssert(value.get<string>() == "default", "Expected default case");
else else
caseStatement.value = make_unique<Literal>(createLiteral(value)); caseStatement.value = make_unique<Literal>(createLiteral(value));
caseStatement.body = createBlock(member(_node, "body")); caseStatement.body = createBlock(member(_node, "body"));
return caseStatement; return caseStatement;
} }
Switch AsmJsonImporter::createSwitch(Json::Value const& _node) Switch AsmJsonImporter::createSwitch(Json const& _node)
{ {
auto switchStatement = createAsmNode<Switch>(_node); auto switchStatement = createAsmNode<Switch>(_node);
switchStatement.expression = make_unique<Expression>(createExpression(member(_node, "expression"))); switchStatement.expression = make_unique<Expression>(createExpression(member(_node, "expression")));
@ -306,7 +306,7 @@ Switch AsmJsonImporter::createSwitch(Json::Value const& _node)
return switchStatement; return switchStatement;
} }
ForLoop AsmJsonImporter::createForLoop(Json::Value const& _node) ForLoop AsmJsonImporter::createForLoop(Json const& _node)
{ {
auto forLoop = createAsmNode<ForLoop>(_node); auto forLoop = createAsmNode<ForLoop>(_node);
forLoop.pre = createBlock(member(_node, "pre")); forLoop.pre = createBlock(member(_node, "pre"));
@ -316,12 +316,12 @@ ForLoop AsmJsonImporter::createForLoop(Json::Value const& _node)
return forLoop; return forLoop;
} }
Break AsmJsonImporter::createBreak(Json::Value const& _node) Break AsmJsonImporter::createBreak(Json const& _node)
{ {
return createAsmNode<Break>(_node); return createAsmNode<Break>(_node);
} }
Continue AsmJsonImporter::createContinue(Json::Value const& _node) Continue AsmJsonImporter::createContinue(Json const& _node)
{ {
return createAsmNode<Continue>(_node); return createAsmNode<Continue>(_node);
} }

View File

@ -23,8 +23,8 @@
#pragma once #pragma once
#include <json/json.h>
#include <liblangutil/SourceLocation.h> #include <liblangutil/SourceLocation.h>
#include <libsolutil/JSON.h>
#include <libyul/ASTForward.h> #include <libyul/ASTForward.h>
#include <utility> #include <utility>
@ -41,36 +41,36 @@ public:
explicit AsmJsonImporter(std::vector<std::shared_ptr<std::string const>> const& _sourceNames): explicit AsmJsonImporter(std::vector<std::shared_ptr<std::string const>> const& _sourceNames):
m_sourceNames(_sourceNames) m_sourceNames(_sourceNames)
{} {}
yul::Block createBlock(Json::Value const& _node); yul::Block createBlock(Json const& _node);
private: private:
langutil::SourceLocation const createSourceLocation(Json::Value const& _node); langutil::SourceLocation const createSourceLocation(Json const& _node);
template <class T> template <class T>
T createAsmNode(Json::Value const& _node); T createAsmNode(Json const& _node);
/// helper function to access member functions of the JSON /// helper function to access member functions of the JSON
/// and throw an error if it does not exist /// 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::Statement createStatement(Json const& _node);
yul::Expression createExpression(Json::Value const& _node); yul::Expression createExpression(Json const& _node);
std::vector<yul::Statement> createStatementVector(Json::Value const& _array); std::vector<yul::Statement> createStatementVector(Json const& _array);
std::vector<yul::Expression> createExpressionVector(Json::Value const& _array); std::vector<yul::Expression> createExpressionVector(Json const& _array);
yul::TypedName createTypedName(Json::Value const& _node); yul::TypedName createTypedName(Json const& _node);
yul::Literal createLiteral(Json::Value const& _node); yul::Literal createLiteral(Json const& _node);
yul::Leave createLeave(Json::Value const& _node); yul::Leave createLeave(Json const& _node);
yul::Identifier createIdentifier(Json::Value const& _node); yul::Identifier createIdentifier(Json const& _node);
yul::Assignment createAssignment(Json::Value const& _node); yul::Assignment createAssignment(Json const& _node);
yul::FunctionCall createFunctionCall(Json::Value const& _node); yul::FunctionCall createFunctionCall(Json const& _node);
yul::ExpressionStatement createExpressionStatement(Json::Value const& _node); yul::ExpressionStatement createExpressionStatement(Json const& _node);
yul::VariableDeclaration createVariableDeclaration(Json::Value const& _node); yul::VariableDeclaration createVariableDeclaration(Json const& _node);
yul::FunctionDefinition createFunctionDefinition(Json::Value const& _node); yul::FunctionDefinition createFunctionDefinition(Json const& _node);
yul::If createIf(Json::Value const& _node); yul::If createIf(Json const& _node);
yul::Case createCase(Json::Value const& _node); yul::Case createCase(Json const& _node);
yul::Switch createSwitch(Json::Value const& _node); yul::Switch createSwitch(Json const& _node);
yul::ForLoop createForLoop(Json::Value const& _node); yul::ForLoop createForLoop(Json const& _node);
yul::Break createBreak(Json::Value const& _node); yul::Break createBreak(Json const& _node);
yul::Continue createContinue(Json::Value const& _node); yul::Continue createContinue(Json const& _node);
std::vector<std::shared_ptr<std::string const>> const& m_sourceNames; std::vector<std::shared_ptr<std::string const>> const& m_sourceNames;
}; };

View File

@ -125,9 +125,9 @@ mv solidity solc
# Fetch dependencies # Fetch dependencies
mkdir -p ./solc/deps/downloads/ 2>/dev/null || true mkdir -p ./solc/deps/downloads/ 2>/dev/null || true
wget -O ./solc/deps/downloads/jsoncpp-1.9.3.tar.gz https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz
wget -O ./solc/deps/downloads/range-v3-0.12.0.tar.gz https://github.com/ericniebler/range-v3/archive/0.12.0.tar.gz wget -O ./solc/deps/downloads/range-v3-0.12.0.tar.gz https://github.com/ericniebler/range-v3/archive/0.12.0.tar.gz
wget -O ./solc/deps/downloads/fmt-8.0.1.tar.gz https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz wget -O ./solc/deps/downloads/fmt-8.0.1.tar.gz https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz
wget -O ./solc/deps/nlohmann/json/json.hpp https://github.com/nlohmann/json/releases/download/v3.10.2/json.hpp
# Determine version # Determine version
cd solc cd solc

View File

@ -280,23 +280,23 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract)
if (!m_options.compiler.outputs.signatureHashes) if (!m_options.compiler.outputs.signatureHashes)
return; return;
Json::Value interfaceSymbols = m_compiler->interfaceSymbols(_contract); Json interfaceSymbols = m_compiler->interfaceSymbols(_contract);
string out = "Function signatures:\n"; string out = "Function signatures:\n";
for (auto const& name: interfaceSymbols["methods"].getMemberNames()) for (auto const& [name, value]: interfaceSymbols["methods"].items())
out += interfaceSymbols["methods"][name].asString() + ": " + name + "\n"; out += value.get<string>() + ": " + name + "\n";
if (interfaceSymbols.isMember("errors")) if (interfaceSymbols.contains("errors"))
{ {
out += "\nError signatures:\n"; out += "\nError signatures:\n";
for (auto const& name: interfaceSymbols["errors"].getMemberNames()) for (auto const& [name, value]: interfaceSymbols["errors"].items())
out += interfaceSymbols["errors"][name].asString() + ": " + name + "\n"; out += value.get<string>() + ": " + name + "\n";
} }
if (interfaceSymbols.isMember("events")) if (interfaceSymbols.contains("events"))
{ {
out += "\nEvent signatures:\n"; out += "\nEvent signatures:\n";
for (auto const& name: interfaceSymbols["events"].getMemberNames()) for (auto const& [name, value]: interfaceSymbols["events"].items())
out += interfaceSymbols["events"][name].asString() + ": " + name + "\n"; out += value.get<string>() + ": " + name + "\n";
} }
if (!m_options.output.dir.empty()) if (!m_options.output.dir.empty())
@ -394,40 +394,40 @@ void CommandLineInterface::handleGasEstimation(string const& _contract)
{ {
solAssert(CompilerInputModes.count(m_options.input.mode) == 1); solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
Json::Value estimates = m_compiler->gasEstimates(_contract); Json estimates = m_compiler->gasEstimates(_contract);
sout() << "Gas estimation:" << endl; sout() << "Gas estimation:" << endl;
if (estimates["creation"].isObject()) if (estimates["creation"].is_object())
{ {
Json::Value creation = estimates["creation"]; Json creation = estimates["creation"];
sout() << "construction:" << endl; sout() << "construction:" << endl;
sout() << " " << creation["executionCost"].asString(); sout() << " " << creation["executionCost"].get<string>();
sout() << " + " << creation["codeDepositCost"].asString(); sout() << " + " << creation["codeDepositCost"].get<string>();
sout() << " = " << creation["totalCost"].asString() << endl; sout() << " = " << creation["totalCost"].get<string>() << endl;
} }
if (estimates["external"].isObject()) if (estimates["external"].is_object())
{ {
Json::Value externalFunctions = estimates["external"]; Json externalFunctions = estimates["external"];
sout() << "external:" << endl; sout() << "external:" << endl;
for (auto const& name: externalFunctions.getMemberNames()) for (auto const& [name, gas]: externalFunctions.items())
{ {
if (name.empty()) if (name.empty())
sout() << " fallback:\t"; sout() << " fallback:\t";
else else
sout() << " " << name << ":\t"; sout() << " " << name << ":\t";
sout() << externalFunctions[name].asString() << endl; sout() << gas.get<string>() << endl;
} }
} }
if (estimates["internal"].isObject()) if (estimates["internal"].is_object())
{ {
Json::Value internalFunctions = estimates["internal"]; Json internalFunctions = estimates["internal"];
sout() << "internal:" << endl; sout() << "internal:" << endl;
for (auto const& name: internalFunctions.getMemberNames()) for (auto const& [name, gas]: internalFunctions.items())
{ {
sout() << " " << name << ":\t"; sout() << " " << name << ":\t";
sout() << internalFunctions[name].asString() << endl; sout() << gas.get<string>() << endl;
} }
} }
} }
@ -537,25 +537,25 @@ void CommandLineInterface::readInputFiles()
solThrow(CommandLineValidationError, "All specified input files either do not exist or are not regular files."); solThrow(CommandLineValidationError, "All specified input files either do not exist or are not regular files.");
} }
map<string, Json::Value> CommandLineInterface::parseAstFromInput() map<string, Json> CommandLineInterface::parseAstFromInput()
{ {
solAssert(m_options.input.mode == InputMode::CompilerWithASTImport); solAssert(m_options.input.mode == InputMode::CompilerWithASTImport);
map<string, Json::Value> sourceJsons; map<string, Json> sourceJsons;
map<string, string> tmpSources; map<string, string> tmpSources;
for (SourceCode const& sourceCode: m_fileReader.sourceUnits() | ranges::views::values) 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(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, _]: ast["sources"].items())
{ {
std::string astKey = ast["sources"][src].isMember("ast") ? "ast" : "AST"; std::string astKey = ast["sources"][src].contains("ast") ? "ast" : "AST";
astAssert(ast["sources"][src].isMember(astKey), "astkey is not member"); astAssert(ast["sources"][src].contains(astKey), "astkey is not member");
astAssert(ast["sources"][src][astKey]["nodeType"].asString() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); astAssert(ast["sources"][src][astKey]["nodeType"].get<string>() == "SourceUnit", "Top-level node should be a 'SourceUnit'");
astAssert(sourceJsons.count(src) == 0, "All sources must have unique names"); 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(ast["sources"][src][astKey]));
tmpSources[src] = util::jsonCompactPrint(ast); tmpSources[src] = util::jsonCompactPrint(ast);
@ -806,16 +806,16 @@ void CommandLineInterface::handleCombinedJSON()
if (!m_options.compiler.combinedJsonRequests.has_value()) if (!m_options.compiler.combinedJsonRequests.has_value())
return; return;
Json::Value output(Json::objectValue); Json output(Json::object());
output[g_strVersion] = frontend::VersionString; output[g_strVersion] = frontend::VersionString;
vector<string> contracts = m_compiler->contractNames(); vector<string> contracts = m_compiler->contractNames();
if (!contracts.empty()) if (!contracts.empty())
output[g_strContracts] = Json::Value(Json::objectValue); output[g_strContracts] = Json::object();
for (string const& contractName: contracts) for (string const& contractName: contracts)
{ {
Json::Value& contractData = output[g_strContracts][contractName] = Json::objectValue; Json& contractData = output[g_strContracts][contractName] = Json::object();
if (m_options.compiler.combinedJsonRequests->abi) if (m_options.compiler.combinedJsonRequests->abi)
contractData[g_strAbi] = m_compiler->contractABI(contractName); contractData[g_strAbi] = m_compiler->contractABI(contractName);
if (m_options.compiler.combinedJsonRequests->metadata) if (m_options.compiler.combinedJsonRequests->metadata)
@ -867,19 +867,19 @@ void CommandLineInterface::handleCombinedJSON()
if (needsSourceList) if (needsSourceList)
{ {
// Indices into this array are used to abbreviate source names in source locations. // 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_compiler->sourceNames()) for (auto const& source: m_compiler->sourceNames())
output[g_strSourceList].append(source); output[g_strSourceList].emplace_back(source);
} }
if (m_options.compiler.combinedJsonRequests->ast) if (m_options.compiler.combinedJsonRequests->ast)
{ {
output[g_strSources] = Json::Value(Json::objectValue); output[g_strSources] = Json(Json::object());
for (auto const& sourceCode: m_fileReader.sourceUnits()) for (auto const& sourceCode: m_fileReader.sourceUnits())
{ {
ASTJsonExporter converter(m_compiler->state(), m_compiler->sourceIndices()); ASTJsonExporter converter(m_compiler->state(), m_compiler->sourceIndices());
output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue); output[g_strSources][sourceCode.first] = Json(Json::object());
output[g_strSources][sourceCode.first]["AST"] = converter.toJson(m_compiler->ast(sourceCode.first)); output[g_strSources][sourceCode.first]["AST"] = converter.toJson(m_compiler->ast(sourceCode.first));
} }
} }

View File

@ -113,7 +113,7 @@ private:
/// such that they can be imported into the compiler (importASTs()) /// such that they can be imported into the compiler (importASTs())
/// (produced by --combined-json ast <file.sol> /// (produced by --combined-json ast <file.sol>
/// or standard-json output /// or standard-json output
std::map<std::string, Json::Value> parseAstFromInput(); std::map<std::string, Json> parseAstFromInput();
/// Create a file in the given directory /// Create a file in the given directory
/// @arg _fileName the name of the file /// @arg _fileName the name of the file

View File

@ -174,33 +174,33 @@ std::optional<map<string, string>> parseCBORMetadata(bytes const& _metadata)
bool isValidMetadata(string const& _serialisedMetadata) bool isValidMetadata(string const& _serialisedMetadata)
{ {
Json::Value metadata; Json metadata;
if (!util::jsonParseStrict(_serialisedMetadata, metadata)) if (!util::jsonParseStrict(_serialisedMetadata, metadata))
return false; return false;
return isValidMetadata(metadata); return isValidMetadata(metadata);
} }
bool isValidMetadata(Json::Value const& _metadata) bool isValidMetadata(Json const& _metadata)
{ {
if ( if (
!_metadata.isObject() || !_metadata.is_object() ||
!_metadata.isMember("version") || !_metadata.contains("version") ||
!_metadata.isMember("language") || !_metadata.contains("language") ||
!_metadata.isMember("compiler") || !_metadata.contains("compiler") ||
!_metadata.isMember("settings") || !_metadata.contains("settings") ||
!_metadata.isMember("sources") || !_metadata.contains("sources") ||
!_metadata.isMember("output") || !_metadata.contains("output") ||
!_metadata["settings"].isMember("evmVersion") || !_metadata["settings"].contains("evmVersion") ||
!_metadata["settings"].isMember("metadata") || !_metadata["settings"].contains("metadata") ||
!_metadata["settings"]["metadata"].isMember("bytecodeHash") !_metadata["settings"]["metadata"].contains("bytecodeHash")
) )
return false; return false;
if (!_metadata["version"].isNumeric() || _metadata["version"] != 1) if (!_metadata["version"].is_number() || _metadata["version"] != 1)
return false; return false;
if (!_metadata["language"].isString() || _metadata["language"].asString() != "Solidity") if (!_metadata["language"].is_string() || _metadata["language"].get<string>() != "Solidity")
return false; return false;
/// @TODO add more strict checks /// @TODO add more strict checks

View File

@ -53,6 +53,6 @@ std::optional<std::map<std::string, std::string>> parseCBORMetadata(bytes const&
bool isValidMetadata(std::string const& _serialisedMetadata); bool isValidMetadata(std::string const& _serialisedMetadata);
/// Expects a deserialised metadata JSON and returns true if the content is valid metadata. /// 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 } // end namespaces

View File

@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
"{\"begin\":8,\"end\":18,\"name\":\"MSTORE\",\"source\":2}" "{\"begin\":8,\"end\":18,\"name\":\"MSTORE\",\"source\":2}"
"]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"},\"sourceList\":[\"root.asm\",\"sub.asm\",\"verbatim.asm\"]}" "]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"},\"sourceList\":[\"root.asm\",\"sub.asm\",\"verbatim.asm\"]}"
}; };
Json::Value jsonValue; Json jsonValue;
BOOST_CHECK(util::jsonParseStrict(json, jsonValue)); BOOST_CHECK(util::jsonParseStrict(json, jsonValue));
BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue)); BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue));
} }

View File

@ -82,18 +82,15 @@ void GasTest::parseExpectations(std::istream& _stream)
void GasTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const void GasTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const
{ {
Json::Value estimates = compiler().gasEstimates(compiler().lastContractName()); Json estimates = compiler().gasEstimates(compiler().lastContractName());
for (auto groupIt = estimates.begin(); groupIt != estimates.end(); ++groupIt) for (auto const& [group, content]: estimates.items())
{ {
_stream << _linePrefix << groupIt.key().asString() << ":" << std::endl; _stream << _linePrefix << group << ":" << std::endl;
for (auto it = groupIt->begin(); it != groupIt->end(); ++it) for (auto const& [function, gas]: content.items())
{ {
_stream << _linePrefix << " "; _stream << _linePrefix << " ";
if (it.key().asString().empty()) _stream << (function.empty() ? "fallback" : function);
_stream << "fallback"; _stream << ": " << gas << std::endl;
else
_stream << it.key().asString();
_stream << ": " << it->asString() << std::endl;
} }
} }
} }
@ -123,14 +120,14 @@ TestCase::TestResult GasTest::run(ostream& _stream, string const& _linePrefix, b
return TestResult::FatalError; return TestResult::FatalError;
} }
Json::Value estimateGroups = compiler().gasEstimates(compiler().lastContractName()); Json estimateGroups = compiler().gasEstimates(compiler().lastContractName());
if ( if (
m_expectations.size() == estimateGroups.size() && m_expectations.size() == estimateGroups.size() &&
boost::all(m_expectations, [&](auto const& expectations) { boost::all(m_expectations, [&](auto const& expectations) {
auto const& estimates = estimateGroups[expectations.first]; Json const& estimates = estimateGroups[expectations.first];
return estimates.size() == expectations.second.size() && return estimates.size() == expectations.second.size() &&
boost::all(expectations.second, [&](auto const& entry) { boost::all(expectations.second, [&](auto const& entry) {
return entry.second == estimates[entry.first].asString(); return entry.second == estimates[entry.first].template get<string>();
}); });
}) })
) )

View File

@ -37,30 +37,30 @@ namespace
/// TODO: share this between StandardCompiler.cpp /// TODO: share this between StandardCompiler.cpp
/// Helper to match a specific error type and message /// Helper to match a specific error type and message
bool containsError(Json::Value const& _compilerResult, string const& _type, string const& _message) bool containsError(Json const& _compilerResult, string const& _type, string const& _message)
{ {
if (!_compilerResult.isMember("errors")) if (!_compilerResult.contains("errors"))
return false; return false;
for (auto const& error: _compilerResult["errors"]) for (auto const& error: _compilerResult["errors"])
{ {
BOOST_REQUIRE(error.isObject()); BOOST_REQUIRE(error.is_object());
BOOST_REQUIRE(error["type"].isString()); BOOST_REQUIRE(error["type"].is_string());
BOOST_REQUIRE(error["message"].isString()); BOOST_REQUIRE(error["message"].is_string());
if ((error["type"].asString() == _type) && (error["message"].asString() == _message)) if ((error["type"].get<string>() == _type) && (error["message"].get<string>() == _message))
return true; return true;
} }
return false; return false;
} }
Json::Value compile(string const& _input, CStyleReadFileCallback _callback = nullptr) Json compile(string const& _input, CStyleReadFileCallback _callback = nullptr)
{ {
char* output_ptr = solidity_compile(_input.c_str(), _callback, nullptr); char* output_ptr = solidity_compile(_input.c_str(), _callback, nullptr);
string output(output_ptr); string output(output_ptr);
solidity_free(output_ptr); solidity_free(output_ptr);
solidity_reset(); solidity_reset();
Json::Value ret; Json ret;
BOOST_REQUIRE(util::jsonParseStrict(output, ret)); BOOST_REQUIRE(util::jsonParseStrict(output, ret));
return ret; return ret;
} }
@ -101,14 +101,14 @@ BOOST_AUTO_TEST_CASE(standard_compilation)
} }
} }
)"; )";
Json::Value result = compile(input); Json result = compile(input);
BOOST_REQUIRE(result.isObject()); BOOST_REQUIRE(result.is_object());
// Only tests some assumptions. The StandardCompiler is tested properly in another suite. // 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, // 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. // so there should not be a contract member.
BOOST_CHECK(!result.isMember("contracts")); BOOST_CHECK(!result.contains("contracts"));
} }
BOOST_AUTO_TEST_CASE(missing_callback) BOOST_AUTO_TEST_CASE(missing_callback)
@ -123,8 +123,8 @@ BOOST_AUTO_TEST_CASE(missing_callback)
} }
} }
)"; )";
Json::Value result = compile(input); Json result = compile(input);
BOOST_REQUIRE(result.isObject()); BOOST_REQUIRE(result.is_object());
BOOST_CHECK(containsError(result, "ParserError", "Source \"missing.sol\" not found: File not supplied initially.")); BOOST_CHECK(containsError(result, "ParserError", "Source \"missing.sol\" not found: File not supplied initially."));
} }
@ -169,8 +169,8 @@ BOOST_AUTO_TEST_CASE(with_callback)
} }
}; };
Json::Value result = compile(input, callback); Json result = compile(input, callback);
BOOST_REQUIRE(result.isObject()); BOOST_REQUIRE(result.is_object());
// This ensures that "found.sol" was properly loaded which triggered the second import statement. // 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.")); BOOST_CHECK(containsError(result, "ParserError", "Source \"missing.sol\" not found: Missing file."));

View File

@ -58,17 +58,17 @@ optional<string> compileAndCheckLicenseMetadata(string const& _contractName, cha
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
string const& serialisedMetadata = compilerStack.metadata(_contractName); string const& serialisedMetadata = compilerStack.metadata(_contractName);
Json::Value metadata; Json metadata;
BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata));
BOOST_CHECK_EQUAL(metadata["sources"].size(), 1); 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()); BOOST_REQUIRE(metadata["sources"]["A.sol"]["license"].is_string());
return metadata["sources"]["A.sol"]["license"].asString(); return metadata["sources"]["A.sol"]["license"].get<string>();
} }
else else
return nullopt; return nullopt;
@ -250,12 +250,12 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources)
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
string const& serialisedMetadata = compilerStack.metadata("A"); string const& serialisedMetadata = compilerStack.metadata("A");
Json::Value metadata; Json metadata;
BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata));
BOOST_CHECK_EQUAL(metadata["sources"].size(), 1); 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) BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports)
@ -291,14 +291,14 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports)
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
string const& serialisedMetadata = compilerStack.metadata("C"); string const& serialisedMetadata = compilerStack.metadata("C");
Json::Value metadata; Json metadata;
BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata));
BOOST_CHECK_EQUAL(metadata["sources"].size(), 3); BOOST_CHECK_EQUAL(metadata["sources"].size(), 3);
BOOST_CHECK(metadata["sources"].isMember("A")); BOOST_CHECK(metadata["sources"].contains("A"));
BOOST_CHECK(metadata["sources"].isMember("B")); BOOST_CHECK(metadata["sources"].contains("B"));
BOOST_CHECK(metadata["sources"].isMember("C")); BOOST_CHECK(metadata["sources"].contains("C"));
} }
BOOST_AUTO_TEST_CASE(metadata_useLiteralContent) BOOST_AUTO_TEST_CASE(metadata_useLiteralContent)
@ -319,16 +319,16 @@ BOOST_AUTO_TEST_CASE(metadata_useLiteralContent)
compilerStack.useMetadataLiteralSources(_literal); compilerStack.useMetadataLiteralSources(_literal);
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
string metadata_str = compilerStack.metadata("test"); string metadata_str = compilerStack.metadata("test");
Json::Value metadata; Json metadata;
BOOST_REQUIRE(util::jsonParseStrict(metadata_str, metadata)); BOOST_REQUIRE(util::jsonParseStrict(metadata_str, metadata));
BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata));
BOOST_CHECK(metadata.isMember("settings")); BOOST_CHECK(metadata.contains("settings"));
BOOST_CHECK(metadata["settings"].isMember("metadata")); BOOST_CHECK(metadata["settings"].contains("metadata"));
BOOST_CHECK(metadata["settings"]["metadata"].isMember("bytecodeHash")); BOOST_CHECK(metadata["settings"]["metadata"].contains("bytecodeHash"));
if (_literal) if (_literal)
{ {
BOOST_CHECK(metadata["settings"]["metadata"].isMember("useLiteralContent")); BOOST_CHECK(metadata["settings"]["metadata"].contains("useLiteralContent"));
BOOST_CHECK(metadata["settings"]["metadata"]["useLiteralContent"].asBool()); BOOST_CHECK(metadata["settings"]["metadata"]["useLiteralContent"].get<bool>());
} }
}; };
@ -353,17 +353,17 @@ BOOST_AUTO_TEST_CASE(metadata_viair)
compilerStack.setViaIR(_viaIR); compilerStack.setViaIR(_viaIR);
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
Json::Value metadata; Json metadata;
BOOST_REQUIRE(util::jsonParseStrict(compilerStack.metadata("test"), metadata)); BOOST_REQUIRE(util::jsonParseStrict(compilerStack.metadata("test"), metadata));
BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata));
BOOST_CHECK(metadata.isMember("settings")); BOOST_CHECK(metadata.contains("settings"));
if (_viaIR) if (_viaIR)
{ {
BOOST_CHECK(metadata["settings"].isMember("viaIR")); BOOST_CHECK(metadata["settings"].contains("viaIR"));
BOOST_CHECK(metadata["settings"]["viaIR"].asBool()); BOOST_CHECK(metadata["settings"]["viaIR"].get<bool>());
} }
else 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));
BOOST_CHECK(compilerStack.cborMetadata("test") != compilerStack.cborMetadata("test", !_viaIR)); BOOST_CHECK(compilerStack.cborMetadata("test") != compilerStack.cborMetadata("test", !_viaIR));
@ -393,7 +393,7 @@ BOOST_AUTO_TEST_CASE(metadata_revert_strings)
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
string const& serialisedMetadata = compilerStack.metadata("A"); string const& serialisedMetadata = compilerStack.metadata("A");
Json::Value metadata; Json metadata;
BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata));
@ -431,14 +431,14 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence)
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
string const& serialisedMetadata = compilerStack.metadata("C"); string const& serialisedMetadata = compilerStack.metadata("C");
Json::Value metadata; Json metadata;
BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata));
BOOST_CHECK(metadata["settings"]["optimizer"].isMember("details")); BOOST_CHECK(metadata["settings"]["optimizer"].contains("details"));
BOOST_CHECK(metadata["settings"]["optimizer"]["details"].isMember("yulDetails")); BOOST_CHECK(metadata["settings"]["optimizer"]["details"].contains("yulDetails"));
BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].isMember("optimizerSteps")); BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps"));
string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].asString(); string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get<string>();
string const expectedMetadataOptimiserSteps = _optimizerSequence + ":" + _optimizerCleanupSequence; string const expectedMetadataOptimiserSteps = _optimizerSequence + ":" + _optimizerCleanupSequence;
BOOST_CHECK_EQUAL(metadataOptimizerSteps, expectedMetadataOptimiserSteps); BOOST_CHECK_EQUAL(metadataOptimizerSteps, expectedMetadataOptimiserSteps);
}; };

View File

@ -431,7 +431,7 @@ TestCase::TestResult SemanticTest::runTest(
{ {
soltestAssert( soltestAssert(
m_allowNonExistingFunctions || 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" "The function " + test.call().signature + " is not known to the compiler"
); );

View File

@ -50,17 +50,17 @@ public:
m_compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); m_compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed");
Json::Value generatedDocumentation; Json generatedDocumentation;
if (_userDocumentation) if (_userDocumentation)
generatedDocumentation = m_compilerStack.natspecUser(_contractName); generatedDocumentation = m_compilerStack.natspecUser(_contractName);
else else
generatedDocumentation = m_compilerStack.natspecDev(_contractName); generatedDocumentation = m_compilerStack.natspecDev(_contractName);
Json::Value expectedDocumentation; Json expectedDocumentation;
std::string parseError; std::string parseError;
BOOST_REQUIRE_MESSAGE(util::jsonParseStrict(_expectedDocumentationString, expectedDocumentation, &parseError), parseError); BOOST_REQUIRE_MESSAGE(util::jsonParseStrict(_expectedDocumentationString, expectedDocumentation, &parseError), parseError);
expectedDocumentation["version"] = Json::Value(Natspec::c_natspecVersion); expectedDocumentation["version"] = Natspec::c_natspecVersion;
expectedDocumentation["kind"] = Json::Value(_userDocumentation ? "user" : "dev"); expectedDocumentation["kind"] = _userDocumentation ? "user" : "dev";
BOOST_CHECK_MESSAGE( BOOST_CHECK_MESSAGE(
expectedDocumentation == generatedDocumentation, expectedDocumentation == generatedDocumentation,
@ -2125,12 +2125,12 @@ BOOST_AUTO_TEST_CASE(dev_explicit_inehrit_complex)
BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed");
Json::Value generatedDocumentation = m_compilerStack.natspecDev("Token"); Json generatedDocumentation = m_compilerStack.natspecDev("Token");
Json::Value expectedDocumentation; Json expectedDocumentation;
util::jsonParseStrict(natspec, expectedDocumentation); util::jsonParseStrict(natspec, expectedDocumentation);
expectedDocumentation["version"] = Json::Value(Natspec::c_natspecVersion); expectedDocumentation["version"] = Natspec::c_natspecVersion;
expectedDocumentation["kind"] = Json::Value("dev"); expectedDocumentation["kind"] = "dev";
BOOST_CHECK_MESSAGE( BOOST_CHECK_MESSAGE(
expectedDocumentation == generatedDocumentation, expectedDocumentation == generatedDocumentation,

File diff suppressed because it is too large Load Diff

View File

@ -141,16 +141,16 @@ optional<ABIType> isFixedPoint(string const& type)
return fixedPointType; return fixedPointType;
} }
string functionSignatureFromABI(Json::Value const& _functionABI) string functionSignatureFromABI(Json const& _functionABI)
{ {
auto inputs = _functionABI["inputs"]; auto inputs = _functionABI["inputs"];
string signature = {_functionABI["name"].asString() + "("}; string signature = {_functionABI["name"].get<string>() + "("};
size_t parameterCount = 0; size_t parameterCount = 0;
for (auto const& input: inputs) for (auto const& input: inputs)
{ {
parameterCount++; parameterCount++;
signature += input["type"].asString(); signature += input["type"].get<string>();
if (parameterCount < inputs.size()) if (parameterCount < inputs.size())
signature += ","; signature += ",";
} }
@ -162,7 +162,7 @@ string functionSignatureFromABI(Json::Value const& _functionABI)
std::optional<solidity::frontend::test::ParameterList> ContractABIUtils::parametersFromJsonOutputs( std::optional<solidity::frontend::test::ParameterList> ContractABIUtils::parametersFromJsonOutputs(
ErrorReporter& _errorReporter, ErrorReporter& _errorReporter,
Json::Value const& _contractABI, Json const& _contractABI,
string const& _functionSignature string const& _functionSignature
) )
{ {
@ -178,7 +178,7 @@ std::optional<solidity::frontend::test::ParameterList> ContractABIUtils::paramet
for (auto const& output: function["outputs"]) for (auto const& output: function["outputs"])
{ {
string type = output["type"].asString(); string type = output["type"].get<string>();
ABITypes inplaceTypes; ABITypes inplaceTypes;
ABITypes dynamicTypes; ABITypes dynamicTypes;
@ -210,13 +210,13 @@ std::optional<solidity::frontend::test::ParameterList> ContractABIUtils::paramet
} }
bool ContractABIUtils::appendTypesFromName( bool ContractABIUtils::appendTypesFromName(
Json::Value const& _functionOutput, Json const& _functionOutput,
ABITypes& _inplaceTypes, ABITypes& _inplaceTypes,
ABITypes& _dynamicTypes, ABITypes& _dynamicTypes,
bool _isCompoundType bool _isCompoundType
) )
{ {
string type = _functionOutput["type"].asString(); string type = _functionOutput["type"].get<string>();
if (isBool(type)) if (isBool(type))
_inplaceTypes.push_back(ABIType{ABIType::Boolean}); _inplaceTypes.push_back(ABIType{ABIType::Boolean});
else if (isUint(type)) else if (isUint(type))

View File

@ -19,8 +19,7 @@
#include <test/libsolidity/util/SoltestErrors.h> #include <test/libsolidity/util/SoltestErrors.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/JSON.h>
#include <json/json.h>
namespace solidity::frontend::test namespace solidity::frontend::test
{ {
@ -40,7 +39,7 @@ public:
/// auto-correction during interactive update routine. /// auto-correction during interactive update routine.
static std::optional<ParameterList> parametersFromJsonOutputs( static std::optional<ParameterList> parametersFromJsonOutputs(
ErrorReporter& _errorReporter, ErrorReporter& _errorReporter,
Json::Value const& _contractABI, Json const& _contractABI,
std::string const& _functionSignature std::string const& _functionSignature
); );
@ -86,7 +85,7 @@ private:
/// `bytes` -> [`Unsigned`, `Unsigned`, `HexString`] /// `bytes` -> [`Unsigned`, `Unsigned`, `HexString`]
/// ... /// ...
static bool appendTypesFromName( static bool appendTypesFromName(
Json::Value const& _functionOutput, Json const& _functionOutput,
ABITypes& _inplaceTypes, ABITypes& _inplaceTypes,
ABITypes& _dynamicTypes, ABITypes& _dynamicTypes,
bool _isCompoundType = false bool _isCompoundType = false

View File

@ -368,7 +368,7 @@ void TestFunctionCall::reset()
{ {
m_rawBytes = bytes{}; m_rawBytes = bytes{};
m_failure = true; m_failure = true;
m_contractABI = Json::Value{}; m_contractABI = Json{};
m_calledNonExistingFunction = false; m_calledNonExistingFunction = false;
} }

View File

@ -23,8 +23,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/JSON.h> #include <libsolutil/JSON.h>
#include <json/json.h>
#include <iosfwd> #include <iosfwd>
#include <numeric> #include <numeric>
#include <stdexcept> #include <stdexcept>
@ -94,7 +92,7 @@ public:
void setFailure(const bool _failure) { m_failure = _failure; } void setFailure(const bool _failure) { m_failure = _failure; }
void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; } void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; }
void setGasCost(std::string const& _runType, u256 const& _gasCost) { m_gasCosts[_runType] = _gasCost; } void setGasCost(std::string const& _runType, u256 const& _gasCost) { m_gasCosts[_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<std::string> _sideEffects) { m_call.actualSideEffects = _sideEffects; } void setSideEffects(std::vector<std::string> _sideEffects) { m_call.actualSideEffects = _sideEffects; }
private: private:
@ -147,7 +145,7 @@ private:
bool m_failure = true; bool m_failure = true;
/// JSON object which holds the contract ABI and that is used to set the output formatting /// JSON object which holds the contract ABI and that is used to set the output formatting
/// in the interactive update routine. /// 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. /// Flags that the test failed because the called function is not known to exist on the contract.
bool m_calledNonExistingFunction = false; bool m_calledNonExistingFunction = false;
}; };

View File

@ -35,50 +35,46 @@ BOOST_AUTO_TEST_SUITE(JsonTest, *boost::unit_test::label("nooptions"))
BOOST_AUTO_TEST_CASE(json_types) BOOST_AUTO_TEST_CASE(json_types)
{ {
auto check = [](Json::Value value, string const& expectation) { auto check = [](Json value, string const& expectation) {
BOOST_CHECK(jsonCompactPrint(value) == expectation); BOOST_CHECK(jsonCompactPrint(value) == expectation);
}; };
Json::Value value; Json value;
BOOST_CHECK(value.empty()); BOOST_CHECK(value.empty());
value = {}; value = {};
BOOST_CHECK(value.empty()); BOOST_CHECK(value.empty());
value = Json::Value(); value = Json();
BOOST_CHECK(value.empty()); BOOST_CHECK(value.empty());
value = Json::nullValue; value = Json(nullptr);
BOOST_CHECK(value.empty()); BOOST_CHECK(value.empty());
check(value, "null"); check(value, "null");
check({}, "null"); check({}, "null");
check(Json::Value(), "null"); check(Json(), "null");
check(Json::nullValue, "null"); check(Json(nullptr), "null");
check(Json::objectValue, "{}"); check(Json::object(), "{}");
check(Json::arrayValue, "[]"); check(Json::array(), "[]");
check(Json::UInt(1), "1"); check(Json::number_unsigned_t(1), "1");
check(Json::UInt(-1), "4294967295"); check(Json::number_unsigned_t(-1), "18446744073709551615");
check(Json::UInt64(1), "1"); check(Json::number_unsigned_t(0xffffffff), "4294967295");
check(Json::UInt64(-1), "18446744073709551615"); check(Json("test"), "\"test\"");
check(Json::LargestUInt(1), "1");
check(Json::LargestUInt(-1), "18446744073709551615");
check(Json::LargestUInt(0xffffffff), "4294967295");
check(Json::Value("test"), "\"test\"");
check("test", "\"test\""); check("test", "\"test\"");
check(true, "true"); check(true, "true");
value = Json::objectValue; value = Json::object();
value["key"] = "value"; value["key"] = "value";
check(value, "{\"key\":\"value\"}"); check(value, "{\"key\":\"value\"}");
value = Json::arrayValue; value = Json::array();
value.append(1); value.emplace_back(1);
value.append(2); value.emplace_back(2);
check(value, "[1,2]"); check(value, "[1,2]");
} }
BOOST_AUTO_TEST_CASE(json_pretty_print) BOOST_AUTO_TEST_CASE(json_pretty_print)
{ {
Json::Value json; Json json;
Json::Value jsonChild; Json jsonChild;
jsonChild["3.1"] = "3.1"; jsonChild["3.1"] = "3.1";
jsonChild["3.2"] = 2; jsonChild["3.2"] = 2;
@ -104,8 +100,8 @@ BOOST_AUTO_TEST_CASE(json_pretty_print)
BOOST_AUTO_TEST_CASE(json_compact_print) BOOST_AUTO_TEST_CASE(json_compact_print)
{ {
Json::Value json; Json json;
Json::Value jsonChild; Json jsonChild;
jsonChild["3.1"] = "3.1"; jsonChild["3.1"] = "3.1";
jsonChild["3.2"] = 2; jsonChild["3.2"] = 2;
@ -123,7 +119,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) // 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/) // and ECMA-404 (https://www.ecma-international.org/publications-and-standards/standards/ecma-404/)
Json::Value json; Json json;
std::string errors; std::string errors;
// Just parse a valid json input // Just parse a valid json input
@ -135,31 +131,28 @@ BOOST_AUTO_TEST_CASE(parse_json_strict)
// Trailing garbage is not allowed in ECMA-262 // 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)); BOOST_CHECK(!jsonParseStrict("{\"1\":2,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":3}}}}}}}}}}", json, &errors));
BOOST_CHECK(errors == "[json.exception.parse_error.101] parse error at line 1, column 42: syntax error while parsing value - unexpected '}'; expected end of input");
// Comments are not allowed in ECMA-262 // Comments are not allowed in ECMA-262
// ... but JSONCPP allows them BOOST_CHECK(!jsonParseStrict(
BOOST_CHECK(jsonParseStrict(
"{\"1\":3, // awesome comment\n\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":5}}", json, &errors "{\"1\":3, // awesome comment\n\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":5}}", json, &errors
)); ));
BOOST_CHECK(json["1"] == 3); BOOST_CHECK(errors == "[json.exception.parse_error.101] parse error at line 1, column 9: syntax error while parsing object key - invalid literal; last read: '3, /'; expected string literal");
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 // According to ECMA-404 object, array, number, string, true, false, null are allowed
// ... but JSONCPP disallows value types // ... but JSONCPP disallows value types
BOOST_CHECK(jsonParseStrict("[]", json, &errors)); BOOST_CHECK(jsonParseStrict("[]", json, &errors));
BOOST_CHECK(json.isArray()); BOOST_CHECK(json.is_array());
BOOST_CHECK(jsonParseStrict("{}", json, &errors)); BOOST_CHECK(jsonParseStrict("{}", json, &errors));
BOOST_CHECK(json.isObject()); BOOST_CHECK(json.is_object());
BOOST_CHECK(!jsonParseStrict("1", json, &errors)); BOOST_CHECK(jsonParseStrict("1", json, &errors));
// BOOST_CHECK(json.isNumeric()); BOOST_CHECK(json.is_number());
BOOST_CHECK(!jsonParseStrict("\"hello\"", json, &errors)); BOOST_CHECK(jsonParseStrict("\"hello\"", json, &errors));
// BOOST_CHECK(json.isString()); BOOST_CHECK(json.is_string());
BOOST_CHECK(!jsonParseStrict("true", json, &errors)); BOOST_CHECK(jsonParseStrict("true", json, &errors));
// BOOST_CHECK(json.isBool()); BOOST_CHECK(json.is_boolean());
BOOST_CHECK(!jsonParseStrict("null", json, &errors)); BOOST_CHECK(jsonParseStrict("null", json, &errors));
// BOOST_CHECK(json.isNull()); BOOST_CHECK(json.is_null());
// Single quotes are also disallowed by ECMA-404 // Single quotes are also disallowed by ECMA-404
BOOST_CHECK(!jsonParseStrict("'hello'", json, &errors)); BOOST_CHECK(!jsonParseStrict("'hello'", json, &errors));
@ -172,15 +165,12 @@ BOOST_AUTO_TEST_CASE(parse_json_strict)
// a few control characters (\b, \f, \n, \r, \t) // 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. // More lenient parsers allow hex escapes as long as they translate to a valid UTF-8 encoding.
// BOOST_CHECK(!jsonParseStrict("[ \"\x80\xec\x80\" ]", json, &errors));
// ... but JSONCPP allows any hex escapes BOOST_CHECK(errors == "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"?'");
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. // This would be valid more lenient parsers.
BOOST_CHECK(jsonParseStrict("[ \"\xF0\x9F\x98\x8A\" ]", json, &errors)); 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] == "😊");
} }

View File

@ -1018,6 +1018,16 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
BOOST_TEST(result.reader.basePath() == expectedWorkDir / "base/"); BOOST_TEST(result.reader.basePath() == expectedWorkDir / "base/");
} }
namespace {
set<string> getMemberNames(Json const& _json)
{
set<string> keys;
for (auto const& [key, _]: _json.items())
keys.insert(key);
return keys;
}
}
BOOST_AUTO_TEST_CASE(standard_json_include_paths) BOOST_AUTO_TEST_CASE(standard_json_include_paths)
{ {
TemporaryDirectory tempDir({"base/", "include/", "lib/nested/"}, TEST_CASE_NAME); TemporaryDirectory tempDir({"base/", "include/", "lib/nested/"}, TEST_CASE_NAME);
@ -1094,15 +1104,15 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths)
OptionsReaderAndMessages result = runCLI(commandLine, standardJsonInput); OptionsReaderAndMessages result = runCLI(commandLine, standardJsonInput);
Json::Value parsedStdout; Json parsedStdout;
string jsonParsingErrors; string jsonParsingErrors;
BOOST_TEST(util::jsonParseStrict(result.stdoutContent, parsedStdout, &jsonParsingErrors)); BOOST_TEST(util::jsonParseStrict(result.stdoutContent, parsedStdout, &jsonParsingErrors));
BOOST_TEST(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 // The error list might contain pre-release compiler warning
BOOST_TEST(errorDict["severity"] != "error"); BOOST_TEST(errorDict["severity"] != "error");
BOOST_TEST( BOOST_TEST(
(parsedStdout["sources"].getMemberNames() | ranges::to<set>) == (getMemberNames(parsedStdout["sources"]) | ranges::to<set>) ==
(expectedSources | ranges::views::keys | ranges::to<set>) + set<string>{"main.sol"} (expectedSources | ranges::views::keys | ranges::to<set>) + set<string>{"main.sol"}
); );

View File

@ -56,13 +56,13 @@ void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize,
if (!_quiet) if (!_quiet)
cout << "Testing compiler " << (_optimize ? "with" : "without") << " optimizer." << endl; cout << "Testing compiler " << (_optimize ? "with" : "without") << " optimizer." << endl;
Json::Value config = Json::objectValue; Json config = Json::object();
config["language"] = "Solidity"; config["language"] = "Solidity";
config["sources"] = Json::objectValue; config["sources"] = Json::object();
config["sources"][""] = Json::objectValue; config["sources"][""] = Json::object();
config["sources"][""]["content"] = _input; config["sources"][""]["content"] = _input;
config["settings"] = Json::objectValue; config["settings"] = Json::object();
config["settings"]["optimizer"] = Json::objectValue; config["settings"]["optimizer"] = Json::object();
config["settings"]["optimizer"]["enabled"] = _optimize; config["settings"]["optimizer"]["enabled"] = _optimize;
config["settings"]["optimizer"]["runs"] = static_cast<int>(OptimiserSettings{}.expectedExecutionsPerDeployment); config["settings"]["optimizer"]["runs"] = static_cast<int>(OptimiserSettings{}.expectedExecutionsPerDeployment);
config["settings"]["evmVersion"] = "berlin"; config["settings"]["evmVersion"] = "berlin";
@ -146,23 +146,23 @@ void FuzzerUtil::runCompiler(string const& _input, bool _quiet)
// This should be safe given the above copies the output. // This should be safe given the above copies the output.
solidity_reset(); solidity_reset();
Json::Value output; Json output;
if (!jsonParseStrict(outputString, output)) if (!jsonParseStrict(outputString, output))
{ {
string msg{"Compiler produced invalid JSON output."}; string msg{"Compiler produced invalid JSON output."};
cout << msg << endl; cout << msg << endl;
BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg)));
} }
if (output.isMember("errors")) if (output.contains("errors"))
for (auto const& error: output["errors"]) for (auto const& error: output["errors"])
{ {
string invalid = findAnyOf(error["type"].asString(), vector<string>{ string invalid = findAnyOf(error["type"].get<string>(), vector<string>{
"Exception", "Exception",
"InternalCompilerError" "InternalCompilerError"
}); });
if (!invalid.empty()) if (!invalid.empty())
{ {
string msg = "Invalid error: \"" + error["type"].asString() + "\""; string msg = "Invalid error: \"" + error["type"].get<string>() + "\"";
cout << msg << endl; cout << msg << endl;
BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg)));
} }

View File

@ -58,7 +58,7 @@ optional<CompilerOutput> SolidityCompilationFramework::compileContract()
else else
contractName = m_compilerInput.contractName; contractName = m_compilerInput.contractName;
evmasm::LinkerObject obj = m_compiler.object(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}; 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 // isabelle test entry point. At the moment, we are sure that the
// entry point is the second method in the contract (hence the ++) // entry point is the second method in the contract (hence the ++)
// but not its name. // but not its name.
methodName = (++cOutput->methodIdentifiersInContract.begin())->asString() + methodName = (++cOutput->methodIdentifiersInContract.begin())->get<string>() +
_fuzzIsabelle.substr(2, _fuzzIsabelle.size()); _fuzzIsabelle.substr(2, _fuzzIsabelle.size());
else else
methodName = cOutput->methodIdentifiersInContract[m_methodName].asString(); methodName = cOutput->methodIdentifiersInContract[m_methodName].get<string>();
return deployAndExecute( return deployAndExecute(
cOutput->byteCode, cOutput->byteCode,

View File

@ -35,7 +35,7 @@ struct CompilerOutput
/// EVM bytecode returned by compiler /// EVM bytecode returned by compiler
solidity::bytes byteCode; solidity::bytes byteCode;
/// Method identifiers in a contract /// Method identifiers in a contract
Json::Value methodIdentifiersInContract; Json methodIdentifiersInContract;
}; };
struct CompilerInput struct CompilerInput
@ -89,7 +89,7 @@ public:
m_compilerInput.libraryAddresses = std::move(_libraryAddresses); m_compilerInput.libraryAddresses = std::move(_libraryAddresses);
} }
/// @returns method identifiers in contract called @param _contractName. /// @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"]; return m_compiler.interfaceSymbols(_contractName)["methods"];
} }

View File

@ -381,7 +381,7 @@ BOOST_AUTO_TEST_CASE(toJson)
CharStream sourceStream(sourceCode, current_test_case().p_name); CharStream sourceStream(sourceCode, current_test_case().p_name);
Program program = get<Program>(Program::load(sourceStream)); Program program = get<Program>(Program::load(sourceStream));
Json::Value parsingResult; Json parsingResult;
string errors; string errors;
BOOST_TEST(jsonParseStrict(program.toJson(), parsingResult, &errors)); BOOST_TEST(jsonParseStrict(program.toJson(), parsingResult, &errors));
BOOST_TEST(errors.empty()); BOOST_TEST(errors.empty());

View File

@ -112,7 +112,7 @@ ostream& phaser::operator<<(ostream& _stream, Program const& _program)
string Program::toJson() const string Program::toJson() const
{ {
Json::Value serializedAst = AsmJsonConverter(0)(*m_ast); Json serializedAst = AsmJsonConverter(0)(*m_ast);
return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst)));
} }