blob: 3a434d1bacbf19f8e39d448fd5e57358aa8d79ff [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 Moolenaard0200c82023-01-28 15:19:40 +00001004def Test_call_interface_method()
1005 var lines =<< trim END
1006 vim9script
1007 interface Base
1008 def Enter(): void
1009 endinterface
1010
1011 class Child implements Base
1012 def Enter(): void
1013 g:result ..= 'child'
1014 enddef
1015 endclass
1016
1017 def F(obj: Base)
1018 obj.Enter()
1019 enddef
1020
1021 g:result = ''
1022 F(Child.new())
1023 assert_equal('child', g:result)
1024 unlet g:result
1025 END
1026 v9.CheckScriptSuccess(lines)
1027
1028 lines =<< trim END
1029 vim9script
1030 class Base
1031 def Enter(): void
1032 g:result ..= 'base'
1033 enddef
1034 endclass
1035
1036 class Child extends Base
1037 def Enter(): void
1038 g:result ..= 'child'
1039 enddef
1040 endclass
1041
1042 def F(obj: Base)
1043 obj.Enter()
1044 enddef
1045
1046 g:result = ''
1047 F(Child.new())
1048 assert_equal('child', g:result)
1049 unlet g:result
1050 END
1051 v9.CheckScriptSuccess(lines)
1052enddef
1053
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001054def Test_class_used_as_type()
1055 var lines =<< trim END
1056 vim9script
1057
1058 class Point
1059 this.x = 0
1060 this.y = 0
1061 endclass
1062
1063 var p: Point
1064 p = Point.new(2, 33)
1065 assert_equal(2, p.x)
1066 assert_equal(33, p.y)
1067 END
1068 v9.CheckScriptSuccess(lines)
1069
1070 lines =<< trim END
1071 vim9script
1072
1073 interface HasX
1074 this.x: number
1075 endinterface
1076
1077 class Point implements HasX
1078 this.x = 0
1079 this.y = 0
1080 endclass
1081
1082 var p: Point
1083 p = Point.new(2, 33)
1084 var hx = p
1085 assert_equal(2, hx.x)
1086 END
1087 v9.CheckScriptSuccess(lines)
1088
1089 lines =<< trim END
1090 vim9script
1091
1092 class Point
1093 this.x = 0
1094 this.y = 0
1095 endclass
1096
1097 var p: Point
1098 p = 'text'
1099 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001100 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001101enddef
1102
Bram Moolenaar83677162023-01-08 19:54:10 +00001103def Test_class_extends()
1104 var lines =<< trim END
1105 vim9script
1106 class Base
1107 this.one = 1
1108 def GetOne(): number
1109 return this.one
1110 enddef
1111 endclass
1112 class Child extends Base
1113 this.two = 2
1114 def GetTotal(): number
1115 return this.one + this.two
1116 enddef
1117 endclass
1118 var o = Child.new()
1119 assert_equal(1, o.one)
1120 assert_equal(2, o.two)
1121 assert_equal(1, o.GetOne())
1122 assert_equal(3, o.GetTotal())
1123 END
1124 v9.CheckScriptSuccess(lines)
1125
1126 lines =<< trim END
1127 vim9script
1128 class Base
1129 this.one = 1
1130 endclass
1131 class Child extends Base
1132 this.two = 2
1133 endclass
1134 var o = Child.new(3, 44)
1135 assert_equal(3, o.one)
1136 assert_equal(44, o.two)
1137 END
1138 v9.CheckScriptSuccess(lines)
1139
1140 lines =<< trim END
1141 vim9script
1142 class Base
1143 this.one = 1
1144 endclass
1145 class Child extends Base extends Base
1146 this.two = 2
1147 endclass
1148 END
1149 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1150
1151 lines =<< trim END
1152 vim9script
1153 class Child extends BaseClass
1154 this.two = 2
1155 endclass
1156 END
1157 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1158
1159 lines =<< trim END
1160 vim9script
1161 var SomeVar = 99
1162 class Child extends SomeVar
1163 this.two = 2
1164 endclass
1165 END
1166 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001167
1168 lines =<< trim END
1169 vim9script
1170 class Base
1171 this.name: string
1172 def ToString(): string
1173 return this.name
1174 enddef
1175 endclass
1176
1177 class Child extends Base
1178 this.age: number
1179 def ToString(): string
1180 return super.ToString() .. ': ' .. this.age
1181 enddef
1182 endclass
1183
1184 var o = Child.new('John', 42)
1185 assert_equal('John: 42', o.ToString())
1186 END
1187 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001188
1189 lines =<< trim END
1190 vim9script
1191 class Child
1192 this.age: number
1193 def ToString(): number
1194 return this.age
1195 enddef
1196 def ToString(): string
1197 return this.age
1198 enddef
1199 endclass
1200 END
1201 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1202
1203 lines =<< trim END
1204 vim9script
1205 class Child
1206 this.age: number
1207 def ToString(): string
1208 return super .ToString() .. ': ' .. this.age
1209 enddef
1210 endclass
1211 var o = Child.new(42)
1212 echo o.ToString()
1213 END
1214 v9.CheckScriptFailure(lines, 'E1356:')
1215
1216 lines =<< trim END
1217 vim9script
1218 class Base
1219 this.name: string
1220 def ToString(): string
1221 return this.name
1222 enddef
1223 endclass
1224
1225 var age = 42
1226 def ToString(): string
1227 return super.ToString() .. ': ' .. age
1228 enddef
1229 echo ToString()
1230 END
1231 v9.CheckScriptFailure(lines, 'E1357:')
1232
1233 lines =<< trim END
1234 vim9script
1235 class Child
1236 this.age: number
1237 def ToString(): string
1238 return super.ToString() .. ': ' .. this.age
1239 enddef
1240 endclass
1241 var o = Child.new(42)
1242 echo o.ToString()
1243 END
1244 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001245
1246 lines =<< trim END
1247 vim9script
1248 class Base
1249 this.name: string
1250 static def ToString(): string
1251 return 'Base class'
1252 enddef
1253 endclass
1254
1255 class Child extends Base
1256 this.age: number
1257 def ToString(): string
1258 return Base.ToString() .. ': ' .. this.age
1259 enddef
1260 endclass
1261
1262 var o = Child.new('John', 42)
1263 assert_equal('Base class: 42', o.ToString())
1264 END
1265 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001266
1267 lines =<< trim END
1268 vim9script
1269 class Base
1270 this.value = 1
1271 def new(init: number)
1272 this.value = number + 1
1273 enddef
1274 endclass
1275 class Child extends Base
1276 def new()
1277 this.new(3)
1278 enddef
1279 endclass
1280 var c = Child.new()
1281 END
1282 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00001283
1284 # base class with more than one object member
1285 lines =<< trim END
1286 vim9script
1287
1288 class Result
1289 this.success: bool
1290 this.value: any = null
1291 endclass
1292
1293 class Success extends Result
1294 def new(this.value = v:none)
1295 this.success = true
1296 enddef
1297 endclass
1298
1299 var v = Success.new('asdf')
1300 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
1301 END
1302 v9.CheckScriptSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00001303enddef
1304
Bram Moolenaara86655a2023-01-12 17:06:27 +00001305def Test_class_import()
1306 var lines =<< trim END
1307 vim9script
1308 export class Animal
1309 this.kind: string
1310 this.name: string
1311 endclass
1312 END
1313 writefile(lines, 'Xanimal.vim', 'D')
1314
1315 lines =<< trim END
1316 vim9script
1317 import './Xanimal.vim' as animal
1318
1319 var a: animal.Animal
1320 a = animal.Animal.new('fish', 'Eric')
1321 assert_equal('fish', a.kind)
1322 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00001323
1324 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
1325 assert_equal('cat', b.kind)
1326 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00001327 END
1328 v9.CheckScriptSuccess(lines)
1329enddef
1330
Bram Moolenaar24a8d062023-01-14 13:12:06 +00001331def Test_abstract_class()
1332 var lines =<< trim END
1333 vim9script
1334 abstract class Base
1335 this.name: string
1336 endclass
1337 class Person extends Base
1338 this.age: number
1339 endclass
1340 var p: Base = Person.new('Peter', 42)
1341 assert_equal('Peter', p.name)
1342 assert_equal(42, p.age)
1343 END
1344 v9.CheckScriptSuccess(lines)
1345
1346 lines =<< trim END
1347 vim9script
1348 abstract class Base
1349 this.name: string
1350 endclass
1351 class Person extends Base
1352 this.age: number
1353 endclass
1354 var p = Base.new('Peter')
1355 END
1356 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
1357
1358 lines =<< trim END
1359 abstract class Base
1360 this.name: string
1361 endclass
1362 END
1363 v9.CheckScriptFailure(lines, 'E1316:')
1364enddef
1365
Bram Moolenaar486fc252023-01-18 14:51:07 +00001366def Test_closure_in_class()
1367 var lines =<< trim END
1368 vim9script
1369
1370 class Foo
1371 this.y: list<string> = ['B']
1372
1373 def new()
1374 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
1375 enddef
1376 endclass
1377
1378 Foo.new()
1379 assert_equal(['A'], g:result)
1380 END
1381 v9.CheckScriptSuccess(lines)
1382enddef
1383
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001384def Test_defer_with_object()
1385 var lines =<< trim END
1386 vim9script
1387
1388 class CWithEE
1389 def Enter()
1390 g:result ..= "entered/"
1391 enddef
1392 def Exit()
1393 g:result ..= "exited"
1394 enddef
1395 endclass
1396
1397 def With(ee: CWithEE, F: func)
1398 ee.Enter()
1399 defer ee.Exit()
1400 F()
1401 enddef
1402
1403 g:result = ''
1404 var obj = CWithEE.new()
1405 obj->With(() => {
1406 g:result ..= "called/"
1407 })
1408 assert_equal('entered/called/exited', g:result)
1409 END
1410 v9.CheckScriptSuccess(lines)
1411 unlet g:result
1412enddef
1413
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001414
1415" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker