mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Parse override keyword
This commit is contained in:
@@ -604,6 +604,32 @@ protected:
|
||||
ASTPointer<ParameterList> m_returnParameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function override specifier. Consists of a single override keyword
|
||||
* potentially followed by a parenthesized list of base contract names.
|
||||
*/
|
||||
class OverrideSpecifier: public ASTNode
|
||||
{
|
||||
public:
|
||||
OverrideSpecifier(
|
||||
SourceLocation const& _location,
|
||||
std::vector<ASTPointer<UserDefinedTypeName>> const& _overrides
|
||||
):
|
||||
ASTNode(_location),
|
||||
m_overrides(_overrides)
|
||||
{
|
||||
}
|
||||
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
/// @returns the list of specific overrides, if any
|
||||
std::vector<ASTPointer<UserDefinedTypeName>> const& overrides() const { return m_overrides; }
|
||||
|
||||
protected:
|
||||
std::vector<ASTPointer<UserDefinedTypeName>> m_overrides;
|
||||
};
|
||||
|
||||
class FunctionDefinition: public CallableDeclaration, public Documented, public ImplementationOptional
|
||||
{
|
||||
public:
|
||||
@@ -613,6 +639,7 @@ public:
|
||||
Declaration::Visibility _visibility,
|
||||
StateMutability _stateMutability,
|
||||
bool _isConstructor,
|
||||
ASTPointer<OverrideSpecifier> const& _overrides,
|
||||
ASTPointer<ASTString> const& _documentation,
|
||||
ASTPointer<ParameterList> const& _parameters,
|
||||
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
|
||||
@@ -624,6 +651,7 @@ public:
|
||||
ImplementationOptional(_body != nullptr),
|
||||
m_stateMutability(_stateMutability),
|
||||
m_isConstructor(_isConstructor),
|
||||
m_overrides(_overrides),
|
||||
m_functionModifiers(_modifiers),
|
||||
m_body(_body)
|
||||
{}
|
||||
@@ -633,6 +661,7 @@ public:
|
||||
|
||||
StateMutability stateMutability() const { return m_stateMutability; }
|
||||
bool isConstructor() const { return m_isConstructor; }
|
||||
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
|
||||
bool isFallback() const { return !m_isConstructor && name().empty(); }
|
||||
bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
|
||||
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
|
||||
@@ -661,6 +690,7 @@ public:
|
||||
private:
|
||||
StateMutability m_stateMutability;
|
||||
bool m_isConstructor;
|
||||
ASTPointer<OverrideSpecifier> m_overrides;
|
||||
std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
|
||||
ASTPointer<Block> m_body;
|
||||
};
|
||||
@@ -683,6 +713,7 @@ public:
|
||||
bool _isStateVar = false,
|
||||
bool _isIndexed = false,
|
||||
bool _isConstant = false,
|
||||
ASTPointer<OverrideSpecifier> const& _overrides = nullptr,
|
||||
Location _referenceLocation = Location::Unspecified
|
||||
):
|
||||
Declaration(_sourceLocation, _name, _visibility),
|
||||
@@ -691,6 +722,7 @@ public:
|
||||
m_isStateVariable(_isStateVar),
|
||||
m_isIndexed(_isIndexed),
|
||||
m_isConstant(_isConstant),
|
||||
m_overrides(_overrides),
|
||||
m_location(_referenceLocation) {}
|
||||
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
@@ -730,6 +762,7 @@ public:
|
||||
bool isStateVariable() const { return m_isStateVariable; }
|
||||
bool isIndexed() const { return m_isIndexed; }
|
||||
bool isConstant() const { return m_isConstant; }
|
||||
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
|
||||
Location referenceLocation() const { return m_location; }
|
||||
/// @returns a set of allowed storage locations for the variable.
|
||||
std::set<Location> allowedDataLocations() const;
|
||||
@@ -753,6 +786,7 @@ private:
|
||||
bool m_isStateVariable; ///< Whether or not this is a contract state variable
|
||||
bool m_isIndexed; ///< Whether this is an indexed variable (used by events).
|
||||
bool m_isConstant; ///< Whether the variable is a compile-time constant.
|
||||
ASTPointer<OverrideSpecifier> m_overrides; ///< Contains the override specifier node
|
||||
Location m_location; ///< Location of the variable if it is of reference type.
|
||||
};
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ class PragmaDirective;
|
||||
class ImportDirective;
|
||||
class Declaration;
|
||||
class CallableDeclaration;
|
||||
class OverrideSpecifier;
|
||||
class ContractDefinition;
|
||||
class InheritanceSpecifier;
|
||||
class UsingForDirective;
|
||||
|
||||
@@ -334,6 +334,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
|
||||
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
||||
make_pair("superFunction", idOrNull(_node.annotation().superFunction)),
|
||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
make_pair("overrides", _node.overrides() ? toJson(_node.overrides()->overrides()) : Json::nullValue),
|
||||
make_pair("parameters", toJson(_node.parameterList())),
|
||||
make_pair("returnParameters", toJson(*_node.returnParameterList())),
|
||||
make_pair("modifiers", toJson(_node.modifiers())),
|
||||
@@ -355,6 +356,7 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node)
|
||||
make_pair("constant", _node.isConstant()),
|
||||
make_pair("stateVariable", _node.isStateVariable()),
|
||||
make_pair("storageLocation", location(_node.referenceLocation())),
|
||||
make_pair("overrides", _node.overrides() ? toJson(_node.overrides()->overrides()) : Json::nullValue),
|
||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue),
|
||||
make_pair("scope", idOrNull(_node.scope())),
|
||||
|
||||
@@ -111,6 +111,13 @@ bool ASTPrinter::visit(ParameterList const& _node)
|
||||
return goDeeper();
|
||||
}
|
||||
|
||||
bool ASTPrinter::visit(OverrideSpecifier const& _node)
|
||||
{
|
||||
writeLine("OverrideSpecifier");
|
||||
printSourcePart(_node);
|
||||
return goDeeper();
|
||||
}
|
||||
|
||||
bool ASTPrinter::visit(FunctionDefinition const& _node)
|
||||
{
|
||||
writeLine(
|
||||
@@ -432,6 +439,11 @@ void ASTPrinter::endVisit(ParameterList const&)
|
||||
m_indentation--;
|
||||
}
|
||||
|
||||
void ASTPrinter::endVisit(OverrideSpecifier const&)
|
||||
{
|
||||
m_indentation--;
|
||||
}
|
||||
|
||||
void ASTPrinter::endVisit(FunctionDefinition const&)
|
||||
{
|
||||
m_indentation--;
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
bool visit(EnumDefinition const& _node) override;
|
||||
bool visit(EnumValue const& _node) override;
|
||||
bool visit(ParameterList const& _node) override;
|
||||
bool visit(OverrideSpecifier const& _node) override;
|
||||
bool visit(FunctionDefinition const& _node) override;
|
||||
bool visit(VariableDeclaration const& _node) override;
|
||||
bool visit(ModifierDefinition const& _node) override;
|
||||
@@ -101,6 +102,7 @@ public:
|
||||
void endVisit(EnumDefinition const&) override;
|
||||
void endVisit(EnumValue const&) override;
|
||||
void endVisit(ParameterList const&) override;
|
||||
void endVisit(OverrideSpecifier const&) override;
|
||||
void endVisit(FunctionDefinition const&) override;
|
||||
void endVisit(VariableDeclaration const&) override;
|
||||
void endVisit(ModifierDefinition const&) override;
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
virtual bool visit(EnumDefinition& _node) { return visitNode(_node); }
|
||||
virtual bool visit(EnumValue& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ParameterList& _node) { return visitNode(_node); }
|
||||
virtual bool visit(OverrideSpecifier& _node) { return visitNode(_node); }
|
||||
virtual bool visit(FunctionDefinition& _node) { return visitNode(_node); }
|
||||
virtual bool visit(VariableDeclaration& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ModifierDefinition& _node) { return visitNode(_node); }
|
||||
@@ -100,6 +101,7 @@ public:
|
||||
virtual void endVisit(EnumDefinition& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(EnumValue& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ParameterList& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(OverrideSpecifier& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(FunctionDefinition& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(VariableDeclaration& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ModifierDefinition& _node) { endVisitNode(_node); }
|
||||
@@ -159,6 +161,7 @@ public:
|
||||
virtual bool visit(EnumDefinition const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(EnumValue const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ParameterList const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(OverrideSpecifier const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(FunctionDefinition const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(VariableDeclaration const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ModifierDefinition const& _node) { return visitNode(_node); }
|
||||
@@ -205,6 +208,7 @@ public:
|
||||
virtual void endVisit(EnumDefinition const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(EnumValue const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ParameterList const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(OverrideSpecifier const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(FunctionDefinition const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(VariableDeclaration const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ModifierDefinition const& _node) { endVisitNode(_node); }
|
||||
|
||||
@@ -187,10 +187,26 @@ void ParameterList::accept(ASTConstVisitor& _visitor) const
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void OverrideSpecifier::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
listAccept(m_overrides, _visitor);
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void OverrideSpecifier::accept(ASTConstVisitor& _visitor) const
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
listAccept(m_overrides, _visitor);
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void FunctionDefinition::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_overrides)
|
||||
m_overrides->accept(_visitor);
|
||||
m_parameters->accept(_visitor);
|
||||
if (m_returnParameters)
|
||||
m_returnParameters->accept(_visitor);
|
||||
@@ -205,6 +221,8 @@ void FunctionDefinition::accept(ASTConstVisitor& _visitor) const
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_overrides)
|
||||
m_overrides->accept(_visitor);
|
||||
m_parameters->accept(_visitor);
|
||||
if (m_returnParameters)
|
||||
m_returnParameters->accept(_visitor);
|
||||
|
||||
@@ -382,6 +382,36 @@ Declaration::Visibility Parser::parseVisibilitySpecifier()
|
||||
return visibility;
|
||||
}
|
||||
|
||||
ASTPointer<OverrideSpecifier> Parser::parseOverrideSpecifier()
|
||||
{
|
||||
solAssert(m_scanner->currentToken() == Token::Override, "");
|
||||
|
||||
ASTNodeFactory nodeFactory(*this);
|
||||
std::vector<ASTPointer<UserDefinedTypeName>> overrides;
|
||||
|
||||
nodeFactory.markEndPosition();
|
||||
m_scanner->next();
|
||||
|
||||
if (m_scanner->currentToken() == Token::LParen)
|
||||
{
|
||||
m_scanner->next();
|
||||
while (true)
|
||||
{
|
||||
overrides.push_back(parseUserDefinedTypeName());
|
||||
|
||||
if (m_scanner->currentToken() == Token::RParen)
|
||||
break;
|
||||
|
||||
expectToken(Token::Comma);
|
||||
}
|
||||
|
||||
nodeFactory.markEndPosition();
|
||||
expectToken(Token::RParen);
|
||||
}
|
||||
|
||||
return nodeFactory.createNode<OverrideSpecifier>(move(overrides));
|
||||
}
|
||||
|
||||
StateMutability Parser::parseStateMutability()
|
||||
{
|
||||
StateMutability stateMutability(StateMutability::NonPayable);
|
||||
@@ -411,12 +441,13 @@ StateMutability Parser::parseStateMutability()
|
||||
return stateMutability;
|
||||
}
|
||||
|
||||
Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers)
|
||||
Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _onlyFuncType, bool _allowFuncDef)
|
||||
{
|
||||
RecursionGuard recursionGuard(*this);
|
||||
FunctionHeaderParserResult result;
|
||||
|
||||
result.isConstructor = false;
|
||||
result.overrides = nullptr;
|
||||
|
||||
if (m_scanner->currentToken() == Token::Constructor)
|
||||
result.isConstructor = true;
|
||||
@@ -426,7 +457,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
|
||||
|
||||
if (result.isConstructor)
|
||||
result.name = make_shared<ASTString>();
|
||||
else if (_forceEmptyName || m_scanner->currentToken() == Token::LParen)
|
||||
else if (_onlyFuncType || m_scanner->currentToken() == Token::LParen)
|
||||
result.name = make_shared<ASTString>();
|
||||
else if (m_scanner->currentToken() == Token::Constructor)
|
||||
fatalParserError(string(
|
||||
@@ -443,7 +474,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
|
||||
while (true)
|
||||
{
|
||||
Token token = m_scanner->currentToken();
|
||||
if (_allowModifiers && token == Token::Identifier)
|
||||
if (_allowFuncDef && token == Token::Identifier)
|
||||
{
|
||||
// If the name is empty (and this is not a constructor),
|
||||
// then this can either be a modifier (fallback function declaration)
|
||||
@@ -493,6 +524,13 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
|
||||
else
|
||||
result.stateMutability = parseStateMutability();
|
||||
}
|
||||
else if (_allowFuncDef && token == Token::Override)
|
||||
{
|
||||
if (result.overrides)
|
||||
parserError("Override already specified.");
|
||||
|
||||
result.overrides = parseOverrideSpecifier();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
@@ -521,6 +559,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable()
|
||||
header.isConstructor ||
|
||||
!header.modifiers.empty() ||
|
||||
!header.name->empty() ||
|
||||
header.overrides ||
|
||||
m_scanner->currentToken() == Token::Semicolon ||
|
||||
m_scanner->currentToken() == Token::LBrace
|
||||
)
|
||||
@@ -540,6 +579,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable()
|
||||
header.visibility,
|
||||
header.stateMutability,
|
||||
header.isConstructor,
|
||||
header.overrides,
|
||||
docstring,
|
||||
header.parameters,
|
||||
header.modifiers,
|
||||
@@ -637,6 +677,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
||||
}
|
||||
bool isIndexed = false;
|
||||
bool isDeclaredConst = false;
|
||||
ASTPointer<OverrideSpecifier> overrides = nullptr;
|
||||
Declaration::Visibility visibility(Declaration::Visibility::Default);
|
||||
VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified;
|
||||
ASTPointer<ASTString> identifier;
|
||||
@@ -659,6 +700,13 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
||||
else
|
||||
visibility = parseVisibilitySpecifier();
|
||||
}
|
||||
else if (_options.isStateVariable && token == Token::Override)
|
||||
{
|
||||
if (overrides)
|
||||
parserError("Override already specified.");
|
||||
|
||||
overrides = parseOverrideSpecifier();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_options.allowIndexed && token == Token::Indexed)
|
||||
@@ -724,6 +772,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
||||
_options.isStateVariable,
|
||||
isIndexed,
|
||||
isDeclaredConst,
|
||||
overrides,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ private:
|
||||
struct FunctionHeaderParserResult
|
||||
{
|
||||
bool isConstructor;
|
||||
ASTPointer<OverrideSpecifier> overrides;
|
||||
ASTPointer<ASTString> name;
|
||||
ASTPointer<ParameterList> parameters;
|
||||
ASTPointer<ParameterList> returnParameters;
|
||||
@@ -88,8 +89,9 @@ private:
|
||||
ASTPointer<ContractDefinition> parseContractDefinition();
|
||||
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
|
||||
Declaration::Visibility parseVisibilitySpecifier();
|
||||
ASTPointer<OverrideSpecifier> parseOverrideSpecifier();
|
||||
StateMutability parseStateMutability();
|
||||
FunctionHeaderParserResult parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers);
|
||||
FunctionHeaderParserResult parseFunctionHeader(bool _onlyFuncType, bool _allowFuncDef);
|
||||
ASTPointer<ASTNode> parseFunctionDefinitionOrFunctionTypeStateVariable();
|
||||
ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName);
|
||||
ASTPointer<StructDefinition> parseStructDefinition();
|
||||
|
||||
Reference in New Issue
Block a user