aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-05-22 20:33:46 +0800
committerGitHub <noreply@github.com>2017-05-22 20:33:46 +0800
commit8eead553aff1ec30c3d1b15ae9b2929b887ede49 (patch)
treea9eba765277360c579ee89ee78d9606c17cb9ffa
parente3af064098edae79aa3bbfb2a96b43fa3479269d (diff)
parente82df073d15237455b1e53e35ef544aea72a69f9 (diff)
downloaddexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.gz
dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.zst
dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.zip
Merge pull request #1810 from ethereum/compactJson
Compact format for AST-Json.
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/analysis/TypeChecker.cpp16
-rw-r--r--libsolidity/ast/AST.h9
-rw-r--r--libsolidity/ast/ASTAnnotations.h13
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp860
-rw-r--r--libsolidity/ast/ASTJsonConverter.h112
-rw-r--r--libsolidity/ast/Types.cpp2
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp6
-rw-r--r--libsolidity/formal/Why3Translator.cpp2
-rw-r--r--libsolidity/interface/StandardCompiler.cpp3
-rw-r--r--solc/CommandLineInterface.cpp10
-rw-r--r--solc/jsonCompiler.cpp2
-rw-r--r--test/libsolidity/ASTJSON.cpp24
-rw-r--r--test/libsolidity/JSONCompiler.cpp8
-rw-r--r--test/libsolidity/StandardCompiler.cpp6
15 files changed, 579 insertions, 495 deletions
diff --git a/Changelog.md b/Changelog.md
index be5c18c5..650d75d8 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,4 +1,5 @@
### 0.4.12 (unreleased)
+ * AST: export all attributes to Json format
### 0.4.11 (2017-05-03)
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 38cdc1f8..8161a3a1 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -1238,13 +1238,17 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
if (auto const* typeType = dynamic_cast<TypeType const*>(expressionType.get()))
{
- _functionCall.annotation().isStructConstructorCall = (typeType->actualType()->category() == Type::Category::Struct);
- _functionCall.annotation().isTypeConversion = !_functionCall.annotation().isStructConstructorCall;
+ if (typeType->actualType()->category() == Type::Category::Struct)
+ _functionCall.annotation().kind = FunctionCallKind::StructConstructorCall;
+ else
+ _functionCall.annotation().kind = FunctionCallKind::TypeConversion;
+
}
else
- _functionCall.annotation().isStructConstructorCall = _functionCall.annotation().isTypeConversion = false;
+ _functionCall.annotation().kind = FunctionCallKind::FunctionCall;
+ solAssert(_functionCall.annotation().kind != FunctionCallKind::Unset, "");
- if (_functionCall.annotation().isTypeConversion)
+ if (_functionCall.annotation().kind == FunctionCallKind::TypeConversion)
{
TypeType const& t = dynamic_cast<TypeType const&>(*expressionType);
TypePointer resultType = t.actualType();
@@ -1274,7 +1278,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
/// For error message: Struct members that were removed during conversion to memory.
set<string> membersRemovedForStructConstructor;
- if (_functionCall.annotation().isStructConstructorCall)
+ if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall)
{
TypeType const& t = dynamic_cast<TypeType const&>(*expressionType);
auto const& structType = dynamic_cast<StructType const&>(*t.actualType());
@@ -1312,7 +1316,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
toString(parameterTypes.size()) +
".";
// Extend error message in case we try to construct a struct with mapping member.
- if (_functionCall.annotation().isStructConstructorCall && !membersRemovedForStructConstructor.empty())
+ if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall && !membersRemovedForStructConstructor.empty())
{
msg += " Members that have to be skipped in memory:";
for (auto const& member: membersRemovedForStructConstructor)
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 02234ffc..71b81a69 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -583,8 +583,7 @@ public:
bool isPayable() const { return m_isPayable; }
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); }
- Block const& body() const { return *m_body; }
-
+ Block const& body() const { solAssert(m_body, ""); return *m_body; }
virtual bool isVisibleInContract() const override
{
return Declaration::isVisibleInContract() && !isConstructor() && !name().empty();
@@ -1314,7 +1313,7 @@ private:
/**
* Tuple, parenthesized expression, or bracketed expression.
- * Examples: (1, 2), (x,), (x), (), [1, 2],
+ * Examples: (1, 2), (x,), (x), (), [1, 2],
* Individual components might be empty shared pointers (as in the second example).
* The respective types in lvalue context are: 2-tuple, 2-tuple (with wildcard), type of x, 0-tuple
* Not in lvalue context: 2-tuple, _1_-tuple, type of x, 0-tuple.
@@ -1327,8 +1326,8 @@ public:
std::vector<ASTPointer<Expression>> const& _components,
bool _isArray
):
- Expression(_location),
- m_components(_components),
+ Expression(_location),
+ m_components(_components),
m_isArray(_isArray) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h
index a7d89248..45a6dd1a 100644
--- a/libsolidity/ast/ASTAnnotations.h
+++ b/libsolidity/ast/ASTAnnotations.h
@@ -200,12 +200,17 @@ struct BinaryOperationAnnotation: ExpressionAnnotation
TypePointer commonType;
};
+enum class FunctionCallKind
+{
+ Unset,
+ FunctionCall,
+ TypeConversion,
+ StructConstructorCall
+};
+
struct FunctionCallAnnotation: ExpressionAnnotation
{
- /// Whether this is an explicit type conversion.
- bool isTypeConversion = false;
- /// Whether this is a struct constructor call.
- bool isStructConstructorCall = false;
+ FunctionCallKind kind = FunctionCallKind::Unset;
};
}
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";
diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h
index bd5e6560..5ee40536 100644
--- a/libsolidity/ast/ASTJsonConverter.h
+++ b/libsolidity/ast/ASTJsonConverter.h
@@ -42,15 +42,23 @@ class ASTJsonConverter: public ASTConstVisitor
{
public:
/// Create a converter to JSON for the given abstract syntax tree.
+ /// @a _legacy if true, use legacy format
/// @a _sourceIndices is used to abbreviate source names in source locations.
explicit ASTJsonConverter(
- ASTNode const& _ast,
+ bool _legacy,
std::map<std::string, unsigned> _sourceIndices = std::map<std::string, unsigned>()
);
/// Output the json representation of the AST to _stream.
- void print(std::ostream& _stream);
- Json::Value const& json();
-
+ void print(std::ostream& _stream, ASTNode const& _node);
+ Json::Value toJson(ASTNode const& _node);
+ template <class T>
+ Json::Value toJson(std::vector<ASTPointer<T>> const& _nodes)
+ {
+ Json::Value ret(Json::arrayValue);
+ for (auto const& n: _nodes)
+ ret.append(n ? toJson(*n) : Json::nullValue);
+ return ret;
+ }
bool visit(SourceUnit const& _node) override;
bool visit(PragmaDirective const& _node) override;
bool visit(ImportDirective const& _node) override;
@@ -97,82 +105,60 @@ public:
bool visit(ElementaryTypeNameExpression const& _node) override;
bool visit(Literal const& _node) override;
- void endVisit(SourceUnit const&) override;
- void endVisit(PragmaDirective const&) override;
- void endVisit(ImportDirective const&) override;
- void endVisit(ContractDefinition const&) override;
- void endVisit(InheritanceSpecifier const&) override;
- void endVisit(UsingForDirective const&) override;
- void endVisit(StructDefinition const&) override;
- void endVisit(EnumDefinition const&) override;
- void endVisit(EnumValue const&) override;
- void endVisit(ParameterList const&) override;
- void endVisit(FunctionDefinition const&) override;
- void endVisit(VariableDeclaration const&) override;
- void endVisit(ModifierDefinition const&) override;
- void endVisit(ModifierInvocation const&) override;
void endVisit(EventDefinition const&) override;
- void endVisit(TypeName const&) override;
- void endVisit(ElementaryTypeName const&) override;
- void endVisit(UserDefinedTypeName const&) override;
- void endVisit(FunctionTypeName const&) override;
- void endVisit(Mapping const&) override;
- void endVisit(ArrayTypeName const&) override;
- void endVisit(InlineAssembly const&) override;
- void endVisit(Block const&) override;
- void endVisit(PlaceholderStatement const&) override;
- void endVisit(IfStatement const&) override;
- void endVisit(WhileStatement const&) override;
- void endVisit(ForStatement const&) override;
- void endVisit(Continue const&) override;
- void endVisit(Break const&) override;
- void endVisit(Return const&) override;
- void endVisit(Throw const&) override;
- void endVisit(VariableDeclarationStatement const&) override;
- void endVisit(ExpressionStatement const&) override;
- void endVisit(Conditional const&) override;
- void endVisit(Assignment const&) override;
- void endVisit(TupleExpression const&) override;
- void endVisit(UnaryOperation const&) override;
- void endVisit(BinaryOperation const&) override;
- void endVisit(FunctionCall const&) override;
- void endVisit(NewExpression const&) override;
- void endVisit(MemberAccess const&) override;
- void endVisit(IndexAccess const&) override;
- void endVisit(Identifier const&) override;
- void endVisit(ElementaryTypeNameExpression const&) override;
- void endVisit(Literal const&) override;
private:
- void process();
- void addJsonNode(
+ void setJsonNode(
ASTNode const& _node,
std::string const& _nodeName,
- std::initializer_list<std::pair<std::string const, Json::Value const>> _attributes,
- bool _hasChildren
+ std::initializer_list<std::pair<std::string, Json::Value>>&& _attributes
);
- void addJsonNode(
+ void setJsonNode(
ASTNode const& _node,
std::string const& _nodeName,
- std::vector<std::pair<std::string const, Json::Value const>> const& _attributes,
- bool _hasChildren
+ std::vector<std::pair<std::string, Json::Value>>&& _attributes
);
std::string sourceLocationToString(SourceLocation const& _location) const;
+ std::string namePathToString(std::vector<ASTString> const& _namePath) const;
+ Json::Value idOrNull(ASTNode const* _pt)
+ {
+ return _pt ? Json::Value(nodeId(*_pt)) : Json::nullValue;
+ }
+ Json::Value toJsonOrNull(ASTNode const* _node)
+ {
+ return _node ? toJson(*_node) : Json::nullValue;
+ }
+ Json::Value inlineAssemblyIdentifierToJson(std::pair<assembly::Identifier const* , InlineAssemblyAnnotation::ExternalIdentifierInfo> _info);
std::string visibility(Declaration::Visibility const& _visibility);
std::string location(VariableDeclaration::Location _location);
+ std::string contractKind(ContractDefinition::ContractKind _kind);
+ std::string functionCallKind(FunctionCallKind _kind);
std::string type(Expression const& _expression);
std::string type(VariableDeclaration const& _varDecl);
- inline void goUp()
+ int nodeId(ASTNode const& _node)
{
- solAssert(!m_jsonNodePtrs.empty(), "Uneven json nodes stack. Internal error.");
- m_jsonNodePtrs.pop();
+ return _node.id();
}
-
+ template<class Container>
+ Json::Value getContainerIds(Container const& container)
+ {
+ Json::Value tmp(Json::arrayValue);
+ for (auto const& element: container)
+ {
+ solAssert(element, "");
+ tmp.append(nodeId(*element));
+ }
+ return tmp;
+ }
+ Json::Value typePointerToJson(TypePointer _tp);
+ Json::Value typePointerToJson(std::shared_ptr<std::vector<TypePointer>> _tps);
+ void appendExpressionAttributes(
+ std::vector<std::pair<std::string, Json::Value>> &_attributes,
+ ExpressionAnnotation const& _annotation
+ );
+ bool m_legacy = false; ///< if true, use legacy format
bool m_inEvent = false; ///< whether we are currently inside an event or not
- bool processed = false;
- Json::Value m_astJson;
- std::stack<Json::Value*> m_jsonNodePtrs;
- ASTNode const* m_ast;
+ Json::Value m_currentValue;
std::map<std::string, unsigned> m_sourceIndices;
};
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 41ee6498..cfee041e 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -2183,6 +2183,8 @@ string FunctionType::identifier() const
case Kind::ArrayPush: id += "arraypush"; break;
case Kind::ByteArrayPush: id += "bytearraypush"; break;
case Kind::ObjectCreation: id += "objectcreation"; break;
+ case Kind::Assert: id += "assert"; break;
+ case Kind::Require: id += "require";break;
default: solAssert(false, "Unknown function location."); break;
}
if (isConstant())
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index f018b311..0aa82ea8 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -434,7 +434,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
{
CompilerContext::LocationSetter locationSetter(m_context, _functionCall);
- if (_functionCall.annotation().isTypeConversion)
+ if (_functionCall.annotation().kind == FunctionCallKind::TypeConversion)
{
solAssert(_functionCall.arguments().size() == 1, "");
solAssert(_functionCall.names().empty(), "");
@@ -445,7 +445,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
}
FunctionTypePointer functionType;
- if (_functionCall.annotation().isStructConstructorCall)
+ if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall)
{
auto const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
@@ -476,7 +476,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
solAssert(found, "");
}
- if (_functionCall.annotation().isStructConstructorCall)
+ if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall)
{
TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp
index b6f17907..77d3c217 100644
--- a/libsolidity/formal/Why3Translator.cpp
+++ b/libsolidity/formal/Why3Translator.cpp
@@ -582,7 +582,7 @@ bool Why3Translator::visit(BinaryOperation const& _binaryOperation)
bool Why3Translator::visit(FunctionCall const& _node)
{
- if (_node.annotation().isTypeConversion || _node.annotation().isStructConstructorCall)
+ if (_node.annotation().kind == FunctionCallKind::TypeConversion || _node.annotation().kind == FunctionCallKind::StructConstructorCall)
{
error(_node, "Only ordinary function calls supported.");
return true;
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 503be57b..d5dbaa46 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -377,7 +377,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
{
Json::Value sourceResult = Json::objectValue;
sourceResult["id"] = sourceIndex++;
- sourceResult["legacyAST"] = ASTJsonConverter(m_compilerStack.ast(source), m_compilerStack.sourceIndices()).json();
+ sourceResult["ast"] = ASTJsonConverter(false, m_compilerStack.sourceIndices()).toJson(m_compilerStack.ast(source));
+ sourceResult["legacyAST"] = ASTJsonConverter(true, m_compilerStack.sourceIndices()).toJson(m_compilerStack.ast(source));
output["sources"][source] = sourceResult;
}
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index d5a60b50..e55e3e7e 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -838,9 +838,9 @@ void CommandLineInterface::handleCombinedJSON()
output[g_strSources] = Json::Value(Json::objectValue);
for (auto const& sourceCode: m_sourceCodes)
{
- ASTJsonConverter converter(m_compiler->ast(sourceCode.first), m_compiler->sourceIndices());
+ ASTJsonConverter converter(true, m_compiler->sourceIndices());
output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue);
- output[g_strSources][sourceCode.first]["AST"] = converter.json();
+ output[g_strSources][sourceCode.first]["AST"] = converter.toJson(m_compiler->ast(sourceCode.first));
}
}
cout << dev::jsonCompactPrint(output) << endl;
@@ -883,8 +883,7 @@ void CommandLineInterface::handleAst(string const& _argStr)
}
else
{
- ASTJsonConverter converter(m_compiler->ast(sourceCode.first));
- converter.print(data);
+ ASTJsonConverter(true).print(data, m_compiler->ast(sourceCode.first));
postfix += "_json";
}
boost::filesystem::path path(sourceCode.first);
@@ -908,8 +907,7 @@ void CommandLineInterface::handleAst(string const& _argStr)
}
else
{
- ASTJsonConverter converter(m_compiler->ast(sourceCode.first));
- converter.print(cout);
+ ASTJsonConverter(true).print(cout, m_compiler->ast(sourceCode.first));
}
}
}
diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp
index 92a102b6..7f99324e 100644
--- a/solc/jsonCompiler.cpp
+++ b/solc/jsonCompiler.cpp
@@ -245,7 +245,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback
output["sourceList"].append(source);
output["sources"] = Json::Value(Json::objectValue);
for (auto const& source: compiler.sourceNames())
- output["sources"][source]["AST"] = ASTJsonConverter(compiler.ast(source), compiler.sourceIndices()).json();
+ output["sources"][source]["AST"] = ASTJsonConverter(true, compiler.sourceIndices()).toJson(compiler.ast(source));
}
catch (...)
{
diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp
index d23815b4..8a790347 100644
--- a/test/libsolidity/ASTJSON.cpp
+++ b/test/libsolidity/ASTJSON.cpp
@@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(smoke_test)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit");
}
@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(source_location)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit");
BOOST_CHECK_EQUAL(astJson["children"][0]["name"], "ContractDefinition");
BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["name"], "FunctionDefinition");
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(inheritance_specifier)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
BOOST_CHECK_EQUAL(astJson["children"][1]["attributes"]["name"], "C2");
BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["name"], "InheritanceSpecifier");
BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["src"], "30:2:1");
@@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(using_for_directive)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value usingFor = astJson["children"][1]["children"][0];
BOOST_CHECK_EQUAL(usingFor["name"], "UsingForDirective");
BOOST_CHECK_EQUAL(usingFor["src"], "26:17:1");
@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(enum_value)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value enumDefinition = astJson["children"][0]["children"][0];
BOOST_CHECK_EQUAL(enumDefinition["children"][0]["name"], "EnumValue");
BOOST_CHECK_EQUAL(enumDefinition["children"][0]["attributes"]["name"], "A");
@@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(modifier_definition)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value modifier = astJson["children"][0]["children"][0];
BOOST_CHECK_EQUAL(modifier["name"], "ModifierDefinition");
BOOST_CHECK_EQUAL(modifier["attributes"]["name"], "M");
@@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(modifier_invocation)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value modifier = astJson["children"][0]["children"][1]["children"][2];
BOOST_CHECK_EQUAL(modifier["name"], "ModifierInvocation");
BOOST_CHECK_EQUAL(modifier["src"], "52:4:1");
@@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(event_definition)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value event = astJson["children"][0]["children"][0];
BOOST_CHECK_EQUAL(event["name"], "EventDefinition");
BOOST_CHECK_EQUAL(event["attributes"]["name"], "E");
@@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(array_type_name)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value array = astJson["children"][0]["children"][0]["children"][0];
BOOST_CHECK_EQUAL(array["name"], "ArrayTypeName");
BOOST_CHECK_EQUAL(array["src"], "13:6:1");
@@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(placeholder_statement)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value placeholder = astJson["children"][0]["children"][0]["children"][1]["children"][0];
BOOST_CHECK_EQUAL(placeholder["name"], "PlaceholderStatement");
BOOST_CHECK_EQUAL(placeholder["src"], "26:1:1");
@@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(non_utf8)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value literal = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][1];
BOOST_CHECK_EQUAL(literal["name"], "Literal");
BOOST_CHECK_EQUAL(literal["attributes"]["hexvalue"], "ff");
@@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE(function_type)
c.parseAndAnalyze();
map<string, unsigned> sourceIndices;
sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a"));
Json::Value fun = astJson["children"][0]["children"][0];
BOOST_CHECK_EQUAL(fun["name"], "FunctionDefinition");
Json::Value argument = fun["children"][0]["children"][0];
diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp
index 46c718d7..6aec59ab 100644
--- a/test/libsolidity/JSONCompiler.cpp
+++ b/test/libsolidity/JSONCompiler.cpp
@@ -90,10 +90,12 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
BOOST_CHECK(result["sources"]["fileA"].isObject());
BOOST_CHECK(result["sources"]["fileA"]["AST"].isObject());
BOOST_CHECK(dev::jsonCompactPrint(result["sources"]["fileA"]["AST"]) ==
- "{\"children\":[{\"attributes\":{\"fullyImplemented\":true,\"isLibrary\":false,\"linearizedBaseContracts\":[1],"
- "\"name\":\"A\"},\"children\":[],\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"name\":\"SourceUnit\"}");
+ "{\"attributes\":{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]}},"
+ "\"children\":[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null],"
+ "\"contractKind\":\"contract\",\"fullyImplemented\":true,\"linearizedBaseContracts\":[1],"
+ "\"name\":\"A\",\"nodes\":[null],\"scope\":2},\"id\":1,\"name\":\"ContractDefinition\","
+ "\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}");
}
-
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp
index ec2f69d9..050ca500 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -215,8 +215,10 @@ BOOST_AUTO_TEST_CASE(basic_compilation)
BOOST_CHECK(result["sources"]["fileA"].isObject());
BOOST_CHECK(result["sources"]["fileA"]["legacyAST"].isObject());
BOOST_CHECK(dev::jsonCompactPrint(result["sources"]["fileA"]["legacyAST"]) ==
- "{\"children\":[{\"attributes\":{\"fullyImplemented\":true,\"isLibrary\":false,\"linearizedBaseContracts\":[1],"
- "\"name\":\"A\"},\"children\":[],\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"name\":\"SourceUnit\"}");
+ "{\"attributes\":{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]}},\"children\":"
+ "[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null],\"contractKind\":\"contract\","
+ "\"fullyImplemented\":true,\"linearizedBaseContracts\":[1],\"name\":\"A\",\"nodes\":[null],\"scope\":2},"
+ "\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}");
}
BOOST_AUTO_TEST_SUITE_END()