0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 9.0.1127: no error if function argument shadows class member

Problem:    No error if function argument shadows class member.
Solution:   Give an error for shadowing a class member.
This commit is contained in:
Bram Moolenaar 2023-01-01 19:53:30 +00:00
parent fc966c19f8
commit 6acf757c6a
6 changed files with 82 additions and 57 deletions

View File

@ -6,7 +6,7 @@ void ex_enum(exarg_T *eap);
void ex_type(exarg_T *eap); void ex_type(exarg_T *eap);
int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose); int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose);
ufunc_T *find_class_func(char_u **arg); ufunc_T *find_class_func(char_u **arg);
int class_member_exists(char_u *name, class_T **cl_ret, int *idx_ret, cctx_T *cctx); int class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx);
void copy_object(typval_T *from, typval_T *to); void copy_object(typval_T *from, typval_T *to);
void object_unref(object_T *obj); void object_unref(object_T *obj);
void copy_class(typval_T *from, typval_T *to); void copy_class(typval_T *from, typval_T *to);

View File

@ -367,7 +367,8 @@ def Test_class_object_member_access()
v9.CheckScriptFailure(lines, 'E1041:') v9.CheckScriptFailure(lines, 'E1041:')
enddef enddef
def Test_class_member_access() def Test_class_member()
# check access rules
var lines =<< trim END var lines =<< trim END
vim9script vim9script
class TextPos class TextPos
@ -401,6 +402,38 @@ def Test_class_member_access()
assert_equal(17, TextPos.anybody) assert_equal(17, TextPos.anybody)
END END
v9.CheckScriptSuccess(lines) v9.CheckScriptSuccess(lines)
# check shadowing
lines =<< trim END
vim9script
class Some
static count = 0
def Method(count: number)
echo count
enddef
endclass
var s = Some.new()
s.Method(7)
END
v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
lines =<< trim END
vim9script
class Some
static count = 0
def Method(arg: number)
var count = 3
echo arg count
enddef
endclass
var s = Some.new()
s.Method(7)
END
v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
enddef enddef
def Test_class_function() def Test_class_function()

View File

@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1127,
/**/ /**/
1126, 1126,
/**/ /**/

View File

@ -358,11 +358,12 @@ ex_class(exarg_T *eap)
ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE); ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE);
ga_clear_strings(&lines_to_free); ga_clear_strings(&lines_to_free);
// TODO: how about errors? if (uf != NULL)
{
int is_new = STRNCMP(uf->uf_name, "new", 3) == 0; int is_new = STRNCMP(uf->uf_name, "new", 3) == 0;
garray_T *fgap = has_static || is_new garray_T *fgap = has_static || is_new
? &classfunctions : &objmethods; ? &classfunctions : &objmethods;
if (uf != NULL && ga_grow(fgap, 1) == OK) if (ga_grow(fgap, 1) == OK)
{ {
if (is_new) if (is_new)
uf->uf_flags |= FC_NEW; uf->uf_flags |= FC_NEW;
@ -371,6 +372,7 @@ ex_class(exarg_T *eap)
++fgap->ga_len; ++fgap->ga_len;
} }
} }
}
// class members // class members
else if (has_static) else if (has_static)
@ -863,32 +865,30 @@ fail_after_eval:
} }
/* /*
* If "cctx->ctx_ufunc" indicates we are in a class, check if "name" is a class * If "name[len]" is a class member in cctx->ctx_ufunc->uf_class return the
* member. If it is then return TRUE and set "cl_ret" and "idx_ret". * index in class.class_class_members[].
* If "cl_ret" is not NULL set it to the class.
* Otherwise return -1;
*/ */
int int
class_member_exists( class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx)
char_u *name,
class_T **cl_ret,
int *idx_ret,
cctx_T *cctx)
{ {
if (cctx->ctx_ufunc == NULL || cctx->ctx_ufunc->uf_class == NULL) if (cctx == NULL || cctx->ctx_ufunc == NULL
return FALSE; || cctx->ctx_ufunc->uf_class == NULL)
return -1;
class_T *cl = cctx->ctx_ufunc->uf_class; class_T *cl = cctx->ctx_ufunc->uf_class;
for (int idx = 0; idx < cl->class_class_member_count; ++idx) for (int i = 0; i < cl->class_class_member_count; ++i)
{ {
ocmember_T *m = &cl->class_class_members[idx]; ocmember_T *m = &cl->class_class_members[i];
if (STRCMP(m->ocm_name, name) == 0) if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
{ {
if (cl_ret != NULL)
*cl_ret = cl; *cl_ret = cl;
*idx_ret = idx; return i;
return TRUE;
} }
} }
return -1;
return FALSE;
} }
/* /*

View File

@ -301,28 +301,6 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
return FAIL; return FAIL;
} }
/*
* If "name" is a class member in cctx->ctx_ufunc->uf_class return the index in
* class.class_class_members[].
* Otherwise return -1;
*/
static int
class_member_index(char_u *name, size_t len, cctx_T *cctx)
{
if (cctx == NULL || cctx->ctx_ufunc == NULL
|| cctx->ctx_ufunc->uf_class == NULL)
return -1;
class_T *cl = cctx->ctx_ufunc->uf_class;
for (int i = 0; i < cl->class_class_member_count; ++i)
{
ocmember_T *m = &cl->class_class_members[i];
if (STRNCMP(name, m->ocm_name, len) == 0
&& m->ocm_name[len] == NUL)
return i;
}
return -1;
}
/* /*
* Return TRUE if "name" is a local variable, argument, script variable or * Return TRUE if "name" is a local variable, argument, script variable or
* imported. * imported.
@ -338,7 +316,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
&& (cctx->ctx_ufunc->uf_flags & FC_OBJECT) && (cctx->ctx_ufunc->uf_flags & FC_OBJECT)
&& STRNCMP(name, "this", 4) == 0))) && STRNCMP(name, "this", 4) == 0)))
|| script_var_exists(name, len, cctx, NULL) == OK || script_var_exists(name, len, cctx, NULL) == OK
|| class_member_index(name, len, cctx) >= 0 || class_member_index(name, len, NULL, cctx) >= 0
|| find_imported(name, len, FALSE) != NULL; || find_imported(name, len, FALSE) != NULL;
} }
@ -376,9 +354,6 @@ check_defined(
if (len == 1 && *p == '_') if (len == 1 && *p == '_')
return OK; return OK;
if (class_member_index(p, len, cctx) >= 0)
return OK;
if (script_var_exists(p, len, cctx, cstack) == OK) if (script_var_exists(p, len, cctx, cstack) == OK)
{ {
if (is_arg) if (is_arg)
@ -388,6 +363,15 @@ check_defined(
return FAIL; return FAIL;
} }
if (class_member_index(p, len, NULL, cctx) >= 0)
{
if (is_arg)
semsg(_(e_argument_already_declared_in_class_str), p);
else
semsg(_(e_variable_already_declared_in_class_str), p);
return FAIL;
}
p[len] = NUL; p[len] = NUL;
if ((cctx != NULL if ((cctx != NULL
&& (lookup_local(p, len, NULL, cctx) == OK && (lookup_local(p, len, NULL, cctx) == OK
@ -1592,8 +1576,14 @@ compile_lhs(
} }
} }
else if ((lhs->lhs_classmember_idx = class_member_index( else if ((lhs->lhs_classmember_idx = class_member_index(
var_start, lhs->lhs_varlen, cctx)) >= 0) var_start, lhs->lhs_varlen, NULL, cctx)) >= 0)
{ {
if (is_decl)
{
semsg(_(e_variable_already_declared_in_class_str),
lhs->lhs_name);
return FAIL;
}
lhs->lhs_dest = dest_class_member; lhs->lhs_dest = dest_class_member;
lhs->lhs_class = cctx->ctx_ufunc->uf_class; lhs->lhs_class = cctx->ctx_ufunc->uf_class;
} }

View File

@ -603,7 +603,7 @@ compile_load(
else else
gen_load = TRUE; gen_load = TRUE;
} }
else if (class_member_exists(name, &cl, &idx, cctx)) else if ((idx = class_member_index(*arg, len, &cl, cctx)) >= 0)
{ {
res = generate_CLASSMEMBER(cctx, TRUE, cl, idx); res = generate_CLASSMEMBER(cctx, TRUE, cl, idx);
} }