From 7a38f8ec2129a4ae7ca1c1f76fba47d0cd1f7052 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Mon, 8 Jun 2015 15:55:02 +0100 Subject: [PATCH] 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 --- src/lib/eolian/Eolian.h | 13 +++++ src/lib/eolian/eo_lexer.c | 97 ++++++++++++++++++++++++++----- src/lib/eolian/eolian_database.c | 8 +++ src/lib/eolian/eolian_database.h | 1 + src/tests/eolian/data/docs.eo | 9 ++- src/tests/eolian/eolian_parsing.c | 7 +++ 6 files changed, 121 insertions(+), 14 deletions(-) diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index 2ecb5821d2..cb6b97eb0f 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -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 /** diff --git a/src/lib/eolian/eo_lexer.c b/src/lib/eolian/eo_lexer.c index b0c73904dc..3ed337ae64 100644 --- a/src/lib/eolian/eo_lexer.c +++ b/src/lib/eolian/eo_lexer.c @@ -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 diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c index cc23f87d6b..4ebc9785a7 100644 --- a/src/lib/eolian/eolian_database.c +++ b/src/lib/eolian/eolian_database.c @@ -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" diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index c3a7a55b30..91b12f78c1 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -65,6 +65,7 @@ struct _Eolian_Documentation Eolian_Object base; Eina_Stringshare *summary; Eina_Stringshare *description; + Eina_Stringshare *since; }; struct _Eolian_Declaration diff --git a/src/tests/eolian/data/docs.eo b/src/tests/eolian/data/docs.eo index eb89c929f6..c7c8622fe7 100644 --- a/src/tests/eolian/data/docs.eo +++ b/src/tests/eolian/data/docs.eo @@ -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.]] } diff --git a/src/tests/eolian/eolian_parsing.c b/src/tests/eolian/eolian_parsing.c index ed0626a9eb..f5e441ba85 100644 --- a/src/tests/eolian/eolian_parsing.c +++ b/src/tests/eolian/eolian_parsing.c @@ -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."));