mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Refactor error reporting
This commit introduces ErrorReporter, a utility class which consolidates all of the error logging functionality into a common set of functions. It also replaces all direct interactions with an ErrorList with calls to an ErrorReporter. This commit resolves issue #2209
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/analysis/TypeChecker.h>
|
||||
#include <libsolidity/interface/Exceptions.h>
|
||||
#include <libsolidity/interface/ErrorReporter.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -36,10 +36,10 @@ namespace solidity
|
||||
NameAndTypeResolver::NameAndTypeResolver(
|
||||
vector<Declaration const*> const& _globals,
|
||||
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
|
||||
ErrorList& _errors
|
||||
ErrorReporter& _errorReporter
|
||||
) :
|
||||
m_scopes(_scopes),
|
||||
m_errors(_errors)
|
||||
m_errorReporter(_errorReporter)
|
||||
{
|
||||
if (!m_scopes[nullptr])
|
||||
m_scopes[nullptr].reset(new DeclarationContainer());
|
||||
@@ -52,11 +52,11 @@ bool NameAndTypeResolver::registerDeclarations(ASTNode& _sourceUnit, ASTNode con
|
||||
// The helper registers all declarations in m_scopes as a side-effect of its construction.
|
||||
try
|
||||
{
|
||||
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors, _currentScope);
|
||||
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, _currentScope);
|
||||
}
|
||||
catch (FatalError const&)
|
||||
{
|
||||
if (m_errors.empty())
|
||||
if (m_errorReporter.errors().empty())
|
||||
throw; // Something is weird here, rather throw again.
|
||||
return false;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
|
||||
string const& path = imp->annotation().absolutePath;
|
||||
if (!_sourceUnits.count(path))
|
||||
{
|
||||
reportDeclarationError(
|
||||
m_errorReporter.declarationError(
|
||||
imp->location(),
|
||||
"Import \"" + path + "\" (referenced as \"" + imp->path() + "\") not found."
|
||||
);
|
||||
@@ -88,7 +88,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
|
||||
auto declarations = scope->second->resolveName(alias.first->name(), false);
|
||||
if (declarations.empty())
|
||||
{
|
||||
reportDeclarationError(
|
||||
m_errorReporter.declarationError(
|
||||
imp->location(),
|
||||
"Declaration \"" +
|
||||
alias.first->name() +
|
||||
@@ -106,7 +106,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
|
||||
ASTString const* name = alias.second ? alias.second.get() : &declaration->name();
|
||||
if (!target.registerDeclaration(*declaration, name))
|
||||
{
|
||||
reportDeclarationError(
|
||||
m_errorReporter.declarationError(
|
||||
imp->location(),
|
||||
"Identifier \"" + *name + "\" already declared."
|
||||
);
|
||||
@@ -119,7 +119,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
|
||||
for (auto const& declaration: nameAndDeclaration.second)
|
||||
if (!target.registerDeclaration(*declaration, &nameAndDeclaration.first))
|
||||
{
|
||||
reportDeclarationError(
|
||||
m_errorReporter.declarationError(
|
||||
imp->location(),
|
||||
"Identifier \"" + nameAndDeclaration.first + "\" already declared."
|
||||
);
|
||||
@@ -137,7 +137,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ASTNode& _node, bool _resolveInsi
|
||||
}
|
||||
catch (FatalError const&)
|
||||
{
|
||||
if (m_errors.empty())
|
||||
if (m_errorReporter.errors().empty())
|
||||
throw; // Something is weird here, rather throw again.
|
||||
return false;
|
||||
}
|
||||
@@ -152,7 +152,7 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
|
||||
}
|
||||
catch (FatalError const&)
|
||||
{
|
||||
if (m_errors.empty())
|
||||
if (m_errorReporter.errors().empty())
|
||||
throw; // Something is weird here, rather throw again.
|
||||
return false;
|
||||
}
|
||||
@@ -214,7 +214,7 @@ vector<Declaration const*> NameAndTypeResolver::cleanedDeclarations(
|
||||
|
||||
for (auto parameter: functionType->parameterTypes() + functionType->returnParameterTypes())
|
||||
if (!parameter)
|
||||
reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context.");
|
||||
m_errorReporter.fatalDeclarationError(_identifier.location(), "Function type can not be used in this context.");
|
||||
|
||||
if (uniqueFunctions.end() == find_if(
|
||||
uniqueFunctions.begin(),
|
||||
@@ -290,7 +290,7 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res
|
||||
{
|
||||
if (m_scopes.count(&_node))
|
||||
m_currentScope = m_scopes[&_node].get();
|
||||
return ReferencesResolver(m_errors, *this, _resolveInsideCode).resolve(_node);
|
||||
return ReferencesResolver(m_errorReporter, *this, _resolveInsideCode).resolve(_node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,11 +328,10 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base)
|
||||
secondDeclarationLocation = declaration->location();
|
||||
}
|
||||
|
||||
reportDeclarationError(
|
||||
m_errorReporter.declarationError(
|
||||
secondDeclarationLocation,
|
||||
"Identifier already declared.",
|
||||
firstDeclarationLocation,
|
||||
"The previous declaration is here:"
|
||||
SecondarySourceLocation().append("The previous declaration is here:", firstDeclarationLocation),
|
||||
"Identifier already declared."
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -347,19 +346,19 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
|
||||
UserDefinedTypeName const& baseName = baseSpecifier->name();
|
||||
auto base = dynamic_cast<ContractDefinition const*>(baseName.annotation().referencedDeclaration);
|
||||
if (!base)
|
||||
reportFatalTypeError(baseName.createTypeError("Contract expected."));
|
||||
m_errorReporter.fatalTypeError(baseName.location(), "Contract expected.");
|
||||
// "push_front" has the effect that bases mentioned later can overwrite members of bases
|
||||
// mentioned earlier
|
||||
input.back().push_front(base);
|
||||
vector<ContractDefinition const*> const& basesBases = base->annotation().linearizedBaseContracts;
|
||||
if (basesBases.empty())
|
||||
reportFatalTypeError(baseName.createTypeError("Definition of base has to precede definition of derived contract"));
|
||||
m_errorReporter.fatalTypeError(baseName.location(), "Definition of base has to precede definition of derived contract");
|
||||
input.push_front(list<ContractDefinition const*>(basesBases.begin(), basesBases.end()));
|
||||
}
|
||||
input.back().push_front(&_contract);
|
||||
vector<ContractDefinition const*> result = cThreeMerge(input);
|
||||
if (result.empty())
|
||||
reportFatalTypeError(_contract.createTypeError("Linearization of inheritance graph impossible"));
|
||||
m_errorReporter.fatalTypeError(_contract.location(), "Linearization of inheritance graph impossible");
|
||||
_contract.annotation().linearizedBaseContracts = result;
|
||||
_contract.annotation().contractDependencies.insert(result.begin() + 1, result.end());
|
||||
}
|
||||
@@ -415,61 +414,15 @@ vector<_T const*> NameAndTypeResolver::cThreeMerge(list<list<_T const*>>& _toMer
|
||||
return result;
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::reportDeclarationError(
|
||||
SourceLocation _sourceLoction,
|
||||
string const& _description,
|
||||
SourceLocation _secondarySourceLocation,
|
||||
string const& _secondaryDescription
|
||||
)
|
||||
{
|
||||
auto err = make_shared<Error>(Error::Type::DeclarationError); // todo remove Error?
|
||||
*err <<
|
||||
errinfo_sourceLocation(_sourceLoction) <<
|
||||
errinfo_comment(_description) <<
|
||||
errinfo_secondarySourceLocation(
|
||||
SecondarySourceLocation().append(_secondaryDescription, _secondarySourceLocation)
|
||||
);
|
||||
|
||||
m_errors.push_back(err);
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::reportDeclarationError(SourceLocation _sourceLocation, string const& _description)
|
||||
{
|
||||
auto err = make_shared<Error>(Error::Type::DeclarationError); // todo remove Error?
|
||||
*err << errinfo_sourceLocation(_sourceLocation) << errinfo_comment(_description);
|
||||
|
||||
m_errors.push_back(err);
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::reportFatalDeclarationError(
|
||||
SourceLocation _sourceLocation,
|
||||
string const& _description
|
||||
)
|
||||
{
|
||||
reportDeclarationError(_sourceLocation, _description);
|
||||
BOOST_THROW_EXCEPTION(FatalError());
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::reportTypeError(Error const& _e)
|
||||
{
|
||||
m_errors.push_back(make_shared<Error>(_e));
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::reportFatalTypeError(Error const& _e)
|
||||
{
|
||||
reportTypeError(_e);
|
||||
BOOST_THROW_EXCEPTION(FatalError());
|
||||
}
|
||||
|
||||
DeclarationRegistrationHelper::DeclarationRegistrationHelper(
|
||||
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
|
||||
ASTNode& _astRoot,
|
||||
ErrorList& _errors,
|
||||
ErrorReporter& _errorReporter,
|
||||
ASTNode const* _currentScope
|
||||
):
|
||||
m_scopes(_scopes),
|
||||
m_currentScope(_currentScope),
|
||||
m_errors(_errors)
|
||||
m_errorReporter(_errorReporter)
|
||||
{
|
||||
_astRoot.accept(*this);
|
||||
solAssert(m_currentScope == _currentScope, "Scopes not correctly closed.");
|
||||
@@ -633,11 +586,10 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
|
||||
secondDeclarationLocation = _declaration.location();
|
||||
}
|
||||
|
||||
declarationError(
|
||||
m_errorReporter.declarationError(
|
||||
secondDeclarationLocation,
|
||||
"Identifier already declared.",
|
||||
firstDeclarationLocation,
|
||||
"The previous declaration is here:"
|
||||
SecondarySourceLocation().append("The previous declaration is here:", firstDeclarationLocation),
|
||||
"Identifier already declared."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -665,40 +617,5 @@ string DeclarationRegistrationHelper::currentCanonicalName() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DeclarationRegistrationHelper::declarationError(
|
||||
SourceLocation _sourceLocation,
|
||||
string const& _description,
|
||||
SourceLocation _secondarySourceLocation,
|
||||
string const& _secondaryDescription
|
||||
)
|
||||
{
|
||||
auto err = make_shared<Error>(Error::Type::DeclarationError);
|
||||
*err <<
|
||||
errinfo_sourceLocation(_sourceLocation) <<
|
||||
errinfo_comment(_description) <<
|
||||
errinfo_secondarySourceLocation(
|
||||
SecondarySourceLocation().append(_secondaryDescription, _secondarySourceLocation)
|
||||
);
|
||||
|
||||
m_errors.push_back(err);
|
||||
}
|
||||
|
||||
void DeclarationRegistrationHelper::declarationError(SourceLocation _sourceLocation, string const& _description)
|
||||
{
|
||||
auto err = make_shared<Error>(Error::Type::DeclarationError);
|
||||
*err << errinfo_sourceLocation(_sourceLocation) << errinfo_comment(_description);
|
||||
|
||||
m_errors.push_back(err);
|
||||
}
|
||||
|
||||
void DeclarationRegistrationHelper::fatalDeclarationError(
|
||||
SourceLocation _sourceLocation,
|
||||
string const& _description
|
||||
)
|
||||
{
|
||||
declarationError(_sourceLocation, _description);
|
||||
BOOST_THROW_EXCEPTION(FatalError());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user