aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-05-19 23:55:33 +0800
committerGitHub <noreply@github.com>2017-05-19 23:55:33 +0800
commit56424bb2026ab484470b5e0e6f1ddb2ab3c7ac85 (patch)
tree4ba6d697307c932957f7fe95d3d6b80797030e00
parent20125c18ba6bd8876b24d988dd299e309fda8c83 (diff)
parentbbef2cd4a8c4dd3ad0d1e16d6070a88a5f83fcc6 (diff)
downloaddexon-solidity-56424bb2026ab484470b5e0e6f1ddb2ab3c7ac85.tar.gz
dexon-solidity-56424bb2026ab484470b5e0e6f1ddb2ab3c7ac85.tar.zst
dexon-solidity-56424bb2026ab484470b5e0e6f1ddb2ab3c7ac85.zip
Merge pull request #2262 from ethereum/interface-cleanup
Cleanup the external interfaces (ABI and Natspec)
-rw-r--r--libsolidity/interface/ABI.cpp116
-rw-r--r--libsolidity/interface/ABI.h56
-rw-r--r--libsolidity/interface/CompilerStack.cpp42
-rw-r--r--libsolidity/interface/CompilerStack.h16
-rw-r--r--libsolidity/interface/InterfaceHandler.cpp197
-rw-r--r--libsolidity/interface/Natspec.cpp130
-rw-r--r--libsolidity/interface/Natspec.h (renamed from libsolidity/interface/InterfaceHandler.h)9
-rw-r--r--libsolidity/interface/StandardCompiler.cpp6
-rw-r--r--libsolidity/parsing/Parser.cpp1
-rw-r--r--solc/CommandLineInterface.cpp39
-rw-r--r--solc/CommandLineInterface.h3
-rw-r--r--solc/jsonCompiler.cpp2
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp2
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp4
14 files changed, 369 insertions, 254 deletions
diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp
new file mode 100644
index 00000000..12f958fc
--- /dev/null
+++ b/libsolidity/interface/ABI.cpp
@@ -0,0 +1,116 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Utilities to handle the Contract ABI (https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI)
+ */
+
+#include <libsolidity/interface/ABI.h>
+#include <boost/range/irange.hpp>
+#include <libsolidity/ast/AST.h>
+
+using namespace std;
+using namespace dev;
+using namespace dev::solidity;
+
+Json::Value ABI::generate(ContractDefinition const& _contractDef)
+{
+ Json::Value abi(Json::arrayValue);
+
+ for (auto it: _contractDef.interfaceFunctions())
+ {
+ auto externalFunctionType = it.second->interfaceFunctionType();
+ Json::Value method;
+ method["type"] = "function";
+ method["name"] = it.second->declaration().name();
+ method["constant"] = it.second->isConstant();
+ method["payable"] = it.second->isPayable();
+ method["inputs"] = formatTypeList(
+ externalFunctionType->parameterNames(),
+ externalFunctionType->parameterTypes(),
+ _contractDef.isLibrary()
+ );
+ method["outputs"] = formatTypeList(
+ externalFunctionType->returnParameterNames(),
+ externalFunctionType->returnParameterTypes(),
+ _contractDef.isLibrary()
+ );
+ abi.append(method);
+ }
+ if (_contractDef.constructor())
+ {
+ Json::Value method;
+ method["type"] = "constructor";
+ auto externalFunction = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType();
+ solAssert(!!externalFunction, "");
+ method["payable"] = externalFunction->isPayable();
+ method["inputs"] = formatTypeList(
+ externalFunction->parameterNames(),
+ externalFunction->parameterTypes(),
+ _contractDef.isLibrary()
+ );
+ abi.append(method);
+ }
+ if (_contractDef.fallbackFunction())
+ {
+ auto externalFunctionType = FunctionType(*_contractDef.fallbackFunction(), false).interfaceFunctionType();
+ solAssert(!!externalFunctionType, "");
+ Json::Value method;
+ method["type"] = "fallback";
+ method["payable"] = externalFunctionType->isPayable();
+ abi.append(method);
+ }
+ for (auto const& it: _contractDef.interfaceEvents())
+ {
+ Json::Value event;
+ event["type"] = "event";
+ event["name"] = it->name();
+ event["anonymous"] = it->isAnonymous();
+ Json::Value params(Json::arrayValue);
+ for (auto const& p: it->parameters())
+ {
+ solAssert(!!p->annotation().type->interfaceType(false), "");
+ Json::Value input;
+ input["name"] = p->name();
+ input["type"] = p->annotation().type->interfaceType(false)->canonicalName(false);
+ input["indexed"] = p->isIndexed();
+ params.append(input);
+ }
+ event["inputs"] = params;
+ abi.append(event);
+ }
+
+ return abi;
+}
+
+Json::Value ABI::formatTypeList(
+ vector<string> const& _names,
+ vector<TypePointer> const& _types,
+ bool _forLibrary
+)
+{
+ Json::Value params(Json::arrayValue);
+ solAssert(_names.size() == _types.size(), "Names and types vector size does not match");
+ for (unsigned i = 0; i < _names.size(); ++i)
+ {
+ solAssert(_types[i], "");
+ Json::Value param;
+ param["name"] = _names[i];
+ param["type"] = _types[i]->canonicalName(_forLibrary);
+ params.append(param);
+ }
+ return params;
+}
diff --git a/libsolidity/interface/ABI.h b/libsolidity/interface/ABI.h
new file mode 100644
index 00000000..95b162a9
--- /dev/null
+++ b/libsolidity/interface/ABI.h
@@ -0,0 +1,56 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Utilities to handle the Contract ABI (https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI)
+ */
+
+#pragma once
+
+#include <string>
+#include <memory>
+#include <json/json.h>
+
+namespace dev
+{
+namespace solidity
+{
+
+// Forward declarations
+class ContractDefinition;
+class Type;
+using TypePointer = std::shared_ptr<Type const>;
+
+class ABI
+{
+public:
+ /// Get the ABI Interface of the contract
+ /// @param _contractDef The contract definition
+ /// @return A JSONrepresentation of the contract's ABI Interface
+ static Json::Value generate(ContractDefinition const& _contractDef);
+private:
+ /// @returns a json value suitable for a list of types in function input or output
+ /// parameters or other places. If @a _forLibrary is true, complex types are referenced
+ /// by name, otherwise they are anonymously expanded.
+ static Json::Value formatTypeList(
+ std::vector<std::string> const& _names,
+ std::vector<TypePointer> const& _types,
+ bool _forLibrary
+ );
+};
+
+}
+}
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 5c836358..72712298 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -37,7 +37,8 @@
#include <libsolidity/analysis/PostTypeChecker.h>
#include <libsolidity/analysis/SyntaxChecker.h>
#include <libsolidity/codegen/Compiler.h>
-#include <libsolidity/interface/InterfaceHandler.h>
+#include <libsolidity/interface/ABI.h>
+#include <libsolidity/interface/Natspec.h>
#include <libsolidity/interface/GasEstimator.h>
#include <libsolidity/formal/Why3Translator.h>
@@ -219,8 +220,8 @@ bool CompilerStack::analyze()
TypeChecker typeChecker(m_errors);
if (typeChecker.checkTypeRequirements(*contract))
{
- contract->setDevDocumentation(InterfaceHandler::devDocumentation(*contract));
- contract->setUserDocumentation(InterfaceHandler::userDocumentation(*contract));
+ contract->setDevDocumentation(Natspec::devDocumentation(*contract));
+ contract->setUserDocumentation(Natspec::userDocumentation(*contract));
}
else
noErrors = false;
@@ -444,17 +445,31 @@ map<string, unsigned> CompilerStack::sourceIndices() const
return indices;
}
-Json::Value const& CompilerStack::interface(string const& _contractName) const
+Json::Value const& CompilerStack::contractABI(string const& _contractName) const
{
- return metadata(_contractName, DocumentationType::ABIInterface);
+ return contractABI(contract(_contractName));
}
-Json::Value const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const
+Json::Value const& CompilerStack::contractABI(Contract const& _contract) const
{
- return metadata(contract(_contractName), _type);
+ if (m_stackState < AnalysisSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+
+ solAssert(_contract.contract, "");
+
+ // caches the result
+ if (!_contract.abi)
+ _contract.abi.reset(new Json::Value(ABI::generate(*_contract.contract)));
+
+ return *_contract.abi;
}
-Json::Value const& CompilerStack::metadata(Contract const& _contract, DocumentationType _type) const
+Json::Value const& CompilerStack::natspec(string const& _contractName, DocumentationType _type) const
+{
+ return natspec(contract(_contractName), _type);
+}
+
+Json::Value const& CompilerStack::natspec(Contract const& _contract, DocumentationType _type) const
{
if (m_stackState < AnalysisSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
@@ -471,16 +486,13 @@ Json::Value const& CompilerStack::metadata(Contract const& _contract, Documentat
case DocumentationType::NatspecDev:
doc = &_contract.devDocumentation;
break;
- case DocumentationType::ABIInterface:
- doc = &_contract.interface;
- break;
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type."));
}
// caches the result
if (!*doc)
- doc->reset(new Json::Value(InterfaceHandler::documentation(*_contract.contract, _type)));
+ doc->reset(new Json::Value(Natspec::documentation(*_contract.contract, _type)));
return *(*doc);
}
@@ -830,9 +842,9 @@ string CompilerStack::createOnChainMetadata(Contract const& _contract) const
for (auto const& library: m_libraries)
meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes());
- meta["output"]["abi"] = metadata(_contract, DocumentationType::ABIInterface);
- meta["output"]["userdoc"] = metadata(_contract, DocumentationType::NatspecUser);
- meta["output"]["devdoc"] = metadata(_contract, DocumentationType::NatspecDev);
+ meta["output"]["abi"] = contractABI(_contract);
+ meta["output"]["userdoc"] = natspec(_contract, DocumentationType::NatspecUser);
+ meta["output"]["devdoc"] = natspec(_contract, DocumentationType::NatspecDev);
return jsonCompactPrint(meta);
}
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index c1d344ca..84d15d70 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -59,15 +59,14 @@ class FunctionDefinition;
class SourceUnit;
class Compiler;
class GlobalContext;
-class InterfaceHandler;
+class Natspec;
class Error;
class DeclarationContainer;
enum class DocumentationType: uint8_t
{
NatspecUser = 1,
- NatspecDev,
- ABIInterface
+ NatspecDev
};
/**
@@ -173,14 +172,14 @@ public:
/// @returns a mapping assigning each source name its index inside the vector returned
/// by sourceNames().
std::map<std::string, unsigned> sourceIndices() const;
- /// @returns a JSON representing the contract interface.
+ /// @returns a JSON representing the contract ABI.
/// Prerequisite: Successful call to parse or compile.
- Json::Value const& interface(std::string const& _contractName = "") const;
+ Json::Value const& contractABI(std::string const& _contractName = "") const;
/// @returns a JSON representing the contract's documentation.
/// Prerequisite: Successful call to parse or compile.
/// @param type The type of the documentation to get.
/// Can be one of 4 types defined at @c DocumentationType
- Json::Value const& metadata(std::string const& _contractName, DocumentationType _type) const;
+ Json::Value const& natspec(std::string const& _contractName, DocumentationType _type) const;
std::string const& onChainMetadata(std::string const& _contractName) const;
void useMetadataLiteralSources(bool _metadataLiteralSources) { m_metadataLiteralSources = _metadataLiteralSources; }
@@ -230,7 +229,7 @@ private:
eth::LinkerObject runtimeObject;
eth::LinkerObject cloneObject;
std::string onChainMetadata; ///< The metadata json that will be hashed into the chain.
- mutable std::unique_ptr<Json::Value const> interface;
+ mutable std::unique_ptr<Json::Value const> abi;
mutable std::unique_ptr<Json::Value const> userDocumentation;
mutable std::unique_ptr<Json::Value const> devDocumentation;
mutable std::unique_ptr<std::string const> sourceMapping;
@@ -267,7 +266,8 @@ private:
std::string createOnChainMetadata(Contract const& _contract) const;
std::string computeSourceMapping(eth::AssemblyItems const& _items) const;
- Json::Value const& metadata(Contract const&, DocumentationType _type) const;
+ Json::Value const& contractABI(Contract const&) const;
+ Json::Value const& natspec(Contract const&, DocumentationType _type) const;
struct Remapping
{
diff --git a/libsolidity/interface/InterfaceHandler.cpp b/libsolidity/interface/InterfaceHandler.cpp
deleted file mode 100644
index 6c1bb0c4..00000000
--- a/libsolidity/interface/InterfaceHandler.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-
-#include <libsolidity/interface/InterfaceHandler.h>
-#include <boost/range/irange.hpp>
-#include <libsolidity/ast/AST.h>
-#include <libsolidity/interface/CompilerStack.h>
-
-using namespace std;
-using namespace dev;
-using namespace dev::solidity;
-
-Json::Value InterfaceHandler::documentation(
- ContractDefinition const& _contractDef,
- DocumentationType _type
-)
-{
- switch(_type)
- {
- case DocumentationType::NatspecUser:
- return userDocumentation(_contractDef);
- case DocumentationType::NatspecDev:
- return devDocumentation(_contractDef);
- case DocumentationType::ABIInterface:
- return abiInterface(_contractDef);
- }
-
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation type"));
-}
-
-Json::Value InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
-{
- Json::Value abi(Json::arrayValue);
-
- for (auto it: _contractDef.interfaceFunctions())
- {
- auto externalFunctionType = it.second->interfaceFunctionType();
- Json::Value method;
- method["type"] = "function";
- method["name"] = it.second->declaration().name();
- method["constant"] = it.second->isConstant();
- method["payable"] = it.second->isPayable();
- method["inputs"] = formatTypeList(
- externalFunctionType->parameterNames(),
- externalFunctionType->parameterTypes(),
- _contractDef.isLibrary()
- );
- method["outputs"] = formatTypeList(
- externalFunctionType->returnParameterNames(),
- externalFunctionType->returnParameterTypes(),
- _contractDef.isLibrary()
- );
- abi.append(method);
- }
- if (_contractDef.constructor())
- {
- Json::Value method;
- method["type"] = "constructor";
- auto externalFunction = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType();
- solAssert(!!externalFunction, "");
- method["payable"] = externalFunction->isPayable();
- method["inputs"] = formatTypeList(
- externalFunction->parameterNames(),
- externalFunction->parameterTypes(),
- _contractDef.isLibrary()
- );
- abi.append(method);
- }
- if (_contractDef.fallbackFunction())
- {
- auto externalFunctionType = FunctionType(*_contractDef.fallbackFunction(), false).interfaceFunctionType();
- solAssert(!!externalFunctionType, "");
- Json::Value method;
- method["type"] = "fallback";
- method["payable"] = externalFunctionType->isPayable();
- abi.append(method);
- }
- for (auto const& it: _contractDef.interfaceEvents())
- {
- Json::Value event;
- event["type"] = "event";
- event["name"] = it->name();
- event["anonymous"] = it->isAnonymous();
- Json::Value params(Json::arrayValue);
- for (auto const& p: it->parameters())
- {
- solAssert(!!p->annotation().type->interfaceType(false), "");
- Json::Value input;
- input["name"] = p->name();
- input["type"] = p->annotation().type->interfaceType(false)->canonicalName(false);
- input["indexed"] = p->isIndexed();
- params.append(input);
- }
- event["inputs"] = params;
- abi.append(event);
- }
-
- return abi;
-}
-
-Json::Value InterfaceHandler::userDocumentation(ContractDefinition const& _contractDef)
-{
- Json::Value doc;
- Json::Value methods(Json::objectValue);
-
- for (auto const& it: _contractDef.interfaceFunctions())
- if (it.second->hasDeclaration())
- if (auto const* f = dynamic_cast<FunctionDefinition const*>(&it.second->declaration()))
- {
- string value = extractDoc(f->annotation().docTags, "notice");
- if (!value.empty())
- {
- Json::Value user;
- // since @notice is the only user tag if missing function should not appear
- user["notice"] = Json::Value(value);
- methods[it.second->externalSignature()] = user;
- }
- }
- doc["methods"] = methods;
-
- return doc;
-}
-
-Json::Value InterfaceHandler::devDocumentation(ContractDefinition const& _contractDef)
-{
- Json::Value doc;
- Json::Value methods(Json::objectValue);
-
- auto author = extractDoc(_contractDef.annotation().docTags, "author");
- if (!author.empty())
- doc["author"] = author;
- auto title = extractDoc(_contractDef.annotation().docTags, "title");
- if (!title.empty())
- doc["title"] = title;
-
- for (auto const& it: _contractDef.interfaceFunctions())
- {
- if (!it.second->hasDeclaration())
- continue;
- Json::Value method;
- if (auto fun = dynamic_cast<FunctionDefinition const*>(&it.second->declaration()))
- {
- auto dev = extractDoc(fun->annotation().docTags, "dev");
- if (!dev.empty())
- method["details"] = Json::Value(dev);
-
- auto author = extractDoc(fun->annotation().docTags, "author");
- if (!author.empty())
- method["author"] = author;
-
- auto ret = extractDoc(fun->annotation().docTags, "return");
- if (!ret.empty())
- method["return"] = ret;
-
- Json::Value params(Json::objectValue);
- auto paramRange = fun->annotation().docTags.equal_range("param");
- for (auto i = paramRange.first; i != paramRange.second; ++i)
- params[i->second.paramName] = Json::Value(i->second.content);
-
- if (!params.empty())
- method["params"] = params;
-
- if (!method.empty())
- // add the function, only if we have any documentation to add
- methods[it.second->externalSignature()] = method;
- }
- }
- doc["methods"] = methods;
-
- return doc;
-}
-
-Json::Value InterfaceHandler::formatTypeList(
- vector<string> const& _names,
- vector<TypePointer> const& _types,
- bool _forLibrary
-)
-{
- Json::Value params(Json::arrayValue);
- solAssert(_names.size() == _types.size(), "Names and types vector size does not match");
- for (unsigned i = 0; i < _names.size(); ++i)
- {
- solAssert(_types[i], "");
- Json::Value param;
- param["name"] = _names[i];
- param["type"] = _types[i]->canonicalName(_forLibrary);
- params.append(param);
- }
- return params;
-}
-
-string InterfaceHandler::extractDoc(multimap<string, DocTag> const& _tags, string const& _name)
-{
- string value;
- auto range = _tags.equal_range(_name);
- for (auto i = range.first; i != range.second; i++)
- value += i->second.content;
- return value;
-}
diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp
new file mode 100644
index 00000000..70486e23
--- /dev/null
+++ b/libsolidity/interface/Natspec.cpp
@@ -0,0 +1,130 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Lefteris <lefteris@ethdev.com>
+ * @date 2014
+ * Takes the parsed AST and produces the Natspec documentation:
+ * https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format
+ *
+ * Can generally deal with JSON files
+ */
+
+#include <libsolidity/interface/Natspec.h>
+#include <boost/range/irange.hpp>
+#include <libsolidity/ast/AST.h>
+#include <libsolidity/interface/CompilerStack.h>
+
+using namespace std;
+using namespace dev;
+using namespace dev::solidity;
+
+Json::Value Natspec::documentation(
+ ContractDefinition const& _contractDef,
+ DocumentationType _type
+)
+{
+ switch(_type)
+ {
+ case DocumentationType::NatspecUser:
+ return userDocumentation(_contractDef);
+ case DocumentationType::NatspecDev:
+ return devDocumentation(_contractDef);
+ }
+
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation type"));
+}
+
+Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
+{
+ Json::Value doc;
+ Json::Value methods(Json::objectValue);
+
+ for (auto const& it: _contractDef.interfaceFunctions())
+ if (it.second->hasDeclaration())
+ if (auto const* f = dynamic_cast<FunctionDefinition const*>(&it.second->declaration()))
+ {
+ string value = extractDoc(f->annotation().docTags, "notice");
+ if (!value.empty())
+ {
+ Json::Value user;
+ // since @notice is the only user tag if missing function should not appear
+ user["notice"] = Json::Value(value);
+ methods[it.second->externalSignature()] = user;
+ }
+ }
+ doc["methods"] = methods;
+
+ return doc;
+}
+
+Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
+{
+ Json::Value doc;
+ Json::Value methods(Json::objectValue);
+
+ auto author = extractDoc(_contractDef.annotation().docTags, "author");
+ if (!author.empty())
+ doc["author"] = author;
+ auto title = extractDoc(_contractDef.annotation().docTags, "title");
+ if (!title.empty())
+ doc["title"] = title;
+
+ for (auto const& it: _contractDef.interfaceFunctions())
+ {
+ if (!it.second->hasDeclaration())
+ continue;
+ Json::Value method;
+ if (auto fun = dynamic_cast<FunctionDefinition const*>(&it.second->declaration()))
+ {
+ auto dev = extractDoc(fun->annotation().docTags, "dev");
+ if (!dev.empty())
+ method["details"] = Json::Value(dev);
+
+ auto author = extractDoc(fun->annotation().docTags, "author");
+ if (!author.empty())
+ method["author"] = author;
+
+ auto ret = extractDoc(fun->annotation().docTags, "return");
+ if (!ret.empty())
+ method["return"] = ret;
+
+ Json::Value params(Json::objectValue);
+ auto paramRange = fun->annotation().docTags.equal_range("param");
+ for (auto i = paramRange.first; i != paramRange.second; ++i)
+ params[i->second.paramName] = Json::Value(i->second.content);
+
+ if (!params.empty())
+ method["params"] = params;
+
+ if (!method.empty())
+ // add the function, only if we have any documentation to add
+ methods[it.second->externalSignature()] = method;
+ }
+ }
+ doc["methods"] = methods;
+
+ return doc;
+}
+
+string Natspec::extractDoc(multimap<string, DocTag> const& _tags, string const& _name)
+{
+ string value;
+ auto range = _tags.equal_range(_name);
+ for (auto i = range.first; i != range.second; i++)
+ value += i->second.content;
+ return value;
+}
diff --git a/libsolidity/interface/InterfaceHandler.h b/libsolidity/interface/Natspec.h
index 56927d44..bec9acd2 100644
--- a/libsolidity/interface/InterfaceHandler.h
+++ b/libsolidity/interface/Natspec.h
@@ -17,8 +17,7 @@
/**
* @author Lefteris <lefteris@ethdev.com>
* @date 2014
- * Takes the parsed AST and produces the Natspec
- * documentation and the ABI interface
+ * Takes the parsed AST and produces the Natspec documentation:
* https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format
*
* Can generally deal with JSON files
@@ -59,7 +58,7 @@ enum class CommentOwner
Function
};
-class InterfaceHandler
+class Natspec
{
public:
/// Get the given type of documentation
@@ -71,10 +70,6 @@ public:
ContractDefinition const& _contractDef,
DocumentationType _type
);
- /// Get the ABI Interface of the contract
- /// @param _contractDef The contract definition
- /// @return A JSONrepresentation of the contract's ABI Interface
- static Json::Value abiInterface(ContractDefinition const& _contractDef);
/// Get the User documentation of the contract
/// @param _contractDef The contract definition
/// @return A JSON representation of the contract's user documentation
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 223cc15d..503be57b 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -391,10 +391,10 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
// ABI, documentation and metadata
Json::Value contractData(Json::objectValue);
- contractData["abi"] = m_compilerStack.metadata(contractName, DocumentationType::ABIInterface);
+ contractData["abi"] = m_compilerStack.contractABI(contractName);
contractData["metadata"] = m_compilerStack.onChainMetadata(contractName);
- contractData["userdoc"] = m_compilerStack.metadata(contractName, DocumentationType::NatspecUser);
- contractData["devdoc"] = m_compilerStack.metadata(contractName, DocumentationType::NatspecDev);
+ contractData["userdoc"] = m_compilerStack.natspec(contractName, DocumentationType::NatspecUser);
+ contractData["devdoc"] = m_compilerStack.natspec(contractName, DocumentationType::NatspecDev);
// EVM
Json::Value evmData(Json::objectValue);
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index b5130c8a..72150a3e 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -27,7 +27,6 @@
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/inlineasm/AsmParser.h>
#include <libsolidity/interface/Exceptions.h>
-#include <libsolidity/interface/InterfaceHandler.h>
using namespace std;
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 0f2e83dc..d5a60b50 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -266,24 +266,31 @@ void CommandLineInterface::handleOnChainMetadata(string const& _contract)
return;
string data = m_compiler->onChainMetadata(_contract);
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile(m_compiler->filesystemFriendlyName(_contract) + "_meta.json", data);
else
cout << "Metadata: " << endl << data << endl;
}
-void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract)
+void CommandLineInterface::handleABI(string const& _contract)
+{
+ if (!m_args.count(g_argAbi))
+ return;
+
+ string data = dev::jsonCompactPrint(m_compiler->contractABI(_contract));
+ if (m_args.count(g_argOutputDir))
+ createFile(m_compiler->filesystemFriendlyName(_contract) + ".abi", data);
+ else
+ cout << "Contract JSON ABI " << endl << data << endl;
+}
+
+void CommandLineInterface::handleNatspec(DocumentationType _type, string const& _contract)
{
std::string argName;
std::string suffix;
std::string title;
switch(_type)
{
- case DocumentationType::ABIInterface:
- argName = g_argAbi;
- suffix = ".abi";
- title = "Contract JSON ABI";
- break;
case DocumentationType::NatspecUser:
argName = g_argNatspecUser;
suffix = ".docuser";
@@ -301,11 +308,7 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co
if (m_args.count(argName))
{
- std::string output;
- if (_type == DocumentationType::ABIInterface)
- output = dev::jsonCompactPrint(m_compiler->metadata(_contract, _type));
- else
- output = dev::jsonPrettyPrint(m_compiler->metadata(_contract, _type));
+ std::string output = dev::jsonPrettyPrint(m_compiler->natspec(_contract, _type));
if (m_args.count(g_argOutputDir))
createFile(m_compiler->filesystemFriendlyName(_contract) + suffix, output);
@@ -787,7 +790,7 @@ void CommandLineInterface::handleCombinedJSON()
{
Json::Value contractData(Json::objectValue);
if (requests.count(g_strAbi))
- contractData[g_strAbi] = dev::jsonCompactPrint(m_compiler->interface(contractName));
+ contractData[g_strAbi] = dev::jsonCompactPrint(m_compiler->contractABI(contractName));
if (requests.count("metadata"))
contractData["metadata"] = m_compiler->onChainMetadata(contractName);
if (requests.count(g_strBinary))
@@ -814,9 +817,9 @@ void CommandLineInterface::handleCombinedJSON()
contractData[g_strSrcMapRuntime] = map ? *map : "";
}
if (requests.count(g_strNatspecDev))
- contractData[g_strNatspecDev] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecDev));
+ contractData[g_strNatspecDev] = dev::jsonCompactPrint(m_compiler->natspec(contractName, DocumentationType::NatspecDev));
if (requests.count(g_strNatspecUser))
- contractData[g_strNatspecUser] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecUser));
+ contractData[g_strNatspecUser] = dev::jsonCompactPrint(m_compiler->natspec(contractName, DocumentationType::NatspecUser));
output[g_strContracts][contractName] = contractData;
}
@@ -1069,9 +1072,9 @@ void CommandLineInterface::outputCompilationResults()
handleBytecode(contract);
handleSignatureHashes(contract);
handleOnChainMetadata(contract);
- handleMeta(DocumentationType::ABIInterface, contract);
- handleMeta(DocumentationType::NatspecDev, contract);
- handleMeta(DocumentationType::NatspecUser, contract);
+ handleABI(contract);
+ handleNatspec(DocumentationType::NatspecDev, contract);
+ handleNatspec(DocumentationType::NatspecUser, contract);
} // end of contracts iteration
handleFormal();
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index f52a03c7..ebf52625 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -67,7 +67,8 @@ private:
void handleBytecode(std::string const& _contract);
void handleSignatureHashes(std::string const& _contract);
void handleOnChainMetadata(std::string const& _contract);
- void handleMeta(DocumentationType _type, std::string const& _contract);
+ void handleABI(std::string const& _contract);
+ void handleNatspec(DocumentationType _type, std::string const& _contract);
void handleGasEstimation(std::string const& _contract);
void handleFormal();
diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp
index 42c25de0..92a102b6 100644
--- a/solc/jsonCompiler.cpp
+++ b/solc/jsonCompiler.cpp
@@ -193,7 +193,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback
for (string const& contractName: compiler.contractNames())
{
Json::Value contractData(Json::objectValue);
- contractData["interface"] = dev::jsonCompactPrint(compiler.interface(contractName));
+ contractData["interface"] = dev::jsonCompactPrint(compiler.contractABI(contractName));
contractData["bytecode"] = compiler.object(contractName).toHex();
contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex();
contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode);
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index bdcc5b10..1ebccc13 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -44,7 +44,7 @@ public:
{
ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze("pragma solidity >=0.0;\n" + _code), "Parsing contract failed");
- Json::Value generatedInterface = m_compilerStack.metadata("", DocumentationType::ABIInterface);
+ Json::Value generatedInterface = m_compilerStack.contractABI("");
Json::Value expectedInterface;
m_reader.parse(_expectedInterfaceString, expectedInterface);
BOOST_CHECK_MESSAGE(
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index 78c1a0ee..2a7376b9 100644
--- a/test/libsolidity/SolidityNatspecJSON.cpp
+++ b/test/libsolidity/SolidityNatspecJSON.cpp
@@ -49,9 +49,9 @@ public:
Json::Value generatedDocumentation;
if (_userDocumentation)
- generatedDocumentation = m_compilerStack.metadata("", DocumentationType::NatspecUser);
+ generatedDocumentation = m_compilerStack.natspec("", DocumentationType::NatspecUser);
else
- generatedDocumentation = m_compilerStack.metadata("", DocumentationType::NatspecDev);
+ generatedDocumentation = m_compilerStack.natspec("", DocumentationType::NatspecDev);
Json::Value expectedDocumentation;
m_reader.parse(_expectedDocumentationString, expectedDocumentation);
BOOST_CHECK_MESSAGE(