pythonexuberant-ctags

Exuberant-ctags incorrectly tags python multi line class definitions


Exuberant-ctags generate wrong tags when python class definition spans multiple lines, only the last line goes to the search pattern:

Consider the file test.py:

class FirstSubclass(
    LongLineBaseClass, AnotherLongClassName,
    MoreBaseClassWithVeryLongName
):
    pass


class SecondSubclass(
    LongLineBaseClass, AnotherLongClassName,
    MoreBaseClassWithVeryLongName
):
    pass


class OneLineClass(LongLineBaseClass):
    pass

and the resulting tags file for ctags test.py (comments added):

FirstSubclass   test.py /^):$/;"    c !PROBLEM
OneLineClass    test.py /^class OneLineClass(LongLineBaseClass):$/;"    c !OK
SecondSubclass  test.py /^):$/;"    c !PROBLEM

Both FirstSubclass and SecondSubclass received the same search pattern (ex command): /^):$ i.e. the only two characters of the last line of each class definition. This makes tags navigating in vim unusable.

Exuberant ctags version and info:

Exuberant Ctags 5.9~svn20110310, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: Oct  7 2014, 13:52:37
  Addresses: <dhiebert@users.sourceforge.net>, http://ctags.sourceforge.net
  Optional compiled features: +wildcards, +regex

What I've tried: I used the ctags with and without language-python kinds, parameters and nothing.


Any ideas ? Thanks in advance.


Solution

  • Universal-ctags (https://ctags.io), an unofficial fork of Exuebrante-ctags, can extract the patterns expectedly:

    [yamato@slave]~% cat /tmp/foo.py 
    cat /tmp/foo.py 
    class FirstSubclass(
        LongLineBaseClass, AnotherLongClassName,
        MoreBaseClassWithVeryLongName
    ):
        pass
    
    
    class SecondSubclass(
        LongLineBaseClass, AnotherLongClassName,
        MoreBaseClassWithVeryLongName
    ):
        pass
    
    
    class OneLineClass(LongLineBaseClass):
        pass
    
    [yamato@slave]~% u-ctags -o - /tmp/foo.py
    u-ctags -o - /tmp/foo.py
    FirstSubclass   /tmp/foo.py /^class FirstSubclass($/;"  c
    OneLineClass    /tmp/foo.py /^class OneLineClass(LongLineBaseClass):$/;"    c
    SecondSubclass  /tmp/foo.py /^class SecondSubclass($/;" c
    

    Moreover it can fills inherits fields:

    [yamato@slave]~% u-ctags --fields=+i -o - /tmp/foo.py
    u-ctags --fields=+i -o - /tmp/foo.py
    FirstSubclass   /tmp/foo.py /^class FirstSubclass($/;"  c   inherits:LongLineBaseClass, AnotherLongClassName, MoreBaseClassWithVeryLongName 
    OneLineClass    /tmp/foo.py /^class OneLineClass(LongLineBaseClass):$/;"    c   inherits:LongLineBaseClass
    SecondSubclass  /tmp/foo.py /^class SecondSubclass($/;" c   inherits:LongLineBaseClass, AnotherLongClassName, MoreBaseClassWithVeryLongName