vim-patch:7.4.1105

Problem:    When using slices there is a mixup of variable name and namespace.
Solution:   Recognize variables that can't be a namespace. (Hirohito Higashi)

9bbf63dbf8
This commit is contained in:
Jurica Bradaric
2016-02-27 18:11:39 +01:00
parent 3e0fab6b7c
commit 11cf3680e4
3 changed files with 72 additions and 32 deletions

View File

@@ -173,6 +173,7 @@ static char *e_illvar = N_("E461: Illegal variable name: %s");
static char *e_float_as_string = N_("E806: using Float as a String"); static char *e_float_as_string = N_("E806: using Float as a String");
static char_u * const empty_string = (char_u *)""; static char_u * const empty_string = (char_u *)"";
static char_u * const namespace_char = (char_u *)"abglstvw";
static dictitem_T globvars_var; /* variable used for g: */ static dictitem_T globvars_var; /* variable used for g: */
#define globvarht globvardict.dv_hashtab #define globvarht globvardict.dv_hashtab
@@ -17801,21 +17802,28 @@ static int get_env_len(char_u **arg)
return len; return len;
} }
/* // Get the length of the name of a function or internal variable.
* Get the length of the name of a function or internal variable. // "arg" is advanced to the first non-white character after the name.
* "arg" is advanced to the first non-white character after the name. // Return 0 if something is wrong.
* Return 0 if something is wrong. static int get_id_len(char_u **arg) {
*/ char_u *p;
static int get_id_len(char_u **arg)
{
char_u *p;
int len; int len;
/* Find the end of the name. */ // Find the end of the name.
for (p = *arg; eval_isnamec(*p); ++p) for (p = *arg; eval_isnamec(*p); p++) {
; if (*p == ':') {
if (p == *arg) /* no name found */ // "s:" is start of "s:var", but "n:" is not and can be used in
// slice "[n:]". Also "xx:" is not a namespace.
len = (int)(p - *arg);
if (len > 1
|| (len == 1 && vim_strchr(namespace_char, **arg) == NULL)) {
break;
}
}
}
if (p == *arg) { // no name found
return 0; return 0;
}
len = (int)(p - *arg); len = (int)(p - *arg);
*arg = skipwhite(p); *arg = skipwhite(p);
@@ -17886,28 +17894,28 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose)
return len; return len;
} }
/* // Find the end of a variable or function name, taking care of magic braces.
* Find the end of a variable or function name, taking care of magic braces. // If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
* If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the // start and end of the first magic braces item.
* start and end of the first magic braces item. // "flags" can have FNE_INCL_BR and FNE_CHECK_START.
* "flags" can have FNE_INCL_BR and FNE_CHECK_START. // Return a pointer to just after the name. Equal to "arg" if there is no
* Return a pointer to just after the name. Equal to "arg" if there is no // valid name.
* valid name.
*/
static char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags) static char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags)
{ {
int mb_nest = 0; int mb_nest = 0;
int br_nest = 0; int br_nest = 0;
char_u *p; char_u *p;
int len;
if (expr_start != NULL) { if (expr_start != NULL) {
*expr_start = NULL; *expr_start = NULL;
*expr_end = NULL; *expr_end = NULL;
} }
/* Quick check for valid starting character. */ // Quick check for valid starting character.
if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{') if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{') {
return arg; return arg;
}
for (p = arg; *p != NUL for (p = arg; *p != NUL
&& (eval_isnamec(*p) && (eval_isnamec(*p)
@@ -17922,30 +17930,44 @@ static char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end
if (*p == NUL) if (*p == NUL)
break; break;
} else if (*p == '"') { } else if (*p == '"') {
/* skip over "str\"ing" to avoid counting [ and ] inside it. */ // skip over "str\"ing" to avoid counting [ and ] inside it.
for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p)) for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p)) {
if (*p == '\\' && p[1] != NUL) if (*p == '\\' && p[1] != NUL) {
++p; ++p;
if (*p == NUL) }
}
if (*p == NUL) {
break; break;
}
} else if (br_nest == 0 && mb_nest == 0 && *p == ':') {
// "s:" is start of "s:var", but "n:" is not and can be used in
// slice "[n:]". Also "xx:" is not a namespace.
len = (int)(p - arg);
if (len > 1
|| (len == 1 && vim_strchr(namespace_char, *arg) == NULL)) {
break;
}
} }
if (mb_nest == 0) { if (mb_nest == 0) {
if (*p == '[') if (*p == '[') {
++br_nest; ++br_nest;
else if (*p == ']') } else if (*p == ']') {
--br_nest; --br_nest;
}
} }
if (br_nest == 0) { if (br_nest == 0) {
if (*p == '{') { if (*p == '{') {
mb_nest++; mb_nest++;
if (expr_start != NULL && *expr_start == NULL) if (expr_start != NULL && *expr_start == NULL) {
*expr_start = p; *expr_start = p;
}
} else if (*p == '}') { } else if (*p == '}') {
mb_nest--; mb_nest--;
if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL) if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL) {
*expr_end = p; *expr_end = p;
}
} }
} }
} }

View File

@@ -185,7 +185,7 @@ static int included_patches[] = {
// 1108, // 1108,
// 1107, // 1107,
// 1106 NA // 1106 NA
// 1105, 1105,
// 1104 NA // 1104 NA
// 1103 NA // 1103 NA
// 1102, // 1102,

View File

@@ -693,4 +693,22 @@ describe('eval', function()
start: start:
6]]) 6]])
end) end)
it('substring and variable name', function()
execute("let str = 'abcdef'")
execute('let n = 3')
eq('def', eval('str[n:]'))
eq('abcd', eval('str[:n]'))
eq('d', eval('str[n:n]'))
execute('unlet n')
execute('let nn = 3')
eq('def', eval('str[nn:]'))
eq('abcd', eval('str[:nn]'))
eq('d', eval('str[nn:nn]'))
execute('unlet nn')
execute('let b:nn = 4')
eq('ef', eval('str[b:nn:]'))
eq('abcde', eval('str[:b:nn]'))
eq('e', eval('str[b:nn:b:nn]'))
end)
end) end)