Moving all Interface and Documentation functionality to own class

- Creating the Interface Handler class which will take care of the
  parsing of Natspec comments and of interfacing with and outputing to
  JSON files.

- Will also handle the ABI interface creation
This commit is contained in:
Lefteris Karapetsas 2014-12-03 16:40:37 +01:00
parent be81981ec4
commit d25581de7c
4 changed files with 199 additions and 79 deletions

View File

@ -27,8 +27,7 @@
#include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Compiler.h>
#include <libsolidity/CompilerStack.h>
#include <jsonrpc/json/json.h>
#include <libsolidity/InterfaceHandler.h>
using namespace std;
@ -37,6 +36,8 @@ namespace dev
namespace solidity
{
CompilerStack::CompilerStack():m_interfaceHandler(make_shared<InterfaceHandler>()){}
void CompilerStack::setSource(string const& _sourceCode)
{
reset();
@ -83,84 +84,33 @@ void CompilerStack::streamAssembly(ostream& _outStream)
m_compiler->streamAssembly(_outStream);
}
string const& CompilerStack::getInterface()
std::string const* CompilerStack::getJsonDocumentation(enum documentation_type _type)
{
Json::StyledWriter writer;
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
if (m_interface.empty())
auto createOrReturnDoc = [&, this](std::unique_ptr<string>& _doc)
{
Json::Value methods(Json::arrayValue);
vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions();
for (FunctionDefinition const* f: exportedFunctions)
if(!_doc)
{
Json::Value method;
Json::Value inputs(Json::arrayValue);
Json::Value outputs(Json::arrayValue);
auto streamVariables = [](vector<ASTPointer<VariableDeclaration>> const& _vars)
{
Json::Value params(Json::arrayValue);
for (ASTPointer<VariableDeclaration> const& var: _vars)
{
Json::Value input;
input["name"] = var->getName();
input["type"] = var->getType()->toString();
params.append(input);
}
return params;
};
method["name"] = f->getName();
method["inputs"] = streamVariables(f->getParameters());
method["outputs"] = streamVariables(f->getReturnParameters());
methods.append(method);
_doc = m_interfaceHandler->getDocumentation(m_contractASTNode, _type);
}
m_interface = writer.write(methods);
}
return m_interface;
}
};
string const& CompilerStack::getUserDocumentation()
{
Json::StyledWriter writer;
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
if (m_userDocumentation.empty())
switch (_type)
{
Json::Value doc;
Json::Value methods(Json::objectValue);
for (FunctionDefinition const* f: m_contractASTNode->getInterfaceFunctions())
{
Json::Value user;
auto strPtr = f->getDocumentation();
if (strPtr)
{
user["notice"] = Json::Value(*strPtr);
methods[f->getName()] = user;
}
}
doc["methods"] = methods;
m_userDocumentation = writer.write(doc);
case NATSPEC_USER:
createOrReturnDoc(m_userDocumentation);
return m_userDocumentation.get();
case NATSPEC_DEV:
createOrReturnDoc(m_devDocumentation);
return m_devDocumentation.get();
case ABI_INTERFACE:
createOrReturnDoc(m_interface);
return m_interface.get();
}
return m_userDocumentation;
}
string const& CompilerStack::getDevDocumentation()
{
Json::StyledWriter writer;
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
if (m_devDocumentation.empty())
{
// TODO
}
return m_devDocumentation;
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Internal error"));
return nullptr;
}
bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize)

View File

@ -35,6 +35,14 @@ class Scanner;
class ContractDefinition;
class Compiler;
class GlobalContext;
class InterfaceHandler;
enum documentation_type : unsigned short
{
NATSPEC_USER = 1,
NATSPEC_DEV,
ABI_INTERFACE
};
/**
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
@ -44,7 +52,7 @@ class GlobalContext;
class CompilerStack
{
public:
CompilerStack() {}
CompilerStack();
void reset() { *this = CompilerStack(); }
void setSource(std::string const& _sourceCode);
void parse();
@ -62,12 +70,11 @@ public:
/// Returns a string representing the contract interface in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& getInterface();
/// Returns a string representing the contract's user documentation in JSON.
/// Returns a string representing the contract's documentation in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& getUserDocumentation();
/// Returns a string representing the contract's developer documentation in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& getDevDocumentation();
/// @param type The type of the documentation to get.
/// Can be one of 3 types defined at @c documentation_type
std::string const* getJsonDocumentation(enum documentation_type type);
/// Returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& getScanner() const { return *m_scanner; }
@ -82,10 +89,11 @@ private:
std::shared_ptr<GlobalContext> m_globalContext;
std::shared_ptr<ContractDefinition> m_contractASTNode;
bool m_parseSuccessful;
std::string m_interface;
std::string m_userDocumentation;
std::string m_devDocumentation;
std::unique_ptr<std::string> m_interface;
std::unique_ptr<std::string> m_userDocumentation;
std::unique_ptr<std::string> m_devDocumentation;
std::shared_ptr<Compiler> m_compiler;
std::shared_ptr<InterfaceHandler> m_interfaceHandler;
bytes m_bytecode;
};

88
InterfaceHandler.cpp Normal file
View File

@ -0,0 +1,88 @@
#include <libsolidity/InterfaceHandler.h>
#include <libsolidity/AST.h>
#include <libsolidity/CompilerStack.h>
namespace dev {
namespace solidity {
InterfaceHandler::InterfaceHandler()
{
}
std::unique_ptr<std::string> InterfaceHandler::getDocumentation(std::shared_ptr<ContractDefinition> _contractDef,
enum documentation_type _type)
{
switch(_type)
{
case NATSPEC_USER:
return getUserDocumentation(_contractDef);
case NATSPEC_DEV:
return getDevDocumentation(_contractDef);
case ABI_INTERFACE:
return getABIInterface(_contractDef);
}
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Internal error"));
return nullptr;
}
std::unique_ptr<std::string> InterfaceHandler::getABIInterface(std::shared_ptr<ContractDefinition> _contractDef)
{
Json::Value methods(Json::arrayValue);
std::vector<FunctionDefinition const*> exportedFunctions = _contractDef->getInterfaceFunctions();
for (FunctionDefinition const* f: exportedFunctions)
{
Json::Value method;
Json::Value inputs(Json::arrayValue);
Json::Value outputs(Json::arrayValue);
auto streamVariables = [](std::vector<ASTPointer<VariableDeclaration>> const& _vars)
{
Json::Value params(Json::arrayValue);
for (ASTPointer<VariableDeclaration> const& var: _vars)
{
Json::Value input;
input["name"] = var->getName();
input["type"] = var->getType()->toString();
params.append(input);
}
return params;
};
method["name"] = f->getName();
method["inputs"] = streamVariables(f->getParameters());
method["outputs"] = streamVariables(f->getReturnParameters());
methods.append(method);
}
return std::unique_ptr<std::string>(new std::string(m_writer.write(methods)));
}
std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(std::shared_ptr<ContractDefinition> _contractDef)
{
Json::Value doc;
Json::Value methods(Json::objectValue);
for (FunctionDefinition const* f: _contractDef->getInterfaceFunctions())
{
Json::Value user;
auto strPtr = f->getDocumentation();
if (strPtr)
{
user["notice"] = Json::Value(*strPtr);
methods[f->getName()] = user;
}
}
doc["methods"] = methods;
return std::unique_ptr<std::string>(new std::string(m_writer.write(doc)));
}
std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(std::shared_ptr<ContractDefinition> _contractDef)
{
//TODO
return nullptr;
}
} //solidity NS
} // dev NS

74
InterfaceHandler.h Normal file
View File

@ -0,0 +1,74 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum 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.
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris <lefteris@ethdev.com>
* @date 2014
* Takes the parsed AST and produces the Natspec
* documentation and the ABI interface
* https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format
*
* Can generally deal with JSON files
*/
#pragma once
#include <string>
#include <memory>
#include <jsonrpc/json/json.h>
namespace dev {
namespace solidity {
// Forward declarations
class ContractDefinition;
enum documentation_type: unsigned short;
class InterfaceHandler
{
public:
InterfaceHandler();
/// 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 documentation_type
/// @return A unique pointer contained string with the json
/// representation of provided type
std::unique_ptr<std::string> getDocumentation(std::shared_ptr<ContractDefinition> _contractDef,
enum documentation_type _type);
/// Get the ABI Interface of the contract
/// @param _contractDef The contract definition
/// @return A unique pointer contained string with the json
/// representation of the contract's ABI Interface
std::unique_ptr<std::string> getABIInterface(std::shared_ptr<ContractDefinition> _contractDef);
/// Get the User documentation of the contract
/// @param _contractDef The contract definition
/// @return A unique pointer contained string with the json
/// representation of the contract's user documentation
std::unique_ptr<std::string> getUserDocumentation(std::shared_ptr<ContractDefinition> _contractDef);
/// Get the Developer's documentation of the contract
/// @param _contractDef The contract definition
/// @return A unique pointer contained string with the json
/// representation of the contract's developer documentation
std::unique_ptr<std::string> getDevDocumentation(std::shared_ptr<ContractDefinition> _contractDef);
private:
Json::StyledWriter m_writer;
};
} //solidity NS
} // dev NS