blob: a59cdc4c4e994f3256164b231b38114ea4c22c4c [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
51 endclass school's out
52 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
138 lines =<< trim END
139 vim9script
140
141 class TextPosition
142 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000143 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000144
Bram Moolenaar418b5472022-12-20 13:38:22 +0000145 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000146 def ToString(): string
147 return $'({this.lnum}, {this.col})'
148 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000149 endclass
150
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000151 # use the automatically generated new() method
152 var pos = TextPosition.new(2, 12)
153 assert_equal(2, pos.lnum)
154 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000155
156 # call an object method
157 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000158
159 assert_equal(v:t_class, type(TextPosition))
160 assert_equal(v:t_object, type(pos))
161 assert_equal('class<TextPosition>', typename(TextPosition))
162 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000163 END
164 v9.CheckScriptSuccess(lines)
165enddef
166
Bram Moolenaar657aea72023-01-27 13:16:19 +0000167def Test_class_interface_wrong_end()
168 var lines =<< trim END
169 vim9script
170 abstract class SomeName
171 this.member = 'text'
172 endinterface
173 END
174 v9.CheckScriptFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
175
176 lines =<< trim END
177 vim9script
178 export interface AnotherName
179 this.member: string
180 endclass
181 END
182 v9.CheckScriptFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
183enddef
184
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000185def Test_class_member_initializer()
186 var lines =<< trim END
187 vim9script
188
189 class TextPosition
190 this.lnum: number = 1
191 this.col: number = 1
192
Bram Moolenaar418b5472022-12-20 13:38:22 +0000193 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000194 def new(lnum: number)
195 this.lnum = lnum
196 enddef
197 endclass
198
199 var pos = TextPosition.new(3)
200 assert_equal(3, pos.lnum)
201 assert_equal(1, pos.col)
202
203 var instr = execute('disassemble TextPosition.new')
204 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000205 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000206 '\d PUSHNR 1\_s*' ..
207 '\d STORE_THIS 0\_s*' ..
208 '\d PUSHNR 1\_s*' ..
209 '\d STORE_THIS 1\_s*' ..
210 'this.lnum = lnum\_s*' ..
211 '\d LOAD arg\[-1]\_s*' ..
212 '\d PUSHNR 0\_s*' ..
213 '\d LOAD $0\_s*' ..
214 '\d\+ STOREINDEX object\_s*' ..
215 '\d\+ RETURN object.*',
216 instr)
217 END
218 v9.CheckScriptSuccess(lines)
219enddef
220
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000221def Test_assignment_with_operator()
222 var lines =<< trim END
223 vim9script
224
225 class Foo
226 this.x: number
227
228 def Add(n: number)
229 this.x += n
230 enddef
231 endclass
232
233 var f = Foo.new(3)
234 f.Add(17)
235 assert_equal(20, f.x)
236 END
237 v9.CheckScriptSuccess(lines)
238enddef
239
Bram Moolenaarf4508042023-01-15 16:54:57 +0000240def Test_list_of_objects()
241 var lines =<< trim END
242 vim9script
243
244 class Foo
245 def Add()
246 enddef
247 endclass
248
249 def ProcessList(fooList: list<Foo>)
250 for foo in fooList
251 foo.Add()
252 endfor
253 enddef
254
255 var l: list<Foo> = [Foo.new()]
256 ProcessList(l)
257 END
258 v9.CheckScriptSuccess(lines)
259enddef
260
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000261def Test_expr_after_using_object()
262 var lines =<< trim END
263 vim9script
264
265 class Something
266 this.label: string = ''
267 endclass
268
269 def Foo(): Something
270 var v = Something.new()
271 echo 'in Foo(): ' .. typename(v)
272 return v
273 enddef
274
275 Foo()
276 END
277 v9.CheckScriptSuccess(lines)
278enddef
279
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000280def Test_class_default_new()
281 var lines =<< trim END
282 vim9script
283
284 class TextPosition
285 this.lnum: number = 1
286 this.col: number = 1
287 endclass
288
289 var pos = TextPosition.new()
290 assert_equal(1, pos.lnum)
291 assert_equal(1, pos.col)
292
293 pos = TextPosition.new(v:none, v:none)
294 assert_equal(1, pos.lnum)
295 assert_equal(1, pos.col)
296
297 pos = TextPosition.new(3, 22)
298 assert_equal(3, pos.lnum)
299 assert_equal(22, pos.col)
300
301 pos = TextPosition.new(v:none, 33)
302 assert_equal(1, pos.lnum)
303 assert_equal(33, pos.col)
304 END
305 v9.CheckScriptSuccess(lines)
306
307 lines =<< trim END
308 vim9script
309 class Person
310 this.name: string
311 this.age: number = 42
312 this.education: string = "unknown"
313
314 def new(this.name, this.age = v:none, this.education = v:none)
315 enddef
316 endclass
317
318 var piet = Person.new("Piet")
319 assert_equal("Piet", piet.name)
320 assert_equal(42, piet.age)
321 assert_equal("unknown", piet.education)
322
323 var chris = Person.new("Chris", 4, "none")
324 assert_equal("Chris", chris.name)
325 assert_equal(4, chris.age)
326 assert_equal("none", chris.education)
327 END
328 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000329
330 lines =<< trim END
331 vim9script
332 class Person
333 this.name: string
334 this.age: number = 42
335 this.education: string = "unknown"
336
337 def new(this.name, this.age = v:none, this.education = v:none)
338 enddef
339 endclass
340
341 var missing = Person.new()
342 END
343 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000344enddef
345
Bram Moolenaar74e12742022-12-13 21:14:28 +0000346def Test_class_object_member_inits()
347 var lines =<< trim END
348 vim9script
349 class TextPosition
350 this.lnum: number
351 this.col = 1
352 this.addcol: number = 2
353 endclass
354
355 var pos = TextPosition.new()
356 assert_equal(0, pos.lnum)
357 assert_equal(1, pos.col)
358 assert_equal(2, pos.addcol)
359 END
360 v9.CheckScriptSuccess(lines)
361
362 lines =<< trim END
363 vim9script
364 class TextPosition
365 this.lnum
366 this.col = 1
367 endclass
368 END
369 v9.CheckScriptFailure(lines, 'E1022:')
370
371 lines =<< trim END
372 vim9script
373 class TextPosition
374 this.lnum = v:none
375 this.col = 1
376 endclass
377 END
378 v9.CheckScriptFailure(lines, 'E1330:')
379enddef
380
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000381def Test_class_object_member_access()
382 var lines =<< trim END
383 vim9script
384 class Triple
385 this._one = 1
386 this.two = 2
387 public this.three = 3
388
389 def GetOne(): number
390 return this._one
391 enddef
392 endclass
393
394 var trip = Triple.new()
395 assert_equal(1, trip.GetOne())
396 assert_equal(2, trip.two)
397 assert_equal(3, trip.three)
398 assert_fails('echo trip._one', 'E1333')
399
400 assert_fails('trip._one = 11', 'E1333')
401 assert_fails('trip.two = 22', 'E1335')
402 trip.three = 33
403 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000404
405 assert_fails('trip.four = 4', 'E1334')
406 END
407 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000408
409 lines =<< trim END
410 vim9script
411
412 class MyCar
413 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000414 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000415
416 def new(make_arg: string)
417 this.make = make_arg
418 enddef
419
420 def GetMake(): string
421 return $"make = {this.make}"
422 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000423 def GetAge(): number
424 return this.age
425 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000426 endclass
427
428 var c = MyCar.new("abc")
429 assert_equal('make = abc', c.GetMake())
430
431 c = MyCar.new("def")
432 assert_equal('make = def', c.GetMake())
433
434 var c2 = MyCar.new("123")
435 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000436
437 def CheckCar()
438 assert_equal("make = def", c.GetMake())
439 assert_equal(5, c.GetAge())
440 enddef
441 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000442 END
443 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000444
445 lines =<< trim END
446 vim9script
447
448 class MyCar
449 this.make: string
450
451 def new(make_arg: string)
452 this.make = make_arg
453 enddef
454 endclass
455
456 var c = MyCar.new("abc")
457 var c = MyCar.new("def")
458 END
459 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000460
461 lines =<< trim END
462 vim9script
463
464 class Foo
465 this.x: list<number> = []
466
467 def Add(n: number): any
468 this.x->add(n)
469 return this
470 enddef
471 endclass
472
473 echo Foo.new().Add(1).Add(2).x
474 echo Foo.new().Add(1).Add(2)
475 .x
476 echo Foo.new().Add(1)
477 .Add(2).x
478 echo Foo.new()
479 .Add(1).Add(2).x
480 echo Foo.new()
481 .Add(1)
482 .Add(2)
483 .x
484 END
485 v9.CheckScriptSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +0000486enddef
487
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000488def Test_class_object_compare()
489 var class_lines =<< trim END
490 vim9script
491 class Item
492 this.nr = 0
493 this.name = 'xx'
494 endclass
495 END
496
497 # used at the script level and in a compiled function
498 var test_lines =<< trim END
499 var i1 = Item.new()
500 assert_equal(i1, i1)
501 assert_true(i1 is i1)
502 var i2 = Item.new()
503 assert_equal(i1, i2)
504 assert_false(i1 is i2)
505 var i3 = Item.new(0, 'xx')
506 assert_equal(i1, i3)
507
508 var io1 = Item.new(1, 'xx')
509 assert_notequal(i1, io1)
510 var io2 = Item.new(0, 'yy')
511 assert_notequal(i1, io2)
512 END
513
514 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000515 v9.CheckScriptSuccess(
516 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000517
518 for op in ['>', '>=', '<', '<=', '=~', '!~']
519 var op_lines = [
520 'var i1 = Item.new()',
521 'var i2 = Item.new()',
522 'echo i1 ' .. op .. ' i2',
523 ]
524 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000525 v9.CheckScriptFailure(class_lines
526 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000527 endfor
528enddef
529
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000530def Test_object_type()
531 var lines =<< trim END
532 vim9script
533
534 class One
535 this.one = 1
536 endclass
537 class Two
538 this.two = 2
539 endclass
540 class TwoMore extends Two
541 this.more = 9
542 endclass
543
544 var o: One = One.new()
545 var t: Two = Two.new()
546 var m: TwoMore = TwoMore.new()
547 var tm: Two = TwoMore.new()
548
549 t = m
550 END
551 v9.CheckScriptSuccess(lines)
552
553 lines =<< trim END
554 vim9script
555
556 class One
557 this.one = 1
558 endclass
559 class Two
560 this.two = 2
561 endclass
562
563 var o: One = Two.new()
564 END
565 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000566
567 lines =<< trim END
568 vim9script
569
570 interface One
571 def GetMember(): number
572 endinterface
573 class Two implements One
574 this.one = 1
575 def GetMember(): number
576 return this.one
577 enddef
578 endclass
579
580 var o: One = Two.new(5)
581 assert_equal(5, o.GetMember())
582 END
583 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +0000584
585 lines =<< trim END
586 vim9script
587
588 class Num
589 this.n: number = 0
590 endclass
591
592 def Ref(name: string): func(Num): Num
593 return (arg: Num): Num => {
594 return eval(name)(arg)
595 }
596 enddef
597
598 const Fn = Ref('Double')
599 var Double = (m: Num): Num => Num.new(m.n * 2)
600
601 echo Fn(Num.new(4))
602 END
603 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000604enddef
605
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000606def Test_class_member()
607 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +0000608 var lines =<< trim END
609 vim9script
610 class TextPos
611 this.lnum = 1
612 this.col = 1
613 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000614 static _secret = 7
615 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +0000616
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000617 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +0000618 counter += nr
619 enddef
620 endclass
621
622 assert_equal(0, TextPos.counter)
623 TextPos.AddToCounter(3)
624 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000625 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000626
627 def GetCounter(): number
628 return TextPos.counter
629 enddef
630 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +0000631
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000632 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000633 assert_fails('TextPos.counter = 5', 'E1335:')
634 assert_fails('TextPos.counter += 5', 'E1335:')
635
636 assert_fails('echo TextPos._secret', 'E1333:')
637 assert_fails('TextPos._secret = 8', 'E1333:')
638
639 assert_equal(42, TextPos.anybody)
640 TextPos.anybody = 12
641 assert_equal(12, TextPos.anybody)
642 TextPos.anybody += 5
643 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000644 END
645 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000646
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000647 # example in the help
648 lines =<< trim END
649 vim9script
650 class OtherThing
651 this.size: number
652 static totalSize: number
653
654 def new(this.size)
655 totalSize += this.size
656 enddef
657 endclass
658 assert_equal(0, OtherThing.totalSize)
659 var to3 = OtherThing.new(3)
660 assert_equal(3, OtherThing.totalSize)
661 var to7 = OtherThing.new(7)
662 assert_equal(10, OtherThing.totalSize)
663 END
664 v9.CheckScriptSuccess(lines)
665
Bram Moolenaar62a69232023-01-24 15:07:04 +0000666 # access private member in lambda
667 lines =<< trim END
668 vim9script
669
670 class Foo
671 this._x: number = 0
672
673 def Add(n: number): number
674 const F = (): number => this._x + n
675 return F()
676 enddef
677 endclass
678
679 var foo = Foo.new()
680 assert_equal(5, foo.Add(5))
681 END
682 v9.CheckScriptSuccess(lines)
683
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000684 # check shadowing
685 lines =<< trim END
686 vim9script
687
688 class Some
689 static count = 0
690 def Method(count: number)
691 echo count
692 enddef
693 endclass
694
695 var s = Some.new()
696 s.Method(7)
697 END
698 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
699
700 lines =<< trim END
701 vim9script
702
703 class Some
704 static count = 0
705 def Method(arg: number)
706 var count = 3
707 echo arg count
708 enddef
709 endclass
710
711 var s = Some.new()
712 s.Method(7)
713 END
714 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000715enddef
716
Bram Moolenaarcf760d52023-01-05 13:16:04 +0000717func Test_class_garbagecollect()
718 let lines =<< trim END
719 vim9script
720
721 class Point
722 this.p = [2, 3]
723 static pl = ['a', 'b']
724 static pd = {a: 'a', b: 'b'}
725 endclass
726
727 echo Point.pl Point.pd
728 call test_garbagecollect_now()
729 echo Point.pl Point.pd
730 END
731 call v9.CheckScriptSuccess(lines)
732endfunc
733
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000734def Test_class_function()
735 var lines =<< trim END
736 vim9script
737 class Value
738 this.value = 0
739 static objects = 0
740
741 def new(v: number)
742 this.value = v
743 ++objects
744 enddef
745
746 static def GetCount(): number
747 return objects
748 enddef
749 endclass
750
751 assert_equal(0, Value.GetCount())
752 var v1 = Value.new(2)
753 assert_equal(1, Value.GetCount())
754 var v2 = Value.new(7)
755 assert_equal(2, Value.GetCount())
756 END
757 v9.CheckScriptSuccess(lines)
758enddef
759
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +0000760def Test_class_object_to_string()
761 var lines =<< trim END
762 vim9script
763 class TextPosition
764 this.lnum = 1
765 this.col = 22
766 endclass
767
768 assert_equal("class TextPosition", string(TextPosition))
769
770 var pos = TextPosition.new()
771 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
772 END
773 v9.CheckScriptSuccess(lines)
774enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +0000775
Bram Moolenaar554d0312023-01-05 19:59:18 +0000776def Test_interface_basics()
777 var lines =<< trim END
778 vim9script
779 interface Something
780 this.value: string
781 static count: number
782 def GetCount(): number
783 endinterface
784 END
785 v9.CheckScriptSuccess(lines)
786
787 lines =<< trim END
788 interface SomethingWrong
789 static count = 7
790 endinterface
791 END
792 v9.CheckScriptFailure(lines, 'E1342:')
793
794 lines =<< trim END
795 vim9script
796
797 interface Some
798 static count: number
799 def Method(count: number)
800 endinterface
801 END
Bram Moolenaard40f00c2023-01-13 17:36:49 +0000802 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
803
804 lines =<< trim END
805 vim9script
806
807 interface Some
808 this.value: number
809 def Method(value: number)
810 endinterface
811 END
812 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: value')
Bram Moolenaar554d0312023-01-05 19:59:18 +0000813
814 lines =<< trim END
815 vim9script
816 interface somethingWrong
817 static count = 7
818 endinterface
819 END
820 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
821
822 lines =<< trim END
823 vim9script
824 interface SomethingWrong
825 this.value: string
826 static count = 7
827 def GetCount(): number
828 endinterface
829 END
830 v9.CheckScriptFailure(lines, 'E1344:')
831
832 lines =<< trim END
833 vim9script
834 interface SomethingWrong
835 this.value: string
836 static count: number
837 def GetCount(): number
838 return 5
839 enddef
840 endinterface
841 END
842 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +0000843
844 lines =<< trim END
845 vim9script
846 export interface EnterExit
847 def Enter(): void
848 def Exit(): void
849 endinterface
850 END
851 writefile(lines, 'XdefIntf.vim', 'D')
852
853 lines =<< trim END
854 vim9script
855 import './XdefIntf.vim' as defIntf
856 export def With(ee: defIntf.EnterExit, F: func)
857 ee.Enter()
858 try
859 F()
860 finally
861 ee.Exit()
862 endtry
863 enddef
864 END
865 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000866
867 var imported =<< trim END
868 vim9script
869 export abstract class EnterExit
870 def Enter(): void
871 enddef
872 def Exit(): void
873 enddef
874 endclass
875 END
876 writefile(imported, 'XdefIntf2.vim', 'D')
877
878 lines[1] = " import './XdefIntf2.vim' as defIntf"
879 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +0000880enddef
881
Bram Moolenaar94674f22023-01-06 18:42:20 +0000882def Test_class_implements_interface()
883 var lines =<< trim END
884 vim9script
885
886 interface Some
887 static count: number
888 def Method(nr: number)
889 endinterface
890
891 class SomeImpl implements Some
892 static count: number
893 def Method(nr: number)
894 echo nr
895 enddef
896 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +0000897
898 interface Another
899 this.member: string
900 endinterface
901
902 class SomeImpl implements Some, Another
903 this.member = 'abc'
904 static count: number
905 def Method(nr: number)
906 echo nr
907 enddef
908 endclass
909
Bram Moolenaar94674f22023-01-06 18:42:20 +0000910 END
911 v9.CheckScriptSuccess(lines)
912
913 lines =<< trim END
914 vim9script
915
916 interface Some
917 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +0000918 endinterface
919
920 class SomeImpl implements Some implements Some
921 static count: number
922 endclass
923 END
924 v9.CheckScriptFailure(lines, 'E1350:')
925
926 lines =<< trim END
927 vim9script
928
929 interface Some
930 static counter: number
931 endinterface
932
933 class SomeImpl implements Some, Some
934 static count: number
935 endclass
936 END
937 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
938
939 lines =<< trim END
940 vim9script
941
942 interface Some
943 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +0000944 def Method(nr: number)
945 endinterface
946
947 class SomeImpl implements Some
948 static count: number
949 def Method(nr: number)
950 echo nr
951 enddef
952 endclass
953 END
954 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
955
956 lines =<< trim END
957 vim9script
958
959 interface Some
960 static count: number
961 def Methods(nr: number)
962 endinterface
963
964 class SomeImpl implements Some
965 static count: number
966 def Method(nr: number)
967 echo nr
968 enddef
969 endclass
970 END
971 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +0000972
973 # Check different order of members in class and interface works.
974 lines =<< trim END
975 vim9script
976
977 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +0000978 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +0000979 this.errpos: number
980 endinterface
981
982 # order of members is opposite of interface
983 class Failure implements Result
984 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +0000985 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +0000986 endclass
987
988 def Test()
989 var result: Result = Failure.new()
990
991 assert_equal('label', result.label)
992 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +0000993
994 result.label = 'different'
995 assert_equal('different', result.label)
996 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +0000997 enddef
998
999 Test()
1000 END
1001 v9.CheckScriptSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00001002enddef
1003
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001004def Test_class_used_as_type()
1005 var lines =<< trim END
1006 vim9script
1007
1008 class Point
1009 this.x = 0
1010 this.y = 0
1011 endclass
1012
1013 var p: Point
1014 p = Point.new(2, 33)
1015 assert_equal(2, p.x)
1016 assert_equal(33, p.y)
1017 END
1018 v9.CheckScriptSuccess(lines)
1019
1020 lines =<< trim END
1021 vim9script
1022
1023 interface HasX
1024 this.x: number
1025 endinterface
1026
1027 class Point implements HasX
1028 this.x = 0
1029 this.y = 0
1030 endclass
1031
1032 var p: Point
1033 p = Point.new(2, 33)
1034 var hx = p
1035 assert_equal(2, hx.x)
1036 END
1037 v9.CheckScriptSuccess(lines)
1038
1039 lines =<< trim END
1040 vim9script
1041
1042 class Point
1043 this.x = 0
1044 this.y = 0
1045 endclass
1046
1047 var p: Point
1048 p = 'text'
1049 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001050 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001051enddef
1052
Bram Moolenaar83677162023-01-08 19:54:10 +00001053def Test_class_extends()
1054 var lines =<< trim END
1055 vim9script
1056 class Base
1057 this.one = 1
1058 def GetOne(): number
1059 return this.one
1060 enddef
1061 endclass
1062 class Child extends Base
1063 this.two = 2
1064 def GetTotal(): number
1065 return this.one + this.two
1066 enddef
1067 endclass
1068 var o = Child.new()
1069 assert_equal(1, o.one)
1070 assert_equal(2, o.two)
1071 assert_equal(1, o.GetOne())
1072 assert_equal(3, o.GetTotal())
1073 END
1074 v9.CheckScriptSuccess(lines)
1075
1076 lines =<< trim END
1077 vim9script
1078 class Base
1079 this.one = 1
1080 endclass
1081 class Child extends Base
1082 this.two = 2
1083 endclass
1084 var o = Child.new(3, 44)
1085 assert_equal(3, o.one)
1086 assert_equal(44, o.two)
1087 END
1088 v9.CheckScriptSuccess(lines)
1089
1090 lines =<< trim END
1091 vim9script
1092 class Base
1093 this.one = 1
1094 endclass
1095 class Child extends Base extends Base
1096 this.two = 2
1097 endclass
1098 END
1099 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1100
1101 lines =<< trim END
1102 vim9script
1103 class Child extends BaseClass
1104 this.two = 2
1105 endclass
1106 END
1107 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1108
1109 lines =<< trim END
1110 vim9script
1111 var SomeVar = 99
1112 class Child extends SomeVar
1113 this.two = 2
1114 endclass
1115 END
1116 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001117
1118 lines =<< trim END
1119 vim9script
1120 class Base
1121 this.name: string
1122 def ToString(): string
1123 return this.name
1124 enddef
1125 endclass
1126
1127 class Child extends Base
1128 this.age: number
1129 def ToString(): string
1130 return super.ToString() .. ': ' .. this.age
1131 enddef
1132 endclass
1133
1134 var o = Child.new('John', 42)
1135 assert_equal('John: 42', o.ToString())
1136 END
1137 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001138
1139 lines =<< trim END
1140 vim9script
1141 class Child
1142 this.age: number
1143 def ToString(): number
1144 return this.age
1145 enddef
1146 def ToString(): string
1147 return this.age
1148 enddef
1149 endclass
1150 END
1151 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1152
1153 lines =<< trim END
1154 vim9script
1155 class Child
1156 this.age: number
1157 def ToString(): string
1158 return super .ToString() .. ': ' .. this.age
1159 enddef
1160 endclass
1161 var o = Child.new(42)
1162 echo o.ToString()
1163 END
1164 v9.CheckScriptFailure(lines, 'E1356:')
1165
1166 lines =<< trim END
1167 vim9script
1168 class Base
1169 this.name: string
1170 def ToString(): string
1171 return this.name
1172 enddef
1173 endclass
1174
1175 var age = 42
1176 def ToString(): string
1177 return super.ToString() .. ': ' .. age
1178 enddef
1179 echo ToString()
1180 END
1181 v9.CheckScriptFailure(lines, 'E1357:')
1182
1183 lines =<< trim END
1184 vim9script
1185 class Child
1186 this.age: number
1187 def ToString(): string
1188 return super.ToString() .. ': ' .. this.age
1189 enddef
1190 endclass
1191 var o = Child.new(42)
1192 echo o.ToString()
1193 END
1194 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001195
1196 lines =<< trim END
1197 vim9script
1198 class Base
1199 this.name: string
1200 static def ToString(): string
1201 return 'Base class'
1202 enddef
1203 endclass
1204
1205 class Child extends Base
1206 this.age: number
1207 def ToString(): string
1208 return Base.ToString() .. ': ' .. this.age
1209 enddef
1210 endclass
1211
1212 var o = Child.new('John', 42)
1213 assert_equal('Base class: 42', o.ToString())
1214 END
1215 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001216
1217 lines =<< trim END
1218 vim9script
1219 class Base
1220 this.value = 1
1221 def new(init: number)
1222 this.value = number + 1
1223 enddef
1224 endclass
1225 class Child extends Base
1226 def new()
1227 this.new(3)
1228 enddef
1229 endclass
1230 var c = Child.new()
1231 END
1232 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00001233
1234 # base class with more than one object member
1235 lines =<< trim END
1236 vim9script
1237
1238 class Result
1239 this.success: bool
1240 this.value: any = null
1241 endclass
1242
1243 class Success extends Result
1244 def new(this.value = v:none)
1245 this.success = true
1246 enddef
1247 endclass
1248
1249 var v = Success.new('asdf')
1250 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
1251 END
1252 v9.CheckScriptSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00001253enddef
1254
Bram Moolenaara86655a2023-01-12 17:06:27 +00001255def Test_class_import()
1256 var lines =<< trim END
1257 vim9script
1258 export class Animal
1259 this.kind: string
1260 this.name: string
1261 endclass
1262 END
1263 writefile(lines, 'Xanimal.vim', 'D')
1264
1265 lines =<< trim END
1266 vim9script
1267 import './Xanimal.vim' as animal
1268
1269 var a: animal.Animal
1270 a = animal.Animal.new('fish', 'Eric')
1271 assert_equal('fish', a.kind)
1272 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00001273
1274 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
1275 assert_equal('cat', b.kind)
1276 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00001277 END
1278 v9.CheckScriptSuccess(lines)
1279enddef
1280
Bram Moolenaar24a8d062023-01-14 13:12:06 +00001281def Test_abstract_class()
1282 var lines =<< trim END
1283 vim9script
1284 abstract class Base
1285 this.name: string
1286 endclass
1287 class Person extends Base
1288 this.age: number
1289 endclass
1290 var p: Base = Person.new('Peter', 42)
1291 assert_equal('Peter', p.name)
1292 assert_equal(42, p.age)
1293 END
1294 v9.CheckScriptSuccess(lines)
1295
1296 lines =<< trim END
1297 vim9script
1298 abstract class Base
1299 this.name: string
1300 endclass
1301 class Person extends Base
1302 this.age: number
1303 endclass
1304 var p = Base.new('Peter')
1305 END
1306 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
1307
1308 lines =<< trim END
1309 abstract class Base
1310 this.name: string
1311 endclass
1312 END
1313 v9.CheckScriptFailure(lines, 'E1316:')
1314enddef
1315
Bram Moolenaar486fc252023-01-18 14:51:07 +00001316def Test_closure_in_class()
1317 var lines =<< trim END
1318 vim9script
1319
1320 class Foo
1321 this.y: list<string> = ['B']
1322
1323 def new()
1324 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
1325 enddef
1326 endclass
1327
1328 Foo.new()
1329 assert_equal(['A'], g:result)
1330 END
1331 v9.CheckScriptSuccess(lines)
1332enddef
1333
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001334def Test_defer_with_object()
1335 var lines =<< trim END
1336 vim9script
1337
1338 class CWithEE
1339 def Enter()
1340 g:result ..= "entered/"
1341 enddef
1342 def Exit()
1343 g:result ..= "exited"
1344 enddef
1345 endclass
1346
1347 def With(ee: CWithEE, F: func)
1348 ee.Enter()
1349 defer ee.Exit()
1350 F()
1351 enddef
1352
1353 g:result = ''
1354 var obj = CWithEE.new()
1355 obj->With(() => {
1356 g:result ..= "called/"
1357 })
1358 assert_equal('entered/called/exited', g:result)
1359 END
1360 v9.CheckScriptSuccess(lines)
1361 unlet g:result
1362enddef
1363
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001364
1365" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker