summaryrefslogtreecommitdiff
path: root/lib-src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2016-01-30 13:56:23 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2016-01-30 13:56:23 -0800
commit99fa8c3dbf333f1e3fa7d6449d4b4428ce439ce1 (patch)
treefc459c16ca5f7204aa5a21529f8a189bfb45f831 /lib-src
parent3005605776955593e0b416de9e1ebf158114343e (diff)
parent875577bcc8d6139d61f91118d0907b847912b3e1 (diff)
-
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c133
1 files changed, 128 insertions, 5 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 2192627c7e..ff75de4565 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -354,6 +354,7 @@ static void Cstar_entries (FILE *);
static void Erlang_functions (FILE *);
static void Forth_words (FILE *);
static void Fortran_functions (FILE *);
+static void Go_functions (FILE *);
static void HTML_labels (FILE *);
static void Lisp_functions (FILE *);
static void Lua_functions (FILE *);
@@ -641,6 +642,10 @@ static const char *Fortran_suffixes [] =
static const char Fortran_help [] =
"In Fortran code, functions, subroutines and block data are tags.";
+static const char *Go_suffixes [] = {"go", NULL};
+static const char Go_help [] =
+ "In Go code, functions, interfaces and packages are tags.";
+
static const char *HTML_suffixes [] =
{ "htm", "html", "shtml", NULL };
static const char HTML_help [] =
@@ -727,7 +732,7 @@ static const char *Ruby_suffixes [] =
{ "rb", "ruby", NULL };
static const char Ruby_help [] =
"In Ruby code, 'def' or 'class' or 'module' at the beginning of\n\
-a line generate a tag.";
+a line generate a tag. Constants also generate a tag.";
/* Can't do the `SCM' or `scm' prefix with a version number. */
static const char *Scheme_suffixes [] =
@@ -794,6 +799,7 @@ static language lang_names [] =
{ "erlang", Erlang_help, Erlang_functions, Erlang_suffixes },
{ "forth", Forth_help, Forth_words, Forth_suffixes },
{ "fortran", Fortran_help, Fortran_functions, Fortran_suffixes },
+ { "go", Go_help, Go_functions, Go_suffixes },
{ "html", HTML_help, HTML_labels, HTML_suffixes },
{ "java", Cjava_help, Cjava_entries, Cjava_suffixes },
{ "lisp", Lisp_help, Lisp_functions, Lisp_suffixes },
@@ -4210,6 +4216,73 @@ Fortran_functions (FILE *inf)
/*
+ * Go language support
+ * Original code by Xi Lu <lx@shellcodes.org> (2016)
+ */
+static void
+Go_functions(FILE *inf)
+{
+ char *cp, *name;
+
+ LOOP_ON_INPUT_LINES(inf, lb, cp)
+ {
+ cp = skip_spaces (cp);
+
+ if (LOOKING_AT (cp, "package"))
+ {
+ name = cp;
+ while (!notinname (*cp) && *cp != '\0')
+ cp++;
+ make_tag (name, cp - name, false, lb.buffer,
+ cp - lb.buffer + 1, lineno, linecharno);
+ }
+ else if (LOOKING_AT (cp, "func"))
+ {
+ /* Go implementation of interface, such as:
+ func (n *Integer) Add(m Integer) ...
+ skip `(n *Integer)` part.
+ */
+ if (*cp == '(')
+ {
+ while (*cp != ')')
+ cp++;
+ cp = skip_spaces (cp+1);
+ }
+
+ if (*cp)
+ {
+ name = cp;
+
+ while (!notinname (*cp))
+ cp++;
+
+ make_tag (name, cp - name, true, lb.buffer,
+ cp - lb.buffer + 1, lineno, linecharno);
+ }
+ }
+ else if (members && LOOKING_AT (cp, "type"))
+ {
+ name = cp;
+
+ /* Ignore the likes of the following:
+ type (
+ A
+ )
+ */
+ if (*cp == '(')
+ return;
+
+ while (!notinname (*cp) && *cp != '\0')
+ cp++;
+
+ make_tag (name, cp - name, false, lb.buffer,
+ cp - lb.buffer + 1, lineno, linecharno);
+ }
+ }
+}
+
+
+/*
* Ada parsing
* Original code by
* Philippe Waroquiers (1998)
@@ -4551,18 +4624,68 @@ Ruby_functions (FILE *inf)
LOOP_ON_INPUT_LINES (inf, lb, cp)
{
+ bool is_class = false;
+ bool is_method = false;
+ char *name;
+
cp = skip_spaces (cp);
- if (LOOKING_AT (cp, "def")
- || LOOKING_AT (cp, "class")
- || LOOKING_AT (cp, "module"))
+ if (c_isalpha (*cp) && c_isupper (*cp)) /* constants */
{
- char *name = cp;
+ char *bp, *colon = NULL;
+
+ name = cp;
+
+ for (cp++; c_isalnum (*cp) || *cp == '_' || *cp == ':'; cp++)
+ {
+ if (*cp == ':')
+ colon = cp;
+ }
+ if (cp > name + 1)
+ {
+ bp = skip_spaces (cp);
+ if (*bp == '=' && c_isspace (bp[1]))
+ {
+ if (colon && !c_isspace (colon[1]))
+ name = colon + 1;
+ make_tag (name, cp - name, false,
+ lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ }
+ }
+ }
+ else if ((is_method = LOOKING_AT (cp, "def")) /* module/class/method */
+ || (is_class = LOOKING_AT (cp, "class"))
+ || LOOKING_AT (cp, "module"))
+ {
+ const char self_name[] = "self.";
+ const size_t self_size1 = sizeof ("self.") - 1;
+
+ name = cp;
/* Ruby method names can end in a '='. Also, operator overloading can
define operators whose names include '='. */
while (!notinname (*cp) || *cp == '=')
cp++;
+ /* Remove "self." from the method name. */
+ if (cp - name > self_size1
+ && strneq (name, self_name, self_size1))
+ name += self_size1;
+
+ /* Remove the class/module qualifiers from method names. */
+ if (is_method)
+ {
+ char *q;
+
+ for (q = name; q < cp && *q != '.'; q++)
+ ;
+ if (q < cp - 1) /* punt if we see just "FOO." */
+ name = q + 1;
+ }
+
+ /* Don't tag singleton classes. */
+ if (is_class && strneq (name, "<<", 2) && cp == name + 2)
+ continue;
+
make_tag (name, cp - name, true,
lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
}