summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2019-06-21 15:05:50 +0200
committerDaniel Kolesa <d.kolesa@samsung.com>2019-06-24 15:15:30 +0200
commit1bbf4380abce4c704eb101d1bbfd8795ee31044b (patch)
treee0117464464d17ea8be870172e48d3c9bafc1495
parent61235a6e5c47a564d217576fbcdef4e3c0a59b6f (diff)
downloadefl-1bbf4380abce4c704eb101d1bbfd8795ee31044b.tar.gz
eolian: add library support for declaring and using errors
You can now declare errors like this: error Foo = "message"; [[documentation]] Then you can use them as types like this: foo { return: error(Error1, Error2, ...); } They have a separate type category and storage. They are checked for redefinitions the same as anything else though. This does not add any generator support nor it adds any advanced checking. Ref T6890
-rw-r--r--src/lib/eolian/Eolian.h178
-rw-r--r--src/lib/eolian/database_type_api.c9
-rw-r--r--src/lib/eolian/database_validate.c22
-rw-r--r--src/lib/eolian/eo_lexer.h14
-rw-r--r--src/lib/eolian/eo_parser.c102
-rw-r--r--src/lib/eolian/eolian_database.c70
-rw-r--r--src/lib/eolian/eolian_database.h15
-rw-r--r--src/tests/eolian/data/error.eo13
-rw-r--r--src/tests/eolian/eolian_parsing.c48
9 files changed, 467 insertions, 4 deletions
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;
@@ -1079,6 +1087,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.
*
* @return the iterator or NULL
@@ -1101,6 +1119,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.
*
* @param[in] unit The unit.
@@ -1266,6 +1295,19 @@ eolian_state_constant_by_name_get(const Eolian_State *state, const char *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.
*
* @param[in] state The state.
@@ -1291,6 +1333,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.
*
* @see eolian_unit_globals_get
@@ -1317,6 +1372,19 @@ eolian_state_constants_get(const Eolian_State *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.
*
* @see eolian_unit_alias_by_name_get
@@ -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.
@@ -2753,6 +2822,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.
*
* This is true when a parameter, return or whatever is marked as @owned.
@@ -3131,6 +3210,101 @@ eolian_variable_is_beta(const Eolian_Variable *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.
*
* This should never return NULL unless the input is invalid.
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);
}
@@ -1240,6 +1244,17 @@ eolian_state_constants_by_file_get(const Eolian_State *state, const char *file_n
}
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)
{
if (!state) return NULL;
@@ -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);