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:
Rhett Aultman
2017-05-30 07:28:31 -07:00
parent 0066a08aa8
commit 89b60ffbd4
47 changed files with 770 additions and 707 deletions
+24 -107
View File
@@ -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());
}
}
}