Merge pull request #353 from AntelopeIO/call_abi
SC: Generate `call` and `call_results` sections in ABI files for sync calls and bump ABI version to `1.3`
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"antelope-spring-dev":{
|
||||
"target":"return_status",
|
||||
"target":"sync_call",
|
||||
"prerelease":false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,27 +126,6 @@ BOOST_AUTO_TEST_CASE(void_func_test) { try {
|
||||
check(trx_trace);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify a function tagged as both `action` and `call` works
|
||||
BOOST_AUTO_TEST_CASE(mixed_action_call_tags_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
// `sum` in `callee` contract is tagged as `action` and `call`
|
||||
|
||||
// Make sure we can make a sync call to `sum` (`mulparamtest` in `caller` does
|
||||
// a sync call to `sum`)
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hstmulprmtst"_n, "caller"_n, {}));
|
||||
|
||||
// Make sure we can push an action using `sum`.
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("callee"_n, "sum"_n, "callee"_n,
|
||||
mvo()
|
||||
("a", 1)
|
||||
("b", 2)
|
||||
("c", 3)));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify the receiver contract with only one sync call function works
|
||||
// (for testing the sync_call entry point dispatcher)
|
||||
BOOST_AUTO_TEST_CASE(single_function_test) { try {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": ["--abi-version=1.2"],
|
||||
"expected" : {
|
||||
"abi-file" : "action_results_test.abi"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests": [
|
||||
{
|
||||
"compile_flags": ["--abi-version=1.2"],
|
||||
"expected": {
|
||||
"abi-file": "aliased_type_variant_template_arg.abi"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": ["--abi-version=1.2"],
|
||||
"expected" : {
|
||||
"abi-file" : "nested_container.abi"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags" : ["-R={cwd}"],
|
||||
"compile_flags" : ["--abi-version=1.2", "-R={cwd}"],
|
||||
"expected" : {
|
||||
"abi-file" : "ricardian_contract_test.abi"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": ["--abi-version=1.2"],
|
||||
"expected" : {
|
||||
"abi-file" : "singleton_contract.abi"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests": [
|
||||
{
|
||||
"compile_flags": ["--abi-version=1.2"],
|
||||
"expected": {
|
||||
"abi-file": "struct_base_typedefd.abi"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"____comment": "This file was generated with eosio-abigen. DO NOT EDIT ",
|
||||
"version": "eosio::abi/1.3",
|
||||
"types": [],
|
||||
"structs": [
|
||||
{
|
||||
"name": "call_data_header",
|
||||
"base": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "version",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "func_name",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "noparam",
|
||||
"base": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "header",
|
||||
"type": "call_data_header"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sum",
|
||||
"base": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "header",
|
||||
"type": "call_data_header"
|
||||
},
|
||||
{
|
||||
"name": "a",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "c",
|
||||
"type": "uint32"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "voidfunc",
|
||||
"base": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "header",
|
||||
"type": "call_data_header"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "withparam",
|
||||
"base": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "header",
|
||||
"type": "call_data_header"
|
||||
},
|
||||
{
|
||||
"name": "in",
|
||||
"type": "uint32"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"actions": [],
|
||||
"tables": [],
|
||||
"ricardian_clauses": [],
|
||||
"variants": [],
|
||||
"action_results": [],
|
||||
"calls": [
|
||||
{
|
||||
"name": "noparam",
|
||||
"type": "noparam"
|
||||
},
|
||||
{
|
||||
"name": "sum",
|
||||
"type": "sum"
|
||||
},
|
||||
{
|
||||
"name": "voidfunc",
|
||||
"type": "voidfunc"
|
||||
},
|
||||
{
|
||||
"name": "withparam",
|
||||
"type": "withparam"
|
||||
}
|
||||
],
|
||||
"call_results": [
|
||||
{
|
||||
"name": "noparam",
|
||||
"result_type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "sum",
|
||||
"result_type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "withparam",
|
||||
"result_type": "uint32"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
class [[eosio::contract]] sync_call_test : public eosio::contract {
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t noparam() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t withparam(uint32_t in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
void voidfunc() {
|
||||
int i = 10;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t sum(uint32_t a, uint32_t b, uint32_t c) {
|
||||
return a + b + c;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"expected" : {
|
||||
"abi-file" : "sync_call_test.abi"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": ["--abi-version=1.2"],
|
||||
"expected" : {
|
||||
"abi-file" : "tagged_number_test.abi"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": ["--abi-version=1.2"],
|
||||
"expected" : {
|
||||
"abi-file" : "using_std_array.abi"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
// Test the validation that action and call tags cannot be mixed.
|
||||
|
||||
class [[eosio::contract]] invalid_call_tags : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::action, eosio::call]]
|
||||
uint32_t act1() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[eosio::call, eosio::action]]
|
||||
uint32_t act2() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"exit-code": 255,
|
||||
"stderr": "codegen error (cannot be tagged as both action and call)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
// Test the validation that action and call tags cannot be mixed.
|
||||
|
||||
class [[eosio::contract]] invalid_call_tags : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::action]]
|
||||
uint32_t act();
|
||||
};
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t invalid_call_tags::act() {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"exit-code": 255,
|
||||
"stderr": "codegen error (cannot be tagged as both action and call)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
// Test the validation that action and call tags cannot be mixed.
|
||||
|
||||
class [[eosio::contract]] invalid_call_tags : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t act();
|
||||
};
|
||||
|
||||
[[eosio::action]]
|
||||
uint32_t invalid_call_tags::act() {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"exit-code": 255,
|
||||
"stderr": "codegen error (cannot be tagged as both action and call)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -16,7 +16,7 @@ void sync_call_callee::voidfunc() {
|
||||
eosio::print("I am a void function");
|
||||
}
|
||||
|
||||
[[eosio::action, eosio::call]]
|
||||
[[eosio::call]]
|
||||
uint32_t sync_call_callee::sum(uint32_t a, uint32_t b, uint32_t c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
[[eosio::call]]
|
||||
void voidfunc();
|
||||
|
||||
[[eosio::action, eosio::call]]
|
||||
[[eosio::call]]
|
||||
uint32_t sum(uint32_t a, uint32_t b, uint32_t c);
|
||||
|
||||
// pass in a struct and return it
|
||||
|
||||
@@ -6,7 +6,7 @@ class [[eosio::contract]] sync_call_single_func : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::action, eosio::call]]
|
||||
[[eosio::call]]
|
||||
uint32_t getten() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@@ -948,9 +948,13 @@ static Options CreateOptions(bool add_defaults=true) {
|
||||
|
||||
#endif
|
||||
|
||||
// 1.2 -- action results
|
||||
// 1.3 -- sync calls, bitset type, action and sync call names in C++
|
||||
// identifier format
|
||||
|
||||
/* TODO add some way of defaulting these to the current highest version */
|
||||
int abi_version_major = 1;
|
||||
int abi_version_minor = 2;
|
||||
int abi_version_minor = 3;
|
||||
|
||||
if (!abi_version_opt.empty()) {
|
||||
abi_version_major = std::stoi(abi_version_opt);
|
||||
|
||||
@@ -30,6 +30,12 @@ struct abi_action {
|
||||
bool operator<(const abi_action& s) const { return name < s.name; }
|
||||
};
|
||||
|
||||
struct abi_call {
|
||||
std::string name;
|
||||
std::string type;
|
||||
bool operator<(const abi_call& s) const { return name < s.name; }
|
||||
};
|
||||
|
||||
struct abi_table {
|
||||
std::string name;
|
||||
std::string type;
|
||||
@@ -61,6 +67,17 @@ struct abi_action_result {
|
||||
bool operator<(const abi_action_result& ar) const { return name < ar.name; }
|
||||
};
|
||||
|
||||
struct abi_call_result {
|
||||
std::string name;
|
||||
std::string type;
|
||||
bool operator<(const abi_call_result& ar) const { return name < ar.name; }
|
||||
};
|
||||
|
||||
// The version when sync call was first introduced.
|
||||
constexpr int abi_call_version_major = 1;
|
||||
constexpr int abi_call_version_minor = 3;
|
||||
constexpr int abi_call_version = abi_call_version_major * 10 + abi_call_version_minor;
|
||||
|
||||
/// From eosio libraries/chain/include/eosio/chain/abi_def.hpp
|
||||
struct abi {
|
||||
int version_major = 1;
|
||||
@@ -69,11 +86,13 @@ struct abi {
|
||||
std::set<abi_struct> structs;
|
||||
std::set<abi_typedef> typedefs;
|
||||
std::set<abi_action> actions;
|
||||
std::set<abi_call> calls;
|
||||
std::set<abi_table> tables;
|
||||
std::set<abi_variant> variants;
|
||||
std::vector<abi_ricardian_clause_pair> ricardian_clauses;
|
||||
std::vector<abi_error_message> error_messages;
|
||||
std::set<abi_action_result> action_results;
|
||||
std::set<abi_call_result> call_results;
|
||||
};
|
||||
|
||||
inline void dump( const abi& abi ) {
|
||||
|
||||
@@ -131,6 +131,43 @@ namespace eosio { namespace cdt {
|
||||
}
|
||||
}
|
||||
|
||||
void add_call( const clang::CXXRecordDecl* decl ) {
|
||||
abi_call ret;
|
||||
auto call_name = decl->getEosioCallAttr()->getName();
|
||||
|
||||
if (call_name.empty()) {
|
||||
validate_name(decl->getName().str(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); });
|
||||
ret.name = decl->getName().str();
|
||||
}
|
||||
else {
|
||||
validate_name( call_name.str(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); });
|
||||
ret.name = call_name.str();
|
||||
}
|
||||
ret.type = decl->getName().str();
|
||||
_abi.calls.insert(ret);
|
||||
}
|
||||
|
||||
void add_call( const clang::CXXMethodDecl* decl ) {
|
||||
abi_call ret;
|
||||
|
||||
auto call_name = decl->getEosioCallAttr()->getName();
|
||||
|
||||
if (call_name.empty()) {
|
||||
validate_name( decl->getNameAsString(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); } );
|
||||
ret.name = decl->getNameAsString();
|
||||
}
|
||||
else {
|
||||
validate_name( call_name.str(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); } );
|
||||
ret.name = call_name.str();
|
||||
}
|
||||
ret.type = decl->getNameAsString();
|
||||
_abi.calls.insert(ret);
|
||||
if (translate_type(decl->getReturnType()) != "void") {
|
||||
add_type(decl->getReturnType());
|
||||
_abi.call_results.insert({get_call_name(decl), translate_type(decl->getReturnType())});
|
||||
}
|
||||
}
|
||||
|
||||
void add_tuple(const clang::QualType& type) {
|
||||
auto pt = llvm::dyn_cast<clang::ElaboratedType>(type.getTypePtr());
|
||||
auto tst = llvm::dyn_cast<clang::TemplateSpecializationType>((pt) ? pt->desugar().getTypePtr() : type.getTypePtr());
|
||||
@@ -216,6 +253,21 @@ namespace eosio { namespace cdt {
|
||||
void add_struct( const clang::CXXMethodDecl* decl ) {
|
||||
abi_struct new_struct;
|
||||
new_struct.name = decl->getNameAsString();
|
||||
|
||||
if (decl->isEosioCall()) {
|
||||
// Add call_data_header definition to structs set
|
||||
abi_struct data_header;
|
||||
data_header.name = "call_data_header";
|
||||
if (_abi.structs.count(data_header) == 0) {
|
||||
data_header.fields.push_back({"version", "uint32"});
|
||||
data_header.fields.push_back({"func_name", "uint64"});
|
||||
_abi.structs.insert(data_header);
|
||||
}
|
||||
|
||||
// Add header field as the first field to the method struct
|
||||
new_struct.fields.push_back({"header", "call_data_header"});
|
||||
}
|
||||
|
||||
for (auto param : decl->parameters() ) {
|
||||
auto param_type = param->getType().getNonReferenceType().getUnqualifiedType();
|
||||
new_struct.fields.push_back({param->getNameAsString(), get_type(param_type)});
|
||||
@@ -551,6 +603,13 @@ namespace eosio { namespace cdt {
|
||||
return o;
|
||||
}
|
||||
|
||||
ojson call_to_json( const abi_call& c ) {
|
||||
ojson o;
|
||||
o["name"] = c.name;
|
||||
o["type"] = c.type;
|
||||
return o;
|
||||
}
|
||||
|
||||
ojson clause_to_json( const abi_ricardian_clause_pair& clause ) {
|
||||
ojson o;
|
||||
o["id"] = clause.id;
|
||||
@@ -575,6 +634,13 @@ namespace eosio { namespace cdt {
|
||||
return o;
|
||||
}
|
||||
|
||||
ojson call_result_to_json( const abi_call_result& result ) {
|
||||
ojson o;
|
||||
o["name"] = result.name;
|
||||
o["result_type"] = result.type;
|
||||
return o;
|
||||
}
|
||||
|
||||
bool is_empty() {
|
||||
std::set<abi_table> set_of_tables;
|
||||
for ( auto t : ctables ) {
|
||||
@@ -593,7 +659,7 @@ namespace eosio { namespace cdt {
|
||||
set_of_tables.insert(t);
|
||||
}
|
||||
|
||||
return _abi.structs.empty() && _abi.typedefs.empty() && _abi.actions.empty() && set_of_tables.empty() && _abi.ricardian_clauses.empty() && _abi.variants.empty();
|
||||
return _abi.structs.empty() && _abi.typedefs.empty() && _abi.actions.empty() && _abi.calls.empty() && set_of_tables.empty() && _abi.ricardian_clauses.empty() && _abi.variants.empty();
|
||||
}
|
||||
|
||||
ojson to_json() {
|
||||
@@ -658,6 +724,10 @@ namespace eosio { namespace cdt {
|
||||
if (as.name == _translate_type(a.type))
|
||||
return true;
|
||||
}
|
||||
for ( auto a : _abi.calls ) {
|
||||
if (as.name == _translate_type(a.type))
|
||||
return true;
|
||||
}
|
||||
for( auto t : set_of_tables ) {
|
||||
if (as.name == _translate_type(t.type))
|
||||
return true;
|
||||
@@ -670,6 +740,10 @@ namespace eosio { namespace cdt {
|
||||
if (as.name == _translate_type(ar.type))
|
||||
return true;
|
||||
}
|
||||
for( auto ar : _abi.call_results ) {
|
||||
if (as.name == _translate_type(ar.type))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -695,6 +769,9 @@ namespace eosio { namespace cdt {
|
||||
for ( auto a : _abi.actions )
|
||||
if ( a.type == td.new_type_name )
|
||||
return true;
|
||||
for ( auto a : _abi.calls )
|
||||
if ( a.type == td.new_type_name )
|
||||
return true;
|
||||
for ( auto _td : _abi.typedefs )
|
||||
if ( remove_suffix(_td.type) == td.new_type_name )
|
||||
return true;
|
||||
@@ -702,6 +779,9 @@ namespace eosio { namespace cdt {
|
||||
if ( ar.type == td.new_type_name )
|
||||
return true;
|
||||
}
|
||||
for ( auto ar : _abi.call_results )
|
||||
if ( ar.type == td.new_type_name )
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -719,6 +799,18 @@ namespace eosio { namespace cdt {
|
||||
for ( auto a : _abi.actions ) {
|
||||
o["actions"].push_back(action_to_json( a ));
|
||||
}
|
||||
if (_abi.version_major > abi_call_version_major ||
|
||||
_abi.version_major == abi_call_version_major && _abi.version_minor >= abi_call_version_minor) { // sync call
|
||||
o["calls"] = ojson::array();
|
||||
for ( auto a : _abi.calls ) {
|
||||
o["calls"].push_back(call_to_json( a ));
|
||||
}
|
||||
|
||||
o["call_results"] = ojson::array();
|
||||
for ( auto ar : _abi.call_results ) {
|
||||
o["call_results"].push_back(call_result_to_json( ar ));
|
||||
}
|
||||
}
|
||||
o["tables"] = ojson::array();
|
||||
for ( auto t : set_of_tables ) {
|
||||
o["tables"].push_back(table_to_json( t ));
|
||||
@@ -778,6 +870,14 @@ namespace eosio { namespace cdt {
|
||||
ag.add_type( param->getType() );
|
||||
}
|
||||
}
|
||||
|
||||
if (decl->isEosioCall() && ag.is_eosio_contract(decl, ag.get_contract_name())) {
|
||||
ag.add_struct(decl);
|
||||
ag.add_call(decl);
|
||||
for (auto param : decl->parameters()) {
|
||||
ag.add_type( param->getType() );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) {
|
||||
@@ -786,10 +886,12 @@ namespace eosio { namespace cdt {
|
||||
ag.add_contracts(ag.parse_contracts());
|
||||
has_added_clauses = true;
|
||||
}
|
||||
if ((decl->isEosioAction() || decl->isEosioTable()) && ag.is_eosio_contract(decl, ag.get_contract_name())) {
|
||||
if ((decl->isEosioAction() || decl->isEosioCall() || decl->isEosioTable()) && ag.is_eosio_contract(decl, ag.get_contract_name())) {
|
||||
ag.add_struct(decl);
|
||||
if (decl->isEosioAction())
|
||||
ag.add_action(decl);
|
||||
if (decl->isEosioCall())
|
||||
ag.add_call(decl);
|
||||
if (decl->isEosioTable())
|
||||
ag.add_table(decl);
|
||||
for (auto field : decl->fields()) {
|
||||
|
||||
@@ -37,6 +37,10 @@ class ABIMerger {
|
||||
if (std::stod(vers.substr(vers.size()-3))*10 >= 12) {
|
||||
ret["action_results"] = merge_action_results(other);
|
||||
}
|
||||
if (std::stod(vers.substr(vers.size()-3))*10 >= abi_call_version) {
|
||||
ret["calls"] = merge_calls(other);
|
||||
ret["call_results"] = merge_call_results(other);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
@@ -82,6 +86,10 @@ class ABIMerger {
|
||||
a["type"] == b["type"];
|
||||
}
|
||||
|
||||
static bool call_is_same(ojson a, ojson b) {
|
||||
return a["name"] == b["name"] &&
|
||||
a["type"] == b["type"];
|
||||
}
|
||||
|
||||
static bool variant_is_same(ojson a, ojson b) {
|
||||
for (auto tya : a["types"].array_range()) {
|
||||
@@ -114,6 +122,11 @@ class ABIMerger {
|
||||
a["result_type"] == b["result_type"];
|
||||
}
|
||||
|
||||
static bool call_result_is_same(ojson a, ojson b) {
|
||||
return a["name"] == b["name"] &&
|
||||
a["result_type"] == b["result_type"];
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void add_object_to_array(ojson& ret, ojson a, ojson b, std::string type, std::string id, F&& is_same_func) {
|
||||
for (auto obj_a : a[type].array_range()) {
|
||||
@@ -181,6 +194,12 @@ class ABIMerger {
|
||||
return acts;
|
||||
}
|
||||
|
||||
ojson merge_calls(ojson b) {
|
||||
ojson calls = ojson::array();
|
||||
add_object_to_array(calls, abi, b, "calls", "name", call_is_same);
|
||||
return calls;
|
||||
}
|
||||
|
||||
ojson merge_tables(ojson b) {
|
||||
ojson tabs = ojson::array();
|
||||
add_object_to_array(tabs, abi, b, "tables", "name", table_is_same);
|
||||
@@ -199,6 +218,12 @@ class ABIMerger {
|
||||
return res;
|
||||
}
|
||||
|
||||
ojson merge_call_results(ojson b) {
|
||||
ojson res = ojson::array();
|
||||
add_object_to_array(res, abi, b, "call_results", "name", call_result_is_same);
|
||||
return res;
|
||||
}
|
||||
|
||||
ojson abi;
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
@@ -317,6 +317,11 @@ namespace eosio { namespace cdt {
|
||||
static std::set<std::string> _action_set; //used for validations
|
||||
static std::set<std::string> _notify_set; //used for validations
|
||||
static std::set<std::string> _call_set; //used for validations
|
||||
|
||||
if (decl->isEosioAction() && decl->isEosioCall()) {
|
||||
CDT_ERROR("codegen_error", decl->getLocation(), "cannot be tagged as both action and call");
|
||||
}
|
||||
|
||||
if (decl->isEosioAction()) {
|
||||
name = generation_utils::get_action_name(decl);
|
||||
validate_name(name, [&](auto s) {
|
||||
@@ -363,10 +368,7 @@ namespace eosio { namespace cdt {
|
||||
create_notify_dispatch(decl);
|
||||
cg.notify_handlers.insert(full_notify_name); // insert the method action, so we don't create the dispatcher twice
|
||||
}
|
||||
}
|
||||
|
||||
// We allow a method to be tagged as both `action` and `call`
|
||||
if (decl->isEosioCall()) {
|
||||
} else if (decl->isEosioCall()) {
|
||||
name = generation_utils::get_call_name(decl);
|
||||
validate_name(name, [&](auto s) {
|
||||
CDT_ERROR("codegen_error", decl->getLocation(), std::string("call name (")+s+") is not a valid eosio name");
|
||||
|
||||
@@ -192,12 +192,17 @@ struct generation_utils {
|
||||
return decl->getNameAsString();
|
||||
}
|
||||
static inline std::string get_call_name( const clang::CXXMethodDecl* decl ) {
|
||||
std::string call_name = "";
|
||||
auto tmp = decl->getEosioCallAttr()->getName();
|
||||
if (!tmp.empty())
|
||||
return tmp;
|
||||
return decl->getNameAsString();
|
||||
}
|
||||
static inline std::string get_call_name( const clang::CXXRecordDecl* decl ) {
|
||||
auto tmp = decl->getEosioCallAttr()->getName();
|
||||
if (!tmp.empty())
|
||||
return tmp;
|
||||
return decl->getName();
|
||||
}
|
||||
static inline std::string get_notify_pair( const clang::CXXMethodDecl* decl ) {
|
||||
std::string notify_pair = "";
|
||||
auto tmp = decl->getEosioNotifyAttr()->getName();
|
||||
|
||||
Reference in New Issue
Block a user