q66 pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=2ffc93ddf9c8fd18ccbb051d3fdc408ac3e9b4ed

commit 2ffc93ddf9c8fd18ccbb051d3fdc408ac3e9b4ed
Author: Daniel Kolesa <d.kol...@osg.samsung.com>
Date:   Tue Dec 6 19:08:42 2016 +0100

    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.
---
 src/lib/eolian/Eolian.h           |  34 ++++++++-
 src/lib/eolian/eolian_database.c  | 145 +++++++++++++++++++++++++++++++++++++-
 src/tests/eolian/eolian_parsing.c |  12 ++--
 3 files changed, 183 insertions(+), 8 deletions(-)

diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h
index 57c5669..3613482 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 86fb6bc..5ce1777 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 b16494a..b7146ae 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);

-- 


Reply via email to