mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
created secondarySoureLocation error type
added additional information to error msgs
This commit is contained in:
parent
ef26d96111
commit
8b5fa857d7
18
AST.cpp
18
AST.cpp
@ -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()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
17
Exceptions.h
17
Exceptions.h
@ -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>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user