aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorEli Zaretskii2015-05-25 18:02:21 +0300
committerEli Zaretskii2015-05-25 18:02:21 +0300
commit9c66c5a0cabc748ce50d844a0f1af8d1fc121436 (patch)
treeee646dc097c061206e8da00fd976485e25bc7038 /lib-src
parent9b995d55c566737ef7aa3432826e1b7b656ff1c7 (diff)
downloademacs-9c66c5a0cabc748ce50d844a0f1af8d1fc121436.tar.gz
emacs-9c66c5a0cabc748ce50d844a0f1af8d1fc121436.zip
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 */
441static bool cplusplus; /* .[hc] means C++, not C (undocumented) */ 441static bool cplusplus; /* .[hc] means C++, not C (undocumented) */
442static bool ignoreindent; /* -I: ignore indentation in C */ 442static bool ignoreindent; /* -I: ignore indentation in C */
443static int packages_only; /* --packages-only: in Ada, only tag packages*/ 443static int packages_only; /* --packages-only: in Ada, only tag packages*/
444static int class_qualify; /* -Q: produce class-qualified tags in C++/Java */
444 445
445/* STDIN is defined in LynxOS system headers */ 446/* STDIN is defined in LynxOS system headers */
446#ifdef STDIN 447#ifdef STDIN
@@ -468,6 +469,7 @@ static struct option longopts[] =
468 { "members", no_argument, &members, 1 }, 469 { "members", no_argument, &members, 1 },
469 { "no-members", no_argument, &members, 0 }, 470 { "no-members", no_argument, &members, 0 },
470 { "output", required_argument, NULL, 'o' }, 471 { "output", required_argument, NULL, 'o' },
472 { "class-qualify", no_argument, &class_qualify, 'Q' },
471 { "regex", required_argument, NULL, 'r' }, 473 { "regex", required_argument, NULL, 'r' },
472 { "no-regex", no_argument, NULL, 'R' }, 474 { "no-regex", no_argument, NULL, 'R' },
473 { "ignore-case-regex", required_argument, NULL, 'c' }, 475 { "ignore-case-regex", required_argument, NULL, 'c' },
@@ -933,6 +935,12 @@ Relative ones are stored relative to the output file's directory.\n");
933 Do not create tag entries for members of structures\n\ 935 Do not create tag entries for members of structures\n\
934 in some languages."); 936 in some languages.");
935 937
938 puts ("-Q, --class-qualify\n\
939 Qualify tag names with their class name in C++, ObjC, and Java.\n\
940 This produces tag names of the form \"class::member\" for C++,\n\
941 \"class(category)\" for Objective C, and \"class.member\" for Java.\n\
942 For Objective C, this also produces class methods qualified with\n\
943 their arguments, as in \"foo:bar:baz:more\".");
936 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\ 944 puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
937 Make a tag for each line matching a regular expression pattern\n\ 945 Make a tag for each line matching a regular expression pattern\n\
938 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\ 946 in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
@@ -1050,7 +1058,7 @@ main (int argc, char **argv)
1050 1058
1051 /* When the optstring begins with a '-' getopt_long does not rearrange the 1059 /* When the optstring begins with a '-' getopt_long does not rearrange the
1052 non-options arguments to be at the end, but leaves them alone. */ 1060 non-options arguments to be at the end, but leaves them alone. */
1053 optstring = concat ("-ac:Cf:Il:o:r:RSVhH", 1061 optstring = concat ("-ac:Cf:Il:o:Qr:RSVhH",
1054 (CTAGS) ? "BxdtTuvw" : "Di:", 1062 (CTAGS) ? "BxdtTuvw" : "Di:",
1055 ""); 1063 "");
1056 1064
@@ -1139,6 +1147,9 @@ main (int argc, char **argv)
1139 case 'H': 1147 case 'H':
1140 help_asked = true; 1148 help_asked = true;
1141 break; 1149 break;
1150 case 'Q':
1151 class_qualify = 1;
1152 break;
1142 1153
1143 /* Etags options */ 1154 /* Etags options */
1144 case 'D': constantypedefs = false; break; 1155 case 'D': constantypedefs = false; break;
@@ -2852,12 +2863,15 @@ consider_token (char *str, int len, int c, int *c_extp,
2852 case omethodparm: 2863 case omethodparm:
2853 if (parlev == 0) 2864 if (parlev == 0)
2854 { 2865 {
2855 int oldlen = token_name.len;
2856 fvdef = fvnone;
2857 objdef = omethodtag; 2866 objdef = omethodtag;
2858 linebuffer_setlen (&token_name, oldlen + len); 2867 if (class_qualify)
2859 memcpy (token_name.buffer + oldlen, str, len); 2868 {
2860 token_name.buffer[oldlen + len] = '\0'; 2869 int oldlen = token_name.len;
2870 fvdef = fvnone;
2871 linebuffer_setlen (&token_name, oldlen + len);
2872 memcpy (token_name.buffer + oldlen, str, len);
2873 token_name.buffer[oldlen + len] = '\0';
2874 }
2861 return true; 2875 return true;
2862 } 2876 }
2863 return false; 2877 return false;
@@ -3307,21 +3321,42 @@ C_entries (int c_ext, FILE *inf)
3307 && nestlev > 0 && definedef == dnone) 3321 && nestlev > 0 && definedef == dnone)
3308 /* in struct body */ 3322 /* in struct body */
3309 { 3323 {
3310 int len; 3324 if (class_qualify)
3311 write_classname (&token_name, qualifier); 3325 {
3312 len = token_name.len; 3326 int len;
3313 linebuffer_setlen (&token_name, len+qlen+toklen); 3327 write_classname (&token_name, qualifier);
3314 sprintf (token_name.buffer + len, "%s%.*s", 3328 len = token_name.len;
3315 qualifier, toklen, newlb.buffer + tokoff); 3329 linebuffer_setlen (&token_name,
3330 len + qlen + toklen);
3331 sprintf (token_name.buffer + len, "%s%.*s",
3332 qualifier, toklen,
3333 newlb.buffer + tokoff);
3334 }
3335 else
3336 {
3337 linebuffer_setlen (&token_name, toklen);
3338 sprintf (token_name.buffer, "%.*s",
3339 toklen, newlb.buffer + tokoff);
3340 }
3316 token.named = true; 3341 token.named = true;
3317 } 3342 }
3318 else if (objdef == ocatseen) 3343 else if (objdef == ocatseen)
3319 /* Objective C category */ 3344 /* Objective C category */
3320 { 3345 {
3321 int len = strlen (objtag) + 2 + toklen; 3346 if (class_qualify)
3322 linebuffer_setlen (&token_name, len); 3347 {
3323 sprintf (token_name.buffer, "%s(%.*s)", 3348 int len = strlen (objtag) + 2 + toklen;
3324 objtag, toklen, newlb.buffer + tokoff); 3349 linebuffer_setlen (&token_name, len);
3350 sprintf (token_name.buffer, "%s(%.*s)",
3351 objtag, toklen,
3352 newlb.buffer + tokoff);
3353 }
3354 else
3355 {
3356 linebuffer_setlen (&token_name, toklen);
3357 sprintf (token_name.buffer, "%.*s",
3358 newlb.buffer + tokoff);
3359 }
3325 token.named = true; 3360 token.named = true;
3326 } 3361 }
3327 else if (objdef == omethodtag 3362 else if (objdef == omethodtag
@@ -3479,9 +3514,12 @@ C_entries (int c_ext, FILE *inf)
3479 case omethodtag: 3514 case omethodtag:
3480 case omethodparm: 3515 case omethodparm:
3481 objdef = omethodcolon; 3516 objdef = omethodcolon;
3482 int toklen = token_name.len; 3517 if (class_qualify)
3483 linebuffer_setlen (&token_name, toklen + 1); 3518 {
3484 strcpy (token_name.buffer + toklen, ":"); 3519 int toklen = token_name.len;
3520 linebuffer_setlen (&token_name, toklen + 1);
3521 strcpy (token_name.buffer + toklen, ":");
3522 }
3485 break; 3523 break;
3486 } 3524 }
3487 if (structdef == stagseen) 3525 if (structdef == stagseen)
@@ -3716,6 +3754,28 @@ C_entries (int c_ext, FILE *inf)
3716 switch (fvdef) 3754 switch (fvdef)
3717 { 3755 {
3718 case flistseen: 3756 case flistseen:
3757 if (cplpl && !class_qualify)
3758 {
3759 /* Remove class and namespace qualifiers from the token,
3760 leaving only the method/member name. */
3761 char *cc, *uqname = token_name.buffer;
3762 char *tok_end = token_name.buffer + token_name.len;
3763
3764 for (cc = token_name.buffer; cc < tok_end; cc++)
3765 {
3766 if (*cc == ':' && cc[1] == ':')
3767 {
3768 uqname = cc + 2;
3769 cc++;
3770 }
3771 }
3772 if (uqname > token_name.buffer)
3773 {
3774 int uqlen = strlen (uqname);
3775 linebuffer_setlen (&token_name, uqlen);
3776 memmove (token_name.buffer, uqname, uqlen + 1);
3777 }
3778 }
3719 make_C_tag (true); /* a function */ 3779 make_C_tag (true); /* a function */
3720 /* FALLTHRU */ 3780 /* FALLTHRU */
3721 case fignore: 3781 case fignore: