blob: a8128c7c77fd82a6519bc16e9fdee941a82cfd26 [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
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 Moolenaar94722c52023-01-28 19:19:03 +0000626
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000627 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)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001052
1053 # No class that implements the interface.
1054 lines =<< trim END
1055 vim9script
1056
1057 interface IWithEE
1058 def Enter(): any
1059 def Exit(): void
1060 endinterface
1061
1062 def With1(ee: IWithEE, F: func)
1063 var r = ee.Enter()
1064 enddef
1065
1066 defcompile
1067 END
1068 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001069enddef
1070
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001071def Test_class_used_as_type()
1072 var lines =<< trim END
1073 vim9script
1074
1075 class Point
1076 this.x = 0
1077 this.y = 0
1078 endclass
1079
1080 var p: Point
1081 p = Point.new(2, 33)
1082 assert_equal(2, p.x)
1083 assert_equal(33, p.y)
1084 END
1085 v9.CheckScriptSuccess(lines)
1086
1087 lines =<< trim END
1088 vim9script
1089
1090 interface HasX
1091 this.x: number
1092 endinterface
1093
1094 class Point implements HasX
1095 this.x = 0
1096 this.y = 0
1097 endclass
1098
1099 var p: Point
1100 p = Point.new(2, 33)
1101 var hx = p
1102 assert_equal(2, hx.x)
1103 END
1104 v9.CheckScriptSuccess(lines)
1105
1106 lines =<< trim END
1107 vim9script
1108
1109 class Point
1110 this.x = 0
1111 this.y = 0
1112 endclass
1113
1114 var p: Point
1115 p = 'text'
1116 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001117 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001118enddef
1119
Bram Moolenaar83677162023-01-08 19:54:10 +00001120def Test_class_extends()
1121 var lines =<< trim END
1122 vim9script
1123 class Base
1124 this.one = 1
1125 def GetOne(): number
1126 return this.one
1127 enddef
1128 endclass
1129 class Child extends Base
1130 this.two = 2
1131 def GetTotal(): number
1132 return this.one + this.two
1133 enddef
1134 endclass
1135 var o = Child.new()
1136 assert_equal(1, o.one)
1137 assert_equal(2, o.two)
1138 assert_equal(1, o.GetOne())
1139 assert_equal(3, o.GetTotal())
1140 END
1141 v9.CheckScriptSuccess(lines)
1142
1143 lines =<< trim END
1144 vim9script
1145 class Base
1146 this.one = 1
1147 endclass
1148 class Child extends Base
1149 this.two = 2
1150 endclass
1151 var o = Child.new(3, 44)
1152 assert_equal(3, o.one)
1153 assert_equal(44, o.two)
1154 END
1155 v9.CheckScriptSuccess(lines)
1156
1157 lines =<< trim END
1158 vim9script
1159 class Base
1160 this.one = 1
1161 endclass
1162 class Child extends Base extends Base
1163 this.two = 2
1164 endclass
1165 END
1166 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1167
1168 lines =<< trim END
1169 vim9script
1170 class Child extends BaseClass
1171 this.two = 2
1172 endclass
1173 END
1174 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1175
1176 lines =<< trim END
1177 vim9script
1178 var SomeVar = 99
1179 class Child extends SomeVar
1180 this.two = 2
1181 endclass
1182 END
1183 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001184
1185 lines =<< trim END
1186 vim9script
1187 class Base
1188 this.name: string
1189 def ToString(): string
1190 return this.name
1191 enddef
1192 endclass
1193
1194 class Child extends Base
1195 this.age: number
1196 def ToString(): string
1197 return super.ToString() .. ': ' .. this.age
1198 enddef
1199 endclass
1200
1201 var o = Child.new('John', 42)
1202 assert_equal('John: 42', o.ToString())
1203 END
1204 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001205
1206 lines =<< trim END
1207 vim9script
1208 class Child
1209 this.age: number
1210 def ToString(): number
1211 return this.age
1212 enddef
1213 def ToString(): string
1214 return this.age
1215 enddef
1216 endclass
1217 END
1218 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1219
1220 lines =<< trim END
1221 vim9script
1222 class Child
1223 this.age: number
1224 def ToString(): string
1225 return super .ToString() .. ': ' .. this.age
1226 enddef
1227 endclass
1228 var o = Child.new(42)
1229 echo o.ToString()
1230 END
1231 v9.CheckScriptFailure(lines, 'E1356:')
1232
1233 lines =<< trim END
1234 vim9script
1235 class Base
1236 this.name: string
1237 def ToString(): string
1238 return this.name
1239 enddef
1240 endclass
1241
1242 var age = 42
1243 def ToString(): string
1244 return super.ToString() .. ': ' .. age
1245 enddef
1246 echo ToString()
1247 END
1248 v9.CheckScriptFailure(lines, 'E1357:')
1249
1250 lines =<< trim END
1251 vim9script
1252 class Child
1253 this.age: number
1254 def ToString(): string
1255 return super.ToString() .. ': ' .. this.age
1256 enddef
1257 endclass
1258 var o = Child.new(42)
1259 echo o.ToString()
1260 END
1261 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001262
1263 lines =<< trim END
1264 vim9script
1265 class Base
1266 this.name: string
1267 static def ToString(): string
1268 return 'Base class'
1269 enddef
1270 endclass
1271
1272 class Child extends Base
1273 this.age: number
1274 def ToString(): string
1275 return Base.ToString() .. ': ' .. this.age
1276 enddef
1277 endclass
1278
1279 var o = Child.new('John', 42)
1280 assert_equal('Base class: 42', o.ToString())
1281 END
1282 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001283
1284 lines =<< trim END
1285 vim9script
1286 class Base
1287 this.value = 1
1288 def new(init: number)
1289 this.value = number + 1
1290 enddef
1291 endclass
1292 class Child extends Base
1293 def new()
1294 this.new(3)
1295 enddef
1296 endclass
1297 var c = Child.new()
1298 END
1299 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00001300
1301 # base class with more than one object member
1302 lines =<< trim END
1303 vim9script
1304
1305 class Result
1306 this.success: bool
1307 this.value: any = null
1308 endclass
1309
1310 class Success extends Result
1311 def new(this.value = v:none)
1312 this.success = true
1313 enddef
1314 endclass
1315
1316 var v = Success.new('asdf')
1317 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
1318 END
1319 v9.CheckScriptSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00001320enddef
1321
Bram Moolenaara86655a2023-01-12 17:06:27 +00001322def Test_class_import()
1323 var lines =<< trim END
1324 vim9script
1325 export class Animal
1326 this.kind: string
1327 this.name: string
1328 endclass
1329 END
1330 writefile(lines, 'Xanimal.vim', 'D')
1331
1332 lines =<< trim END
1333 vim9script
1334 import './Xanimal.vim' as animal
1335
1336 var a: animal.Animal
1337 a = animal.Animal.new('fish', 'Eric')
1338 assert_equal('fish', a.kind)
1339 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00001340
1341 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
1342 assert_equal('cat', b.kind)
1343 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00001344 END
1345 v9.CheckScriptSuccess(lines)
1346enddef
1347
Bram Moolenaar24a8d062023-01-14 13:12:06 +00001348def Test_abstract_class()
1349 var lines =<< trim END
1350 vim9script
1351 abstract class Base
1352 this.name: string
1353 endclass
1354 class Person extends Base
1355 this.age: number
1356 endclass
1357 var p: Base = Person.new('Peter', 42)
1358 assert_equal('Peter', p.name)
1359 assert_equal(42, p.age)
1360 END
1361 v9.CheckScriptSuccess(lines)
1362
1363 lines =<< trim END
1364 vim9script
1365 abstract class Base
1366 this.name: string
1367 endclass
1368 class Person extends Base
1369 this.age: number
1370 endclass
1371 var p = Base.new('Peter')
1372 END
1373 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
1374
1375 lines =<< trim END
1376 abstract class Base
1377 this.name: string
1378 endclass
1379 END
1380 v9.CheckScriptFailure(lines, 'E1316:')
1381enddef
1382
Bram Moolenaar486fc252023-01-18 14:51:07 +00001383def Test_closure_in_class()
1384 var lines =<< trim END
1385 vim9script
1386
1387 class Foo
1388 this.y: list<string> = ['B']
1389
1390 def new()
1391 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
1392 enddef
1393 endclass
1394
1395 Foo.new()
1396 assert_equal(['A'], g:result)
1397 END
1398 v9.CheckScriptSuccess(lines)
1399enddef
1400
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001401def Test_defer_with_object()
1402 var lines =<< trim END
1403 vim9script
1404
1405 class CWithEE
1406 def Enter()
1407 g:result ..= "entered/"
1408 enddef
1409 def Exit()
1410 g:result ..= "exited"
1411 enddef
1412 endclass
1413
1414 def With(ee: CWithEE, F: func)
1415 ee.Enter()
1416 defer ee.Exit()
1417 F()
1418 enddef
1419
1420 g:result = ''
1421 var obj = CWithEE.new()
1422 obj->With(() => {
1423 g:result ..= "called/"
1424 })
1425 assert_equal('entered/called/exited', g:result)
1426 END
1427 v9.CheckScriptSuccess(lines)
1428 unlet g:result
1429enddef
1430
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001431
1432" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker