summaryrefslogtreecommitdiff
path: root/lib-src
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2015-05-25 18:02:21 +0300
committerEli Zaretskii <eliz@gnu.org>2015-05-25 18:02:21 +0300
commit9c66c5a0cabc748ce50d844a0f1af8d1fc121436 (patch)
treeee646dc097c061206e8da00fd976485e25bc7038 /lib-src
parent9b995d55c566737ef7aa3432826e1b7b656ff1c7 (diff)
downloademacs-9c66c5a0cabc748ce50d844a0f1af8d1fc121436.tar.gz
Fix tagging of class members in C-like OO languages
* lib-src/etags.c (longopts): Add new option --class-qualify and its shorthand -Q. (print_help): Add help text for --class-qualify. (main): Add handling of -Q. (consider_token, C_entries) <omethodparm>: Append argument types to Objective C methods only if --class-qualify was specified. Qualify C++, Objective C, and Java class members with their class names only if --class-qualify was specified. (C_entries): If --class-qualify was not specified, remove the namespace and class qualifiers from tag names of C++ methods. This allows to use etags.el as xref back-end without the tag-symbol-match-p method, which greatly increases the number of potentially false positives. (Bug#20629) * doc/man/etags.1: Update to document the new --class-qualify option. * test/etags/ETAGS.good_1: * test/etags/ETAGS.good_2: * test/etags/ETAGS.good_3: * test/etags/ETAGS.good_4: * test/etags/ETAGS.good_5: * test/etags/CTAGS.good: Update due to changes in etags.c.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c98
1 files changed, 79 insertions, 19 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 4b99e392728..73dd5a8a405 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -441,6 +441,7 @@ static bool cxref_style; /* -x: create cxref style output */
static bool cplusplus; /* .[hc] means C++, not C (undocumented) */
static bool ignoreindent; /* -I: ignore indentation in C */
static int packages_only; /* --packages-only: in Ada, only tag packages*/
+static int class_qualify; /* -Q: produce class-qualified tags in C++/Java */
/* STDIN is defined in LynxOS system headers */
#ifdef STDIN
@@ -468,6 +469,7 @@ static struct option longopts[] =
{ "members", no_argument, &members, 1 },
{ "no-members", no_argument, &members, 0 },
{ "output", required_argument, NULL, 'o' },
+ { "class-qualify", no_argument, &class_qualify, 'Q' },
{ "regex", required_argument, NULL, 'r' },
{ "no-regex", no_argument, NULL, 'R' },
{ "ignore-case-regex", required_argument, NULL, 'c' },
@@ -933,6 +935,12 @@ Relative ones are stored relative to the output file's directory.\n");
Do not create tag entries for members of structures\n\
in some languages.");
+ puts ("-Q, --class-qualify\n\
+ Qualify tag names with their class name in C++, ObjC, and Java.\n\
+ This produces tag names of the form \"class::member\" for C++,\n\
+ \"class(category)\" for Objective C, and \"class.member\" for Java.\n\
+ For Objective C, this also produces class methods qualified with\n\
+ their arguments, as in \"foo:bar:baz:more\".");
puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
Make a tag for each line matching a regular expression pattern\n\
in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
@@ -1050,7 +1058,7 @@ main (int argc, char **argv)
/* When the optstring begins with a '-' getopt_long does not rearrange the
non-options arguments to be at the end, but leaves them alone. */
- optstring = concat ("-ac:Cf:Il:o:r:RSVhH",
+ optstring = concat ("-ac:Cf:Il:o:Qr:RSVhH",
(CTAGS) ? "BxdtTuvw" : "Di:",
"");
@@ -1139,6 +1147,9 @@ main (int argc, char **argv)
case 'H':
help_asked = true;
break;
+ case 'Q':
+ class_qualify = 1;
+ break;
/* Etags options */
case 'D': constantypedefs = false; break;
@@ -2852,12 +2863,15 @@ consider_token (char *str, int len, int c, int *c_extp,
case omethodparm:
if (parlev == 0)
{
- int oldlen = token_name.len;
- fvdef = fvnone;
objdef = omethodtag;
- linebuffer_setlen (&token_name, oldlen + len);
- memcpy (token_name.buffer + oldlen, str, len);
- token_name.buffer[oldlen + len] = '\0';
+ if (class_qualify)
+ {
+ int oldlen = token_name.len;
+ fvdef = fvnone;
+ linebuffer_setlen (&token_name, oldlen + len);
+ memcpy (token_name.buffer + oldlen, str, len);
+ token_name.buffer[oldlen + len] = '\0';
+ }
return true;
}
return false;
@@ -3307,21 +3321,42 @@ C_entries (int c_ext, FILE *inf)
&& nestlev > 0 && definedef == dnone)
/* in struct body */
{
- int len;
- write_classname (&token_name, qualifier);
- len = token_name.len;
- linebuffer_setlen (&token_name, len+qlen+toklen);
- sprintf (token_name.buffer + len, "%s%.*s",
- qualifier, toklen, newlb.buffer + tokoff);
+ if (class_qualify)
+ {
+ int len;
+ write_classname (&token_name, qualifier);
+ len = token_name.len;
+ linebuffer_setlen (&token_name,
+ len + qlen + toklen);
+ sprintf (token_name.buffer + len, "%s%.*s",
+ qualifier, toklen,
+ newlb.buffer + tokoff);
+ }
+ else
+ {
+ linebuffer_setlen (&token_name, toklen);
+ sprintf (token_name.buffer, "%.*s",
+ toklen, newlb.buffer + tokoff);
+ }
token.named = true;
}
else if (objdef == ocatseen)
/* Objective C category */
{
- int len = strlen (objtag) + 2 + toklen;
- linebuffer_setlen (&token_name, len);
- sprintf (token_name.buffer, "%s(%.*s)",
- objtag, toklen, newlb.buffer + tokoff);
+ if (class_qualify)
+ {
+ int len = strlen (objtag) + 2 + toklen;
+ linebuffer_setlen (&token_name, len);
+ sprintf (token_name.buffer, "%s(%.*s)",
+ objtag, toklen,
+ newlb.buffer + tokoff);
+ }
+ else
+ {
+ linebuffer_setlen (&token_name, toklen);
+ sprintf (token_name.buffer, "%.*s",
+ newlb.buffer + tokoff);
+ }
token.named = true;
}
else if (objdef == omethodtag
@@ -3479,9 +3514,12 @@ C_entries (int c_ext, FILE *inf)
case omethodtag:
case omethodparm:
objdef = omethodcolon;
- int toklen = token_name.len;
- linebuffer_setlen (&token_name, toklen + 1);
- strcpy (token_name.buffer + toklen, ":");
+ if (class_qualify)
+ {
+ int toklen = token_name.len;
+ linebuffer_setlen (&token_name, toklen + 1);
+ strcpy (token_name.buffer + toklen, ":");
+ }
break;
}
if (structdef == stagseen)
@@ -3716,6 +3754,28 @@ C_entries (int c_ext, FILE *inf)
switch (fvdef)
{
case flistseen:
+ if (cplpl && !class_qualify)
+ {
+ /* Remove class and namespace qualifiers from the token,
+ leaving only the method/member name. */
+ char *cc, *uqname = token_name.buffer;
+ char *tok_end = token_name.buffer + token_name.len;
+
+ for (cc = token_name.buffer; cc < tok_end; cc++)
+ {
+ if (*cc == ':' && cc[1] == ':')
+ {
+ uqname = cc + 2;
+ cc++;
+ }
+ }
+ if (uqname > token_name.buffer)
+ {
+ int uqlen = strlen (uqname);
+ linebuffer_setlen (&token_name, uqlen);
+ memmove (token_name.buffer, uqname, uqlen + 1);
+ }
+ }
make_C_tag (true); /* a function */
/* FALLTHRU */
case fignore: