blob: e73b31c9b3943073c7ca2172617ed5e550d07e58 [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 Moolenaar552bdca2023-02-17 21:08:50 +0000185def Test_object_not_set()
186 var lines =<< trim END
187 vim9script
188
189 class State
190 this.value = 'xyz'
191 endclass
192
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000193 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000194 var db = {'xyz': 789}
195 echo db[state.value]
196 END
197 v9.CheckScriptFailure(lines, 'E1360:')
198enddef
199
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000200def Test_class_member_initializer()
201 var lines =<< trim END
202 vim9script
203
204 class TextPosition
205 this.lnum: number = 1
206 this.col: number = 1
207
Bram Moolenaar418b5472022-12-20 13:38:22 +0000208 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000209 def new(lnum: number)
210 this.lnum = lnum
211 enddef
212 endclass
213
214 var pos = TextPosition.new(3)
215 assert_equal(3, pos.lnum)
216 assert_equal(1, pos.col)
217
218 var instr = execute('disassemble TextPosition.new')
219 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000220 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000221 '\d PUSHNR 1\_s*' ..
222 '\d STORE_THIS 0\_s*' ..
223 '\d PUSHNR 1\_s*' ..
224 '\d STORE_THIS 1\_s*' ..
225 'this.lnum = lnum\_s*' ..
226 '\d LOAD arg\[-1]\_s*' ..
227 '\d PUSHNR 0\_s*' ..
228 '\d LOAD $0\_s*' ..
229 '\d\+ STOREINDEX object\_s*' ..
230 '\d\+ RETURN object.*',
231 instr)
232 END
233 v9.CheckScriptSuccess(lines)
234enddef
235
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000236def Test_assignment_with_operator()
237 var lines =<< trim END
238 vim9script
239
240 class Foo
241 this.x: number
242
243 def Add(n: number)
244 this.x += n
245 enddef
246 endclass
247
248 var f = Foo.new(3)
249 f.Add(17)
250 assert_equal(20, f.x)
251 END
252 v9.CheckScriptSuccess(lines)
253enddef
254
Bram Moolenaarf4508042023-01-15 16:54:57 +0000255def Test_list_of_objects()
256 var lines =<< trim END
257 vim9script
258
259 class Foo
260 def Add()
261 enddef
262 endclass
263
264 def ProcessList(fooList: list<Foo>)
265 for foo in fooList
266 foo.Add()
267 endfor
268 enddef
269
270 var l: list<Foo> = [Foo.new()]
271 ProcessList(l)
272 END
273 v9.CheckScriptSuccess(lines)
274enddef
275
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000276def Test_expr_after_using_object()
277 var lines =<< trim END
278 vim9script
279
280 class Something
281 this.label: string = ''
282 endclass
283
284 def Foo(): Something
285 var v = Something.new()
286 echo 'in Foo(): ' .. typename(v)
287 return v
288 enddef
289
290 Foo()
291 END
292 v9.CheckScriptSuccess(lines)
293enddef
294
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000295def Test_class_default_new()
296 var lines =<< trim END
297 vim9script
298
299 class TextPosition
300 this.lnum: number = 1
301 this.col: number = 1
302 endclass
303
304 var pos = TextPosition.new()
305 assert_equal(1, pos.lnum)
306 assert_equal(1, pos.col)
307
308 pos = TextPosition.new(v:none, v:none)
309 assert_equal(1, pos.lnum)
310 assert_equal(1, pos.col)
311
312 pos = TextPosition.new(3, 22)
313 assert_equal(3, pos.lnum)
314 assert_equal(22, pos.col)
315
316 pos = TextPosition.new(v:none, 33)
317 assert_equal(1, pos.lnum)
318 assert_equal(33, pos.col)
319 END
320 v9.CheckScriptSuccess(lines)
321
322 lines =<< trim END
323 vim9script
324 class Person
325 this.name: string
326 this.age: number = 42
327 this.education: string = "unknown"
328
329 def new(this.name, this.age = v:none, this.education = v:none)
330 enddef
331 endclass
332
333 var piet = Person.new("Piet")
334 assert_equal("Piet", piet.name)
335 assert_equal(42, piet.age)
336 assert_equal("unknown", piet.education)
337
338 var chris = Person.new("Chris", 4, "none")
339 assert_equal("Chris", chris.name)
340 assert_equal(4, chris.age)
341 assert_equal("none", chris.education)
342 END
343 v9.CheckScriptSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000344
345 lines =<< trim END
346 vim9script
347 class Person
348 this.name: string
349 this.age: number = 42
350 this.education: string = "unknown"
351
352 def new(this.name, this.age = v:none, this.education = v:none)
353 enddef
354 endclass
355
356 var missing = Person.new()
357 END
358 v9.CheckScriptFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000359enddef
360
Bram Moolenaar74e12742022-12-13 21:14:28 +0000361def Test_class_object_member_inits()
362 var lines =<< trim END
363 vim9script
364 class TextPosition
365 this.lnum: number
366 this.col = 1
367 this.addcol: number = 2
368 endclass
369
370 var pos = TextPosition.new()
371 assert_equal(0, pos.lnum)
372 assert_equal(1, pos.col)
373 assert_equal(2, pos.addcol)
374 END
375 v9.CheckScriptSuccess(lines)
376
377 lines =<< trim END
378 vim9script
379 class TextPosition
380 this.lnum
381 this.col = 1
382 endclass
383 END
384 v9.CheckScriptFailure(lines, 'E1022:')
385
386 lines =<< trim END
387 vim9script
388 class TextPosition
389 this.lnum = v:none
390 this.col = 1
391 endclass
392 END
393 v9.CheckScriptFailure(lines, 'E1330:')
394enddef
395
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000396def Test_class_object_member_access()
397 var lines =<< trim END
398 vim9script
399 class Triple
400 this._one = 1
401 this.two = 2
402 public this.three = 3
403
404 def GetOne(): number
405 return this._one
406 enddef
407 endclass
408
409 var trip = Triple.new()
410 assert_equal(1, trip.GetOne())
411 assert_equal(2, trip.two)
412 assert_equal(3, trip.three)
413 assert_fails('echo trip._one', 'E1333')
414
415 assert_fails('trip._one = 11', 'E1333')
416 assert_fails('trip.two = 22', 'E1335')
417 trip.three = 33
418 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000419
420 assert_fails('trip.four = 4', 'E1334')
421 END
422 v9.CheckScriptSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000423
424 lines =<< trim END
425 vim9script
426
427 class MyCar
428 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000429 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000430
431 def new(make_arg: string)
432 this.make = make_arg
433 enddef
434
435 def GetMake(): string
436 return $"make = {this.make}"
437 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000438 def GetAge(): number
439 return this.age
440 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000441 endclass
442
443 var c = MyCar.new("abc")
444 assert_equal('make = abc', c.GetMake())
445
446 c = MyCar.new("def")
447 assert_equal('make = def', c.GetMake())
448
449 var c2 = MyCar.new("123")
450 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000451
452 def CheckCar()
453 assert_equal("make = def", c.GetMake())
454 assert_equal(5, c.GetAge())
455 enddef
456 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000457 END
458 v9.CheckScriptSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000459
460 lines =<< trim END
461 vim9script
462
463 class MyCar
464 this.make: string
465
466 def new(make_arg: string)
467 this.make = make_arg
468 enddef
469 endclass
470
471 var c = MyCar.new("abc")
472 var c = MyCar.new("def")
473 END
474 v9.CheckScriptFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000475
476 lines =<< trim END
477 vim9script
478
479 class Foo
480 this.x: list<number> = []
481
482 def Add(n: number): any
483 this.x->add(n)
484 return this
485 enddef
486 endclass
487
488 echo Foo.new().Add(1).Add(2).x
489 echo Foo.new().Add(1).Add(2)
490 .x
491 echo Foo.new().Add(1)
492 .Add(2).x
493 echo Foo.new()
494 .Add(1).Add(2).x
495 echo Foo.new()
496 .Add(1)
497 .Add(2)
498 .x
499 END
500 v9.CheckScriptSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +0000501enddef
502
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000503def Test_class_object_compare()
504 var class_lines =<< trim END
505 vim9script
506 class Item
507 this.nr = 0
508 this.name = 'xx'
509 endclass
510 END
511
512 # used at the script level and in a compiled function
513 var test_lines =<< trim END
514 var i1 = Item.new()
515 assert_equal(i1, i1)
516 assert_true(i1 is i1)
517 var i2 = Item.new()
518 assert_equal(i1, i2)
519 assert_false(i1 is i2)
520 var i3 = Item.new(0, 'xx')
521 assert_equal(i1, i3)
522
523 var io1 = Item.new(1, 'xx')
524 assert_notequal(i1, io1)
525 var io2 = Item.new(0, 'yy')
526 assert_notequal(i1, io2)
527 END
528
529 v9.CheckScriptSuccess(class_lines + test_lines)
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000530 v9.CheckScriptSuccess(
531 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000532
533 for op in ['>', '>=', '<', '<=', '=~', '!~']
534 var op_lines = [
535 'var i1 = Item.new()',
536 'var i2 = Item.new()',
537 'echo i1 ' .. op .. ' i2',
538 ]
539 v9.CheckScriptFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
Bram Moolenaar46ab9252023-01-03 14:01:21 +0000540 v9.CheckScriptFailure(class_lines
541 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +0000542 endfor
543enddef
544
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000545def Test_object_type()
546 var lines =<< trim END
547 vim9script
548
549 class One
550 this.one = 1
551 endclass
552 class Two
553 this.two = 2
554 endclass
555 class TwoMore extends Two
556 this.more = 9
557 endclass
558
559 var o: One = One.new()
560 var t: Two = Two.new()
561 var m: TwoMore = TwoMore.new()
562 var tm: Two = TwoMore.new()
563
564 t = m
565 END
566 v9.CheckScriptSuccess(lines)
567
568 lines =<< trim END
569 vim9script
570
571 class One
572 this.one = 1
573 endclass
574 class Two
575 this.two = 2
576 endclass
577
578 var o: One = Two.new()
579 END
580 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +0000581
582 lines =<< trim END
583 vim9script
584
585 interface One
586 def GetMember(): number
587 endinterface
588 class Two implements One
589 this.one = 1
590 def GetMember(): number
591 return this.one
592 enddef
593 endclass
594
595 var o: One = Two.new(5)
596 assert_equal(5, o.GetMember())
597 END
598 v9.CheckScriptSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +0000599
600 lines =<< trim END
601 vim9script
602
603 class Num
604 this.n: number = 0
605 endclass
606
607 def Ref(name: string): func(Num): Num
608 return (arg: Num): Num => {
609 return eval(name)(arg)
610 }
611 enddef
612
613 const Fn = Ref('Double')
614 var Double = (m: Num): Num => Num.new(m.n * 2)
615
616 echo Fn(Num.new(4))
617 END
618 v9.CheckScriptSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +0000619enddef
620
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000621def Test_class_member()
622 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +0000623 var lines =<< trim END
624 vim9script
625 class TextPos
626 this.lnum = 1
627 this.col = 1
628 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000629 static _secret = 7
630 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +0000631
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000632 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +0000633 counter += nr
634 enddef
635 endclass
636
637 assert_equal(0, TextPos.counter)
638 TextPos.AddToCounter(3)
639 assert_equal(3, TextPos.counter)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000640 assert_fails('echo TextPos.noSuchMember', 'E1338:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000641
Bram Moolenaar3259ff32023-01-04 18:54:09 +0000642 def GetCounter(): number
643 return TextPos.counter
644 enddef
645 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +0000646
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000647 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +0000648 assert_fails('TextPos.counter = 5', 'E1335:')
649 assert_fails('TextPos.counter += 5', 'E1335:')
650
651 assert_fails('echo TextPos._secret', 'E1333:')
652 assert_fails('TextPos._secret = 8', 'E1333:')
653
654 assert_equal(42, TextPos.anybody)
655 TextPos.anybody = 12
656 assert_equal(12, TextPos.anybody)
657 TextPos.anybody += 5
658 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000659 END
660 v9.CheckScriptSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000661
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000662 # example in the help
663 lines =<< trim END
664 vim9script
665 class OtherThing
666 this.size: number
667 static totalSize: number
668
669 def new(this.size)
670 totalSize += this.size
671 enddef
672 endclass
673 assert_equal(0, OtherThing.totalSize)
674 var to3 = OtherThing.new(3)
675 assert_equal(3, OtherThing.totalSize)
676 var to7 = OtherThing.new(7)
677 assert_equal(10, OtherThing.totalSize)
678 END
679 v9.CheckScriptSuccess(lines)
680
Bram Moolenaar62a69232023-01-24 15:07:04 +0000681 # access private member in lambda
682 lines =<< trim END
683 vim9script
684
685 class Foo
686 this._x: number = 0
687
688 def Add(n: number): number
689 const F = (): number => this._x + n
690 return F()
691 enddef
692 endclass
693
694 var foo = Foo.new()
695 assert_equal(5, foo.Add(5))
696 END
697 v9.CheckScriptSuccess(lines)
698
Bram Moolenaar6acf7572023-01-01 19:53:30 +0000699 # check shadowing
700 lines =<< trim END
701 vim9script
702
703 class Some
704 static count = 0
705 def Method(count: number)
706 echo count
707 enddef
708 endclass
709
710 var s = Some.new()
711 s.Method(7)
712 END
713 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
714
715 lines =<< trim END
716 vim9script
717
718 class Some
719 static count = 0
720 def Method(arg: number)
721 var count = 3
722 echo arg count
723 enddef
724 endclass
725
726 var s = Some.new()
727 s.Method(7)
728 END
729 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000730enddef
731
Bram Moolenaarcf760d52023-01-05 13:16:04 +0000732func Test_class_garbagecollect()
733 let lines =<< trim END
734 vim9script
735
736 class Point
737 this.p = [2, 3]
738 static pl = ['a', 'b']
739 static pd = {a: 'a', b: 'b'}
740 endclass
741
742 echo Point.pl Point.pd
743 call test_garbagecollect_now()
744 echo Point.pl Point.pd
745 END
746 call v9.CheckScriptSuccess(lines)
747endfunc
748
Bram Moolenaar6bafdd42023-01-01 12:58:33 +0000749def Test_class_function()
750 var lines =<< trim END
751 vim9script
752 class Value
753 this.value = 0
754 static objects = 0
755
756 def new(v: number)
757 this.value = v
758 ++objects
759 enddef
760
761 static def GetCount(): number
762 return objects
763 enddef
764 endclass
765
766 assert_equal(0, Value.GetCount())
767 var v1 = Value.new(2)
768 assert_equal(1, Value.GetCount())
769 var v2 = Value.new(7)
770 assert_equal(2, Value.GetCount())
771 END
772 v9.CheckScriptSuccess(lines)
773enddef
774
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +0000775def Test_class_object_to_string()
776 var lines =<< trim END
777 vim9script
778 class TextPosition
779 this.lnum = 1
780 this.col = 22
781 endclass
782
783 assert_equal("class TextPosition", string(TextPosition))
784
785 var pos = TextPosition.new()
786 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
787 END
788 v9.CheckScriptSuccess(lines)
789enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +0000790
Bram Moolenaar554d0312023-01-05 19:59:18 +0000791def Test_interface_basics()
792 var lines =<< trim END
793 vim9script
794 interface Something
795 this.value: string
796 static count: number
797 def GetCount(): number
798 endinterface
799 END
800 v9.CheckScriptSuccess(lines)
801
802 lines =<< trim END
803 interface SomethingWrong
804 static count = 7
805 endinterface
806 END
807 v9.CheckScriptFailure(lines, 'E1342:')
808
809 lines =<< trim END
810 vim9script
811
812 interface Some
813 static count: number
814 def Method(count: number)
815 endinterface
816 END
Bram Moolenaard40f00c2023-01-13 17:36:49 +0000817 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: count')
818
819 lines =<< trim END
820 vim9script
821
822 interface Some
823 this.value: number
824 def Method(value: number)
825 endinterface
826 END
827 v9.CheckScriptFailure(lines, 'E1340: Argument already declared in the class: value')
Bram Moolenaar554d0312023-01-05 19:59:18 +0000828
829 lines =<< trim END
830 vim9script
831 interface somethingWrong
832 static count = 7
833 endinterface
834 END
835 v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
836
837 lines =<< trim END
838 vim9script
839 interface SomethingWrong
840 this.value: string
841 static count = 7
842 def GetCount(): number
843 endinterface
844 END
845 v9.CheckScriptFailure(lines, 'E1344:')
846
847 lines =<< trim END
848 vim9script
849 interface SomethingWrong
850 this.value: string
851 static count: number
852 def GetCount(): number
853 return 5
854 enddef
855 endinterface
856 END
857 v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +0000858
859 lines =<< trim END
860 vim9script
861 export interface EnterExit
862 def Enter(): void
863 def Exit(): void
864 endinterface
865 END
866 writefile(lines, 'XdefIntf.vim', 'D')
867
868 lines =<< trim END
869 vim9script
870 import './XdefIntf.vim' as defIntf
871 export def With(ee: defIntf.EnterExit, F: func)
872 ee.Enter()
873 try
874 F()
875 finally
876 ee.Exit()
877 endtry
878 enddef
879 END
880 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000881
882 var imported =<< trim END
883 vim9script
884 export abstract class EnterExit
885 def Enter(): void
886 enddef
887 def Exit(): void
888 enddef
889 endclass
890 END
891 writefile(imported, 'XdefIntf2.vim', 'D')
892
893 lines[1] = " import './XdefIntf2.vim' as defIntf"
894 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +0000895enddef
896
Bram Moolenaar94674f22023-01-06 18:42:20 +0000897def Test_class_implements_interface()
898 var lines =<< trim END
899 vim9script
900
901 interface Some
902 static count: number
903 def Method(nr: number)
904 endinterface
905
906 class SomeImpl implements Some
907 static count: number
908 def Method(nr: number)
909 echo nr
910 enddef
911 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +0000912
913 interface Another
914 this.member: string
915 endinterface
916
917 class SomeImpl implements Some, Another
918 this.member = 'abc'
919 static count: number
920 def Method(nr: number)
921 echo nr
922 enddef
923 endclass
924
Bram Moolenaar94674f22023-01-06 18:42:20 +0000925 END
926 v9.CheckScriptSuccess(lines)
927
928 lines =<< trim END
929 vim9script
930
931 interface Some
932 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +0000933 endinterface
934
935 class SomeImpl implements Some implements Some
936 static count: number
937 endclass
938 END
939 v9.CheckScriptFailure(lines, 'E1350:')
940
941 lines =<< trim END
942 vim9script
943
944 interface Some
945 static counter: number
946 endinterface
947
948 class SomeImpl implements Some, Some
949 static count: number
950 endclass
951 END
952 v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
953
954 lines =<< trim END
955 vim9script
956
957 interface Some
958 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +0000959 def Method(nr: number)
960 endinterface
961
962 class SomeImpl implements Some
963 static count: number
964 def Method(nr: number)
965 echo nr
966 enddef
967 endclass
968 END
969 v9.CheckScriptFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
970
971 lines =<< trim END
972 vim9script
973
974 interface Some
975 static count: number
976 def Methods(nr: number)
977 endinterface
978
979 class SomeImpl implements Some
980 static count: number
981 def Method(nr: number)
982 echo nr
983 enddef
984 endclass
985 END
986 v9.CheckScriptFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +0000987
988 # Check different order of members in class and interface works.
989 lines =<< trim END
990 vim9script
991
992 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +0000993 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +0000994 this.errpos: number
995 endinterface
996
997 # order of members is opposite of interface
998 class Failure implements Result
999 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001000 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001001 endclass
1002
1003 def Test()
1004 var result: Result = Failure.new()
1005
1006 assert_equal('label', result.label)
1007 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001008
1009 result.label = 'different'
1010 assert_equal('different', result.label)
1011 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001012 enddef
1013
1014 Test()
1015 END
1016 v9.CheckScriptSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00001017enddef
1018
Bram Moolenaard0200c82023-01-28 15:19:40 +00001019def Test_call_interface_method()
1020 var lines =<< trim END
1021 vim9script
1022 interface Base
1023 def Enter(): void
1024 endinterface
1025
1026 class Child implements Base
1027 def Enter(): void
1028 g:result ..= 'child'
1029 enddef
1030 endclass
1031
1032 def F(obj: Base)
1033 obj.Enter()
1034 enddef
1035
1036 g:result = ''
1037 F(Child.new())
1038 assert_equal('child', g:result)
1039 unlet g:result
1040 END
1041 v9.CheckScriptSuccess(lines)
1042
1043 lines =<< trim END
1044 vim9script
1045 class Base
1046 def Enter(): void
1047 g:result ..= 'base'
1048 enddef
1049 endclass
1050
1051 class Child extends Base
1052 def Enter(): void
1053 g:result ..= 'child'
1054 enddef
1055 endclass
1056
1057 def F(obj: Base)
1058 obj.Enter()
1059 enddef
1060
1061 g:result = ''
1062 F(Child.new())
1063 assert_equal('child', g:result)
1064 unlet g:result
1065 END
1066 v9.CheckScriptSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001067
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00001068 # method of interface returns a value
1069 lines =<< trim END
1070 vim9script
1071 interface Base
1072 def Enter(): string
1073 endinterface
1074
1075 class Child implements Base
1076 def Enter(): string
1077 g:result ..= 'child'
1078 return "/resource"
1079 enddef
1080 endclass
1081
1082 def F(obj: Base)
1083 var r = obj.Enter()
1084 g:result ..= r
1085 enddef
1086
1087 g:result = ''
1088 F(Child.new())
1089 assert_equal('child/resource', g:result)
1090 unlet g:result
1091 END
1092 v9.CheckScriptSuccess(lines)
1093
1094 lines =<< trim END
1095 vim9script
1096 class Base
1097 def Enter(): string
1098 return null_string
1099 enddef
1100 endclass
1101
1102 class Child extends Base
1103 def Enter(): string
1104 g:result ..= 'child'
1105 return "/resource"
1106 enddef
1107 endclass
1108
1109 def F(obj: Base)
1110 var r = obj.Enter()
1111 g:result ..= r
1112 enddef
1113
1114 g:result = ''
1115 F(Child.new())
1116 assert_equal('child/resource', g:result)
1117 unlet g:result
1118 END
1119 v9.CheckScriptSuccess(lines)
1120
1121
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00001122 # No class that implements the interface.
1123 lines =<< trim END
1124 vim9script
1125
1126 interface IWithEE
1127 def Enter(): any
1128 def Exit(): void
1129 endinterface
1130
1131 def With1(ee: IWithEE, F: func)
1132 var r = ee.Enter()
1133 enddef
1134
1135 defcompile
1136 END
1137 v9.CheckScriptSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00001138enddef
1139
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001140def Test_class_used_as_type()
1141 var lines =<< trim END
1142 vim9script
1143
1144 class Point
1145 this.x = 0
1146 this.y = 0
1147 endclass
1148
1149 var p: Point
1150 p = Point.new(2, 33)
1151 assert_equal(2, p.x)
1152 assert_equal(33, p.y)
1153 END
1154 v9.CheckScriptSuccess(lines)
1155
1156 lines =<< trim END
1157 vim9script
1158
1159 interface HasX
1160 this.x: number
1161 endinterface
1162
1163 class Point implements HasX
1164 this.x = 0
1165 this.y = 0
1166 endclass
1167
1168 var p: Point
1169 p = Point.new(2, 33)
1170 var hx = p
1171 assert_equal(2, hx.x)
1172 END
1173 v9.CheckScriptSuccess(lines)
1174
1175 lines =<< trim END
1176 vim9script
1177
1178 class Point
1179 this.x = 0
1180 this.y = 0
1181 endclass
1182
1183 var p: Point
1184 p = 'text'
1185 END
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001186 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00001187enddef
1188
Bram Moolenaar83677162023-01-08 19:54:10 +00001189def Test_class_extends()
1190 var lines =<< trim END
1191 vim9script
1192 class Base
1193 this.one = 1
1194 def GetOne(): number
1195 return this.one
1196 enddef
1197 endclass
1198 class Child extends Base
1199 this.two = 2
1200 def GetTotal(): number
1201 return this.one + this.two
1202 enddef
1203 endclass
1204 var o = Child.new()
1205 assert_equal(1, o.one)
1206 assert_equal(2, o.two)
1207 assert_equal(1, o.GetOne())
1208 assert_equal(3, o.GetTotal())
1209 END
1210 v9.CheckScriptSuccess(lines)
1211
1212 lines =<< trim END
1213 vim9script
1214 class Base
1215 this.one = 1
1216 endclass
1217 class Child extends Base
1218 this.two = 2
1219 endclass
1220 var o = Child.new(3, 44)
1221 assert_equal(3, o.one)
1222 assert_equal(44, o.two)
1223 END
1224 v9.CheckScriptSuccess(lines)
1225
1226 lines =<< trim END
1227 vim9script
1228 class Base
1229 this.one = 1
1230 endclass
1231 class Child extends Base extends Base
1232 this.two = 2
1233 endclass
1234 END
1235 v9.CheckScriptFailure(lines, 'E1352: Duplicate "extends"')
1236
1237 lines =<< trim END
1238 vim9script
1239 class Child extends BaseClass
1240 this.two = 2
1241 endclass
1242 END
1243 v9.CheckScriptFailure(lines, 'E1353: Class name not found: BaseClass')
1244
1245 lines =<< trim END
1246 vim9script
1247 var SomeVar = 99
1248 class Child extends SomeVar
1249 this.two = 2
1250 endclass
1251 END
1252 v9.CheckScriptFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00001253
1254 lines =<< trim END
1255 vim9script
1256 class Base
1257 this.name: string
1258 def ToString(): string
1259 return this.name
1260 enddef
1261 endclass
1262
1263 class Child extends Base
1264 this.age: number
1265 def ToString(): string
1266 return super.ToString() .. ': ' .. this.age
1267 enddef
1268 endclass
1269
1270 var o = Child.new('John', 42)
1271 assert_equal('John: 42', o.ToString())
1272 END
1273 v9.CheckScriptSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00001274
1275 lines =<< trim END
1276 vim9script
1277 class Child
1278 this.age: number
1279 def ToString(): number
1280 return this.age
1281 enddef
1282 def ToString(): string
1283 return this.age
1284 enddef
1285 endclass
1286 END
1287 v9.CheckScriptFailure(lines, 'E1355: Duplicate function: ToString')
1288
1289 lines =<< trim END
1290 vim9script
1291 class Child
1292 this.age: number
1293 def ToString(): string
1294 return super .ToString() .. ': ' .. this.age
1295 enddef
1296 endclass
1297 var o = Child.new(42)
1298 echo o.ToString()
1299 END
1300 v9.CheckScriptFailure(lines, 'E1356:')
1301
1302 lines =<< trim END
1303 vim9script
1304 class Base
1305 this.name: string
1306 def ToString(): string
1307 return this.name
1308 enddef
1309 endclass
1310
1311 var age = 42
1312 def ToString(): string
1313 return super.ToString() .. ': ' .. age
1314 enddef
1315 echo ToString()
1316 END
1317 v9.CheckScriptFailure(lines, 'E1357:')
1318
1319 lines =<< trim END
1320 vim9script
1321 class Child
1322 this.age: number
1323 def ToString(): string
1324 return super.ToString() .. ': ' .. this.age
1325 enddef
1326 endclass
1327 var o = Child.new(42)
1328 echo o.ToString()
1329 END
1330 v9.CheckScriptFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001331
1332 lines =<< trim END
1333 vim9script
1334 class Base
1335 this.name: string
1336 static def ToString(): string
1337 return 'Base class'
1338 enddef
1339 endclass
1340
1341 class Child extends Base
1342 this.age: number
1343 def ToString(): string
1344 return Base.ToString() .. ': ' .. this.age
1345 enddef
1346 endclass
1347
1348 var o = Child.new('John', 42)
1349 assert_equal('Base class: 42', o.ToString())
1350 END
1351 v9.CheckScriptSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001352
1353 lines =<< trim END
1354 vim9script
1355 class Base
1356 this.value = 1
1357 def new(init: number)
1358 this.value = number + 1
1359 enddef
1360 endclass
1361 class Child extends Base
1362 def new()
1363 this.new(3)
1364 enddef
1365 endclass
1366 var c = Child.new()
1367 END
1368 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Child": new(')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00001369
1370 # base class with more than one object member
1371 lines =<< trim END
1372 vim9script
1373
1374 class Result
1375 this.success: bool
1376 this.value: any = null
1377 endclass
1378
1379 class Success extends Result
1380 def new(this.value = v:none)
1381 this.success = true
1382 enddef
1383 endclass
1384
1385 var v = Success.new('asdf')
1386 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
1387 END
1388 v9.CheckScriptSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00001389enddef
1390
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00001391def Test_using_base_class()
1392 var lines =<< trim END
1393 vim9script
1394
1395 class BaseEE
1396 def Enter(): any
1397 return null
1398 enddef
1399 def Exit(resource: any): void
1400 enddef
1401 endclass
1402
1403 class ChildEE extends BaseEE
1404 def Enter(): any
1405 return 42
1406 enddef
1407
1408 def Exit(resource: number): void
1409 g:result ..= '/exit'
1410 enddef
1411 endclass
1412
1413 def With(ee: BaseEE)
1414 var r = ee.Enter()
1415 try
1416 g:result ..= r
1417 finally
1418 g:result ..= '/finally'
1419 ee.Exit(r)
1420 endtry
1421 enddef
1422
1423 g:result = ''
1424 With(ChildEE.new())
1425 assert_equal('42/finally/exit', g:result)
1426 END
1427 v9.CheckScriptSuccess(lines)
1428 unlet g:result
1429enddef
1430
1431
Bram Moolenaara86655a2023-01-12 17:06:27 +00001432def Test_class_import()
1433 var lines =<< trim END
1434 vim9script
1435 export class Animal
1436 this.kind: string
1437 this.name: string
1438 endclass
1439 END
1440 writefile(lines, 'Xanimal.vim', 'D')
1441
1442 lines =<< trim END
1443 vim9script
1444 import './Xanimal.vim' as animal
1445
1446 var a: animal.Animal
1447 a = animal.Animal.new('fish', 'Eric')
1448 assert_equal('fish', a.kind)
1449 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00001450
1451 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
1452 assert_equal('cat', b.kind)
1453 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00001454 END
1455 v9.CheckScriptSuccess(lines)
1456enddef
1457
Bram Moolenaar24a8d062023-01-14 13:12:06 +00001458def Test_abstract_class()
1459 var lines =<< trim END
1460 vim9script
1461 abstract class Base
1462 this.name: string
1463 endclass
1464 class Person extends Base
1465 this.age: number
1466 endclass
1467 var p: Base = Person.new('Peter', 42)
1468 assert_equal('Peter', p.name)
1469 assert_equal(42, p.age)
1470 END
1471 v9.CheckScriptSuccess(lines)
1472
1473 lines =<< trim END
1474 vim9script
1475 abstract class Base
1476 this.name: string
1477 endclass
1478 class Person extends Base
1479 this.age: number
1480 endclass
1481 var p = Base.new('Peter')
1482 END
1483 v9.CheckScriptFailure(lines, 'E1325: Method not found on class "Base": new(')
1484
1485 lines =<< trim END
1486 abstract class Base
1487 this.name: string
1488 endclass
1489 END
1490 v9.CheckScriptFailure(lines, 'E1316:')
1491enddef
1492
Bram Moolenaar486fc252023-01-18 14:51:07 +00001493def Test_closure_in_class()
1494 var lines =<< trim END
1495 vim9script
1496
1497 class Foo
1498 this.y: list<string> = ['B']
1499
1500 def new()
1501 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
1502 enddef
1503 endclass
1504
1505 Foo.new()
1506 assert_equal(['A'], g:result)
1507 END
1508 v9.CheckScriptSuccess(lines)
1509enddef
1510
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001511def Test_defer_with_object()
1512 var lines =<< trim END
1513 vim9script
1514
1515 class CWithEE
1516 def Enter()
1517 g:result ..= "entered/"
1518 enddef
1519 def Exit()
1520 g:result ..= "exited"
1521 enddef
1522 endclass
1523
1524 def With(ee: CWithEE, F: func)
1525 ee.Enter()
1526 defer ee.Exit()
1527 F()
1528 enddef
1529
1530 g:result = ''
1531 var obj = CWithEE.new()
1532 obj->With(() => {
1533 g:result ..= "called/"
1534 })
1535 assert_equal('entered/called/exited', g:result)
1536 END
1537 v9.CheckScriptSuccess(lines)
1538 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00001539
1540 lines =<< trim END
1541 vim9script
1542
1543 class BaseWithEE
1544 def Enter()
1545 g:result ..= "entered-base/"
1546 enddef
1547 def Exit()
1548 g:result ..= "exited-base"
1549 enddef
1550 endclass
1551
1552 class CWithEE extends BaseWithEE
1553 def Enter()
1554 g:result ..= "entered-child/"
1555 enddef
1556 def Exit()
1557 g:result ..= "exited-child"
1558 enddef
1559 endclass
1560
1561 def With(ee: BaseWithEE, F: func)
1562 ee.Enter()
1563 defer ee.Exit()
1564 F()
1565 enddef
1566
1567 g:result = ''
1568 var obj = CWithEE.new()
1569 obj->With(() => {
1570 g:result ..= "called/"
1571 })
1572 assert_equal('entered-child/called/exited-child', g:result)
1573 END
1574 v9.CheckScriptSuccess(lines)
1575 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00001576enddef
1577
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001578
1579" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker