summaryrefslogtreecommitdiffstats
path: root/src/testdir/test_vim9_class.vim
diff options
context:
space:
mode:
Diffstat (limited to 'src/testdir/test_vim9_class.vim')
-rw-r--r--src/testdir/test_vim9_class.vim476
1 files changed, 475 insertions, 1 deletions
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index c643457cca..9799a2f518 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -3480,7 +3480,7 @@ enddef
" Test for locking a variable referring to an object and reassigning to another
" object.
-def Test_object_lockvar()
+def Test_lockvar_object()
var lines =<< trim END
vim9script
@@ -3515,6 +3515,480 @@ def Test_object_lockvar()
v9.CheckSourceSuccess(lines)
enddef
+" Test trying to lock an object variable from various places
+def Test_lockvar_object_variable()
+ # An object variable lockvar has several cases:
+ # object method, scriptlevel, scriplevel from :def, :def arg
+ # method arg, static method arg.
+ # Also different depths
+
+ # TODO: handle inside_class in vim9class
+ # lockvar of a read-only currently fails even if inside
+
+ #
+ # lockvar of read-only object variable
+ #
+
+ # read-only lockvar from object method
+ var lines =<< trim END
+ vim9script
+
+ class C
+ this.val1: number
+ def Lock()
+ lockvar this.val1
+ enddef
+ endclass
+ var o = C.new(3)
+ o.Lock()
+ END
+ # TODO: wrong error
+ v9.CheckSourceFailure(lines, 'E1335: Variable "val1" in class "C" is not writable')
+
+ # read-only lockvar from scriptlevel
+ lines =<< trim END
+ vim9script
+
+ class C
+ this.val2: number
+ endclass
+ var o = C.new(3)
+ lockvar o.val2
+ END
+ v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
+
+ # read-only lockvar of scriptlevel variable from def
+ lines =<< trim END
+ vim9script
+
+ class C
+ this.val3: number
+ endclass
+ var o = C.new(3)
+ def Lock()
+ lockvar o.val3
+ enddef
+ Lock()
+ END
+ v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
+
+ # read-only lockvar of def argument variable
+ lines =<< trim END
+ vim9script
+
+ class C
+ this.val4: number
+ endclass
+ def Lock(o: C)
+ lockvar o.val4
+ enddef
+ Lock(C.new(3))
+ END
+ v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
+
+ # TODO: the following tests use type "any" for argument. Need a run time
+ # check for access. Probably OK as is for now.
+
+ # read-only lockvar from object method arg
+ lines =<< trim END
+ vim9script
+
+ class C
+ this.val5: number
+ def Lock(o_any: any)
+ lockvar o_any.val5
+ enddef
+ endclass
+ var o = C.new(3)
+ o.Lock(C.new(5))
+ END
+ # TODO: wrong error, tricky since type "any"
+ v9.CheckSourceFailure(lines, 'E1335: Variable "val5" in class "C" is not writable')
+
+ # read-only lockvar from class method arg
+ lines =<< trim END
+ vim9script
+
+ class C
+ this.val6: number
+ static def Lock(o_any: any)
+ lockvar o_any.val6
+ enddef
+ endclass
+ var o = C.new(3)
+ C.Lock(o)
+ END
+ # TODO: wrong error, tricky since type "any"
+ v9.CheckSourceFailure(lines, 'E1335: Variable "val6" in class "C" is not writable')
+
+ #
+ # lockvar of public object variable
+ #
+
+ # lockvar from object method
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val1: number
+ def Lock()
+ lockvar this.val1
+ enddef
+ endclass
+ var o = C.new(3)
+ o.Lock()
+ END
+ v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
+
+ # lockvar from scriptlevel
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val2: number
+ endclass
+ var o = C.new(3)
+ lockvar o.val2
+ END
+ v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
+
+ # lockvar of scriptlevel variable from def
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val3: number
+ endclass
+ var o = C.new(3)
+ def Lock()
+ lockvar o.val3
+ enddef
+ Lock()
+ END
+ v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
+
+ # lockvar of def argument variable
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val4: number
+ endclass
+ def Lock(o: C)
+ lockvar o.val4
+ enddef
+ Lock(C.new(3))
+ END
+ v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
+
+ # lockvar from object method arg
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val5: number
+ def Lock(o_any: any)
+ lockvar o_any.val5
+ enddef
+ endclass
+ var o = C.new(3)
+ o.Lock(C.new(5))
+ END
+ v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val5" in class "C"', 1)
+
+ # lockvar from class method arg
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val6: number
+ static def Lock(o_any: any)
+ lockvar o_any.val6
+ enddef
+ endclass
+ var o = C.new(3)
+ C.Lock(o)
+ END
+ v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val6" in class "C"', 1)
+enddef
+
+" Test trying to lock a class variable from various places
+def Test_lockvar_class_variable()
+
+ # lockvar bare static from object method
+ var lines =<< trim END
+ vim9script
+
+ class C
+ public static sval1: number
+ def Lock()
+ lockvar sval1
+ enddef
+ endclass
+ var o = C.new()
+ o.Lock()
+ END
+ v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
+
+ # lockvar C.static from object method
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval2: number
+ def Lock()
+ lockvar C.sval2
+ enddef
+ endclass
+ var o = C.new()
+ o.Lock()
+ END
+ v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
+
+ # lockvar bare static from class method
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval3: number
+ static def Lock()
+ lockvar sval3
+ enddef
+ endclass
+ C.Lock()
+ END
+ v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
+
+ # lockvar C.static from class method
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval4: number
+ static def Lock()
+ lockvar C.sval4
+ enddef
+ endclass
+ C.Lock()
+ END
+ v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
+
+ # lockvar C.static from script level
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval5: number
+ endclass
+ lockvar C.sval5
+ END
+ v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
+
+ # lockvar o.static from script level
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval6: number
+ endclass
+ var o = C.new()
+ lockvar o.sval6
+ END
+ v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
+enddef
+
+" Test locking an argument to :def
+def Test_lockvar_argument()
+ # Lockvar a function arg
+ var lines =<< trim END
+ vim9script
+
+ def Lock(val: any)
+ lockvar val
+ enddef
+
+ var d = {a: 1, b: 2}
+ Lock(d)
+
+ d->extend({c: 3})
+ END
+ v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
+
+ # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
+ # class member in "C". This tests lval_root_is_arg.
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval: list<number>
+ endclass
+
+ def Lock2(sval: any)
+ lockvar sval
+ enddef
+
+ var o = C.new()
+ Lock2(o)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # Lock a class.
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval: list<number>
+ endclass
+
+ def Lock2(sval: any)
+ lockvar sval
+ enddef
+
+ Lock2(C)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # Lock an object.
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval: list<number>
+ endclass
+
+ def Lock2(sval: any)
+ lockvar sval
+ enddef
+
+ Lock2(C.new())
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # In this case (unlike previous) "lockvar sval" is a class member.
+ lines =<< trim END
+ vim9script
+
+ class C
+ public static sval: list<number>
+ def Lock2()
+ lockvar sval
+ enddef
+ endclass
+
+
+ var o = C.new()
+ o.Lock2()
+ END
+ v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
+enddef
+
+" Test that this can be locked without error
+def Test_lockvar_this()
+ # lockvar this
+ var lines =<< trim END
+ vim9script
+ class C
+ def TLock()
+ lockvar this
+ enddef
+ endclass
+ var o = C.new()
+ o.TLock()
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # lockvar four (four letter word, but not this)
+ lines =<< trim END
+ vim9script
+ class C
+ def TLock4()
+ var four: number
+ lockvar four
+ enddef
+ endclass
+ var o = C.new()
+ o.TLock4()
+ END
+ v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
+
+ # lockvar this5; "this" + one char, 5 letter word, starting with "this"
+ lines =<< trim END
+ vim9script
+ class C
+ def TLock5()
+ var this5: number
+ lockvar this5
+ enddef
+ endclass
+ var o = C.new()
+ o.TLock5()
+ END
+ v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
+enddef
+
+" Test some general lockvar cases
+def Test_lockvar_general()
+ # lockvar an object and a class. It does nothing
+ var lines =<< trim END
+ vim9script
+ class C
+ endclass
+ var o = C.new()
+ lockvar o
+ lockvar C
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # Lock a list element that's nested in an object variable from a :def
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val: list<list<number>> = [ [1], [2], [3] ]
+ endclass
+ def Lock2(obj: any)
+ lockvar obj.val[1]
+ enddef
+
+ var o = C.new()
+ Lock2(o)
+ o.val[0] = [9]
+ assert_equal([ [9], [2], [3] ], o.val)
+ try
+ o.val[1] = [999]
+ call assert_false(true, 'assign should have failed')
+ catch
+ assert_exception('E741:')
+ endtry
+ o.val[2] = [8]
+ assert_equal([ [9], [2], [8] ], o.val)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # Lock a list element that's nested in an object variable from scriptlevel
+ lines =<< trim END
+ vim9script
+
+ class C
+ public this.val: list<list<number>> = [ [1], [2], [3] ]
+ endclass
+
+ var o = C.new()
+ lockvar o.val[1]
+ o.val[0] = [9]
+ assert_equal([ [9], [2], [3] ], o.val)
+ try
+ o.val[1] = [999]
+ call assert_false(true, 'assign should have failed')
+ catch
+ assert_exception('E741:')
+ endtry
+ o.val[2] = [8]
+ assert_equal([ [9], [2], [8] ], o.val)
+ END
+ v9.CheckSourceSuccess(lines)
+enddef
+
" Test for a private object method
def Test_private_object_method()
# Try calling a private method using an object (at the script level)