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
include(EthDependencies)
include(fmtlib)
include(jsoncpp)
include(nlohmann-json)
include(range-v3)
include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR})
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
THE SOFTWARE.
jsoncpp:
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
nlohmann-json:
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
| | |__ | | | | | | version 3.10.2
|_____|_____|_____|_|___| https://github.com/nlohmann/json
The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by The JsonCpp Authors, and is
released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
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
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:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
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:
The liblangutil/{CharStream,Scanner,Token}.{h,cpp} files are derived from

View File

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

View File

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

View File

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

View File

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

View File

@ -26,10 +26,8 @@
#include <libsolidity/ast/ASTAnnotations.h>
#include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/interface/CompilerStack.h>
#include <liblangutil/Exceptions.h>
#include <json/json.h>
#include <libsolutil/JSON.h>
#include <liblangutil/Exceptions.h>
#include <algorithm>
#include <optional>
@ -60,16 +58,16 @@ public:
);
/// Output the json representation of the AST to _stream.
void print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format);
Json::Value toJson(ASTNode const& _node);
Json toJson(ASTNode const& _node);
template <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)
if (n)
appendMove(ret, toJson(*n));
else
ret.append(Json::nullValue);
ret.emplace_back(Json{});
return ret;
}
bool visit(SourceUnit const& _node) override;
@ -134,27 +132,27 @@ private:
void setJsonNode(
ASTNode const& _node,
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(
ASTNode const& _node,
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.
std::optional<size_t> sourceIndexFromLocation(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 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 contractKind(ContractKind _kind);
static std::string functionCallKind(FunctionCallKind _kind);
@ -166,7 +164,7 @@ private:
return _node.id();
}
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;
@ -177,28 +175,27 @@ private:
}
if (_order)
std::sort(tmp.begin(), tmp.end());
Json::Value json(Json::arrayValue);
Json json{Json::array()};
for (int64_t val: tmp)
json.append(val);
json.emplace_back(val);
return json;
}
static Json::Value typePointerToJson(Type const* _tp, bool _withoutDataLocation = false);
static Json::Value typePointerToJson(std::optional<FuncCallArguments> const& _tps);
static Json typePointerToJson(Type const* _tp, bool _withoutDataLocation = false);
static Json typePointerToJson(std::optional<FuncCallArguments> const& _tps);
void appendExpressionAttributes(
std::vector<std::pair<std::string, Json::Value>> &_attributes,
std::vector<std::pair<std::string, Json>> &_attributes,
ExpressionAnnotation const& _annotation
);
static void appendMove(Json::Value& _array, Json::Value&& _value)
static void appendMove(Json& _array, Json&& _value)
{
solAssert(_array.isArray(), "");
_array.append(std::move(_value));
solAssert(_array.is_array(), "");
_array.emplace_back(std::move(_value));
}
CompilerStack::State m_stackState = CompilerStack::State::Empty; ///< Used to only access information that already exists
bool m_inEvent = false; ///< whether we are currently inside an event or not
Json::Value m_currentValue;
Json m_currentValue;
std::map<std::string, unsigned> m_sourceIndices;
};

View File

@ -44,9 +44,9 @@ namespace solidity::frontend
using SourceLocation = langutil::SourceLocation;
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;
else
return dynamic_pointer_cast<T>(convertJsonToASTNode(_json));
@ -55,13 +55,13 @@ ASTPointer<T> ASTJsonImporter::nullOrCast(Json::Value const& _json)
// ============ 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)
m_sourceNames.emplace_back(make_shared<string const>(src.first));
for (auto const& srcPair: _sourceList)
{
astAssert(!srcPair.second.isNull());
astAssert(!srcPair.second.is_null(), "");
astAssert(member(srcPair.second,"nodeType") == "SourceUnit", "The 'nodeType' of the highest node must be 'SourceUnit'.");
m_sourceUnits[srcPair.first] = createSourceUnit(srcPair.second, srcPair.first);
}
@ -72,11 +72,11 @@ map<string, ASTPointer<SourceUnit>> ASTJsonImporter::jsonToSourceUnit(map<string
// =========== general creation functions ==============
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!");
@ -88,36 +88,36 @@ ASTPointer<T> ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&...
return n;
}
SourceLocation const ASTJsonImporter::createSourceLocation(Json::Value const& _node)
SourceLocation const ASTJsonImporter::createSourceLocation(Json const& _node)
{
astAssert(member(_node, "src").isString(), "'src' must be a string");
astAssert(member(_node, "src").is_string(), "'src' must be a string");
return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames);
return solidity::langutil::parseSourceLocation(_node["src"].get<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;
if (_node.isMember("nameLocations") && _node["nameLocations"].isArray())
if (_node.contains("nameLocations") && _node["nameLocations"].is_array())
{
for (auto const& val: _node["nameLocations"])
locations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames));
locations.emplace_back(langutil::parseSourceLocation(val.get<string>(), m_sourceNames));
return locations;
}
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>
ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node)
ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json const& _node)
{
ASTPointer<T> ret = dynamic_pointer_cast<T>(convertJsonToASTNode(_node));
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.");
string nodeType = _json["nodeType"].asString();
astAssert(_json["nodeType"].is_string() && _json.contains("id"), "JSON-Node needs to have 'nodeType' and 'id' fields.");
string nodeType = _json["nodeType"].get<string>();
if (nodeType == "PragmaDirective")
return createPragmaDirective(_json);
if (nodeType == "ImportDirective")
@ -250,11 +250,11 @@ ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js
// ============ 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;
if (_node.isMember("license") && !_node["license"].isNull())
license = _node["license"].asString();
if (_node.contains("license") && !_node["license"].is_null())
license = _node["license"].get<string>();
vector<ASTPointer<ASTNode>> nodes;
for (auto& child: member(_node, "nodes"))
@ -265,20 +265,20 @@ ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _nod
return tmp;
}
ASTPointer<PragmaDirective> ASTJsonImporter::createPragmaDirective(Json::Value const& _node)
ASTPointer<PragmaDirective> ASTJsonImporter::createPragmaDirective(Json const& _node)
{
vector<Token> tokens;
vector<ASTString> literals;
for (auto const& lit: member(_node, "literals"))
{
string l = lit.asString();
string l = lit.get<string>();
literals.push_back(l);
tokens.push_back(scanSingleToken(l));
}
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> path = memberAsASTString(_node, "file");
@ -286,11 +286,11 @@ ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json::Value c
for (auto& tuple: member(_node, "symbolAliases"))
{
astAssert(tuple["local"].isNull() || tuple["local"].isString(), "expected 'local' to be a string or null!");
astAssert(tuple["local"].is_null() || tuple["local"].is_string(), "expected 'local' to be a string or null!");
symbolAliases.push_back({
createIdentifier(tuple["foreign"]),
tuple["local"].isNull() ? nullptr : make_shared<ASTString>(tuple["local"].asString()),
tuple["local"].is_null() ? nullptr : make_shared<ASTString>(tuple["local"].get<string>()),
createSourceLocation(tuple["foreign"])}
);
}
@ -302,15 +302,15 @@ ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json::Value c
std::move(symbolAliases)
);
astAssert(_node["absolutePath"].isString(), "Expected 'absolutePath' to be a string!");
astAssert(_node["absolutePath"].is_string(), "Expected 'absolutePath' to be a string!");
tmp->annotation().absolutePath = _node["absolutePath"].asString();
tmp->annotation().absolutePath = _node["absolutePath"].get<string>();
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;
@ -324,9 +324,9 @@ ASTPointer<ContractDefinition> ASTJsonImporter::createContractDefinition(Json::V
return createASTNode<ContractDefinition>(
_node,
make_shared<ASTString>(_node["name"].asString()),
make_shared<ASTString>(_node["name"].get<string>()),
createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
_node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
baseContracts,
subNodes,
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<SourceLocation> namePathLocations;
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("."));
astAssert(!strs.empty(), "Expected at least one element in IdentifierPath.");
for (string s: strs)
@ -350,9 +350,9 @@ ASTPointer<IdentifierPath> ASTJsonImporter::createIdentifierPath(Json::Value con
namePath.emplace_back(s);
}
if (_node.isMember("nameLocations") && _node["nameLocations"].isArray())
if (_node.contains("nameLocations") && _node["nameLocations"].is_array())
for (auto const& val: _node["nameLocations"])
namePathLocations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames));
namePathLocations.emplace_back(langutil::parseSourceLocation(val.get<string>(), m_sourceNames));
else
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;
for (auto& arg: member(_node, "arguments"))
@ -376,29 +376,29 @@ ASTPointer<InheritanceSpecifier> ASTJsonImporter::createInheritanceSpecifier(Jso
return createASTNode<InheritanceSpecifier>(
_node,
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;
if (_node.isMember("libraryName"))
if (_node.contains("libraryName"))
functions.emplace_back(createIdentifierPath(_node["libraryName"]));
else if (_node.isMember("functionList"))
for (Json::Value const& function: _node["functionList"])
else if (_node.contains("functionList"))
for (Json const& function: _node["functionList"])
functions.emplace_back(createIdentifierPath(function["function"]));
return createASTNode<UsingForDirective>(
_node,
std::move(functions),
!_node.isMember("libraryName"),
_node["typeName"].isNull() ? nullptr : convertJsonToASTNode<TypeName>(_node["typeName"]),
!_node.contains("libraryName"),
_node["typeName"].is_null() ? nullptr : convertJsonToASTNode<TypeName>(_node["typeName"]),
memberAsBool(_node, "global")
);
}
ASTPointer<ASTNode> ASTJsonImporter::createStructDefinition(Json::Value const& _node)
ASTPointer<ASTNode> ASTJsonImporter::createStructDefinition(Json const& _node)
{
std::vector<ASTPointer<VariableDeclaration>> 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;
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>(
_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>(
_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;
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;
@ -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;
bool freeFunction = false;
string kindStr = member(_node, "kind").asString();
string kindStr = member(_node, "kind").get<string>();
if (kindStr == "constructor")
kind = Token::Constructor;
@ -509,8 +509,8 @@ ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::V
freeFunction,
kind,
memberAsBool(_node, "virtual"),
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
_node["overrides"].is_null() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
_node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters")),
modifiers,
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{};
astAssert(member(_node, "mutability").isString(), "'mutability' expected to be string.");
string const mutabilityStr = member(_node, "mutability").asString();
astAssert(member(_node, "mutability").is_string(), "'mutability' expected to be string.");
string const mutabilityStr = member(_node, "mutability").get<string>();
if (mutabilityStr == "constant")
{
mutability = VariableDeclaration::Mutability::Constant;
@ -544,33 +544,33 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
return createASTNode<VariableDeclaration>(
_node,
nullOrCast<TypeName>(member(_node, "typeName")),
make_shared<ASTString>(member(_node, "name").asString()),
make_shared<ASTString>(member(_node, "name").get<string>()),
createNameSourceLocation(_node),
nullOrCast<Expression>(member(_node, "value")),
visibility(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
_node.isMember("indexed") ? memberAsBool(_node, "indexed") : false,
_node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
_node.contains("indexed") ? memberAsBool(_node, "indexed") : false,
mutability,
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
_node["overrides"].is_null() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
location(_node)
);
}
ASTPointer<ModifierDefinition> ASTJsonImporter::createModifierDefinition(Json::Value const& _node)
ASTPointer<ModifierDefinition> ASTJsonImporter::createModifierDefinition(Json const& _node)
{
return createASTNode<ModifierDefinition>(
_node,
memberAsASTString(_node, "name"),
createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
_node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters")),
memberAsBool(_node, "virtual"),
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
_node["body"].isNull() ? nullptr: createBlock(member(_node, "body"), false)
_node["overrides"].is_null() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
_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;
for (auto& arg: member(_node, "arguments"))
@ -578,53 +578,53 @@ ASTPointer<ModifierInvocation> ASTJsonImporter::createModifierInvocation(Json::V
return createASTNode<ModifierInvocation>(
_node,
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>(
_node,
memberAsASTString(_node, "name"),
createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
_node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters")),
memberAsBool(_node, "anonymous")
);
}
ASTPointer<ErrorDefinition> ASTJsonImporter::createErrorDefinition(Json::Value const& _node)
ASTPointer<ErrorDefinition> ASTJsonImporter::createErrorDefinition(Json const& _node)
{
return createASTNode<ErrorDefinition>(
_node,
memberAsASTString(_node, "name"),
createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
_node["documentation"].is_null() ? nullptr : createDocumentation(member(_node, "documentation")),
createParameterList(member(_node, "parameters"))
);
}
ASTPointer<ElementaryTypeName> ASTJsonImporter::createElementaryTypeName(Json::Value const& _node)
ASTPointer<ElementaryTypeName> ASTJsonImporter::createElementaryTypeName(Json const& _node)
{
unsigned short firstNum;
unsigned short secondNum;
astAssert(_node["name"].isString(), "Expected 'name' to be a string!");
astAssert(_node["name"].is_string(), "Expected 'name' to be a string!");
string name = member(_node, "name").asString();
string name = member(_node, "name").get<string>();
Token token;
tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name);
ElementaryTypeNameToken elem(token, firstNum, secondNum);
std::optional<StateMutability> mutability = {};
if (_node.isMember("stateMutability"))
if (_node.contains("stateMutability"))
mutability = stateMutability(_node);
return createASTNode<ElementaryTypeName>(_node, elem, mutability);
}
ASTPointer<UserDefinedTypeName> ASTJsonImporter::createUserDefinedTypeName(Json::Value const& _node)
ASTPointer<UserDefinedTypeName> ASTJsonImporter::createUserDefinedTypeName(Json const& _node)
{
return createASTNode<UserDefinedTypeName>(
_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>(
_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>(
_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>(
_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!");
auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].asString());
astAssert(_node["evmVersion"].is_string(), "Expected evmVersion to be a string!");
auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].get<string>());
astAssert(evmVersion.has_value(), "Invalid EVM version!");
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
ASTPointer<vector<ASTPointer<ASTString>>> flags;
if (_node.isMember("flags"))
if (_node.contains("flags"))
{
flags = make_shared<vector<ASTPointer<ASTString>>>();
Json::Value const& flagsNode = _node["flags"];
astAssert(flagsNode.isArray(), "Assembly flags must be an array.");
for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i)
Json const& flagsNode = _node["flags"];
astAssert(flagsNode.is_array(), "Assembly flags must be an array.");
for (Json const& flag: flagsNode)
{
astAssert(flagsNode[i].isString(), "Assembly flag must be a string.");
flags->emplace_back(make_shared<ASTString>(flagsNode[i].asString()));
astAssert(flag.is_string(), "Assembly flag must be a string.");
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")));
@ -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;
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>(
_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>(
_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>(
_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;
@ -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>(
_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>(
_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>(
_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>(
_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>(
_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>(
_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>(
_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>(
_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;
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>(
_node,
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>(
_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>(
_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>(
_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;
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>(
_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>(
_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;
for (auto& arg: member(_node, "arguments"))
@ -904,8 +904,8 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
std::vector<ASTPointer<ASTString>> names;
for (auto& name: member(_node, "names"))
{
astAssert(name.isString(), "Expected 'names' members to be strings!");
names.push_back(make_shared<ASTString>(name.asString()));
astAssert(name.is_string(), "Expected 'names' members to be strings!");
names.push_back(make_shared<ASTString>(name.get<string>()));
}
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;
for (auto& option: member(_node, "options"))
@ -929,8 +929,8 @@ ASTPointer<FunctionCallOptions> ASTJsonImporter::createFunctionCallOptions(Json:
std::vector<ASTPointer<ASTString>> names;
for (auto& name: member(_node, "names"))
{
astAssert(name.isString(), "Expected 'names' members to be strings!");
names.push_back(make_shared<ASTString>(name.asString()));
astAssert(name.is_string(), "Expected 'names' members to be strings!");
names.push_back(make_shared<ASTString>(name.get<string>()));
}
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>(
_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;
if (member(_node, "memberLocation").isString())
memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].asString(), m_sourceNames);
if (member(_node, "memberLocation").is_string())
memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].get<string>(), m_sourceNames);
return createASTNode<MemberAccess>(
_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>(
_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>(
_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"));
}
ASTPointer<ElementaryTypeNameExpression> ASTJsonImporter::createElementaryTypeNameExpression(Json::Value const& _node)
ASTPointer<ElementaryTypeNameExpression> ASTJsonImporter::createElementaryTypeNameExpression(Json const& _node)
{
return createASTNode<ElementaryTypeNameExpression>(
_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 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) ?
make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].asString()))) :
make_shared<ASTString>(_node[valStr].asString());
ASTPointer<ASTString> value = _node.contains(hexValStr) ?
make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].get<string>()))) :
make_shared<ASTString>(_node[valStr].get<string>());
return createASTNode<Literal>(
_node,
literalTokenKind(_node),
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";
astAssert(member(_node, textString).isString(), "'text' must be a string");
astAssert(member(_node, textString).is_string(), "'text' must be a string");
return createASTNode<StructuredDocumentation>(
_node,
make_shared<ASTString>(_node[textString].asString())
make_shared<ASTString>(_node[textString].get<string>())
);
}
// ===== 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))
return Json::nullValue;
if (!_node.contains(_name))
return Json{};
return _node[_name];
}
Token ASTJsonImporter::scanSingleToken(Json::Value const& _node)
Token ASTJsonImporter::scanSingleToken(Json const& _node)
{
langutil::CharStream charStream(_node.asString(), "");
langutil::CharStream charStream(_node.get<string>(), "");
langutil::Scanner scanner{charStream};
astAssert(scanner.peekNextToken() == Token::EOS, "Token string is too long.");
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);
astAssert(value.isString(), "field " + _name + " must be of type string.");
return make_shared<ASTString>(_node[_name].asString());
Json value = member(_node, _name);
astAssert(value.is_string(), "field " + _name + " must be of type string.");
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);
astAssert(value.isBool(), "field " + _name + " must be of type boolean.");
return _node[_name].asBool();
Json value = member(_node, _name);
astAssert(value.is_boolean(), "field " + _name + " must be of type boolean.");
return _node[_name].get<bool>();
}
// =========== JSON to definition helpers =======================
ContractKind ASTJsonImporter::contractKind(Json::Value const& _node)
ContractKind ASTJsonImporter::contractKind(Json const& _node)
{
ContractKind kind;
astAssert(!member(_node, "contractKind").isNull(), "'Contract-kind' can not be null.");
if (_node["contractKind"].asString() == "interface")
astAssert(!member(_node, "contractKind").is_null(), "'Contract-kind' can not be null.");
if (_node["contractKind"].get<string>() == "interface")
kind = ContractKind::Interface;
else if (_node["contractKind"].asString() == "contract")
else if (_node["contractKind"].get<string>() == "contract")
kind = ContractKind::Contract;
else if (_node["contractKind"].asString() == "library")
else if (_node["contractKind"].get<string>() == "library")
kind = ContractKind::Library;
else
astAssert(false, "Unknown ContractKind");
return kind;
}
Token ASTJsonImporter::literalTokenKind(Json::Value const& _node)
Token ASTJsonImporter::literalTokenKind(Json const& _node)
{
astAssert(member(_node, "kind").isString(), "Token-'kind' expected to be a string.");
astAssert(member(_node, "kind").is_string(), "Token-'kind' expected to be a string.");
Token tok;
if (_node["kind"].asString() == "number")
if (_node["kind"].get<string>() == "number")
tok = Token::Number;
else if (_node["kind"].asString() == "string")
else if (_node["kind"].get<string>() == "string")
tok = Token::StringLiteral;
else if (_node["kind"].asString() == "unicodeString")
else if (_node["kind"].get<string>() == "unicodeString")
tok = Token::UnicodeStringLiteral;
else if (_node["kind"].asString() == "hexString")
else if (_node["kind"].get<string>() == "hexString")
tok = Token::HexStringLiteral;
else if (_node["kind"].asString() == "bool")
tok = (member(_node, "value").asString() == "true") ? Token::TrueLiteral : Token::FalseLiteral;
else if (_node["kind"].get<string>() == "bool")
tok = (member(_node, "value").get<string>() == "true") ? Token::TrueLiteral : Token::FalseLiteral;
else
astAssert(false, "Unknown kind of literalString");
return tok;
}
Visibility ASTJsonImporter::visibility(Json::Value const& _node)
Visibility ASTJsonImporter::visibility(Json const& _node)
{
Json::Value visibility = member(_node, "visibility");
astAssert(visibility.isString(), "'visibility' expected to be a string.");
Json visibility = member(_node, "visibility");
astAssert(visibility.is_string(), "'visibility' expected to be a string.");
string const visibilityStr = visibility.asString();
string const visibilityStr = visibility.get<string>();
if (visibilityStr == "default")
return Visibility::Default;
@ -1123,12 +1123,12 @@ Visibility ASTJsonImporter::visibility(Json::Value const& _node)
util::unreachable();
}
VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node)
VariableDeclaration::Location ASTJsonImporter::location(Json const& _node)
{
Json::Value storageLoc = member(_node, "storageLocation");
astAssert(storageLoc.isString(), "'storageLocation' expected to be a string.");
Json storageLoc = member(_node, "storageLocation");
astAssert(storageLoc.is_string(), "'storageLocation' expected to be a string.");
string const storageLocStr = storageLoc.asString();
string const storageLocStr = storageLoc.get<string>();
if (storageLocStr == "default")
return VariableDeclaration::Location::Unspecified;
@ -1145,16 +1145,16 @@ VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node
util::unreachable();
}
Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _node)
Literal::SubDenomination ASTJsonImporter::subdenomination(Json const& _node)
{
Json::Value subDen = member(_node, "subdenomination");
Json subDen = member(_node, "subdenomination");
if (subDen.isNull())
if (subDen.is_null())
return Literal::SubDenomination::None;
astAssert(subDen.isString(), "'subDenomination' expected to be string.");
astAssert(subDen.is_string(), "'subDenomination' expected to be string.");
string const subDenStr = subDen.asString();
string const subDenStr = subDen.get<string>();
if (subDenStr == "wei")
return Literal::SubDenomination::Wei;
@ -1181,10 +1181,10 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no
util::unreachable();
}
StateMutability ASTJsonImporter::stateMutability(Json::Value const& _node)
StateMutability ASTJsonImporter::stateMutability(Json const& _node)
{
astAssert(member(_node, "stateMutability").isString(), "StateMutability' expected to be string.");
string const mutabilityStr = member(_node, "stateMutability").asString();
astAssert(member(_node, "stateMutability").is_string(), "StateMutability' expected to be string.");
string const mutabilityStr = member(_node, "stateMutability").get<string>();
if (mutabilityStr == "pure")
return StateMutability::Pure;

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,10 +26,10 @@
#pragma once
#include <json/json.h>
#include <memory>
#include <string>
#include <libsolidity/ast/AST.h>
#include <libsolutil/JSON.h>
namespace solidity::frontend
{
@ -46,32 +46,32 @@ public:
/// Get the User documentation of the contract
/// @param _contractDef The contract definition
/// @return A JSON representation of the contract's user documentation
static Json::Value userDocumentation(ContractDefinition const& _contractDef);
static Json userDocumentation(ContractDefinition const& _contractDef);
/// Generates the Developer's documentation of the contract
/// @param _contractDef The contract definition
/// @return A JSON representation
/// of the contract's developer documentation
static Json::Value devDocumentation(ContractDefinition const& _contractDef);
static Json devDocumentation(ContractDefinition const& _contractDef);
private:
/// @returns concatenation of all content under the given tag name.
static std::string extractDoc(std::multimap<std::string, DocTag> const& _tags, std::string const& _name);
/// 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.
/// @param _tags docTags that are used.
/// @return A JSON representation
/// 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.
/// @param _tags docTags that are used.
/// @param _returnParameterNames names of the return parameters
/// @return A JSON representation
/// of a method's return notice documentation
static Json::Value extractReturnParameterDocs(std::multimap<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
/// 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
/// output. Parsing errors are returned as regular errors.
std::string compile(std::string const& _input) noexcept;
static Json::Value formatFunctionDebugData(
static Json formatFunctionDebugData(
std::map<std::string, evmasm::LinkerObject::FunctionDebugData> const& _debugInfo
);
@ -71,7 +71,7 @@ private:
struct InputsAndSettings
{
std::string language;
Json::Value errors;
Json errors;
bool parserErrorRecovery = false;
CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful;
std::map<std::string, std::string> sources;
@ -85,17 +85,17 @@ private:
bool metadataLiteralSources = false;
CompilerStack::MetadataFormat metadataFormat = CompilerStack::defaultMetadataFormat();
CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS;
Json::Value outputSelection;
Json outputSelection;
ModelCheckerSettings modelCheckerSettings = ModelCheckerSettings{};
bool viaIR = false;
};
/// Parses the input json (and potentially invokes the read callback) and either returns
/// it in condensed form or an error as a json object.
std::variant<InputsAndSettings, Json::Value> parseInput(Json::Value const& _input);
std::variant<InputsAndSettings, Json> parseInput(Json const& _input);
Json::Value compileSolidity(InputsAndSettings _inputsAndSettings);
Json::Value compileYul(InputsAndSettings _inputsAndSettings);
Json compileSolidity(InputsAndSettings _inputsAndSettings);
Json compileYul(InputsAndSettings _inputsAndSettings);
ReadCallback::Callback m_readFile;

View File

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

View File

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

View File

@ -32,7 +32,7 @@ using namespace solidity::langutil;
using namespace solidity::lsp;
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);
@ -59,8 +59,8 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
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)
reply.append(toJson(location));
reply.emplace_back(toJson(location));
client().reply(_id, reply);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -22,7 +22,7 @@
#include <libsolidity/interface/CompilerStack.h>
#include <libsolidity/interface/FileReader.h>
#include <json/value.h>
#include <libsolutil/JSON.h>
#include <functional>
#include <map>
@ -85,29 +85,29 @@ private:
/// Checks if the server is initialized (to be used by messages that need it to be initialized).
/// Reports an error and returns false if not.
void requireServerInitialized();
void handleInitialize(MessageID _id, Json::Value const& _args);
void handleInitialized(MessageID _id, Json::Value const& _args);
void handleWorkspaceDidChangeConfiguration(Json::Value const& _args);
void setTrace(Json::Value const& _args);
void handleTextDocumentDidOpen(Json::Value const& _args);
void handleTextDocumentDidChange(Json::Value const& _args);
void handleTextDocumentDidClose(Json::Value const& _args);
void handleRename(Json::Value const& _args);
void handleGotoDefinition(MessageID _id, Json::Value const& _args);
void semanticTokensFull(MessageID _id, Json::Value const& _args);
void handleInitialize(MessageID _id, Json const& _args);
void handleInitialized(MessageID _id, Json const& _args);
void handleWorkspaceDidChangeConfiguration(Json const& _args);
void setTrace(Json const& _args);
void handleTextDocumentDidOpen(Json const& _args);
void handleTextDocumentDidChange(Json const& _args);
void handleTextDocumentDidClose(Json const& _args);
void handleRename(Json const& _args);
void handleGotoDefinition(MessageID _id, Json const& _args);
void semanticTokensFull(MessageID _id, Json const& _args);
/// Invoked when the server user-supplied configuration changes (initiated by the client).
void changeConfiguration(Json::Value const&);
void changeConfiguration(Json const&);
/// Compile everything until after analysis phase.
void compile();
std::vector<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::Value toJson(langutil::SourceLocation const& _location);
Json toRange(langutil::SourceLocation const& _location);
Json toJson(langutil::SourceLocation const& _location);
// LSP related member fields
@ -127,7 +127,7 @@ private:
frontend::CompilerStack m_compilerStack;
/// 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);
string const newName = _args["newName"].asString();
string const uri = _args["textDocument"]["uri"].asString();
string const newName = _args["newName"].get<string>();
string const uri = _args["textDocument"]["uri"].get<string>();
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)
sort(m_locations.begin(), m_locations.end());
Json::Value reply = Json::objectValue;
reply["changes"] = Json::objectValue;
Json reply = Json::object();
reply["changes"] = Json::object();
Json::Value edits = Json::arrayValue;
Json edits = Json::array();
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);
fileRepository().setSourceByUri(uri, std::move(buffer));
Json::Value edit = Json::objectValue;
Json edit = Json::object();
edit["range"] = toRange(*i);
edit["newText"] = newName;
// Record changes for the client
edits.append(edit);
edits.emplace_back(edit);
if (i + 1 == m_locations.rend() || (i + 1)->sourceName != i->sourceName)
{
reply["changes"][uri] = edits;
edits = Json::arrayValue;
edits = Json::array();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -43,7 +43,7 @@ set(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}")
add_dependencies(solutil solidity_BuildInfo.h)

View File

@ -33,8 +33,8 @@
using namespace std;
static_assert(
(JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 3),
"Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.3."
(NLOHMANN_JSON_VERSION_MAJOR == 3) && (NLOHMANN_JSON_VERSION_MINOR == 10) && (NLOHMANN_JSON_VERSION_PATCH == 2),
"Unexpected nlohmann-json version. Expecting 3.10.2."
);
namespace solidity::util
@ -43,53 +43,9 @@ namespace solidity::util
namespace
{
/// StreamWriterBuilder that can be constructed with specific settings
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);
}
#if 0
/// 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)
for (auto& child: _json)
@ -104,46 +60,54 @@ void removeNullMembersHelper(Json::Value& _json)
removeNullMembersHelper(value);
}
}
#endif
} // end anonymous namespace
Json::Value removeNullMembers(Json::Value _json)
Json removeNullMembers(Json _json)
{
removeNullMembersHelper(_json);
// TODO: Support this.
// removeNullMembersHelper(_json);
return _json;
}
string jsonPrettyPrint(Json::Value const& _input)
string jsonPrettyPrint(Json const& _input)
{
return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty });
}
string jsonCompactPrint(Json::Value const& _input)
string jsonCompactPrint(Json const& _input)
{
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;
if (_format.format == JsonFormat::Pretty)
{
settings["indentation"] = string(_format.indent, ' ');
settings["enableYAMLCompatibility"] = 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;
// NOTE: -1 here means no new lines (it is also the default setting)
return _input.dump(
/* indent */ (_format.format == JsonFormat::Pretty) ? static_cast<int>(_format.indent) : -1,
/* indent_char */ ' ',
/* ensure_ascii */ true
);
}
bool jsonParseStrict(string const& _input, Json::Value& _json, string* _errs /* = nullptr */)
bool jsonParseStrict(string const& _input, Json& _json, string* _errs /* = nullptr */)
{
static StrictModeCharReaderBuilder readerBuilder;
return parse(readerBuilder, _input, _json, _errs);
try
{
_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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -125,9 +125,9 @@ mv solidity solc
# Fetch dependencies
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/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
cd solc

View File

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

View File

@ -113,7 +113,7 @@ private:
/// such that they can be imported into the compiler (importASTs())
/// (produced by --combined-json ast <file.sol>
/// or standard-json output
std::map<std::string, Json::Value> parseAstFromInput();
std::map<std::string, Json> parseAstFromInput();
/// Create a file in the given directory
/// @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)
{
Json::Value metadata;
Json metadata;
if (!util::jsonParseStrict(_serialisedMetadata, metadata))
return false;
return isValidMetadata(metadata);
}
bool isValidMetadata(Json::Value const& _metadata)
bool isValidMetadata(Json const& _metadata)
{
if (
!_metadata.isObject() ||
!_metadata.isMember("version") ||
!_metadata.isMember("language") ||
!_metadata.isMember("compiler") ||
!_metadata.isMember("settings") ||
!_metadata.isMember("sources") ||
!_metadata.isMember("output") ||
!_metadata["settings"].isMember("evmVersion") ||
!_metadata["settings"].isMember("metadata") ||
!_metadata["settings"]["metadata"].isMember("bytecodeHash")
!_metadata.is_object() ||
!_metadata.contains("version") ||
!_metadata.contains("language") ||
!_metadata.contains("compiler") ||
!_metadata.contains("settings") ||
!_metadata.contains("sources") ||
!_metadata.contains("output") ||
!_metadata["settings"].contains("evmVersion") ||
!_metadata["settings"].contains("metadata") ||
!_metadata["settings"]["metadata"].contains("bytecodeHash")
)
return false;
if (!_metadata["version"].isNumeric() || _metadata["version"] != 1)
if (!_metadata["version"].is_number() || _metadata["version"] != 1)
return false;
if (!_metadata["language"].isString() || _metadata["language"].asString() != "Solidity")
if (!_metadata["language"].is_string() || _metadata["language"].get<string>() != "Solidity")
return false;
/// @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);
/// 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

View File

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

View File

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

View File

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

View File

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

View File

@ -431,7 +431,7 @@ TestCase::TestResult SemanticTest::runTest(
{
soltestAssert(
m_allowNonExistingFunctions ||
m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].isMember(test.call().signature),
m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].contains(test.call().signature),
"The function " + test.call().signature + " is not known to the compiler"
);

View File

@ -50,17 +50,17 @@ public:
m_compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed");
Json::Value generatedDocumentation;
Json generatedDocumentation;
if (_userDocumentation)
generatedDocumentation = m_compilerStack.natspecUser(_contractName);
else
generatedDocumentation = m_compilerStack.natspecDev(_contractName);
Json::Value expectedDocumentation;
Json expectedDocumentation;
std::string parseError;
BOOST_REQUIRE_MESSAGE(util::jsonParseStrict(_expectedDocumentationString, expectedDocumentation, &parseError), parseError);
expectedDocumentation["version"] = Json::Value(Natspec::c_natspecVersion);
expectedDocumentation["kind"] = Json::Value(_userDocumentation ? "user" : "dev");
expectedDocumentation["version"] = Natspec::c_natspecVersion;
expectedDocumentation["kind"] = _userDocumentation ? "user" : "dev";
BOOST_CHECK_MESSAGE(
expectedDocumentation == generatedDocumentation,
@ -2125,12 +2125,12 @@ BOOST_AUTO_TEST_CASE(dev_explicit_inehrit_complex)
BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed");
Json::Value generatedDocumentation = m_compilerStack.natspecDev("Token");
Json::Value expectedDocumentation;
Json generatedDocumentation = m_compilerStack.natspecDev("Token");
Json expectedDocumentation;
util::jsonParseStrict(natspec, expectedDocumentation);
expectedDocumentation["version"] = Json::Value(Natspec::c_natspecVersion);
expectedDocumentation["kind"] = Json::Value("dev");
expectedDocumentation["version"] = Natspec::c_natspecVersion;
expectedDocumentation["kind"] = "dev";
BOOST_CHECK_MESSAGE(
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;
}
string functionSignatureFromABI(Json::Value const& _functionABI)
string functionSignatureFromABI(Json const& _functionABI)
{
auto inputs = _functionABI["inputs"];
string signature = {_functionABI["name"].asString() + "("};
string signature = {_functionABI["name"].get<string>() + "("};
size_t parameterCount = 0;
for (auto const& input: inputs)
{
parameterCount++;
signature += input["type"].asString();
signature += input["type"].get<string>();
if (parameterCount < inputs.size())
signature += ",";
}
@ -162,7 +162,7 @@ string functionSignatureFromABI(Json::Value const& _functionABI)
std::optional<solidity::frontend::test::ParameterList> ContractABIUtils::parametersFromJsonOutputs(
ErrorReporter& _errorReporter,
Json::Value const& _contractABI,
Json const& _contractABI,
string const& _functionSignature
)
{
@ -178,7 +178,7 @@ std::optional<solidity::frontend::test::ParameterList> ContractABIUtils::paramet
for (auto const& output: function["outputs"])
{
string type = output["type"].asString();
string type = output["type"].get<string>();
ABITypes inplaceTypes;
ABITypes dynamicTypes;
@ -210,13 +210,13 @@ std::optional<solidity::frontend::test::ParameterList> ContractABIUtils::paramet
}
bool ContractABIUtils::appendTypesFromName(
Json::Value const& _functionOutput,
Json const& _functionOutput,
ABITypes& _inplaceTypes,
ABITypes& _dynamicTypes,
bool _isCompoundType
)
{
string type = _functionOutput["type"].asString();
string type = _functionOutput["type"].get<string>();
if (isBool(type))
_inplaceTypes.push_back(ABIType{ABIType::Boolean});
else if (isUint(type))

View File

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

View File

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

View File

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

View File

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

View File

@ -1018,6 +1018,16 @@ BOOST_AUTO_TEST_CASE(cli_include_paths)
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)
{
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);
Json::Value parsedStdout;
Json parsedStdout;
string jsonParsingErrors;
BOOST_TEST(util::jsonParseStrict(result.stdoutContent, parsedStdout, &jsonParsingErrors));
BOOST_TEST(jsonParsingErrors == "");
for (Json::Value const& errorDict: parsedStdout["errors"])
for (Json const& errorDict: parsedStdout["errors"])
// The error list might contain pre-release compiler warning
BOOST_TEST(errorDict["severity"] != "error");
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"}
);

View File

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

View File

@ -58,7 +58,7 @@ optional<CompilerOutput> SolidityCompilationFramework::compileContract()
else
contractName = m_compilerInput.contractName;
evmasm::LinkerObject obj = m_compiler.object(contractName);
Json::Value methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"];
Json methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"];
return CompilerOutput{obj.bytecode, methodIdentifiers};
}
}
@ -164,10 +164,10 @@ evmc::result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle)
// isabelle test entry point. At the moment, we are sure that the
// entry point is the second method in the contract (hence the ++)
// but not its name.
methodName = (++cOutput->methodIdentifiersInContract.begin())->asString() +
methodName = (++cOutput->methodIdentifiersInContract.begin())->get<string>() +
_fuzzIsabelle.substr(2, _fuzzIsabelle.size());
else
methodName = cOutput->methodIdentifiersInContract[m_methodName].asString();
methodName = cOutput->methodIdentifiersInContract[m_methodName].get<string>();
return deployAndExecute(
cOutput->byteCode,

View File

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

View File

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

View File

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