From 30bc1d285b871efe54a65b2c58cccea20b168817 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Wed, 10 Feb 2016 16:04:01 +0000 Subject: [PATCH] eolian: allow silencing of type errors in validation This allows generators to silence type errors in validation in order to reduce duplicate error messages when generating multiple files. Also adjusted the C generator to only emit type errors when generating Eo header files. @feature --- src/Makefile_Eolian_Helper.am | 4 +- src/bin/eolian/main.c | 6 +- src/bin/eolian_cxx/eolian_cxx.cc | 2 +- src/bindings/luajit/eolian.lua | 6 +- src/lib/eolian/Eolian.h | 3 +- src/lib/eolian/database_validate.c | 167 ++++++++++++++++------------- src/lib/eolian/eolian_database.c | 4 +- src/lib/eolian/eolian_database.h | 2 +- 8 files changed, 110 insertions(+), 84 deletions(-) diff --git a/src/Makefile_Eolian_Helper.am b/src/Makefile_Eolian_Helper.am index 5cd5e380c9..f9c2066217 100644 --- a/src/Makefile_Eolian_Helper.am +++ b/src/Makefile_Eolian_Helper.am @@ -15,7 +15,7 @@ SUFFIXES = .eo .eo.c .eo.h .eo.legacy.h .eot .eot.h %.eo.c: %.eo ${_EOLIAN_GEN_DEP} $(AM_V_EOL) \ $(MKDIR_P) $(dir $@); \ - $(EOLIAN_GEN) --legacy $(EOLIAN_FLAGS) --gc -o $@ $< + $(EOLIAN_GEN) --legacy --silent-types $(EOLIAN_FLAGS) --gc -o $@ $< %.eo.h: %.eo ${_EOLIAN_GEN_DEP} $(AM_V_EOL) \ @@ -30,6 +30,6 @@ SUFFIXES = .eo .eo.c .eo.h .eo.legacy.h .eot .eot.h %.eo.legacy.h: %.eo ${_EOLIAN_GEN_DEP} $(AM_V_EOL) \ $(MKDIR_P) $(dir $@); \ - $(EOLIAN_GEN) --legacy $(EOLIAN_FLAGS) --gh -o $@ $< + $(EOLIAN_GEN) --legacy --silent-types $(EOLIAN_FLAGS) --gh -o $@ $< CLEANFILES += $(BUILT_SOURCES) diff --git a/src/bin/eolian/main.c b/src/bin/eolian/main.c index 20bb7d2e9c..075ab1c8b0 100644 --- a/src/bin/eolian/main.c +++ b/src/bin/eolian/main.c @@ -260,7 +260,7 @@ enum int main(int argc, char **argv) { - int gen_what = GEN_NOTHING, do_legacy = 0, ret = 1; + int gen_what = GEN_NOTHING, do_legacy = 0, ret = 1, silent_types = 0; Eina_Bool help = EINA_FALSE; const char *outf = NULL; @@ -286,6 +286,7 @@ main(int argc, char **argv) { "output", required_argument, NULL, 'o' }, { "legacy", no_argument, &do_legacy, 1 }, { "include", required_argument, NULL, 'I' }, + { "silent-types", no_argument, &silent_types, 1 }, { NULL, 0, NULL, 0 } }; @@ -322,6 +323,7 @@ main(int argc, char **argv) printf(" --gc Generate C source file [.c]\n"); printf(" --gi Generate C implementation source file [.c]. The output will be a series of functions that have to be filled.\n"); printf(" --legacy Generate legacy\n"); + printf(" --silent-types Silence type validation\n"); ret = 0; goto end; } @@ -339,7 +341,7 @@ main(int argc, char **argv) goto end; } - if (!eolian_database_validate()) + if (!eolian_database_validate(silent_types)) { fprintf(stderr, "eolian: error validating database\n"); goto end; diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc index cb33de4e53..d7f3d935b5 100644 --- a/src/bin/eolian_cxx/eolian_cxx.cc +++ b/src/bin/eolian_cxx/eolian_cxx.cc @@ -243,7 +243,7 @@ database_load(options_type const& opts) << "Eolian failed parsing input files"; assert(false && "Error parsing input files"); } - if (!::eolian_database_validate()) + if (!::eolian_database_validate(EINA_FALSE)) { EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) << "Eolian failed validating database."; diff --git a/src/bindings/luajit/eolian.lua b/src/bindings/luajit/eolian.lua index a517631648..3192703f7e 100644 --- a/src/bindings/luajit/eolian.lua +++ b/src/bindings/luajit/eolian.lua @@ -188,7 +188,7 @@ ffi.cdef [[ Eina_Bool eolian_system_directory_scan(); Eina_Bool eolian_all_eo_files_parse(); Eina_Bool eolian_all_eot_files_parse(); - Eina_Bool eolian_database_validate(void); + Eina_Bool eolian_database_validate(Eina_Bool silent_types); const Eolian_Class *eolian_class_get_by_name(const char *class_name); const Eolian_Class *eolian_class_get_by_file(const char *file_name); const char *eolian_class_file_get(const Eolian_Class *klass); @@ -402,8 +402,8 @@ M.all_eot_files_get = function() return iterator.String_Iterator(eolian.eolian_all_eot_files_get()) end -M.database_validate = function() - return eolian.eolian_database_validate() ~= 0 +M.database_validate = function(silent) + return eolian.eolian_database_validate((not not silent) or false) ~= 0 end M.declaration_type = { diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index a659e1f51e..a5748eb09e 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -453,13 +453,14 @@ EAPI Eina_Bool eolian_all_eot_files_parse(void); /* * @brief Validates the database, printing errors and warnings. * + * @param[in] silent_types whether to silence type errors * @return EINA_TRUE on success, EINA_FALSE otherwise. * * Useful to catch type errors etc. early on. * * @ingroup Eolian */ -EAPI Eina_Bool eolian_database_validate(void); +EAPI Eina_Bool eolian_database_validate(Eina_Bool silent_types); /* * @brief Gets a class by its name diff --git a/src/lib/eolian/database_validate.c b/src/lib/eolian/database_validate.c index 938d6c817e..82eba4999a 100644 --- a/src/lib/eolian/database_validate.c +++ b/src/lib/eolian/database_validate.c @@ -6,8 +6,18 @@ #include "eo_lexer.h" +typedef struct _Validator { + Eina_Bool silent_types; +} Validator; + +typedef struct _Val_Success { + const Validator *vs; + Eina_Bool success; +} Val_Success; + static Eina_Bool -_validate_ref(const char *ref, const Eolian_Object *info) +_validate_ref(const Validator *vs EINA_UNUSED, const char *ref, + const Eolian_Object *info) { if (eolian_declaration_get_by_name(ref)) return EINA_TRUE; @@ -78,7 +88,8 @@ failed: } static Eina_Bool -_validate_docstr(Eina_Stringshare *str, const Eolian_Object *info) +_validate_docstr(const Validator *vs, Eina_Stringshare *str, + const Eolian_Object *info) { if (!str) return EINA_TRUE; @@ -99,7 +110,7 @@ _validate_docstr(Eina_Stringshare *str, const Eolian_Object *info) ++p; if (*(p - 1) == '.') --p; Eina_Stringshare *refs = eina_stringshare_add_length(ref, (p - ref)); - if (!_validate_ref(refs, info)) + if (!_validate_ref(vs, refs, info)) { eina_stringshare_del(refs); return EINA_FALSE; @@ -111,66 +122,69 @@ _validate_docstr(Eina_Stringshare *str, const Eolian_Object *info) } static Eina_Bool -_validate_doc(const Eolian_Documentation *doc) +_validate_doc(const Validator *vs, const Eolian_Documentation *doc) { if (!doc) return EINA_TRUE; - if (!_validate_docstr(doc->summary, &doc->base)) + if (!_validate_docstr(vs, doc->summary, &doc->base)) return EINA_FALSE; - if (!_validate_docstr(doc->description, &doc->base)) + if (!_validate_docstr(vs, doc->description, &doc->base)) return EINA_FALSE; return EINA_TRUE; } -static Eina_Bool _validate_type(const Eolian_Type *tp); -static Eina_Bool _validate_expr(const Eolian_Expression *expr, +static Eina_Bool _validate_type(const Validator *vs, const Eolian_Type *tp); +static Eina_Bool _validate_expr(const Validator *vs, + const Eolian_Expression *expr, const Eolian_Type *tp, Eolian_Expression_Mask msk); static Eina_Bool _sf_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, - const Eolian_Struct_Type_Field *sf, Eina_Bool *success) + const Eolian_Struct_Type_Field *sf, Val_Success *sc) { - *success = _validate_type(sf->type); + sc->success = _validate_type(sc->vs, sf->type); - if (!*success) + if (!sc->success) return EINA_FALSE; - *success = _validate_doc(sf->doc); + sc->success = _validate_doc(sc->vs, sf->doc); - return *success; + return sc->success; } static Eina_Bool _ef_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, - const Eolian_Enum_Type_Field *ef, Eina_Bool *success) + const Eolian_Enum_Type_Field *ef, Val_Success *sc) { if (ef->value) - *success = _validate_expr(ef->value, NULL, EOLIAN_MASK_INT); + sc->success = _validate_expr(sc->vs, ef->value, NULL, EOLIAN_MASK_INT); else - *success = EINA_TRUE; + sc->success = EINA_TRUE; - if (!*success) + if (!sc->success) return EINA_FALSE; - *success = _validate_doc(ef->doc); + sc->success = _validate_doc(sc->vs, ef->doc); - return *success; + return sc->success; } static Eina_Bool -_type_error(const Eolian_Type *tp, const char *msg) +_type_error(const Validator *vs, const Eolian_Type *tp, const char *msg) { + if (vs->silent_types) + return EINA_FALSE; eina_log_print(_eolian_log_dom, EINA_LOG_LEVEL_WARN, tp->base.file, "", tp->base.line, "%s at column %d", msg, tp->base.column); return EINA_FALSE; } static Eina_Bool -_validate_type(const Eolian_Type *tp) +_validate_type(const Validator *vs, const Eolian_Type *tp) { - if (!_validate_doc(tp->doc)) + if (!_validate_doc(vs, tp->doc)) return EINA_FALSE; switch (tp->type) @@ -192,27 +206,31 @@ _validate_type(const Eolian_Type *tp) { char buf[256]; snprintf(buf, sizeof(buf), "undefined type %s", tp->full_name); - _type_error(tp, buf); + _type_error(vs, tp, buf); return EINA_TRUE; /* for now only warn */ } - return _validate_type(tpp); + return _validate_type(vs, tpp); } case EOLIAN_TYPE_POINTER: case EOLIAN_TYPE_ALIAS: - return _validate_type(tp->base_type); + return _validate_type(vs, tp->base_type); case EOLIAN_TYPE_STRUCT: { - Eina_Bool succ = EINA_TRUE; + Val_Success succ; + succ.vs = vs; + succ.success = EINA_TRUE; eina_hash_foreach(tp->fields, (Eina_Hash_Foreach)_sf_map_cb, &succ); - return succ; + return succ.success; } case EOLIAN_TYPE_STRUCT_OPAQUE: return EINA_TRUE; case EOLIAN_TYPE_ENUM: { - Eina_Bool succ = EINA_TRUE; + Val_Success succ; + succ.vs = vs; + succ.success = EINA_TRUE; eina_hash_foreach(tp->fields, (Eina_Hash_Foreach)_ef_map_cb, &succ); - return succ; + return succ.success; } case EOLIAN_TYPE_CLASS: { @@ -222,7 +240,7 @@ _validate_type(const Eolian_Type *tp) char buf[256]; snprintf(buf, sizeof(buf), "undefined class %s " "(likely wrong namespacing)", tp->full_name); - _type_error(tp, buf); + _type_error(vs, tp, buf); } return EINA_TRUE; } @@ -233,8 +251,8 @@ _validate_type(const Eolian_Type *tp) } static Eina_Bool -_validate_expr(const Eolian_Expression *expr, const Eolian_Type *tp, - Eolian_Expression_Mask msk) +_validate_expr(const Validator *vs EINA_UNUSED, const Eolian_Expression *expr, + const Eolian_Type *tp, Eolian_Expression_Mask msk) { Eolian_Value val; /* TODO: enable later, for now we can't (unfinished interfaces */ @@ -252,40 +270,40 @@ _validate_expr(const Eolian_Expression *expr, const Eolian_Type *tp, } static Eina_Bool -_validate_param(const Eolian_Function_Parameter *param) +_validate_param(const Validator *vs, const Eolian_Function_Parameter *param) { - if (!_validate_type(param->type)) + if (!_validate_type(vs, param->type)) return EINA_FALSE; - if (!_validate_doc(param->doc)) + if (!_validate_doc(vs, param->doc)) return EINA_FALSE; return EINA_TRUE; } static Eina_Bool -_validate_function(const Eolian_Function *func) +_validate_function(const Validator *vs, const Eolian_Function *func) { Eina_List *l; const Eolian_Function_Parameter *param; - if (func->get_ret_type && !_validate_type(func->get_ret_type)) + if (func->get_ret_type && !_validate_type(vs, func->get_ret_type)) return EINA_FALSE; - if (func->set_ret_type && !_validate_type(func->set_ret_type)) + if (func->set_ret_type && !_validate_type(vs, func->set_ret_type)) return EINA_FALSE; - if (func->get_ret_val && !_validate_expr(func->get_ret_val, + if (func->get_ret_val && !_validate_expr(vs, func->get_ret_val, func->get_ret_type, 0)) return EINA_FALSE; - if (func->set_ret_val && !_validate_expr(func->set_ret_val, + if (func->set_ret_val && !_validate_expr(vs, func->set_ret_val, func->set_ret_type, 0)) return EINA_FALSE; #define EOLIAN_PARAMS_VALIDATE(params) \ EINA_LIST_FOREACH(params, l, param) \ - if (!_validate_param(param)) \ + if (!_validate_param(vs, param)) \ return EINA_FALSE; EOLIAN_PARAMS_VALIDATE(func->prop_values); @@ -297,67 +315,67 @@ _validate_function(const Eolian_Function *func) #undef EOLIAN_PARAMS_VALIDATE - if (!_validate_doc(func->common_doc)) + if (!_validate_doc(vs, func->common_doc)) return EINA_FALSE; - if (!_validate_doc(func->get_doc)) + if (!_validate_doc(vs, func->get_doc)) return EINA_FALSE; - if (!_validate_doc(func->set_doc)) + if (!_validate_doc(vs, func->set_doc)) return EINA_FALSE; - if (!_validate_doc(func->get_return_doc)) + if (!_validate_doc(vs, func->get_return_doc)) return EINA_FALSE; - if (!_validate_doc(func->set_return_doc)) + if (!_validate_doc(vs, func->set_return_doc)) return EINA_FALSE; return EINA_TRUE; } static Eina_Bool -_validate_event(const Eolian_Event *event) +_validate_event(const Validator *vs, const Eolian_Event *event) { - if (event->type && !_validate_type(event->type)) + if (event->type && !_validate_type(vs, event->type)) return EINA_FALSE; - if (!_validate_doc(event->doc)) + if (!_validate_doc(vs, event->doc)) return EINA_FALSE; return EINA_TRUE; } static Eina_Bool -_validate_class(const Eolian_Class *cl) +_validate_class(const Validator *vs, const Eolian_Class *cl) { Eina_List *l; const Eolian_Function *func; const Eolian_Event *event; EINA_LIST_FOREACH(cl->properties, l, func) - if (!_validate_function(func)) + if (!_validate_function(vs, func)) return EINA_FALSE; EINA_LIST_FOREACH(cl->methods, l, func) - if (!_validate_function(func)) + if (!_validate_function(vs, func)) return EINA_FALSE; EINA_LIST_FOREACH(cl->events, l, event) - if (!_validate_event(event)) + if (!_validate_event(vs, event)) return EINA_FALSE; - if (!_validate_doc(cl->doc)) + if (!_validate_doc(vs, cl->doc)) return EINA_FALSE; return EINA_TRUE; } static Eina_Bool -_validate_variable(const Eolian_Variable *var) +_validate_variable(const Validator *vs, const Eolian_Variable *var) { - if (!_validate_type(var->base_type)) + if (!_validate_type(vs, var->base_type)) return EINA_FALSE; - if (var->value && !_validate_expr(var->value, var->base_type, 0)) + if (var->value && !_validate_expr(vs, var->value, var->base_type, 0)) return EINA_FALSE; - if (!_validate_doc(var->doc)) + if (!_validate_doc(vs, var->doc)) return EINA_FALSE; return EINA_TRUE; @@ -365,54 +383,59 @@ _validate_variable(const Eolian_Variable *var) static Eina_Bool _type_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, - const Eolian_Type *tp, Eina_Bool *success) + const Eolian_Type *tp, Val_Success *sc) { - *success = _validate_type(tp); - return *success; + sc->success = _validate_type(sc->vs, tp); + return sc->success; } static Eina_Bool _var_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, - const Eolian_Variable *var, Eina_Bool *success) + const Eolian_Variable *var, Val_Success *sc) { - *success = _validate_variable(var); - return *success; + sc->success = _validate_variable(sc->vs, var); + return sc->success; } Eina_Bool -database_validate(void) +database_validate(Eina_Bool silent_types) { + Validator vs; const Eolian_Class *cl; + vs.silent_types = silent_types; + Eina_Iterator *iter = eolian_all_classes_get(); EINA_ITERATOR_FOREACH(iter, cl) - if (!_validate_class(cl)) + if (!_validate_class(&vs, cl)) { eina_iterator_free(iter); return EINA_FALSE; } eina_iterator_free(iter); - Eina_Bool succ = EINA_TRUE; + Val_Success succ; + succ.vs = &vs; + succ.success = EINA_TRUE; eina_hash_foreach(_aliases, (Eina_Hash_Foreach)_type_map_cb, &succ); - if (!succ) + if (!succ.success) return EINA_FALSE; eina_hash_foreach(_structs, (Eina_Hash_Foreach)_type_map_cb, &succ); - if (!succ) + if (!succ.success) return EINA_FALSE; eina_hash_foreach(_enums, (Eina_Hash_Foreach)_type_map_cb, &succ); - if (!succ) + if (!succ.success) return EINA_FALSE; eina_hash_foreach(_globals, (Eina_Hash_Foreach)_var_map_cb, &succ); - if (!succ) + if (!succ.success) return EINA_FALSE; eina_hash_foreach(_constants, (Eina_Hash_Foreach)_var_map_cb, &succ); - if (!succ) + if (!succ.success) return EINA_FALSE; return EINA_TRUE; diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c index 01a329b40a..fa0931088e 100644 --- a/src/lib/eolian/eolian_database.c +++ b/src/lib/eolian/eolian_database.c @@ -369,12 +369,12 @@ eolian_all_eo_files_parse() } EAPI Eina_Bool -eolian_database_validate(void) +eolian_database_validate(Eina_Bool silent_types) { if (_database_init_count <= 0) return EINA_FALSE; - return database_validate(); + return database_validate(silent_types); } EAPI Eina_Iterator * diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index 6a51c6273a..6bc470bd3a 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -271,7 +271,7 @@ int database_init(void); int database_shutdown(void); char *database_class_to_filename(const char *cname); -Eina_Bool database_validate(void); +Eina_Bool database_validate(Eina_Bool silent_types); Eina_Bool database_class_name_validate(const char *class_name, const Eolian_Class **cl); void database_decl_add(Eina_Stringshare *name, Eolian_Declaration_Type type,