blob: ad0be5b5114490ad578ff5f19c4dcf72253c5fbd [file] [log] [blame]
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001" Test Vim9 classes
2
3source check.vim
4import './vim9.vim' as v9
5
6def Test_class_basic()
7 var lines =<< trim END
8 class NotWorking
9 endclass
10 END
11 v9.CheckScriptFailure(lines, 'E1316:')
12
13 lines =<< trim END
14 vim9script
15 class notWorking
16 endclass
17 END
18 v9.CheckScriptFailure(lines, 'E1314:')
19
20 lines =<< trim END
21 vim9script
22 class Not@working
23 endclass
24 END
25 v9.CheckScriptFailure(lines, 'E1315:')
26
27 lines =<< trim END
28 vim9script
29 abstract noclass Something
30 endclass
31 END
32 v9.CheckScriptFailure(lines, 'E475:')
33
34 lines =<< trim END
35 vim9script
36 abstract classy Something
37 endclass
38 END
39 v9.CheckScriptFailure(lines, 'E475:')
40
41 lines =<< trim END
42 vim9script
43 class Something
44 endcl
45 END
46 v9.CheckScriptFailure(lines, 'E1065:')
47
48 lines =<< trim END
49 vim9script
50 class Something
Bram Moolenaar94722c52023-01-28 19:19:03 +000051 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000052 END
53 v9.CheckScriptFailure(lines, 'E488:')
54
55 lines =<< trim END
56 vim9script
57 class Something
58 endclass | echo 'done'
59 END
60 v9.CheckScriptFailure(lines, 'E488:')
61
62 lines =<< trim END
63 vim9script
64 class Something
65 this
66 endclass
67 END
68 v9.CheckScriptFailure(lines, 'E1317:')
69
70 lines =<< trim END
71 vim9script
72 class Something
73 this.
74 endclass
75 END
76 v9.CheckScriptFailure(lines, 'E1317:')
77
78 lines =<< trim END
79 vim9script
80 class Something
81 this .count
82 endclass
83 END
84 v9.CheckScriptFailure(lines, 'E1317:')
85
86 lines =<< trim END
87 vim9script
88 class Something
89 this. count
90 endclass
91 END
92 v9.CheckScriptFailure(lines, 'E1317:')
93
94 lines =<< trim END
95 vim9script
96 class Something
97 this.count: number
98 that.count
99 endclass
100 END
101 v9.CheckScriptFailure(lines, 'E1318: Not a valid command in a class: that.count')
102
103 lines =<< trim END
104 vim9script
105 class Something
106 this.count
107 endclass
108 END
109 v9.CheckScriptFailure(lines, 'E1022:')
110
111 lines =<< trim END
112 vim9script
113 class Something
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000114 def new()
115 this.state = 0
116 enddef
117 endclass
118 var obj = Something.new()
119 END
120 v9.CheckScriptFailure(lines, 'E1089:')
121
122 lines =<< trim END
123 vim9script
124 class Something
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000125 this.count : number
126 endclass
127 END
128 v9.CheckScriptFailure(lines, 'E1059:')
129
130 lines =<< trim END
131 vim9script
132 class Something
133 this.count:number
134 endclass
135 END
136 v9.CheckScriptFailure(lines, 'E1069:')
137
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200138 # Test for unsupported comment specifier
139 lines =<< trim END
140 vim9script
141 class Something
142 # comment
143 #{
144 endclass
145 END
146 v9.CheckScriptFailure(lines, 'E1170:')
147
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000148 lines =<< trim END
149 vim9script
150
151 class TextPosition
152 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000153 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000154
Bram Moolenaar418b5472022-12-20 13:38:22 +0000155 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000156 def ToString(): string
157 return $'({this.lnum}, {this.col})'
158 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000159 endclass
160
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000161 # use the automatically generated new() method
162 var pos = TextPosition.new(2, 12)
163 assert_equal(2, pos.lnum)
164 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000165
166 # call an object method
167 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000168
169 assert_equal(v:t_class, type(TextPosition))
170 assert_equal(v:t_object, type(pos))
171 assert_equal('class<TextPosition>', typename(TextPosition))
172 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000173 END
174 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200175
176 # When referencing object methods, space cannot be used after a "."
177 lines =<< trim END
178 vim9script
179 class A
180 def Foo(): number
181 return 10
182 enddef
183 endclass
184 var a = A.new()
185 var v = a. Foo()
186 END
187 v9.CheckScriptFailure(lines, 'E1202:')
188
189 # Using an object without specifying a method or a member variable
190 lines =<< trim END
191 vim9script
192 class A
193 def Foo(): number
194 return 10
195 enddef
196 endclass
197 var a = A.new()
198 var v = a.
199 END
200 v9.CheckScriptFailure(lines, 'E15:')
201
202 # Error when parsing the arguments of an object method.
203 lines =<< trim END
204 vim9script
205 class A
206 def Foo()
207 enddef
208 endclass
209 var a = A.new()
210 var v = a.Foo(,)
211 END
212 v9.CheckScriptFailure(lines, 'E15:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200213
214 lines =<< trim END
215 vim9script
216 class A
217 this.y = {
218 X: 1
219 }
220 endclass
221 var a = A.new()
222 END
223 v9.CheckScriptSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000224enddef
225
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000226def Test_class_defined_twice()
227 # class defined twice should fail
228 var lines =<< trim END
229 vim9script
230 class There
231 endclass
232 class There
233 endclass
234 END
235 v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "There"')
236
237 # one class, reload same script twice is OK
238 lines =<< trim END
239 vim9script
240 class There
241 endclass
242 END
243 writefile(lines, 'XclassTwice.vim', 'D')
244 source XclassTwice.vim
245 source XclassTwice.vim
246enddef
247
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000248def Test_returning_null_object()
249 # this was causing an internal error
250 var lines =<< trim END
251 vim9script
252
253 class BufferList
254 def Current(): any
255 return null_object
256 enddef
257 endclass
258
259 var buffers = BufferList.new()
260 echo buffers.Current()
261 END
262 v9.CheckScriptSuccess(lines)
263enddef
264
Bram Moolenaard13dd302023-03-11 20:56:35 +0000265def Test_using_null_class()
266 var lines =<< trim END
267 @_ = null_class.member
268 END
269 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
270enddef
271
Bram Moolenaar657aea72023-01-27 13:16:19 +0000272def Test_class_interface_wrong_end()
273 var lines =<< trim END
274 vim9script
275 abstract class SomeName
276 this.member = 'text'
277 endinterface
278 END
279 v9.CheckScriptFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
280
281 lines =<< trim END
282 vim9script
283 export interface AnotherName
284 this.member: string
285 endclass
286 END
287 v9.CheckScriptFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
288enddef
289
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000290def Test_object_not_set()
291 var lines =<< trim END
292 vim9script
293
294 class State
295 this.value = 'xyz'
296 endclass
297
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000298 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000299 var db = {'xyz': 789}
300 echo db[state.value]
301 END
302 v9.CheckScriptFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000303
304 lines =<< trim END
305 vim9script
306
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000307 class Class
308 this.id: string
309 def Method1()
310 echo 'Method1' .. this.id
311 enddef
312 endclass
313
314 var obj: Class
315 def Func()
316 obj.Method1()
317 enddef
318 Func()
319 END
320 v9.CheckScriptFailure(lines, 'E1360:')
321
322 lines =<< trim END
323 vim9script
324
Bram Moolenaar0917e862023-02-18 14:42:44 +0000325 class Background
326 this.background = 'dark'
327 endclass
328
329 class Colorscheme
330 this._bg: Background
331
332 def GetBackground(): string
333 return this._bg.background
334 enddef
335 endclass
336
337 var bg: Background # UNINITIALIZED
338 echo Colorscheme.new(bg).GetBackground()
339 END
Ernie Rael5c018be2023-08-27 18:40:26 +0200340 v9.CheckScriptFailure(lines, 'E1360:')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000341
342 # TODO: this should not give an error but be handled at runtime
343 lines =<< trim END
344 vim9script
345
346 class Class
347 this.id: string
348 def Method1()
349 echo 'Method1' .. this.id
350 enddef
351 endclass
352
353 var obj = null_object
354 def Func()
355 obj.Method1()
356 enddef
357 Func()
358 END
359 v9.CheckScriptFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000360enddef
361
Ernie Rael5c018be2023-08-27 18:40:26 +0200362def Test_null_object_assign_compare()
363 var lines =<< trim END
364 vim9script
365
366 var nullo = null_object
367 def F(): any
368 return nullo
369 enddef
370 assert_equal('object<Unknown>', typename(F()))
371
372 var o0 = F()
373 assert_true(o0 == null_object)
374 assert_true(o0 == null)
375
376 var o1: any = nullo
377 assert_true(o1 == null_object)
378 assert_true(o1 == null)
379
380 def G()
381 var x = null_object
382 enddef
383
384 class C
385 endclass
386 var o2: C
387 assert_true(o2 == null_object)
388 assert_true(o2 == null)
389
390 o2 = null_object
391 assert_true(o2 == null)
392
393 o2 = C.new()
394 assert_true(o2 != null)
395
396 o2 = null_object
397 assert_true(o2 == null)
398 END
399 v9.CheckScriptSuccess(lines)
400enddef
401
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000402def Test_class_member_initializer()
403 var lines =<< trim END
404 vim9script
405
406 class TextPosition
407 this.lnum: number = 1
408 this.col: number = 1
409
Bram Moolenaar418b5472022-12-20 13:38:22 +0000410 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000411 def new(lnum: number)
412 this.lnum = lnum
413 enddef
414 endclass
415
416 var pos = TextPosition.new(3)
417 assert_equal(3, pos.lnum)
418 assert_equal(1, pos.col)
419
420 var instr = execute('disassemble TextPosition.new')
421 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000422 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000423 '\d PUSHNR 1\_s*' ..
424 '\d STORE_THIS 0\_s*' ..
425 '\d PUSHNR 1\_s*' ..
426 '\d STORE_THIS 1\_s*' ..
427 'this.lnum = lnum\_s*' ..
428 '\d LOAD arg\[-1]\_s*' ..
429 '\d PUSHNR 0\_s*' ..
430 '\d LOAD $0\_s*' ..
431 '\d\+ STOREINDEX object\_s*' ..
432 '\d\+ RETURN object.*',
433 instr)
434 END
435 v9.CheckScriptSuccess(lines)
436enddef
437
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000438def Test_member_any_used_as_object()
439 var lines =<< trim END
440 vim9script
441
442 class Inner
443 this.value: number = 0
444 endclass
445
446 class Outer
447 this.inner: any
448 endclass
449
450 def F(outer: Outer)
451 outer.inner.value = 1
452 enddef
453
454 var inner_obj = Inner.new(0)
455 var outer_obj = Outer.new(inner_obj)
456 F(outer_obj)
457 assert_equal(1, inner_obj.value)
458 END
459 v9.CheckScriptSuccess(lines)
460
461 lines =<< trim END
462 vim9script
463
464 class Inner
465 this.value: number = 0
466 endclass
467
468 class Outer
469 this.inner: Inner
470 endclass
471
472 def F(outer: Outer)
473 outer.inner.value = 1
474 enddef
475
476 def Test_assign_to_nested_typed_member()
477 var inner = Inner.new(0)
478 var outer = Outer.new(inner)
479 F(outer)
480 assert_equal(1, inner.value)
481 enddef
482
483 Test_assign_to_nested_typed_member()
484 END
485 v9.CheckScriptSuccess(lines)
486enddef
487
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000488def Test_assignment_with_operator()
489 var lines =<< trim END
490 vim9script
491
492 class Foo
493 this.x: number
494
495 def Add(n: number)
496 this.x += n
497 enddef
498 endclass
499
500 var f = Foo.new(3)
501 f.Add(17)
502 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100503
504 def AddToFoo(obj: Foo)
505 obj.x += 3
506 enddef
507
508 AddToFoo(f)
509 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000510 END
511 v9.CheckScriptSuccess(lines)
512enddef
513
Bram Moolenaarf4508042023-01-15 16:54:57 +0000514def Test_list_of_objects()
515 var lines =<< trim END
516 vim9script
517
518 class Foo
519 def Add()
520 enddef
521 endclass
522
523 def ProcessList(fooList: list<Foo>)
524 for foo in fooList
525 foo.Add()
526 endfor
527 enddef
528
529 var l: list<Foo> = [Foo.new()]
530 ProcessList(l)
531 END
532 v9.CheckScriptSuccess(lines)
533enddef
534
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000535def Test_expr_after_using_object()
536 var lines =<< trim END
537 vim9script
538
539 class Something
540 this.label: string = ''
541 endclass
542
543 def Foo(): Something
544 var v = Something.new()
545 echo 'in Foo(): ' .. typename(v)
546 return v
547 enddef
548
549 Foo()
550 END
551 v9.CheckScriptSuccess(lines)
552enddef
553
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000554def Test_class_default_new()
555 var lines =<< trim END
556 vim9script
557
558 class TextPosition
559 this.lnum: number = 1
560 this.col: number = 1
561 endclass
562
563 var pos = TextPosition.new()
564 assert_equal(1, pos.lnum)
565 assert_equal(1, pos.col)
566
567 pos = TextPosition.new(v:none, v:none)
568 assert_equal(1, pos.lnum)
569 assert_equal(1, pos.col)
570
571 pos = TextPosition.new(3, 22)
572 assert_equal(3, pos.lnum)
573 assert_equal(22, pos.col)
574
575 pos = TextPosition.new(v:none, 33)
576 assert_equal(1, pos.lnum)
577 assert_equal(33, pos.col)
578 END
579 v9.CheckScriptSuccess(lines)
580
581 lines =<< trim END
582 vim9script
583 class Person
584 this.name: string
585 this.age: number = 42
586 this.education: string = "unknown"
587
588 def new(this.name, this.age = v:none, this.education = v:none)
589 enddef
590 endclass
591
592 var piet = Person.new("Piet")
593 assert_equal("Piet", piet.name)
594 assert_equal(42, piet.age)
595 assert_equal("unknown", piet.education)
596
597 var chris = Person.new("Chris", 4, "none")
598 assert_equal("Chris", chris.name)
599 assert_equal(4, chris.age)
600 assert_equal("none", chris.education)
601 END
602 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000603
604 lines =<< trim END
605 vim9script
606 class Person
607 this.name: string
608 this.age: number = 42
609 this.education: string = "unknown"
610
611 def new(this.name, this.age = v:none, this.education = v:none)
612 enddef
613 endclass
614
615 var missing = Person.new()
616 END
617 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000618enddef
619
h-east2261c892023-08-16 21:49:54 +0900620
621def Test_class_new_with_object_member()
622 var lines =<< trim END
623 vim9script
624
625 class C
626 this.str: string
627 this.num: number
628 def new(this.str, this.num)
629 enddef
630 def newVals(this.str, this.num)
631 enddef
632 endclass
633
634 def Check()
635 try
636 var c = C.new('cats', 2)
637 assert_equal('cats', c.str)
638 assert_equal(2, c.num)
639
640 c = C.newVals('dogs', 4)
641 assert_equal('dogs', c.str)
642 assert_equal(4, c.num)
643 catch
644 assert_report($'Unexpected exception was caught: {v:exception}')
645 endtry
646 enddef
647
648 Check()
649 END
650 v9.CheckScriptSuccess(lines)
651
652 lines =<< trim END
653 vim9script
654
655 class C
656 this.str: string
657 this.num: number
658 def new(this.str, this.num)
659 enddef
660 endclass
661
662 def Check()
663 try
664 var c = C.new(1, 2)
665 catch
666 assert_report($'Unexpected exception was caught: {v:exception}')
667 endtry
668 enddef
669
670 Check()
671 END
672 v9.CheckScriptFailure(lines, 'E1013:')
673
674 lines =<< trim END
675 vim9script
676
677 class C
678 this.str: string
679 this.num: number
680 def newVals(this.str, this.num)
681 enddef
682 endclass
683
684 def Check()
685 try
686 var c = C.newVals('dogs', 'apes')
687 catch
688 assert_report($'Unexpected exception was caught: {v:exception}')
689 endtry
690 enddef
691
692 Check()
693 END
694 v9.CheckScriptFailure(lines, 'E1013:')
695enddef
696
Bram Moolenaar74e12742022-12-13 21:14:28 +0000697def Test_class_object_member_inits()
698 var lines =<< trim END
699 vim9script
700 class TextPosition
701 this.lnum: number
702 this.col = 1
703 this.addcol: number = 2
704 endclass
705
706 var pos = TextPosition.new()
707 assert_equal(0, pos.lnum)
708 assert_equal(1, pos.col)
709 assert_equal(2, pos.addcol)
710 END
711 v9.CheckScriptSuccess(lines)
712
713 lines =<< trim END
714 vim9script
715 class TextPosition
716 this.lnum
717 this.col = 1
718 endclass
719 END
720 v9.CheckScriptFailure(lines, 'E1022:')
721
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200722 # If the type is not specified for a member, then it should be set during
723 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000724 lines =<< trim END
725 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200726
727 var init_count = 0
728 def Init(): string
729 init_count += 1
730 return 'foo'
731 enddef
732
733 class A
734 this.str1 = Init()
735 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000736 this.col = 1
737 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200738
739 assert_equal(init_count, 0)
740 var a = A.new()
741 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000742 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200743 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200744
745 # Test for initializing an object member with an unknown variable/type
746 lines =<< trim END
747 vim9script
748 class A
749 this.value = init_val
750 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200751 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200752 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200753 v9.CheckScriptFailure(lines, 'E1001:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000754enddef
755
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000756def Test_class_object_member_access()
757 var lines =<< trim END
758 vim9script
759 class Triple
760 this._one = 1
761 this.two = 2
762 public this.three = 3
763
764 def GetOne(): number
765 return this._one
766 enddef
767 endclass
768
769 var trip = Triple.new()
770 assert_equal(1, trip.GetOne())
771 assert_equal(2, trip.two)
772 assert_equal(3, trip.three)
773 assert_fails('echo trip._one', 'E1333')
774
775 assert_fails('trip._one = 11', 'E1333')
776 assert_fails('trip.two = 22', 'E1335')
777 trip.three = 33
778 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000779
780 assert_fails('trip.four = 4', 'E1334')
781 END
782 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000783
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200784 # Test for a public member variable name beginning with an underscore
785 lines =<< trim END
786 vim9script
787 class A
788 public this._val = 10
789 endclass
790 END
791 v9.CheckScriptFailure(lines, 'E1332:')
792
Bram Moolenaar590162c2022-12-24 21:24:06 +0000793 lines =<< trim END
794 vim9script
795
796 class MyCar
797 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000798 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000799
800 def new(make_arg: string)
801 this.make = make_arg
802 enddef
803
804 def GetMake(): string
805 return $"make = {this.make}"
806 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000807 def GetAge(): number
808 return this.age
809 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000810 endclass
811
812 var c = MyCar.new("abc")
813 assert_equal('make = abc', c.GetMake())
814
815 c = MyCar.new("def")
816 assert_equal('make = def', c.GetMake())
817
818 var c2 = MyCar.new("123")
819 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000820
821 def CheckCar()
822 assert_equal("make = def", c.GetMake())
823 assert_equal(5, c.GetAge())
824 enddef
825 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000826 END
827 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000828
829 lines =<< trim END
830 vim9script
831
832 class MyCar
833 this.make: string
834
835 def new(make_arg: string)
836 this.make = make_arg
837 enddef
838 endclass
839
840 var c = MyCar.new("abc")
841 var c = MyCar.new("def")
842 END
843 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000844
845 lines =<< trim END
846 vim9script
847
848 class Foo
849 this.x: list<number> = []
850
851 def Add(n: number): any
852 this.x->add(n)
853 return this
854 enddef
855 endclass
856
857 echo Foo.new().Add(1).Add(2).x
858 echo Foo.new().Add(1).Add(2)
859 .x
860 echo Foo.new().Add(1)
861 .Add(2).x
862 echo Foo.new()
863 .Add(1).Add(2).x
864 echo Foo.new()
865 .Add(1)
866 .Add(2)
867 .x
868 END
869 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200870
871 # Test for "public" cannot be abbreviated
872 lines =<< trim END
873 vim9script
874 class Something
875 pub this.val = 1
876 endclass
877 END
878 v9.CheckScriptFailure(lines, 'E1065:')
879
880 # Test for "public" keyword must be followed by "this" or "static".
881 lines =<< trim END
882 vim9script
883 class Something
884 public val = 1
885 endclass
886 END
887 v9.CheckScriptFailure(lines, 'E1331:')
888
889 # Test for "static" cannot be abbreviated
890 lines =<< trim END
891 vim9script
892 class Something
893 stat this.val = 1
894 endclass
895 END
896 v9.CheckScriptFailure(lines, 'E1065:')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +0200897
898 # Test for "static" cannot be followed by "this".
899 lines =<< trim END
900 vim9script
901 class Something
902 static this.val = 1
903 endclass
904 END
905 v9.CheckScriptFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
Bram Moolenaard505d172022-12-18 21:42:55 +0000906enddef
907
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000908def Test_class_object_compare()
909 var class_lines =<< trim END
910 vim9script
911 class Item
912 this.nr = 0
913 this.name = 'xx'
914 endclass
915 END
916
917 # used at the script level and in a compiled function
918 var test_lines =<< trim END
919 var i1 = Item.new()
920 assert_equal(i1, i1)
921 assert_true(i1 is i1)
922 var i2 = Item.new()
923 assert_equal(i1, i2)
924 assert_false(i1 is i2)
925 var i3 = Item.new(0, 'xx')
926 assert_equal(i1, i3)
927
928 var io1 = Item.new(1, 'xx')
929 assert_notequal(i1, io1)
930 var io2 = Item.new(0, 'yy')
931 assert_notequal(i1, io2)
932 END
933
934 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000935 v9.CheckScriptSuccess(
936 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000937
938 for op in ['>', '>=', '<', '<=', '=~', '!~']
939 var op_lines = [
940 'var i1 = Item.new()',
941 'var i2 = Item.new()',
942 'echo i1 ' .. op .. ' i2',
943 ]
944 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000945 v9.CheckScriptFailure(class_lines
946 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000947 endfor
948enddef
949
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000950def Test_object_type()
951 var lines =<< trim END
952 vim9script
953
954 class One
955 this.one = 1
956 endclass
957 class Two
958 this.two = 2
959 endclass
960 class TwoMore extends Two
961 this.more = 9
962 endclass
963
964 var o: One = One.new()
965 var t: Two = Two.new()
966 var m: TwoMore = TwoMore.new()
967 var tm: Two = TwoMore.new()
968
969 t = m
970 END
971 v9.CheckScriptSuccess(lines)
972
973 lines =<< trim END
974 vim9script
975
976 class One
977 this.one = 1
978 endclass
979 class Two
980 this.two = 2
981 endclass
982
983 var o: One = Two.new()
984 END
985 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000986
987 lines =<< trim END
988 vim9script
989
990 interface One
991 def GetMember(): number
992 endinterface
993 class Two implements One
994 this.one = 1
995 def GetMember(): number
996 return this.one
997 enddef
998 endclass
999
1000 var o: One = Two.new(5)
1001 assert_equal(5, o.GetMember())
1002 END
1003 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001004
1005 lines =<< trim END
1006 vim9script
1007
1008 class Num
1009 this.n: number = 0
1010 endclass
1011
1012 def Ref(name: string): func(Num): Num
1013 return (arg: Num): Num => {
1014 return eval(name)(arg)
1015 }
1016 enddef
1017
1018 const Fn = Ref('Double')
1019 var Double = (m: Num): Num => Num.new(m.n * 2)
1020
1021 echo Fn(Num.new(4))
1022 END
1023 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001024enddef
1025
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001026def Test_class_member()
1027 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001028 var lines =<< trim END
1029 vim9script
1030 class TextPos
1031 this.lnum = 1
1032 this.col = 1
1033 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001034 static _secret = 7
1035 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001036
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001037 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001038 counter += nr
1039 enddef
1040 endclass
1041
1042 assert_equal(0, TextPos.counter)
1043 TextPos.AddToCounter(3)
1044 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001045 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001046
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001047 def GetCounter(): number
1048 return TextPos.counter
1049 enddef
1050 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001051
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001052 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001053 assert_fails('TextPos.counter = 5', 'E1335:')
1054 assert_fails('TextPos.counter += 5', 'E1335:')
1055
1056 assert_fails('echo TextPos._secret', 'E1333:')
1057 assert_fails('TextPos._secret = 8', 'E1333:')
1058
1059 assert_equal(42, TextPos.anybody)
1060 TextPos.anybody = 12
1061 assert_equal(12, TextPos.anybody)
1062 TextPos.anybody += 5
1063 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001064 END
1065 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001066
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001067 # example in the help
1068 lines =<< trim END
1069 vim9script
1070 class OtherThing
1071 this.size: number
1072 static totalSize: number
1073
1074 def new(this.size)
1075 totalSize += this.size
1076 enddef
1077 endclass
1078 assert_equal(0, OtherThing.totalSize)
1079 var to3 = OtherThing.new(3)
1080 assert_equal(3, OtherThing.totalSize)
1081 var to7 = OtherThing.new(7)
1082 assert_equal(10, OtherThing.totalSize)
1083 END
1084 v9.CheckScriptSuccess(lines)
1085
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001086 # using static class member twice
1087 lines =<< trim END
1088 vim9script
1089
1090 class HTML
1091 static author: string = 'John Doe'
1092
1093 static def MacroSubstitute(s: string): string
1094 return substitute(s, '{{author}}', author, 'gi')
1095 enddef
1096 endclass
1097
1098 assert_equal('some text', HTML.MacroSubstitute('some text'))
1099 assert_equal('some text', HTML.MacroSubstitute('some text'))
1100 END
1101 v9.CheckScriptSuccess(lines)
1102
Bram Moolenaar62a69232023-01-24 15:07:04 +00001103 # access private member in lambda
1104 lines =<< trim END
1105 vim9script
1106
1107 class Foo
1108 this._x: number = 0
1109
1110 def Add(n: number): number
1111 const F = (): number => this._x + n
1112 return F()
1113 enddef
1114 endclass
1115
1116 var foo = Foo.new()
1117 assert_equal(5, foo.Add(5))
1118 END
1119 v9.CheckScriptSuccess(lines)
1120
h-east2bd6a092023-05-19 19:01:17 +01001121 # access private member in lambda body
1122 lines =<< trim END
1123 vim9script
1124
1125 class Foo
1126 this._x: number = 6
1127
1128 def Add(n: number): number
1129 var Lam = () => {
1130 this._x = this._x + n
1131 }
1132 Lam()
1133 return this._x
1134 enddef
1135 endclass
1136
1137 var foo = Foo.new()
1138 assert_equal(13, foo.Add(7))
1139 END
1140 v9.CheckScriptSuccess(lines)
1141
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001142 # check shadowing
1143 lines =<< trim END
1144 vim9script
1145
1146 class Some
1147 static count = 0
1148 def Method(count: number)
1149 echo count
1150 enddef
1151 endclass
1152
1153 var s = Some.new()
1154 s.Method(7)
1155 END
1156 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
1157
1158 lines =<< trim END
1159 vim9script
1160
1161 class Some
1162 static count = 0
1163 def Method(arg: number)
1164 var count = 3
1165 echo arg count
1166 enddef
1167 endclass
1168
1169 var s = Some.new()
1170 s.Method(7)
1171 END
1172 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001173
1174 # Test for using an invalid type for a member variable
1175 lines =<< trim END
1176 vim9script
1177 class A
1178 this.val: xxx
1179 endclass
1180 END
1181 v9.CheckScriptFailure(lines, 'E1010:')
1182
1183 # Test for no space before or after the '=' when initializing a member
1184 # variable
1185 lines =<< trim END
1186 vim9script
1187 class A
1188 this.val: number= 10
1189 endclass
1190 END
1191 v9.CheckScriptFailure(lines, 'E1004:')
1192 lines =<< trim END
1193 vim9script
1194 class A
1195 this.val: number =10
1196 endclass
1197 END
1198 v9.CheckScriptFailure(lines, 'E1004:')
1199
1200 # Access a non-existing member
1201 lines =<< trim END
1202 vim9script
1203 class A
1204 endclass
1205 var a = A.new()
1206 var v = a.bar
1207 END
1208 v9.CheckScriptFailure(lines, 'E1326:')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001209enddef
1210
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001211func Test_class_garbagecollect()
1212 let lines =<< trim END
1213 vim9script
1214
1215 class Point
1216 this.p = [2, 3]
1217 static pl = ['a', 'b']
1218 static pd = {a: 'a', b: 'b'}
1219 endclass
1220
1221 echo Point.pl Point.pd
1222 call test_garbagecollect_now()
1223 echo Point.pl Point.pd
1224 END
1225 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001226
1227 let lines =<< trim END
1228 vim9script
1229
1230 interface View
1231 endinterface
1232
1233 class Widget
1234 this.view: View
1235 endclass
1236
1237 class MyView implements View
1238 this.widget: Widget
1239
1240 def new()
1241 # this will result in a circular reference to this object
1242 this.widget = Widget.new(this)
1243 enddef
1244 endclass
1245
1246 var view = MyView.new()
1247
1248 # overwrite "view", will be garbage-collected next
1249 view = MyView.new()
1250 test_garbagecollect_now()
1251 END
1252 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001253endfunc
1254
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001255def Test_class_function()
1256 var lines =<< trim END
1257 vim9script
1258 class Value
1259 this.value = 0
1260 static objects = 0
1261
1262 def new(v: number)
1263 this.value = v
1264 ++objects
1265 enddef
1266
1267 static def GetCount(): number
1268 return objects
1269 enddef
1270 endclass
1271
1272 assert_equal(0, Value.GetCount())
1273 var v1 = Value.new(2)
1274 assert_equal(1, Value.GetCount())
1275 var v2 = Value.new(7)
1276 assert_equal(2, Value.GetCount())
1277 END
1278 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001279
1280 # Test for cleaning up after a class definition failure when using class
1281 # functions.
1282 lines =<< trim END
1283 vim9script
1284 class A
1285 static def Foo()
1286 enddef
1287 aaa
1288 endclass
1289 END
1290 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001291enddef
1292
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001293def Test_class_defcompile()
1294 var lines =<< trim END
1295 vim9script
1296
1297 class C
1298 def Fo(i: number): string
1299 return i
1300 enddef
1301 endclass
1302
1303 defcompile C.Fo
1304 END
1305 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1306
1307 lines =<< trim END
1308 vim9script
1309
1310 class C
1311 static def Fc(): number
1312 return 'x'
1313 enddef
1314 endclass
1315
1316 defcompile C.Fc
1317 END
1318 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001319
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001320 lines =<< trim END
1321 vim9script
1322
1323 class C
1324 static def new()
1325 enddef
1326 endclass
1327
1328 defcompile C.new
1329 END
1330 v9.CheckScriptFailure(lines, 'E1370: Cannot define a "new" function as static')
1331
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001332 # Trying to compile a function using a non-existing class variable
1333 lines =<< trim END
1334 vim9script
1335 defcompile x.Foo()
1336 END
1337 v9.CheckScriptFailure(lines, 'E475:')
1338
1339 # Trying to compile a function using a variable which is not a class
1340 lines =<< trim END
1341 vim9script
1342 var x: number
1343 defcompile x.Foo()
1344 END
1345 v9.CheckScriptFailure(lines, 'E475:')
1346
1347 # Trying to compile a function without specifying the name
1348 lines =<< trim END
1349 vim9script
1350 class A
1351 endclass
1352 defcompile A.
1353 END
1354 v9.CheckScriptFailure(lines, 'E475:')
1355
1356 # Trying to compile a non-existing class object member function
1357 lines =<< trim END
1358 vim9script
1359 class A
1360 endclass
1361 var a = A.new()
1362 defcompile a.Foo()
1363 END
1364 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001365enddef
1366
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001367def Test_class_object_to_string()
1368 var lines =<< trim END
1369 vim9script
1370 class TextPosition
1371 this.lnum = 1
1372 this.col = 22
1373 endclass
1374
1375 assert_equal("class TextPosition", string(TextPosition))
1376
1377 var pos = TextPosition.new()
1378 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1379 END
1380 v9.CheckScriptSuccess(lines)
1381enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001382
Bram Moolenaar554d0312023-01-05 19:59:18 +00001383def Test_interface_basics()
1384 var lines =<< trim END
1385 vim9script
1386 interface Something
1387 this.value: string
1388 static count: number
1389 def GetCount(): number
1390 endinterface
1391 END
1392 v9.CheckScriptSuccess(lines)
1393
1394 lines =<< trim END
1395 interface SomethingWrong
1396 static count = 7
1397 endinterface
1398 END
1399 v9.CheckScriptFailure(lines, 'E1342:')
1400
1401 lines =<< trim END
1402 vim9script
1403
1404 interface Some
1405 static count: number
1406 def Method(count: number)
1407 endinterface
1408 END
h-east61378a12023-04-18 19:07:29 +01001409 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001410
1411 lines =<< trim END
1412 vim9script
1413
1414 interface Some
1415 this.value: number
1416 def Method(value: number)
1417 endinterface
1418 END
h-east61378a12023-04-18 19:07:29 +01001419 # The argument name and the object member name are the same, but this is not a
1420 # problem because object members are always accessed with the "this." prefix.
1421 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001422
1423 lines =<< trim END
1424 vim9script
1425 interface somethingWrong
1426 static count = 7
1427 endinterface
1428 END
1429 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1430
1431 lines =<< trim END
1432 vim9script
1433 interface SomethingWrong
1434 this.value: string
1435 static count = 7
1436 def GetCount(): number
1437 endinterface
1438 END
1439 v9.CheckScriptFailure(lines, 'E1344:')
1440
1441 lines =<< trim END
1442 vim9script
1443 interface SomethingWrong
1444 this.value: string
1445 static count: number
1446 def GetCount(): number
1447 return 5
1448 enddef
1449 endinterface
1450 END
1451 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001452
1453 lines =<< trim END
1454 vim9script
1455 export interface EnterExit
1456 def Enter(): void
1457 def Exit(): void
1458 endinterface
1459 END
1460 writefile(lines, 'XdefIntf.vim', 'D')
1461
1462 lines =<< trim END
1463 vim9script
1464 import './XdefIntf.vim' as defIntf
1465 export def With(ee: defIntf.EnterExit, F: func)
1466 ee.Enter()
1467 try
1468 F()
1469 finally
1470 ee.Exit()
1471 endtry
1472 enddef
1473 END
1474 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001475
1476 var imported =<< trim END
1477 vim9script
1478 export abstract class EnterExit
1479 def Enter(): void
1480 enddef
1481 def Exit(): void
1482 enddef
1483 endclass
1484 END
1485 writefile(imported, 'XdefIntf2.vim', 'D')
1486
1487 lines[1] = " import './XdefIntf2.vim' as defIntf"
1488 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001489enddef
1490
Bram Moolenaar94674f22023-01-06 18:42:20 +00001491def Test_class_implements_interface()
1492 var lines =<< trim END
1493 vim9script
1494
1495 interface Some
1496 static count: number
1497 def Method(nr: number)
1498 endinterface
1499
1500 class SomeImpl implements Some
1501 static count: number
1502 def Method(nr: number)
1503 echo nr
1504 enddef
1505 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001506
1507 interface Another
1508 this.member: string
1509 endinterface
1510
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001511 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001512 this.member = 'abc'
1513 static count: number
1514 def Method(nr: number)
1515 echo nr
1516 enddef
1517 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001518 END
1519 v9.CheckScriptSuccess(lines)
1520
1521 lines =<< trim END
1522 vim9script
1523
1524 interface Some
1525 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001526 endinterface
1527
1528 class SomeImpl implements Some implements Some
1529 static count: number
1530 endclass
1531 END
1532 v9.CheckScriptFailure(lines, 'E1350:')
1533
1534 lines =<< trim END
1535 vim9script
1536
1537 interface Some
1538 static counter: number
1539 endinterface
1540
1541 class SomeImpl implements Some, Some
1542 static count: number
1543 endclass
1544 END
1545 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1546
1547 lines =<< trim END
1548 vim9script
1549
1550 interface Some
1551 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001552 def Method(nr: number)
1553 endinterface
1554
1555 class SomeImpl implements Some
1556 static count: number
1557 def Method(nr: number)
1558 echo nr
1559 enddef
1560 endclass
1561 END
1562 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1563
1564 lines =<< trim END
1565 vim9script
1566
1567 interface Some
1568 static count: number
1569 def Methods(nr: number)
1570 endinterface
1571
1572 class SomeImpl implements Some
1573 static count: number
1574 def Method(nr: number)
1575 echo nr
1576 enddef
1577 endclass
1578 END
1579 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001580
1581 # Check different order of members in class and interface works.
1582 lines =<< trim END
1583 vim9script
1584
1585 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001586 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001587 this.errpos: number
1588 endinterface
1589
1590 # order of members is opposite of interface
1591 class Failure implements Result
1592 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001593 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001594 endclass
1595
1596 def Test()
1597 var result: Result = Failure.new()
1598
1599 assert_equal('label', result.label)
1600 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001601
1602 result.label = 'different'
1603 assert_equal('different', result.label)
1604 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001605 enddef
1606
1607 Test()
1608 END
1609 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001610
1611 # Interface name after "extends" doesn't end in a space or NUL character
1612 lines =<< trim END
1613 vim9script
1614 interface A
1615 endinterface
1616 class B extends A"
1617 endclass
1618 END
1619 v9.CheckScriptFailure(lines, 'E1315:')
1620
1621 # Trailing characters after a class name
1622 lines =<< trim END
1623 vim9script
1624 class A bbb
1625 endclass
1626 END
1627 v9.CheckScriptFailure(lines, 'E488:')
1628
1629 # using "implements" with a non-existing class
1630 lines =<< trim END
1631 vim9script
1632 class A implements B
1633 endclass
1634 END
1635 v9.CheckScriptFailure(lines, 'E1346:')
1636
1637 # using "implements" with a regular class
1638 lines =<< trim END
1639 vim9script
1640 class A
1641 endclass
1642 class B implements A
1643 endclass
1644 END
1645 v9.CheckScriptFailure(lines, 'E1347:')
1646
1647 # using "implements" with a variable
1648 lines =<< trim END
1649 vim9script
1650 var T: number = 10
1651 class A implements T
1652 endclass
1653 END
1654 v9.CheckScriptFailure(lines, 'E1347:')
1655
1656 # all the class methods in an "interface" should be implemented
1657 lines =<< trim END
1658 vim9script
1659 interface A
1660 static def Foo()
1661 endinterface
1662 class B implements A
1663 endclass
1664 END
1665 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001666
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02001667 # implements should be followed by a white space
1668 lines =<< trim END
1669 vim9script
1670 interface A
1671 endinterface
1672 class B implements A;
1673 endclass
1674 END
1675 v9.CheckScriptFailure(lines, 'E1315:')
1676
LemonBoyc5d27442023-08-19 13:02:35 +02001677 lines =<< trim END
1678 vim9script
1679
1680 interface One
1681 static matching: bool
1682 static as_any: any
1683 static not_matching: number
1684 endinterface
1685 class Two implements One
1686 static not_matching: string
1687 static as_any: string
1688 static matching: bool
1689 endclass
1690 END
1691 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1692
1693 lines =<< trim END
1694 vim9script
1695
1696 interface One
1697 def IsEven(nr: number): bool
1698 endinterface
1699 class Two implements One
1700 def IsEven(nr: number): string
1701 enddef
1702 endclass
1703 END
1704 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1705
1706 lines =<< trim END
1707 vim9script
1708
1709 interface One
1710 def IsEven(nr: number): bool
1711 endinterface
1712 class Two implements One
1713 def IsEven(nr: bool): bool
1714 enddef
1715 endclass
1716 END
1717 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1718
1719 lines =<< trim END
1720 vim9script
1721
1722 interface One
1723 def IsEven(nr: number): bool
1724 endinterface
1725 class Two implements One
1726 def IsEven(nr: number, ...extra: list<number>): bool
1727 enddef
1728 endclass
1729 END
1730 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
Bram Moolenaar94674f22023-01-06 18:42:20 +00001731enddef
1732
Bram Moolenaard0200c82023-01-28 15:19:40 +00001733def Test_call_interface_method()
1734 var lines =<< trim END
1735 vim9script
1736 interface Base
1737 def Enter(): void
1738 endinterface
1739
1740 class Child implements Base
1741 def Enter(): void
1742 g:result ..= 'child'
1743 enddef
1744 endclass
1745
1746 def F(obj: Base)
1747 obj.Enter()
1748 enddef
1749
1750 g:result = ''
1751 F(Child.new())
1752 assert_equal('child', g:result)
1753 unlet g:result
1754 END
1755 v9.CheckScriptSuccess(lines)
1756
1757 lines =<< trim END
1758 vim9script
1759 class Base
1760 def Enter(): void
1761 g:result ..= 'base'
1762 enddef
1763 endclass
1764
1765 class Child extends Base
1766 def Enter(): void
1767 g:result ..= 'child'
1768 enddef
1769 endclass
1770
1771 def F(obj: Base)
1772 obj.Enter()
1773 enddef
1774
1775 g:result = ''
1776 F(Child.new())
1777 assert_equal('child', g:result)
1778 unlet g:result
1779 END
1780 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001781
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001782 # method of interface returns a value
1783 lines =<< trim END
1784 vim9script
1785 interface Base
1786 def Enter(): string
1787 endinterface
1788
1789 class Child implements Base
1790 def Enter(): string
1791 g:result ..= 'child'
1792 return "/resource"
1793 enddef
1794 endclass
1795
1796 def F(obj: Base)
1797 var r = obj.Enter()
1798 g:result ..= r
1799 enddef
1800
1801 g:result = ''
1802 F(Child.new())
1803 assert_equal('child/resource', g:result)
1804 unlet g:result
1805 END
1806 v9.CheckScriptSuccess(lines)
1807
1808 lines =<< trim END
1809 vim9script
1810 class Base
1811 def Enter(): string
1812 return null_string
1813 enddef
1814 endclass
1815
1816 class Child extends Base
1817 def Enter(): string
1818 g:result ..= 'child'
1819 return "/resource"
1820 enddef
1821 endclass
1822
1823 def F(obj: Base)
1824 var r = obj.Enter()
1825 g:result ..= r
1826 enddef
1827
1828 g:result = ''
1829 F(Child.new())
1830 assert_equal('child/resource', g:result)
1831 unlet g:result
1832 END
1833 v9.CheckScriptSuccess(lines)
1834
1835
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001836 # No class that implements the interface.
1837 lines =<< trim END
1838 vim9script
1839
1840 interface IWithEE
1841 def Enter(): any
1842 def Exit(): void
1843 endinterface
1844
1845 def With1(ee: IWithEE, F: func)
1846 var r = ee.Enter()
1847 enddef
1848
1849 defcompile
1850 END
1851 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001852enddef
1853
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001854def Test_class_used_as_type()
1855 var lines =<< trim END
1856 vim9script
1857
1858 class Point
1859 this.x = 0
1860 this.y = 0
1861 endclass
1862
1863 var p: Point
1864 p = Point.new(2, 33)
1865 assert_equal(2, p.x)
1866 assert_equal(33, p.y)
1867 END
1868 v9.CheckScriptSuccess(lines)
1869
1870 lines =<< trim END
1871 vim9script
1872
1873 interface HasX
1874 this.x: number
1875 endinterface
1876
1877 class Point implements HasX
1878 this.x = 0
1879 this.y = 0
1880 endclass
1881
1882 var p: Point
1883 p = Point.new(2, 33)
1884 var hx = p
1885 assert_equal(2, hx.x)
1886 END
1887 v9.CheckScriptSuccess(lines)
1888
1889 lines =<< trim END
1890 vim9script
1891
1892 class Point
1893 this.x = 0
1894 this.y = 0
1895 endclass
1896
1897 var p: Point
1898 p = 'text'
1899 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001900 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001901enddef
1902
Bram Moolenaar83677162023-01-08 19:54:10 +00001903def Test_class_extends()
1904 var lines =<< trim END
1905 vim9script
1906 class Base
1907 this.one = 1
1908 def GetOne(): number
1909 return this.one
1910 enddef
1911 endclass
1912 class Child extends Base
1913 this.two = 2
1914 def GetTotal(): number
1915 return this.one + this.two
1916 enddef
1917 endclass
1918 var o = Child.new()
1919 assert_equal(1, o.one)
1920 assert_equal(2, o.two)
1921 assert_equal(1, o.GetOne())
1922 assert_equal(3, o.GetTotal())
1923 END
1924 v9.CheckScriptSuccess(lines)
1925
1926 lines =<< trim END
1927 vim9script
1928 class Base
1929 this.one = 1
1930 endclass
1931 class Child extends Base
1932 this.two = 2
1933 endclass
1934 var o = Child.new(3, 44)
1935 assert_equal(3, o.one)
1936 assert_equal(44, o.two)
1937 END
1938 v9.CheckScriptSuccess(lines)
1939
1940 lines =<< trim END
1941 vim9script
1942 class Base
1943 this.one = 1
1944 endclass
1945 class Child extends Base extends Base
1946 this.two = 2
1947 endclass
1948 END
1949 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1950
1951 lines =<< trim END
1952 vim9script
1953 class Child extends BaseClass
1954 this.two = 2
1955 endclass
1956 END
1957 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1958
1959 lines =<< trim END
1960 vim9script
1961 var SomeVar = 99
1962 class Child extends SomeVar
1963 this.two = 2
1964 endclass
1965 END
1966 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001967
1968 lines =<< trim END
1969 vim9script
1970 class Base
1971 this.name: string
1972 def ToString(): string
1973 return this.name
1974 enddef
1975 endclass
1976
1977 class Child extends Base
1978 this.age: number
1979 def ToString(): string
1980 return super.ToString() .. ': ' .. this.age
1981 enddef
1982 endclass
1983
1984 var o = Child.new('John', 42)
1985 assert_equal('John: 42', o.ToString())
1986 END
1987 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001988
1989 lines =<< trim END
1990 vim9script
1991 class Child
1992 this.age: number
1993 def ToString(): number
1994 return this.age
1995 enddef
1996 def ToString(): string
1997 return this.age
1998 enddef
1999 endclass
2000 END
2001 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
2002
2003 lines =<< trim END
2004 vim9script
2005 class Child
2006 this.age: number
2007 def ToString(): string
2008 return super .ToString() .. ': ' .. this.age
2009 enddef
2010 endclass
2011 var o = Child.new(42)
2012 echo o.ToString()
2013 END
2014 v9.CheckScriptFailure(lines, 'E1356:')
2015
2016 lines =<< trim END
2017 vim9script
2018 class Base
2019 this.name: string
2020 def ToString(): string
2021 return this.name
2022 enddef
2023 endclass
2024
2025 var age = 42
2026 def ToString(): string
2027 return super.ToString() .. ': ' .. age
2028 enddef
2029 echo ToString()
2030 END
2031 v9.CheckScriptFailure(lines, 'E1357:')
2032
2033 lines =<< trim END
2034 vim9script
2035 class Child
2036 this.age: number
2037 def ToString(): string
2038 return super.ToString() .. ': ' .. this.age
2039 enddef
2040 endclass
2041 var o = Child.new(42)
2042 echo o.ToString()
2043 END
2044 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002045
2046 lines =<< trim END
2047 vim9script
2048 class Base
2049 this.name: string
2050 static def ToString(): string
2051 return 'Base class'
2052 enddef
2053 endclass
2054
2055 class Child extends Base
2056 this.age: number
2057 def ToString(): string
2058 return Base.ToString() .. ': ' .. this.age
2059 enddef
2060 endclass
2061
2062 var o = Child.new('John', 42)
2063 assert_equal('Base class: 42', o.ToString())
2064 END
2065 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002066
2067 lines =<< trim END
2068 vim9script
2069 class Base
2070 this.value = 1
2071 def new(init: number)
2072 this.value = number + 1
2073 enddef
2074 endclass
2075 class Child extends Base
2076 def new()
2077 this.new(3)
2078 enddef
2079 endclass
2080 var c = Child.new()
2081 END
2082 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002083
2084 # base class with more than one object member
2085 lines =<< trim END
2086 vim9script
2087
2088 class Result
2089 this.success: bool
2090 this.value: any = null
2091 endclass
2092
2093 class Success extends Result
2094 def new(this.value = v:none)
2095 this.success = true
2096 enddef
2097 endclass
2098
2099 var v = Success.new('asdf')
2100 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2101 END
2102 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002103
2104 # class name after "extends" doesn't end in a space or NUL character
2105 lines =<< trim END
2106 vim9script
2107 class A
2108 endclass
2109 class B extends A"
2110 endclass
2111 END
2112 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002113enddef
2114
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002115def Test_using_base_class()
2116 var lines =<< trim END
2117 vim9script
2118
2119 class BaseEE
2120 def Enter(): any
2121 return null
2122 enddef
2123 def Exit(resource: any): void
2124 enddef
2125 endclass
2126
2127 class ChildEE extends BaseEE
2128 def Enter(): any
2129 return 42
2130 enddef
2131
2132 def Exit(resource: number): void
2133 g:result ..= '/exit'
2134 enddef
2135 endclass
2136
2137 def With(ee: BaseEE)
2138 var r = ee.Enter()
2139 try
2140 g:result ..= r
2141 finally
2142 g:result ..= '/finally'
2143 ee.Exit(r)
2144 endtry
2145 enddef
2146
2147 g:result = ''
2148 With(ChildEE.new())
2149 assert_equal('42/finally/exit', g:result)
2150 END
2151 v9.CheckScriptSuccess(lines)
2152 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002153
2154 # Using super, Child invokes Base method which has optional arg. #12471
2155 lines =<< trim END
2156 vim9script
2157
2158 class Base
2159 this.success: bool = false
2160 def Method(arg = 0)
2161 this.success = true
2162 enddef
2163 endclass
2164
2165 class Child extends Base
2166 def new()
2167 super.Method()
2168 enddef
2169 endclass
2170
2171 var obj = Child.new()
2172 assert_equal(true, obj.success)
2173 END
2174 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002175enddef
2176
2177
Bram Moolenaara86655a2023-01-12 17:06:27 +00002178def Test_class_import()
2179 var lines =<< trim END
2180 vim9script
2181 export class Animal
2182 this.kind: string
2183 this.name: string
2184 endclass
2185 END
2186 writefile(lines, 'Xanimal.vim', 'D')
2187
2188 lines =<< trim END
2189 vim9script
2190 import './Xanimal.vim' as animal
2191
2192 var a: animal.Animal
2193 a = animal.Animal.new('fish', 'Eric')
2194 assert_equal('fish', a.kind)
2195 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002196
2197 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2198 assert_equal('cat', b.kind)
2199 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002200 END
2201 v9.CheckScriptSuccess(lines)
2202enddef
2203
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002204def Test_abstract_class()
2205 var lines =<< trim END
2206 vim9script
2207 abstract class Base
2208 this.name: string
2209 endclass
2210 class Person extends Base
2211 this.age: number
2212 endclass
2213 var p: Base = Person.new('Peter', 42)
2214 assert_equal('Peter', p.name)
2215 assert_equal(42, p.age)
2216 END
2217 v9.CheckScriptSuccess(lines)
2218
2219 lines =<< trim END
2220 vim9script
2221 abstract class Base
2222 this.name: string
2223 endclass
2224 class Person extends Base
2225 this.age: number
2226 endclass
2227 var p = Base.new('Peter')
2228 END
2229 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2230
2231 lines =<< trim END
2232 abstract class Base
2233 this.name: string
2234 endclass
2235 END
2236 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002237
2238 # Abstract class cannot have a "new" function
2239 lines =<< trim END
2240 vim9script
2241 abstract class Base
2242 def new()
2243 enddef
2244 endclass
2245 END
2246 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002247enddef
2248
Bram Moolenaar486fc252023-01-18 14:51:07 +00002249def Test_closure_in_class()
2250 var lines =<< trim END
2251 vim9script
2252
2253 class Foo
2254 this.y: list<string> = ['B']
2255
2256 def new()
2257 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2258 enddef
2259 endclass
2260
2261 Foo.new()
2262 assert_equal(['A'], g:result)
2263 END
2264 v9.CheckScriptSuccess(lines)
2265enddef
2266
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002267def Test_call_constructor_from_legacy()
2268 var lines =<< trim END
2269 vim9script
2270
2271 var newCalled = 'false'
2272
2273 class A
2274 def new()
2275 newCalled = 'true'
2276 enddef
2277 endclass
2278
2279 export def F(options = {}): any
2280 return A
2281 enddef
2282
2283 g:p = F()
2284 legacy call p.new()
2285 assert_equal('true', newCalled)
2286 END
2287 v9.CheckScriptSuccess(lines)
2288enddef
2289
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002290def Test_defer_with_object()
2291 var lines =<< trim END
2292 vim9script
2293
2294 class CWithEE
2295 def Enter()
2296 g:result ..= "entered/"
2297 enddef
2298 def Exit()
2299 g:result ..= "exited"
2300 enddef
2301 endclass
2302
2303 def With(ee: CWithEE, F: func)
2304 ee.Enter()
2305 defer ee.Exit()
2306 F()
2307 enddef
2308
2309 g:result = ''
2310 var obj = CWithEE.new()
2311 obj->With(() => {
2312 g:result ..= "called/"
2313 })
2314 assert_equal('entered/called/exited', g:result)
2315 END
2316 v9.CheckScriptSuccess(lines)
2317 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002318
2319 lines =<< trim END
2320 vim9script
2321
2322 class BaseWithEE
2323 def Enter()
2324 g:result ..= "entered-base/"
2325 enddef
2326 def Exit()
2327 g:result ..= "exited-base"
2328 enddef
2329 endclass
2330
2331 class CWithEE extends BaseWithEE
2332 def Enter()
2333 g:result ..= "entered-child/"
2334 enddef
2335 def Exit()
2336 g:result ..= "exited-child"
2337 enddef
2338 endclass
2339
2340 def With(ee: BaseWithEE, F: func)
2341 ee.Enter()
2342 defer ee.Exit()
2343 F()
2344 enddef
2345
2346 g:result = ''
2347 var obj = CWithEE.new()
2348 obj->With(() => {
2349 g:result ..= "called/"
2350 })
2351 assert_equal('entered-child/called/exited-child', g:result)
2352 END
2353 v9.CheckScriptSuccess(lines)
2354 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002355enddef
2356
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002357" The following test used to crash Vim (Github issue #12676)
2358def Test_extends_method_crashes_vim()
2359 var lines =<< trim END
2360 vim9script
2361
2362 class Observer
2363 endclass
2364
2365 class Property
2366 this.value: any
2367
2368 def Set(v: any)
2369 if v != this.value
2370 this.value = v
2371 endif
2372 enddef
2373
2374 def Register(observer: Observer)
2375 enddef
2376 endclass
2377
2378 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002379 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002380 endclass
2381
2382 def Observe(obj: Property, who: Observer)
2383 obj.Register(who)
2384 enddef
2385
2386 var p = Bool.new(false)
2387 var myObserver = Observer.new()
2388
2389 Observe(p, myObserver)
2390
2391 p.Set(true)
2392 END
2393 v9.CheckScriptSuccess(lines)
2394enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002395
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002396" Test for calling a method in a class that is extended
2397def Test_call_method_in_extended_class()
2398 var lines =<< trim END
2399 vim9script
2400
2401 var prop_init_called = false
2402 var prop_register_called = false
2403
2404 class Property
2405 def Init()
2406 prop_init_called = true
2407 enddef
2408
2409 def Register()
2410 prop_register_called = true
2411 enddef
2412 endclass
2413
2414 class Bool extends Property
2415 endclass
2416
2417 def Observe(obj: Property)
2418 obj.Register()
2419 enddef
2420
2421 var p = Property.new()
2422 Observe(p)
2423
2424 p.Init()
2425 assert_true(prop_init_called)
2426 assert_true(prop_register_called)
2427 END
2428 v9.CheckScriptSuccess(lines)
2429enddef
2430
LemonBoyafe04662023-08-23 21:08:11 +02002431def Test_instanceof()
2432 var lines =<< trim END
2433 vim9script
2434
2435 class Base1
2436 endclass
2437
2438 class Base2 extends Base1
2439 endclass
2440
2441 interface Intf1
2442 endinterface
2443
2444 class Mix1 implements Intf1
2445 endclass
2446
2447 class Base3 extends Mix1
2448 endclass
2449
2450 var b1 = Base1.new()
2451 var b2 = Base2.new()
2452 var b3 = Base3.new()
2453
2454 assert_true(instanceof(b1, Base1))
2455 assert_true(instanceof(b2, Base1))
2456 assert_false(instanceof(b1, Base2))
2457 assert_true(instanceof(b3, Mix1))
2458 assert_false(instanceof(b3, []))
2459 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002460
2461 def Foo()
2462 var a1 = Base1.new()
2463 var a2 = Base2.new()
2464 var a3 = Base3.new()
2465
2466 assert_true(instanceof(a1, Base1))
2467 assert_true(instanceof(a2, Base1))
2468 assert_false(instanceof(a1, Base2))
2469 assert_true(instanceof(a3, Mix1))
2470 assert_false(instanceof(a3, []))
2471 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2472 enddef
2473 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002474 END
2475 v9.CheckScriptSuccess(lines)
2476enddef
2477
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002478" Test for calling a method in the parent class that is extended partially.
2479" This used to fail with the 'E118: Too many arguments for function: Text' error
2480" message (Github issue #12524).
2481def Test_call_method_in_parent_class()
2482 var lines =<< trim END
2483 vim9script
2484
2485 class Widget
2486 this._lnum: number = 1
2487
2488 def SetY(lnum: number)
2489 this._lnum = lnum
2490 enddef
2491
2492 def Text(): string
2493 return ''
2494 enddef
2495 endclass
2496
2497 class Foo extends Widget
2498 def Text(): string
2499 return '<Foo>'
2500 enddef
2501 endclass
2502
2503 def Stack(w1: Widget, w2: Widget): list<Widget>
2504 w1.SetY(1)
2505 w2.SetY(2)
2506 return [w1, w2]
2507 enddef
2508
2509 var foo1 = Foo.new()
2510 var foo2 = Foo.new()
2511 var l = Stack(foo1, foo2)
2512 END
2513 v9.CheckScriptSuccess(lines)
2514enddef
2515
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002516" Test for calling methods from three levels of classes
2517def Test_multi_level_method_call()
2518 var lines =<< trim END
2519 vim9script
2520
2521 var A_func1: number = 0
2522 var A_func2: number = 0
2523 var A_func3: number = 0
2524 var B_func2: number = 0
2525 var B_func3: number = 0
2526 var C_func3: number = 0
2527
2528 class A
2529 def Func1()
2530 A_func1 += 1
2531 enddef
2532
2533 def Func2()
2534 A_func2 += 1
2535 enddef
2536
2537 def Func3()
2538 A_func3 += 1
2539 enddef
2540 endclass
2541
2542 class B extends A
2543 def Func2()
2544 B_func2 += 1
2545 enddef
2546
2547 def Func3()
2548 B_func3 += 1
2549 enddef
2550 endclass
2551
2552 class C extends B
2553 def Func3()
2554 C_func3 += 1
2555 enddef
2556 endclass
2557
2558 def A_CallFuncs(a: A)
2559 a.Func1()
2560 a.Func2()
2561 a.Func3()
2562 enddef
2563
2564 def B_CallFuncs(b: B)
2565 b.Func1()
2566 b.Func2()
2567 b.Func3()
2568 enddef
2569
2570 def C_CallFuncs(c: C)
2571 c.Func1()
2572 c.Func2()
2573 c.Func3()
2574 enddef
2575
2576 var cobj = C.new()
2577 A_CallFuncs(cobj)
2578 B_CallFuncs(cobj)
2579 C_CallFuncs(cobj)
2580 assert_equal(3, A_func1)
2581 assert_equal(0, A_func2)
2582 assert_equal(0, A_func3)
2583 assert_equal(3, B_func2)
2584 assert_equal(0, B_func3)
2585 assert_equal(3, C_func3)
2586 END
2587 v9.CheckScriptSuccess(lines)
2588enddef
2589
2590" Test for using members from three levels of classes
2591def Test_multi_level_member_access()
2592 var lines =<< trim END
2593 vim9script
2594
2595 class A
2596 this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002597 endclass
2598
2599 class B extends A
2600 this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002601 endclass
2602
2603 class C extends B
2604 this.val3: number = 0
2605 endclass
2606
2607 def A_members(a: A)
2608 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002609 enddef
2610
2611 def B_members(b: B)
2612 b.val1 += 1
2613 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002614 enddef
2615
2616 def C_members(c: C)
2617 c.val1 += 1
2618 c.val2 += 1
2619 c.val3 += 1
2620 enddef
2621
2622 var cobj = C.new()
2623 A_members(cobj)
2624 B_members(cobj)
2625 C_members(cobj)
2626 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002627 assert_equal(2, cobj.val2)
2628 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002629 END
2630 v9.CheckScriptSuccess(lines)
2631enddef
2632
LemonBoy0ffc17a2023-08-20 18:09:11 +02002633" Test expansion of <stack> with class methods.
2634def Test_stack_expansion_with_methods()
2635 var lines =<< trim END
2636 vim9script
2637
2638 class C
2639 def M1()
2640 F0()
2641 enddef
2642 endclass
2643
2644 def F0()
2645 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2646 enddef
2647
2648 def F()
2649 C.new().M1()
2650 enddef
2651
2652 F()
2653 END
2654 v9.CheckScriptSuccess(lines)
2655enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002656
2657" Test the return type of the new() constructor
2658def Test_new_return_type()
2659 # new() uses the default return type and there is no return statement
2660 var lines =<< trim END
2661 vim9script
2662
2663 class C
2664 this._bufnr: number
2665
2666 def new(this._bufnr)
2667 if !bufexists(this._bufnr)
2668 this._bufnr = -1
2669 endif
2670 enddef
2671 endclass
2672
2673 var c = C.new(12345)
2674 assert_equal('object<C>', typename(c))
2675
2676 var v1: C
2677 v1 = C.new(12345)
2678 assert_equal('object<C>', typename(v1))
2679
2680 def F()
2681 var v2: C
2682 v2 = C.new(12345)
2683 assert_equal('object<C>', typename(v2))
2684 enddef
2685 F()
2686 END
2687 v9.CheckScriptSuccess(lines)
2688
2689 # new() uses the default return type and an empty 'return' statement
2690 lines =<< trim END
2691 vim9script
2692
2693 class C
2694 this._bufnr: number
2695
2696 def new(this._bufnr)
2697 if !bufexists(this._bufnr)
2698 this._bufnr = -1
2699 return
2700 endif
2701 enddef
2702 endclass
2703
2704 var c = C.new(12345)
2705 assert_equal('object<C>', typename(c))
2706
2707 var v1: C
2708 v1 = C.new(12345)
2709 assert_equal('object<C>', typename(v1))
2710
2711 def F()
2712 var v2: C
2713 v2 = C.new(12345)
2714 assert_equal('object<C>', typename(v2))
2715 enddef
2716 F()
2717 END
2718 v9.CheckScriptSuccess(lines)
2719
2720 # new() uses "any" return type and returns "this"
2721 lines =<< trim END
2722 vim9script
2723
2724 class C
2725 this._bufnr: number
2726
2727 def new(this._bufnr): any
2728 if !bufexists(this._bufnr)
2729 this._bufnr = -1
2730 return this
2731 endif
2732 enddef
2733 endclass
2734 END
2735 v9.CheckScriptFailure(lines, 'E1365:')
2736
2737 # new() uses 'Dict' return type and returns a Dict
2738 lines =<< trim END
2739 vim9script
2740
2741 class C
2742 this._state: dict<any>
2743
2744 def new(): dict<any>
2745 this._state = {}
2746 return this._state
2747 enddef
2748 endclass
2749
2750 var c = C.new()
2751 assert_equal('object<C>', typename(c))
2752 END
2753 v9.CheckScriptFailure(lines, 'E1365:')
2754enddef
2755
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02002756" Test for checking a member initialization type at run time.
2757def Test_runtime_type_check_for_member_init()
2758 var lines =<< trim END
2759 vim9script
2760
2761 var retnum: bool = false
2762
2763 def F(): any
2764 retnum = !retnum
2765 if retnum
2766 return 1
2767 else
2768 return "hello"
2769 endif
2770 enddef
2771
2772 class C
2773 this._foo: bool = F()
2774 endclass
2775
2776 var c1 = C.new()
2777 var c2 = C.new()
2778 END
2779 v9.CheckScriptFailure(lines, 'E1012:')
2780enddef
2781
2782" Test for locking a variable referring to an object and reassigning to another
2783" object.
2784def Test_object_lockvar()
2785 var lines =<< trim END
2786 vim9script
2787
2788 class C
2789 this.val: number
2790 def new(this.val)
2791 enddef
2792 endclass
2793
2794 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
2795 lockvar 2 some_dict
2796
2797 var current: C
2798 current = some_dict['c']
2799 assert_equal(3, current.val)
2800 current = some_dict['b']
2801 assert_equal(2, current.val)
2802
2803 def F()
2804 current = some_dict['c']
2805 enddef
2806
2807 def G()
2808 current = some_dict['b']
2809 enddef
2810
2811 F()
2812 assert_equal(3, current.val)
2813 G()
2814 assert_equal(2, current.val)
2815 END
2816 v9.CheckScriptSuccess(lines)
2817enddef
2818
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02002819" Test for a private object method
2820def Test_private_object_method()
2821 # Try calling a private method using an object (at the script level)
2822 var lines =<< trim END
2823 vim9script
2824
2825 class A
2826 def _Foo(): number
2827 return 1234
2828 enddef
2829 endclass
2830 var a = A.new()
2831 a._Foo()
2832 END
2833 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2834
2835 # Try calling a private method using an object (from a def function)
2836 lines =<< trim END
2837 vim9script
2838
2839 class A
2840 def _Foo(): number
2841 return 1234
2842 enddef
2843 endclass
2844 def T()
2845 var a = A.new()
2846 a._Foo()
2847 enddef
2848 T()
2849 END
2850 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
2851
2852 # Use a private method from another object method (in script context)
2853 lines =<< trim END
2854 vim9script
2855
2856 class A
2857 def _Foo(): number
2858 return 1234
2859 enddef
2860 def Bar(): number
2861 return this._Foo()
2862 enddef
2863 endclass
2864 var a = A.new()
2865 assert_equal(1234, a.Bar())
2866 END
2867 v9.CheckScriptSuccess(lines)
2868
2869 # Use a private method from another object method (def function context)
2870 lines =<< trim END
2871 vim9script
2872
2873 class A
2874 def _Foo(): number
2875 return 1234
2876 enddef
2877 def Bar(): number
2878 return this._Foo()
2879 enddef
2880 endclass
2881 def T()
2882 var a = A.new()
2883 assert_equal(1234, a.Bar())
2884 enddef
2885 T()
2886 END
2887 v9.CheckScriptSuccess(lines)
2888
2889 # Try calling a private method without the "this" prefix
2890 lines =<< trim END
2891 vim9script
2892
2893 class A
2894 def _Foo(): number
2895 return 1234
2896 enddef
2897 def Bar(): number
2898 return _Foo()
2899 enddef
2900 endclass
2901 var a = A.new()
2902 a.Bar()
2903 END
2904 v9.CheckScriptFailure(lines, 'E117: Unknown function: _Foo')
2905
2906 # Try calling a private method using the class name
2907 lines =<< trim END
2908 vim9script
2909
2910 class A
2911 def _Foo(): number
2912 return 1234
2913 enddef
2914 endclass
2915 A._Foo()
2916 END
2917 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
2918
2919 # Try to use "public" keyword when defining a private method
2920 lines =<< trim END
2921 vim9script
2922
2923 class A
2924 public def _Foo()
2925 enddef
2926 endclass
2927 var a = A.new()
2928 a._Foo()
2929 END
2930 v9.CheckScriptFailure(lines, 'E1331: Public must be followed by "this" or "static"')
2931
2932 # Define two private methods with the same name
2933 lines =<< trim END
2934 vim9script
2935
2936 class A
2937 def _Foo()
2938 enddef
2939 def _Foo()
2940 enddef
2941 endclass
2942 var a = A.new()
2943 END
2944 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
2945
2946 # Define a private method and a object method with the same name
2947 lines =<< trim END
2948 vim9script
2949
2950 class A
2951 def _Foo()
2952 enddef
2953 def Foo()
2954 enddef
2955 endclass
2956 var a = A.new()
2957 END
2958 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
2959
2960 # Define an object method and a private method with the same name
2961 lines =<< trim END
2962 vim9script
2963
2964 class A
2965 def Foo()
2966 enddef
2967 def _Foo()
2968 enddef
2969 endclass
2970 var a = A.new()
2971 END
2972 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: _Foo')
2973
2974 # Call a public method and a private method from a private method
2975 lines =<< trim END
2976 vim9script
2977
2978 class A
2979 def Foo(): number
2980 return 100
2981 enddef
2982 def _Bar(): number
2983 return 200
2984 enddef
2985 def _Baz()
2986 assert_equal(100, this.Foo())
2987 assert_equal(200, this._Bar())
2988 enddef
2989 def T()
2990 this._Baz()
2991 enddef
2992 endclass
2993 var a = A.new()
2994 a.T()
2995 END
2996 v9.CheckScriptSuccess(lines)
2997
2998 # Try calling a private method from another class
2999 lines =<< trim END
3000 vim9script
3001
3002 class A
3003 def _Foo(): number
3004 return 100
3005 enddef
3006 endclass
3007 class B
3008 def Foo(): number
3009 var a = A.new()
3010 a._Foo()
3011 enddef
3012 endclass
3013 var b = B.new()
3014 b.Foo()
3015 END
3016 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3017
3018 # Call a private object method from a child class object method
3019 lines =<< trim END
3020 vim9script
3021 class A
3022 def _Foo(): number
3023 return 1234
3024 enddef
3025 endclass
3026 class B extends A
3027 def Bar()
3028 enddef
3029 endclass
3030 class C extends B
3031 def Baz(): number
3032 return this._Foo()
3033 enddef
3034 endclass
3035 var c = C.new()
3036 assert_equal(1234, c.Baz())
3037 END
3038 v9.CheckScriptSuccess(lines)
3039
3040 # Call a private object method from a child class object
3041 lines =<< trim END
3042 vim9script
3043 class A
3044 def _Foo(): number
3045 return 1234
3046 enddef
3047 endclass
3048 class B extends A
3049 def Bar()
3050 enddef
3051 endclass
3052 class C extends B
3053 def Baz(): number
3054 enddef
3055 endclass
3056 var c = C.new()
3057 assert_equal(1234, c._Foo())
3058 END
3059 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3060
3061 # Using "_" prefix in a method name should fail outside of a class
3062 lines =<< trim END
3063 vim9script
3064 def _Foo(): number
3065 return 1234
3066 enddef
3067 var a = _Foo()
3068 END
3069 v9.CheckScriptFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
3070enddef
3071
3072" Test for an private class method
3073def Test_private_class_method()
3074 # Try calling a class private method (at the script level)
3075 var lines =<< trim END
3076 vim9script
3077
3078 class A
3079 static def _Foo(): number
3080 return 1234
3081 enddef
3082 endclass
3083 A._Foo()
3084 END
3085 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3086
3087 # Try calling a class private method (from a def function)
3088 lines =<< trim END
3089 vim9script
3090
3091 class A
3092 static def _Foo(): number
3093 return 1234
3094 enddef
3095 endclass
3096 def T()
3097 A._Foo()
3098 enddef
3099 T()
3100 END
3101 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3102
3103 # Try calling a class private method using an object (at the script level)
3104 lines =<< trim END
3105 vim9script
3106
3107 class A
3108 static def _Foo(): number
3109 return 1234
3110 enddef
3111 endclass
3112 var a = A.new()
3113 a._Foo()
3114 END
3115 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3116
3117 # Try calling a class private method using an object (from a def function)
3118 lines =<< trim END
3119 vim9script
3120
3121 class A
3122 static def _Foo(): number
3123 return 1234
3124 enddef
3125 endclass
3126 def T()
3127 var a = A.new()
3128 a._Foo()
3129 enddef
3130 T()
3131 END
3132 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "A": _Foo()')
3133
3134 # Use a class private method from an object method
3135 lines =<< trim END
3136 vim9script
3137
3138 class A
3139 static def _Foo(): number
3140 return 1234
3141 enddef
3142 def Bar()
3143 assert_equal(1234, A._Foo())
3144 enddef
3145 endclass
3146 var a = A.new()
3147 a.Bar()
3148 END
3149 v9.CheckScriptSuccess(lines)
3150
3151 # Use a class private method from another class private method
3152 lines =<< trim END
3153 vim9script
3154
3155 class A
3156 static def _Foo1(): number
3157 return 1234
3158 enddef
3159 static def _Foo2()
3160 assert_equal(1234, A._Foo1())
3161 enddef
3162 def Bar()
3163 A._Foo2()
3164 enddef
3165 endclass
3166 var a = A.new()
3167 a.Bar()
3168 END
3169 v9.CheckScriptSuccess(lines)
3170
3171 # Declare a class method and a class private method with the same name
3172 lines =<< trim END
3173 vim9script
3174
3175 class A
3176 static def _Foo()
3177 enddef
3178 static def Foo()
3179 enddef
3180 endclass
3181 var a = A.new()
3182 END
3183 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: Foo')
3184
3185 # Try calling a class private method from another class
3186 lines =<< trim END
3187 vim9script
3188
3189 class A
3190 static def _Foo(): number
3191 return 1234
3192 enddef
3193 endclass
3194 class B
3195 def Foo(): number
3196 return A._Foo()
3197 enddef
3198 endclass
3199 var b = B.new()
3200 assert_equal(1234, b.Foo())
3201 END
3202 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3203
3204 # Call a private class method from a child class object method
3205 lines =<< trim END
3206 vim9script
3207 class A
3208 static def _Foo(): number
3209 return 1234
3210 enddef
3211 endclass
3212 class B extends A
3213 def Bar()
3214 enddef
3215 endclass
3216 class C extends B
3217 def Baz(): number
3218 return A._Foo()
3219 enddef
3220 endclass
3221 var c = C.new()
3222 assert_equal(1234, c.Baz())
3223 END
3224 v9.CheckScriptSuccess(lines)
3225
3226 # Call a private class method from a child class private class method
3227 lines =<< trim END
3228 vim9script
3229 class A
3230 static def _Foo(): number
3231 return 1234
3232 enddef
3233 endclass
3234 class B extends A
3235 def Bar()
3236 enddef
3237 endclass
3238 class C extends B
3239 static def Baz(): number
3240 return A._Foo()
3241 enddef
3242 endclass
3243 assert_equal(1234, C.Baz())
3244 END
3245 v9.CheckScriptSuccess(lines)
3246
3247 # Call a private class method from a child class object
3248 lines =<< trim END
3249 vim9script
3250 class A
3251 static def _Foo(): number
3252 return 1234
3253 enddef
3254 endclass
3255 class B extends A
3256 def Bar()
3257 enddef
3258 endclass
3259 class C extends B
3260 def Baz(): number
3261 enddef
3262 endclass
3263 var c = C.new()
3264 assert_equal(1234, C._Foo())
3265 END
3266 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3267enddef
3268
3269" Test for an interface private object_method
3270def Test_interface_private_object_method()
3271 # Implement an interface private method and use it from a public method
3272 var lines =<< trim END
3273 vim9script
3274 interface Intf
3275 def _Foo(): number
3276 endinterface
3277 class A implements Intf
3278 def _Foo(): number
3279 return 1234
3280 enddef
3281 def Bar(): number
3282 return this._Foo()
3283 enddef
3284 endclass
3285 var a = A.new()
3286 assert_equal(1234, a.Bar())
3287 END
3288 v9.CheckScriptSuccess(lines)
3289
3290 # Call an interface private class method (script context)
3291 lines =<< trim END
3292 vim9script
3293 interface Intf
3294 def _Foo(): number
3295 endinterface
3296 class A implements Intf
3297 def _Foo(): number
3298 return 1234
3299 enddef
3300 endclass
3301 var a = A.new()
3302 assert_equal(1234, a._Foo())
3303 END
3304 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3305
3306 # Call an interface private class method (def context)
3307 lines =<< trim END
3308 vim9script
3309 interface Intf
3310 def _Foo(): number
3311 endinterface
3312 class A implements Intf
3313 def _Foo(): number
3314 return 1234
3315 enddef
3316 endclass
3317 def T()
3318 var a = A.new()
3319 assert_equal(1234, a._Foo())
3320 enddef
3321 T()
3322 END
3323 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo()')
3324
3325 # Implement an interface private object method as a private class method
3326 lines =<< trim END
3327 vim9script
3328 interface Intf
3329 def _Foo(): number
3330 endinterface
3331 class A implements Intf
3332 static def _Foo(): number
3333 return 1234
3334 enddef
3335 endclass
3336 END
3337 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3338enddef
3339
3340" Test for an interface private class method
3341def Test_interface_private_class_method()
3342 # Implement an interface private class method and use it from a public method
3343 var lines =<< trim END
3344 vim9script
3345 interface Intf
3346 static def _Foo(): number
3347 endinterface
3348 class A implements Intf
3349 static def _Foo(): number
3350 return 1234
3351 enddef
3352 def Bar(): number
3353 return A._Foo()
3354 enddef
3355 endclass
3356 var a = A.new()
3357 assert_equal(1234, a.Bar())
3358 END
3359 v9.CheckScriptSuccess(lines)
3360
3361 # Call an interface private class method (script context)
3362 lines =<< trim END
3363 vim9script
3364 interface Intf
3365 static def _Foo(): number
3366 endinterface
3367 class A implements Intf
3368 static def _Foo(): number
3369 return 1234
3370 enddef
3371 endclass
3372 assert_equal(1234, A._Foo())
3373 END
3374 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3375
3376 # Call an interface private class method (def context)
3377 lines =<< trim END
3378 vim9script
3379 interface Intf
3380 static def _Foo(): number
3381 endinterface
3382 class A implements Intf
3383 static def _Foo(): number
3384 return 1234
3385 enddef
3386 endclass
3387 def T()
3388 assert_equal(1234, A._Foo())
3389 enddef
3390 T()
3391 END
3392 v9.CheckScriptFailure(lines, 'E1366: Cannot access private method: _Foo())')
3393
3394 # Implement an interface private class method as a private object method
3395 lines =<< trim END
3396 vim9script
3397 interface Intf
3398 static def _Foo(): number
3399 endinterface
3400 class A implements Intf
3401 def _Foo(): number
3402 return 1234
3403 enddef
3404 endclass
3405 END
3406 v9.CheckScriptFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
3407enddef
3408
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003409" Test for using the return value of a class/object method as a function
3410" argument.
3411def Test_objmethod_funcarg()
3412 var lines =<< trim END
3413 vim9script
3414
3415 class C
3416 def Foo(): string
3417 return 'foo'
3418 enddef
3419 endclass
3420
3421 def Bar(a: number, s: string): string
3422 return s
3423 enddef
3424
3425 def Baz(c: C)
3426 assert_equal('foo', Bar(10, c.Foo()))
3427 enddef
3428
3429 var t = C.new()
3430 Baz(t)
3431 END
3432 v9.CheckScriptSuccess(lines)
3433
3434 lines =<< trim END
3435 vim9script
3436
3437 class C
3438 static def Foo(): string
3439 return 'foo'
3440 enddef
3441 endclass
3442
3443 def Bar(a: number, s: string): string
3444 return s
3445 enddef
3446
3447 def Baz()
3448 assert_equal('foo', Bar(10, C.Foo()))
3449 enddef
3450
3451 Baz()
3452 END
3453 v9.CheckScriptSuccess(lines)
3454enddef
3455
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003456" Test for declaring duplicate object and class members
3457def Test_dup_member_variable()
3458 # Duplicate member variable
3459 var lines =<< trim END
3460 vim9script
3461 class C
3462 this.val = 10
3463 this.val = 20
3464 endclass
3465 END
3466 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3467
3468 # Duplicate private member variable
3469 lines =<< trim END
3470 vim9script
3471 class C
3472 this._val = 10
3473 this._val = 20
3474 endclass
3475 END
3476 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3477
3478 # Duplicate public member variable
3479 lines =<< trim END
3480 vim9script
3481 class C
3482 public this.val = 10
3483 public this.val = 20
3484 endclass
3485 END
3486 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3487
3488 # Duplicate private member variable
3489 lines =<< trim END
3490 vim9script
3491 class C
3492 this.val = 10
3493 this._val = 20
3494 endclass
3495 END
3496 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3497
3498 # Duplicate public and private member variable
3499 lines =<< trim END
3500 vim9script
3501 class C
3502 this._val = 20
3503 public this.val = 10
3504 endclass
3505 END
3506 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3507
3508 # Duplicate class member variable
3509 lines =<< trim END
3510 vim9script
3511 class C
3512 static s: string = "abc"
3513 static _s: string = "def"
3514 endclass
3515 END
3516 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3517
3518 # Duplicate public and private class member variable
3519 lines =<< trim END
3520 vim9script
3521 class C
3522 public static s: string = "abc"
3523 static _s: string = "def"
3524 endclass
3525 END
3526 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _s')
3527
3528 # Duplicate class and object member variable
3529 lines =<< trim END
3530 vim9script
3531 class C
3532 static val = 10
3533 this.val = 20
3534 def new()
3535 enddef
3536 endclass
3537 var c = C.new()
3538 assert_equal(10, C.val)
3539 assert_equal(20, c.val)
3540 END
3541 v9.CheckScriptSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003542
3543 # Duplicate object member variable in a derived class
3544 lines =<< trim END
3545 vim9script
3546 class A
3547 this.val = 10
3548 endclass
3549 class B extends A
3550 endclass
3551 class C extends B
3552 this.val = 20
3553 endclass
3554 END
3555 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3556
3557 # Duplicate object private member variable in a derived class
3558 lines =<< trim END
3559 vim9script
3560 class A
3561 this._val = 10
3562 endclass
3563 class B extends A
3564 endclass
3565 class C extends B
3566 this._val = 20
3567 endclass
3568 END
3569 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3570
3571 # Duplicate object private member variable in a derived class
3572 lines =<< trim END
3573 vim9script
3574 class A
3575 this.val = 10
3576 endclass
3577 class B extends A
3578 endclass
3579 class C extends B
3580 this._val = 20
3581 endclass
3582 END
3583 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3584
3585 # Duplicate object member variable in a derived class
3586 lines =<< trim END
3587 vim9script
3588 class A
3589 this._val = 10
3590 endclass
3591 class B extends A
3592 endclass
3593 class C extends B
3594 this.val = 20
3595 endclass
3596 END
3597 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3598
3599 # Duplicate class member variable in a derived class
3600 lines =<< trim END
3601 vim9script
3602 class A
3603 static val = 10
3604 endclass
3605 class B extends A
3606 endclass
3607 class C extends B
3608 static val = 20
3609 endclass
3610 END
3611 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
3612
3613 # Duplicate private class member variable in a derived class
3614 lines =<< trim END
3615 vim9script
3616 class A
3617 static _val = 10
3618 endclass
3619 class B extends A
3620 endclass
3621 class C extends B
3622 static _val = 20
3623 endclass
3624 END
3625 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3626
3627 # Duplicate private class member variable in a derived class
3628 lines =<< trim END
3629 vim9script
3630 class A
3631 static val = 10
3632 endclass
3633 class B extends A
3634 endclass
3635 class C extends B
3636 static _val = 20
3637 endclass
3638 END
3639 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: _val')
3640
3641 # Duplicate class member variable in a derived class
3642 lines =<< trim END
3643 vim9script
3644 class A
3645 static _val = 10
3646 endclass
3647 class B extends A
3648 endclass
3649 class C extends B
3650 static val = 20
3651 endclass
3652 END
3653 v9.CheckScriptFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003654enddef
3655
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02003656" Test for accessing a private member outside a class in a def function
3657def Test_private_member_access_outside_class()
3658 # private object member variable
3659 var lines =<< trim END
3660 vim9script
3661 class A
3662 this._val = 10
3663 def GetVal(): number
3664 return this._val
3665 enddef
3666 endclass
3667 def T()
3668 var a = A.new()
3669 a._val = 20
3670 enddef
3671 T()
3672 END
3673 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
3674
3675 # private class member variable
3676 lines =<< trim END
3677 vim9script
3678 class A
3679 static _val: number = 10
3680 endclass
3681 def T()
3682 A._val = 20
3683 enddef
3684 T()
3685 END
3686 v9.CheckScriptFailure(lines, 'E1333: Cannot access private member: _val')
3687enddef
3688
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003689" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker