summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2023-10-11 21:43:52 +0200
committerChristian Brabandt <cb@256bit.org>2023-10-11 21:43:52 +0200
commit1ea428883f16838aca5763aee156fde3929d9ab6 (patch)
treef5bbcbcfe81da0df16fd416ed62fb71c383c4ba8
parent4c8da025ef8140168b7a09d9fe922ce4bb40f19d (diff)
patch 9.0.2016: Vim9: assignment operators don't work for class varsv9.0.2016
Problem: Vim9: assignment operators don't work for class vars Solution: implement it closes: #13306 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
-rw-r--r--src/proto/vim9class.pro4
-rw-r--r--src/testdir/test_vim9_class.vim46
-rw-r--r--src/version.c2
-rw-r--r--src/vim9class.c4
-rw-r--r--src/vim9compile.c20
5 files changed, 70 insertions, 6 deletions
diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro
index c9e19d0067..362e2cac5e 100644
--- a/src/proto/vim9class.pro
+++ b/src/proto/vim9class.pro
@@ -1,8 +1,8 @@
/* vim9class.c */
int object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl);
void ex_class(exarg_T *eap);
-type_T *class_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx);
-type_T *class_member_type_by_idx(class_T *cl, int is_object, int member_idx);
+type_T *oc_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx);
+type_T *oc_member_type_by_idx(class_T *cl, int is_object, int member_idx);
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);
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index eead19283a..1aa9de7b99 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -7431,4 +7431,50 @@ def Test_funcref_argtype_returntype_check()
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
enddef
+" Test for using an operator (e.g. +) with an assignment
+def Test_op_and_assignment()
+ # Using += with a class variable
+ var lines =<< trim END
+ vim9script
+ class A
+ public static val: list<number> = []
+ static def Foo(): list<number>
+ val += [1]
+ return val
+ enddef
+ endclass
+ def Bar(): list<number>
+ A.val += [2]
+ return A.val
+ enddef
+ assert_equal([1], A.Foo())
+ assert_equal([1, 2], Bar())
+ A.val += [3]
+ assert_equal([1, 2, 3], A.val)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # Using += with an object variable
+ lines =<< trim END
+ vim9script
+ class A
+ public this.val: list<number> = []
+ def Foo(): list<number>
+ this.val += [1]
+ return this.val
+ enddef
+ endclass
+ def Bar(bar_a: A): list<number>
+ bar_a.val += [2]
+ return bar_a.val
+ enddef
+ var a = A.new()
+ assert_equal([1], a.Foo())
+ assert_equal([1, 2], Bar(a))
+ a.val += [3]
+ assert_equal([1, 2, 3], a.val)
+ END
+ v9.CheckSourceSuccess(lines)
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/version.c b/src/version.c
index 61f6289e28..4031debd86 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2016,
+/**/
2015,
/**/
2014,
diff --git a/src/vim9class.c b/src/vim9class.c
index 0cb353bb57..5dda700fa3 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -2032,7 +2032,7 @@ cleanup:
* Set *p_m ocmmember_T if not NULL
*/
type_T *
-class_member_type(
+oc_member_type(
class_T *cl,
int is_object,
char_u *name,
@@ -2060,7 +2060,7 @@ class_member_type(
* Given a class or object variable index, return the variable type
*/
type_T *
-class_member_type_by_idx(
+oc_member_type_by_idx(
class_T *cl,
int is_object,
int member_idx)
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 7e1914b694..544ad17e10 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1770,7 +1770,7 @@ compile_lhs(
lhs->lhs_dest = dest_class_member;
lhs->lhs_class = cctx->ctx_ufunc->uf_class;
lhs->lhs_type =
- class_member_type_by_idx(cctx->ctx_ufunc->uf_class,
+ oc_member_type_by_idx(cctx->ctx_ufunc->uf_class,
FALSE, lhs->lhs_classmember_idx);
}
else
@@ -2254,7 +2254,7 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
return FAIL;
class_T *cl = lhs->lhs_type->tt_class;
- type_T *type = class_member_type(cl, TRUE, dot + 1,
+ type_T *type = oc_member_type(cl, TRUE, dot + 1,
lhs->lhs_end, &lhs->lhs_member_idx);
if (lhs->lhs_member_idx < 0)
return FAIL;
@@ -2275,6 +2275,22 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
return generate_GET_ITF_MEMBER(cctx, cl, lhs->lhs_member_idx, type);
return generate_GET_OBJ_MEMBER(cctx, lhs->lhs_member_idx, type);
}
+ else if (lhs->lhs_type->tt_type == VAR_CLASS)
+ {
+ // "<classname>.value": load class variable "classname.value"
+ char_u *dot = vim_strchr(var_start, '.');
+ if (dot == NULL)
+ return FAIL;
+
+ class_T *cl = lhs->lhs_type->tt_class;
+ ocmember_T *m = class_member_lookup(cl, dot + 1,
+ lhs->lhs_end - dot - 1,
+ &lhs->lhs_member_idx);
+ if (m == NULL)
+ return FAIL;
+
+ return generate_CLASSMEMBER(cctx, TRUE, cl, lhs->lhs_member_idx);
+ }
compile_load_lhs(lhs, var_start, NULL, cctx);