summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2023-01-01 19:53:30 +0000
committerBram Moolenaar <Bram@vim.org>2023-01-01 19:53:30 +0000
commit6acf757c6a11c0653b0132a17c22983856da5ad6 (patch)
tree8e5a3c9b014b9f008a66aac1bfcaaf9a26efee46
parentfc966c19f85afc6b856a06c00a93c4fe96280d31 (diff)
patch 9.0.1127: no error if function argument shadows class memberv9.0.1127
Problem: No error if function argument shadows class member. Solution: Give an error for shadowing a class member.
-rw-r--r--src/proto/vim9class.pro2
-rw-r--r--src/testdir/test_vim9_class.vim35
-rw-r--r--src/version.c2
-rw-r--r--src/vim9class.c52
-rw-r--r--src/vim9compile.c46
-rw-r--r--src/vim9expr.c2
6 files changed, 82 insertions, 57 deletions
diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro
index edbddd267b..66c6107a1a 100644
--- a/src/proto/vim9class.pro
+++ b/src/proto/vim9class.pro
@@ -6,7 +6,7 @@ void ex_enum(exarg_T *eap);
void ex_type(exarg_T *eap);
int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose);
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 object_unref(object_T *obj);
void copy_class(typval_T *from, typval_T *to);
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 9dd6f83942..8cb9113384 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -367,7 +367,8 @@ def Test_class_object_member_access()
v9.CheckScriptFailure(lines, 'E1041:')
enddef
-def Test_class_member_access()
+def Test_class_member()
+ # check access rules
var lines =<< trim END
vim9script
class TextPos
@@ -401,6 +402,38 @@ def Test_class_member_access()
assert_equal(17, TextPos.anybody)
END
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
def Test_class_function()
diff --git a/src/version.c b/src/version.c
index 389209aae3..dc320bef6f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1127,
+/**/
1126,
/**/
1125,
diff --git a/src/vim9class.c b/src/vim9class.c
index b05dea8eff..8e05a17f4c 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -358,17 +358,19 @@ ex_class(exarg_T *eap)
ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE);
ga_clear_strings(&lines_to_free);
- // TODO: how about errors?
- int is_new = STRNCMP(uf->uf_name, "new", 3) == 0;
- garray_T *fgap = has_static || is_new
- ? &classfunctions : &objmethods;
- if (uf != NULL && ga_grow(fgap, 1) == OK)
+ if (uf != NULL)
{
- if (is_new)
- uf->uf_flags |= FC_NEW;
+ int is_new = STRNCMP(uf->uf_name, "new", 3) == 0;
+ garray_T *fgap = has_static || is_new
+ ? &classfunctions : &objmethods;
+ if (ga_grow(fgap, 1) == OK)
+ {
+ if (is_new)
+ uf->uf_flags |= FC_NEW;
- ((ufunc_T **)fgap->ga_data)[fgap->ga_len] = uf;
- ++fgap->ga_len;
+ ((ufunc_T **)fgap->ga_data)[fgap->ga_len] = uf;
+ ++fgap->ga_len;
+ }
}
}
@@ -863,32 +865,30 @@ fail_after_eval:
}
/*
- * If "cctx->ctx_ufunc" indicates we are in a class, check if "name" is a class
- * member. If it is then return TRUE and set "cl_ret" and "idx_ret".
+ * If "name[len]" is a class member in cctx->ctx_ufunc->uf_class return the
+ * index in class.class_class_members[].
+ * If "cl_ret" is not NULL set it to the class.
+ * Otherwise return -1;
*/
int
-class_member_exists(
- char_u *name,
- class_T **cl_ret,
- int *idx_ret,
- cctx_T *cctx)
+class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx)
{
- if (cctx->ctx_ufunc == NULL || cctx->ctx_ufunc->uf_class == NULL)
- return FALSE;
+ 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 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];
- if (STRCMP(m->ocm_name, name) == 0)
+ ocmember_T *m = &cl->class_class_members[i];
+ if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
{
- *cl_ret = cl;
- *idx_ret = idx;
- return TRUE;
+ if (cl_ret != NULL)
+ *cl_ret = cl;
+ return i;
}
}
-
- return FALSE;
+ return -1;
}
/*
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 0d980ba4e2..0e6c32cbf7 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -302,28 +302,6 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
}
/*
- * 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
* imported.
*/
@@ -338,7 +316,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
&& (cctx->ctx_ufunc->uf_flags & FC_OBJECT)
&& STRNCMP(name, "this", 4) == 0)))
|| 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;
}
@@ -376,9 +354,6 @@ check_defined(
if (len == 1 && *p == '_')
return OK;
- if (class_member_index(p, len, cctx) >= 0)
- return OK;
-
if (script_var_exists(p, len, cctx, cstack) == OK)
{
if (is_arg)
@@ -388,6 +363,15 @@ check_defined(
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;
if ((cctx != NULL
&& (lookup_local(p, len, NULL, cctx) == OK
@@ -1592,8 +1576,14 @@ compile_lhs(
}
}
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_class = cctx->ctx_ufunc->uf_class;
}
@@ -2264,7 +2254,7 @@ compile_assignment(
CLEAR_FIELD(lhs);
long start_lnum = SOURCING_LNUM;
- int has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
+ int has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
if (has_arg_is_set_prefix)
{
arg += 11;
diff --git a/src/vim9expr.c b/src/vim9expr.c
index 463e79cbe4..4a3527f057 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -603,7 +603,7 @@ compile_load(
else
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);
}