eolian: support for @since tag in new doc comments

This is kind of ugly, but I didn't see a better way to do it without turning
this into a much more complicated parser. So this will have to do unless we
find something else to add, in which case a new doc parser will be required.

@feature
This commit is contained in:
Daniel Kolesa 2015-06-08 15:55:02 +01:00
parent 15a64fdc86
commit 7a38f8ec21
6 changed files with 121 additions and 14 deletions

View File

@ -2239,6 +2239,19 @@ EAPI Eina_Stringshare *eolian_documentation_summary_get(const Eolian_Documentati
*/
EAPI Eina_Stringshare *eolian_documentation_description_get(const Eolian_Documentation *doc);
/*
* @brief Get the "since" tag of the documentation.
*
* This can return NULL if the tag wasn't specified or
* if the input is wrong.
*
* @param[in] doc the documentation
* @return the description or NULL
*
* @ingroup Eolian
*/
EAPI Eina_Stringshare *eolian_documentation_since_get(const Eolian_Documentation *doc);
#endif
/**

View File

@ -252,6 +252,15 @@ cend:
if (tok) tok->value.s = eina_stringshare_add(eina_strbuf_string_get(ls->buff));
}
void doc_error(Eo_Lexer *ls, const char *msg, Eolian_Documentation *doc, Eina_Strbuf *buf)
{
eina_stringshare_del(doc->summary);
eina_stringshare_del(doc->description);
free(doc);
eina_strbuf_free(buf);
eo_lexer_lex_error(ls, msg, -1);
}
static void
read_doc(Eo_Lexer *ls, Eo_Token *tok, int line, int column)
{
@ -270,8 +279,7 @@ read_doc(Eo_Lexer *ls, Eo_Token *tok, int line, int column)
{
if (!ls->current)
{
free(doc);
eo_lexer_lex_error(ls, "unfinished documentation", -1);
doc_error(ls, "unfinished documentation", doc, NULL);
return; /* unreachable, for static analysis */
}
if (is_newline(ls->current))
@ -312,18 +320,79 @@ read_doc(Eo_Lexer *ls, Eo_Token *tok, int line, int column)
doc->summary = eina_stringshare_add(eina_strbuf_string_get(ls->buff));
Eina_Strbuf *rbuf = eina_strbuf_new();
Eina_Bool had_nl = EINA_TRUE;
for (;;)
{
if (!ls->current)
{
eina_stringshare_del(doc->summary);
free(doc);
eina_strbuf_free(rbuf);
eo_lexer_lex_error(ls, "unfinished documentation", -1);
doc_error(ls, "unfinished documentation", doc, NULL);
return; /* unreachable, for static analysis */
}
eina_strbuf_reset(ls->buff);
if (had_nl && ls->current == '@')
{
#define LEX_SINCE(c, failure) \
next_char(ls); \
if (ls->current != c) \
{ \
eina_strbuf_append(ls->buff, failure); \
goto normal; \
}
LEX_SINCE('s', "@");
LEX_SINCE('i', "@s");
LEX_SINCE('n', "@si");
LEX_SINCE('c', "@sin");
LEX_SINCE('e', "@sinc");
LEX_SINCE(' ', "@since");
#undef LEX_SINCE
skip_ws(ls);
/* gotta have a value */
if (!ls->current || is_newline(ls->current) || ls->current == ']')
goto docerr;
/* append the since string */
while (ls->current && ls->current != ']' && !is_newline(ls->current))
{
eina_strbuf_append_char(ls->buff, ls->current);
next_char(ls);
}
/* trigger "unfinished documentation" if things end early */
if (!ls->current)
continue;
/* strip final whitespace */
while (isspace(ls->current))
{
if (is_newline(ls->current))
next_line(ls);
else
next_char(ls);
}
if (ls->current != ']') goto docerr;
next_char(ls);
if (ls->current != ']') goto docerr;
next_char(ls);
eina_strbuf_trim(ls->buff);
doc->since = eina_stringshare_add(eina_strbuf_string_get(ls->buff));
goto done;
docerr:
doc_error(ls, "mangled documentation", doc, rbuf);
return;
}
normal:
had_nl = EINA_FALSE;
while (ls->current && !is_newline(ls->current))
{
if (ls->current == ']')
@ -336,13 +405,7 @@ read_doc(Eo_Lexer *ls, Eo_Token *tok, int line, int column)
next_char(ls);
eina_strbuf_trim(ls->buff);
eina_strbuf_append(rbuf, eina_strbuf_string_get(ls->buff));
eina_strbuf_trim(rbuf);
if (eina_strbuf_string_get(rbuf)[0])
doc->description = eina_stringshare_add(
eina_strbuf_string_get(rbuf));
eina_strbuf_free(rbuf);
tok->value.doc = doc;
return;
goto done;
}
}
eina_strbuf_append_char(ls->buff, ls->current);
@ -361,8 +424,16 @@ read_doc(Eo_Lexer *ls, Eo_Token *tok, int line, int column)
eina_strbuf_append_char(rbuf, ' ');
while (is_newline(ls->current))
next_line_ws(ls);
had_nl = EINA_TRUE;
}
}
done:
eina_strbuf_trim(rbuf);
if (eina_strbuf_string_get(rbuf)[0])
doc->description = eina_stringshare_add(eina_strbuf_string_get(rbuf));
eina_strbuf_free(rbuf);
tok->value.doc = doc;
}
static void

View File

@ -166,6 +166,7 @@ void database_doc_del(Eolian_Documentation *doc)
if (!doc) return;
eina_stringshare_del(doc->summary);
eina_stringshare_del(doc->description);
eina_stringshare_del(doc->since);
free(doc);
}
@ -183,6 +184,13 @@ eolian_documentation_description_get(const Eolian_Documentation *doc)
return doc->description;
}
EAPI Eina_Stringshare *
eolian_documentation_since_get(const Eolian_Documentation *doc)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(doc, NULL);
return doc->since;
}
#define EO_SUFFIX ".eo"
#define EOT_SUFFIX ".eot"

View File

@ -65,6 +65,7 @@ struct _Eolian_Documentation
Eolian_Object base;
Eina_Stringshare *summary;
Eina_Stringshare *description;
Eina_Stringshare *since;
};
struct _Eolian_Declaration

View File

@ -5,6 +5,8 @@ struct Foo {
This is a longer description for struct Foo.
This is another paragraph.
@since 1.66
]]
field1: int; [[Field documentation.]]
field2: float;
@ -22,6 +24,8 @@ type Alias: Bar; [[Docs for typedef.
More docs for typedef.
See @Bar.
@since 2.0
]]
var pants: int = 150; [[Docs for var.]]
@ -48,7 +52,10 @@ class Docs {
return: int; [[Return documentation.]]
}
@property prop {
[[Property common documentation.]]
[[Property common documentation.
@since 1.18
]]
get {
[[Get documentation.]]
}

View File

@ -1125,6 +1125,8 @@ START_TEST(eolian_docs)
fail_if(strcmp(eolian_documentation_description_get(doc),
"This is a longer description for struct Foo.\n\n"
"This is another paragraph."));
fail_if(strcmp(eolian_documentation_since_get(doc),
"1.66"));
fail_if(!(sfl = eolian_type_struct_field_get(type, "field1")));
fail_if(!(doc = eolian_type_struct_field_documentation_get(sfl)));
@ -1146,6 +1148,7 @@ START_TEST(eolian_docs)
fail_if(strcmp(eolian_documentation_summary_get(doc),
"Docs for enum Bar."));
fail_if(eolian_documentation_description_get(doc));
fail_if(eolian_documentation_since_get(doc));
fail_if(!(efl = eolian_type_enum_field_get(type, "blah")));
fail_if(eolian_type_enum_field_documentation_get(efl));
@ -1168,6 +1171,8 @@ START_TEST(eolian_docs)
"Docs for typedef."));
fail_if(strcmp(eolian_documentation_description_get(doc),
"More docs for typedef. See @Bar."));
fail_if(strcmp(eolian_documentation_since_get(doc),
"2.0"));
fail_if(!(var = eolian_variable_global_get_by_name("pants")));
fail_if(!(doc = eolian_variable_documentation_get(var)));
@ -1224,6 +1229,8 @@ START_TEST(eolian_docs)
fail_if(strcmp(eolian_documentation_summary_get(doc),
"Property common documentation."));
fail_if(eolian_documentation_description_get(doc));
fail_if(strcmp(eolian_documentation_since_get(doc),
"1.18"));
fail_if(!(doc = eolian_function_documentation_get(fid, EOLIAN_PROP_GET)));
fail_if(strcmp(eolian_documentation_summary_get(doc),
"Get documentation."));