comparison src/testdir/test_vim9_class.vim @ 33286:0c3553cfe22e v9.0.1909

patch 9.0.1909: Vim9: problem calling class method from other class Commit: https://github.com/vim/vim/commit/00cd18222ee1551c65228e9556c158624507fc7a Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Mon Sep 18 19:56:49 2023 +0200 patch 9.0.1909: Vim9: problem calling class method from other class Problem: Vim9: problem calling class method from other class Solution: Fix this problem, fix readonly object access, update error messages. Calling a class method from another method without the class name prefix doesn't work properly. A readonly object variable is modifiable outside the class using a nested object assignment. Remove the unused E1338 error message. Update error messages. closes: #13116 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Mon, 18 Sep 2023 20:00:12 +0200
parents b5ed566262d3
children 4cb421ba3385
comparison
equal deleted inserted replaced
33285:a24779258892 33286:0c3553cfe22e
2 2
3 source check.vim 3 source check.vim
4 import './vim9.vim' as v9 4 import './vim9.vim' as v9
5 5
6 def Test_class_basic() 6 def Test_class_basic()
7 # Class supported only in "vim9script"
7 var lines =<< trim END 8 var lines =<< trim END
8 class NotWorking 9 class NotWorking
9 endclass 10 endclass
10 END 11 END
11 v9.CheckSourceFailure(lines, 'E1316:') 12 v9.CheckSourceFailure(lines, 'E1316:')
12 13
14 # First character in a class name should be capitalized.
13 lines =<< trim END 15 lines =<< trim END
14 vim9script 16 vim9script
15 class notWorking 17 class notWorking
16 endclass 18 endclass
17 END 19 END
18 v9.CheckSourceFailure(lines, 'E1314:') 20 v9.CheckSourceFailure(lines, 'E1314:')
19 21
22 # Only alphanumeric characters are supported in a class name
20 lines =<< trim END 23 lines =<< trim END
21 vim9script 24 vim9script
22 class Not@working 25 class Not@working
23 endclass 26 endclass
24 END 27 END
25 v9.CheckSourceFailure(lines, 'E1315:') 28 v9.CheckSourceFailure(lines, 'E1315:')
26 29
30 # Unsupported keyword (instead of class)
27 lines =<< trim END 31 lines =<< trim END
28 vim9script 32 vim9script
29 abstract noclass Something 33 abstract noclass Something
30 endclass 34 endclass
31 END 35 END
32 v9.CheckSourceFailure(lines, 'E475:') 36 v9.CheckSourceFailure(lines, 'E475:')
33 37
38 # Only the completed word "class" should be recognized
34 lines =<< trim END 39 lines =<< trim END
35 vim9script 40 vim9script
36 abstract classy Something 41 abstract classy Something
37 endclass 42 endclass
38 END 43 END
39 v9.CheckSourceFailure(lines, 'E475:') 44 v9.CheckSourceFailure(lines, 'E475:')
40 45
46 # The complete "endclass" should be specified.
41 lines =<< trim END 47 lines =<< trim END
42 vim9script 48 vim9script
43 class Something 49 class Something
44 endcl 50 endcl
45 END 51 END
46 v9.CheckSourceFailure(lines, 'E1065:') 52 v9.CheckSourceFailure(lines, 'E1065:')
47 53
54 # Additional words after "endclass"
48 lines =<< trim END 55 lines =<< trim END
49 vim9script 56 vim9script
50 class Something 57 class Something
51 endclass school's out 58 endclass school's out
52 END 59 END
53 v9.CheckSourceFailure(lines, 'E488:') 60 v9.CheckSourceFailure(lines, 'E488:')
54 61
62 # Additional commands after "endclass"
55 lines =<< trim END 63 lines =<< trim END
56 vim9script 64 vim9script
57 class Something 65 class Something
58 endclass | echo 'done' 66 endclass | echo 'done'
59 END 67 END
60 v9.CheckSourceFailure(lines, 'E488:') 68 v9.CheckSourceFailure(lines, 'E488:')
61 69
70 # Use "this" without any member variable name
62 lines =<< trim END 71 lines =<< trim END
63 vim9script 72 vim9script
64 class Something 73 class Something
65 this 74 this
66 endclass 75 endclass
67 END 76 END
68 v9.CheckSourceFailure(lines, 'E1317:') 77 v9.CheckSourceFailure(lines, 'E1317:')
69 78
79 # Use "this." without any member variable name
70 lines =<< trim END 80 lines =<< trim END
71 vim9script 81 vim9script
72 class Something 82 class Something
73 this. 83 this.
74 endclass 84 endclass
75 END 85 END
76 v9.CheckSourceFailure(lines, 'E1317:') 86 v9.CheckSourceFailure(lines, 'E1317:')
77 87
88 # Space between "this" and ".<variable>"
78 lines =<< trim END 89 lines =<< trim END
79 vim9script 90 vim9script
80 class Something 91 class Something
81 this .count 92 this .count
82 endclass 93 endclass
83 END 94 END
84 v9.CheckSourceFailure(lines, 'E1317:') 95 v9.CheckSourceFailure(lines, 'E1317:')
85 96
97 # Space between "this." and the member variable name
86 lines =<< trim END 98 lines =<< trim END
87 vim9script 99 vim9script
88 class Something 100 class Something
89 this. count 101 this. count
90 endclass 102 endclass
91 END 103 END
92 v9.CheckSourceFailure(lines, 'E1317:') 104 v9.CheckSourceFailure(lines, 'E1317:')
93 105
106 # Use "that" instead of "this"
94 lines =<< trim END 107 lines =<< trim END
95 vim9script 108 vim9script
96 class Something 109 class Something
97 this.count: number 110 this.count: number
98 that.count 111 that.count
99 endclass 112 endclass
100 END 113 END
101 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count') 114 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count')
102 115
116 # Member variable without a type or initialization
103 lines =<< trim END 117 lines =<< trim END
104 vim9script 118 vim9script
105 class Something 119 class Something
106 this.count 120 this.count
107 endclass 121 endclass
108 END 122 END
109 v9.CheckSourceFailure(lines, 'E1022:') 123 v9.CheckSourceFailure(lines, 'E1022:')
110 124
125 # Use a non-existing member variable in new()
111 lines =<< trim END 126 lines =<< trim END
112 vim9script 127 vim9script
113 class Something 128 class Something
114 def new() 129 def new()
115 this.state = 0 130 this.state = 0
116 enddef 131 enddef
117 endclass 132 endclass
118 var obj = Something.new() 133 var obj = Something.new()
119 END 134 END
120 v9.CheckSourceFailure(lines, 'E1089:') 135 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Something": state')
121 136
137 # Space before ":" in a member variable declaration
122 lines =<< trim END 138 lines =<< trim END
123 vim9script 139 vim9script
124 class Something 140 class Something
125 this.count : number 141 this.count : number
126 endclass 142 endclass
127 END 143 END
128 v9.CheckSourceFailure(lines, 'E1059:') 144 v9.CheckSourceFailure(lines, 'E1059:')
129 145
146 # No space after ":" in a member variable declaration
130 lines =<< trim END 147 lines =<< trim END
131 vim9script 148 vim9script
132 class Something 149 class Something
133 this.count:number 150 this.count:number
134 endclass 151 endclass
202 var a = A.new() 219 var a = A.new()
203 :exe 'call ' .. a 220 :exe 'call ' .. a
204 END 221 END
205 v9.CheckSourceFailure(lines, 'E1324: Using an object as a String') 222 v9.CheckSourceFailure(lines, 'E1324: Using an object as a String')
206 223
224 # Test creating a class with member variables and methods, calling a object
225 # method. Check for using type() and typename() with a class and an object.
207 lines =<< trim END 226 lines =<< trim END
208 vim9script 227 vim9script
209 228
210 class TextPosition 229 class TextPosition
211 this.lnum: number 230 this.lnum: number
268 var a = A.new() 287 var a = A.new()
269 var v = a.Foo(,) 288 var v = a.Foo(,)
270 END 289 END
271 v9.CheckSourceFailure(lines, 'E15:') 290 v9.CheckSourceFailure(lines, 'E15:')
272 291
292 # Use a multi-line initialization for a member variable
273 lines =<< trim END 293 lines =<< trim END
274 vim9script 294 vim9script
275 class A 295 class A
276 this.y = { 296 this.y = {
277 X: 1 297 X: 1
345 END 365 END
346 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface') 366 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
347 enddef 367 enddef
348 368
349 def Test_object_not_set() 369 def Test_object_not_set()
370 # Use an uninitialized object in script context
350 var lines =<< trim END 371 var lines =<< trim END
351 vim9script 372 vim9script
352 373
353 class State 374 class State
354 this.value = 'xyz' 375 this.value = 'xyz'
358 var db = {'xyz': 789} 379 var db = {'xyz': 789}
359 echo db[state.value] 380 echo db[state.value]
360 END 381 END
361 v9.CheckSourceFailure(lines, 'E1360:') 382 v9.CheckSourceFailure(lines, 'E1360:')
362 383
384 # Use an uninitialized object from a def function
363 lines =<< trim END 385 lines =<< trim END
364 vim9script 386 vim9script
365 387
366 class Class 388 class Class
367 this.id: string 389 this.id: string
376 enddef 398 enddef
377 Func() 399 Func()
378 END 400 END
379 v9.CheckSourceFailure(lines, 'E1360:') 401 v9.CheckSourceFailure(lines, 'E1360:')
380 402
403 # Pass an uninitialized object variable to a "new" function and try to call an
404 # object method.
381 lines =<< trim END 405 lines =<< trim END
382 vim9script 406 vim9script
383 407
384 class Background 408 class Background
385 this.background = 'dark' 409 this.background = 'dark'
416 Func() 440 Func()
417 END 441 END
418 v9.CheckSourceFailure(lines, 'E1363:') 442 v9.CheckSourceFailure(lines, 'E1363:')
419 enddef 443 enddef
420 444
445 " Null object assignment and comparison
421 def Test_null_object_assign_compare() 446 def Test_null_object_assign_compare()
422 var lines =<< trim END 447 var lines =<< trim END
423 vim9script 448 vim9script
424 449
425 var nullo = null_object 450 var nullo = null_object
456 assert_true(o2 == null) 481 assert_true(o2 == null)
457 END 482 END
458 v9.CheckSourceSuccess(lines) 483 v9.CheckSourceSuccess(lines)
459 enddef 484 enddef
460 485
486 " Test for object member initialization and disassembly
461 def Test_class_member_initializer() 487 def Test_class_member_initializer()
462 var lines =<< trim END 488 var lines =<< trim END
463 vim9script 489 vim9script
464 490
465 class TextPosition 491 class TextPosition
515 F(outer_obj) 541 F(outer_obj)
516 assert_equal(1, inner_obj.value) 542 assert_equal(1, inner_obj.value)
517 END 543 END
518 v9.CheckSourceSuccess(lines) 544 v9.CheckSourceSuccess(lines)
519 545
520 lines =<< trim END
521 vim9script
522
523 class Inner
524 this.value: number = 0
525 endclass
526
527 class Outer
528 this.inner: Inner
529 endclass
530
531 def F(outer: Outer)
532 outer.inner.value = 1
533 enddef
534
535 def Test_assign_to_nested_typed_member()
536 var inner = Inner.new(0)
537 var outer = Outer.new(inner)
538 F(outer)
539 assert_equal(1, inner.value)
540 enddef
541
542 Test_assign_to_nested_typed_member()
543 END
544 v9.CheckSourceSuccess(lines)
545
546 # Try modifying a private variable using an "any" object 546 # Try modifying a private variable using an "any" object
547 lines =<< trim END 547 lines =<< trim END
548 vim9script 548 vim9script
549 549
550 class Inner 550 class Inner
586 F(outer_obj) 586 F(outer_obj)
587 END 587 END
588 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Inner": someval') 588 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Inner": someval')
589 enddef 589 enddef
590 590
591 " Nested assignment to a object variable which is of another class type
592 def Test_assignment_nested_type()
593 var lines =<< trim END
594 vim9script
595
596 class Inner
597 public this.value: number = 0
598 endclass
599
600 class Outer
601 this.inner: Inner
602 endclass
603
604 def F(outer: Outer)
605 outer.inner.value = 1
606 enddef
607
608 def Test_assign_to_nested_typed_member()
609 var inner = Inner.new(0)
610 var outer = Outer.new(inner)
611 F(outer)
612 assert_equal(1, inner.value)
613 enddef
614
615 Test_assign_to_nested_typed_member()
616 END
617 v9.CheckSourceSuccess(lines)
618 enddef
619
591 def Test_assignment_with_operator() 620 def Test_assignment_with_operator()
621 # Use "+=" to assign to a object variable
592 var lines =<< trim END 622 var lines =<< trim END
593 vim9script 623 vim9script
594 624
595 class Foo 625 class Foo
596 public this.x: number 626 public this.x: number
759 enddef 789 enddef
760 endclass 790 endclass
761 END 791 END
762 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'") 792 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'")
763 enddef 793 enddef
764
765 794
766 def Test_class_new_with_object_member() 795 def Test_class_new_with_object_member()
767 var lines =<< trim END 796 var lines =<< trim END
768 vim9script 797 vim9script
769 798
1675 assert_equal(150, o.ObjFoo()) 1704 assert_equal(150, o.ObjFoo())
1676 END 1705 END
1677 call v9.CheckSourceSuccess(lines) 1706 call v9.CheckSourceSuccess(lines)
1678 endfunc 1707 endfunc
1679 1708
1680 def Test_class_function() 1709 def Test_class_method()
1681 var lines =<< trim END 1710 var lines =<< trim END
1682 vim9script 1711 vim9script
1683 class Value 1712 class Value
1684 this.value = 0 1713 this.value = 0
1685 static objects = 0 1714 static objects = 0
1711 enddef 1740 enddef
1712 aaa 1741 aaa
1713 endclass 1742 endclass
1714 END 1743 END
1715 v9.CheckSourceFailure(lines, 'E1318:') 1744 v9.CheckSourceFailure(lines, 'E1318:')
1745
1746 # Test for calling a class method from another class method without the class
1747 # name prefix.
1748 lines =<< trim END
1749 vim9script
1750 class A
1751 static myList: list<number> = [1]
1752 static def Foo(n: number)
1753 myList->add(n)
1754 enddef
1755 static def Bar()
1756 Foo(2)
1757 enddef
1758 def Baz()
1759 Foo(3)
1760 enddef
1761 endclass
1762 A.Bar()
1763 var a = A.new()
1764 a.Baz()
1765 assert_equal([1, 2, 3], A.myList)
1766 END
1767 v9.CheckSourceSuccess(lines)
1716 enddef 1768 enddef
1717 1769
1718 def Test_class_defcompile() 1770 def Test_class_defcompile()
1719 var lines =<< trim END 1771 var lines =<< trim END
1720 vim9script 1772 vim9script
2341 assert_equal('child/resource', g:result) 2393 assert_equal('child/resource', g:result)
2342 unlet g:result 2394 unlet g:result
2343 END 2395 END
2344 v9.CheckSourceSuccess(lines) 2396 v9.CheckSourceSuccess(lines)
2345 2397
2346
2347 # No class that implements the interface. 2398 # No class that implements the interface.
2348 lines =<< trim END 2399 lines =<< trim END
2349 vim9script 2400 vim9script
2350 2401
2351 interface IWithEE 2402 interface IWithEE
2682 var obj = Child.new() 2733 var obj = Child.new()
2683 assert_equal(true, obj.success) 2734 assert_equal(true, obj.success)
2684 END 2735 END
2685 v9.CheckSourceSuccess(lines) 2736 v9.CheckSourceSuccess(lines)
2686 enddef 2737 enddef
2687
2688 2738
2689 def Test_class_import() 2739 def Test_class_import()
2690 var lines =<< trim END 2740 var lines =<< trim END
2691 vim9script 2741 vim9script
2692 export class Animal 2742 export class Animal
3649 class A 3699 class A
3650 static def _Foo(): number 3700 static def _Foo(): number
3651 return 1234 3701 return 1234
3652 enddef 3702 enddef
3653 def Bar() 3703 def Bar()
3654 assert_equal(1234, A._Foo()) 3704 assert_equal(1234, _Foo())
3655 enddef 3705 enddef
3656 endclass 3706 endclass
3657 var a = A.new() 3707 var a = A.new()
3658 a.Bar() 3708 a.Bar()
3659 END 3709 END
3660 v9.CheckSourceSuccess(lines) 3710 v9.CheckSourceSuccess(lines)
3661 3711
3662 # Use a class private method from another class private method 3712 # Use a class private method from another class private method without the
3713 # class name prefix.
3663 lines =<< trim END 3714 lines =<< trim END
3664 vim9script 3715 vim9script
3665 3716
3666 class A 3717 class A
3667 static def _Foo1(): number 3718 static def _Foo1(): number
3668 return 1234 3719 return 1234
3669 enddef 3720 enddef
3670 static def _Foo2() 3721 static def _Foo2()
3671 assert_equal(1234, A._Foo1()) 3722 assert_equal(1234, _Foo1())
3672 enddef 3723 enddef
3673 def Bar() 3724 def Bar()
3674 A._Foo2() 3725 _Foo2()
3675 enddef 3726 enddef
3676 endclass 3727 endclass
3677 var a = A.new() 3728 var a = A.new()
3678 a.Bar() 3729 a.Bar()
3679 END 3730 END
4061 var a = A.new() 4112 var a = A.new()
4062 a._a = 1 4113 a._a = 1
4063 enddef 4114 enddef
4064 T() 4115 T()
4065 END 4116 END
4066 v9.CheckSourceFailure(lines, 'E1089: Unknown variable: _a') 4117 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": _a')
4067 4118
4068 # private static member variable 4119 # private static member variable
4069 lines =<< trim END 4120 lines =<< trim END
4070 vim9script 4121 vim9script
4071 class A 4122 class A
4089 var a = A.new() 4140 var a = A.new()
4090 a._val = 3 4141 a._val = 3
4091 enddef 4142 enddef
4092 T() 4143 T()
4093 END 4144 END
4094 v9.CheckSourceFailure(lines, 'E1374: Class member "_val" accessible only inside class "A"') 4145 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
4095 4146
4096 # private static class variable 4147 # private static class variable
4097 lines =<< trim END 4148 lines =<< trim END
4098 vim9script 4149 vim9script
4099 class A 4150 class A
4263 var a = A.new() 4314 var a = A.new()
4264 a.svar2 = [2] 4315 a.svar2 = [2]
4265 enddef 4316 enddef
4266 T() 4317 T()
4267 END 4318 END
4268 v9.CheckSourceFailure(lines, 'E1374: Class member "svar2" accessible only inside class "A"') 4319 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
4269 enddef 4320 enddef
4270 4321
4271 " Test for using a interface method using a child object 4322 " Test for using a interface method using a child object
4272 def Test_interface_method_from_child() 4323 def Test_interface_method_from_child()
4273 var lines =<< trim END 4324 var lines =<< trim END
4709 var a = A.new() 4760 var a = A.new()
4710 a.val = 20 4761 a.val = 20
4711 enddef 4762 enddef
4712 T() 4763 T()
4713 END 4764 END
4714 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"') 4765 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4715 4766
4716 # Reading a class variable using an object at function level 4767 # Reading a class variable using an object at function level
4717 lines =<< trim END 4768 lines =<< trim END
4718 vim9script 4769 vim9script
4719 4770
4975 vim9script 5026 vim9script
4976 interface A 5027 interface A
4977 static num: number 5028 static num: number
4978 endinterface 5029 endinterface
4979 END 5030 END
4980 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface') 5031 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
4981 5032
4982 lines =<< trim END 5033 lines =<< trim END
4983 vim9script 5034 vim9script
4984 interface A 5035 interface A
4985 static _num: number 5036 static _num: number
4986 endinterface 5037 endinterface
4987 END 5038 END
4988 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface') 5039 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
4989 5040
4990 lines =<< trim END 5041 lines =<< trim END
4991 vim9script 5042 vim9script
4992 interface A 5043 interface A
4993 public static num: number 5044 public static num: number
4994 endinterface 5045 endinterface
4995 END 5046 END
4996 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface') 5047 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
4997 5048
4998 lines =<< trim END 5049 lines =<< trim END
4999 vim9script 5050 vim9script
5000 interface A 5051 interface A
5001 public static _num: number 5052 public static _num: number
5002 endinterface 5053 endinterface
5003 END 5054 END
5004 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface') 5055 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
5005 5056
5006 lines =<< trim END 5057 lines =<< trim END
5007 vim9script 5058 vim9script
5008 interface A 5059 interface A
5009 static def Foo(d: dict<any>): list<string> 5060 static def Foo(d: dict<any>): list<string>
5010 endinterface 5061 endinterface
5011 END 5062 END
5012 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface') 5063 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
5013 5064
5014 lines =<< trim END 5065 lines =<< trim END
5015 vim9script 5066 vim9script
5016 interface A 5067 interface A
5017 static def _Foo(d: dict<any>): list<string> 5068 static def _Foo(d: dict<any>): list<string>
5018 endinterface 5069 endinterface
5019 END 5070 END
5020 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface') 5071 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
5021 5072
5022 lines =<< trim END 5073 lines =<< trim END
5023 vim9script 5074 vim9script
5024 interface A 5075 interface A
5025 this._Foo: list<string> 5076 this._Foo: list<string>
5400 var b = B.new() 5451 var b = B.new()
5401 END 5452 END
5402 v9.CheckSourceFailure(lines, 'E1382: Member "val": type mismatch, expected list<dict<string>> but got dict<number>') 5453 v9.CheckSourceFailure(lines, 'E1382: Member "val": type mismatch, expected list<dict<string>> but got dict<number>')
5403 enddef 5454 enddef
5404 5455
5456 " Test for assigning to a member variable in a nested class
5457 def Test_nested_object_assignment()
5458 var lines =<< trim END
5459 vim9script
5460
5461 class A
5462 this.value: number
5463 endclass
5464
5465 class B
5466 this.a: A = A.new()
5467 endclass
5468
5469 class C
5470 this.b: B = B.new()
5471 endclass
5472
5473 class D
5474 this.c: C = C.new()
5475 endclass
5476
5477 def T(da: D)
5478 da.c.b.a.value = 10
5479 enddef
5480
5481 var d = D.new()
5482 T(d)
5483 END
5484 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "value"')
5485 enddef
5486
5405 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 5487 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker