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.vim758
1 files changed, 746 insertions, 12 deletions
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index b34d2ad..d6c55bf 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -67,7 +67,23 @@ def Test_class_basic()
END
v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3)
- # Use old "this." prefixed member variable declaration syntax (without intialization)
+ # Try to define a class with the same name as an existing variable
+ lines =<< trim END
+ vim9script
+ var Something: list<number> = [1]
+ class Thing
+ endclass
+ interface Api
+ endinterface
+ class Something extends Thing implements Api
+ var v1: string = ''
+ def Foo()
+ enddef
+ endclass
+ END
+ v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 7)
+
+ # Use old "this." prefixed member variable declaration syntax (without initialization)
lines =<< trim END
vim9script
class Something
@@ -76,7 +92,7 @@ def Test_class_basic()
END
v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number', 3)
- # Use old "this." prefixed member variable declaration syntax (with intialization)
+ # Use old "this." prefixed member variable declaration syntax (with initialization)
lines =<< trim END
vim9script
class Something
@@ -9659,31 +9675,749 @@ def Test_const_class_object_variable()
v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
enddef
-" Test for using double underscore prefix in a class/object method name.
-def Test_method_double_underscore_prefix()
- # class method
+" Test for compiling class/object methods using :defcompile
+def Test_defcompile_class()
+ # defcompile all the classes in the current script
var lines =<< trim END
vim9script
class A
- static def __foo()
- echo "foo"
+ def Foo()
+ var i = 10
+ enddef
+ endclass
+ class B
+ def Bar()
+ var i = 20
+ xxx
enddef
endclass
defcompile
END
- v9.CheckSourceFailure(lines, 'E1034: Cannot use reserved name __foo()', 3)
+ v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
- # object method
+ # defcompile a specific class
lines =<< trim END
vim9script
class A
- def __foo()
- echo "foo"
+ def Foo()
+ xxx
+ enddef
+ endclass
+ class B
+ def Bar()
+ yyy
+ enddef
+ endclass
+ defcompile B
+ END
+ v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
+
+ # defcompile a non-class
+ lines =<< trim END
+ vim9script
+ class A
+ def Foo()
+ enddef
+ endclass
+ var X: list<number> = []
+ defcompile X
+ END
+ v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
+
+ # defcompile a class twice
+ lines =<< trim END
+ vim9script
+ class A
+ def new()
+ enddef
+ endclass
+ defcompile A
+ defcompile A
+ assert_equal('Function A.new does not need compiling', v:statusmsg)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # defcompile should not compile an imported class
+ lines =<< trim END
+ vim9script
+ export class A
+ def Foo()
+ xxx
enddef
endclass
+ END
+ writefile(lines, 'Xdefcompileimport.vim', 'D')
+ lines =<< trim END
+ vim9script
+
+ import './Xdefcompileimport.vim'
+ class B
+ endclass
defcompile
END
- v9.CheckSourceFailure(lines, 'E1034: Cannot use reserved name __foo()', 3)
+ v9.CheckScriptSuccess(lines)
+enddef
+
+" Test for cases common to all the object builtin methods
+def Test_object_builtin_method()
+ var lines =<< trim END
+ vim9script
+ class A
+ def abc()
+ enddef
+ endclass
+ END
+ v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
+
+ for funcname in ["len", "string", "empty"]
+ lines =<< trim eval END
+ vim9script
+ class A
+ static def {funcname}(): number
+ enddef
+ endclass
+ END
+ v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
+ endfor
+enddef
+
+" Test for using the empty() builtin method with an object
+" This is a legacy function to use the test_garbagecollect_now() function.
+func Test_object_empty()
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal(true, empty(afoo))
+ assert_equal(true, afoo->empty())
+ enddef
+
+ var a = A.new()
+ assert_equal(1, empty(a))
+ assert_equal(1, a->empty())
+ test_garbagecollect_now()
+ assert_equal(1, empty(a))
+ Foo()
+ test_garbagecollect_now()
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " empty() should return 1 without a builtin method
+ let lines =<< trim END
+ vim9script
+ class A
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal(1, empty(afoo))
+ enddef
+
+ var a = A.new()
+ assert_equal(1, empty(a))
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Unsupported signature for the empty() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty()
+ enddef
+ endclass
+ END
+ call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
+
+ " Error when calling the empty() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ throw "Failed to check emptiness"
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ var i = empty(afoo)
+ enddef
+
+ var a = A.new()
+ assert_fails('empty(a)', 'Failed to check emptiness')
+ assert_fails('Foo()', 'Failed to check emptiness')
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call empty() using an object from a script
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+ var afoo = A.new()
+ assert_equal(true, afoo.empty())
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call empty() using an object from a method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+ def Foo()
+ var afoo = A.new()
+ assert_equal(true, afoo.empty())
+ enddef
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call empty() using "this" from an object method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ def Foo(): bool
+ return this.empty()
+ enddef
+ endclass
+ def Bar()
+ var abar = A.new()
+ assert_equal(true, abar.Foo())
+ enddef
+ Bar()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Call empty() from a derived object
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return false
+ enddef
+ endclass
+ class B extends A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+ def Foo(afoo: A)
+ assert_equal(true, empty(afoo))
+ var bfoo = B.new()
+ assert_equal(true, empty(bfoo))
+ enddef
+ var b = B.new()
+ assert_equal(1, empty(b))
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Invoking empty method using an interface
+ let lines =<< trim END
+ vim9script
+ interface A
+ def empty(): bool
+ endinterface
+ class B implements A
+ def empty(): bool
+ return false
+ enddef
+ endclass
+ def Foo(a: A)
+ assert_equal(false, empty(a))
+ enddef
+ var b = B.new()
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+endfunc
+
+" Test for using the len() builtin method with an object
+" This is a legacy function to use the test_garbagecollect_now() function.
+func Test_object_length()
+ let lines =<< trim END
+ vim9script
+ class A
+ var mylen: number = 0
+ def new(n: number)
+ this.mylen = n
+ enddef
+ def len(): number
+ return this.mylen
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new(12)
+ assert_equal(12, len(afoo))
+ assert_equal(12, afoo->len())
+ enddef
+
+ var a = A.new(22)
+ assert_equal(22, len(a))
+ assert_equal(22, a->len())
+ test_garbagecollect_now()
+ assert_equal(22, len(a))
+ Foo()
+ test_garbagecollect_now()
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " len() should return 0 without a builtin method
+ let lines =<< trim END
+ vim9script
+ class A
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal(0, len(afoo))
+ enddef
+
+ var a = A.new()
+ assert_equal(0, len(a))
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Unsupported signature for the len() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len()
+ enddef
+ endclass
+ END
+ call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
+
+ " Error when calling the len() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ throw "Failed to compute length"
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ var i = len(afoo)
+ enddef
+
+ var a = A.new()
+ assert_fails('len(a)', 'Failed to compute length')
+ assert_fails('Foo()', 'Failed to compute length')
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call len() using an object from a script
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 5
+ enddef
+ endclass
+ var afoo = A.new()
+ assert_equal(5, afoo.len())
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call len() using an object from a method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 5
+ enddef
+ endclass
+ def Foo()
+ var afoo = A.new()
+ assert_equal(5, afoo.len())
+ enddef
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call len() using "this" from an object method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 8
+ enddef
+ def Foo(): number
+ return this.len()
+ enddef
+ endclass
+ def Bar()
+ var abar = A.new()
+ assert_equal(8, abar.Foo())
+ enddef
+ Bar()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Call len() from a derived object
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 10
+ enddef
+ endclass
+ class B extends A
+ def len(): number
+ return 20
+ enddef
+ endclass
+ def Foo(afoo: A)
+ assert_equal(20, len(afoo))
+ var bfoo = B.new()
+ assert_equal(20, len(bfoo))
+ enddef
+ var b = B.new()
+ assert_equal(20, len(b))
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Invoking len method using an interface
+ let lines =<< trim END
+ vim9script
+ interface A
+ def len(): number
+ endinterface
+ class B implements A
+ def len(): number
+ return 123
+ enddef
+ endclass
+ def Foo(a: A)
+ assert_equal(123, len(a))
+ enddef
+ var b = B.new()
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+endfunc
+
+" Test for using the string() builtin method with an object
+" This is a legacy function to use the test_garbagecollect_now() function.
+func Test_object_string()
+ let lines =<< trim END
+ vim9script
+ class A
+ var name: string
+ def string(): string
+ return this.name
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new("foo-A")
+ assert_equal('foo-A', string(afoo))
+ assert_equal('foo-A', afoo->string())
+ enddef
+
+ var a = A.new("script-A")
+ assert_equal('script-A', string(a))
+ assert_equal('script-A', a->string())
+ assert_equal(['script-A'], execute('echo a')->split("\n"))
+ test_garbagecollect_now()
+ assert_equal('script-A', string(a))
+ Foo()
+ test_garbagecollect_now()
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " string() should return "object of A {}" without a builtin method
+ let lines =<< trim END
+ vim9script
+ class A
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal('object of A {}', string(afoo))
+ enddef
+
+ var a = A.new()
+ assert_equal('object of A {}', string(a))
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Unsupported signature for the string() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string()
+ enddef
+ endclass
+ END
+ call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
+
+ " Error when calling the string() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ throw "Failed to get text"
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ var i = string(afoo)
+ enddef
+
+ var a = A.new()
+ assert_fails('string(a)', 'Failed to get text')
+ assert_fails('Foo()', 'Failed to get text')
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call string() using an object from a script
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ endclass
+ var afoo = A.new()
+ assert_equal('A', afoo.string())
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call string() using an object from a method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ endclass
+ def Foo()
+ var afoo = A.new()
+ assert_equal('A', afoo.string())
+ enddef
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call string() using "this" from an object method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ def Foo(): string
+ return this.string()
+ enddef
+ endclass
+ def Bar()
+ var abar = A.new()
+ assert_equal('A', abar.string())
+ enddef
+ Bar()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Call string() from a derived object
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ endclass
+ class B extends A
+ def string(): string
+ return 'B'
+ enddef
+ endclass
+ def Foo(afoo: A)
+ assert_equal('B', string(afoo))
+ var bfoo = B.new()
+ assert_equal('B', string(bfoo))
+ enddef
+ var b = B.new()
+ assert_equal('B', string(b))
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Invoking string method using an interface
+ let lines =<< trim END
+ vim9script
+ interface A
+ def string(): string
+ endinterface
+ class B implements A
+ def string(): string
+ return 'B'
+ enddef
+ endclass
+ def Foo(a: A)
+ assert_equal('B', string(a))
+ enddef
+ var b = B.new()
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+endfunc
+
+" Test for using a class in the class definition
+def Test_Ref_Class_Within_Same_Class()
+ var lines =<< trim END
+ vim9script
+ class A
+ var n: number = 0
+ def Equals(other: A): bool
+ return this.n == other.n
+ enddef
+ endclass
+
+ var a1 = A.new(10)
+ var a2 = A.new(10)
+ var a3 = A.new(20)
+ assert_equal(true, a1.Equals(a2))
+ assert_equal(false, a2.Equals(a3))
+ END
+ v9.CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+
+ class Foo
+ var num: number
+ def Clone(): Foo
+ return Foo.new(this.num)
+ enddef
+ endclass
+
+ var f1 = Foo.new(1)
+
+ def F()
+ var f2: Foo = f1.Clone()
+ assert_equal(false, f2 is f1)
+ assert_equal(true, f2.num == f1.num)
+ enddef
+ F()
+
+ var f3: Foo = f1.Clone()
+ assert_equal(false, f3 is f1)
+ assert_equal(true, f3.num == f1.num)
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # Test for trying to use a class to extend when defining the same class
+ lines =<< trim END
+ vim9script
+ class A extends A
+ endclass
+ END
+ v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
+
+ # Test for trying to use a class to implement when defining the same class
+ lines =<< trim END
+ vim9script
+ class A implements A
+ endclass
+ END
+ v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
+enddef
+
+" Test for using a compound operator from a lambda function in an object method
+def Test_compound_op_in_objmethod_lambda()
+ # Test using the "+=" operator
+ var lines =<< trim END
+ vim9script
+ class A
+ var n: number = 10
+ def Foo()
+ var Fn = () => {
+ this.n += 1
+ }
+ Fn()
+ enddef
+ endclass
+
+ var a = A.new()
+ a.Foo()
+ assert_equal(11, a.n)
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # Test using the "..=" operator
+ lines =<< trim END
+ vim9script
+ class A
+ var s: string = "a"
+ def Foo()
+ var Fn = () => {
+ this.s ..= "a"
+ }
+ Fn()
+ enddef
+ endclass
+
+ var a = A.new()
+ a.Foo()
+ a.Foo()
+ assert_equal("aaa", a.s)
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
+" call a lambda function in one object from another object
+def Test_lambda_invocation_across_classes()
+ var lines =<< trim END
+ vim9script
+ class A
+ var s: string = "foo"
+ def GetFn(): func
+ var Fn = (): string => {
+ return this.s
+ }
+ return Fn
+ enddef
+ endclass
+
+ class B
+ var s: string = "bar"
+ def GetFn(): func
+ var a = A.new()
+ return a.GetFn()
+ enddef
+ endclass
+
+ var b = B.new()
+ var Fn = b.GetFn()
+ assert_equal("foo", Fn())
+ END
+ v9.CheckScriptSuccess(lines)
enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker