created secondarySoureLocation error type

added additional information to error msgs
This commit is contained in:
Liana Husikyan 2015-04-30 18:06:04 +02:00
parent ef26d96111
commit 8b5fa857d7
7 changed files with 100 additions and 28 deletions

18
AST.cpp
View File

@ -140,12 +140,22 @@ void ContractDefinition::checkDuplicateFunctions() const
map<string, vector<FunctionDefinition const*>> functions;
for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions())
functions[function->getName()].push_back(function.get());
if (functions[getName()].size() > 1)
{
SecondarySourceLocation ssl;
auto it = functions[getName()].begin();
++it;
for(; it != functions[getName()].end(); ++it)
ssl.append("Another declaration is here:", (*it)->getLocation());
BOOST_THROW_EXCEPTION(
DeclarationError() <<
errinfo_sourceLocation(getLocation()) <<
errinfo_comment("More than one constructor defined.")
errinfo_sourceLocation(getConstructor()->getLocation()) <<
errinfo_comment("More than one constructor defined.") <<
errinfo_secondarySourceLocation(ssl)
);
}
for (auto const& it: functions)
{
vector<FunctionDefinition const*> const& overloads = it.second;
@ -155,7 +165,9 @@ void ContractDefinition::checkDuplicateFunctions() const
BOOST_THROW_EXCEPTION(
DeclarationError() <<
errinfo_sourceLocation(overloads[j]->getLocation()) <<
errinfo_comment("Function with same name and arguments already defined.")
errinfo_comment("Function with same name and arguments already defined.") <<
errinfo_secondarySourceLocation(SecondarySourceLocation().append(
"The previous declaration is here:", overloads[i]->getLocation()))
);
}
}

View File

@ -28,6 +28,28 @@ using namespace std;
using namespace dev;
using namespace dev::solidity;
Declaration const* DeclarationContainer::conflictingDeclaration(Declaration const& _declaration) const
{
ASTString const& name(_declaration.getName());
solAssert(!name.empty(), "");
vector<Declaration const*> declarations;
if (m_declarations.count(name))
declarations += m_declarations.at(name);
if (m_invisibleDeclarations.count(name))
declarations += m_invisibleDeclarations.at(name);
if (dynamic_cast<FunctionDefinition const*>(&_declaration))
{
// check that all other declarations with the same name are functions
for (Declaration const* declaration: declarations)
if (!dynamic_cast<FunctionDefinition const*>(declaration))
return declaration;
}
else if (!declarations.empty())
return declarations.front();
return nullptr;
}
bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _invisible, bool _update)
{
ASTString const& name(_declaration.getName());
@ -40,24 +62,8 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration,
m_declarations.erase(name);
m_invisibleDeclarations.erase(name);
}
else
{
vector<Declaration const*> declarations;
if (m_declarations.count(name))
declarations += m_declarations.at(name);
if (m_invisibleDeclarations.count(name))
declarations += m_invisibleDeclarations.at(name);
if (dynamic_cast<FunctionDefinition const*>(&_declaration))
{
// check that all other declarations with the same name are functions
for (Declaration const* declaration: declarations)
if (!dynamic_cast<FunctionDefinition const*>(declaration))
return false;
}
else if (!declarations.empty())
return false;
}
else if (conflictingDeclaration(_declaration))
return false;
if (_invisible)
m_invisibleDeclarations[name].insert(&_declaration);

View File

@ -34,7 +34,7 @@ namespace solidity
{
/**
* Container that stores mappings betwee names and declarations. It also contains a link to the
* Container that stores mappings between names and declarations. It also contains a link to the
* enclosing scope.
*/
class DeclarationContainer
@ -51,6 +51,8 @@ public:
std::set<Declaration const*> resolveName(ASTString const& _name, bool _recursive = false) const;
Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; }
std::map<ASTString, std::set<Declaration const*>> const& getDeclarations() const { return m_declarations; }
/// @returns weather declaration is valid, and if not also returns previous declaration.
Declaration const* conflictingDeclaration(Declaration const& _declaration) const;
private:
Declaration const* m_enclosingDeclaration;

View File

@ -23,6 +23,7 @@
#pragma once
#include <string>
#include <utility>
#include <libdevcore/Exceptions.h>
#include <libevmcore/SourceLocation.h>
@ -38,7 +39,23 @@ struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {};
struct DocstringParsingError: virtual Exception {};
using errorSourceLocationInfo = std::pair<std::string, SourceLocation>;
class SecondarySourceLocation
{
public:
//SecondarySourceLocation(){}
SecondarySourceLocation& append(std::string const& _errMsg, SourceLocation const& _sourceLocation)
{
infos.push_back(std::make_pair(_errMsg, _sourceLocation));
return *this;
}
std::vector<errorSourceLocationInfo> infos;
};
using errinfo_sourceLocation = boost::error_info<struct tag_sourceLocation, SourceLocation>;
using errinfo_secondarySourceLocation = boost::error_info<struct tag_secondarySourceLocation, SecondarySourceLocation>;
}
}

View File

@ -354,8 +354,16 @@ void DeclarationRegistrationHelper::closeCurrentScope()
void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope)
{
if (!m_scopes[m_currentScope].registerDeclaration(_declaration, !_declaration.isVisibleInContract()))
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_declaration.getLocation())
<< errinfo_comment("Identifier already declared."));
{
solAssert(m_scopes[m_currentScope].conflictingDeclaration(_declaration), "");
BOOST_THROW_EXCEPTION(DeclarationError()
<< errinfo_sourceLocation(_declaration.getLocation())
<< errinfo_comment("Identifier already declared.")
<< errinfo_secondarySourceLocation(SecondarySourceLocation().append(
"The previous declaration is here:",
m_scopes[m_currentScope].conflictingDeclaration(_declaration)->getLocation())));
}
//@todo the exception should also contain the location of the first declaration
_declaration.setScope(m_currentScope);
if (_opensScope)

View File

@ -64,28 +64,53 @@ void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
<< "Spanning multiple lines.\n";
}
void SourceReferenceFormatter::printSourceName(ostream& _stream,
SourceLocation const& _location,
Scanner const& _scanner)
{
int startLine;
int startColumn;
tie(startLine, startColumn) = _scanner.translatePositionToLineColumn(_location.start);
_stream << *_location.sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": ";
}
void SourceReferenceFormatter::printExceptionInformation(ostream& _stream,
Exception const& _exception,
string const& _name,
CompilerStack const& _compiler)
{
SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
auto secondarylocation = boost::get_error_info<errinfo_secondarySourceLocation>(_exception);
Scanner const* scanner;
if (location)
{
scanner = &_compiler.getScanner(*location->sourceName);
int startLine;
int startColumn;
tie(startLine, startColumn) = scanner->translatePositionToLineColumn(location->start);
_stream << *location->sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": ";
printSourceName(_stream, *location, *scanner);
}
_stream << _name;
if (string const* description = boost::get_error_info<errinfo_comment>(_exception))
_stream << ": " << *description << endl;
if (location)
{
solAssert(scanner, "");
printSourceLocation(_stream, *location, *scanner);
}
if (secondarylocation && !secondarylocation->infos.empty())
{
for(auto info: secondarylocation->infos)
{
scanner = &_compiler.getScanner(*info.second.sourceName);
_stream << info.first << " ";
printSourceName(_stream, info.second, *scanner);
_stream << endl;
printSourceLocation(_stream, info.second, *scanner);
}
_stream << endl;
}
}
}

View File

@ -42,6 +42,8 @@ public:
static void printSourceLocation(std::ostream& _stream, SourceLocation const& _location, Scanner const& _scanner);
static void printExceptionInformation(std::ostream& _stream, Exception const& _exception,
std::string const& _name, CompilerStack const& _compiler);
private:
static void printSourceName(std::ostream& _stream, SourceLocation const& _location, Scanner const& _scanner);
};
}