mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Error formatting.
This commit is contained in:
parent
39d1e2bc06
commit
42c0009205
@ -77,6 +77,7 @@ void CompilerStack::reset(bool _keepSources, bool _addStandardSources)
|
|||||||
m_globalContext.reset();
|
m_globalContext.reset();
|
||||||
m_sourceOrder.clear();
|
m_sourceOrder.clear();
|
||||||
m_contracts.clear();
|
m_contracts.clear();
|
||||||
|
m_errors.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompilerStack::addSource(string const& _name, string const& _content, bool _isLibrary)
|
bool CompilerStack::addSource(string const& _name, string const& _content, bool _isLibrary)
|
||||||
@ -94,8 +95,10 @@ void CompilerStack::setSource(string const& _sourceCode)
|
|||||||
addSource("", _sourceCode);
|
addSource("", _sourceCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerStack::parse()
|
bool CompilerStack::parse()
|
||||||
{
|
{
|
||||||
|
m_errors.clear();
|
||||||
|
|
||||||
for (auto& sourcePair: m_sources)
|
for (auto& sourcePair: m_sources)
|
||||||
{
|
{
|
||||||
sourcePair.second.scanner->reset();
|
sourcePair.second.scanner->reset();
|
||||||
@ -117,6 +120,7 @@ void CompilerStack::parse()
|
|||||||
resolver.resolveNamesAndTypes(*contract);
|
resolver.resolveNamesAndTypes(*contract);
|
||||||
m_contracts[contract->name()].contract = contract;
|
m_contracts[contract->name()].contract = contract;
|
||||||
}
|
}
|
||||||
|
|
||||||
InterfaceHandler interfaceHandler;
|
InterfaceHandler interfaceHandler;
|
||||||
for (Source const* source: m_sourceOrder)
|
for (Source const* source: m_sourceOrder)
|
||||||
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
|
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
|
||||||
@ -127,20 +131,19 @@ void CompilerStack::parse()
|
|||||||
TypeChecker typeChecker;
|
TypeChecker typeChecker;
|
||||||
bool typesFine = typeChecker.checkTypeRequirements(*contract);
|
bool typesFine = typeChecker.checkTypeRequirements(*contract);
|
||||||
if (!typesFine)
|
if (!typesFine)
|
||||||
BOOST_THROW_EXCEPTION(*typeChecker.errors().front());
|
m_errors += typeChecker.errors();
|
||||||
//@todo extract warnings and errors
|
|
||||||
// store whether we had an error
|
|
||||||
contract->setDevDocumentation(interfaceHandler.devDocumentation(*contract));
|
contract->setDevDocumentation(interfaceHandler.devDocumentation(*contract));
|
||||||
contract->setUserDocumentation(interfaceHandler.userDocumentation(*contract));
|
contract->setUserDocumentation(interfaceHandler.userDocumentation(*contract));
|
||||||
m_contracts[contract->name()].contract = contract;
|
m_contracts[contract->name()].contract = contract;
|
||||||
}
|
}
|
||||||
m_parseSuccessful = true;
|
m_parseSuccessful = m_errors.empty();
|
||||||
|
return m_parseSuccessful;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerStack::parse(string const& _sourceCode)
|
bool CompilerStack::parse(string const& _sourceCode)
|
||||||
{
|
{
|
||||||
setSource(_sourceCode);
|
setSource(_sourceCode);
|
||||||
parse();
|
return parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> CompilerStack::contractNames() const
|
vector<string> CompilerStack::contractNames() const
|
||||||
@ -154,12 +157,11 @@ vector<string> CompilerStack::contractNames() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CompilerStack::compile(bool _optimize, unsigned _runs)
|
bool CompilerStack::compile(bool _optimize, unsigned _runs)
|
||||||
{
|
{
|
||||||
if (!m_parseSuccessful)
|
if (!m_parseSuccessful)
|
||||||
parse();
|
if (!parse())
|
||||||
|
return false;
|
||||||
//@todo do not compile or error (also in other places)
|
|
||||||
|
|
||||||
map<ContractDefinition const*, eth::Assembly const*> compiledContracts;
|
map<ContractDefinition const*, eth::Assembly const*> compiledContracts;
|
||||||
for (Source const* source: m_sourceOrder)
|
for (Source const* source: m_sourceOrder)
|
||||||
@ -180,13 +182,12 @@ void CompilerStack::compile(bool _optimize, unsigned _runs)
|
|||||||
cloneCompiler.compileClone(*contract, compiledContracts);
|
cloneCompiler.compileClone(*contract, compiledContracts);
|
||||||
compiledContract.cloneObject = cloneCompiler.assembledObject();
|
compiledContract.cloneObject = cloneCompiler.assembledObject();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
eth::LinkerObject const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
|
bool CompilerStack::compile(string const& _sourceCode, bool _optimize)
|
||||||
{
|
{
|
||||||
parse(_sourceCode);
|
return parse(_sourceCode) && compile(_optimize);
|
||||||
compile(_optimize);
|
|
||||||
return object();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerStack::link(const std::map<string, h160>& _libraries)
|
void CompilerStack::link(const std::map<string, h160>& _libraries)
|
||||||
@ -325,12 +326,6 @@ size_t CompilerStack::functionEntryPoint(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
eth::LinkerObject CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize)
|
|
||||||
{
|
|
||||||
CompilerStack stack;
|
|
||||||
return stack.compile(_sourceCode, _optimize);
|
|
||||||
}
|
|
||||||
|
|
||||||
tuple<int, int, int, int> CompilerStack::positionFromSourceLocation(SourceLocation const& _sourceLocation) const
|
tuple<int, int, int, int> CompilerStack::positionFromSourceLocation(SourceLocation const& _sourceLocation) const
|
||||||
{
|
{
|
||||||
int startLine;
|
int startLine;
|
||||||
|
@ -54,6 +54,7 @@ class SourceUnit;
|
|||||||
class Compiler;
|
class Compiler;
|
||||||
class GlobalContext;
|
class GlobalContext;
|
||||||
class InterfaceHandler;
|
class InterfaceHandler;
|
||||||
|
struct Error;
|
||||||
|
|
||||||
enum class DocumentationType: uint8_t
|
enum class DocumentationType: uint8_t
|
||||||
{
|
{
|
||||||
@ -85,18 +86,21 @@ public:
|
|||||||
bool addSource(std::string const& _name, std::string const& _content, bool _isLibrary = false);
|
bool addSource(std::string const& _name, std::string const& _content, bool _isLibrary = false);
|
||||||
void setSource(std::string const& _sourceCode);
|
void setSource(std::string const& _sourceCode);
|
||||||
/// Parses all source units that were added
|
/// Parses all source units that were added
|
||||||
void parse();
|
/// @returns false on error.
|
||||||
|
bool parse();
|
||||||
/// Sets the given source code as the only source unit apart from standard sources and parses it.
|
/// Sets the given source code as the only source unit apart from standard sources and parses it.
|
||||||
void parse(std::string const& _sourceCode);
|
/// @returns false on error.
|
||||||
|
bool parse(std::string const& _sourceCode);
|
||||||
/// Returns a list of the contract names in the sources.
|
/// Returns a list of the contract names in the sources.
|
||||||
std::vector<std::string> contractNames() const;
|
std::vector<std::string> contractNames() const;
|
||||||
std::string defaultContractName() const;
|
std::string defaultContractName() const;
|
||||||
|
|
||||||
/// Compiles the source units that were previously added and parsed.
|
/// Compiles the source units that were previously added and parsed.
|
||||||
void compile(bool _optimize = false, unsigned _runs = 200);
|
/// @returns false on error.
|
||||||
|
bool compile(bool _optimize = false, unsigned _runs = 200);
|
||||||
/// Parses and compiles the given source code.
|
/// Parses and compiles the given source code.
|
||||||
/// @returns the compiled linker object
|
/// @returns false on error.
|
||||||
eth::LinkerObject const& compile(std::string const& _sourceCode, bool _optimize = false);
|
bool compile(std::string const& _sourceCode, bool _optimize = false);
|
||||||
|
|
||||||
/// Inserts the given addresses into the linker objects of all compiled contracts.
|
/// Inserts the given addresses into the linker objects of all compiled contracts.
|
||||||
void link(std::map<std::string, h160> const& _libraries);
|
void link(std::map<std::string, h160> const& _libraries);
|
||||||
@ -152,15 +156,14 @@ public:
|
|||||||
FunctionDefinition const& _function
|
FunctionDefinition const& _function
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
/// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for
|
|
||||||
/// scanning the source code - this is useful for printing exception information.
|
|
||||||
static eth::LinkerObject staticCompile(std::string const& _sourceCode, bool _optimize = false);
|
|
||||||
|
|
||||||
/// Helper function for logs printing. Do only use in error cases, it's quite expensive.
|
/// Helper function for logs printing. Do only use in error cases, it's quite expensive.
|
||||||
/// line and columns are numbered starting from 1 with following order:
|
/// line and columns are numbered starting from 1 with following order:
|
||||||
/// start line, start column, end line, end column
|
/// start line, start column, end line, end column
|
||||||
std::tuple<int, int, int, int> positionFromSourceLocation(SourceLocation const& _sourceLocation) const;
|
std::tuple<int, int, int, int> positionFromSourceLocation(SourceLocation const& _sourceLocation) const;
|
||||||
|
|
||||||
|
/// @returns the list of errors that occured during parsing and type checking.
|
||||||
|
std::vector<std::shared_ptr<Error const>> const& errors() const { return m_errors; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Information pertaining to one source unit, filled gradually during parsing and compilation.
|
* Information pertaining to one source unit, filled gradually during parsing and compilation.
|
||||||
@ -200,6 +203,7 @@ private:
|
|||||||
std::shared_ptr<GlobalContext> m_globalContext;
|
std::shared_ptr<GlobalContext> m_globalContext;
|
||||||
std::vector<Source const*> m_sourceOrder;
|
std::vector<Source const*> m_sourceOrder;
|
||||||
std::map<std::string const, Contract> m_contracts;
|
std::map<std::string const, Contract> m_contracts;
|
||||||
|
std::vector<std::shared_ptr<Error const>> m_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,15 @@ namespace dev
|
|||||||
namespace solidity
|
namespace solidity
|
||||||
{
|
{
|
||||||
|
|
||||||
struct ParserError: virtual Exception {};
|
struct Error: virtual Exception {};
|
||||||
struct TypeError: virtual Exception {};
|
|
||||||
struct DeclarationError: virtual Exception {};
|
struct ParserError: virtual Error {};
|
||||||
|
struct TypeError: virtual Error {};
|
||||||
|
struct DeclarationError: virtual Error {};
|
||||||
|
struct DocstringParsingError: virtual Error {};
|
||||||
|
|
||||||
struct CompilerError: virtual Exception {};
|
struct CompilerError: virtual Exception {};
|
||||||
struct InternalCompilerError: virtual Exception {};
|
struct InternalCompilerError: virtual Exception {};
|
||||||
struct DocstringParsingError: virtual Exception {};
|
|
||||||
struct FatalError: virtual Exception {};
|
struct FatalError: virtual Exception {};
|
||||||
|
|
||||||
using errorSourceLocationInfo = std::pair<std::string, SourceLocation>;
|
using errorSourceLocationInfo = std::pair<std::string, SourceLocation>;
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
bool checkTypeRequirements(ContractDefinition const& _contract);
|
bool checkTypeRequirements(ContractDefinition const& _contract);
|
||||||
|
|
||||||
/// @returns the list of errors found during type checking.
|
/// @returns the list of errors found during type checking.
|
||||||
std::vector<std::shared_ptr<Exception const>> const& errors() const { return m_errors; }
|
std::vector<std::shared_ptr<Error const>> const& errors() const { return m_errors; }
|
||||||
|
|
||||||
/// @returns the type of an expression and asserts that it is present.
|
/// @returns the type of an expression and asserts that it is present.
|
||||||
TypePointer const& type(Expression const& _expression) const;
|
TypePointer const& type(Expression const& _expression) const;
|
||||||
@ -107,7 +107,7 @@ private:
|
|||||||
/// Runs type checks on @a _expression to infer its type and then checks that it is an LValue.
|
/// Runs type checks on @a _expression to infer its type and then checks that it is an LValue.
|
||||||
void requireLValue(Expression const& _expression);
|
void requireLValue(Expression const& _expression);
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Exception const>> m_errors;
|
std::vector<std::shared_ptr<Error const>> m_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -490,7 +490,12 @@ bool CommandLineInterface::processInput()
|
|||||||
// TODO: Perhaps we should not compile unless requested
|
// TODO: Perhaps we should not compile unless requested
|
||||||
bool optimize = m_args.count("optimize") > 0;
|
bool optimize = m_args.count("optimize") > 0;
|
||||||
unsigned runs = m_args["optimize-runs"].as<unsigned>();
|
unsigned runs = m_args["optimize-runs"].as<unsigned>();
|
||||||
m_compiler->compile(optimize, runs);
|
if (!m_compiler->compile(optimize, runs))
|
||||||
|
{
|
||||||
|
for (auto const& error: m_compiler->errors())
|
||||||
|
SourceReferenceFormatter::printExceptionInformation(cerr, *error, "Error", *m_compiler);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
m_compiler->link(m_libraries);
|
m_compiler->link(m_libraries);
|
||||||
}
|
}
|
||||||
catch (ParserError const& _exception)
|
catch (ParserError const& _exception)
|
||||||
|
@ -46,10 +46,7 @@ string formatError(Exception const& _exception, string const& _name, CompilerSta
|
|||||||
{
|
{
|
||||||
ostringstream errorOutput;
|
ostringstream errorOutput;
|
||||||
SourceReferenceFormatter::printExceptionInformation(errorOutput, _exception, _name, _compiler);
|
SourceReferenceFormatter::printExceptionInformation(errorOutput, _exception, _name, _compiler);
|
||||||
|
return errorOutput.str();
|
||||||
Json::Value output(Json::objectValue);
|
|
||||||
output["error"] = errorOutput.str();
|
|
||||||
return Json::FastWriter().write(output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value functionHashes(ContractDefinition const& _contract)
|
Json::Value functionHashes(ContractDefinition const& _contract)
|
||||||
@ -123,43 +120,52 @@ string compile(string _input, bool _optimize)
|
|||||||
sources[""] = _input;
|
sources[""] = _input;
|
||||||
|
|
||||||
Json::Value output(Json::objectValue);
|
Json::Value output(Json::objectValue);
|
||||||
|
Json::Value errors(Json::arrayValue);
|
||||||
CompilerStack compiler;
|
CompilerStack compiler;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
compiler.compile(_input, _optimize);
|
if (!compiler.compile(_input, _optimize))
|
||||||
|
{
|
||||||
|
for (auto const& error: compiler.errors())
|
||||||
|
errors.append(formatError(*error, "Error", compiler));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ParserError const& exception)
|
catch (ParserError const& exception)
|
||||||
{
|
{
|
||||||
return formatError(exception, "Parser error", compiler);
|
errors.append(formatError(exception, "Parser error", compiler));
|
||||||
}
|
}
|
||||||
catch (DeclarationError const& exception)
|
catch (DeclarationError const& exception)
|
||||||
{
|
{
|
||||||
return formatError(exception, "Declaration error", compiler);
|
errors.append(formatError(exception, "Declaration error", compiler));
|
||||||
}
|
}
|
||||||
catch (TypeError const& exception)
|
catch (TypeError const& exception)
|
||||||
{
|
{
|
||||||
return formatError(exception, "Type error", compiler);
|
errors.append(formatError(exception, "Type error", compiler));
|
||||||
}
|
}
|
||||||
catch (CompilerError const& exception)
|
catch (CompilerError const& exception)
|
||||||
{
|
{
|
||||||
return formatError(exception, "Compiler error", compiler);
|
errors.append(formatError(exception, "Compiler error", compiler));
|
||||||
}
|
}
|
||||||
catch (InternalCompilerError const& exception)
|
catch (InternalCompilerError const& exception)
|
||||||
{
|
{
|
||||||
return formatError(exception, "Internal compiler error", compiler);
|
errors.append(formatError(exception, "Internal compiler error", compiler));
|
||||||
}
|
}
|
||||||
catch (DocstringParsingError const& exception)
|
catch (DocstringParsingError const& exception)
|
||||||
{
|
{
|
||||||
return formatError(exception, "Documentation parsing error", compiler);
|
errors.append(formatError(exception, "Documentation parsing error", compiler));
|
||||||
}
|
}
|
||||||
catch (Exception const& exception)
|
catch (Exception const& exception)
|
||||||
{
|
{
|
||||||
output["error"] = "Exception during compilation: " + boost::diagnostic_information(exception);
|
errors.append("Exception during compilation: " + boost::diagnostic_information(exception));
|
||||||
return Json::FastWriter().write(output);
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
output["error"] = "Unknown exception during compilation.";
|
errors.append("Unknown exception during compilation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.size() > 0)
|
||||||
|
{
|
||||||
|
output["errors"] = errors;
|
||||||
return Json::FastWriter().write(output);
|
return Json::FastWriter().write(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user