Skip to content

Commit 6acf757

Browse files
committed
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.
1 parent fc966c1 commit 6acf757

6 files changed

Lines changed: 82 additions & 57 deletions

File tree

src/proto/vim9class.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ void ex_enum(exarg_T *eap);
66
void ex_type(exarg_T *eap);
77
int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose);
88
ufunc_T *find_class_func(char_u **arg);
9-
int class_member_exists(char_u *name, class_T **cl_ret, int *idx_ret, cctx_T *cctx);
9+
int class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx);
1010
void copy_object(typval_T *from, typval_T *to);
1111
void object_unref(object_T *obj);
1212
void copy_class(typval_T *from, typval_T *to);

src/testdir/test_vim9_class.vim

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,8 @@ def Test_class_object_member_access()
367367
v9.CheckScriptFailure(lines, 'E1041:')
368368
enddef
369369

370-
def Test_class_member_access()
370+
def Test_class_member()
371+
# check access rules
371372
var lines =<< trim END
372373
vim9script
373374
class TextPos
@@ -401,6 +402,38 @@ def Test_class_member_access()
401402
assert_equal(17, TextPos.anybody)
402403
END
403404
v9.CheckScriptSuccess(lines)
405+
406+
# check shadowing
407+
lines =<< trim END
408+
vim9script
409+
410+
class Some
411+
static count = 0
412+
def Method(count: number)
413+
echo count
414+
enddef
415+
endclass
416+
417+
var s = Some.new()
418+
s.Method(7)
419+
END
420+
v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
421+
422+
lines =<< trim END
423+
vim9script
424+
425+
class Some
426+
static count = 0
427+
def Method(arg: number)
428+
var count = 3
429+
echo arg count
430+
enddef
431+
endclass
432+
433+
var s = Some.new()
434+
s.Method(7)
435+
END
436+
v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
404437
enddef
405438

406439
def Test_class_function()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ static char *(features[]) =
695695

696696
static int included_patches[] =
697697
{ /* Add new patch number below this line */
698+
/**/
699+
1127,
698700
/**/
699701
1126,
700702
/**/

src/vim9class.c

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -358,17 +358,19 @@ ex_class(exarg_T *eap)
358358
ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE);
359359
ga_clear_strings(&lines_to_free);
360360

361-
// TODO: how about errors?
362-
int is_new = STRNCMP(uf->uf_name, "new", 3) == 0;
363-
garray_T *fgap = has_static || is_new
364-
? &classfunctions : &objmethods;
365-
if (uf != NULL && ga_grow(fgap, 1) == OK)
361+
if (uf != NULL)
366362
{
367-
if (is_new)
368-
uf->uf_flags |= FC_NEW;
363+
int is_new = STRNCMP(uf->uf_name, "new", 3) == 0;
364+
garray_T *fgap = has_static || is_new
365+
? &classfunctions : &objmethods;
366+
if (ga_grow(fgap, 1) == OK)
367+
{
368+
if (is_new)
369+
uf->uf_flags |= FC_NEW;
369370

370-
((ufunc_T **)fgap->ga_data)[fgap->ga_len] = uf;
371-
++fgap->ga_len;
371+
((ufunc_T **)fgap->ga_data)[fgap->ga_len] = uf;
372+
++fgap->ga_len;
373+
}
372374
}
373375
}
374376

@@ -863,32 +865,30 @@ find_class_func(char_u **arg)
863865
}
864866

865867
/*
866-
* If "cctx->ctx_ufunc" indicates we are in a class, check if "name" is a class
867-
* member. If it is then return TRUE and set "cl_ret" and "idx_ret".
868+
* If "name[len]" is a class member in cctx->ctx_ufunc->uf_class return the
869+
* index in class.class_class_members[].
870+
* If "cl_ret" is not NULL set it to the class.
871+
* Otherwise return -1;
868872
*/
869873
int
870-
class_member_exists(
871-
char_u *name,
872-
class_T **cl_ret,
873-
int *idx_ret,
874-
cctx_T *cctx)
874+
class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx)
875875
{
876-
if (cctx->ctx_ufunc == NULL || cctx->ctx_ufunc->uf_class == NULL)
877-
return FALSE;
876+
if (cctx == NULL || cctx->ctx_ufunc == NULL
877+
|| cctx->ctx_ufunc->uf_class == NULL)
878+
return -1;
878879
class_T *cl = cctx->ctx_ufunc->uf_class;
879880

880-
for (int idx = 0; idx < cl->class_class_member_count; ++idx)
881+
for (int i = 0; i < cl->class_class_member_count; ++i)
881882
{
882-
ocmember_T *m = &cl->class_class_members[idx];
883-
if (STRCMP(m->ocm_name, name) == 0)
883+
ocmember_T *m = &cl->class_class_members[i];
884+
if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
884885
{
885-
*cl_ret = cl;
886-
*idx_ret = idx;
887-
return TRUE;
886+
if (cl_ret != NULL)
887+
*cl_ret = cl;
888+
return i;
888889
}
889890
}
890-
891-
return FALSE;
891+
return -1;
892892
}
893893

894894
/*

src/vim9compile.c

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -301,28 +301,6 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
301301
return FAIL;
302302
}
303303

304-
/*
305-
* If "name" is a class member in cctx->ctx_ufunc->uf_class return the index in
306-
* class.class_class_members[].
307-
* Otherwise return -1;
308-
*/
309-
static int
310-
class_member_index(char_u *name, size_t len, cctx_T *cctx)
311-
{
312-
if (cctx == NULL || cctx->ctx_ufunc == NULL
313-
|| cctx->ctx_ufunc->uf_class == NULL)
314-
return -1;
315-
class_T *cl = cctx->ctx_ufunc->uf_class;
316-
for (int i = 0; i < cl->class_class_member_count; ++i)
317-
{
318-
ocmember_T *m = &cl->class_class_members[i];
319-
if (STRNCMP(name, m->ocm_name, len) == 0
320-
&& m->ocm_name[len] == NUL)
321-
return i;
322-
}
323-
return -1;
324-
}
325-
326304
/*
327305
* Return TRUE if "name" is a local variable, argument, script variable or
328306
* imported.
@@ -338,7 +316,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
338316
&& (cctx->ctx_ufunc->uf_flags & FC_OBJECT)
339317
&& STRNCMP(name, "this", 4) == 0)))
340318
|| script_var_exists(name, len, cctx, NULL) == OK
341-
|| class_member_index(name, len, cctx) >= 0
319+
|| class_member_index(name, len, NULL, cctx) >= 0
342320
|| find_imported(name, len, FALSE) != NULL;
343321
}
344322

@@ -376,9 +354,6 @@ check_defined(
376354
if (len == 1 && *p == '_')
377355
return OK;
378356

379-
if (class_member_index(p, len, cctx) >= 0)
380-
return OK;
381-
382357
if (script_var_exists(p, len, cctx, cstack) == OK)
383358
{
384359
if (is_arg)
@@ -388,6 +363,15 @@ check_defined(
388363
return FAIL;
389364
}
390365

366+
if (class_member_index(p, len, NULL, cctx) >= 0)
367+
{
368+
if (is_arg)
369+
semsg(_(e_argument_already_declared_in_class_str), p);
370+
else
371+
semsg(_(e_variable_already_declared_in_class_str), p);
372+
return FAIL;
373+
}
374+
391375
p[len] = NUL;
392376
if ((cctx != NULL
393377
&& (lookup_local(p, len, NULL, cctx) == OK
@@ -1592,8 +1576,14 @@ compile_lhs(
15921576
}
15931577
}
15941578
else if ((lhs->lhs_classmember_idx = class_member_index(
1595-
var_start, lhs->lhs_varlen, cctx)) >= 0)
1579+
var_start, lhs->lhs_varlen, NULL, cctx)) >= 0)
15961580
{
1581+
if (is_decl)
1582+
{
1583+
semsg(_(e_variable_already_declared_in_class_str),
1584+
lhs->lhs_name);
1585+
return FAIL;
1586+
}
15971587
lhs->lhs_dest = dest_class_member;
15981588
lhs->lhs_class = cctx->ctx_ufunc->uf_class;
15991589
}
@@ -2264,7 +2254,7 @@ compile_assignment(
22642254
CLEAR_FIELD(lhs);
22652255
long start_lnum = SOURCING_LNUM;
22662256

2267-
int has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
2257+
int has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
22682258
if (has_arg_is_set_prefix)
22692259
{
22702260
arg += 11;

src/vim9expr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ compile_load(
603603
else
604604
gen_load = TRUE;
605605
}
606-
else if (class_member_exists(name, &cl, &idx, cctx))
606+
else if ((idx = class_member_index(*arg, len, &cl, cctx)) >= 0)
607607
{
608608
res = generate_CLASSMEMBER(cctx, TRUE, cl, idx);
609609
}

0 commit comments

Comments
 (0)