universal-ctags / ctags

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

Cxx: No more parsing after elif #1790

Open reidakdumont opened 6 years ago

reidakdumont commented 6 years ago

The name of the parser: C++

The command line you used to run ctags:

$ ctags --options=NONE --fields-c++=+{properties} --fields=+n+a+Z -f- --c++-kinds=csguedfpzlmv --sort=no testCTAGS.cpp

The content of input file:

void test()
{
#if defined(unix) || defined(__unix) || defined(__unix__)
    int ev_l, er_l, ma_l, mi_l;
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
    SHORT Vk;
    UINT Vkey;
#endif
}

The tags output you are not satisfied with:

test    testCTAGS.cpp   /^void test()$/;"   f   line:1  typeref:typename:void
ev_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
er_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
ma_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
mi_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
...

The tags output you expect:

test    testCTAGS.cpp   /^void test()$/;"   f   line:1  typeref:typename:void
ev_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
er_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
ma_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
mi_l    testCTAGS.cpp   /^    int ev_l, er_l, ma_l, mi_l;$/;"   l   line:4  scope:function:test typeref:typename:int    file:
ma_l    testCTAGS.cpp   /^    SHORT Vk;$/;" l   line:6  scope:function:test typeref:typename:SHORT  file:
mi_l    testCTAGS.cpp   /^    UINT Vkey;$/;"    l   line:7  scope:function:test typeref:typename:UINT   file:
...

The version of ctags:

$ ctags --version
Universal Ctags 0.0.0(00be957), Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: Jun 29 2018, 16:48:41
  URL: https://ctags.io/
  Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath

How do you get ctags binary:

Building it locally, via GNU/Linux distribution, ubuntu 16.04

masatake commented 6 years ago

Though Vk and Vkey are not listed in your "The tags output you expect:", I guess what you expect are Vk and Vkey.

This behavior of ctags is expected and its limitation. Quoted from ctags.1 man page:

       In general, ctags tries to be smart about conditional preprocessor directives. If a preprocessor  con‐
       ditional is encountered within a statement which defines a tag, ctags follows only the first branch of
       that conditional (except in the special case of "#if 0", in  which  case  it  follows  only  the  last
       branch). The reason for this is that failing to pursue only one branch can result in ambiguous syntax,
       as in the following example:

              #ifdef TWO_ALTERNATIVES
              struct {
              #else
              union {
              #endif
                  short a;
                  long b;
              }

       Both branches cannot be followed, or braces become unbalanced and ctags would be unable to make  sense
       of the syntax.
jerome-caucat commented 6 years ago

Would it be possible to control which branch of conditional preprocessor directives is parsed with an option? For example -D TWO_ALTERNATIVES to undef and -D TWO_ALTERNATIVES=42 to change the value.

Otherwise I guess one option would be to use perl to comment/uncomment sections beforehand...

masatake commented 6 years ago

@pragmaware, how do you think this?

I would like to write my position. If someone (other than @pragmaware) implements the feature (extending cpreprocessor.c), I will not reject it. However, I will not implement the feature.

Running a perl or something preprocessor for ctags is very interesting idea. Generalizing it will make much benefits. However, that will be done after releasing 6.0.