From 46a6949b2e29bddacd523d96564492957faecc34 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Thu, 19 Sep 2019 16:49:31 +0200 Subject: [PATCH] eolian: auto-add composited interfaces into implements if needed The condition here is that the composited interface does not already appear in the inheritance tree of the given class. If it does, don't add. If it doesn't, add it to the class that specifies the composited block. --- src/lib/eolian/database_validate.c | 57 ++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/src/lib/eolian/database_validate.c b/src/lib/eolian/database_validate.c index cdbd699293..f13e0e82b7 100644 --- a/src/lib/eolian/database_validate.c +++ b/src/lib/eolian/database_validate.c @@ -865,6 +865,22 @@ _extend_impl(Eina_Hash *fs, Eolian_Implement *impl, Eina_Bool as_iface) return !st; } +/* fills a complete set of stuff implemented or inherited on a class + * this is used to check whether to auto-add composited interfaces into + * implemented/extended list + */ +static void +_db_fill_ihash(Eolian_Class *icl, Eina_Hash *icls) +{ + if (icl->parent) + _db_fill_ihash(icl->parent, icls); + Eina_List *l; + Eolian_Class *sicl; + EINA_LIST_FOREACH(icl->extends, l, sicl) + _db_fill_ihash(sicl, icls); + eina_hash_set(icls, &icl, icl); +} + static void _db_fill_callables(Eolian_Class *cl, Eolian_Class *icl, Eina_Hash *fs, Eina_Bool parent) { @@ -1084,13 +1100,6 @@ _db_swap_inherit(Eolian_Class *cl, Eina_Bool succ, Eina_Stringshare *in_cl, succ = EINA_FALSE; _eo_parser_log(&cl->base, "non-interface class '%s' in composite list", icl->base.name); } - else if (iface_only && !_get_impl_class(cl, icl->base.name)) - { - /* TODO: optimize check using a lookup hash later */ - succ = EINA_FALSE; - _eo_parser_log(&cl->base, "interface '%s' not found within the inheritance tree of '%s'", - icl->base.name, cl->base.name); - } else *out_cl = icl; eina_stringshare_del(in_cl); @@ -1183,6 +1192,7 @@ _db_fill_inherits(Validate_State *vals, Eolian_Class *cl, Eina_Hash *fhash, /* replace the composite list with real instances and initial-fill the hash */ il = cl->composite; cl->composite = NULL; + int ncomp = 0; EINA_LIST_FREE(il, inn) { Eolian_Class *out_cl = NULL; @@ -1190,6 +1200,8 @@ _db_fill_inherits(Validate_State *vals, Eolian_Class *cl, Eina_Hash *fhash, if (!succ) continue; cl->composite = eina_list_append(cl->composite, out_cl); + succ = _db_fill_inherits(vals, out_cl, fhash, errh); + ++ncomp; eina_hash_set(ch, &out_cl, out_cl); } @@ -1216,6 +1228,37 @@ _db_fill_inherits(Validate_State *vals, Eolian_Class *cl, Eina_Hash *fhash, eina_hash_add(fhash, &cl->base.name, cl); + /* there are more than zero of composites of its own */ + if (ncomp > 0) + { + /* this one stores what is already in inheritance tree */ + Eina_Hash *ih = eina_hash_pointer_new(NULL); + + /* fill a complete inheritance tree set */ + if (cl->parent) + _db_fill_ihash(cl->parent, ih); + + EINA_LIST_FOREACH(cl->extends, il, icl) + _db_fill_ihash(icl, ih); + + /* go through only the explicitly specified composite list part, as the + * rest was to be handled in parents already... add what hasn't been + * explicitly implemented so far into implements/extends + */ + EINA_LIST_FOREACH(cl->composite, il, icl) + { + /* ran out of classes */ + if (!ncomp--) + break; + /* found in inheritance tree, skip */ + if (eina_hash_find(ih, &icl)) + continue; + cl->extends = eina_list_append(cl->extends, icl); + } + + eina_hash_free(ih); + } + /* stores mappings from function to Impl_Status */ Eina_Hash *fh = eina_hash_pointer_new(NULL);