Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Improve abi-generator #3970

Merged
merged 1 commit into from
Jun 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contracts/eosio.token/eosio.token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @copyright defined in eos/LICENSE.txt
*/

#include <eosio.token/eosio.token.hpp>
#include "eosio.token.hpp"

namespace eosio {

Expand Down
71 changes: 26 additions & 45 deletions libraries/abi_generator/abi_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ string abi_generator::translate_type(const string& type_name) {
else if (type_name == "long" || type_name == "int32_t") built_in_type = "int32";
else if (type_name == "short" || type_name == "int16_t") built_in_type = "int16";
else if (type_name == "char" || type_name == "int8_t") built_in_type = "int8";
else if (type_name == "double") built_in_type = "float64";
else {
static auto types = eosio::chain::common_type_defs();
auto itr = std::find_if( types.begin(), types.end(),
Expand All @@ -100,9 +101,6 @@ bool abi_generator::inspect_type_methods_for_actions(const Decl* decl) { try {
const auto* rec_decl = dyn_cast<CXXRecordDecl>(decl);
if(rec_decl == nullptr) return false;

if( rec_decl->getName().str() != target_contract )
return false;

const auto* type = rec_decl->getTypeForDecl();
ABI_ASSERT(type != nullptr);

Expand All @@ -112,9 +110,24 @@ bool abi_generator::inspect_type_methods_for_actions(const Decl* decl) { try {

auto method_name = method->getNameAsString();

// Try to get "action" annotation from method comment
bool raw_comment_is_action = false;
const RawComment* raw_comment = ast_context->getRawCommentForDeclNoCache(method);
if(raw_comment != nullptr) {
SourceManager& source_manager = ast_context->getSourceManager();
string raw_text = raw_comment->getRawText(source_manager);
regex r(R"(@abi (action)((?: [a-z0-9]+)*))");
smatch smatch;
regex_search(raw_text, smatch, r);
raw_comment_is_action = smatch.size() == 3;
}

if( std::find(target_actions.begin(), target_actions.end(), method_name) == target_actions.end() )
// Check if current method is listed the EOSIO_ABI macro
bool is_action_from_macro = rec_decl->getName().str() == target_contract && std::find(target_actions.begin(), target_actions.end(), method_name) != target_actions.end();

if(!raw_comment_is_action && !is_action_from_macro) {
return;
}

ABI_ASSERT(find_struct(method_name) == nullptr, "action already exists ${method_name}", ("method_name",method_name));

Expand Down Expand Up @@ -189,18 +202,11 @@ void abi_generator::handle_decl(const Decl* decl) { try {
return;
}

// If EOSIO_ABI macro was found, check if the current declaration
// is of the type specified in the macro and export their methods (actions).
bool type_has_actions = false;
if( target_contract.size() ) {
type_has_actions = inspect_type_methods_for_actions(decl);
}

// The current Decl was the type referenced in EOSIO_ABI macro
// Check if the current declaration has actions (EOSIO_ABI, or explicit)
bool type_has_actions = inspect_type_methods_for_actions(decl);
if( type_has_actions ) return;

// The current Decl was not the type referenced in EOSIO_ABI macro
// so we try to see if it has comments attached to the declaration
// The current Decl doesn't have actions
const RawComment* raw_comment = ast_context->getRawCommentForDeclNoCache(decl);
if(raw_comment == nullptr) {
return;
Expand Down Expand Up @@ -275,9 +281,10 @@ void abi_generator::handle_decl(const Decl* decl) { try {
table.name = params[0];
}

if(params.size() >= 2)
if(params.size() >= 2) {
table.index_type = params[1];
else { try {
ABI_ASSERT(table.index_type == "i64", "Only i64 index is supported. ${index_type}",("index_type",table.index_type));
} else { try {
guess_index_type(table, *s);
} FC_CAPTURE_AND_RETHROW( (type_name) ) }

Expand Down Expand Up @@ -324,34 +331,14 @@ void abi_generator::get_all_fields(const struct_def& s, vector<field_def>& field
}
}

bool abi_generator::is_i64i64i64_index(const vector<field_def>& fields) {
return fields.size() >= 3 && is_64bit(fields[0].type) && is_64bit(fields[1].type) && is_64bit(fields[2].type);
}

bool abi_generator::is_i64_index(const vector<field_def>& fields) {
return fields.size() >= 1 && is_64bit(fields[0].type);
}

bool abi_generator::is_i128i128_index(const vector<field_def>& fields) {
return fields.size() >= 2 && is_128bit(fields[0].type) && is_128bit(fields[1].type);
}

bool abi_generator::is_str_index(const vector<field_def>& fields) {
return fields.size() == 2 && is_string(fields[0].type);
}

void abi_generator::guess_index_type(table_def& table, const struct_def s) {

vector<field_def> fields;
get_all_fields(s, fields);

if( is_str_index(fields) ) {
table.index_type = "str";
} else if ( is_i64i64i64_index(fields) ) {
table.index_type = "i64i64i64";
} else if( is_i128i128_index(fields) ) {
table.index_type = "i128i128";
} else if( is_i64_index(fields) ) {
if( is_i64_index(fields) ) {
table.index_type = "i64";
} else {
ABI_ASSERT(false, "Unable to guess index type");
Expand All @@ -363,8 +350,7 @@ void abi_generator::guess_key_names(table_def& table, const struct_def s) {
vector<field_def> fields;
get_all_fields(s, fields);

if( table.index_type == "i64i64i64" || table.index_type == "i128i128"
|| table.index_type == "i64") {
if( table.index_type == "i64") {

table.key_names.clear();
table.key_types.clear();
Expand All @@ -376,18 +362,13 @@ void abi_generator::guess_key_names(table_def& table, const struct_def s) {
table.key_types.emplace_back(f.type);
key_size += type_size[f.type]/8;

if((table.index_type == "i64i64i64" && key_size >= sizeof(uint64_t)*3) ||
(table.index_type == "i64" && key_size >= sizeof(uint64_t)) ||
(table.index_type == "i128i128" && key_size >= sizeof(__int128)*2)) {
if(table.index_type == "i64" && key_size >= sizeof(uint64_t)) {
valid_key = true;
break;
}
}

ABI_ASSERT(valid_key, "Unable to guess key names");
} else if( table.index_type == "str" && is_str_index(fields) ) {
table.key_names = vector<field_name>{fields[0].name};
table.key_types = vector<type_name>{fields[0].type};
} else {
ABI_ASSERT(false, "Unable to guess key names");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,25 @@ namespace eosio {
callback_handler(CompilerInstance& compiler_instance, find_eosio_abi_macro_action& act)
: compiler_instance(compiler_instance), act(act) {}

string remove_namespace(const string& full_name) {
int i = full_name.size();
int on_spec = 0;
int colons = 0;
while( --i >= 0 ) {
if( full_name[i] == '>' ) {
++on_spec; colons=0;
} else if( full_name[i] == '<' ) {
--on_spec; colons=0;
} else if( full_name[i] == ':' && !on_spec) {
if (++colons == 2)
return full_name.substr(i+2);
} else {
colons = 0;
}
}
return full_name;
}

void MacroExpands (const Token &token, const MacroDefinition &md, SourceRange range, const MacroArgs *args) override {

auto* id = token.getIdentifierInfo();
Expand All @@ -366,7 +385,7 @@ namespace eosio {
auto res = regex_search(macrostr, smatch, r);
ABI_ASSERT( res );

act.contract = smatch[1].str();
act.contract = remove_namespace(smatch[1].str());

auto actions_str = smatch[2].str();
boost::trim(actions_str);
Expand Down
Loading