diff --git a/src/bin/edje/edje_cc.c b/src/bin/edje/edje_cc.c index df2a877c5a..a4b6947c4c 100644 --- a/src/bin/edje/edje_cc.c +++ b/src/bin/edje/edje_cc.c @@ -49,6 +49,7 @@ int annotate = 0; int no_etc1 = 0; int no_etc2 = 0; int beta = 0; +Eina_Bool namespace_verify; unsigned int max_open_files; @@ -130,6 +131,7 @@ main_help(void) "-fastdecomp Use a faster decompression algorithm (LZ4HC) (mutually exclusive with -fastcomp)\n" "-threads Compile the edje file using multiple parallel threads (by default)\n" "-nothreads Compile the edje file using only the main loop\n" + "-N Use the first segment of each group name as a namespace to verify parts/signals\n" "-V [--version] show program version\n" , progname); } @@ -326,6 +328,10 @@ main(int argc, char **argv) { beta = 1; } + else if (!strcmp(argv[i], "-N")) + { + namespace_verify = 1; + } else if (!file_in) file_in = argv[i]; else if (!file_out) diff --git a/src/bin/edje/edje_cc.h b/src/bin/edje/edje_cc.h index 6208d139d1..aec77a4587 100644 --- a/src/bin/edje/edje_cc.h +++ b/src/bin/edje/edje_cc.h @@ -356,4 +356,5 @@ extern int had_quote; extern unsigned int max_open_files; extern Eina_Array *requires; +extern Eina_Bool namespace_verify; #endif diff --git a/src/bin/edje/edje_cc_out.c b/src/bin/edje/edje_cc_out.c index 00275cce4f..80331b1040 100644 --- a/src/bin/edje/edje_cc_out.c +++ b/src/bin/edje/edje_cc_out.c @@ -236,6 +236,7 @@ static Eina_List *model_lookups = NULL; static Eina_Hash *part_dest_lookup = NULL; static Eina_Hash *part_pc_dest_lookup = NULL; +static Eina_Hash *groups_sourced = NULL; static Eet_File *cur_ef; static int image_num; @@ -587,6 +588,35 @@ check_state(Edje_Part_Collection *pc, Edje_Part *ep, Edje_Part_Description_Commo check_nameless_state(pc, ep, ed, ef); } +static void +_part_namespace_verify(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef, Eina_Bool ns_required) +{ + char buf[1024], *p; + size_t len; + Edje_Part_Collection_Directory_Entry *de; + + if (!namespace_verify) return; + /* this is from a group used as a source, either GROUP or TEXTBLOCK + * namespacing not required + */ + if (eina_hash_find(groups_sourced, pc->name)) return; + + de = eina_hash_find(edje_collections_lookup, &pc->id); + + p = strchr(de->entry, '/'); + if (!p) return; + + len = p - de->entry; + if (eina_strlcpy(buf, de->entry, len + 1) >= sizeof(buf)) return; + + p = strchr(ep->name, '.'); + /* ignore part types without required namespacing or without '.' in name */ + if ((!ns_required) && (!p)) return; + + if (strncmp(ep->name, buf, len)) + error_and_abort(ef, "Part '%s' from group %s is not properly namespaced (should begin with '%s.')!", ep->name, de->entry, buf); +} + static void check_part(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef) { @@ -621,6 +651,21 @@ check_part(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef) check_text_part_desc(pc, ep, (Edje_Part_Description_Text *)ep->other.desc[i], ef); } + switch (ep->type) + { + case EDJE_PART_TYPE_BOX: + case EDJE_PART_TYPE_TABLE: + case EDJE_PART_TYPE_SWALLOW: + _part_namespace_verify(pc, ep, ef, 1); + break; + case EDJE_PART_TYPE_TEXT: + case EDJE_PART_TYPE_TEXTBLOCK: + case EDJE_PART_TYPE_SPACER: + _part_namespace_verify(pc, ep, ef, 0); + break; + default: break; + } + /* FIXME: When smart masks are supported, remove this check */ if (ep->clip_to_id != -1 && (pc->parts[ep->clip_to_id]->type != EDJE_PART_TYPE_RECTANGLE) && @@ -630,6 +675,33 @@ check_part(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef) pc->id, pc->parts[ep->clip_to_id]->name); } +static void +_program_signal_namespace_verify(Edje_Part_Collection *pc, Eet_File *ef, const char *sig, const char *src) +{ + char buf[1024], *p; + size_t len; + Edje_Part_Collection_Directory_Entry *de; + + if (!namespace_verify) return; + /* this is from a group used as a source, either GROUP or TEXTBLOCK + * namespacing not required + */ + if (eina_hash_find(groups_sourced, pc->name)) return; + + /* ignore propagation to GROUP parts */ + if (strchr(sig, ':')) return; + + de = eina_hash_find(edje_collections_lookup, &pc->id); + + p = strchr(de->entry, '/'); + if (!p) return; + len = p - de->entry; + if (eina_strlcpy(buf, de->entry, len + 1) >= sizeof(buf)) return; + + if (strncmp(sig, buf, len)) + error_and_abort(ef, "SIGNAL_EMIT (%s:%s) does not match group namespace (%s)!", sig, src, de->entry); +} + static void check_program(Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef) { @@ -659,6 +731,11 @@ check_program(Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef) camera_id = i; } + if ((!ep->targets) && (ep->action == EDJE_ACTION_TYPE_SIGNAL_EMIT)) + { + _program_signal_namespace_verify(pc, ef, ep->state, ep->state2); + } + EINA_LIST_FOREACH(ep->targets, l, et) { if (((ep->action == EDJE_ACTION_TYPE_STATE_SET) || @@ -3885,6 +3962,7 @@ data_process_lookups(void) free(program); } + groups_sourced = eina_hash_string_superfast_new(NULL); EINA_LIST_FREE(group_lookups, group) { Edje_Part_Collection_Directory_Entry *de; @@ -3919,6 +3997,7 @@ data_process_lookups(void) exit(-1); } + eina_hash_add(groups_sourced, group->name, (void*)1); free_group: free(group->name); free(group);