gogtags: Golang tag jump to function caller with GNU GLOBAL

PUBLISHED ON FEB 5, 2017 — GOLANG

Although you can find the definition line with godef, it is convenient to jump to the function caller. So, I created a tool to generate tags compatible with GLOBAL in golang. https://github.com/juntaki/gogtags

Installation

$ go get github.com/juntaki/gogtags

GNU GLOBAL with sqlite3 support is required to refer to generated tags. Build it with the option --with-sqlite3. https://www.gnu.org/software/global/

$ ./configure --with-sqlite3
$ make
$ sudo make install

How to use

Create tags in the current directory. When the option -v is specified, the analyzed file path will be printed.

$ cd <target directory>
$ gogtags -v

screenshot1

When referring to the generated tag, it is OK to usual way to do it. Extension of editor like helm-gtags using output of global command, so it has no effect even if the file format of GTAGS changes.

screenshot2

other ways to do the same thing

You can use Pygments parser, but it requires bothersome setups. and I found ctags-compatible implement.

Format of GNU GLOBAL’s tag

The most detailed description of the format was in source code comment. This is the description of format version 6. Standard format is for GTAGS, Compact format is for GRTAGS. Berkeley DB is default database, and sqlite 3 can be used if it is a recent version. In addition, GSYMS is no longer made from 5.9 (information on symbols other than function calls are also included in GRTAGS).

 * [Specification of format version 6]
 *
 * Standard format:
 *
 *  This format is the default format of GTAGS.
 *
 *         <file id> <tag name> <line number> <line image>
 *
 *                 * Separator is single blank.
 *
 *         [example]
 *         +------------------------------------
 *         |110 func 10 int func(int a)
 *         |110 func 30 func(int a1, int a2)
 *
 *         Line image might be compressed (GTAGS_COMPRESS).
 *         Tag name might be compressed (GTAGS_COMPNAME).
 *
 * Compact format:
 *
 *  This format is the default format of GRTAGS.
 *  It is used for GTAGS with the -c option.
 *
 *         <file id> <tag name> <line number>,...
 *
 *                 * Separator is single blank.
 *
 *         [example]
 *         +------------------------------------
 *         |110 func 10,30
 *
 *         Line numbers are sorted in a line.
 *     Each line number might be expressed as difference from the previous
 *     line number except for the head (GTAGS_COMPLINE).
 *           ex: 10,3,2 means '10 13 15'.
 *     In addition,successive line numbers are expressed as a range.
 *           ex: 10-3 means '10 11 12 13'.

Analysis of format of sqlite 3 generated by gtags

Execute gtags --sqlite3 for the followings

     1  #include<stdio.h>
     2
     3  int a = 1;
     4
     5  int func1(){
     6    int a = 100;
     7    printf("%d", a);
     8    return 1;
     9  }
    10
    11  int main(){
    12    int a = 10;
    13    printf("%d", a);
    14    a = func1();
    15    return 0;
    16  }

Although it was not in the specification, the character string of the tag name is replaced with @n. Also, it seems to remove whitespace before and after the line image. GTAGS contains function definitions, and the dat column is stored according to format version 6. key is the tag name and extra seems to be the file ID. The column types are text.

juntaki@ubuntu ~/g/g/test> sqlite3 -header -column GTAGS "select * from db;"
key           dat                            extra
------------  -----------------------------  ----------
 __.COMPRESS   __.COMPRESS ddefine ttypedef
 __.COMPNAME   __.COMPNAME
 __.VERSION    __.VERSION 6
func1         1 @n 5 int @n(){               1
main          1 @n 11 int @n(){              1
func1         2 @n 5 int @n(){               2
main          2 @n 11 int @n(){              2

GRTAGS contains function calls and variable definitions, references.

sqlite> select * from db;
key              dat              extra
---------------  ---------------  ----------
 __.COMPACT       __.COMPACT
 __.COMPLINE      __.COMPLINE
 __.COMPNAME      __.COMPNAME
 __.VERSION       __.VERSION 6
a                1 @n 3,3-1,5-2   1
func1            1 @n 14          1
printf           1 @n 7,6         1
a                2 @n 3,3-1,5-2   2
func1            2 @n 14          2
printf           2 @n 7,6         2

There is a file name and the file ID entry. GPATH seems to have another version from GTAGS and GRTAGS.

juntaki@ubuntu ~/g/g/test> sqlite3 -header -column GPATH "select * from db;"
key          dat            extra
-----------  -------------  ----------
 __.VERSION   __.VERSION 2
./main.c     1
1            ./main.c
./main2.c    2
2            ./main2.c
 __.NEXTKEY  3
comments powered by Disqus