Add unique IDs to error reporting calls

This commit is contained in:
a3d4 2020-05-09 01:28:55 +02:00
parent 6965f199fd
commit c3e519a151
4 changed files with 65 additions and 58 deletions

View File

@ -77,9 +77,9 @@ void ParserBase::expectToken(Token _value, bool _advance)
{
string const expectedToken = ParserBase::tokenName(_value);
if (m_parserErrorRecovery)
parserError("Expected " + expectedToken + " but got " + tokenName(tok));
parserError(6635_error, "Expected " + expectedToken + " but got " + tokenName(tok));
else
fatalParserError("Expected " + expectedToken + " but got " + tokenName(tok));
fatalParserError(2314_error, "Expected " + expectedToken + " but got " + tokenName(tok));
// Do not advance so that recovery can sync or make use of the current token.
// This is especially useful if the expected token
// is the only one that is missing and is at the end of a construct.
@ -108,21 +108,21 @@ void ParserBase::expectTokenOrConsumeUntil(Token _value, string const& _currentN
// rollback to where the token started, and raise exception to be caught at a higher level.
m_scanner->setPosition(startPosition);
m_inParserRecovery = true;
fatalParserError(errorLoc, msg);
fatalParserError(1957_error, errorLoc, msg);
}
else
{
if (m_inParserRecovery)
parserWarning("Recovered in " + _currentNodeName + " at " + expectedToken + ".");
parserWarning(3796_error, "Recovered in " + _currentNodeName + " at " + expectedToken + ".");
else
parserError(errorLoc, msg + "Recovered at next " + expectedToken);
parserError(1054_error, errorLoc, msg + "Recovered at next " + expectedToken);
m_inParserRecovery = false;
}
}
else if (m_inParserRecovery)
{
string expectedToken = ParserBase::tokenName(_value);
parserWarning("Recovered in " + _currentNodeName + " at " + expectedToken + ".");
parserWarning(3347_error, "Recovered in " + _currentNodeName + " at " + expectedToken + ".");
m_inParserRecovery = false;
}
@ -134,7 +134,7 @@ void ParserBase::increaseRecursionDepth()
{
m_recursionDepth++;
if (m_recursionDepth >= 1200)
fatalParserError("Maximum recursion depth reached during parsing.");
fatalParserError(7319_error, "Maximum recursion depth reached during parsing.");
}
void ParserBase::decreaseRecursionDepth()

View File

@ -103,7 +103,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
nodes.push_back(parseEnumDefinition());
break;
default:
fatalParserError(string("Expected pragma, import directive or contract/interface/library/struct/enum definition."));
fatalParserError(7858_error, string("Expected pragma, import directive or contract/interface/library/struct/enum definition."));
}
}
solAssert(m_recursionDepth == 0, "");
@ -163,7 +163,7 @@ ASTPointer<PragmaDirective> Parser::parsePragmaDirective()
{
Token token = m_scanner->currentToken();
if (token == Token::Illegal)
parserError("Token incompatible with Solidity parser as part of pragma directive.");
parserError(6281_error, "Token incompatible with Solidity parser as part of pragma directive.");
else
{
string literal = m_scanner->currentLiteral();
@ -241,18 +241,18 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
unitAlias = expectIdentifierToken();
}
else
fatalParserError("Expected string literal (path), \"*\" or alias list.");
fatalParserError(9478_error, "Expected string literal (path), \"*\" or alias list.");
// "from" is not a keyword but parsed as an identifier because of backwards
// compatibility and because it is a really common word.
if (m_scanner->currentToken() != Token::Identifier || m_scanner->currentLiteral() != "from")
fatalParserError("Expected \"from\".");
fatalParserError(8208_error, "Expected \"from\".");
m_scanner->next();
if (m_scanner->currentToken() != Token::StringLiteral)
fatalParserError("Expected import path.");
fatalParserError(6845_error, "Expected import path.");
path = getLiteralAndAdvance();
}
if (path->empty())
fatalParserError("Import path cannot be empty.");
fatalParserError(6326_error, "Import path cannot be empty.");
nodeFactory.markEndPosition();
expectToken(Token::Semicolon);
return nodeFactory.createNode<ImportDirective>(path, unitAlias, move(symbolAliases));
@ -279,7 +279,7 @@ std::pair<ContractKind, bool> Parser::parseContractKind()
kind = ContractKind::Library;
break;
default:
parserError("Expected keyword \"contract\", \"interface\" or \"library\".");
parserError(3515_error, "Expected keyword \"contract\", \"interface\" or \"library\".");
return std::make_pair(ContractKind::Contract, abstract);
}
m_scanner->next();
@ -344,7 +344,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
else if (currentTokenValue == Token::Using)
subNodes.push_back(parseUsingDirective());
else
fatalParserError(string("Function, variable, struct or modifier declaration expected."));
fatalParserError(9182_error, string("Function, variable, struct or modifier declaration expected."));
}
}
catch (FatalError const&)
@ -463,6 +463,7 @@ StateMutability Parser::parseStateMutability()
case Token::Constant:
stateMutability = StateMutability::View;
parserError(
7698_error,
"The state mutability modifier \"constant\" was removed in version 0.5.0. "
"Use \"view\" or \"pure\" instead."
);
@ -495,7 +496,8 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
// Detect this and return early.
if (_isStateVariable && (result.visibility == Visibility::External || result.visibility == Visibility::Internal))
break;
parserError(string(
parserError(
9439_error,string(
"Visibility already specified as \"" +
Declaration::visibilityToString(result.visibility) +
"\"."
@ -509,7 +511,8 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
{
if (result.stateMutability != StateMutability::NonPayable)
{
parserError(string(
parserError(
9680_error,string(
"State mutability already specified as \"" +
stateMutabilityToString(result.stateMutability) +
"\"."
@ -522,14 +525,14 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
else if (!_isStateVariable && token == Token::Override)
{
if (result.overrides)
parserError("Override already specified.");
parserError(1827_error, "Override already specified.");
result.overrides = parseOverrideSpecifier();
}
else if (!_isStateVariable && token == Token::Virtual)
{
if (result.isVirtual)
parserError("Virtual already specified.");
parserError(6879_error, "Virtual already specified.");
result.isVirtual = true;
m_scanner->next();
@ -577,9 +580,9 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition()
"the \"function\" keyword to define it."
};
if (m_scanner->currentToken() == Token::Constructor)
parserError(message);
parserError(3323_error, message);
else
parserWarning(message);
parserWarning(3445_error, message);
m_scanner->next();
}
else
@ -660,10 +663,10 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
break;
expectToken(Token::Comma);
if (m_scanner->currentToken() != Token::Identifier)
fatalParserError(string("Expected identifier after ','"));
fatalParserError(1612_error, string("Expected identifier after ','"));
}
if (members.empty())
parserError({"enum with no members is not allowed."});
parserError(3147_error, {"enum with no members is not allowed."});
nodeFactory.markEndPosition();
expectToken(Token::RBrace);
@ -690,6 +693,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
if (dynamic_cast<FunctionTypeName*>(type.get()) && _options.isStateVariable && m_scanner->currentToken() == Token::LBrace)
fatalParserError(
2915_error,
"Expected a state variable declaration. If you intended this as a fallback function "
"or a function to handle plain ether transactions, use the \"fallback\" keyword "
"or the \"receive\" keyword instead."
@ -710,7 +714,8 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
nodeFactory.markEndPosition();
if (visibility != Visibility::Default)
{
parserError(string(
parserError(
4110_error,string(
"Visibility already specified as \"" +
Declaration::visibilityToString(visibility) +
"\"."
@ -723,7 +728,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
else if (_options.isStateVariable && token == Token::Override)
{
if (overrides)
parserError("Override already specified.");
parserError(9125_error, "Override already specified.");
overrides = parseOverrideSpecifier();
}
@ -735,6 +740,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
{
if (mutability != VariableDeclaration::Mutability::Mutable)
parserError(
3109_error,
string("Mutability already set to ") +
(mutability == VariableDeclaration::Mutability::Constant ? "\"constant\"" : "\"immutable\"")
);
@ -746,9 +752,9 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
else if (_options.allowLocationSpecifier && TokenTraits::isLocationSpecifier(token))
{
if (location != VariableDeclaration::Location::Unspecified)
parserError(string("Location already specified."));
parserError(3548_error, string("Location already specified."));
else if (!type)
parserError(string("Location specifier needs explicit type name."));
parserError(7439_error, string("Location specifier needs explicit type name."));
else
{
switch (token)
@ -837,13 +843,13 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
if (m_scanner->currentToken() == Token::Override)
{
if (overrides)
parserError("Override already specified.");
parserError(9102_error, "Override already specified.");
overrides = parseOverrideSpecifier();
}
else if (m_scanner->currentToken() == Token::Virtual)
{
if (isVirtual)
parserError("Virtual already specified.");
parserError(2662_error, "Virtual already specified.");
isVirtual = true;
m_scanner->next();
@ -991,7 +997,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
}
else
{
parserError("State mutability can only be specified for address types.");
parserError(9106_error, "State mutability can only be specified for address types.");
m_scanner->next();
}
}
@ -1000,7 +1006,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
else if (token == Token::Var)
{
if (!_allowVar)
parserError(string("Expected explicit type name."));
parserError(7059_error, string("Expected explicit type name."));
m_scanner->next();
}
else if (token == Token::Function)
@ -1010,7 +1016,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
else if (token == Token::Identifier)
type = parseUserDefinedTypeName();
else
fatalParserError(string("Expected type name"));
fatalParserError(3546_error, string("Expected type name"));
if (type)
// Parse "[...]" postfixes for arrays.
@ -1053,7 +1059,7 @@ ASTPointer<Mapping> Parser::parseMapping()
m_scanner->next();
}
else
fatalParserError(string("Expected elementary type name or identifier for mapping key type"));
fatalParserError(1005_error, string("Expected elementary type name or identifier for mapping key type"));
expectToken(Token::Arrow);
bool const allowVar = false;
ASTPointer<TypeName> valueType = parseTypeName(allowVar);
@ -1079,7 +1085,7 @@ ASTPointer<ParameterList> Parser::parseParameterList(
while (m_scanner->currentToken() != Token::RParen)
{
if (m_scanner->currentToken() == Token::Comma && m_scanner->peekNextToken() == Token::RParen)
fatalParserError("Unexpected trailing comma in parameter list.");
fatalParserError(7591_error, "Unexpected trailing comma in parameter list.");
expectToken(Token::Comma);
parameters.push_back(parseVariableDeclaration(options));
}
@ -1214,7 +1220,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
if (m_scanner->currentToken() == Token::StringLiteral)
{
if (m_scanner->currentLiteral() != "evmasm")
fatalParserError("Only \"evmasm\" supported.");
fatalParserError(4531_error, "Only \"evmasm\" supported.");
// This can be used in the future to set the dialect.
m_scanner->next();
}
@ -1377,7 +1383,7 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
ASTNodeFactory eventCallNodeFactory(*this);
if (m_scanner->currentToken() != Token::Identifier)
fatalParserError("Expected event name or path.");
fatalParserError(5620_error, "Expected event name or path.");
IndexAccessedPath iap;
while (true)
@ -1845,7 +1851,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
nodeFactory.markEndPosition();
m_scanner->next();
if (m_scanner->currentToken() == Token::Illegal)
fatalParserError(to_string(m_scanner->currentError()));
fatalParserError(5428_error, to_string(m_scanner->currentError()));
expression = nodeFactory.createNode<Literal>(token, make_shared<ASTString>(literal));
break;
}
@ -1876,7 +1882,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != oppositeToken)
components.push_back(parseExpression());
else if (isArray)
parserError("Expected expression (inline array elements cannot be omitted).");
parserError(4799_error, "Expected expression (inline array elements cannot be omitted).");
else
components.push_back(ASTPointer<Expression>());
@ -1891,7 +1897,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
break;
}
case Token::Illegal:
fatalParserError(to_string(m_scanner->currentError()));
fatalParserError(8936_error, to_string(m_scanner->currentError()));
break;
default:
if (TokenTraits::isElementaryTypeName(token))
@ -1907,7 +1913,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
m_scanner->next();
}
else
fatalParserError(string("Expected primary expression."));
fatalParserError(6933_error, string("Expected primary expression."));
break;
}
return expression;
@ -1965,7 +1971,7 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars
m_scanner->peekNextToken() == Token::RBrace
)
{
parserError("Unexpected trailing comma.");
parserError(2074_error, "Unexpected trailing comma.");
m_scanner->next();
}
@ -2084,7 +2090,7 @@ ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAcces
for (auto const& lengthExpression: _iap.indices)
{
if (lengthExpression.end)
parserError(lengthExpression.location, "Expected array length expression.");
parserError(5464_error, lengthExpression.location, "Expected array length expression.");
nodeFactory.setLocation(lengthExpression.location);
type = nodeFactory.createNode<ArrayTypeName>(type, lengthExpression.start);
}

View File

@ -122,11 +122,11 @@ Statement Parser::parseStatement()
if (currentToken() == Token::Default)
_switch.cases.emplace_back(parseCase());
if (currentToken() == Token::Default)
fatalParserError("Only one default case allowed.");
fatalParserError(6931_error, "Only one default case allowed.");
else if (currentToken() == Token::Case)
fatalParserError("Case not allowed after default case.");
fatalParserError(4904_error, "Case not allowed after default case.");
if (_switch.cases.empty())
fatalParserError("Switch statement without any cases.");
fatalParserError(2418_error, "Switch statement without any cases.");
_switch.location.end = _switch.cases.back().body.location.end;
return Statement{move(_switch)};
}
@ -184,6 +184,7 @@ Statement Parser::parseStatement()
auto const token = currentToken() == Token::Comma ? "," : ":=";
fatalParserError(
2856_error,
std::string("Variable name must precede \"") +
token +
"\"" +
@ -194,7 +195,7 @@ Statement Parser::parseStatement()
auto const& identifier = std::get<Identifier>(elementary);
if (m_dialect.builtin(identifier.name))
fatalParserError("Cannot assign to builtin function \"" + identifier.name.str() + "\".");
fatalParserError(6272_error, "Cannot assign to builtin function \"" + identifier.name.str() + "\".");
variableNames.emplace_back(identifier);
@ -218,7 +219,7 @@ Statement Parser::parseStatement()
return Statement{std::move(assignment)};
}
default:
fatalParserError("Call or assignment expected.");
fatalParserError(6913_error, "Call or assignment expected.");
break;
}
@ -250,7 +251,7 @@ Case Parser::parseCase()
advance();
ElementaryOperation literal = parseElementaryOperation();
if (!holds_alternative<Literal>(literal))
fatalParserError("Literal expected.");
fatalParserError(4805_error, "Literal expected.");
_case.value = make_unique<Literal>(std::get<Literal>(std::move(literal)));
}
else
@ -353,7 +354,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
break;
case Token::Number:
if (!isValidNumberLiteral(currentLiteral()))
fatalParserError("Invalid number literal.");
fatalParserError(4828_error, "Invalid number literal.");
kind = LiteralKind::Number;
break;
case Token::TrueLiteral:
@ -382,7 +383,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
break;
}
default:
fatalParserError("Literal or identifier expected.");
fatalParserError(1856_error, "Literal or identifier expected.");
}
return ret;
}
@ -472,7 +473,7 @@ Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp)
else if (holds_alternative<FunctionCall>(_initialOp))
ret = std::move(std::get<FunctionCall>(_initialOp));
else
fatalParserError("Function name expected.");
fatalParserError(9980_error, "Function name expected.");
expectToken(Token::LParen);
if (currentToken() != Token::RParen)
@ -525,7 +526,7 @@ YulString Parser::expectAsmIdentifier()
}
if (m_dialect.builtin(name))
fatalParserError("Cannot use builtin function name \"" + name.str() + "\" as identifier name.");
fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name.");
advance();
return name;
}

View File

@ -66,7 +66,7 @@ shared_ptr<Object> ObjectParser::parseObject(Object* _containingObject)
RecursionGuard guard(*this);
if (currentToken() != Token::Identifier || currentLiteral() != "object")
fatalParserError("Expected keyword \"object\".");
fatalParserError(4294_error, "Expected keyword \"object\".");
advance();
shared_ptr<Object> ret = make_shared<Object>();
@ -83,7 +83,7 @@ shared_ptr<Object> ObjectParser::parseObject(Object* _containingObject)
else if (currentToken() == Token::Identifier && currentLiteral() == "data")
parseData(*ret);
else
fatalParserError("Expected keyword \"data\" or \"object\" or \"}\".");
fatalParserError(8143_error, "Expected keyword \"data\" or \"object\" or \"}\".");
}
if (_containingObject)
addNamedSubObject(*_containingObject, ret->name, ret);
@ -96,7 +96,7 @@ shared_ptr<Object> ObjectParser::parseObject(Object* _containingObject)
shared_ptr<Block> ObjectParser::parseCode()
{
if (currentToken() != Token::Identifier || currentLiteral() != "code")
fatalParserError("Expected keyword \"code\".");
fatalParserError(4846_error, "Expected keyword \"code\".");
advance();
return parseBlock();
@ -133,11 +133,11 @@ YulString ObjectParser::parseUniqueName(Object const* _containingObject)
expectToken(Token::StringLiteral, false);
YulString name{currentLiteral()};
if (name.empty())
parserError("Object name cannot be empty.");
parserError(3287_error, "Object name cannot be empty.");
else if (_containingObject && _containingObject->name == name)
parserError("Object name cannot be the same as the name of the containing object.");
parserError(8311_error, "Object name cannot be the same as the name of the containing object.");
else if (_containingObject && _containingObject->subIndexByName.count(name))
parserError("Object name \"" + name.str() + "\" already exists inside the containing object.");
parserError(8794_error, "Object name \"" + name.str() + "\" already exists inside the containing object.");
advance();
return name;
}