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