From 8169e149c98b14861cc6467f9f796010f617c521 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 6 May 2017 17:59:16 +0100 Subject: Rename CompilerStack.interface to CompilerStack.contractABI --- libsolidity/interface/CompilerStack.cpp | 2 +- libsolidity/interface/CompilerStack.h | 4 ++-- solc/CommandLineInterface.cpp | 2 +- solc/jsonCompiler.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 5c836358..7887a2cb 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -444,7 +444,7 @@ map 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); } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index c1d344ca..e98c3b82 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -173,9 +173,9 @@ public: /// @returns a mapping assigning each source name its index inside the vector returned /// by sourceNames(). std::map 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. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 0f2e83dc..badebf38 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -787,7 +787,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)) 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); -- cgit From 4bf3cbb09a42131dba27b080a4917f30284959d3 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 6 May 2017 18:02:56 +0100 Subject: Use CompilerStack.contractABI directly --- libsolidity/interface/CompilerStack.cpp | 7 ++++++- libsolidity/interface/StandardCompiler.cpp | 2 +- solc/CommandLineInterface.cpp | 27 +++++++++++++++------------ solc/CommandLineInterface.h | 1 + test/libsolidity/SolidityABIJSON.cpp | 2 +- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 7887a2cb..1f235656 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -449,6 +449,11 @@ Json::Value const& CompilerStack::contractABI(string const& _contractName) const return metadata(_contractName, DocumentationType::ABIInterface); } +Json::Value const& CompilerStack::contractABI(Contract const& _contract) const +{ + return metadata(_contract, DocumentationType::ABIInterface); +} + Json::Value const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const { return metadata(contract(_contractName), _type); @@ -830,7 +835,7 @@ 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"]["abi"] = contractABI(_contract); meta["output"]["userdoc"] = metadata(_contract, DocumentationType::NatspecUser); meta["output"]["devdoc"] = metadata(_contract, DocumentationType::NatspecDev); diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 223cc15d..4eb52fc2 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -391,7 +391,7 @@ 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); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index badebf38..ab79aaa3 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -266,12 +266,24 @@ 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::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::handleMeta(DocumentationType _type, string const& _contract) { std::string argName; @@ -279,11 +291,6 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co 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->metadata(_contract, _type)); if (m_args.count(g_argOutputDir)) createFile(m_compiler->filesystemFriendlyName(_contract) + suffix, output); @@ -1069,7 +1072,7 @@ void CommandLineInterface::outputCompilationResults() handleBytecode(contract); handleSignatureHashes(contract); handleOnChainMetadata(contract); - handleMeta(DocumentationType::ABIInterface, contract); + handleABI(contract); handleMeta(DocumentationType::NatspecDev, contract); handleMeta(DocumentationType::NatspecUser, contract); } // end of contracts iteration diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index f52a03c7..3428532a 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -67,6 +67,7 @@ private: void handleBytecode(std::string const& _contract); void handleSignatureHashes(std::string const& _contract); void handleOnChainMetadata(std::string const& _contract); + void handleABI(std::string const& _contract); void handleMeta(DocumentationType _type, std::string const& _contract); void handleGasEstimation(std::string const& _contract); void handleFormal(); 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( -- cgit From 12328b784875bad30156a2c66912652f89fa8222 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 10 May 2017 10:54:23 +0100 Subject: Split ABI out of InterfaceHandler --- libsolidity/interface/ABI.cpp | 116 +++++++++++++++++++++++++++++ libsolidity/interface/ABI.h | 56 ++++++++++++++ libsolidity/interface/CompilerStack.cpp | 17 +++-- libsolidity/interface/CompilerStack.h | 6 +- libsolidity/interface/InterfaceHandler.cpp | 115 ++++++---------------------- libsolidity/interface/InterfaceHandler.h | 7 +- 6 files changed, 212 insertions(+), 105 deletions(-) create mode 100644 libsolidity/interface/ABI.cpp create mode 100644 libsolidity/interface/ABI.h 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 . +*/ +/** + * Utilities to handle the Contract ABI (https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) + */ + +#include +#include +#include + +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 const& _names, + vector 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 . +*/ +/** + * Utilities to handle the Contract ABI (https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) + */ + +#pragma once + +#include +#include +#include + +namespace dev +{ +namespace solidity +{ + +// Forward declarations +class ContractDefinition; +class Type; +using TypePointer = std::shared_ptr; + +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 const& _names, + std::vector const& _types, + bool _forLibrary + ); +}; + +} +} diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1f235656..4b57b34c 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -446,12 +447,21 @@ map CompilerStack::sourceIndices() const Json::Value const& CompilerStack::contractABI(string const& _contractName) const { - return metadata(_contractName, DocumentationType::ABIInterface); + return contractABI(contract(_contractName)); } Json::Value const& CompilerStack::contractABI(Contract const& _contract) const { - return metadata(_contract, DocumentationType::ABIInterface); + 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(string const& _contractName, DocumentationType _type) const @@ -476,9 +486,6 @@ 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.")); } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index e98c3b82..dd8d671e 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -66,8 +66,7 @@ class DeclarationContainer; enum class DocumentationType: uint8_t { NatspecUser = 1, - NatspecDev, - ABIInterface + NatspecDev }; /** @@ -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 interface; + mutable std::unique_ptr abi; mutable std::unique_ptr userDocumentation; mutable std::unique_ptr devDocumentation; mutable std::unique_ptr sourceMapping; @@ -267,6 +266,7 @@ private: std::string createOnChainMetadata(Contract const& _contract) const; std::string computeSourceMapping(eth::AssemblyItems const& _items) const; + Json::Value const& contractABI(Contract const&) const; Json::Value const& metadata(Contract const&, DocumentationType _type) const; struct Remapping diff --git a/libsolidity/interface/InterfaceHandler.cpp b/libsolidity/interface/InterfaceHandler.cpp index 6c1bb0c4..b73cf46e 100644 --- a/libsolidity/interface/InterfaceHandler.cpp +++ b/libsolidity/interface/InterfaceHandler.cpp @@ -1,3 +1,27 @@ +/* + 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 . +*/ +/** + * @author Lefteris + * @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 #include @@ -19,83 +43,11 @@ Json::Value InterfaceHandler::documentation( 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; @@ -168,25 +120,6 @@ Json::Value InterfaceHandler::devDocumentation(ContractDefinition const& _contra return doc; } -Json::Value InterfaceHandler::formatTypeList( - vector const& _names, - vector 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 const& _tags, string const& _name) { string value; diff --git a/libsolidity/interface/InterfaceHandler.h b/libsolidity/interface/InterfaceHandler.h index 56927d44..883ef3b9 100644 --- a/libsolidity/interface/InterfaceHandler.h +++ b/libsolidity/interface/InterfaceHandler.h @@ -17,8 +17,7 @@ /** * @author Lefteris * @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 @@ -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 -- cgit From 81877cc59441f43a33ad7e7a09b92d3ea06b5f03 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 10 May 2017 10:56:21 +0100 Subject: Rename InterfaceHandler to Natspec --- libsolidity/interface/CompilerStack.cpp | 8 +- libsolidity/interface/CompilerStack.h | 2 +- libsolidity/interface/InterfaceHandler.cpp | 130 ----------------------------- libsolidity/interface/InterfaceHandler.h | 97 --------------------- libsolidity/interface/Natspec.cpp | 130 +++++++++++++++++++++++++++++ libsolidity/interface/Natspec.h | 97 +++++++++++++++++++++ libsolidity/parsing/Parser.cpp | 1 - 7 files changed, 232 insertions(+), 233 deletions(-) delete mode 100644 libsolidity/interface/InterfaceHandler.cpp delete mode 100644 libsolidity/interface/InterfaceHandler.h create mode 100644 libsolidity/interface/Natspec.cpp create mode 100644 libsolidity/interface/Natspec.h diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 4b57b34c..7125adec 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include @@ -220,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; @@ -492,7 +492,7 @@ Json::Value const& CompilerStack::metadata(Contract const& _contract, Documentat // 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); } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index dd8d671e..cc5ba64c 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -59,7 +59,7 @@ class FunctionDefinition; class SourceUnit; class Compiler; class GlobalContext; -class InterfaceHandler; +class Natspec; class Error; class DeclarationContainer; diff --git a/libsolidity/interface/InterfaceHandler.cpp b/libsolidity/interface/InterfaceHandler.cpp deleted file mode 100644 index b73cf46e..00000000 --- a/libsolidity/interface/InterfaceHandler.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ -/** - * @author Lefteris - * @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 -#include -#include -#include - -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); - } - - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation type")); -} - -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(&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(&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 InterfaceHandler::extractDoc(multimap 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/InterfaceHandler.h deleted file mode 100644 index 883ef3b9..00000000 --- a/libsolidity/interface/InterfaceHandler.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - 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 . -*/ -/** - * @author Lefteris - * @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 - */ - -#pragma once - -#include -#include -#include - -namespace dev -{ -namespace solidity -{ - -// Forward declarations -class ContractDefinition; -class Type; -using TypePointer = std::shared_ptr; -struct DocTag; -enum class DocumentationType: uint8_t; - -enum class DocTagType: uint8_t -{ - None = 0, - Dev, - Notice, - Param, - Return, - Author, - Title -}; - -enum class CommentOwner -{ - Contract, - Function -}; - -class InterfaceHandler -{ -public: - /// Get the given type of documentation - /// @param _contractDef The contract definition - /// @param _type The type of the documentation. Can be one of the - /// types provided by @c DocumentationType - /// @return A JSON representation of provided type - static Json::Value documentation( - ContractDefinition const& _contractDef, - DocumentationType _type - ); - /// Get the User documentation of the contract - /// @param _contractDef The contract definition - /// @return A JSON representation of the contract's user documentation - static Json::Value userDocumentation(ContractDefinition const& _contractDef); - /// Genereates the Developer's documentation of the contract - /// @param _contractDef The contract definition - /// @return A JSON representation - /// of the contract's developer documentation - static Json::Value devDocumentation(ContractDefinition const& _contractDef); - -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 const& _names, - std::vector const& _types, - bool _forLibrary - ); - /// @returns concatenation of all content under the given tag name. - static std::string extractDoc(std::multimap const& _tags, std::string const& _name); -}; - -} //solidity NS -} // dev NS 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 . +*/ +/** + * @author Lefteris + * @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 +#include +#include +#include + +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(&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(&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 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.h b/libsolidity/interface/Natspec.h new file mode 100644 index 00000000..bec9acd2 --- /dev/null +++ b/libsolidity/interface/Natspec.h @@ -0,0 +1,97 @@ +/* + 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 . +*/ +/** + * @author Lefteris + * @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 + */ + +#pragma once + +#include +#include +#include + +namespace dev +{ +namespace solidity +{ + +// Forward declarations +class ContractDefinition; +class Type; +using TypePointer = std::shared_ptr; +struct DocTag; +enum class DocumentationType: uint8_t; + +enum class DocTagType: uint8_t +{ + None = 0, + Dev, + Notice, + Param, + Return, + Author, + Title +}; + +enum class CommentOwner +{ + Contract, + Function +}; + +class Natspec +{ +public: + /// Get the given type of documentation + /// @param _contractDef The contract definition + /// @param _type The type of the documentation. Can be one of the + /// types provided by @c DocumentationType + /// @return A JSON representation of provided type + static Json::Value documentation( + ContractDefinition const& _contractDef, + DocumentationType _type + ); + /// Get the User documentation of the contract + /// @param _contractDef The contract definition + /// @return A JSON representation of the contract's user documentation + static Json::Value userDocumentation(ContractDefinition const& _contractDef); + /// Genereates the Developer's documentation of the contract + /// @param _contractDef The contract definition + /// @return A JSON representation + /// of the contract's developer documentation + static Json::Value devDocumentation(ContractDefinition const& _contractDef); + +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 const& _names, + std::vector const& _types, + bool _forLibrary + ); + /// @returns concatenation of all content under the given tag name. + static std::string extractDoc(std::multimap const& _tags, std::string const& _name); +}; + +} //solidity NS +} // dev NS 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 #include #include -#include using namespace std; -- cgit From cd5d93da2aef3b9617cbf02d0d1341ce071789c2 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 10 May 2017 11:04:52 +0100 Subject: Rename CompilerStack.metadata to CompilerStack.natspec --- libsolidity/interface/CompilerStack.cpp | 10 +++++----- libsolidity/interface/CompilerStack.h | 4 ++-- libsolidity/interface/StandardCompiler.cpp | 4 ++-- solc/CommandLineInterface.cpp | 6 +++--- test/libsolidity/SolidityNatspecJSON.cpp | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 7125adec..72712298 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -464,12 +464,12 @@ Json::Value const& CompilerStack::contractABI(Contract const& _contract) const return *_contract.abi; } -Json::Value const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const +Json::Value const& CompilerStack::natspec(string const& _contractName, DocumentationType _type) const { - return metadata(contract(_contractName), _type); + return natspec(contract(_contractName), _type); } -Json::Value const& CompilerStack::metadata(Contract const& _contract, DocumentationType _type) const +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.")); @@ -843,8 +843,8 @@ string CompilerStack::createOnChainMetadata(Contract const& _contract) const meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes()); meta["output"]["abi"] = contractABI(_contract); - meta["output"]["userdoc"] = metadata(_contract, DocumentationType::NatspecUser); - meta["output"]["devdoc"] = metadata(_contract, DocumentationType::NatspecDev); + 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 cc5ba64c..84d15d70 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -179,7 +179,7 @@ public: /// 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; } @@ -267,7 +267,7 @@ private: std::string createOnChainMetadata(Contract const& _contract) const; std::string computeSourceMapping(eth::AssemblyItems const& _items) const; Json::Value const& contractABI(Contract const&) const; - Json::Value const& metadata(Contract const&, DocumentationType _type) const; + Json::Value const& natspec(Contract const&, DocumentationType _type) const; struct Remapping { diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 4eb52fc2..503be57b 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -393,8 +393,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) Json::Value contractData(Json::objectValue); 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/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index ab79aaa3..cee642e0 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -308,7 +308,7 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co if (m_args.count(argName)) { - std::string 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); @@ -817,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; } 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( -- cgit From bbef2cd4a8c4dd3ad0d1e16d6070a88a5f83fcc6 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 11 May 2017 09:10:41 +0100 Subject: Rename handleMeta to handleNatspec --- solc/CommandLineInterface.cpp | 6 +++--- solc/CommandLineInterface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index cee642e0..d5a60b50 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -284,7 +284,7 @@ void CommandLineInterface::handleABI(string const& _contract) cout << "Contract JSON ABI " << endl << data << endl; } -void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) +void CommandLineInterface::handleNatspec(DocumentationType _type, string const& _contract) { std::string argName; std::string suffix; @@ -1073,8 +1073,8 @@ void CommandLineInterface::outputCompilationResults() handleSignatureHashes(contract); handleOnChainMetadata(contract); handleABI(contract); - handleMeta(DocumentationType::NatspecDev, contract); - handleMeta(DocumentationType::NatspecUser, 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 3428532a..ebf52625 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -68,7 +68,7 @@ private: void handleSignatureHashes(std::string const& _contract); void handleOnChainMetadata(std::string const& _contract); void handleABI(std::string const& _contract); - void handleMeta(DocumentationType _type, std::string const& _contract); + void handleNatspec(DocumentationType _type, std::string const& _contract); void handleGasEstimation(std::string const& _contract); void handleFormal(); -- cgit