1
0
forked from aniani/vim

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>
This commit is contained in:
Ernie Rael
2023-10-11 21:35:11 +02:00
committed by Christian Brabandt
parent c97b3febc8
commit 4c8da025ef
7 changed files with 461 additions and 26 deletions

View File

@@ -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)
# 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