Mercurial > vim
diff src/testdir/test_vim9_class.vim @ 33532:f99f5a56ff27 v9.0.2015
patch 9.0.2015: Vim9: does not handle islocked() from a method correctly
Commit: https://github.com/vim/vim/commit/4c8da025ef8140168b7a09d9fe922ce4bb40f19d
Author: Ernie Rael <errael@raelity.com>
Date: Wed Oct 11 21:35:11 2023 +0200
patch 9.0.2015: Vim9: does not handle islocked() from a method correctly
Problem: Vim9: does not handle islocked() from a method correctly
Solution: Handle islocked() builtin from a method.
- Setup `lval_root` from `f_islocked()`.
- Add function `fill_exec_lval_root()` to get info about executing method.
- `sync_root` added in get_lval to handle method member access.
- Conservative approach to reference counting.
closes: #13309
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Ernie Rael <errael@raelity.com>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 11 Oct 2023 21:45:04 +0200 |
parents | 921673b465a6 |
children | c8bd88bdb630 |
line wrap: on
line diff
--- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -1704,8 +1704,7 @@ def Test_class_member() var obj: A obj.val = "" END - # FIXME(in source): this should give E1360 as well! - v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string', 7) + v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7) # Test for accessing a member on a null object, at script level lines =<< trim END @@ -4259,8 +4258,249 @@ def Test_lockvar_islocked() assert_equal(0, islocked("C.c1[0]")) END v9.CheckSourceSuccess(lines) - lines =<< trim END - END + + # Do islocked() from an object method + # and then from a class method + lines =<< trim END + vim9script + + var l0o0 = [ [0], [1], [2]] + var l0o1 = [ [10], [11], [12]] + var l0c0 = [[120], [121], [122]] + var l0c1 = [[130], [131], [132]] + + class C0 + this.o0: list<list<number>> = l0o0 + this.o1: list<list<number>> = l0o1 + static c0: list<list<number>> = l0c0 + static c1: list<list<number>> = l0c1 + def Islocked(arg: string): number + return islocked(arg) + enddef + static def SIslocked(arg: string): number + return islocked(arg) + enddef + endclass + + var l2o0 = [[20000], [20001], [20002]] + var l2o1 = [[20010], [20011], [20012]] + var l2c0 = [[20120], [20121], [20122]] + var l2c1 = [[20130], [20131], [20132]] + + class C2 + this.o0: list<list<number>> = l2o0 + this.o1: list<list<number>> = l2o1 + static c0: list<list<number>> = l2c0 + static c1: list<list<number>> = l2c1 + def Islocked(arg: string): number + return islocked(arg) + enddef + static def SIslocked(arg: string): number + return islocked(arg) + enddef + endclass + + var obj0 = C0.new() + var obj2 = C2.new() + + var l = [ obj0, null_object, obj2 ] + + # lock list, object func access through script var expr + assert_equal(0, obj0.Islocked("l[0].o0")) + assert_equal(0, obj0.Islocked("l[0].o0[2]")) + lockvar l0o0 + assert_equal(1, obj0.Islocked("l[0].o0")) + assert_equal(1, obj0.Islocked("l[0].o0[2]")) + + #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT + + # lock list element, object func access through script var expr + lockvar l0o1[1] + assert_equal(0, obj0.Islocked("this.o1[0]")) + assert_equal(1, obj0.Islocked("this.o1[1]")) + + assert_equal(0, obj0.Islocked("this.o1")) + lockvar l0o1 + assert_equal(1, obj0.Islocked("this.o1")) + unlockvar l0o1 + + lockvar l0c1[1] + + # static by class name member expr from same class + assert_equal(0, obj0.Islocked("C0.c1[0]")) + assert_equal(1, obj0.Islocked("C0.c1[1]")) + # static by bare name member expr from same class + assert_equal(0, obj0.Islocked("c1[0]")) + assert_equal(1, obj0.Islocked("c1[1]")) + + # static by class name member expr from other class + assert_equal(0, obj2.Islocked("C0.c1[0]")) + assert_equal(1, obj2.Islocked("C0.c1[1]")) + # static by bare name member expr from other class + assert_equal(0, obj2.Islocked("c1[0]")) + assert_equal(0, obj2.Islocked("c1[1]")) + + + # static by bare name in same class + assert_equal(0, obj0.Islocked("c0")) + lockvar l0c0 + assert_equal(1, obj0.Islocked("c0")) + + # + # similar stuff, but use static method + # + + unlockvar l0o0 + + # lock list, object func access through script var expr + assert_equal(0, C0.SIslocked("l[0].o0")) + assert_equal(0, C0.SIslocked("l[0].o0[2]")) + lockvar l0o0 + assert_equal(1, C0.SIslocked("l[0].o0")) + assert_equal(1, C0.SIslocked("l[0].o0[2]")) + + unlockvar l0o1 + + # can't access "this" from class method + try + C0.SIslocked("this.o1[0]") + call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed') + catch + call assert_exception('E121: Undefined variable: this') + endtry + + lockvar l0c1[1] + + # static by class name member expr from same class + assert_equal(0, C0.SIslocked("C0.c1[0]")) + assert_equal(1, C0.SIslocked("C0.c1[1]")) + # static by bare name member expr from same class + assert_equal(0, C0.SIslocked("c1[0]")) + assert_equal(1, C0.SIslocked("c1[1]")) + + # static by class name member expr from other class + assert_equal(0, C2.SIslocked("C0.c1[0]")) + assert_equal(1, C2.SIslocked("C0.c1[1]")) + # static by bare name member expr from other class + assert_equal(0, C2.SIslocked("c1[0]")) + assert_equal(0, C2.SIslocked("c1[1]")) + + + # static by bare name in same class + unlockvar l0c0 + assert_equal(0, C0.SIslocked("c0")) + lockvar l0c0 + assert_equal(1, C0.SIslocked("c0")) + END + v9.CheckSourceSuccess(lines) + + # Check islocked class/object from various places. + lines =<< trim END + vim9script + + class C + def Islocked(arg: string): number + return islocked(arg) + enddef + static def SIslocked(arg: string): number + return islocked(arg) + enddef + endclass + var obj = C.new() + + # object method + assert_equal(0, obj.Islocked("this")) + assert_equal(0, obj.Islocked("C")) + + # class method + ### assert_equal(0, C.SIslocked("this")) + assert_equal(0, C.SIslocked("C")) + + #script level + var v: number + v = islocked("C") + assert_equal(0, v) + v = islocked("obj") + assert_equal(0, v) + END + v9.CheckSourceSuccess(lines) +enddef + +def Test_lockvar_islocked_notfound() + # Try non-existent things + var lines =<< trim END + vim9script + + class C + def Islocked(arg: string): number + return islocked(arg) + enddef + static def SIslocked(arg: string): number + return islocked(arg) + enddef + endclass + var obj = C.new() + assert_equal(-1, obj.Islocked("anywhere")) + assert_equal(-1, C.SIslocked("notanywhere")) + END + v9.CheckSourceSuccess(lines) + + # Something not found of the form "name1.name2" is an error + lines =<< trim END + vim9script + + islocked("one.two") + END + v9.CheckSourceFailure(lines, 'E121: Undefined variable: one') + + lines =<< trim END + vim9script + + class C + this.val = { key: "value" } + def Islocked(arg: string): number + return islocked(arg) + enddef + endclass + var obj = C.new() + obj.Islocked("this.val.not_there")) + END + v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"') + + lines =<< trim END + vim9script + + class C + def Islocked(arg: string): number + return islocked(arg) + enddef + endclass + var obj = C.new() + obj.Islocked("this.notobjmember") + END + v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "C": notobjmember') + + # access a script variable through methods + lines =<< trim END + vim9script + + var l = [1] + class C + def Islocked(arg: string): number + return islocked(arg) + enddef + static def SIslocked(arg: string): number + return islocked(arg) + enddef + endclass + var obj = C.new() + assert_equal(0, obj.Islocked("l")) + assert_equal(0, C.SIslocked("l")) + lockvar l + assert_equal(1, obj.Islocked("l")) + assert_equal(1, C.SIslocked("l")) + END + v9.CheckSourceSuccess(lines) enddef " Test for a private object method