blob: 7e33c6d448282423136d256bdcfd474c83c48869 [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
340 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Background> but got object<Unknown>')
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
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000362def Test_class_member_initializer()
363 var lines =<< trim END
364 vim9script
365
366 class TextPosition
367 this.lnum: number = 1
368 this.col: number = 1
369
Bram Moolenaar418b5472022-12-20 13:38:22 +0000370 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000371 def new(lnum: number)
372 this.lnum = lnum
373 enddef
374 endclass
375
376 var pos = TextPosition.new(3)
377 assert_equal(3, pos.lnum)
378 assert_equal(1, pos.col)
379
380 var instr = execute('disassemble TextPosition.new')
381 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000382 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000383 '\d PUSHNR 1\_s*' ..
384 '\d STORE_THIS 0\_s*' ..
385 '\d PUSHNR 1\_s*' ..
386 '\d STORE_THIS 1\_s*' ..
387 'this.lnum = lnum\_s*' ..
388 '\d LOAD arg\[-1]\_s*' ..
389 '\d PUSHNR 0\_s*' ..
390 '\d LOAD $0\_s*' ..
391 '\d\+ STOREINDEX object\_s*' ..
392 '\d\+ RETURN object.*',
393 instr)
394 END
395 v9.CheckScriptSuccess(lines)
396enddef
397
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000398def Test_member_any_used_as_object()
399 var lines =<< trim END
400 vim9script
401
402 class Inner
403 this.value: number = 0
404 endclass
405
406 class Outer
407 this.inner: any
408 endclass
409
410 def F(outer: Outer)
411 outer.inner.value = 1
412 enddef
413
414 var inner_obj = Inner.new(0)
415 var outer_obj = Outer.new(inner_obj)
416 F(outer_obj)
417 assert_equal(1, inner_obj.value)
418 END
419 v9.CheckScriptSuccess(lines)
420
421 lines =<< trim END
422 vim9script
423
424 class Inner
425 this.value: number = 0
426 endclass
427
428 class Outer
429 this.inner: Inner
430 endclass
431
432 def F(outer: Outer)
433 outer.inner.value = 1
434 enddef
435
436 def Test_assign_to_nested_typed_member()
437 var inner = Inner.new(0)
438 var outer = Outer.new(inner)
439 F(outer)
440 assert_equal(1, inner.value)
441 enddef
442
443 Test_assign_to_nested_typed_member()
444 END
445 v9.CheckScriptSuccess(lines)
446enddef
447
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000448def Test_assignment_with_operator()
449 var lines =<< trim END
450 vim9script
451
452 class Foo
453 this.x: number
454
455 def Add(n: number)
456 this.x += n
457 enddef
458 endclass
459
460 var f = Foo.new(3)
461 f.Add(17)
462 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100463
464 def AddToFoo(obj: Foo)
465 obj.x += 3
466 enddef
467
468 AddToFoo(f)
469 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000470 END
471 v9.CheckScriptSuccess(lines)
472enddef
473
Bram Moolenaarf4508042023-01-15 16:54:57 +0000474def Test_list_of_objects()
475 var lines =<< trim END
476 vim9script
477
478 class Foo
479 def Add()
480 enddef
481 endclass
482
483 def ProcessList(fooList: list<Foo>)
484 for foo in fooList
485 foo.Add()
486 endfor
487 enddef
488
489 var l: list<Foo> = [Foo.new()]
490 ProcessList(l)
491 END
492 v9.CheckScriptSuccess(lines)
493enddef
494
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000495def Test_expr_after_using_object()
496 var lines =<< trim END
497 vim9script
498
499 class Something
500 this.label: string = ''
501 endclass
502
503 def Foo(): Something
504 var v = Something.new()
505 echo 'in Foo(): ' .. typename(v)
506 return v
507 enddef
508
509 Foo()
510 END
511 v9.CheckScriptSuccess(lines)
512enddef
513
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000514def Test_class_default_new()
515 var lines =<< trim END
516 vim9script
517
518 class TextPosition
519 this.lnum: number = 1
520 this.col: number = 1
521 endclass
522
523 var pos = TextPosition.new()
524 assert_equal(1, pos.lnum)
525 assert_equal(1, pos.col)
526
527 pos = TextPosition.new(v:none, v:none)
528 assert_equal(1, pos.lnum)
529 assert_equal(1, pos.col)
530
531 pos = TextPosition.new(3, 22)
532 assert_equal(3, pos.lnum)
533 assert_equal(22, pos.col)
534
535 pos = TextPosition.new(v:none, 33)
536 assert_equal(1, pos.lnum)
537 assert_equal(33, pos.col)
538 END
539 v9.CheckScriptSuccess(lines)
540
541 lines =<< trim END
542 vim9script
543 class Person
544 this.name: string
545 this.age: number = 42
546 this.education: string = "unknown"
547
548 def new(this.name, this.age = v:none, this.education = v:none)
549 enddef
550 endclass
551
552 var piet = Person.new("Piet")
553 assert_equal("Piet", piet.name)
554 assert_equal(42, piet.age)
555 assert_equal("unknown", piet.education)
556
557 var chris = Person.new("Chris", 4, "none")
558 assert_equal("Chris", chris.name)
559 assert_equal(4, chris.age)
560 assert_equal("none", chris.education)
561 END
562 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000563
564 lines =<< trim END
565 vim9script
566 class Person
567 this.name: string
568 this.age: number = 42
569 this.education: string = "unknown"
570
571 def new(this.name, this.age = v:none, this.education = v:none)
572 enddef
573 endclass
574
575 var missing = Person.new()
576 END
577 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000578enddef
579
h-east2261c892023-08-16 21:49:54 +0900580
581def Test_class_new_with_object_member()
582 var lines =<< trim END
583 vim9script
584
585 class C
586 this.str: string
587 this.num: number
588 def new(this.str, this.num)
589 enddef
590 def newVals(this.str, this.num)
591 enddef
592 endclass
593
594 def Check()
595 try
596 var c = C.new('cats', 2)
597 assert_equal('cats', c.str)
598 assert_equal(2, c.num)
599
600 c = C.newVals('dogs', 4)
601 assert_equal('dogs', c.str)
602 assert_equal(4, c.num)
603 catch
604 assert_report($'Unexpected exception was caught: {v:exception}')
605 endtry
606 enddef
607
608 Check()
609 END
610 v9.CheckScriptSuccess(lines)
611
612 lines =<< trim END
613 vim9script
614
615 class C
616 this.str: string
617 this.num: number
618 def new(this.str, this.num)
619 enddef
620 endclass
621
622 def Check()
623 try
624 var c = C.new(1, 2)
625 catch
626 assert_report($'Unexpected exception was caught: {v:exception}')
627 endtry
628 enddef
629
630 Check()
631 END
632 v9.CheckScriptFailure(lines, 'E1013:')
633
634 lines =<< trim END
635 vim9script
636
637 class C
638 this.str: string
639 this.num: number
640 def newVals(this.str, this.num)
641 enddef
642 endclass
643
644 def Check()
645 try
646 var c = C.newVals('dogs', 'apes')
647 catch
648 assert_report($'Unexpected exception was caught: {v:exception}')
649 endtry
650 enddef
651
652 Check()
653 END
654 v9.CheckScriptFailure(lines, 'E1013:')
655enddef
656
Bram Moolenaar74e12742022-12-13 21:14:28 +0000657def Test_class_object_member_inits()
658 var lines =<< trim END
659 vim9script
660 class TextPosition
661 this.lnum: number
662 this.col = 1
663 this.addcol: number = 2
664 endclass
665
666 var pos = TextPosition.new()
667 assert_equal(0, pos.lnum)
668 assert_equal(1, pos.col)
669 assert_equal(2, pos.addcol)
670 END
671 v9.CheckScriptSuccess(lines)
672
673 lines =<< trim END
674 vim9script
675 class TextPosition
676 this.lnum
677 this.col = 1
678 endclass
679 END
680 v9.CheckScriptFailure(lines, 'E1022:')
681
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200682 # If the type is not specified for a member, then it should be set during
683 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000684 lines =<< trim END
685 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200686
687 var init_count = 0
688 def Init(): string
689 init_count += 1
690 return 'foo'
691 enddef
692
693 class A
694 this.str1 = Init()
695 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000696 this.col = 1
697 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200698
699 assert_equal(init_count, 0)
700 var a = A.new()
701 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000702 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200703 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200704
705 # Test for initializing an object member with an unknown variable/type
706 lines =<< trim END
707 vim9script
708 class A
709 this.value = init_val
710 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200711 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200712 END
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200713 v9.CheckScriptFailure(lines, 'E1001:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000714enddef
715
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000716def Test_class_object_member_access()
717 var lines =<< trim END
718 vim9script
719 class Triple
720 this._one = 1
721 this.two = 2
722 public this.three = 3
723
724 def GetOne(): number
725 return this._one
726 enddef
727 endclass
728
729 var trip = Triple.new()
730 assert_equal(1, trip.GetOne())
731 assert_equal(2, trip.two)
732 assert_equal(3, trip.three)
733 assert_fails('echo trip._one', 'E1333')
734
735 assert_fails('trip._one = 11', 'E1333')
736 assert_fails('trip.two = 22', 'E1335')
737 trip.three = 33
738 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000739
740 assert_fails('trip.four = 4', 'E1334')
741 END
742 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000743
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200744 # Test for a public member variable name beginning with an underscore
745 lines =<< trim END
746 vim9script
747 class A
748 public this._val = 10
749 endclass
750 END
751 v9.CheckScriptFailure(lines, 'E1332:')
752
Bram Moolenaar590162c2022-12-24 21:24:06 +0000753 lines =<< trim END
754 vim9script
755
756 class MyCar
757 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000758 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000759
760 def new(make_arg: string)
761 this.make = make_arg
762 enddef
763
764 def GetMake(): string
765 return $"make = {this.make}"
766 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000767 def GetAge(): number
768 return this.age
769 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000770 endclass
771
772 var c = MyCar.new("abc")
773 assert_equal('make = abc', c.GetMake())
774
775 c = MyCar.new("def")
776 assert_equal('make = def', c.GetMake())
777
778 var c2 = MyCar.new("123")
779 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000780
781 def CheckCar()
782 assert_equal("make = def", c.GetMake())
783 assert_equal(5, c.GetAge())
784 enddef
785 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000786 END
787 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000788
789 lines =<< trim END
790 vim9script
791
792 class MyCar
793 this.make: string
794
795 def new(make_arg: string)
796 this.make = make_arg
797 enddef
798 endclass
799
800 var c = MyCar.new("abc")
801 var c = MyCar.new("def")
802 END
803 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000804
805 lines =<< trim END
806 vim9script
807
808 class Foo
809 this.x: list<number> = []
810
811 def Add(n: number): any
812 this.x->add(n)
813 return this
814 enddef
815 endclass
816
817 echo Foo.new().Add(1).Add(2).x
818 echo Foo.new().Add(1).Add(2)
819 .x
820 echo Foo.new().Add(1)
821 .Add(2).x
822 echo Foo.new()
823 .Add(1).Add(2).x
824 echo Foo.new()
825 .Add(1)
826 .Add(2)
827 .x
828 END
829 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200830
831 # Test for "public" cannot be abbreviated
832 lines =<< trim END
833 vim9script
834 class Something
835 pub this.val = 1
836 endclass
837 END
838 v9.CheckScriptFailure(lines, 'E1065:')
839
840 # Test for "public" keyword must be followed by "this" or "static".
841 lines =<< trim END
842 vim9script
843 class Something
844 public val = 1
845 endclass
846 END
847 v9.CheckScriptFailure(lines, 'E1331:')
848
849 # Test for "static" cannot be abbreviated
850 lines =<< trim END
851 vim9script
852 class Something
853 stat this.val = 1
854 endclass
855 END
856 v9.CheckScriptFailure(lines, 'E1065:')
Bram Moolenaard505d172022-12-18 21:42:55 +0000857enddef
858
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000859def Test_class_object_compare()
860 var class_lines =<< trim END
861 vim9script
862 class Item
863 this.nr = 0
864 this.name = 'xx'
865 endclass
866 END
867
868 # used at the script level and in a compiled function
869 var test_lines =<< trim END
870 var i1 = Item.new()
871 assert_equal(i1, i1)
872 assert_true(i1 is i1)
873 var i2 = Item.new()
874 assert_equal(i1, i2)
875 assert_false(i1 is i2)
876 var i3 = Item.new(0, 'xx')
877 assert_equal(i1, i3)
878
879 var io1 = Item.new(1, 'xx')
880 assert_notequal(i1, io1)
881 var io2 = Item.new(0, 'yy')
882 assert_notequal(i1, io2)
883 END
884
885 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000886 v9.CheckScriptSuccess(
887 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000888
889 for op in ['>', '>=', '<', '<=', '=~', '!~']
890 var op_lines = [
891 'var i1 = Item.new()',
892 'var i2 = Item.new()',
893 'echo i1 ' .. op .. ' i2',
894 ]
895 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000896 v9.CheckScriptFailure(class_lines
897 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000898 endfor
899enddef
900
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000901def Test_object_type()
902 var lines =<< trim END
903 vim9script
904
905 class One
906 this.one = 1
907 endclass
908 class Two
909 this.two = 2
910 endclass
911 class TwoMore extends Two
912 this.more = 9
913 endclass
914
915 var o: One = One.new()
916 var t: Two = Two.new()
917 var m: TwoMore = TwoMore.new()
918 var tm: Two = TwoMore.new()
919
920 t = m
921 END
922 v9.CheckScriptSuccess(lines)
923
924 lines =<< trim END
925 vim9script
926
927 class One
928 this.one = 1
929 endclass
930 class Two
931 this.two = 2
932 endclass
933
934 var o: One = Two.new()
935 END
936 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000937
938 lines =<< trim END
939 vim9script
940
941 interface One
942 def GetMember(): number
943 endinterface
944 class Two implements One
945 this.one = 1
946 def GetMember(): number
947 return this.one
948 enddef
949 endclass
950
951 var o: One = Two.new(5)
952 assert_equal(5, o.GetMember())
953 END
954 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +0000955
956 lines =<< trim END
957 vim9script
958
959 class Num
960 this.n: number = 0
961 endclass
962
963 def Ref(name: string): func(Num): Num
964 return (arg: Num): Num => {
965 return eval(name)(arg)
966 }
967 enddef
968
969 const Fn = Ref('Double')
970 var Double = (m: Num): Num => Num.new(m.n * 2)
971
972 echo Fn(Num.new(4))
973 END
974 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000975enddef
976
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000977def Test_class_member()
978 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +0000979 var lines =<< trim END
980 vim9script
981 class TextPos
982 this.lnum = 1
983 this.col = 1
984 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000985 static _secret = 7
986 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +0000987
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000988 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +0000989 counter += nr
990 enddef
991 endclass
992
993 assert_equal(0, TextPos.counter)
994 TextPos.AddToCounter(3)
995 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000996 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000997
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000998 def GetCounter(): number
999 return TextPos.counter
1000 enddef
1001 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001002
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001003 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001004 assert_fails('TextPos.counter = 5', 'E1335:')
1005 assert_fails('TextPos.counter += 5', 'E1335:')
1006
1007 assert_fails('echo TextPos._secret', 'E1333:')
1008 assert_fails('TextPos._secret = 8', 'E1333:')
1009
1010 assert_equal(42, TextPos.anybody)
1011 TextPos.anybody = 12
1012 assert_equal(12, TextPos.anybody)
1013 TextPos.anybody += 5
1014 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001015 END
1016 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001017
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001018 # example in the help
1019 lines =<< trim END
1020 vim9script
1021 class OtherThing
1022 this.size: number
1023 static totalSize: number
1024
1025 def new(this.size)
1026 totalSize += this.size
1027 enddef
1028 endclass
1029 assert_equal(0, OtherThing.totalSize)
1030 var to3 = OtherThing.new(3)
1031 assert_equal(3, OtherThing.totalSize)
1032 var to7 = OtherThing.new(7)
1033 assert_equal(10, OtherThing.totalSize)
1034 END
1035 v9.CheckScriptSuccess(lines)
1036
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001037 # using static class member twice
1038 lines =<< trim END
1039 vim9script
1040
1041 class HTML
1042 static author: string = 'John Doe'
1043
1044 static def MacroSubstitute(s: string): string
1045 return substitute(s, '{{author}}', author, 'gi')
1046 enddef
1047 endclass
1048
1049 assert_equal('some text', HTML.MacroSubstitute('some text'))
1050 assert_equal('some text', HTML.MacroSubstitute('some text'))
1051 END
1052 v9.CheckScriptSuccess(lines)
1053
Bram Moolenaar62a69232023-01-24 15:07:04 +00001054 # access private member in lambda
1055 lines =<< trim END
1056 vim9script
1057
1058 class Foo
1059 this._x: number = 0
1060
1061 def Add(n: number): number
1062 const F = (): number => this._x + n
1063 return F()
1064 enddef
1065 endclass
1066
1067 var foo = Foo.new()
1068 assert_equal(5, foo.Add(5))
1069 END
1070 v9.CheckScriptSuccess(lines)
1071
h-east2bd6a092023-05-19 19:01:17 +01001072 # access private member in lambda body
1073 lines =<< trim END
1074 vim9script
1075
1076 class Foo
1077 this._x: number = 6
1078
1079 def Add(n: number): number
1080 var Lam = () => {
1081 this._x = this._x + n
1082 }
1083 Lam()
1084 return this._x
1085 enddef
1086 endclass
1087
1088 var foo = Foo.new()
1089 assert_equal(13, foo.Add(7))
1090 END
1091 v9.CheckScriptSuccess(lines)
1092
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001093 # check shadowing
1094 lines =<< trim END
1095 vim9script
1096
1097 class Some
1098 static count = 0
1099 def Method(count: number)
1100 echo count
1101 enddef
1102 endclass
1103
1104 var s = Some.new()
1105 s.Method(7)
1106 END
1107 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
1108
1109 lines =<< trim END
1110 vim9script
1111
1112 class Some
1113 static count = 0
1114 def Method(arg: number)
1115 var count = 3
1116 echo arg count
1117 enddef
1118 endclass
1119
1120 var s = Some.new()
1121 s.Method(7)
1122 END
1123 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001124
1125 # Test for using an invalid type for a member variable
1126 lines =<< trim END
1127 vim9script
1128 class A
1129 this.val: xxx
1130 endclass
1131 END
1132 v9.CheckScriptFailure(lines, 'E1010:')
1133
1134 # Test for no space before or after the '=' when initializing a member
1135 # variable
1136 lines =<< trim END
1137 vim9script
1138 class A
1139 this.val: number= 10
1140 endclass
1141 END
1142 v9.CheckScriptFailure(lines, 'E1004:')
1143 lines =<< trim END
1144 vim9script
1145 class A
1146 this.val: number =10
1147 endclass
1148 END
1149 v9.CheckScriptFailure(lines, 'E1004:')
1150
1151 # Access a non-existing member
1152 lines =<< trim END
1153 vim9script
1154 class A
1155 endclass
1156 var a = A.new()
1157 var v = a.bar
1158 END
1159 v9.CheckScriptFailure(lines, 'E1326:')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001160enddef
1161
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001162func Test_class_garbagecollect()
1163 let lines =<< trim END
1164 vim9script
1165
1166 class Point
1167 this.p = [2, 3]
1168 static pl = ['a', 'b']
1169 static pd = {a: 'a', b: 'b'}
1170 endclass
1171
1172 echo Point.pl Point.pd
1173 call test_garbagecollect_now()
1174 echo Point.pl Point.pd
1175 END
1176 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001177
1178 let lines =<< trim END
1179 vim9script
1180
1181 interface View
1182 endinterface
1183
1184 class Widget
1185 this.view: View
1186 endclass
1187
1188 class MyView implements View
1189 this.widget: Widget
1190
1191 def new()
1192 # this will result in a circular reference to this object
1193 this.widget = Widget.new(this)
1194 enddef
1195 endclass
1196
1197 var view = MyView.new()
1198
1199 # overwrite "view", will be garbage-collected next
1200 view = MyView.new()
1201 test_garbagecollect_now()
1202 END
1203 call v9.CheckScriptSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001204endfunc
1205
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001206def Test_class_function()
1207 var lines =<< trim END
1208 vim9script
1209 class Value
1210 this.value = 0
1211 static objects = 0
1212
1213 def new(v: number)
1214 this.value = v
1215 ++objects
1216 enddef
1217
1218 static def GetCount(): number
1219 return objects
1220 enddef
1221 endclass
1222
1223 assert_equal(0, Value.GetCount())
1224 var v1 = Value.new(2)
1225 assert_equal(1, Value.GetCount())
1226 var v2 = Value.new(7)
1227 assert_equal(2, Value.GetCount())
1228 END
1229 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001230
1231 # Test for cleaning up after a class definition failure when using class
1232 # functions.
1233 lines =<< trim END
1234 vim9script
1235 class A
1236 static def Foo()
1237 enddef
1238 aaa
1239 endclass
1240 END
1241 v9.CheckScriptFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001242enddef
1243
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001244def Test_class_defcompile()
1245 var lines =<< trim END
1246 vim9script
1247
1248 class C
1249 def Fo(i: number): string
1250 return i
1251 enddef
1252 endclass
1253
1254 defcompile C.Fo
1255 END
1256 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number')
1257
1258 lines =<< trim END
1259 vim9script
1260
1261 class C
1262 static def Fc(): number
1263 return 'x'
1264 enddef
1265 endclass
1266
1267 defcompile C.Fc
1268 END
1269 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001270
1271 # Trying to compile a function using a non-existing class variable
1272 lines =<< trim END
1273 vim9script
1274 defcompile x.Foo()
1275 END
1276 v9.CheckScriptFailure(lines, 'E475:')
1277
1278 # Trying to compile a function using a variable which is not a class
1279 lines =<< trim END
1280 vim9script
1281 var x: number
1282 defcompile x.Foo()
1283 END
1284 v9.CheckScriptFailure(lines, 'E475:')
1285
1286 # Trying to compile a function without specifying the name
1287 lines =<< trim END
1288 vim9script
1289 class A
1290 endclass
1291 defcompile A.
1292 END
1293 v9.CheckScriptFailure(lines, 'E475:')
1294
1295 # Trying to compile a non-existing class object member function
1296 lines =<< trim END
1297 vim9script
1298 class A
1299 endclass
1300 var a = A.new()
1301 defcompile a.Foo()
1302 END
1303 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001304enddef
1305
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001306def Test_class_object_to_string()
1307 var lines =<< trim END
1308 vim9script
1309 class TextPosition
1310 this.lnum = 1
1311 this.col = 22
1312 endclass
1313
1314 assert_equal("class TextPosition", string(TextPosition))
1315
1316 var pos = TextPosition.new()
1317 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1318 END
1319 v9.CheckScriptSuccess(lines)
1320enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001321
Bram Moolenaar554d0312023-01-05 19:59:18 +00001322def Test_interface_basics()
1323 var lines =<< trim END
1324 vim9script
1325 interface Something
1326 this.value: string
1327 static count: number
1328 def GetCount(): number
1329 endinterface
1330 END
1331 v9.CheckScriptSuccess(lines)
1332
1333 lines =<< trim END
1334 interface SomethingWrong
1335 static count = 7
1336 endinterface
1337 END
1338 v9.CheckScriptFailure(lines, 'E1342:')
1339
1340 lines =<< trim END
1341 vim9script
1342
1343 interface Some
1344 static count: number
1345 def Method(count: number)
1346 endinterface
1347 END
h-east61378a12023-04-18 19:07:29 +01001348 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001349
1350 lines =<< trim END
1351 vim9script
1352
1353 interface Some
1354 this.value: number
1355 def Method(value: number)
1356 endinterface
1357 END
h-east61378a12023-04-18 19:07:29 +01001358 # The argument name and the object member name are the same, but this is not a
1359 # problem because object members are always accessed with the "this." prefix.
1360 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001361
1362 lines =<< trim END
1363 vim9script
1364 interface somethingWrong
1365 static count = 7
1366 endinterface
1367 END
1368 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
1369
1370 lines =<< trim END
1371 vim9script
1372 interface SomethingWrong
1373 this.value: string
1374 static count = 7
1375 def GetCount(): number
1376 endinterface
1377 END
1378 v9.CheckScriptFailure(lines, 'E1344:')
1379
1380 lines =<< trim END
1381 vim9script
1382 interface SomethingWrong
1383 this.value: string
1384 static count: number
1385 def GetCount(): number
1386 return 5
1387 enddef
1388 endinterface
1389 END
1390 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001391
1392 lines =<< trim END
1393 vim9script
1394 export interface EnterExit
1395 def Enter(): void
1396 def Exit(): void
1397 endinterface
1398 END
1399 writefile(lines, 'XdefIntf.vim', 'D')
1400
1401 lines =<< trim END
1402 vim9script
1403 import './XdefIntf.vim' as defIntf
1404 export def With(ee: defIntf.EnterExit, F: func)
1405 ee.Enter()
1406 try
1407 F()
1408 finally
1409 ee.Exit()
1410 endtry
1411 enddef
1412 END
1413 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001414
1415 var imported =<< trim END
1416 vim9script
1417 export abstract class EnterExit
1418 def Enter(): void
1419 enddef
1420 def Exit(): void
1421 enddef
1422 endclass
1423 END
1424 writefile(imported, 'XdefIntf2.vim', 'D')
1425
1426 lines[1] = " import './XdefIntf2.vim' as defIntf"
1427 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001428enddef
1429
Bram Moolenaar94674f22023-01-06 18:42:20 +00001430def Test_class_implements_interface()
1431 var lines =<< trim END
1432 vim9script
1433
1434 interface Some
1435 static count: number
1436 def Method(nr: number)
1437 endinterface
1438
1439 class SomeImpl implements Some
1440 static count: number
1441 def Method(nr: number)
1442 echo nr
1443 enddef
1444 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001445
1446 interface Another
1447 this.member: string
1448 endinterface
1449
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001450 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001451 this.member = 'abc'
1452 static count: number
1453 def Method(nr: number)
1454 echo nr
1455 enddef
1456 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001457 END
1458 v9.CheckScriptSuccess(lines)
1459
1460 lines =<< trim END
1461 vim9script
1462
1463 interface Some
1464 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001465 endinterface
1466
1467 class SomeImpl implements Some implements Some
1468 static count: number
1469 endclass
1470 END
1471 v9.CheckScriptFailure(lines, 'E1350:')
1472
1473 lines =<< trim END
1474 vim9script
1475
1476 interface Some
1477 static counter: number
1478 endinterface
1479
1480 class SomeImpl implements Some, Some
1481 static count: number
1482 endclass
1483 END
1484 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
1485
1486 lines =<< trim END
1487 vim9script
1488
1489 interface Some
1490 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001491 def Method(nr: number)
1492 endinterface
1493
1494 class SomeImpl implements Some
1495 static count: number
1496 def Method(nr: number)
1497 echo nr
1498 enddef
1499 endclass
1500 END
1501 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
1502
1503 lines =<< trim END
1504 vim9script
1505
1506 interface Some
1507 static count: number
1508 def Methods(nr: number)
1509 endinterface
1510
1511 class SomeImpl implements Some
1512 static count: number
1513 def Method(nr: number)
1514 echo nr
1515 enddef
1516 endclass
1517 END
1518 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001519
1520 # Check different order of members in class and interface works.
1521 lines =<< trim END
1522 vim9script
1523
1524 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001525 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001526 this.errpos: number
1527 endinterface
1528
1529 # order of members is opposite of interface
1530 class Failure implements Result
1531 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001532 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001533 endclass
1534
1535 def Test()
1536 var result: Result = Failure.new()
1537
1538 assert_equal('label', result.label)
1539 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001540
1541 result.label = 'different'
1542 assert_equal('different', result.label)
1543 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001544 enddef
1545
1546 Test()
1547 END
1548 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001549
1550 # Interface name after "extends" doesn't end in a space or NUL character
1551 lines =<< trim END
1552 vim9script
1553 interface A
1554 endinterface
1555 class B extends A"
1556 endclass
1557 END
1558 v9.CheckScriptFailure(lines, 'E1315:')
1559
1560 # Trailing characters after a class name
1561 lines =<< trim END
1562 vim9script
1563 class A bbb
1564 endclass
1565 END
1566 v9.CheckScriptFailure(lines, 'E488:')
1567
1568 # using "implements" with a non-existing class
1569 lines =<< trim END
1570 vim9script
1571 class A implements B
1572 endclass
1573 END
1574 v9.CheckScriptFailure(lines, 'E1346:')
1575
1576 # using "implements" with a regular class
1577 lines =<< trim END
1578 vim9script
1579 class A
1580 endclass
1581 class B implements A
1582 endclass
1583 END
1584 v9.CheckScriptFailure(lines, 'E1347:')
1585
1586 # using "implements" with a variable
1587 lines =<< trim END
1588 vim9script
1589 var T: number = 10
1590 class A implements T
1591 endclass
1592 END
1593 v9.CheckScriptFailure(lines, 'E1347:')
1594
1595 # all the class methods in an "interface" should be implemented
1596 lines =<< trim END
1597 vim9script
1598 interface A
1599 static def Foo()
1600 endinterface
1601 class B implements A
1602 endclass
1603 END
1604 v9.CheckScriptFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02001605
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02001606 # implements should be followed by a white space
1607 lines =<< trim END
1608 vim9script
1609 interface A
1610 endinterface
1611 class B implements A;
1612 endclass
1613 END
1614 v9.CheckScriptFailure(lines, 'E1315:')
1615
LemonBoyc5d27442023-08-19 13:02:35 +02001616 lines =<< trim END
1617 vim9script
1618
1619 interface One
1620 static matching: bool
1621 static as_any: any
1622 static not_matching: number
1623 endinterface
1624 class Two implements One
1625 static not_matching: string
1626 static as_any: string
1627 static matching: bool
1628 endclass
1629 END
1630 v9.CheckScriptFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
1631
1632 lines =<< trim END
1633 vim9script
1634
1635 interface One
1636 def IsEven(nr: number): bool
1637 endinterface
1638 class Two implements One
1639 def IsEven(nr: number): string
1640 enddef
1641 endclass
1642 END
1643 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(number): string')
1644
1645 lines =<< trim END
1646 vim9script
1647
1648 interface One
1649 def IsEven(nr: number): bool
1650 endinterface
1651 class Two implements One
1652 def IsEven(nr: bool): bool
1653 enddef
1654 endclass
1655 END
1656 v9.CheckScriptFailure(lines, 'E1407: Member "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
1657
1658 lines =<< trim END
1659 vim9script
1660
1661 interface One
1662 def IsEven(nr: number): bool
1663 endinterface
1664 class Two implements One
1665 def IsEven(nr: number, ...extra: list<number>): bool
1666 enddef
1667 endclass
1668 END
1669 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 +00001670enddef
1671
Bram Moolenaard0200c82023-01-28 15:19:40 +00001672def Test_call_interface_method()
1673 var lines =<< trim END
1674 vim9script
1675 interface Base
1676 def Enter(): void
1677 endinterface
1678
1679 class Child implements Base
1680 def Enter(): void
1681 g:result ..= 'child'
1682 enddef
1683 endclass
1684
1685 def F(obj: Base)
1686 obj.Enter()
1687 enddef
1688
1689 g:result = ''
1690 F(Child.new())
1691 assert_equal('child', g:result)
1692 unlet g:result
1693 END
1694 v9.CheckScriptSuccess(lines)
1695
1696 lines =<< trim END
1697 vim9script
1698 class Base
1699 def Enter(): void
1700 g:result ..= 'base'
1701 enddef
1702 endclass
1703
1704 class Child extends Base
1705 def Enter(): void
1706 g:result ..= 'child'
1707 enddef
1708 endclass
1709
1710 def F(obj: Base)
1711 obj.Enter()
1712 enddef
1713
1714 g:result = ''
1715 F(Child.new())
1716 assert_equal('child', g:result)
1717 unlet g:result
1718 END
1719 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001720
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001721 # method of interface returns a value
1722 lines =<< trim END
1723 vim9script
1724 interface Base
1725 def Enter(): string
1726 endinterface
1727
1728 class Child implements Base
1729 def Enter(): string
1730 g:result ..= 'child'
1731 return "/resource"
1732 enddef
1733 endclass
1734
1735 def F(obj: Base)
1736 var r = obj.Enter()
1737 g:result ..= r
1738 enddef
1739
1740 g:result = ''
1741 F(Child.new())
1742 assert_equal('child/resource', g:result)
1743 unlet g:result
1744 END
1745 v9.CheckScriptSuccess(lines)
1746
1747 lines =<< trim END
1748 vim9script
1749 class Base
1750 def Enter(): string
1751 return null_string
1752 enddef
1753 endclass
1754
1755 class Child extends Base
1756 def Enter(): string
1757 g:result ..= 'child'
1758 return "/resource"
1759 enddef
1760 endclass
1761
1762 def F(obj: Base)
1763 var r = obj.Enter()
1764 g:result ..= r
1765 enddef
1766
1767 g:result = ''
1768 F(Child.new())
1769 assert_equal('child/resource', g:result)
1770 unlet g:result
1771 END
1772 v9.CheckScriptSuccess(lines)
1773
1774
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001775 # No class that implements the interface.
1776 lines =<< trim END
1777 vim9script
1778
1779 interface IWithEE
1780 def Enter(): any
1781 def Exit(): void
1782 endinterface
1783
1784 def With1(ee: IWithEE, F: func)
1785 var r = ee.Enter()
1786 enddef
1787
1788 defcompile
1789 END
1790 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001791enddef
1792
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001793def Test_class_used_as_type()
1794 var lines =<< trim END
1795 vim9script
1796
1797 class Point
1798 this.x = 0
1799 this.y = 0
1800 endclass
1801
1802 var p: Point
1803 p = Point.new(2, 33)
1804 assert_equal(2, p.x)
1805 assert_equal(33, p.y)
1806 END
1807 v9.CheckScriptSuccess(lines)
1808
1809 lines =<< trim END
1810 vim9script
1811
1812 interface HasX
1813 this.x: number
1814 endinterface
1815
1816 class Point implements HasX
1817 this.x = 0
1818 this.y = 0
1819 endclass
1820
1821 var p: Point
1822 p = Point.new(2, 33)
1823 var hx = p
1824 assert_equal(2, hx.x)
1825 END
1826 v9.CheckScriptSuccess(lines)
1827
1828 lines =<< trim END
1829 vim9script
1830
1831 class Point
1832 this.x = 0
1833 this.y = 0
1834 endclass
1835
1836 var p: Point
1837 p = 'text'
1838 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001839 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001840enddef
1841
Bram Moolenaar83677162023-01-08 19:54:10 +00001842def Test_class_extends()
1843 var lines =<< trim END
1844 vim9script
1845 class Base
1846 this.one = 1
1847 def GetOne(): number
1848 return this.one
1849 enddef
1850 endclass
1851 class Child extends Base
1852 this.two = 2
1853 def GetTotal(): number
1854 return this.one + this.two
1855 enddef
1856 endclass
1857 var o = Child.new()
1858 assert_equal(1, o.one)
1859 assert_equal(2, o.two)
1860 assert_equal(1, o.GetOne())
1861 assert_equal(3, o.GetTotal())
1862 END
1863 v9.CheckScriptSuccess(lines)
1864
1865 lines =<< trim END
1866 vim9script
1867 class Base
1868 this.one = 1
1869 endclass
1870 class Child extends Base
1871 this.two = 2
1872 endclass
1873 var o = Child.new(3, 44)
1874 assert_equal(3, o.one)
1875 assert_equal(44, o.two)
1876 END
1877 v9.CheckScriptSuccess(lines)
1878
1879 lines =<< trim END
1880 vim9script
1881 class Base
1882 this.one = 1
1883 endclass
1884 class Child extends Base extends Base
1885 this.two = 2
1886 endclass
1887 END
1888 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1889
1890 lines =<< trim END
1891 vim9script
1892 class Child extends BaseClass
1893 this.two = 2
1894 endclass
1895 END
1896 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1897
1898 lines =<< trim END
1899 vim9script
1900 var SomeVar = 99
1901 class Child extends SomeVar
1902 this.two = 2
1903 endclass
1904 END
1905 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001906
1907 lines =<< trim END
1908 vim9script
1909 class Base
1910 this.name: string
1911 def ToString(): string
1912 return this.name
1913 enddef
1914 endclass
1915
1916 class Child extends Base
1917 this.age: number
1918 def ToString(): string
1919 return super.ToString() .. ': ' .. this.age
1920 enddef
1921 endclass
1922
1923 var o = Child.new('John', 42)
1924 assert_equal('John: 42', o.ToString())
1925 END
1926 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001927
1928 lines =<< trim END
1929 vim9script
1930 class Child
1931 this.age: number
1932 def ToString(): number
1933 return this.age
1934 enddef
1935 def ToString(): string
1936 return this.age
1937 enddef
1938 endclass
1939 END
1940 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1941
1942 lines =<< trim END
1943 vim9script
1944 class Child
1945 this.age: number
1946 def ToString(): string
1947 return super .ToString() .. ': ' .. this.age
1948 enddef
1949 endclass
1950 var o = Child.new(42)
1951 echo o.ToString()
1952 END
1953 v9.CheckScriptFailure(lines, 'E1356:')
1954
1955 lines =<< trim END
1956 vim9script
1957 class Base
1958 this.name: string
1959 def ToString(): string
1960 return this.name
1961 enddef
1962 endclass
1963
1964 var age = 42
1965 def ToString(): string
1966 return super.ToString() .. ': ' .. age
1967 enddef
1968 echo ToString()
1969 END
1970 v9.CheckScriptFailure(lines, 'E1357:')
1971
1972 lines =<< trim END
1973 vim9script
1974 class Child
1975 this.age: number
1976 def ToString(): string
1977 return super.ToString() .. ': ' .. this.age
1978 enddef
1979 endclass
1980 var o = Child.new(42)
1981 echo o.ToString()
1982 END
1983 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001984
1985 lines =<< trim END
1986 vim9script
1987 class Base
1988 this.name: string
1989 static def ToString(): string
1990 return 'Base class'
1991 enddef
1992 endclass
1993
1994 class Child extends Base
1995 this.age: number
1996 def ToString(): string
1997 return Base.ToString() .. ': ' .. this.age
1998 enddef
1999 endclass
2000
2001 var o = Child.new('John', 42)
2002 assert_equal('Base class: 42', o.ToString())
2003 END
2004 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002005
2006 lines =<< trim END
2007 vim9script
2008 class Base
2009 this.value = 1
2010 def new(init: number)
2011 this.value = number + 1
2012 enddef
2013 endclass
2014 class Child extends Base
2015 def new()
2016 this.new(3)
2017 enddef
2018 endclass
2019 var c = Child.new()
2020 END
2021 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002022
2023 # base class with more than one object member
2024 lines =<< trim END
2025 vim9script
2026
2027 class Result
2028 this.success: bool
2029 this.value: any = null
2030 endclass
2031
2032 class Success extends Result
2033 def new(this.value = v:none)
2034 this.success = true
2035 enddef
2036 endclass
2037
2038 var v = Success.new('asdf')
2039 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2040 END
2041 v9.CheckScriptSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002042
2043 # class name after "extends" doesn't end in a space or NUL character
2044 lines =<< trim END
2045 vim9script
2046 class A
2047 endclass
2048 class B extends A"
2049 endclass
2050 END
2051 v9.CheckScriptFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002052enddef
2053
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002054def Test_using_base_class()
2055 var lines =<< trim END
2056 vim9script
2057
2058 class BaseEE
2059 def Enter(): any
2060 return null
2061 enddef
2062 def Exit(resource: any): void
2063 enddef
2064 endclass
2065
2066 class ChildEE extends BaseEE
2067 def Enter(): any
2068 return 42
2069 enddef
2070
2071 def Exit(resource: number): void
2072 g:result ..= '/exit'
2073 enddef
2074 endclass
2075
2076 def With(ee: BaseEE)
2077 var r = ee.Enter()
2078 try
2079 g:result ..= r
2080 finally
2081 g:result ..= '/finally'
2082 ee.Exit(r)
2083 endtry
2084 enddef
2085
2086 g:result = ''
2087 With(ChildEE.new())
2088 assert_equal('42/finally/exit', g:result)
2089 END
2090 v9.CheckScriptSuccess(lines)
2091 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002092
2093 # Using super, Child invokes Base method which has optional arg. #12471
2094 lines =<< trim END
2095 vim9script
2096
2097 class Base
2098 this.success: bool = false
2099 def Method(arg = 0)
2100 this.success = true
2101 enddef
2102 endclass
2103
2104 class Child extends Base
2105 def new()
2106 super.Method()
2107 enddef
2108 endclass
2109
2110 var obj = Child.new()
2111 assert_equal(true, obj.success)
2112 END
2113 v9.CheckScriptSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002114enddef
2115
2116
Bram Moolenaara86655a2023-01-12 17:06:27 +00002117def Test_class_import()
2118 var lines =<< trim END
2119 vim9script
2120 export class Animal
2121 this.kind: string
2122 this.name: string
2123 endclass
2124 END
2125 writefile(lines, 'Xanimal.vim', 'D')
2126
2127 lines =<< trim END
2128 vim9script
2129 import './Xanimal.vim' as animal
2130
2131 var a: animal.Animal
2132 a = animal.Animal.new('fish', 'Eric')
2133 assert_equal('fish', a.kind)
2134 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002135
2136 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2137 assert_equal('cat', b.kind)
2138 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002139 END
2140 v9.CheckScriptSuccess(lines)
2141enddef
2142
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002143def Test_abstract_class()
2144 var lines =<< trim END
2145 vim9script
2146 abstract class Base
2147 this.name: string
2148 endclass
2149 class Person extends Base
2150 this.age: number
2151 endclass
2152 var p: Base = Person.new('Peter', 42)
2153 assert_equal('Peter', p.name)
2154 assert_equal(42, p.age)
2155 END
2156 v9.CheckScriptSuccess(lines)
2157
2158 lines =<< trim END
2159 vim9script
2160 abstract class Base
2161 this.name: string
2162 endclass
2163 class Person extends Base
2164 this.age: number
2165 endclass
2166 var p = Base.new('Peter')
2167 END
2168 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
2169
2170 lines =<< trim END
2171 abstract class Base
2172 this.name: string
2173 endclass
2174 END
2175 v9.CheckScriptFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002176
2177 # Abstract class cannot have a "new" function
2178 lines =<< trim END
2179 vim9script
2180 abstract class Base
2181 def new()
2182 enddef
2183 endclass
2184 END
2185 v9.CheckScriptFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002186enddef
2187
Bram Moolenaar486fc252023-01-18 14:51:07 +00002188def Test_closure_in_class()
2189 var lines =<< trim END
2190 vim9script
2191
2192 class Foo
2193 this.y: list<string> = ['B']
2194
2195 def new()
2196 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2197 enddef
2198 endclass
2199
2200 Foo.new()
2201 assert_equal(['A'], g:result)
2202 END
2203 v9.CheckScriptSuccess(lines)
2204enddef
2205
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002206def Test_call_constructor_from_legacy()
2207 var lines =<< trim END
2208 vim9script
2209
2210 var newCalled = 'false'
2211
2212 class A
2213 def new()
2214 newCalled = 'true'
2215 enddef
2216 endclass
2217
2218 export def F(options = {}): any
2219 return A
2220 enddef
2221
2222 g:p = F()
2223 legacy call p.new()
2224 assert_equal('true', newCalled)
2225 END
2226 v9.CheckScriptSuccess(lines)
2227enddef
2228
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002229def Test_defer_with_object()
2230 var lines =<< trim END
2231 vim9script
2232
2233 class CWithEE
2234 def Enter()
2235 g:result ..= "entered/"
2236 enddef
2237 def Exit()
2238 g:result ..= "exited"
2239 enddef
2240 endclass
2241
2242 def With(ee: CWithEE, F: func)
2243 ee.Enter()
2244 defer ee.Exit()
2245 F()
2246 enddef
2247
2248 g:result = ''
2249 var obj = CWithEE.new()
2250 obj->With(() => {
2251 g:result ..= "called/"
2252 })
2253 assert_equal('entered/called/exited', g:result)
2254 END
2255 v9.CheckScriptSuccess(lines)
2256 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002257
2258 lines =<< trim END
2259 vim9script
2260
2261 class BaseWithEE
2262 def Enter()
2263 g:result ..= "entered-base/"
2264 enddef
2265 def Exit()
2266 g:result ..= "exited-base"
2267 enddef
2268 endclass
2269
2270 class CWithEE extends BaseWithEE
2271 def Enter()
2272 g:result ..= "entered-child/"
2273 enddef
2274 def Exit()
2275 g:result ..= "exited-child"
2276 enddef
2277 endclass
2278
2279 def With(ee: BaseWithEE, F: func)
2280 ee.Enter()
2281 defer ee.Exit()
2282 F()
2283 enddef
2284
2285 g:result = ''
2286 var obj = CWithEE.new()
2287 obj->With(() => {
2288 g:result ..= "called/"
2289 })
2290 assert_equal('entered-child/called/exited-child', g:result)
2291 END
2292 v9.CheckScriptSuccess(lines)
2293 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002294enddef
2295
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002296" The following test used to crash Vim (Github issue #12676)
2297def Test_extends_method_crashes_vim()
2298 var lines =<< trim END
2299 vim9script
2300
2301 class Observer
2302 endclass
2303
2304 class Property
2305 this.value: any
2306
2307 def Set(v: any)
2308 if v != this.value
2309 this.value = v
2310 endif
2311 enddef
2312
2313 def Register(observer: Observer)
2314 enddef
2315 endclass
2316
2317 class Bool extends Property
2318 this.value: bool
2319 endclass
2320
2321 def Observe(obj: Property, who: Observer)
2322 obj.Register(who)
2323 enddef
2324
2325 var p = Bool.new(false)
2326 var myObserver = Observer.new()
2327
2328 Observe(p, myObserver)
2329
2330 p.Set(true)
2331 END
2332 v9.CheckScriptSuccess(lines)
2333enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002334
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002335" Test for calling a method in a class that is extended
2336def Test_call_method_in_extended_class()
2337 var lines =<< trim END
2338 vim9script
2339
2340 var prop_init_called = false
2341 var prop_register_called = false
2342
2343 class Property
2344 def Init()
2345 prop_init_called = true
2346 enddef
2347
2348 def Register()
2349 prop_register_called = true
2350 enddef
2351 endclass
2352
2353 class Bool extends Property
2354 endclass
2355
2356 def Observe(obj: Property)
2357 obj.Register()
2358 enddef
2359
2360 var p = Property.new()
2361 Observe(p)
2362
2363 p.Init()
2364 assert_true(prop_init_called)
2365 assert_true(prop_register_called)
2366 END
2367 v9.CheckScriptSuccess(lines)
2368enddef
2369
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002370" Test for calling a method in the parent class that is extended partially.
2371" This used to fail with the 'E118: Too many arguments for function: Text' error
2372" message (Github issue #12524).
2373def Test_call_method_in_parent_class()
2374 var lines =<< trim END
2375 vim9script
2376
2377 class Widget
2378 this._lnum: number = 1
2379
2380 def SetY(lnum: number)
2381 this._lnum = lnum
2382 enddef
2383
2384 def Text(): string
2385 return ''
2386 enddef
2387 endclass
2388
2389 class Foo extends Widget
2390 def Text(): string
2391 return '<Foo>'
2392 enddef
2393 endclass
2394
2395 def Stack(w1: Widget, w2: Widget): list<Widget>
2396 w1.SetY(1)
2397 w2.SetY(2)
2398 return [w1, w2]
2399 enddef
2400
2401 var foo1 = Foo.new()
2402 var foo2 = Foo.new()
2403 var l = Stack(foo1, foo2)
2404 END
2405 v9.CheckScriptSuccess(lines)
2406enddef
2407
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002408" Test for calling methods from three levels of classes
2409def Test_multi_level_method_call()
2410 var lines =<< trim END
2411 vim9script
2412
2413 var A_func1: number = 0
2414 var A_func2: number = 0
2415 var A_func3: number = 0
2416 var B_func2: number = 0
2417 var B_func3: number = 0
2418 var C_func3: number = 0
2419
2420 class A
2421 def Func1()
2422 A_func1 += 1
2423 enddef
2424
2425 def Func2()
2426 A_func2 += 1
2427 enddef
2428
2429 def Func3()
2430 A_func3 += 1
2431 enddef
2432 endclass
2433
2434 class B extends A
2435 def Func2()
2436 B_func2 += 1
2437 enddef
2438
2439 def Func3()
2440 B_func3 += 1
2441 enddef
2442 endclass
2443
2444 class C extends B
2445 def Func3()
2446 C_func3 += 1
2447 enddef
2448 endclass
2449
2450 def A_CallFuncs(a: A)
2451 a.Func1()
2452 a.Func2()
2453 a.Func3()
2454 enddef
2455
2456 def B_CallFuncs(b: B)
2457 b.Func1()
2458 b.Func2()
2459 b.Func3()
2460 enddef
2461
2462 def C_CallFuncs(c: C)
2463 c.Func1()
2464 c.Func2()
2465 c.Func3()
2466 enddef
2467
2468 var cobj = C.new()
2469 A_CallFuncs(cobj)
2470 B_CallFuncs(cobj)
2471 C_CallFuncs(cobj)
2472 assert_equal(3, A_func1)
2473 assert_equal(0, A_func2)
2474 assert_equal(0, A_func3)
2475 assert_equal(3, B_func2)
2476 assert_equal(0, B_func3)
2477 assert_equal(3, C_func3)
2478 END
2479 v9.CheckScriptSuccess(lines)
2480enddef
2481
2482" Test for using members from three levels of classes
2483def Test_multi_level_member_access()
2484 var lines =<< trim END
2485 vim9script
2486
2487 class A
2488 this.val1: number = 0
2489 this.val2: number = 0
2490 this.val3: number = 0
2491 endclass
2492
2493 class B extends A
2494 this.val2: number = 0
2495 this.val3: number = 0
2496 endclass
2497
2498 class C extends B
2499 this.val3: number = 0
2500 endclass
2501
2502 def A_members(a: A)
2503 a.val1 += 1
2504 a.val2 += 1
2505 a.val3 += 1
2506 enddef
2507
2508 def B_members(b: B)
2509 b.val1 += 1
2510 b.val2 += 1
2511 b.val3 += 1
2512 enddef
2513
2514 def C_members(c: C)
2515 c.val1 += 1
2516 c.val2 += 1
2517 c.val3 += 1
2518 enddef
2519
2520 var cobj = C.new()
2521 A_members(cobj)
2522 B_members(cobj)
2523 C_members(cobj)
2524 assert_equal(3, cobj.val1)
2525 assert_equal(3, cobj.val2)
2526 assert_equal(3, cobj.val3)
2527 END
2528 v9.CheckScriptSuccess(lines)
2529enddef
2530
LemonBoy0ffc17a2023-08-20 18:09:11 +02002531" Test expansion of <stack> with class methods.
2532def Test_stack_expansion_with_methods()
2533 var lines =<< trim END
2534 vim9script
2535
2536 class C
2537 def M1()
2538 F0()
2539 enddef
2540 endclass
2541
2542 def F0()
2543 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
2544 enddef
2545
2546 def F()
2547 C.new().M1()
2548 enddef
2549
2550 F()
2551 END
2552 v9.CheckScriptSuccess(lines)
2553enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002554
2555" Test the return type of the new() constructor
2556def Test_new_return_type()
2557 # new() uses the default return type and there is no return statement
2558 var lines =<< trim END
2559 vim9script
2560
2561 class C
2562 this._bufnr: number
2563
2564 def new(this._bufnr)
2565 if !bufexists(this._bufnr)
2566 this._bufnr = -1
2567 endif
2568 enddef
2569 endclass
2570
2571 var c = C.new(12345)
2572 assert_equal('object<C>', typename(c))
2573
2574 var v1: C
2575 v1 = C.new(12345)
2576 assert_equal('object<C>', typename(v1))
2577
2578 def F()
2579 var v2: C
2580 v2 = C.new(12345)
2581 assert_equal('object<C>', typename(v2))
2582 enddef
2583 F()
2584 END
2585 v9.CheckScriptSuccess(lines)
2586
2587 # new() uses the default return type and an empty 'return' statement
2588 lines =<< trim END
2589 vim9script
2590
2591 class C
2592 this._bufnr: number
2593
2594 def new(this._bufnr)
2595 if !bufexists(this._bufnr)
2596 this._bufnr = -1
2597 return
2598 endif
2599 enddef
2600 endclass
2601
2602 var c = C.new(12345)
2603 assert_equal('object<C>', typename(c))
2604
2605 var v1: C
2606 v1 = C.new(12345)
2607 assert_equal('object<C>', typename(v1))
2608
2609 def F()
2610 var v2: C
2611 v2 = C.new(12345)
2612 assert_equal('object<C>', typename(v2))
2613 enddef
2614 F()
2615 END
2616 v9.CheckScriptSuccess(lines)
2617
2618 # new() uses "any" return type and returns "this"
2619 lines =<< trim END
2620 vim9script
2621
2622 class C
2623 this._bufnr: number
2624
2625 def new(this._bufnr): any
2626 if !bufexists(this._bufnr)
2627 this._bufnr = -1
2628 return this
2629 endif
2630 enddef
2631 endclass
2632 END
2633 v9.CheckScriptFailure(lines, 'E1365:')
2634
2635 # new() uses 'Dict' return type and returns a Dict
2636 lines =<< trim END
2637 vim9script
2638
2639 class C
2640 this._state: dict<any>
2641
2642 def new(): dict<any>
2643 this._state = {}
2644 return this._state
2645 enddef
2646 endclass
2647
2648 var c = C.new()
2649 assert_equal('object<C>', typename(c))
2650 END
2651 v9.CheckScriptFailure(lines, 'E1365:')
2652enddef
2653
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02002654" Test for checking a member initialization type at run time.
2655def Test_runtime_type_check_for_member_init()
2656 var lines =<< trim END
2657 vim9script
2658
2659 var retnum: bool = false
2660
2661 def F(): any
2662 retnum = !retnum
2663 if retnum
2664 return 1
2665 else
2666 return "hello"
2667 endif
2668 enddef
2669
2670 class C
2671 this._foo: bool = F()
2672 endclass
2673
2674 var c1 = C.new()
2675 var c2 = C.new()
2676 END
2677 v9.CheckScriptFailure(lines, 'E1012:')
2678enddef
2679
2680" Test for locking a variable referring to an object and reassigning to another
2681" object.
2682def Test_object_lockvar()
2683 var lines =<< trim END
2684 vim9script
2685
2686 class C
2687 this.val: number
2688 def new(this.val)
2689 enddef
2690 endclass
2691
2692 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
2693 lockvar 2 some_dict
2694
2695 var current: C
2696 current = some_dict['c']
2697 assert_equal(3, current.val)
2698 current = some_dict['b']
2699 assert_equal(2, current.val)
2700
2701 def F()
2702 current = some_dict['c']
2703 enddef
2704
2705 def G()
2706 current = some_dict['b']
2707 enddef
2708
2709 F()
2710 assert_equal(3, current.val)
2711 G()
2712 assert_equal(2, current.val)
2713 END
2714 v9.CheckScriptSuccess(lines)
2715enddef
2716
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002717" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker