diff options
author | chriseth <chris@ethereum.org> | 2017-05-22 20:33:46 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-22 20:33:46 +0800 |
commit | 8eead553aff1ec30c3d1b15ae9b2929b887ede49 (patch) | |
tree | a9eba765277360c579ee89ee78d9606c17cb9ffa /libsolidity/ast/ASTJsonConverter.cpp | |
parent | e3af064098edae79aa3bbfb2a96b43fa3479269d (diff) | |
parent | e82df073d15237455b1e53e35ef544aea72a69f9 (diff) | |
download | dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.gz dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.bz2 dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.lz dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.xz dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.zst dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.zip |
Merge pull request #1810 from ethereum/compactJson
Compact format for AST-Json.
Diffstat (limited to 'libsolidity/ast/ASTJsonConverter.cpp')
-rw-r--r-- | libsolidity/ast/ASTJsonConverter.cpp | 860 |
1 files changed, 472 insertions, 388 deletions
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 9ea23687..40c552a3 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -25,6 +25,8 @@ #include <libdevcore/UTF8.h> #include <libsolidity/ast/AST.h> #include <libsolidity/interface/Exceptions.h> +#include <libsolidity/inlineasm/AsmData.h> +#include <libsolidity/inlineasm/AsmPrinter.h> using namespace std; @@ -33,49 +35,86 @@ namespace dev namespace solidity { -void ASTJsonConverter::addJsonNode( +ASTJsonConverter::ASTJsonConverter(bool _legacy, map<string, unsigned> _sourceIndices): + m_legacy(_legacy), + m_sourceIndices(_sourceIndices) +{ +} + + +void ASTJsonConverter::setJsonNode( ASTNode const& _node, string const& _nodeName, - initializer_list<pair<string const, Json::Value const>> _attributes, - bool _hasChildren = false + initializer_list<pair<string, Json::Value>>&& _attributes ) { - ASTJsonConverter::addJsonNode( + ASTJsonConverter::setJsonNode( _node, _nodeName, - std::vector<pair<string const, Json::Value const>>(_attributes), - _hasChildren + std::vector<pair<string, Json::Value>>(std::move(_attributes)) ); } - -void ASTJsonConverter::addJsonNode( + +void ASTJsonConverter::setJsonNode( ASTNode const& _node, - string const& _nodeName, - std::vector<pair<string const, Json::Value const>> const& _attributes, - bool _hasChildren = false + string const& _nodeType, + std::vector<pair<string, Json::Value>>&& _attributes ) { - Json::Value node; - - node["id"] = Json::UInt64(_node.id()); - node["src"] = sourceLocationToString(_node.location()); - node["name"] = _nodeName; - if (_attributes.size() != 0) + m_currentValue = Json::objectValue; + m_currentValue["id"] = nodeId(_node); + m_currentValue["src"] = sourceLocationToString(_node.location()); + if (!m_legacy) { - Json::Value attrs; + m_currentValue["nodeType"] = _nodeType; for (auto& e: _attributes) - attrs[e.first] = e.second; - node["attributes"] = attrs; + m_currentValue[e.first] = std::move(e.second); } - - m_jsonNodePtrs.top()->append(node); - - if (_hasChildren) + else { - Json::Value& addedNode = (*m_jsonNodePtrs.top())[m_jsonNodePtrs.top()->size() - 1]; - Json::Value children(Json::arrayValue); - addedNode["children"] = children; - m_jsonNodePtrs.push(&addedNode["children"]); + m_currentValue["name"] = _nodeType; + Json::Value attrs(Json::objectValue); + if ( + //these nodeTypes need to have a children-node even if it is empty + (_nodeType == "VariableDeclaration") || + (_nodeType == "ParameterList") || + (_nodeType == "Block") || + (_nodeType == "InlineAssembly") || + (_nodeType == "Throw") + ) + { + Json::Value children(Json::arrayValue); + m_currentValue["children"] = children; + } + + for (auto& e: _attributes) + { + if ( + (!e.second.isNull()) && + ( + (e.second.isObject() && e.second.isMember("name")) || + (e.second.isArray() && e.second[0].isObject() && e.second[0].isMember("name")) || + (e.first == "declarations") // (in the case (_,x)= ... there's a nullpointer at [0] + ) + ) + { + if (e.second.isObject()) + m_currentValue["children"].append(std::move(e.second)); + if (e.second.isArray()) + for (auto& child: e.second) + if (!child.isNull()) + m_currentValue["children"].append(std::move(child)); + } + else + { + if (e.first == "typeDescriptions") + attrs["type"] = Json::Value(e.second["typeString"]); + else + attrs[e.first] = std::move(e.second); + } + } + if (!attrs.empty()) + m_currentValue["attributes"] = std::move(attrs); } } @@ -90,34 +129,89 @@ string ASTJsonConverter::sourceLocationToString(SourceLocation const& _location) return std::to_string(_location.start) + ":" + std::to_string(length) + ":" + std::to_string(sourceIndex); } -ASTJsonConverter::ASTJsonConverter( - ASTNode const& _ast, - map<string, unsigned> _sourceIndices -): m_ast(&_ast), m_sourceIndices(_sourceIndices) +string ASTJsonConverter::namePathToString(std::vector<ASTString> const& _namePath) const { + return boost::algorithm::join(_namePath, "."); } -void ASTJsonConverter::print(ostream& _stream) +Json::Value ASTJsonConverter::typePointerToJson(TypePointer _tp) { - process(); - _stream << m_astJson; + Json::Value typeDescriptions(Json::objectValue); + typeDescriptions["typeString"] = _tp ? Json::Value(_tp->toString()) : Json::nullValue; + typeDescriptions["typeIdentifier"] = _tp ? Json::Value(_tp->identifier()) : Json::nullValue; + return typeDescriptions; + +} +Json::Value ASTJsonConverter::typePointerToJson(std::shared_ptr<std::vector<TypePointer>> _tps) +{ + if (_tps) + { + Json::Value arguments(Json::arrayValue); + for (auto const& tp: *_tps) + arguments.append(typePointerToJson(tp)); + return arguments; + } + else + return Json::nullValue; } -Json::Value const& ASTJsonConverter::json() +void ASTJsonConverter::appendExpressionAttributes( + std::vector<pair<string, Json::Value>>& _attributes, + ExpressionAnnotation const& _annotation +) { - process(); - return m_astJson; + std::vector<pair<string, Json::Value>> exprAttributes = { + make_pair("typeDescriptions", typePointerToJson(_annotation.type)), + make_pair("isConstant", _annotation.isConstant), + make_pair("isPure", _annotation.isPure), + make_pair("isLValue", _annotation.isLValue), + make_pair("lValueRequested", _annotation.lValueRequested), + make_pair("argumentTypes", typePointerToJson(_annotation.argumentTypes)) + }; + _attributes += exprAttributes; } -bool ASTJsonConverter::visit(SourceUnit const&) +Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<assembly::Identifier const* ,InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) { - Json::Value children(Json::arrayValue); + Json::Value tuple(Json::objectValue); + tuple["src"] = sourceLocationToString(_info.first->location); + tuple["declaration"] = idOrNull(_info.second.declaration); + tuple["isSlot"] = Json::Value(_info.second.isSlot); + tuple["isOffset"] = Json::Value(_info.second.isOffset); + tuple["valueSize"] = _info.second.valueSize; + return tuple; +} - m_astJson["name"] = "SourceUnit"; - m_astJson["children"] = children; - m_jsonNodePtrs.push(&m_astJson["children"]); +void ASTJsonConverter::print(ostream& _stream, ASTNode const& _node) +{ + _stream << toJson(_node); +} - return true; +Json::Value ASTJsonConverter::toJson(ASTNode const& _node) +{ + _node.accept(*this); + return std::move(m_currentValue); +} + +bool ASTJsonConverter::visit(SourceUnit const& _node) +{ + Json::Value exportedSymbols = Json::objectValue; + for (auto const& sym: _node.annotation().exportedSymbols) + { + exportedSymbols[sym.first] = Json::arrayValue; + for (Declaration const* overload: sym.second) + exportedSymbols[sym.first].append(nodeId(*overload)); + } + setJsonNode( + _node, + "SourceUnit", + { + make_pair("absolutePath", _node.annotation().path), + make_pair("exportedSymbols", move(exportedSymbols)), + make_pair("nodes", toJson(_node.nodes())) + } + ); + return false; } bool ASTJsonConverter::visit(PragmaDirective const& _node) @@ -125,313 +219,487 @@ bool ASTJsonConverter::visit(PragmaDirective const& _node) Json::Value literals(Json::arrayValue); for (auto const& literal: _node.literals()) literals.append(literal); - addJsonNode(_node, "PragmaDirective", { make_pair("literals", literals) }); - return true; + setJsonNode( _node, "PragmaDirective", { + make_pair("literals", std::move(literals)) + }); + return false; } bool ASTJsonConverter::visit(ImportDirective const& _node) { - addJsonNode(_node, "ImportDirective", { make_pair("file", _node.path())}); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("file", _node.path()), + make_pair("absolutePath", _node.annotation().absolutePath), + make_pair(m_legacy ? "SourceUnit" : "sourceUnit", nodeId(*_node.annotation().sourceUnit)), + make_pair("scope", idOrNull(_node.scope())) + }; + attributes.push_back(make_pair("unitAlias", _node.name())); + Json::Value symbolAliases(Json::arrayValue); + for (auto const& symbolAlias: _node.symbolAliases()) + { + Json::Value tuple(Json::objectValue); + solAssert(symbolAlias.first, ""); + tuple["foreign"] = nodeId(*symbolAlias.first); + tuple["local"] = symbolAlias.second ? Json::Value(*symbolAlias.second) : Json::nullValue; + symbolAliases.append(tuple); + } + attributes.push_back(make_pair("symbolAliases", std::move(symbolAliases))); + setJsonNode(_node, "ImportDirective", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(ContractDefinition const& _node) { - Json::Value linearizedBaseContracts(Json::arrayValue); - for (auto const& baseContract: _node.annotation().linearizedBaseContracts) - linearizedBaseContracts.append(Json::UInt64(baseContract->id())); - addJsonNode(_node, "ContractDefinition", { + setJsonNode(_node, "ContractDefinition", { make_pair("name", _node.name()), - make_pair("isLibrary", _node.isLibrary()), + make_pair("contractKind", contractKind(_node.contractKind())), make_pair("fullyImplemented", _node.annotation().isFullyImplemented), - make_pair("linearizedBaseContracts", linearizedBaseContracts), - }, true); - return true; + make_pair("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts)), + make_pair("baseContracts", toJson(_node.baseContracts())), + make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies)), + make_pair("nodes", toJson(_node.subNodes())), + make_pair("scope", idOrNull(_node.scope())) + }); + return false; } bool ASTJsonConverter::visit(InheritanceSpecifier const& _node) { - addJsonNode(_node, "InheritanceSpecifier", {}, true); - return true; + setJsonNode(_node, "InheritanceSpecifier", { + make_pair("baseName", toJson(_node.name())), + make_pair("arguments", toJson(_node.arguments())) + }); + return false; } bool ASTJsonConverter::visit(UsingForDirective const& _node) { - addJsonNode(_node, "UsingForDirective", {}, true); - return true; + setJsonNode(_node, "UsingForDirective", { + make_pair("libraryName", toJson(_node.libraryName())), + make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue) + }); + return false; } bool ASTJsonConverter::visit(StructDefinition const& _node) { - addJsonNode(_node, "StructDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "StructDefinition", { + make_pair("name", _node.name()), + make_pair("visibility", visibility(_node.visibility())), + make_pair("canonicalName", _node.annotation().canonicalName), + make_pair("members", toJson(_node.members())), + make_pair("scope", idOrNull(_node.scope())) + }); + return false; } bool ASTJsonConverter::visit(EnumDefinition const& _node) { - addJsonNode(_node, "EnumDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "EnumDefinition", { + make_pair("name", _node.name()), + make_pair("canonicalName", _node.annotation().canonicalName), + make_pair("members", toJson(_node.members())) + }); + return false; } bool ASTJsonConverter::visit(EnumValue const& _node) { - addJsonNode(_node, "EnumValue", { make_pair("name", _node.name()) }); - return true; + setJsonNode(_node, "EnumValue", { + make_pair("name", _node.name()) + }); + return false; } bool ASTJsonConverter::visit(ParameterList const& _node) { - addJsonNode(_node, "ParameterList", {}, true); - return true; + setJsonNode(_node, "ParameterList", { + make_pair("parameters", toJson(_node.parameters())) + }); + return false; } bool ASTJsonConverter::visit(FunctionDefinition const& _node) { - addJsonNode(_node, "FunctionDefinition", { + std::vector<pair<string, Json::Value>> attributes = { make_pair("name", _node.name()), - make_pair("constant", _node.isDeclaredConst()), + make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.isDeclaredConst()), make_pair("payable", _node.isPayable()), - make_pair("visibility", visibility(_node.visibility())) - }, true); - return true; + make_pair("visibility", visibility(_node.visibility())), + make_pair("parameters", toJson(_node.parameterList())), + make_pair("isConstructor", _node.isConstructor()), + make_pair("returnParameters", toJson(*_node.returnParameterList())), + make_pair("modifiers", toJson(_node.modifiers())), + make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue), + make_pair("implemented", _node.isImplemented()), + make_pair("scope", idOrNull(_node.scope())) + }; + setJsonNode(_node, "FunctionDefinition", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(VariableDeclaration const& _node) { - std::vector<pair<string const, Json::Value const>> attributes = { + std::vector<pair<string, Json::Value>> attributes = { make_pair("name", _node.name()), - make_pair("type", type(_node)), + make_pair("typeName", toJsonOrNull(_node.typeName())), make_pair("constant", _node.isConstant()), + make_pair("stateVariable", _node.isStateVariable()), make_pair("storageLocation", location(_node.referenceLocation())), - make_pair("visibility", visibility(_node.visibility())) - }; + make_pair("visibility", visibility(_node.visibility())), + make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue), + make_pair("scope", idOrNull(_node.scope())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }; if (m_inEvent) attributes.push_back(make_pair("indexed", _node.isIndexed())); - addJsonNode(_node, "VariableDeclaration", attributes, true); - return true; - + setJsonNode(_node, "VariableDeclaration", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(ModifierDefinition const& _node) { - addJsonNode(_node, "ModifierDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "ModifierDefinition", { + make_pair("name", _node.name()), + make_pair("visibility", visibility(_node.visibility())), + make_pair("parameters", toJson(_node.parameterList())), + make_pair("body", toJson(_node.body())) + }); + return false; } bool ASTJsonConverter::visit(ModifierInvocation const& _node) { - addJsonNode(_node, "ModifierInvocation", {}, true); - return true; + setJsonNode(_node, "ModifierInvocation", { + make_pair("modifierName", toJson(*_node.name())), + make_pair("arguments", toJson(_node.arguments())) + }); + return false; } bool ASTJsonConverter::visit(TypeName const&) { - return true; + solAssert(false, "AST node of abstract type used."); + return false; } bool ASTJsonConverter::visit(EventDefinition const& _node) { m_inEvent = true; - addJsonNode(_node, "EventDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "EventDefinition", { + make_pair("name", _node.name()), + make_pair("parameters", toJson(_node.parameterList())), + make_pair("anonymous", _node.isAnonymous()) + }); + return false; } bool ASTJsonConverter::visit(ElementaryTypeName const& _node) { - addJsonNode(_node, "ElementaryTypeName", { make_pair("name", _node.typeName().toString()) }); - return true; + setJsonNode(_node, "ElementaryTypeName", { + make_pair("name", _node.typeName().toString()), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(UserDefinedTypeName const& _node) { - addJsonNode(_node, "UserDefinedTypeName", { - make_pair("name", boost::algorithm::join(_node.namePath(), ".")) + setJsonNode(_node, "UserDefinedTypeName", { + make_pair("name", namePathToString(_node.namePath())), + make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), + make_pair("contractScope", idOrNull(_node.annotation().contractScope)), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) }); - return true; + return false; } bool ASTJsonConverter::visit(FunctionTypeName const& _node) { - addJsonNode(_node, "FunctionTypeName", { + setJsonNode(_node, "FunctionTypeName", { make_pair("payable", _node.isPayable()), make_pair("visibility", visibility(_node.visibility())), - make_pair("constant", _node.isDeclaredConst()) - }, true); - return true; + make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.isDeclaredConst()), + make_pair("parameterTypes", toJson(_node.parameterTypes())), + make_pair("returnParameterTypes", toJson(_node.returnParameterTypes())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(Mapping const& _node) { - addJsonNode(_node, "Mapping", {}, true); - return true; + setJsonNode(_node, "Mapping", { + make_pair("keyType", toJson(_node.keyType())), + make_pair("valueType", toJson(_node.valueType())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(ArrayTypeName const& _node) { - addJsonNode(_node, "ArrayTypeName", {}, true); - return true; + setJsonNode(_node, "ArrayTypeName", { + make_pair("baseType", toJson(_node.baseType())), + make_pair("length", toJsonOrNull(_node.length())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(InlineAssembly const& _node) { - addJsonNode(_node, "InlineAssembly", {}, true); - return true; + Json::Value externalReferences(Json::arrayValue); + for (auto const& it : _node.annotation().externalReferences) + { + if (it.first) + { + Json::Value tuple(Json::objectValue); + tuple[it.first->name] = inlineAssemblyIdentifierToJson(it); + externalReferences.append(tuple); + } + } + setJsonNode(_node, "InlineAssembly", { + make_pair("operations", Json::Value(assembly::AsmPrinter()(_node.operations()))), + make_pair("externalReferences", std::move(externalReferences)) + }); + return false; } bool ASTJsonConverter::visit(Block const& _node) { - addJsonNode(_node, "Block", {}, true); - return true; + setJsonNode(_node, "Block", { + make_pair("statements", toJson(_node.statements())) + }); + return false; } bool ASTJsonConverter::visit(PlaceholderStatement const& _node) { - addJsonNode(_node, "PlaceholderStatement", {}); - return true; + setJsonNode(_node, "PlaceholderStatement", {}); + return false; } bool ASTJsonConverter::visit(IfStatement const& _node) { - addJsonNode(_node, "IfStatement", {}, true); - return true; + setJsonNode(_node, "IfStatement", { + make_pair("condition", toJson(_node.condition())), + make_pair("trueBody", toJson(_node.trueStatement())), + make_pair("falseBody", toJsonOrNull(_node.falseStatement())) + }); + return false; } bool ASTJsonConverter::visit(WhileStatement const& _node) { - addJsonNode( + setJsonNode( _node, _node.isDoWhile() ? "DoWhileStatement" : "WhileStatement", - {}, - true); - return true; + { + make_pair("condition", toJson(_node.condition())), + make_pair("body", toJson(_node.body())) + } + ); + return false; } bool ASTJsonConverter::visit(ForStatement const& _node) { - addJsonNode(_node, "ForStatement", {}, true); - return true; + setJsonNode(_node, "ForStatement", { + make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())), + make_pair("condition", toJsonOrNull(_node.condition())), + make_pair("loopExpression", toJsonOrNull(_node.loopExpression())), + make_pair("body", toJson(_node.body())) + }); + return false; } bool ASTJsonConverter::visit(Continue const& _node) { - addJsonNode(_node, "Continue", {}); - return true; + setJsonNode(_node, "Continue", {}); + return false; } bool ASTJsonConverter::visit(Break const& _node) { - addJsonNode(_node, "Break", {}); - return true; + setJsonNode(_node, "Break", {}); + return false; } bool ASTJsonConverter::visit(Return const& _node) { - addJsonNode(_node, "Return", {}, true);; - return true; + setJsonNode(_node, "Return", { + make_pair("expression", toJsonOrNull(_node.expression())), + make_pair("functionReturnParameters", idOrNull(_node.annotation().functionReturnParameters)) + }); + return false; } bool ASTJsonConverter::visit(Throw const& _node) { - addJsonNode(_node, "Throw", {}, true);; - return true; + setJsonNode(_node, "Throw", {});; + return false; } bool ASTJsonConverter::visit(VariableDeclarationStatement const& _node) { - addJsonNode(_node, "VariableDeclarationStatement", {}, true); - return true; + Json::Value varDecs(Json::arrayValue); + for (auto const& v: _node.annotation().assignments) + varDecs.append(idOrNull(v)); + setJsonNode(_node, "VariableDeclarationStatement", { + make_pair("assignments", std::move(varDecs)), + make_pair("declarations", toJson(_node.declarations())), + make_pair("initialValue", toJsonOrNull(_node.initialValue())) + }); + return false; } bool ASTJsonConverter::visit(ExpressionStatement const& _node) { - addJsonNode(_node, "ExpressionStatement", {}, true); - return true; + setJsonNode(_node, "ExpressionStatement", { + make_pair("expression", toJson(_node.expression())) + }); + return false; } bool ASTJsonConverter::visit(Conditional const& _node) { - addJsonNode(_node, "Conditional", {}, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("condition", toJson(_node.condition())), + make_pair("trueExpression", toJson(_node.trueExpression())), + make_pair("falseExpression", toJson(_node.falseExpression())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "Conditional", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(Assignment const& _node) { - addJsonNode(_node, "Assignment", - { make_pair("operator", Token::toString(_node.assignmentOperator())), - make_pair("type", type(_node)) }, - true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("operator", Token::toString(_node.assignmentOperator())), + make_pair("leftHandSide", toJson(_node.leftHandSide())), + make_pair("rightHandSide", toJson(_node.rightHandSide())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode( _node, "Assignment", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(TupleExpression const& _node) { - addJsonNode(_node, "TupleExpression",{}, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("isInlineArray", Json::Value(_node.isInlineArray())), + make_pair("components", toJson(_node.components())), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "TupleExpression", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(UnaryOperation const& _node) { - addJsonNode(_node, "UnaryOperation", - { make_pair("prefix", _node.isPrefixOperation()), - make_pair("operator", Token::toString(_node.getOperator())), - make_pair("type", type(_node)) }, - true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("prefix", _node.isPrefixOperation()), + make_pair("operator", Token::toString(_node.getOperator())), + make_pair("subExpression", toJson(_node.subExpression())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "UnaryOperation", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(BinaryOperation const& _node) { - addJsonNode(_node, "BinaryOperation", { + std::vector<pair<string, Json::Value>> attributes = { make_pair("operator", Token::toString(_node.getOperator())), - make_pair("type", type(_node)) - }, true); - return true; + make_pair("leftExpression", toJson(_node.leftExpression())), + make_pair("rightExpression", toJson(_node.rightExpression())), + make_pair("commonType", typePointerToJson(_node.annotation().commonType)), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "BinaryOperation", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(FunctionCall const& _node) { - addJsonNode(_node, "FunctionCall", { - make_pair("type_conversion", _node.annotation().isTypeConversion), - make_pair("type", type(_node)) - }, true); - return true; + Json::Value names(Json::arrayValue); + for (auto const& name: _node.names()) + names.append(Json::Value(*name)); + std::vector<pair<string, Json::Value>> attributes = { + make_pair("expression", toJson(_node.expression())), + make_pair("names", std::move(names)), + make_pair("arguments", toJson(_node.arguments())) + }; + if (m_legacy) + { + attributes.push_back(make_pair("isStructConstructorCall", _node.annotation().kind == FunctionCallKind::StructConstructorCall)); + attributes.push_back(make_pair("type_conversion", _node.annotation().kind == FunctionCallKind::TypeConversion)); + } + else + attributes.push_back(make_pair("kind", functionCallKind(_node.annotation().kind))); + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "FunctionCall", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(NewExpression const& _node) { - addJsonNode(_node, "NewExpression", { make_pair("type", type(_node)) }, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("typeName", toJson(_node.typeName())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "NewExpression", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(MemberAccess const& _node) { - addJsonNode(_node, "MemberAccess", { - make_pair("member_name", _node.memberName()), - make_pair("type", type(_node)) - }, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair(m_legacy ? "member_name" : "memberName", _node.memberName()), + make_pair("expression", toJson(_node.expression())), + make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "MemberAccess", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(IndexAccess const& _node) { - addJsonNode(_node, "IndexAccess", { make_pair("type", type(_node)) }, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("baseExpression", toJson(_node.baseExpression())), + make_pair("indexExpression", toJsonOrNull(_node.indexExpression())), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "IndexAccess", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(Identifier const& _node) { - addJsonNode(_node, "Identifier", - { make_pair("value", _node.name()), make_pair("type", type(_node)) }); - return true; + Json::Value overloads(Json::arrayValue); + for (auto const& dec: _node.annotation().overloadedDeclarations) + overloads.append(nodeId(*dec)); + setJsonNode(_node, "Identifier", { + make_pair(m_legacy ? "value" : "name", _node.name()), + make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), + make_pair("overloadedDeclarations", overloads), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)), + make_pair("argumentTypes", typePointerToJson(_node.annotation().argumentTypes)) + }); + return false; } bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node) { - addJsonNode(_node, "ElementaryTypeNameExpression", { - make_pair("value", _node.typeName().toString()), - make_pair("type", type(_node)) - }); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair(m_legacy ? "value" : "typeName", _node.typeName().toString()) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(Literal const& _node) @@ -441,240 +709,26 @@ bool ASTJsonConverter::visit(Literal const& _node) if (!dev::validateUTF8(_node.value())) value = Json::nullValue; Token::Value subdenomination = Token::Value(_node.subDenomination()); - addJsonNode(_node, "Literal", { + std::vector<pair<string, Json::Value>> attributes = { make_pair("token", tokenString ? tokenString : Json::Value()), make_pair("value", value), - make_pair("hexvalue", toHex(_node.value())), + make_pair(m_legacy ? "hexvalue" : "hexValue", toHex(_node.value())), make_pair( "subdenomination", subdenomination == Token::Illegal ? Json::nullValue : Json::Value{Token::toString(subdenomination)} - ), - make_pair("type", type(_node)) - }); - return true; -} - -void ASTJsonConverter::endVisit(SourceUnit const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(PragmaDirective const&) -{ -} - -void ASTJsonConverter::endVisit(ImportDirective const&) -{ -} - -void ASTJsonConverter::endVisit(ContractDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(InheritanceSpecifier const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(UsingForDirective const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(StructDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(EnumDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(EnumValue const&) -{ -} - -void ASTJsonConverter::endVisit(ParameterList const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(FunctionDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(VariableDeclaration const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ModifierDefinition const&) -{ - goUp(); + ) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "Literal", std::move(attributes)); + return false; } -void ASTJsonConverter::endVisit(ModifierInvocation const&) -{ - goUp(); -} void ASTJsonConverter::endVisit(EventDefinition const&) { m_inEvent = false; - goUp(); -} - -void ASTJsonConverter::endVisit(TypeName const&) -{ -} - -void ASTJsonConverter::endVisit(ElementaryTypeName const&) -{ -} - -void ASTJsonConverter::endVisit(UserDefinedTypeName const&) -{ -} - -void ASTJsonConverter::endVisit(FunctionTypeName const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Mapping const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ArrayTypeName const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(InlineAssembly const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Block const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(PlaceholderStatement const&) -{ -} - -void ASTJsonConverter::endVisit(IfStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(WhileStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ForStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Continue const&) -{ -} - -void ASTJsonConverter::endVisit(Break const&) -{ -} - -void ASTJsonConverter::endVisit(Return const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Throw const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(VariableDeclarationStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ExpressionStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Conditional const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Assignment const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(TupleExpression const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(UnaryOperation const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(BinaryOperation const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(FunctionCall const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(NewExpression const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(MemberAccess const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(IndexAccess const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Identifier const&) -{ -} - -void ASTJsonConverter::endVisit(ElementaryTypeNameExpression const&) -{ -} - -void ASTJsonConverter::endVisit(Literal const&) -{ -} - -void ASTJsonConverter::process() -{ - if (!processed) - m_ast->accept(*this); - processed = true; } string ASTJsonConverter::visibility(Declaration::Visibility const& _visibility) @@ -709,6 +763,36 @@ string ASTJsonConverter::location(VariableDeclaration::Location _location) } } +string ASTJsonConverter::contractKind(ContractDefinition::ContractKind _kind) +{ + switch (_kind) + { + case ContractDefinition::ContractKind::Interface: + return "interface"; + case ContractDefinition::ContractKind::Contract: + return "contract"; + case ContractDefinition::ContractKind::Library: + return "library"; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of contract.")); + } +} + +string ASTJsonConverter::functionCallKind(FunctionCallKind _kind) +{ + switch (_kind) + { + case FunctionCallKind::FunctionCall: + return "functionCall"; + case FunctionCallKind::TypeConversion: + return "typeConversion"; + case FunctionCallKind::StructConstructorCall: + return "structConstructorCall"; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of function call .")); + } +} + string ASTJsonConverter::type(Expression const& _expression) { return _expression.annotation().type ? _expression.annotation().type->toString() : "Unknown"; |