diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-10-08 19:21:31 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-10-08 19:21:31 +0200 |
commit | 226630a030c0d41145e1109f09633360fc9c999d (patch) | |
tree | 964ac2372bbc4b653594d660ba3375a8adf33293 /src/normal.c | |
parent | ec68a99464055029c01082762517e97245ddae0c (diff) | |
download | vim-226630a030c0d41145e1109f09633360fc9c999d.zip |
patch 8.0.0023
Problem: "gd" and "gD" may find a match in a comment or string.
Solution: Ignore matches in comments and strings. (Anton Lindqvist)
Diffstat (limited to 'src/normal.c')
-rw-r--r-- | src/normal.c | 82 |
1 files changed, 75 insertions, 7 deletions
diff --git a/src/normal.c b/src/normal.c index 8302ffbc9..99ced410d 100644 --- a/src/normal.c +++ b/src/normal.c @@ -4240,6 +4240,52 @@ nv_gd( } /* + * Return TRUE if line[offset] is not inside a C-style comment or string, FALSE + * otherwise. + */ + static int +is_ident(char_u *line, int offset) +{ + int i; + int incomment = FALSE; + int instring = 0; + int prev = 0; + + for (i = 0; i < offset && line[i] != NUL; i++) + { + if (instring != 0) + { + if (prev != '\\' && line[i] == instring) + instring = 0; + } + else if ((line[i] == '"' || line[i] == '\'') && !incomment) + { + instring = line[i]; + } + else + { + if (incomment) + { + if (prev == '*' && line[i] == '/') + incomment = FALSE; + } + else if (prev == '/' && line[i] == '*') + { + incomment = TRUE; + } + else if (prev == '/' && line[i] == '/') + { + return FALSE; + } + } + + prev = line[i]; + } + + return incomment == FALSE && instring == 0; +} + +/* * Search for variable declaration of "ptr[len]". * When "locally" is TRUE in the current function ("gd"), otherwise in the * current file ("gD"). @@ -4264,6 +4310,7 @@ find_decl( int retval = OK; int incll; int searchflags = flags_arg; + int valid; if ((pat = alloc(len + 7)) == NULL) return FAIL; @@ -4301,6 +4348,7 @@ find_decl( clearpos(&found_pos); for (;;) { + valid = FALSE; t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL); if (curwin->w_cursor.lnum >= old_pos.lnum) @@ -4337,9 +4385,20 @@ find_decl( continue; } #endif - if (!locally) /* global search: use first match found */ + valid = is_ident(ml_get_curline(), curwin->w_cursor.col); + + /* If the current position is not a valid identifier and a previous + * match is present, favor that one instead. */ + if (!valid && found_pos.lnum != 0) + { + curwin->w_cursor = found_pos; break; - if (curwin->w_cursor.lnum >= par_pos.lnum) + } + + /* Global search: use first valid match found */ + if (valid && !locally) + break; + if (valid && curwin->w_cursor.lnum >= par_pos.lnum) { /* If we previously found a valid position, use it. */ if (found_pos.lnum != 0) @@ -4347,11 +4406,20 @@ find_decl( break; } - /* For finding a local variable and the match is before the "{" search - * to find a later match. For K&R style function declarations this - * skips the function header without types. Remove SEARCH_START from - * flags to avoid getting stuck at one position. */ - found_pos = curwin->w_cursor; + /* For finding a local variable and the match is before the "{" or + * inside a comment, continue searching. For K&R style function + * declarations this skips the function header without types. */ + if (!valid) + { + /* Braces needed due to macro expansion of clearpos. */ + clearpos(&found_pos); + } + else + { + found_pos = curwin->w_cursor; + } + /* Remove SEARCH_START from flags to avoid getting stuck at one + * position. */ searchflags &= ~SEARCH_START; } |