From 5f22486457aac995ccc082192c3751fcc095d714 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sat, 29 Apr 2023 15:38:01 +0100 Subject: [PATCH] [D] parse user-defined attributes --- Units/parser-d.r/simple.d.d/expected.tags | 40 +++++++++++++++++++++++ Units/parser-d.r/simple.d.d/input.d | 5 +++ parsers/c-based.c | 17 +++++++--- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/Units/parser-d.r/simple.d.d/expected.tags b/Units/parser-d.r/simple.d.d/expected.tags index 44027c6f1b..c7e04df1c7 100644 --- a/Units/parser-d.r/simple.d.d/expected.tags +++ b/Units/parser-d.r/simple.d.d/expected.tags @@ -1,3 +1,41 @@ +!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/ +!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/ +!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/ +!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/ +!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/ +!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/ +!_TAG_FIELD_DESCRIPTION input /input file/ +!_TAG_FIELD_DESCRIPTION name /tag name/ +!_TAG_FIELD_DESCRIPTION pattern /pattern/ +!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_KIND_DESCRIPTION!D M,module /modules/ +!_TAG_KIND_DESCRIPTION!D T,template /templates/ +!_TAG_KIND_DESCRIPTION!D V,version /version statements/ +!_TAG_KIND_DESCRIPTION!D X,mixin /mixins/ +!_TAG_KIND_DESCRIPTION!D a,alias /aliases/ +!_TAG_KIND_DESCRIPTION!D c,class /classes/ +!_TAG_KIND_DESCRIPTION!D e,enumerator /enumerators (values inside an enumeration)/ +!_TAG_KIND_DESCRIPTION!D f,function /function definitions/ +!_TAG_KIND_DESCRIPTION!D g,enum /enumeration names/ +!_TAG_KIND_DESCRIPTION!D i,interface /interfaces/ +!_TAG_KIND_DESCRIPTION!D m,member /class, struct, and union members/ +!_TAG_KIND_DESCRIPTION!D n,namespace /namespaces/ +!_TAG_KIND_DESCRIPTION!D s,struct /structure names/ +!_TAG_KIND_DESCRIPTION!D u,union /union names/ +!_TAG_KIND_DESCRIPTION!D v,variable /variable definitions/ +!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ +!_TAG_OUTPUT_FILESEP slash /slash or backslash/ +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ +!_TAG_OUTPUT_VERSION 0.0 /current.age/ +!_TAG_PARSER_VERSION!D 0.0 /current.age/ +!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ +!_TAG_PROC_CWD /home/nick/git/ctags/Units/parser-d.r/simple.d.d/ // +!_TAG_PROGRAM_AUTHOR Universal Ctags Team // +!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ +!_TAG_PROGRAM_URL https://ctags.io/ /official site/ +!_TAG_PROGRAM_VERSION 6.0.0 /4a101fd4/ AliasInt input.d /^alias AliasInt = int;$/;" a file: CT input.d /^ class CT(T)$/;" c class:Class file: Class input.d /^class Class : Interface$/;" c file: @@ -11,6 +49,8 @@ TemplateAlias input.d /^ alias TemplateAlias = a!T;$/;" a file: UT input.d /^union UT(T){}$/;" u file: Union input.d /^ union Union$/;" u struct:Struct file: _bar input.d /^ private AliasInt _bar;$/;" m class:Class file: +attr_anon input.d /^@(obj) T attr_anon;$/;" v +attr_decl input.d /^@attr(i) int attr_decl = 1;$/;" v bar input.d /^ bar,$/;" e enum:Enum file: bar input.d /^ public AliasInt bar()$/;" f class:Class conditional input.d /^ T conditional;$/;" v file: diff --git a/Units/parser-d.r/simple.d.d/input.d b/Units/parser-d.r/simple.d.d/input.d index d2878c24f9..baa0eef396 100644 --- a/Units/parser-d.r/simple.d.d/input.d +++ b/Units/parser-d.r/simple.d.d/input.d @@ -78,6 +78,11 @@ int i; int error; +/ +@attr(i) int attr_decl = 1; +@attr(i) attr_decl_infer = 1; // FIXME +@(obj) T attr_anon; +void attr_post() @attr(obj); // FIXME + static if (is(typeof(__traits(getMember, a, name)) == function)) T conditional; diff --git a/parsers/c-based.c b/parsers/c-based.c index 0f53f687d3..f340544e6b 100644 --- a/parsers/c-based.c +++ b/parsers/c-based.c @@ -494,6 +494,7 @@ static const keywordDesc KeywordTable [] = { * FUNCTION PROTOTYPES */ static void createTags (const unsigned int nestLevel, statementInfo *const parent); +static void parseJavaAnnotation (statementInfo *const st); /* * FUNCTION DEFINITIONS @@ -2122,6 +2123,10 @@ static bool skipPostArgumentStuff ( break; } } + else if (isInputLanguage (Lang_d) && c == '@') + { + parseJavaAnnotation (st); + } } if (! end) { @@ -2225,7 +2230,11 @@ static void parseJavaAnnotation (statementInfo *const st) tokenInfo *const token = activeToken (st); int c = skipToNonWhite (); - readIdentifier (token, c); + if (cppIsident1 (c)) + readIdentifier (token, c); + else + cppUngetc (c); // D allows: @ ( ArgumentList ) + if (token->keyword == KEYWORD_INTERFACE) { /* Oops. This was actually "@interface" defining a new annotation. */ @@ -2346,9 +2355,9 @@ static int parseParens (statementInfo *const st, parenInfo *const info) break; default: - if (c == '@' && isInputLanguage (Lang_java)) + if (c == '@' && (isInputLanguage (Lang_d) || isInputLanguage (Lang_java))) { - parseJavaAnnotation(st); + parseJavaAnnotation (st); } else if (cppIsident1 (c)) { @@ -2637,7 +2646,7 @@ static void parseGeneralToken (statementInfo *const st, const int c) if (c2 != '=') cppUngetc (c2); } - else if (c == '@' && isInputLanguage (Lang_java)) + else if (c == '@' && (isInputLanguage (Lang_d) || isInputLanguage (Lang_java))) { parseJavaAnnotation (st); }