mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Syntax changes for catching custom errors.
This commit is contained in:
@@ -856,13 +856,14 @@ string Literal::getChecksummedAddress() const
|
||||
TryCatchClause const* TryStatement::successClause() const
|
||||
{
|
||||
solAssert(m_clauses.size() > 0, "");
|
||||
solAssert(m_clauses.front()->kind() == TryCatchClause::Kind::Success, "");
|
||||
return m_clauses[0].get();
|
||||
}
|
||||
|
||||
TryCatchClause const* TryStatement::panicClause() const
|
||||
{
|
||||
for (size_t i = 1; i < m_clauses.size(); ++i)
|
||||
if (m_clauses[i]->errorName() == "Panic")
|
||||
if (m_clauses[i]->kind() == TryCatchClause::Kind::Panic)
|
||||
return m_clauses[i].get();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -870,7 +871,7 @@ TryCatchClause const* TryStatement::panicClause() const
|
||||
TryCatchClause const* TryStatement::errorClause() const
|
||||
{
|
||||
for (size_t i = 1; i < m_clauses.size(); ++i)
|
||||
if (m_clauses[i]->errorName() == "Error")
|
||||
if (m_clauses[i]->kind() == TryCatchClause::Kind::Error)
|
||||
return m_clauses[i].get();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -878,7 +879,7 @@ TryCatchClause const* TryStatement::errorClause() const
|
||||
TryCatchClause const* TryStatement::fallbackClause() const
|
||||
{
|
||||
for (size_t i = 1; i < m_clauses.size(); ++i)
|
||||
if (m_clauses[i]->errorName().empty())
|
||||
if (m_clauses[i]->kind() == TryCatchClause::Kind::Fallback)
|
||||
return m_clauses[i].get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+23
-4
@@ -1503,29 +1503,46 @@ private:
|
||||
class TryCatchClause: public ASTNode, public Scopable, public ScopeOpener
|
||||
{
|
||||
public:
|
||||
enum Kind
|
||||
{
|
||||
Success,
|
||||
Panic,
|
||||
Error,
|
||||
Fallback,
|
||||
UserDefined
|
||||
};
|
||||
|
||||
TryCatchClause(
|
||||
int64_t _id,
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ASTString> _errorName,
|
||||
Kind _kind,
|
||||
ASTPointer<IdentifierPath> _errorName,
|
||||
ASTPointer<ParameterList> _parameters,
|
||||
ASTPointer<Block> _block
|
||||
):
|
||||
ASTNode(_id, _location),
|
||||
m_kind(_kind),
|
||||
m_errorName(std::move(_errorName)),
|
||||
m_parameters(std::move(_parameters)),
|
||||
m_block(std::move(_block))
|
||||
{}
|
||||
{
|
||||
solAssert(!!m_errorName == (m_kind == Kind::UserDefined), "");
|
||||
}
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
ASTString const& errorName() const { return *m_errorName; }
|
||||
|
||||
Kind kind() const { return m_kind; }
|
||||
/// @returns the name of the error. Should only be called if catch kind is UserDefined.
|
||||
IdentifierPath const& errorName() const { return *m_errorName; }
|
||||
ParameterList const* parameters() const { return m_parameters.get(); }
|
||||
Block const& block() const { return *m_block; }
|
||||
|
||||
TryCatchClauseAnnotation& annotation() const override;
|
||||
|
||||
private:
|
||||
ASTPointer<ASTString> m_errorName;
|
||||
Kind m_kind;
|
||||
ASTPointer<IdentifierPath> m_errorName;
|
||||
ASTPointer<ParameterList> m_parameters;
|
||||
ASTPointer<Block> m_block;
|
||||
};
|
||||
@@ -1535,6 +1552,8 @@ private:
|
||||
* Syntax:
|
||||
* try <call> returns (uint x, uint y) {
|
||||
* // success code
|
||||
* } catch Custom(uint data) {
|
||||
* // custom error handler
|
||||
* } catch Panic(uint errorCode) {
|
||||
* // panic
|
||||
* } catch Error(string memory cause) {
|
||||
|
||||
@@ -578,7 +578,10 @@ bool ASTJsonConverter::visit(IfStatement const& _node)
|
||||
bool ASTJsonConverter::visit(TryCatchClause const& _node)
|
||||
{
|
||||
setJsonNode(_node, "TryCatchClause", {
|
||||
make_pair("errorName", _node.errorName()),
|
||||
make_pair("kind", catchClauseKind(_node.kind())),
|
||||
make_pair("errorName", toJsonOrNull(
|
||||
_node.kind() == TryCatchClause::Kind::UserDefined ? &_node.errorName() : nullptr
|
||||
)),
|
||||
make_pair("parameters", toJsonOrNull(_node.parameters())),
|
||||
make_pair("block", toJson(_node.block()))
|
||||
});
|
||||
@@ -931,6 +934,19 @@ string ASTJsonConverter::functionCallKind(FunctionCallKind _kind)
|
||||
}
|
||||
}
|
||||
|
||||
string ASTJsonConverter::catchClauseKind(TryCatchClause::Kind _kind)
|
||||
{
|
||||
switch (_kind)
|
||||
{
|
||||
case TryCatchClause::Kind::Success: return "success";
|
||||
case TryCatchClause::Kind::Panic: return "panic";
|
||||
case TryCatchClause::Kind::Error: return "error";
|
||||
case TryCatchClause::Kind::Fallback: return "fallback";
|
||||
case TryCatchClause::Kind::UserDefined: return "userDefined";
|
||||
}
|
||||
solAssert(false, "Unknown kind of catch clause.");
|
||||
}
|
||||
|
||||
string ASTJsonConverter::literalTokenKind(Token _token)
|
||||
{
|
||||
switch (_token)
|
||||
|
||||
@@ -153,6 +153,7 @@ private:
|
||||
static std::string location(VariableDeclaration::Location _location);
|
||||
static std::string contractKind(ContractKind _kind);
|
||||
static std::string functionCallKind(FunctionCallKind _kind);
|
||||
static std::string catchClauseKind(TryCatchClause::Kind _kind);
|
||||
static std::string literalTokenKind(Token _token);
|
||||
static std::string type(Expression const& _expression);
|
||||
static std::string type(VariableDeclaration const& _varDecl);
|
||||
|
||||
@@ -642,7 +642,8 @@ ASTPointer<TryCatchClause> ASTJsonImporter::createTryCatchClause(Json::Value con
|
||||
{
|
||||
return createASTNode<TryCatchClause>(
|
||||
_node,
|
||||
memberAsASTString(_node, "errorName"),
|
||||
tryCatchClauseKind(_node),
|
||||
nullOrCast<IdentifierPath>(member(_node, "errorName")),
|
||||
nullOrCast<ParameterList>(member(_node, "parameters")),
|
||||
convertJsonToASTNode<Block>(member(_node, "block"))
|
||||
);
|
||||
@@ -959,6 +960,24 @@ bool ASTJsonImporter::memberAsBool(Json::Value const& _node, string const& _name
|
||||
|
||||
// =========== JSON to definition helpers =======================
|
||||
|
||||
TryCatchClause::Kind ASTJsonImporter::tryCatchClauseKind(Json::Value const& _node)
|
||||
{
|
||||
astAssert(!member(_node, "kind").isNull(), "");
|
||||
if (_node["kind"].asString() == "success")
|
||||
return TryCatchClause::Kind::Success;
|
||||
else if (_node["kind"].asString() == "error")
|
||||
return TryCatchClause::Kind::Error;
|
||||
else if (_node["kind"].asString() == "panic")
|
||||
return TryCatchClause::Kind::Panic;
|
||||
else if (_node["kind"].asString() == "fallback")
|
||||
return TryCatchClause::Kind::Fallback;
|
||||
else if (_node["kind"].asString() == "userDefined")
|
||||
return TryCatchClause::Kind::UserDefined;
|
||||
else
|
||||
astAssert(false, "Unknown try catch clause kind");
|
||||
return {};
|
||||
}
|
||||
|
||||
ContractKind ASTJsonImporter::contractKind(Json::Value const& _node)
|
||||
{
|
||||
ContractKind kind;
|
||||
|
||||
@@ -144,6 +144,7 @@ private:
|
||||
Visibility visibility(Json::Value const& _node);
|
||||
StateMutability stateMutability(Json::Value const& _node);
|
||||
VariableDeclaration::Location location(Json::Value const& _node);
|
||||
TryCatchClause::Kind tryCatchClauseKind(Json::Value const& _node);
|
||||
ContractKind contractKind(Json::Value const& _node);
|
||||
Token literalTokenKind(Json::Value const& _node);
|
||||
Literal::SubDenomination subdenomination(Json::Value const& _node);
|
||||
|
||||
@@ -542,6 +542,8 @@ void TryCatchClause::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_errorName)
|
||||
m_errorName->accept(_visitor);
|
||||
if (m_parameters)
|
||||
m_parameters->accept(_visitor);
|
||||
m_block->accept(_visitor);
|
||||
@@ -553,6 +555,8 @@ void TryCatchClause::accept(ASTConstVisitor& _visitor) const
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_errorName)
|
||||
m_errorName->accept(_visitor);
|
||||
if (m_parameters)
|
||||
m_parameters->accept(_visitor);
|
||||
m_block->accept(_visitor);
|
||||
|
||||
Reference in New Issue
Block a user