From 56f3adebb298e22241eccb862137fce638e0e015 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Fri, 26 Aug 2022 04:44:45 +0900 Subject: [PATCH] Verilog: extract module names used for declaring instances as reference tags This one is conceptually based on https://github.com/universal-ctags/ctags/compare/master...my2817:ctags:master reported and written by @my2817 at #3469. The test case is also taken from #3469 submitted by @my2817. --- Tmain/list-roles.d/stdout-expected.txt | 4 ++ .../verilog-module-ref.d/args.ctags | 3 ++ .../verilog-module-ref.d/expected.tags | 10 +++++ .../verilog-module-ref.d/input.v | 12 ++++++ docs/man/ctags-lang-verilog.7.rst | 23 ++++++++++ man/ctags-lang-verilog.7.rst.in | 22 ++++++++++ parsers/verilog.c | 43 ++++++++++++++++--- 7 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 Units/parser-verilog.r/verilog-module-ref.d/args.ctags create mode 100644 Units/parser-verilog.r/verilog-module-ref.d/expected.tags create mode 100644 Units/parser-verilog.r/verilog-module-ref.d/input.v diff --git a/Tmain/list-roles.d/stdout-expected.txt b/Tmain/list-roles.d/stdout-expected.txt index 2e7d385249..594c897b2c 100644 --- a/Tmain/list-roles.d/stdout-expected.txt +++ b/Tmain/list-roles.d/stdout-expected.txt @@ -92,6 +92,7 @@ Ruby L/library required on loaded by "require" Ruby L/library requiredRel on loaded by "require_relative" method Sh h/heredoc endmarker on end marker Sh s/script loaded on loaded +SystemVerilog m/module decl on declaring instances SystemdUnit u/unit After on referred in After key SystemdUnit u/unit Before on referred in Before key SystemdUnit u/unit RequiredBy on referred in RequiredBy key @@ -108,6 +109,7 @@ Vera d/macro condition off used in part of #if/ Vera d/macro undef on undefined Vera h/header local on local header Vera h/header system on system header +Verilog m/module decl on declaring instances # # all.* @@ -202,6 +204,7 @@ Ruby L/library required on loaded by "require" Ruby L/library requiredRel on loaded by "require_relative" method Sh h/heredoc endmarker on end marker Sh s/script loaded on loaded +SystemVerilog m/module decl on declaring instances SystemdUnit u/unit After on referred in After key SystemdUnit u/unit Before on referred in Before key SystemdUnit u/unit RequiredBy on referred in RequiredBy key @@ -218,6 +221,7 @@ Vera d/macro condition off used in part of #if/ Vera d/macro undef on undefined Vera h/header local on local header Vera h/header system on system header +Verilog m/module decl on declaring instances # # C.* diff --git a/Units/parser-verilog.r/verilog-module-ref.d/args.ctags b/Units/parser-verilog.r/verilog-module-ref.d/args.ctags new file mode 100644 index 0000000000..41f6dbed62 --- /dev/null +++ b/Units/parser-verilog.r/verilog-module-ref.d/args.ctags @@ -0,0 +1,3 @@ +--sort=no +--extras=+r +--fields=+r diff --git a/Units/parser-verilog.r/verilog-module-ref.d/expected.tags b/Units/parser-verilog.r/verilog-module-ref.d/expected.tags new file mode 100644 index 0000000000..de43f189c8 --- /dev/null +++ b/Units/parser-verilog.r/verilog-module-ref.d/expected.tags @@ -0,0 +1,10 @@ +test input.v /^module test (\/*AUTOARG*\/);$/;" m roles:def +i_a input.v /^ input i_a, i_b;$/;" p module:test roles:def +i_b input.v /^ input i_a, i_b;$/;" p module:test roles:def +o_c input.v /^ output o_c;$/;" p module:test roles:def +int1 input.v /^ ref1 int1 ();$/;" i module:test typeref:module:ref1 roles:def +ref1 input.v /^ ref1 int1 ();$/;" m module:test roles:decl +int2 input.v /^ ref1 int2 ();$/;" i module:test typeref:module:ref1 roles:def +ref1 input.v /^ ref1 int2 ();$/;" m module:test roles:decl +int3 input.v /^ int3 ();$/;" i module:test typeref:module:ref3 roles:def +ref3 input.v /^ ref3 # (.A (aaa),$/;" m module:test roles:decl diff --git a/Units/parser-verilog.r/verilog-module-ref.d/input.v b/Units/parser-verilog.r/verilog-module-ref.d/input.v new file mode 100644 index 0000000000..1e5c93a962 --- /dev/null +++ b/Units/parser-verilog.r/verilog-module-ref.d/input.v @@ -0,0 +1,12 @@ +// Taken from #3469 submitted by @my2817 +module test (/*AUTOARG*/); + input i_a, i_b; + output o_c; + + ref1 int1 (); + ref1 int2 (); + ref3 # (.A (aaa), + .B (bbb)) + int3 (); + +endmodule // test diff --git a/docs/man/ctags-lang-verilog.7.rst b/docs/man/ctags-lang-verilog.7.rst index 9bb8a6071f..03c255646b 100644 --- a/docs/man/ctags-lang-verilog.7.rst +++ b/docs/man/ctags-lang-verilog.7.rst @@ -162,6 +162,29 @@ because they cannot be overridden. P3 input.sv /^ parameter P3 = "parameter";$/;" c module:no_parameter_port_list parameter: L7 input.sv /^ localparam L7 = "localparam";$/;" c module:no_parameter_port_list +Supported Roles +~~~~~~~~~~~~~~~ + +.. warning:: + + The support for references in Universal Ctags is still + experimental; the names of the roles can be changed in the future. + + +.. code-block:: console + + $ ./ctags --list-roles=SystemVerilog + #KIND(L/N) NAME ENABLED DESCRIPTION + m/module decl on declaring instances + + $ ./ctags --list-roles=Verilog + #KIND(L/N) NAME ENABLED DESCRIPTION + m/module decl on declaring instances + +The parsers extract modules names used in instance declarations as +reference tags. ``decl`` is the role for the names. See "TAG ENTRIES" +section of :ref:`ctags(1) ` about reference tags and roles. + TIPS ~~~~ diff --git a/man/ctags-lang-verilog.7.rst.in b/man/ctags-lang-verilog.7.rst.in index 1843e2ef78..0b34bb9e73 100644 --- a/man/ctags-lang-verilog.7.rst.in +++ b/man/ctags-lang-verilog.7.rst.in @@ -162,6 +162,28 @@ because they cannot be overridden. P3 input.sv /^ parameter P3 = "parameter";$/;" c module:no_parameter_port_list parameter: L7 input.sv /^ localparam L7 = "localparam";$/;" c module:no_parameter_port_list +Supported Roles +~~~~~~~~~~~~~~~ + +.. code-block:: console + + $ ./ctags --list-roles=SystemVerilog + #KIND(L/N) NAME ENABLED DESCRIPTION + m/module decl on declaring instances + + $ ./ctags --list-roles=Verilog + #KIND(L/N) NAME ENABLED DESCRIPTION + m/module decl on declaring instances + +The parsers extract modules names used in instance declarations as +reference tags. ``decl`` is the role for the tags. See "TAG ENTRIES" +section of ctags(1) about reference tags and roles. + +.. warning:: + + The support for references in Universal Ctags is still + experimental; the names of the roles may be changed in the future. + TIPS ~~~~ diff --git a/parsers/verilog.c b/parsers/verilog.c index 63f9b5b672..9b7bb5f774 100644 --- a/parsers/verilog.c +++ b/parsers/verilog.c @@ -108,6 +108,10 @@ typedef enum { K_NETTYPE, } verilogKind; +typedef enum { + R_MODULE_DECL, +} verilogModuleRole; + typedef struct { const char *keyword; verilogKind kind; @@ -141,11 +145,20 @@ static int Ungetc; static int Lang_verilog; static int Lang_systemverilog; +static roleDefinition VerilogModuleRoles [] = { + { true, "decl", "declaring instances" }, +}; + +static roleDefinition SystemVerilogModuleRoles [] = { + { true, "decl", "declaring instances" }, +}; + static kindDefinition VerilogKinds [] = { { true, 'c', "constant", "constants (define, parameter, specparam)" }, { true, 'e', "event", "events" }, { true, 'f', "function", "functions" }, - { true, 'm', "module", "modules" }, + { true, 'm', "module", "modules", + .referenceOnly = false, ATTACH_ROLES(VerilogModuleRoles) }, { true, 'n', "net", "net data types" }, { true, 'p', "port", "ports" }, { true, 'r', "register", "variable data types" }, @@ -158,7 +171,8 @@ static kindDefinition SystemVerilogKinds [] = { { true, 'c', "constant", "constants (define, parameter, specparam, enum values)" }, { true, 'e', "event", "events" }, { true, 'f', "function", "functions" }, - { true, 'm', "module", "modules" }, + { true, 'm', "module", "modules", + .referenceOnly = false, ATTACH_ROLES(SystemVerilogModuleRoles) }, { true, 'n', "net", "net data types" }, { true, 'p', "port", "ports" }, { true, 'r', "register", "variable data types" }, @@ -949,7 +963,7 @@ static int dropEndContext (tokenInfo *const token, int c) } -static void createTagWithTypeRef (tokenInfo *const token, verilogKind kind, tokenInfo *const typeref) +static void createTagFull (tokenInfo *const token, verilogKind kind, int role, tokenInfo *const typeref) { tagEntryInfo tag; @@ -981,7 +995,10 @@ static void createTagWithTypeRef (tokenInfo *const token, verilogKind kind, toke } /* Create tag */ - initTagEntry (&tag, vStringValue (token->name), kind); + if (role == ROLE_DEFINITION_INDEX) + initTagEntry (&tag, vStringValue (token->name), kind); + else + initRefTagEntry (&tag, vStringValue (token->name), kind, role); tag.lineNumber = token->lineNumber; tag.filePosition = token->filePosition; @@ -1011,7 +1028,8 @@ static void createTagWithTypeRef (tokenInfo *const token, verilogKind kind, toke makeTagEntry (&tag); - if (isXtagEnabled (XTAG_QUALIFIED_TAGS) && currentContext->kind != K_UNDEFINED) + if (isXtagEnabled (XTAG_QUALIFIED_TAGS) && currentContext->kind != K_UNDEFINED + && role == ROLE_DEFINITION_INDEX) { vString *const scopedName = vStringNew (); @@ -1027,7 +1045,7 @@ static void createTagWithTypeRef (tokenInfo *const token, verilogKind kind, toke } /* Push token as context if it is a container */ - if (container) + if (container && role == ROLE_DEFINITION_INDEX) { createContext (kind, token->name); @@ -1037,7 +1055,7 @@ static void createTagWithTypeRef (tokenInfo *const token, verilogKind kind, toke for (unsigned int i = 0; i < ptrArrayCount (tagContents); i++) { tokenInfo *content = ptrArrayItem (tagContents, i); - createTagWithTypeRef (content, content->kind, NULL); + createTagFull (content, content->kind, ROLE_DEFINITION_INDEX, NULL); } /* Drop temporary contexts */ @@ -1049,11 +1067,21 @@ static void createTagWithTypeRef (tokenInfo *const token, verilogKind kind, toke vStringClear (token->inheritance); } +static void createTagWithTypeRef (tokenInfo *const token, verilogKind kind, tokenInfo *const typeref) +{ + createTagFull (token, kind, ROLE_DEFINITION_INDEX, typeref); +} + static void createTag (tokenInfo *const token, verilogKind kind) { createTagWithTypeRef (token, kind, NULL); } +static void createRefTag (tokenInfo *const token, verilogKind kind, int role) +{ + createTagFull (token, kind, role, NULL); +} + static int skipBlockName (tokenInfo *const token, int c) { if (c == ':') @@ -1873,6 +1901,7 @@ static int tagIdsInDataDecl (tokenInfo* token, int c, verilogKind kind) tokenSaved->kind = K_MODULE; // for typeRef field verbose ("find instance: %s with kind %s\n", vStringValue (token->name), getNameForKind (K_INSTANCE)); createTagWithTypeRef (token, K_INSTANCE, tokenSaved); + createRefTag (tokenSaved, K_MODULE, R_MODULE_DECL); } } c = skipMacro (c, token); // `ifdef, `else, `endif, etc. (before comma)