summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@osg.samsung.com>2016-12-06 19:08:42 +0100
committerDaniel Kolesa <d.kolesa@osg.samsung.com>2016-12-06 19:11:17 +0100
commit2ffc93ddf9c8fd18ccbb051d3fdc408ac3e9b4ed (patch)
tree6464b000cf927a18d9c88e0017261b71b3fa8876
parent5ebba4463570626f836cfb0b07b647c36aad7825 (diff)
downloadefl-2ffc93ddf9c8fd18ccbb051d3fdc408ac3e9b4ed.tar.gz
eolian: add a reference resolver
New API function eolian_doc_token_ref_get will resolve the kind of reference in the given token and extract the necessary data you might need for further use, for example class and function for methods, or struct and field for struct field. It also supports event references that will be added into Eolian later. EFL will be switched to the new resolver (by changing the validator code) during the next step.
-rw-r--r--src/lib/eolian/Eolian.h34
-rw-r--r--src/lib/eolian/eolian_database.c145
-rw-r--r--src/tests/eolian/eolian_parsing.c12
3 files changed, 183 insertions, 8 deletions
diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h
index 57c56694d0..36134829df 100644
--- a/src/lib/eolian/Eolian.h
+++ b/src/lib/eolian/Eolian.h
@@ -341,7 +341,6 @@ typedef enum
EOLIAN_DOC_TOKEN_UNKNOWN = -1,
EOLIAN_DOC_TOKEN_TEXT,
EOLIAN_DOC_TOKEN_REF,
- EOLIAN_DOC_TOKEN_REF_EVENT,
EOLIAN_DOC_TOKEN_MARK_NOTE,
EOLIAN_DOC_TOKEN_MARK_WARNING,
EOLIAN_DOC_TOKEN_MARK_REMARK,
@@ -349,6 +348,20 @@ typedef enum
EOLIAN_DOC_TOKEN_MARKUP_MONOSPACE
} Eolian_Doc_Token_Type;
+typedef enum
+{
+ EOLIAN_DOC_REF_INVALID = 0,
+ EOLIAN_DOC_REF_CLASS,
+ EOLIAN_DOC_REF_FUNC,
+ EOLIAN_DOC_REF_EVENT,
+ EOLIAN_DOC_REF_ALIAS,
+ EOLIAN_DOC_REF_STRUCT,
+ EOLIAN_DOC_REF_STRUCT_FIELD,
+ EOLIAN_DOC_REF_ENUM,
+ EOLIAN_DOC_REF_ENUM_FIELD,
+ EOLIAN_DOC_REF_VAR
+} Eolian_Doc_Ref_Type;
+
typedef struct _Eolian_Doc_Token
{
Eolian_Doc_Token_Type type;
@@ -2378,6 +2391,25 @@ EAPI Eolian_Doc_Token_Type eolian_doc_token_type_get(const Eolian_Doc_Token *tok
*/
EAPI char *eolian_doc_token_text_get(const Eolian_Doc_Token *tok);
+/*
+ * @brief Get the thing that a reference token references.
+ *
+ * Returns EOLIAN_DOC_REF_INVALID on failure (when not ref token or
+ * invalid ref, but invalid refs don't happen when database is validated).
+ *
+ * When the reference is a class, alias, struct, enum or var, the first data arg
+ * is filled. When it's a func, the first data is class and second data is
+ * the respective Eolian_Implement, when it's an event the first data is class
+ * and the second data is the event, when it's a struct field or enum field
+ * the first data is is the struct/enum and the second data is the field.
+ *
+ * @param[in] tok the token
+ * @param[out] data the primary data
+ * @param[out] data2 the secondary data
+ * @return the kind of reference this is
+ */
+EAPI Eolian_Doc_Ref_Type eolian_doc_token_ref_get(const Eolian_Doc_Token *tok, const void **data, const void **data2);
+
#endif
/**
diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c
index 86fb6bc296..5ce177709f 100644
--- a/src/lib/eolian/eolian_database.c
+++ b/src/lib/eolian/eolian_database.c
@@ -302,7 +302,7 @@ _get_ref_token(const char *doc, const char **doc_end)
*doc_end = doc;
/* got a reference */
- return is_event ? EOLIAN_DOC_TOKEN_REF_EVENT : EOLIAN_DOC_TOKEN_REF;
+ return EOLIAN_DOC_TOKEN_REF;
}
EAPI const char *
@@ -417,7 +417,8 @@ mloop:
return ret->text_end;
}
-EAPI void eolian_doc_token_init(Eolian_Doc_Token *tok)
+EAPI void
+eolian_doc_token_init(Eolian_Doc_Token *tok)
{
if (!tok)
return;
@@ -448,6 +449,146 @@ eolian_doc_token_text_get(const Eolian_Doc_Token *tok)
return eina_strbuf_string_steal(buf);
}
+static Eolian_Doc_Ref_Type
+_resolve_event(char *name, const void **data, const void **data2)
+{
+ /* never trust the user */
+ if (name[0] == ',')
+ return EOLIAN_DOC_REF_INVALID;
+
+ char *evname = strrchr(name, '.');
+ if (!evname)
+ return EOLIAN_DOC_REF_INVALID;
+
+ *evname++ = '\0';
+ const Eolian_Class *cl = eolian_class_get_by_name(name);
+ if (!cl)
+ return EOLIAN_DOC_REF_INVALID;
+
+ const Eolian_Event *ev = eolian_class_event_get_by_name(cl, evname);
+ if (!ev)
+ return EOLIAN_DOC_REF_INVALID;
+
+ if (data) *data = cl;
+ if (data2) *data2 = ev;
+ return EOLIAN_DOC_REF_EVENT;
+}
+
+EAPI Eolian_Doc_Ref_Type
+eolian_doc_token_ref_get(const Eolian_Doc_Token *tok, const void **data,
+ const void **data2)
+{
+ if (tok->type != EOLIAN_DOC_TOKEN_REF)
+ return EOLIAN_DOC_REF_INVALID;
+
+ size_t nlen = tok->text_end - tok->text;
+
+ /* events are handled separately */
+ if (tok->text[0] == '[')
+ {
+ /* strip brackets */
+ size_t elen = nlen - 2;
+ char *ename = alloca(elen + 1);
+ memcpy(ename, tok->text + 1, elen);
+ ename[elen] = '\0';
+ return _resolve_event(ename, data, data2);
+ }
+
+ char *name = alloca(nlen + 1);
+ memcpy(name, tok->text, nlen);
+ name[nlen] = '\0';
+
+ const Eolian_Declaration *decl = eolian_declaration_get_by_name(name);
+ if (decl) switch (eolian_declaration_type_get(decl))
+ {
+ case EOLIAN_DECL_CLASS:
+ if (data) *data = eolian_declaration_class_get(decl);
+ return EOLIAN_DOC_REF_CLASS;
+ case EOLIAN_DECL_ALIAS:
+ if (data) *data = eolian_declaration_data_type_get(decl);
+ return EOLIAN_DOC_REF_ALIAS;
+ case EOLIAN_DECL_STRUCT:
+ if (data) *data = eolian_declaration_data_type_get(decl);
+ return EOLIAN_DOC_REF_STRUCT;
+ case EOLIAN_DECL_ENUM:
+ if (data) *data = eolian_declaration_data_type_get(decl);
+ return EOLIAN_DOC_REF_ENUM;
+ case EOLIAN_DECL_VAR:
+ if (data) *data = eolian_declaration_variable_get(decl);
+ return EOLIAN_DOC_REF_VAR;
+ default:
+ /* this will not happen but silence static analyzers */
+ return EOLIAN_DOC_REF_INVALID;
+ }
+
+ /* from here it can only be a function, a struct field or an enum field */
+
+ char *suffix = strrchr(name, '.');
+ /* no suffix, therefore invalid */
+ if (!suffix)
+ return EOLIAN_DOC_REF_INVALID;
+
+ /* name will terminate before suffix, suffix will be standalone */
+ *suffix++ = '\0';
+
+ /* try a struct field */
+ const Eolian_Typedecl *tpd = eolian_typedecl_struct_get_by_name(name);
+ if (tpd)
+ {
+ const Eolian_Struct_Type_Field *fld = eolian_typedecl_struct_field_get(tpd, suffix);
+ /* field itself is invalid */
+ if (!fld)
+ return EOLIAN_DOC_REF_INVALID;
+ if (data) *data = tpd;
+ if (data2) *data2 = fld;
+ return EOLIAN_DOC_REF_STRUCT_FIELD;
+ }
+
+ /* try an enum field */
+ tpd = eolian_typedecl_enum_get_by_name(name);
+ if (tpd)
+ {
+ const Eolian_Enum_Type_Field *fld = eolian_typedecl_enum_field_get(tpd, suffix);
+ /* field itself is invalid */
+ if (!fld)
+ return EOLIAN_DOC_REF_INVALID;
+ if (data) *data = tpd;
+ if (data2) *data2 = fld;
+ return EOLIAN_DOC_REF_ENUM_FIELD;
+ }
+
+ /* now it can only be a function or invalid */
+
+ Eolian_Function_Type ftype = EOLIAN_UNRESOLVED;
+ if (!strcmp(suffix, "get"))
+ ftype = EOLIAN_PROP_GET;
+ else if (!strcmp(suffix, "set"))
+ ftype = EOLIAN_PROP_SET;
+
+ if (ftype != EOLIAN_UNRESOLVED)
+ {
+ suffix = strrchr(name, '.');
+ /* wrong suffix, therefore invalid */
+ if (!suffix)
+ return EOLIAN_DOC_REF_INVALID;
+ /* re-terminate */
+ *suffix++ = '\0';
+ }
+
+ const Eolian_Class *cl = eolian_class_get_by_name(name);
+ if (!cl)
+ return EOLIAN_DOC_REF_INVALID;
+
+ const Eolian_Function *fid = eolian_class_function_get_by_name(cl, suffix, ftype);
+ if (!fid)
+ return EOLIAN_DOC_REF_INVALID;
+
+ /* got a func */
+ if (data) *data = cl;
+ if (data2) *data2 = fid;
+ return EOLIAN_DOC_REF_FUNC;
+}
+
#define EO_SUFFIX ".eo"
#define EOT_SUFFIX ".eot"
diff --git a/src/tests/eolian/eolian_parsing.c b/src/tests/eolian/eolian_parsing.c
index b16494a0da..b7146aeb09 100644
--- a/src/tests/eolian/eolian_parsing.c
+++ b/src/tests/eolian/eolian_parsing.c
@@ -1199,8 +1199,8 @@ START_TEST(eolian_docs)
EINA_LIST_FREE(sdoc, dpar)
free(dpar);
- const char *tdoc = "Note: This is $something, see @Blah, "
- "@Foo.Bar.baz, \\@ref foo and @[Things.Stuffs.foo,bar].";
+ const char *tdoc = "Note: This is $something, see @pants, "
+ "@Docs.meth, \\@ref foo and @[Things.Stuffs.foo,bar].";
Eolian_Doc_Token tok;
eolian_doc_token_init(&tok);
@@ -1228,7 +1228,8 @@ START_TEST(eolian_docs)
tdoc = eolian_documentation_tokenize(tdoc, &tok);
fail_if(eolian_doc_token_type_get(&tok) != EOLIAN_DOC_TOKEN_REF);
txt = eolian_doc_token_text_get(&tok);
- fail_if(strcmp(txt, "Blah"));
+ fail_if(strcmp(txt, "pants"));
+ fail_if(eolian_doc_token_ref_get(&tok, NULL, NULL) != EOLIAN_DOC_REF_VAR);
free(txt);
tdoc = eolian_documentation_tokenize(tdoc, &tok);
fail_if(eolian_doc_token_type_get(&tok) != EOLIAN_DOC_TOKEN_TEXT);
@@ -1238,7 +1239,8 @@ START_TEST(eolian_docs)
tdoc = eolian_documentation_tokenize(tdoc, &tok);
fail_if(eolian_doc_token_type_get(&tok) != EOLIAN_DOC_TOKEN_REF);
txt = eolian_doc_token_text_get(&tok);
- fail_if(strcmp(txt, "Foo.Bar.baz"));
+ fail_if(strcmp(txt, "Docs.meth"));
+ fail_if(eolian_doc_token_ref_get(&tok, NULL, NULL) != EOLIAN_DOC_REF_FUNC);
free(txt);
tdoc = eolian_documentation_tokenize(tdoc, &tok);
fail_if(eolian_doc_token_type_get(&tok) != EOLIAN_DOC_TOKEN_TEXT);
@@ -1246,7 +1248,7 @@ START_TEST(eolian_docs)
fail_if(strcmp(txt, ", @ref foo and "));
free(txt);
tdoc = eolian_documentation_tokenize(tdoc, &tok);
- fail_if(eolian_doc_token_type_get(&tok) != EOLIAN_DOC_TOKEN_REF_EVENT);
+ fail_if(eolian_doc_token_type_get(&tok) != EOLIAN_DOC_TOKEN_REF);
txt = eolian_doc_token_text_get(&tok);
fail_if(strcmp(txt, "[Things.Stuffs.foo,bar]"));
free(txt);