universal-ctags / ctags

A maintained ctags implementation
https://ctags.io
GNU General Public License v2.0
6.56k stars 627 forks source link

SystemVerilog typedef not recognized if `include macro used #4056

Closed dawpud closed 2 months ago

dawpud commented 2 months ago

The name of the parser: SystemVerilog

The command line you used to run ctags:

$ ctags --options=NONE -f - test.sv

The content of input file:

typedef enum {
  `include "test.txt"
  OTHER_VAL
} my_enum;

my_enum e;

The tags output you are not satisfied with:

`include    test.sv /^  `include "test.txt"$/;" T
`include    test.sv /^  `include "test.txt"$/;" c   typedef:`include
e   test.sv /^my_enum e;$/;"    r

The tags output you expect:

`include    test.sv /^  `include "test.txt"$/;" T
`include    test.sv /^  `include "test.txt"$/;" c   typedef:`include
e   test.sv /^my_enum e;$/;"    r
OTHER_VAL   test.sv /^  OTHER_VAL$/;"   c   typedef:my_enum
my_enum test.sv /^} my_enum;$/;"    T

The version of ctags:

$ ctags --version
Universal Ctags 6.1.0(e4cb2a0), Copyright (C) 2015-2023 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: Dec 29 2023, 05:50:45
  URL: https://ctags.io/
  Output version: 0.0
  Optional compiled features: +wildcards, +regex, +gnulib_regex, +iconv, +option-directory, +xpath, +json, +interactive, +yaml, +packcc, +optscript

How do you get ctags binary:

Unix binary from nightly builds: uctags-2023.12.29-linux-x86_64.tar.xz


As seen in the results above, as soon as the `include macro is used within the typedef enum, the rest of the enum values stop getting parsed, and the enum itself is not listed in the output tags file. I appreciate any help you can provide! Thank you very much!

masatake commented 2 months ago

Just for the input, the following patch solves the issue;

diff --git a/parsers/verilog.c b/parsers/verilog.c
index 0b107687b..e7555eb60 100644
--- a/parsers/verilog.c
+++ b/parsers/verilog.c
@@ -1612,6 +1612,7 @@ static int pushEnumNames (tokenInfo* token, int c)
    if (c == '{')
    {
        c = skipWhite (vGetc ());
+       c = skipMacro (c, token);
        while (c != '}' && c != EOF)
        {
            if (!isWordToken (c))

However, my change may not work well if you move the include directive elsewhere. I guess directives must eventually be handled in one more lower layer.

Let's see what the parser maintainer says. If I don't hear back within two weeks, I will make a pull request based on the above change.

hirooih commented 2 months ago

I'll take a look at this. Give me some time.

hirooih commented 2 months ago

I sent #4058 fixing this bug. Your fix was very close. SkipMacro() should be in the while-loop.

The current implementation of the Verilog parser's compiler directives is very ad-hoc. Anything other than `define is simply ignored.

I guess directives must eventually be handled in one more lower layer.

As we discussed before, this would be the best solution,

hirooih commented 2 months ago

The fix was merged.

@dawpud Thank you for your report.