eolian/generator: add proper generation of references

Adds proper generation of automatic references in docs.
For now events are missing.

@feature
This commit is contained in:
Daniel Kolesa 2015-07-07 17:19:13 +01:00
parent 70b7043731
commit e9688e63a5
7 changed files with 328 additions and 5 deletions

View File

@ -138,4 +138,6 @@ tests/eolian/data/override_ref.c \
tests/eolian/data/class_simple_ref_eo.h \
tests/eolian/data/class_simple_ref_legacy.h \
tests/eolian/data/import_types_ref.h \
tests/eolian/data/docs_ref.h \
tests/eolian/data/docs_ref_legacy.h \
$(EOLIAN_TESTS_EOS)

View File

@ -22,6 +22,98 @@ _indent_line(Eina_Strbuf *buf, int ind)
#define DOC_LIMIT(ind) ((ind > DOC_LINE_TEST) ? (ind + DOC_LINE_OVER) \
: DOC_LINE_LIMIT)
static void
_generate_ref(const char *refn, Eina_Strbuf *wbuf)
{
const Eolian_Declaration *decl = eolian_declaration_get_by_name(refn);
if (decl)
{
char *n = strdup(eolian_declaration_name_get(decl));
char *p = n;
while ((p = strchr(p, '.'))) *p = '_';
eina_strbuf_append(wbuf, n);
free(n);
return;
}
/* not a plain declaration, so it must be struct/enum field or func */
const char *sfx = strrchr(refn, '.');
if (!sfx) goto noref;
Eina_Stringshare *bname = eina_stringshare_add_length(refn, sfx - refn);
const Eolian_Type *tp = eolian_type_struct_get_by_name(bname);
if (tp)
{
if (!eolian_type_struct_field_get(tp, sfx + 1)) goto noref;
_generate_ref(bname, wbuf);
eina_strbuf_append(wbuf, sfx);
eina_stringshare_del(bname);
return;
}
tp = eolian_type_enum_get_by_name(bname);
if (tp)
{
const Eolian_Enum_Type_Field *efl = eolian_type_enum_field_get(tp, sfx + 1);
if (!efl) goto noref;
_generate_ref(bname, wbuf);
Eina_Stringshare *str = eolian_type_enum_field_c_name_get(efl);
eina_strbuf_append_char(wbuf, '.');
eina_strbuf_append(wbuf, str);
eina_stringshare_del(str);
eina_stringshare_del(bname);
return;
}
const Eolian_Class *cl = eolian_class_get_by_name(bname);
const Eolian_Function *fn = NULL;
Eolian_Function_Type ftype = EOLIAN_UNRESOLVED;
if (!cl)
{
const char *mname;
if (!strcmp(sfx, ".get")) ftype = EOLIAN_PROP_GET;
else if (!strcmp(sfx, ".set")) ftype = EOLIAN_PROP_SET;
if (ftype != EOLIAN_UNRESOLVED)
{
eina_stringshare_del(bname);
mname = sfx - 1;
while ((mname != refn) && (*mname != '.')) --mname;
if (mname == refn) goto noref;
bname = eina_stringshare_add_length(refn, mname - refn);
cl = eolian_class_get_by_name(bname);
eina_stringshare_del(bname);
}
if (cl)
{
char *meth = strndup(mname + 1, sfx - mname - 1);
fn = eolian_class_function_get_by_name(cl, meth, ftype);
if (ftype == EOLIAN_UNRESOLVED)
ftype = eolian_function_type_get(fn);
free(meth);
}
}
else
{
fn = eolian_class_function_get_by_name(cl, sfx + 1, ftype);
ftype = eolian_function_type_get(fn);
}
if (!fn) goto noref;
Eina_Stringshare *fcn = eolian_function_full_c_name_get(fn);
eina_strbuf_append(wbuf, fcn);
eina_stringshare_del(fcn);
if ((ftype == EOLIAN_PROP_GET) || (ftype == EOLIAN_PROPERTY))
eina_strbuf_append(wbuf, "_get");
else if (ftype == EOLIAN_PROP_SET)
eina_strbuf_append(wbuf, "_set");
return;
noref:
eina_strbuf_append(wbuf, refn);
}
int
_append_section(const char *desc, int ind, int curl, Eina_Strbuf *buf,
Eina_Strbuf *wbuf)
@ -40,9 +132,17 @@ _append_section(const char *desc, int ind, int curl, Eina_Strbuf *buf,
}
else if (*desc == '@')
{
desc++;
if (isalpha(*desc))
eina_strbuf_append(wbuf, "@ref ");
const char *ref = ++desc;
if (isalpha(*desc) || (*desc == '_'))
{
eina_strbuf_append(wbuf, "@ref ");
while (isalnum(*desc) || (*desc == '.') || (*desc == '_'))
++desc;
if (*(desc - 1) == '.') --desc;
Eina_Stringshare *refn = eina_stringshare_add_length(ref, desc - ref);
_generate_ref(refn, wbuf);
eina_stringshare_del(refn);
}
else
eina_strbuf_append_char(wbuf, '@');
}

View File

@ -35,11 +35,18 @@ struct Opaque; [[Opaque struct docs. See @Foo for another struct.]]
class Docs {
[[Docs for class.
More docs for class. @.prop.
More docs for class. Testing references now.
@Foo
@Bar
@Alias
@pants
@.meth
@.prop
@.prop.get
@.prop.set
@Foo.field1
@Bar.foo
@Docs
]]
methods {
meth {

View File

@ -0,0 +1,100 @@
#ifndef _EOLIAN_OUTPUT_H_
#define _EOLIAN_OUTPUT_H_
#ifndef _DOCS_EO_CLASS_TYPE
#define _DOCS_EO_CLASS_TYPE
typedef Eo Docs;
#endif
#ifndef _DOCS_EO_TYPES
#define _DOCS_EO_TYPES
/**
* @brief This is struct Foo. It does stuff.
*
* This is a longer description for struct Foo.
*
* This is another paragraph.
*
* @since 1.66
*/
typedef struct _Foo
{
int field1; /** Field documentation. */
float field2;
short field3; /** Another field documentation. */
} Foo;
/** Docs for enum Bar. */
typedef enum
{
BAR_BLAH = 0,
BAR_FOO = 1, /** Docs for foo. */
BAR_BAR = 2 /** Docs for bar. */
} Bar;
/**
* @brief Docs for typedef.
*
* More docs for typedef. See @ref Bar.
*
* @since 2.0
*/
typedef Bar Alias;
/** Opaque struct docs. See @ref Foo for another struct. */
typedef struct _Opaque Opaque;
#endif
/**
* @brief Docs for class.
*
* More docs for class. Testing references now. @ref Foo @ref Bar @ref Alias
* @ref pants @ref docs_meth @ref docs_prop_get @ref docs_prop_get
* @ref docs_prop_set @ref Foo.field1 @ref Bar.BAR_FOO @ref Docs
*/
#define DOCS_CLASS docs_class_get()
EAPI const Eo_Class *docs_class_get(void) EINA_CONST;
/**
* @brief Property common documentation.
*
* Set documentation.
*
* @param[in] val Value documentation.
*
* @since 1.18
*/
EOAPI void docs_prop_set(int val);
/**
* @brief Property common documentation.
*
* Get documentation.
*
* @return Value documentation.
*
* @since 1.18
*/
EOAPI int docs_prop_get(void);
/**
* @brief Method documentation.
*
* @param[out] b
* @param[out] c Another param documentation.
*
* @return Return documentation.
*/
EOAPI int docs_meth(int a, float *b, long *c);
EOAPI extern const Eo_Event_Description _DOCS_EVENT_CLICKED;
/** Event docs. */
#define DOCS_EVENT_CLICKED (&(_DOCS_EVENT_CLICKED))
#endif

View File

@ -0,0 +1,92 @@
#ifndef _EOLIAN_OUTPUT_H_
#define _EOLIAN_OUTPUT_H_
#ifndef _DOCS_EO_CLASS_TYPE
#define _DOCS_EO_CLASS_TYPE
typedef Eo Docs;
#endif
#ifndef _DOCS_EO_TYPES
#define _DOCS_EO_TYPES
/**
* @brief This is struct Foo. It does stuff.
*
* This is a longer description for struct Foo.
*
* This is another paragraph.
*
* @since 1.66
*/
typedef struct _Foo
{
int field1; /** Field documentation. */
float field2;
short field3; /** Another field documentation. */
} Foo;
/** Docs for enum Bar. */
typedef enum
{
BAR_BLAH = 0,
BAR_FOO = 1, /** Docs for foo. */
BAR_BAR = 2 /** Docs for bar. */
} Bar;
/**
* @brief Docs for typedef.
*
* More docs for typedef. See @ref Bar.
*
* @since 2.0
*/
typedef Bar Alias;
/** Opaque struct docs. See @ref Foo for another struct. */
typedef struct _Opaque Opaque;
#endif
/**
* @brief Docs for class.
*
* More docs for class. Testing references now. @ref Foo @ref Bar @ref Alias
* @ref pants @ref docs_meth @ref docs_prop_get @ref docs_prop_get
* @ref docs_prop_set @ref Foo.field1 @ref Bar.BAR_FOO @ref Docs
*/
/**
* @brief Property common documentation.
*
* Set documentation.
*
* @param[in] val Value documentation.
*
* @since 1.18
*/
EAPI void docs_prop_set(Docs *obj, int val);
/**
* @brief Property common documentation.
*
* Get documentation.
*
* @return Value documentation.
*
* @since 1.18
*/
EAPI int docs_prop_get(const Docs *obj);
/**
* @brief Method documentation.
*
* @param[out] b
* @param[out] c Another param documentation.
*
* @return Return documentation.
*/
EAPI int docs_meth(Docs *obj, int a, float *b, long *c);
#endif

View File

@ -192,6 +192,25 @@ START_TEST(eolian_import)
}
END_TEST
START_TEST(eolian_docs)
{
char output_filepath[PATH_MAX] = "";
snprintf(output_filepath, PATH_MAX, "%s/eolian_output.h",
#ifdef HAVE_EVIL
(char *)evil_tmpdir_get()
#else
"/tmp"
#endif
);
remove(output_filepath);
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/docs.eo", "--eo --gh", output_filepath));
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/docs_ref.h", output_filepath));
remove(output_filepath);
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/docs.eo", "--legacy --gh", output_filepath));
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/docs_ref_legacy.h", output_filepath));
}
END_TEST
void eolian_generation_test(TCase *tc)
{
tcase_add_test(tc, eolian_types_generation);
@ -200,5 +219,6 @@ void eolian_generation_test(TCase *tc)
tcase_add_test(tc, eolian_dev_impl_code);
tcase_add_test(tc, eolian_functions_descriptions);
tcase_add_test(tc, eolian_import);
tcase_add_test(tc, eolian_docs);
}

View File

@ -1199,7 +1199,9 @@ START_TEST(eolian_docs)
fail_if(strcmp(eolian_documentation_summary_get(doc),
"Docs for class."));
fail_if(strcmp(eolian_documentation_description_get(doc),
"More docs for class. @Docs.prop. @Foo @Bar @Alias @pants"));
"More docs for class. Testing references now. "
"@Foo @Bar @Alias @pants @Docs.meth @Docs.prop "
"@Docs.prop.get @Docs.prop.set @Foo.field1 @Bar.foo @Docs"));
fail_if(!(fid = eolian_class_function_get_by_name(class, "meth", EOLIAN_METHOD)));
fail_if(!(doc = eolian_function_documentation_get(fid, EOLIAN_METHOD)));