diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index 80ccd1ef94..4c9535dc03 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -170,6 +170,12 @@ typedef struct _Eolian_Expression Eolian_Expression; */ typedef struct _Eolian_Variable Eolian_Variable; +/* Error information + * + * @ingroup Eolian + */ +typedef struct _Eolian_Error Eolian_Error; + /* Struct field information * * @ingroup Eolian @@ -222,7 +228,8 @@ typedef enum EOLIAN_OBJECT_PART, EOLIAN_OBJECT_IMPLEMENT, EOLIAN_OBJECT_CONSTRUCTOR, - EOLIAN_OBJECT_DOCUMENTATION + EOLIAN_OBJECT_DOCUMENTATION, + EOLIAN_OBJECT_ERROR } Eolian_Object_Type; typedef enum @@ -276,6 +283,7 @@ typedef enum EOLIAN_TYPE_VOID, EOLIAN_TYPE_REGULAR, EOLIAN_TYPE_CLASS, + EOLIAN_TYPE_ERROR, EOLIAN_TYPE_UNDEFINED } Eolian_Type_Type; @@ -1078,6 +1086,16 @@ EAPI const Eolian_Variable *eolian_unit_global_by_name_get(const Eolian_Unit *un */ EAPI const Eolian_Variable *eolian_unit_constant_by_name_get(const Eolian_Unit *unit, const char *name); +/* + * @brief Get an error declaration in a unit by name. + * + * @param[in] unit The unit. + * @param[in] name the name of the error + * + * @ingroup Eolian + */ +EAPI const Eolian_Error *eolian_unit_error_by_name_get(const Eolian_Unit *unit, const char *name); + /* * @brief Get an iterator to all constant variables in the Eolian database. * @@ -1100,6 +1118,17 @@ EAPI Eina_Iterator *eolian_unit_constants_get(const Eolian_Unit *unit); */ EAPI Eina_Iterator *eolian_unit_globals_get(const Eolian_Unit *unit); +/* + * @brief Get an iterator to all error declarations in the Eolian database. + * + * @return the iterator or NULL + * + * Thanks to internal caching, this is an O(1) operation. + * + * @ingroup Eolian + */ +EAPI Eina_Iterator *eolian_unit_errors_get(const Eolian_Unit *unit); + /* * @brief Get an alias type declaration within a unit by name. * @@ -1265,6 +1294,19 @@ eolian_state_constant_by_name_get(const Eolian_State *state, const char *name) return eolian_unit_constant_by_name_get(EOLIAN_UNIT(state), name); } +/* + * @brief A helper function to get an error declaration in a state by name. + * + * @see eolian_unit_error_by_name_get + * + * @ingroup Eolian + */ +static inline const Eolian_Error * +eolian_state_error_by_name_get(const Eolian_State *state, const char *name) +{ + return eolian_unit_error_by_name_get(EOLIAN_UNIT(state), name); +} + /* * @brief Get an iterator to all global variables contained in a file. * @@ -1290,6 +1332,19 @@ EAPI Eina_Iterator *eolian_state_globals_by_file_get(const Eolian_State *state, */ EAPI Eina_Iterator *eolian_state_constants_by_file_get(const Eolian_State *state, const char *file_name); +/* + * @brief Get an iterator to all error declarations contained in a file. + * + * @param[in] state The state. + * @param[in] file_name The file name. + * @return the iterator or NULL + * + * Thanks to internal caching, this is an O(1) operation. + * + * @ingroup Eolian + */ +EAPI Eina_Iterator *eolian_state_errors_by_file_get(const Eolian_State *state, const char *file_name); + /* * @brief A helper function to get all globals in a state. * @@ -1316,6 +1371,19 @@ eolian_state_constants_get(const Eolian_State *state) return eolian_unit_constants_get(EOLIAN_UNIT(state)); } +/* + * @brief A helper function to get all error declarations in a state. + * + * @see eolian_unit_errors_get + * + * @ingroup Eolian + */ +static inline Eina_Iterator * +eolian_state_errors_get(const Eolian_State *state) +{ + return eolian_unit_errors_get(EOLIAN_UNIT(state)); +} + /* * @brief A helper function to get an alias in a state by name. * @@ -2704,7 +2772,8 @@ EAPI const Eolian_Type *eolian_type_base_type_get(const Eolian_Type *tp); * * The inner types of a complex type form a chain. Therefore, you first retrieve * the first one via eolian_type_base_type_get and then get the next one via - * this API function called on the first inner type if necessary. + * this API function called on the first inner type if necessary. Another use + * for this is with errors, specifying error(Foo, Bar, ...) makes a chain. * * @param[in] tp the type. * @return the next type or NULL. @@ -2752,6 +2821,16 @@ EAPI const Eolian_Type *eolian_type_aliased_base_get(const Eolian_Type *tp); */ EAPI const Eolian_Class *eolian_type_class_get(const Eolian_Type *tp); +/* + * @brief Get the error declaration associated with an EOLIAN_TYPE_ERROR type. + * + * @param[in] tp the type. + * @return the error or NULL. + * + * @ingroup Eolian + */ +EAPI const Eolian_Error *eolian_type_error_get(const Eolian_Type *tp); + /* * @brief Get whether the given type is owned. * @@ -3130,6 +3209,101 @@ eolian_variable_is_beta(const Eolian_Variable *var) return eolian_object_is_beta(EOLIAN_OBJECT(var)); } +/* + * @brief Get the message of an error declaration. + * + * @param[in] err the error. + * @return the message or NULL. + * + * @ingroup Eolian + */ +EAPI const char *eolian_error_message_get(const Eolian_Error *err); + +/* + * @brief Get the documentation of an error declaration. + * + * @param[in] err the error declaration. + * @return the documentation or NULL. + * + * @ingroup Eolian + */ +EAPI const Eolian_Documentation *eolian_error_documentation_get(const Eolian_Error *err); + +/* + * @brief A helper function to get the full name of an error declaration. + * + * @see eolian_object_name_get + * + * @ingroup Eolian + */ +static inline const char * +eolian_error_name_get(const Eolian_Error *err) +{ + return eolian_object_name_get(EOLIAN_OBJECT(err)); +} + +/* + * @brief A helper function to get the C name of an error declaration. + * + * @see eolian_object_c_name_get + * + * @ingroup Eolian + */ +static inline const char * +eolian_error_c_name_get(const Eolian_Error *err) +{ + return eolian_object_c_name_get(EOLIAN_OBJECT(err)); +} + +/* + * @brief A helper function to get the short name of an error declaration. + * + * @see eolian_object_short_name_get + * + * @ingroup Eolian + */ +static inline const char * +eolian_error_short_name_get(const Eolian_Error *err) +{ + return eolian_object_short_name_get(EOLIAN_OBJECT(err)); +} + +/* + * @brief A helper function to get the namespaces of an error declaration. + * + * @see eolian_object_namespaces_get + * + * @ingroup Eolian + */ +static inline Eina_Iterator * +eolian_error_namespaces_get(const Eolian_Error *err) +{ + return eolian_object_namespaces_get(EOLIAN_OBJECT(err)); +} + +/* + * @brief Get whether an error declaration is beta. + * + * @see eolian_object_is_beta + * + * @ingroup Eolian + */ +static inline Eina_Bool +eolian_error_is_beta(const Eolian_Error *err) +{ + return eolian_object_is_beta(EOLIAN_OBJECT(err)); +} + +/* + * @brief Check if an error declaration is extern. + * + * @param[in] err the errpr decůaratopm. + * @return EINA_TRUE if it's extern, EINA_FALSE otherwise. + * + * @ingroup Eolian + */ +EAPI Eina_Bool eolian_error_is_extern(const Eolian_Error *err); + /* * @brief Get the summary of the documentation. * diff --git a/src/lib/eolian/database_type_api.c b/src/lib/eolian/database_type_api.c index b10a9a700f..d4869e2866 100644 --- a/src/lib/eolian/database_type_api.c +++ b/src/lib/eolian/database_type_api.c @@ -197,6 +197,15 @@ eolian_type_class_get(const Eolian_Type *tp) return tp->klass; } +EAPI const Eolian_Error * +eolian_type_error_get(const Eolian_Type *tp) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL); + if (eolian_type_type_get(tp) != EOLIAN_TYPE_ERROR) + return NULL; + return tp->error; +} + EAPI Eina_Bool eolian_type_is_owned(const Eolian_Type *tp) { diff --git a/src/lib/eolian/database_validate.c b/src/lib/eolian/database_validate.c index 71c05d7d8f..8deea6d595 100644 --- a/src/lib/eolian/database_validate.c +++ b/src/lib/eolian/database_validate.c @@ -351,9 +351,29 @@ _validate_type(Validate_State *vals, Eolian_Type *tp) } if (!tp->freefunc) tp->freefunc = eina_stringshare_add(eo_obj_free); - tp->base.c_name = eina_stringshare_ref(tp->tdecl->base.c_name); + tp->base.c_name = eina_stringshare_ref(tp->klass->base.c_name); return _validate_ownable(tp); } + case EOLIAN_TYPE_ERROR: + { + tp->error = (Eolian_Error *)eolian_unit_error_by_name_get(src, tp->base.name); + if (!tp->error) + { + _eo_parser_log(&tp->base, "undefined error %s " + "(likely wrong namespacing)", tp->base.name); + return EINA_FALSE; + } + else if (vals->stable && tp->error->base.is_beta) + { + _eo_parser_log(&tp->base, "beta error '%s' used in stable context", + tp->error->base.name); + return EINA_FALSE; + } + tp->base.c_name = eina_stringshare_ref(tp->error->base.c_name); + if (tp->next_type && !_validate_type(vals, tp->next_type)) + return EINA_FALSE; + return _validate(&tp->base); + } default: return EINA_FALSE; } diff --git a/src/lib/eolian/eo_lexer.h b/src/lib/eolian/eo_lexer.h index 5bc7064151..0e7921726f 100644 --- a/src/lib/eolian/eo_lexer.h +++ b/src/lib/eolian/eo_lexer.h @@ -28,7 +28,7 @@ enum Tokens #define KEYWORDS KW(class), KW(const), KW(enum), KW(return), KW(struct), \ \ KW(abstract), KW(c_prefix), KW(composite), KW(constructor), KW(constructors), \ - KW(data), KW(destructor), KW(event_prefix), KW(events), KW(extends), \ + KW(data), KW(destructor), KW(error), KW(event_prefix), KW(events), KW(extends), \ KW(free), KW(get), KW(implements), KW(import), KW(interface), \ KW(keys), KW(legacy), KW(methods), KW(mixin), KW(params), \ KW(parse), KW(parts), KW(ptr), KW(set), KW(type), KW(values), KW(var), KW(requires), \ @@ -296,6 +296,18 @@ eo_lexer_expr_release_ref(Eo_Lexer *ls, Eolian_Expression *expr) return eo_lexer_expr_release(ls, expr); } +static inline Eolian_Error * +eo_lexer_error_new(Eo_Lexer *ls) +{ + return (Eolian_Error *)eo_lexer_node_new(ls, sizeof(Eolian_Error)); +} + +static inline Eolian_Error * +eo_lexer_error_release(Eo_Lexer *ls, Eolian_Error *err) +{ + return (Eolian_Error *)eo_lexer_node_release(ls, (Eolian_Object *)err); +} + /* "stack" management, only to protect against errors (jumps) in parsing */ void eo_lexer_dtor_push(Eo_Lexer *ls, Eina_Free_Cb free_cb, void *data); void eo_lexer_dtor_pop(Eo_Lexer *ls); diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c index ee056b7cf5..f33db75f67 100644 --- a/src/lib/eolian/eo_parser.c +++ b/src/lib/eolian/eo_parser.c @@ -646,6 +646,29 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool is_extern, return def; } +/* error(Error1, Error2, Error3, ...) */ +static Eolian_Type * +parse_type_error(Eo_Lexer *ls) +{ + Eolian_Type *def = eo_lexer_type_new(ls); + Eina_Strbuf *buf = eina_strbuf_new(); + eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf); + for (Eolian_Type *cdef = def;; cdef = cdef->next_type) + { + FILL_BASE(cdef->base, ls, ls->line_number, ls->column, TYPE); + parse_name(ls, buf); + cdef->type = EOLIAN_TYPE_ERROR; + cdef->base.name = eina_stringshare_add(eina_strbuf_string_get(buf)); + eina_strbuf_reset(buf); + if (ls->t.token != ',') + break; + eo_lexer_get(ls); + cdef->next_type = eo_lexer_type_release(ls, eo_lexer_type_new(ls)); + } + eo_lexer_dtor_pop(ls); + return def; +} + static Eolian_Type * parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr) { @@ -698,6 +721,17 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr) check_match(ls, ')', '(', pline, pcolumn); return def; } + case KW_error: + { + int pline, pcolumn; + eo_lexer_get(ls); + pline = ls->line_number; + pcolumn = ls->column; + check_next(ls, '('); + def = parse_type_error(ls); + check_match(ls, ')', '(', pline, pcolumn); + return def; + } default: break; } @@ -910,6 +944,71 @@ tags_done: return def; } +static Eolian_Error * +parse_error(Eo_Lexer *ls) +{ + Eolian_Error *def = eo_lexer_error_new(ls); + Eina_Strbuf *buf; + eo_lexer_get(ls); + Eina_Stringshare *cname = NULL; + Eina_Bool has_extern = EINA_FALSE, has_beta = EINA_FALSE, has_c_name = EINA_FALSE; + for (;;) switch (ls->t.kw) + { + case KW_at_extern: + CASE_LOCK(ls, extern, "extern qualifier"); + def->is_extern = EINA_TRUE; + eo_lexer_get(ls); + break; + case KW_at_beta: + CASE_LOCK(ls, beta, "beta qualifier"); + def->base.is_beta = EINA_TRUE; + eo_lexer_get(ls); + break; + case KW_at_c_name: + CASE_LOCK(ls, c_name, "@c_name specifier"); + cname = parse_c_name(ls); + eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname); + break; + default: + goto tags_done; + } +tags_done: + buf = eina_strbuf_new(); + eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf); + eo_lexer_context_push(ls); + FILL_BASE(def->base, ls, ls->line_number, ls->column, ERROR); + parse_name(ls, buf); + def->base.name = eina_stringshare_add(eina_strbuf_string_get(buf)); + if (cname) + { + def->base.c_name = cname; + eo_lexer_dtor_pop(ls); + } + else + def->base.c_name = make_c_name(def->base.name); + Eolian_Object *decl = _eolian_decl_get(ls, def->base.name); + if (decl) + { + eo_lexer_context_restore(ls); + redef_error(ls, decl, &def->base); + } + eo_lexer_context_pop(ls); + check(ls, '='); + /* we need to parse a string so switch to exprmode */ + ls->expr_mode = EINA_TRUE; + /* consume = to get string */ + eo_lexer_get(ls); + /* verify and switch back to plain syntax mode */ + check(ls, TOK_STRING); + ls->expr_mode = EINA_FALSE; + def->msg = eina_stringshare_ref(ls->t.value.s); + eo_lexer_get(ls); + check_next(ls, ';'); + FILL_DOC(ls, def, doc); + eo_lexer_dtor_pop(ls); + return def; +} + typedef struct _Eo_Ret_Def { Eolian_Type *type; @@ -2273,6 +2372,9 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot) parse_variable(ls, ls->t.kw == KW_var))); break; } + case KW_error: + database_error_add(ls->unit, eo_lexer_error_release(ls, parse_error(ls))); + break; case KW_struct: case KW_enum: { diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c index 40b0ca156f..caa43407a4 100644 --- a/src/lib/eolian/eolian_database.c +++ b/src/lib/eolian/eolian_database.c @@ -568,6 +568,7 @@ database_unit_init(Eolian_State *state, Eolian_Unit *unit, const char *file) unit->classes = eina_hash_stringshared_new(EINA_FREE_CB(database_class_del)); unit->globals = eina_hash_stringshared_new(EINA_FREE_CB(database_var_del)); unit->constants = eina_hash_stringshared_new(EINA_FREE_CB(database_var_del)); + unit->errors = eina_hash_stringshared_new(EINA_FREE_CB(database_error_del)); unit->aliases = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del)); unit->structs = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del)); unit->enums = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del)); @@ -585,6 +586,7 @@ _unit_contents_del(Eolian_Unit *unit) eina_hash_free(unit->classes); eina_hash_free(unit->globals); eina_hash_free(unit->constants); + eina_hash_free(unit->errors); eina_hash_free(unit->aliases); eina_hash_free(unit->structs); eina_hash_free(unit->enums); @@ -637,6 +639,7 @@ _state_area_init(Eolian_State *state, Eolian_State_Area *a) a->enums_f = eina_hash_stringshared_new(NULL); a->globals_f = eina_hash_stringshared_new(NULL); a->constants_f = eina_hash_stringshared_new(NULL); + a->errors_f = eina_hash_stringshared_new(NULL); a->objects_f = eina_hash_stringshared_new(NULL); } @@ -663,6 +666,7 @@ _state_area_contents_del(Eolian_State_Area *a) _hashlist_free(a->enums_f); _hashlist_free(a->globals_f); _hashlist_free(a->constants_f); + _hashlist_free(a->errors_f); _hashlist_free(a->objects_f); } @@ -1239,6 +1243,17 @@ eolian_state_constants_by_file_get(const Eolian_State *state, const char *file_n return eina_list_iterator_new(l); } +EAPI Eina_Iterator * +eolian_state_errors_by_file_get(const Eolian_State *state, const char *file_name) +{ + if (!state) return NULL; + Eina_Stringshare *shr = eina_stringshare_add(file_name); + Eina_List *l = eina_hash_find(state->main.errors_f, shr); + eina_stringshare_del(shr); + if (!l) return NULL; + return eina_list_iterator_new(l); +} + EAPI Eina_Iterator * eolian_state_aliases_by_file_get(const Eolian_State *state, const char *file_name) { @@ -1361,6 +1376,16 @@ eolian_unit_constant_by_name_get(const Eolian_Unit *unit, const char *name) return v; } +EAPI const Eolian_Error * +eolian_unit_error_by_name_get(const Eolian_Unit *unit, const char *name) +{ + if (!unit) return NULL; + Eina_Stringshare *shr = eina_stringshare_add(name); + Eolian_Error *v = eina_hash_find(unit->errors, shr); + eina_stringshare_del(shr); + return v; +} + EAPI Eina_Iterator * eolian_unit_constants_get(const Eolian_Unit *unit) { @@ -1373,6 +1398,12 @@ eolian_unit_globals_get(const Eolian_Unit *unit) return (unit ? eina_hash_iterator_data_new(unit->globals) : NULL); } +EAPI Eina_Iterator * +eolian_unit_errors_get(const Eolian_Unit *unit) +{ + return (unit ? eina_hash_iterator_data_new(unit->errors) : NULL); +} + EAPI const Eolian_Typedecl * eolian_unit_alias_by_name_get(const Eolian_Unit *unit, const char *name) { @@ -1424,6 +1455,45 @@ eolian_unit_enums_get(const Eolian_Unit *unit) return (unit ? eina_hash_iterator_data_new(unit->enums) : NULL); } +EAPI const char * +eolian_error_message_get(const Eolian_Error *err) +{ + if (!err) return NULL; + return err->msg; +} + +EAPI Eina_Bool +eolian_error_is_extern(const Eolian_Error *err) +{ + if (!err) return EINA_FALSE; + return err->is_extern; +} + +EAPI const Eolian_Documentation * +eolian_error_documentation_get(const Eolian_Error *err) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(err, NULL); + return err->doc; +} + +void +database_error_del(Eolian_Error *err) +{ + if (!err || eolian_object_unref(&err->base)) return; + eina_stringshare_del(err->msg); + free(err); +} + +void +database_error_add(Eolian_Unit *unit, Eolian_Error *err) +{ + EOLIAN_OBJECT_ADD(unit, err->base.name, err, errors); + eina_hash_set(unit->state->staging.errors_f, err->base.file, eina_list_append + ((Eina_List*)eina_hash_find(unit->state->staging.errors_f, err->base.file), + err)); + database_object_add(unit, &err->base); +} + char * database_class_to_filename(const char *cname) { diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index 0dce769370..950e4114d4 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -41,6 +41,7 @@ struct _Eolian_Unit Eina_Hash *classes; Eina_Hash *globals; Eina_Hash *constants; + Eina_Hash *errors; Eina_Hash *aliases; Eina_Hash *structs; Eina_Hash *enums; @@ -60,6 +61,7 @@ typedef struct _Eolian_State_Area Eina_Hash *enums_f; Eina_Hash *globals_f; Eina_Hash *constants_f; + Eina_Hash *errors_f; Eina_Hash *objects_f; } Eolian_State_Area; @@ -267,6 +269,7 @@ struct _Eolian_Type { Eolian_Class *klass; Eolian_Typedecl *tdecl; + Eolian_Error *error; }; Eina_Bool is_const :1; Eina_Bool is_ptr :1; @@ -325,6 +328,14 @@ struct _Eolian_Event Eina_Bool is_restart :1; }; +struct _Eolian_Error +{ + Eolian_Object base; + Eina_Stringshare *msg; + Eolian_Documentation *doc; + Eina_Bool is_extern :1; +}; + struct _Eolian_Struct_Type_Field { Eolian_Object base; @@ -448,4 +459,8 @@ void database_event_del(Eolian_Event *event); /* parts */ void database_part_del(Eolian_Part *part); +/* errors */ +void database_error_del(Eolian_Error *err); +void database_error_add(Eolian_Unit *unit, Eolian_Error *err); + #endif diff --git a/src/tests/eolian/data/error.eo b/src/tests/eolian/data/error.eo new file mode 100644 index 0000000000..3a5867ac8d --- /dev/null +++ b/src/tests/eolian/data/error.eo @@ -0,0 +1,13 @@ +error Foo = "something bad happened"; [[Error doc]] +error @beta Bar = "another bad thing happened"; [[Another error doc]] + +class @beta Error { + methods { + foo { + return: error(Foo); + } + bar { + return: error(Foo, Bar); + } + } +} diff --git a/src/tests/eolian/eolian_parsing.c b/src/tests/eolian/eolian_parsing.c index 57120f6253..ccabb263fd 100644 --- a/src/tests/eolian/eolian_parsing.c +++ b/src/tests/eolian/eolian_parsing.c @@ -843,6 +843,53 @@ EFL_START_TEST(eolian_var) } EFL_END_TEST +EFL_START_TEST(eolian_error) +{ + const Eolian_Unit *unit; + const Eolian_Class *class; + const Eolian_Function *f1, *f2; + const Eolian_Type *rtp1, *rtp2; + const Eolian_Error *err1, *err2; + + Eolian_State *eos = eolian_state_new(); + + fail_if(!eolian_state_directory_add(eos, TESTS_SRC_DIR"/data")); + fail_if(!(unit = eolian_state_file_parse(eos, "error.eo"))); + + fail_if(!(class = eolian_unit_class_by_name_get(unit, "Error"))); + fail_if(!(f1 = eolian_class_function_by_name_get(class, "foo", EOLIAN_METHOD))); + fail_if(!(f2 = eolian_class_function_by_name_get(class, "bar", EOLIAN_METHOD))); + + fail_if(!(rtp1 = eolian_function_return_type_get(f1, EOLIAN_METHOD))); + fail_if(!(rtp2 = eolian_function_return_type_get(f2, EOLIAN_METHOD))); + + /* single error */ + fail_if(eolian_type_type_get(rtp1) != EOLIAN_TYPE_ERROR); + fail_if(eolian_type_next_type_get(rtp1) != NULL); + fail_if(strcmp(eolian_type_name_get(rtp1), "Foo")); + fail_if(!(err1 = eolian_type_error_get(rtp1))); + fail_if(strcmp(eolian_error_message_get(err1), "something bad happened")); + + /* error range */ + fail_if(eolian_type_type_get(rtp2) != EOLIAN_TYPE_ERROR); + fail_if(!(rtp1 = eolian_type_next_type_get(rtp2))); + fail_if(strcmp(eolian_type_name_get(rtp2), "Foo")); + fail_if(strcmp(eolian_type_name_get(rtp1), "Bar")); + /* it's the same Foo here */ + fail_if(eolian_type_error_get(rtp2) != err1); + fail_if(!(err2 = eolian_type_error_get(rtp1))); + fail_if(strcmp(eolian_error_message_get(err1), "something bad happened")); + fail_if(strcmp(eolian_error_message_get(err2), "another bad thing happened")); + + fail_if(!eolian_error_documentation_get(err1)); + fail_if(!eolian_error_documentation_get(err2)); + fail_if(eolian_error_is_beta(err1)); + fail_if(!eolian_error_is_beta(err2)); + + eolian_state_free(eos); +} +EFL_END_TEST + EFL_START_TEST(eolian_enum) { const Eolian_Enum_Type_Field *field = NULL; @@ -1621,6 +1668,7 @@ void eolian_parsing_test(TCase *tc) tcase_add_test(tc, eolian_struct); tcase_add_test(tc, eolian_extern); tcase_add_test(tc, eolian_var); + tcase_add_test(tc, eolian_error); tcase_add_test(tc, eolian_enum); tcase_add_test(tc, eolian_class_funcs); tcase_add_test(tc, eolian_free_func);