blob: 5e3b9455914bbc6bc58a57a18a48b9e9ebc745d2 [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
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020011 v9.CheckSourceFailure(lines, 'E1316:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000012
13 lines =<< trim END
14 vim9script
15 class notWorking
16 endclass
17 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020018 v9.CheckSourceFailure(lines, 'E1314:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000019
20 lines =<< trim END
21 vim9script
22 class Not@working
23 endclass
24 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020025 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000026
27 lines =<< trim END
28 vim9script
29 abstract noclass Something
30 endclass
31 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020032 v9.CheckSourceFailure(lines, 'E475:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000033
34 lines =<< trim END
35 vim9script
36 abstract classy Something
37 endclass
38 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020039 v9.CheckSourceFailure(lines, 'E475:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000040
41 lines =<< trim END
42 vim9script
43 class Something
44 endcl
45 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020046 v9.CheckSourceFailure(lines, 'E1065:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000047
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
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020053 v9.CheckSourceFailure(lines, 'E488:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000054
55 lines =<< trim END
56 vim9script
57 class Something
58 endclass | echo 'done'
59 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020060 v9.CheckSourceFailure(lines, 'E488:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000061
62 lines =<< trim END
63 vim9script
64 class Something
65 this
66 endclass
67 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020068 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000069
70 lines =<< trim END
71 vim9script
72 class Something
73 this.
74 endclass
75 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020076 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000077
78 lines =<< trim END
79 vim9script
80 class Something
81 this .count
82 endclass
83 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020084 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000085
86 lines =<< trim END
87 vim9script
88 class Something
89 this. count
90 endclass
91 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020092 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000093
94 lines =<< trim END
95 vim9script
96 class Something
97 this.count: number
98 that.count
99 endclass
100 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200101 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000102
103 lines =<< trim END
104 vim9script
105 class Something
106 this.count
107 endclass
108 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200109 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000110
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
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200120 v9.CheckSourceFailure(lines, 'E1089:')
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000121
122 lines =<< trim END
123 vim9script
124 class Something
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000125 this.count : number
126 endclass
127 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200128 v9.CheckSourceFailure(lines, 'E1059:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000129
130 lines =<< trim END
131 vim9script
132 class Something
133 this.count:number
134 endclass
135 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200136 v9.CheckSourceFailure(lines, 'E1069:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000137
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200138 # Test for unsupported comment specifier
139 lines =<< trim END
140 vim9script
141 class Something
142 # comment
143 #{
144 endclass
145 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200146 v9.CheckSourceFailure(lines, 'E1170:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200147
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200148 # Test for using class as a bool
149 lines =<< trim END
150 vim9script
151 class A
152 endclass
153 if A
154 endif
155 END
156 v9.CheckSourceFailure(lines, 'E1319: Using a class as a Number')
157
158 # Test for using object as a bool
159 lines =<< trim END
160 vim9script
161 class A
162 endclass
163 var a = A.new()
164 if a
165 endif
166 END
167 v9.CheckSourceFailure(lines, 'E1320: Using an object as a Number')
168
169 # Test for using class as a float
170 lines =<< trim END
171 vim9script
172 class A
173 endclass
174 sort([1.1, A], 'f')
175 END
176 v9.CheckSourceFailure(lines, 'E1321: Using a class as a Float')
177
178 # Test for using object as a float
179 lines =<< trim END
180 vim9script
181 class A
182 endclass
183 var a = A.new()
184 sort([1.1, a], 'f')
185 END
186 v9.CheckSourceFailure(lines, 'E1322: Using an object as a Float')
187
188 # Test for using class as a string
189 lines =<< trim END
190 vim9script
191 class A
192 endclass
193 :exe 'call ' .. A
194 END
195 v9.CheckSourceFailure(lines, 'E1323: Using a class as a String')
196
197 # Test for using object as a string
198 lines =<< trim END
199 vim9script
200 class A
201 endclass
202 var a = A.new()
203 :exe 'call ' .. a
204 END
205 v9.CheckSourceFailure(lines, 'E1324: Using an object as a String')
206
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000207 lines =<< trim END
208 vim9script
209
210 class TextPosition
211 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000212 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000213
Bram Moolenaar418b5472022-12-20 13:38:22 +0000214 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000215 def ToString(): string
216 return $'({this.lnum}, {this.col})'
217 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000218 endclass
219
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000220 # use the automatically generated new() method
221 var pos = TextPosition.new(2, 12)
222 assert_equal(2, pos.lnum)
223 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000224
225 # call an object method
226 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000227
228 assert_equal(v:t_class, type(TextPosition))
229 assert_equal(v:t_object, type(pos))
230 assert_equal('class<TextPosition>', typename(TextPosition))
231 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000232 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200233 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200234
235 # When referencing object methods, space cannot be used after a "."
236 lines =<< trim END
237 vim9script
238 class A
239 def Foo(): number
240 return 10
241 enddef
242 endclass
243 var a = A.new()
244 var v = a. Foo()
245 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200246 v9.CheckSourceFailure(lines, 'E1202:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200247
248 # Using an object without specifying a method or a member variable
249 lines =<< trim END
250 vim9script
251 class A
252 def Foo(): number
253 return 10
254 enddef
255 endclass
256 var a = A.new()
257 var v = a.
258 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200259 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200260
261 # Error when parsing the arguments of an object method.
262 lines =<< trim END
263 vim9script
264 class A
265 def Foo()
266 enddef
267 endclass
268 var a = A.new()
269 var v = a.Foo(,)
270 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200271 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200272
273 lines =<< trim END
274 vim9script
275 class A
276 this.y = {
277 X: 1
278 }
279 endclass
280 var a = A.new()
281 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200282 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000283enddef
284
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000285def Test_class_defined_twice()
286 # class defined twice should fail
287 var lines =<< trim END
288 vim9script
289 class There
290 endclass
291 class There
292 endclass
293 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200294 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"')
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000295
296 # one class, reload same script twice is OK
297 lines =<< trim END
298 vim9script
299 class There
300 endclass
301 END
302 writefile(lines, 'XclassTwice.vim', 'D')
303 source XclassTwice.vim
304 source XclassTwice.vim
305enddef
306
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000307def Test_returning_null_object()
308 # this was causing an internal error
309 var lines =<< trim END
310 vim9script
311
312 class BufferList
313 def Current(): any
314 return null_object
315 enddef
316 endclass
317
318 var buffers = BufferList.new()
319 echo buffers.Current()
320 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200321 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000322enddef
323
Bram Moolenaard13dd302023-03-11 20:56:35 +0000324def Test_using_null_class()
325 var lines =<< trim END
326 @_ = null_class.member
327 END
328 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
329enddef
330
Bram Moolenaar657aea72023-01-27 13:16:19 +0000331def Test_class_interface_wrong_end()
332 var lines =<< trim END
333 vim9script
334 abstract class SomeName
335 this.member = 'text'
336 endinterface
337 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200338 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000339
340 lines =<< trim END
341 vim9script
342 export interface AnotherName
343 this.member: string
344 endclass
345 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200346 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000347enddef
348
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000349def Test_object_not_set()
350 var lines =<< trim END
351 vim9script
352
353 class State
354 this.value = 'xyz'
355 endclass
356
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000357 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000358 var db = {'xyz': 789}
359 echo db[state.value]
360 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200361 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000362
363 lines =<< trim END
364 vim9script
365
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000366 class Class
367 this.id: string
368 def Method1()
369 echo 'Method1' .. this.id
370 enddef
371 endclass
372
373 var obj: Class
374 def Func()
375 obj.Method1()
376 enddef
377 Func()
378 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200379 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000380
381 lines =<< trim END
382 vim9script
383
Bram Moolenaar0917e862023-02-18 14:42:44 +0000384 class Background
385 this.background = 'dark'
386 endclass
387
388 class Colorscheme
389 this._bg: Background
390
391 def GetBackground(): string
392 return this._bg.background
393 enddef
394 endclass
395
396 var bg: Background # UNINITIALIZED
397 echo Colorscheme.new(bg).GetBackground()
398 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200399 v9.CheckSourceFailure(lines, 'E1360:')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000400
401 # TODO: this should not give an error but be handled at runtime
402 lines =<< trim END
403 vim9script
404
405 class Class
406 this.id: string
407 def Method1()
408 echo 'Method1' .. this.id
409 enddef
410 endclass
411
412 var obj = null_object
413 def Func()
414 obj.Method1()
415 enddef
416 Func()
417 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200418 v9.CheckSourceFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000419enddef
420
Ernie Rael5c018be2023-08-27 18:40:26 +0200421def Test_null_object_assign_compare()
422 var lines =<< trim END
423 vim9script
424
425 var nullo = null_object
426 def F(): any
427 return nullo
428 enddef
429 assert_equal('object<Unknown>', typename(F()))
430
431 var o0 = F()
432 assert_true(o0 == null_object)
433 assert_true(o0 == null)
434
435 var o1: any = nullo
436 assert_true(o1 == null_object)
437 assert_true(o1 == null)
438
439 def G()
440 var x = null_object
441 enddef
442
443 class C
444 endclass
445 var o2: C
446 assert_true(o2 == null_object)
447 assert_true(o2 == null)
448
449 o2 = null_object
450 assert_true(o2 == null)
451
452 o2 = C.new()
453 assert_true(o2 != null)
454
455 o2 = null_object
456 assert_true(o2 == null)
457 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200458 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200459enddef
460
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000461def Test_class_member_initializer()
462 var lines =<< trim END
463 vim9script
464
465 class TextPosition
466 this.lnum: number = 1
467 this.col: number = 1
468
Bram Moolenaar418b5472022-12-20 13:38:22 +0000469 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000470 def new(lnum: number)
471 this.lnum = lnum
472 enddef
473 endclass
474
475 var pos = TextPosition.new(3)
476 assert_equal(3, pos.lnum)
477 assert_equal(1, pos.col)
478
479 var instr = execute('disassemble TextPosition.new')
480 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000481 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000482 '\d PUSHNR 1\_s*' ..
483 '\d STORE_THIS 0\_s*' ..
484 '\d PUSHNR 1\_s*' ..
485 '\d STORE_THIS 1\_s*' ..
486 'this.lnum = lnum\_s*' ..
487 '\d LOAD arg\[-1]\_s*' ..
488 '\d PUSHNR 0\_s*' ..
489 '\d LOAD $0\_s*' ..
490 '\d\+ STOREINDEX object\_s*' ..
491 '\d\+ RETURN object.*',
492 instr)
493 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200494 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000495enddef
496
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000497def Test_member_any_used_as_object()
498 var lines =<< trim END
499 vim9script
500
501 class Inner
502 this.value: number = 0
503 endclass
504
505 class Outer
506 this.inner: any
507 endclass
508
509 def F(outer: Outer)
510 outer.inner.value = 1
511 enddef
512
513 var inner_obj = Inner.new(0)
514 var outer_obj = Outer.new(inner_obj)
515 F(outer_obj)
516 assert_equal(1, inner_obj.value)
517 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200518 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000519
520 lines =<< trim END
521 vim9script
522
523 class Inner
524 this.value: number = 0
525 endclass
526
527 class Outer
528 this.inner: Inner
529 endclass
530
531 def F(outer: Outer)
532 outer.inner.value = 1
533 enddef
534
535 def Test_assign_to_nested_typed_member()
536 var inner = Inner.new(0)
537 var outer = Outer.new(inner)
538 F(outer)
539 assert_equal(1, inner.value)
540 enddef
541
542 Test_assign_to_nested_typed_member()
543 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200544 v9.CheckSourceSuccess(lines)
545
546 # Try modifying a private variable using an "any" object
547 lines =<< trim END
548 vim9script
549
550 class Inner
551 this._value: string = ''
552 endclass
553
554 class Outer
555 this.inner: any
556 endclass
557
558 def F(outer: Outer)
559 outer.inner._value = 'b'
560 enddef
561
562 var inner_obj = Inner.new('a')
563 var outer_obj = Outer.new(inner_obj)
564 F(outer_obj)
565 END
566 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _value')
567
568 # Try modifying a non-existing variable using an "any" object
569 lines =<< trim END
570 vim9script
571
572 class Inner
573 this.value: string = ''
574 endclass
575
576 class Outer
577 this.inner: any
578 endclass
579
580 def F(outer: Outer)
581 outer.inner.someval = 'b'
582 enddef
583
584 var inner_obj = Inner.new('a')
585 var outer_obj = Outer.new(inner_obj)
586 F(outer_obj)
587 END
588 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Inner": someval')
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000589enddef
590
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000591def Test_assignment_with_operator()
592 var lines =<< trim END
593 vim9script
594
595 class Foo
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200596 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000597
598 def Add(n: number)
599 this.x += n
600 enddef
601 endclass
602
603 var f = Foo.new(3)
604 f.Add(17)
605 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100606
607 def AddToFoo(obj: Foo)
608 obj.x += 3
609 enddef
610
611 AddToFoo(f)
612 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000613 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200614 v9.CheckSourceSuccess(lines)
Ernie Rael18143d32023-09-04 22:30:41 +0200615
616 # do the same thing, but through an interface
617 lines =<< trim END
618 vim9script
619
620 interface I
621 public this.x: number
622 endinterface
623
624 class Foo implements I
625 public this.x: number
626
627 def Add(n: number)
628 var i: I = this
629 i.x += n
630 enddef
631 endclass
632
633 var f = Foo.new(3)
634 f.Add(17)
635 assert_equal(20, f.x)
636
637 def AddToFoo(i: I)
638 i.x += 3
639 enddef
640
641 AddToFoo(f)
642 assert_equal(23, f.x)
643 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200644 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000645enddef
646
Bram Moolenaarf4508042023-01-15 16:54:57 +0000647def Test_list_of_objects()
648 var lines =<< trim END
649 vim9script
650
651 class Foo
652 def Add()
653 enddef
654 endclass
655
656 def ProcessList(fooList: list<Foo>)
657 for foo in fooList
658 foo.Add()
659 endfor
660 enddef
661
662 var l: list<Foo> = [Foo.new()]
663 ProcessList(l)
664 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200665 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000666enddef
667
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000668def Test_expr_after_using_object()
669 var lines =<< trim END
670 vim9script
671
672 class Something
673 this.label: string = ''
674 endclass
675
676 def Foo(): Something
677 var v = Something.new()
678 echo 'in Foo(): ' .. typename(v)
679 return v
680 enddef
681
682 Foo()
683 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200684 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000685enddef
686
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000687def Test_class_default_new()
688 var lines =<< trim END
689 vim9script
690
691 class TextPosition
692 this.lnum: number = 1
693 this.col: number = 1
694 endclass
695
696 var pos = TextPosition.new()
697 assert_equal(1, pos.lnum)
698 assert_equal(1, pos.col)
699
700 pos = TextPosition.new(v:none, v:none)
701 assert_equal(1, pos.lnum)
702 assert_equal(1, pos.col)
703
704 pos = TextPosition.new(3, 22)
705 assert_equal(3, pos.lnum)
706 assert_equal(22, pos.col)
707
708 pos = TextPosition.new(v:none, 33)
709 assert_equal(1, pos.lnum)
710 assert_equal(33, pos.col)
711 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200712 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000713
714 lines =<< trim END
715 vim9script
716 class Person
717 this.name: string
718 this.age: number = 42
719 this.education: string = "unknown"
720
721 def new(this.name, this.age = v:none, this.education = v:none)
722 enddef
723 endclass
724
725 var piet = Person.new("Piet")
726 assert_equal("Piet", piet.name)
727 assert_equal(42, piet.age)
728 assert_equal("unknown", piet.education)
729
730 var chris = Person.new("Chris", 4, "none")
731 assert_equal("Chris", chris.name)
732 assert_equal(4, chris.age)
733 assert_equal("none", chris.education)
734 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200735 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000736
737 lines =<< trim END
738 vim9script
739 class Person
740 this.name: string
741 this.age: number = 42
742 this.education: string = "unknown"
743
744 def new(this.name, this.age = v:none, this.education = v:none)
745 enddef
746 endclass
747
748 var missing = Person.new()
749 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200750 v9.CheckSourceFailure(lines, 'E119:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200751
752 # Using a specific value to initialize an instance variable in the new()
753 # method.
754 lines =<< trim END
755 vim9script
756 class A
757 this.val: string
758 def new(this.val = 'a')
759 enddef
760 endclass
761 END
762 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'")
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000763enddef
764
h-east2261c892023-08-16 21:49:54 +0900765
766def Test_class_new_with_object_member()
767 var lines =<< trim END
768 vim9script
769
770 class C
771 this.str: string
772 this.num: number
773 def new(this.str, this.num)
774 enddef
775 def newVals(this.str, this.num)
776 enddef
777 endclass
778
779 def Check()
780 try
781 var c = C.new('cats', 2)
782 assert_equal('cats', c.str)
783 assert_equal(2, c.num)
784
785 c = C.newVals('dogs', 4)
786 assert_equal('dogs', c.str)
787 assert_equal(4, c.num)
788 catch
789 assert_report($'Unexpected exception was caught: {v:exception}')
790 endtry
791 enddef
792
793 Check()
794 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200795 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900796
797 lines =<< trim END
798 vim9script
799
800 class C
801 this.str: string
802 this.num: number
803 def new(this.str, this.num)
804 enddef
805 endclass
806
807 def Check()
808 try
809 var c = C.new(1, 2)
810 catch
811 assert_report($'Unexpected exception was caught: {v:exception}')
812 endtry
813 enddef
814
815 Check()
816 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200817 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900818
819 lines =<< trim END
820 vim9script
821
822 class C
823 this.str: string
824 this.num: number
825 def newVals(this.str, this.num)
826 enddef
827 endclass
828
829 def Check()
830 try
831 var c = C.newVals('dogs', 'apes')
832 catch
833 assert_report($'Unexpected exception was caught: {v:exception}')
834 endtry
835 enddef
836
837 Check()
838 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200839 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900840enddef
841
Bram Moolenaar74e12742022-12-13 21:14:28 +0000842def Test_class_object_member_inits()
843 var lines =<< trim END
844 vim9script
845 class TextPosition
846 this.lnum: number
847 this.col = 1
848 this.addcol: number = 2
849 endclass
850
851 var pos = TextPosition.new()
852 assert_equal(0, pos.lnum)
853 assert_equal(1, pos.col)
854 assert_equal(2, pos.addcol)
855 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200856 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000857
858 lines =<< trim END
859 vim9script
860 class TextPosition
861 this.lnum
862 this.col = 1
863 endclass
864 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200865 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000866
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200867 # If the type is not specified for a member, then it should be set during
868 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000869 lines =<< trim END
870 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200871
872 var init_count = 0
873 def Init(): string
874 init_count += 1
875 return 'foo'
876 enddef
877
878 class A
879 this.str1 = Init()
880 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000881 this.col = 1
882 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200883
884 assert_equal(init_count, 0)
885 var a = A.new()
886 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000887 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200888 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200889
890 # Test for initializing an object member with an unknown variable/type
891 lines =<< trim END
892 vim9script
893 class A
894 this.value = init_val
895 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200896 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200897 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200898 v9.CheckSourceFailure(lines, 'E1001:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200899
900 # Test for initializing an object member with an special type
901 lines =<< trim END
902 vim9script
903 class A
904 this.value: void
905 endclass
906 END
907 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object member: void')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000908enddef
909
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200910" Test for instance variable access
911def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000912 var lines =<< trim END
913 vim9script
914 class Triple
915 this._one = 1
916 this.two = 2
917 public this.three = 3
918
919 def GetOne(): number
920 return this._one
921 enddef
922 endclass
923
924 var trip = Triple.new()
925 assert_equal(1, trip.GetOne())
926 assert_equal(2, trip.two)
927 assert_equal(3, trip.three)
928 assert_fails('echo trip._one', 'E1333')
929
930 assert_fails('trip._one = 11', 'E1333')
931 assert_fails('trip.two = 22', 'E1335')
932 trip.three = 33
933 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000934
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200935 assert_fails('trip.four = 4', 'E1326')
Bram Moolenaard505d172022-12-18 21:42:55 +0000936 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200937 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000938
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200939 # Test for a public member variable name beginning with an underscore
940 lines =<< trim END
941 vim9script
942 class A
943 public this._val = 10
944 endclass
945 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200946 v9.CheckSourceFailure(lines, 'E1332:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200947
Bram Moolenaar590162c2022-12-24 21:24:06 +0000948 lines =<< trim END
949 vim9script
950
951 class MyCar
952 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000953 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000954
955 def new(make_arg: string)
956 this.make = make_arg
957 enddef
958
959 def GetMake(): string
960 return $"make = {this.make}"
961 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000962 def GetAge(): number
963 return this.age
964 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000965 endclass
966
967 var c = MyCar.new("abc")
968 assert_equal('make = abc', c.GetMake())
969
970 c = MyCar.new("def")
971 assert_equal('make = def', c.GetMake())
972
973 var c2 = MyCar.new("123")
974 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000975
976 def CheckCar()
977 assert_equal("make = def", c.GetMake())
978 assert_equal(5, c.GetAge())
979 enddef
980 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000981 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200982 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000983
984 lines =<< trim END
985 vim9script
986
987 class MyCar
988 this.make: string
989
990 def new(make_arg: string)
991 this.make = make_arg
992 enddef
993 endclass
994
995 var c = MyCar.new("abc")
996 var c = MyCar.new("def")
997 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200998 v9.CheckSourceFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000999
1000 lines =<< trim END
1001 vim9script
1002
1003 class Foo
1004 this.x: list<number> = []
1005
1006 def Add(n: number): any
1007 this.x->add(n)
1008 return this
1009 enddef
1010 endclass
1011
1012 echo Foo.new().Add(1).Add(2).x
1013 echo Foo.new().Add(1).Add(2)
1014 .x
1015 echo Foo.new().Add(1)
1016 .Add(2).x
1017 echo Foo.new()
1018 .Add(1).Add(2).x
1019 echo Foo.new()
1020 .Add(1)
1021 .Add(2)
1022 .x
1023 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001024 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001025
1026 # Test for "public" cannot be abbreviated
1027 lines =<< trim END
1028 vim9script
1029 class Something
1030 pub this.val = 1
1031 endclass
1032 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001033 v9.CheckSourceFailure(lines, 'E1065:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001034
1035 # Test for "public" keyword must be followed by "this" or "static".
1036 lines =<< trim END
1037 vim9script
1038 class Something
1039 public val = 1
1040 endclass
1041 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001042 v9.CheckSourceFailure(lines, 'E1331:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001043
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001044 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001045 lines =<< trim END
1046 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001047 class A
1048 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001049 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001050 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001051 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001052 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001053
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001054 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001055 lines =<< trim END
1056 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001057 class A
1058 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001059 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001060 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001061 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001062 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1063
1064 # Modify a instance variable using the class name in a def function
1065 lines =<< trim END
1066 vim9script
1067 class A
1068 public this.val = 1
1069 endclass
1070 def T()
1071 A.val = 1
1072 enddef
1073 T()
1074 END
1075 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1076
1077 # Read a instance variable using the class name in a def function
1078 lines =<< trim END
1079 vim9script
1080 class A
1081 public this.val = 1
1082 endclass
1083 def T()
1084 var i = A.val
1085 enddef
1086 T()
1087 END
1088 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Ernie Raelcf138d42023-09-06 20:45:03 +02001089
1090 # Access from child class extending a class:
1091 lines =<< trim END
1092 vim9script
1093 class A
1094 this.ro_obj_var = 10
1095 public this.rw_obj_var = 20
1096 this._priv_obj_var = 30
Ernie Raelcf138d42023-09-06 20:45:03 +02001097 endclass
1098
1099 class B extends A
1100 def Foo()
1101 var x: number
1102 x = this.ro_obj_var
1103 this.ro_obj_var = 0
1104 x = this.rw_obj_var
1105 this.rw_obj_var = 0
1106 x = this._priv_obj_var
1107 this._priv_obj_var = 0
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001108 enddef
1109 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001110
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001111 var b = B.new()
1112 b.Foo()
1113 END
1114 v9.CheckSourceSuccess(lines)
1115enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001116
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001117" Test for class variable access
1118def Test_class_variable_access()
1119 # Test for "static" cannot be abbreviated
1120 var lines =<< trim END
1121 vim9script
1122 class Something
1123 stat this.val = 1
1124 endclass
1125 END
1126 v9.CheckSourceFailure(lines, 'E1065:')
1127
1128 # Test for "static" cannot be followed by "this".
1129 lines =<< trim END
1130 vim9script
1131 class Something
1132 static this.val = 1
1133 endclass
1134 END
1135 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
1136
1137 # Test for "static" cannot be followed by "public".
1138 lines =<< trim END
1139 vim9script
1140 class Something
1141 static public val = 1
1142 endclass
1143 END
1144 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
1145
1146 # A readonly class variable cannot be modified from a child class
1147 lines =<< trim END
1148 vim9script
1149 class A
1150 static ro_class_var = 40
1151 endclass
1152
1153 class B extends A
1154 def Foo()
1155 A.ro_class_var = 50
1156 enddef
1157 endclass
1158
1159 var b = B.new()
1160 b.Foo()
1161 END
1162 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "ro_class_var"')
1163
1164 # A private class variable cannot be accessed from a child class
1165 lines =<< trim END
1166 vim9script
1167 class A
1168 static _priv_class_var = 60
1169 endclass
1170
1171 class B extends A
1172 def Foo()
1173 var i = A._priv_class_var
1174 enddef
1175 endclass
1176
1177 var b = B.new()
1178 b.Foo()
1179 END
1180 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1181
1182 # A private class variable cannot be modified from a child class
1183 lines =<< trim END
1184 vim9script
1185 class A
1186 static _priv_class_var = 60
1187 endclass
1188
1189 class B extends A
1190 def Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001191 A._priv_class_var = 0
1192 enddef
1193 endclass
1194
1195 var b = B.new()
1196 b.Foo()
1197 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001198 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1199
1200 # Access from child class extending a class and from script context
1201 lines =<< trim END
1202 vim9script
1203 class A
1204 static ro_class_var = 10
1205 public static rw_class_var = 20
1206 static _priv_class_var = 30
1207 endclass
1208
1209 class B extends A
1210 def Foo()
1211 var x: number
1212 x = A.ro_class_var
1213 assert_equal(10, x)
1214 x = A.rw_class_var
1215 assert_equal(25, x)
1216 A.rw_class_var = 20
1217 assert_equal(20, A.rw_class_var)
1218 enddef
1219 endclass
1220
1221 assert_equal(10, A.ro_class_var)
1222 assert_equal(20, A.rw_class_var)
1223 A.rw_class_var = 25
1224 assert_equal(25, A.rw_class_var)
1225 var b = B.new()
1226 b.Foo()
1227 END
1228 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001229enddef
1230
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001231def Test_class_object_compare()
1232 var class_lines =<< trim END
1233 vim9script
1234 class Item
1235 this.nr = 0
1236 this.name = 'xx'
1237 endclass
1238 END
1239
1240 # used at the script level and in a compiled function
1241 var test_lines =<< trim END
1242 var i1 = Item.new()
1243 assert_equal(i1, i1)
1244 assert_true(i1 is i1)
1245 var i2 = Item.new()
1246 assert_equal(i1, i2)
1247 assert_false(i1 is i2)
1248 var i3 = Item.new(0, 'xx')
1249 assert_equal(i1, i3)
1250
1251 var io1 = Item.new(1, 'xx')
1252 assert_notequal(i1, io1)
1253 var io2 = Item.new(0, 'yy')
1254 assert_notequal(i1, io2)
1255 END
1256
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001257 v9.CheckSourceSuccess(class_lines + test_lines)
1258 v9.CheckSourceSuccess(
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001259 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001260
1261 for op in ['>', '>=', '<', '<=', '=~', '!~']
1262 var op_lines = [
1263 'var i1 = Item.new()',
1264 'var i2 = Item.new()',
1265 'echo i1 ' .. op .. ' i2',
1266 ]
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001267 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
1268 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001269 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001270 endfor
1271enddef
1272
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001273def Test_object_type()
1274 var lines =<< trim END
1275 vim9script
1276
1277 class One
1278 this.one = 1
1279 endclass
1280 class Two
1281 this.two = 2
1282 endclass
1283 class TwoMore extends Two
1284 this.more = 9
1285 endclass
1286
1287 var o: One = One.new()
1288 var t: Two = Two.new()
1289 var m: TwoMore = TwoMore.new()
1290 var tm: Two = TwoMore.new()
1291
1292 t = m
1293 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001294 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001295
1296 lines =<< trim END
1297 vim9script
1298
1299 class One
1300 this.one = 1
1301 endclass
1302 class Two
1303 this.two = 2
1304 endclass
1305
1306 var o: One = Two.new()
1307 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001308 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001309
1310 lines =<< trim END
1311 vim9script
1312
1313 interface One
1314 def GetMember(): number
1315 endinterface
1316 class Two implements One
1317 this.one = 1
1318 def GetMember(): number
1319 return this.one
1320 enddef
1321 endclass
1322
1323 var o: One = Two.new(5)
1324 assert_equal(5, o.GetMember())
1325 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001326 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001327
1328 lines =<< trim END
1329 vim9script
1330
1331 class Num
1332 this.n: number = 0
1333 endclass
1334
1335 def Ref(name: string): func(Num): Num
1336 return (arg: Num): Num => {
1337 return eval(name)(arg)
1338 }
1339 enddef
1340
1341 const Fn = Ref('Double')
1342 var Double = (m: Num): Num => Num.new(m.n * 2)
1343
1344 echo Fn(Num.new(4))
1345 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001346 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001347enddef
1348
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001349def Test_class_member()
1350 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001351 var lines =<< trim END
1352 vim9script
1353 class TextPos
1354 this.lnum = 1
1355 this.col = 1
1356 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001357 static _secret = 7
1358 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001359
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001360 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001361 counter += nr
1362 enddef
1363 endclass
1364
1365 assert_equal(0, TextPos.counter)
1366 TextPos.AddToCounter(3)
1367 assert_equal(3, TextPos.counter)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001368 assert_fails('echo TextPos.noSuchMember', 'E1337:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001369
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001370 def GetCounter(): number
1371 return TextPos.counter
1372 enddef
1373 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001374
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001375 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001376 assert_fails('TextPos.counter = 5', 'E1335:')
1377 assert_fails('TextPos.counter += 5', 'E1335:')
1378
1379 assert_fails('echo TextPos._secret', 'E1333:')
1380 assert_fails('TextPos._secret = 8', 'E1333:')
1381
1382 assert_equal(42, TextPos.anybody)
1383 TextPos.anybody = 12
1384 assert_equal(12, TextPos.anybody)
1385 TextPos.anybody += 5
1386 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001387 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001388 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001389
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001390 # example in the help
1391 lines =<< trim END
1392 vim9script
1393 class OtherThing
1394 this.size: number
1395 static totalSize: number
1396
1397 def new(this.size)
1398 totalSize += this.size
1399 enddef
1400 endclass
1401 assert_equal(0, OtherThing.totalSize)
1402 var to3 = OtherThing.new(3)
1403 assert_equal(3, OtherThing.totalSize)
1404 var to7 = OtherThing.new(7)
1405 assert_equal(10, OtherThing.totalSize)
1406 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001407 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001408
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001409 # using static class member twice
1410 lines =<< trim END
1411 vim9script
1412
1413 class HTML
1414 static author: string = 'John Doe'
1415
1416 static def MacroSubstitute(s: string): string
1417 return substitute(s, '{{author}}', author, 'gi')
1418 enddef
1419 endclass
1420
1421 assert_equal('some text', HTML.MacroSubstitute('some text'))
1422 assert_equal('some text', HTML.MacroSubstitute('some text'))
1423 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001424 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001425
Bram Moolenaar62a69232023-01-24 15:07:04 +00001426 # access private member in lambda
1427 lines =<< trim END
1428 vim9script
1429
1430 class Foo
1431 this._x: number = 0
1432
1433 def Add(n: number): number
1434 const F = (): number => this._x + n
1435 return F()
1436 enddef
1437 endclass
1438
1439 var foo = Foo.new()
1440 assert_equal(5, foo.Add(5))
1441 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001442 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001443
h-east2bd6a092023-05-19 19:01:17 +01001444 # access private member in lambda body
1445 lines =<< trim END
1446 vim9script
1447
1448 class Foo
1449 this._x: number = 6
1450
1451 def Add(n: number): number
1452 var Lam = () => {
1453 this._x = this._x + n
1454 }
1455 Lam()
1456 return this._x
1457 enddef
1458 endclass
1459
1460 var foo = Foo.new()
1461 assert_equal(13, foo.Add(7))
1462 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001463 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001464
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001465 # check shadowing
1466 lines =<< trim END
1467 vim9script
1468
1469 class Some
1470 static count = 0
1471 def Method(count: number)
1472 echo count
1473 enddef
1474 endclass
1475
1476 var s = Some.new()
1477 s.Method(7)
1478 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001479 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001480
1481 lines =<< trim END
1482 vim9script
1483
1484 class Some
1485 static count = 0
1486 def Method(arg: number)
1487 var count = 3
1488 echo arg count
1489 enddef
1490 endclass
1491
1492 var s = Some.new()
1493 s.Method(7)
1494 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001495 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001496
1497 # Test for using an invalid type for a member variable
1498 lines =<< trim END
1499 vim9script
1500 class A
1501 this.val: xxx
1502 endclass
1503 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001504 v9.CheckSourceFailure(lines, 'E1010:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001505
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001506 # Test for setting a member on a null object
1507 lines =<< trim END
1508 vim9script
1509 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001510 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001511 endclass
1512
1513 def F()
1514 var obj: A
1515 obj.val = ""
1516 enddef
1517 F()
1518 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001519 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001520
1521 # Test for accessing a member on a null object
1522 lines =<< trim END
1523 vim9script
1524 class A
1525 this.val: string
1526 endclass
1527
1528 def F()
1529 var obj: A
1530 echo obj.val
1531 enddef
1532 F()
1533 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001534 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001535
1536 # Test for setting a member on a null object, at script level
1537 lines =<< trim END
1538 vim9script
1539 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001540 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001541 endclass
1542
1543 var obj: A
1544 obj.val = ""
1545 END
1546 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001547 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001548
1549 # Test for accessing a member on a null object, at script level
1550 lines =<< trim END
1551 vim9script
1552 class A
1553 this.val: string
1554 endclass
1555
1556 var obj: A
1557 echo obj.val
1558 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001559 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001560
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001561 # Test for no space before or after the '=' when initializing a member
1562 # variable
1563 lines =<< trim END
1564 vim9script
1565 class A
1566 this.val: number= 10
1567 endclass
1568 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001569 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001570 lines =<< trim END
1571 vim9script
1572 class A
1573 this.val: number =10
1574 endclass
1575 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001576 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001577
1578 # Access a non-existing member
1579 lines =<< trim END
1580 vim9script
1581 class A
1582 endclass
1583 var a = A.new()
1584 var v = a.bar
1585 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001586 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": bar')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001587enddef
1588
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001589func Test_class_garbagecollect()
1590 let lines =<< trim END
1591 vim9script
1592
1593 class Point
1594 this.p = [2, 3]
1595 static pl = ['a', 'b']
1596 static pd = {a: 'a', b: 'b'}
1597 endclass
1598
1599 echo Point.pl Point.pd
1600 call test_garbagecollect_now()
1601 echo Point.pl Point.pd
1602 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001603 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001604
1605 let lines =<< trim END
1606 vim9script
1607
1608 interface View
1609 endinterface
1610
1611 class Widget
1612 this.view: View
1613 endclass
1614
1615 class MyView implements View
1616 this.widget: Widget
1617
1618 def new()
1619 # this will result in a circular reference to this object
1620 this.widget = Widget.new(this)
1621 enddef
1622 endclass
1623
1624 var view = MyView.new()
1625
1626 # overwrite "view", will be garbage-collected next
1627 view = MyView.new()
1628 test_garbagecollect_now()
1629 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001630 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001631endfunc
1632
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001633" Test interface garbage collection
1634func Test_interface_garbagecollect()
1635 let lines =<< trim END
1636 vim9script
1637
1638 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001639 this.ro_obj_var: number
1640 public this.rw_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001641
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001642 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001643 endinterface
1644
1645 class A implements I
1646 static ro_class_var: number = 10
1647 public static rw_class_var: number = 20
1648 static _priv_class_var: number = 30
1649 this.ro_obj_var: number = 40
1650 public this.rw_obj_var: number = 50
1651 this._priv_obj_var: number = 60
1652
1653 static def _ClassBar(): number
1654 return _priv_class_var
1655 enddef
1656
1657 static def ClassFoo(): number
1658 return ro_class_var + rw_class_var + A._ClassBar()
1659 enddef
1660
1661 def _ObjBar(): number
1662 return this._priv_obj_var
1663 enddef
1664
1665 def ObjFoo(): number
1666 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1667 enddef
1668 endclass
1669
1670 assert_equal(60, A.ClassFoo())
1671 var o = A.new()
1672 assert_equal(150, o.ObjFoo())
1673 test_garbagecollect_now()
1674 assert_equal(60, A.ClassFoo())
1675 assert_equal(150, o.ObjFoo())
1676 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001677 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001678endfunc
1679
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001680def Test_class_function()
1681 var lines =<< trim END
1682 vim9script
1683 class Value
1684 this.value = 0
1685 static objects = 0
1686
1687 def new(v: number)
1688 this.value = v
1689 ++objects
1690 enddef
1691
1692 static def GetCount(): number
1693 return objects
1694 enddef
1695 endclass
1696
1697 assert_equal(0, Value.GetCount())
1698 var v1 = Value.new(2)
1699 assert_equal(1, Value.GetCount())
1700 var v2 = Value.new(7)
1701 assert_equal(2, Value.GetCount())
1702 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001703 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001704
1705 # Test for cleaning up after a class definition failure when using class
1706 # functions.
1707 lines =<< trim END
1708 vim9script
1709 class A
1710 static def Foo()
1711 enddef
1712 aaa
1713 endclass
1714 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001715 v9.CheckSourceFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001716enddef
1717
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001718def Test_class_defcompile()
1719 var lines =<< trim END
1720 vim9script
1721
1722 class C
1723 def Fo(i: number): string
1724 return i
1725 enddef
1726 endclass
1727
1728 defcompile C.Fo
1729 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001730 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001731
1732 lines =<< trim END
1733 vim9script
1734
1735 class C
1736 static def Fc(): number
1737 return 'x'
1738 enddef
1739 endclass
1740
1741 defcompile C.Fc
1742 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001743 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001744
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001745 lines =<< trim END
1746 vim9script
1747
1748 class C
1749 static def new()
1750 enddef
1751 endclass
1752
1753 defcompile C.new
1754 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001755 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" function as static')
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001756
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001757 # Trying to compile a function using a non-existing class variable
1758 lines =<< trim END
1759 vim9script
1760 defcompile x.Foo()
1761 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001762 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001763
1764 # Trying to compile a function using a variable which is not a class
1765 lines =<< trim END
1766 vim9script
1767 var x: number
1768 defcompile x.Foo()
1769 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001770 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001771
1772 # Trying to compile a function without specifying the name
1773 lines =<< trim END
1774 vim9script
1775 class A
1776 endclass
1777 defcompile A.
1778 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001779 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001780
1781 # Trying to compile a non-existing class object member function
1782 lines =<< trim END
1783 vim9script
1784 class A
1785 endclass
1786 var a = A.new()
1787 defcompile a.Foo()
1788 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001789 v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001790enddef
1791
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001792def Test_class_object_to_string()
1793 var lines =<< trim END
1794 vim9script
1795 class TextPosition
1796 this.lnum = 1
1797 this.col = 22
1798 endclass
1799
1800 assert_equal("class TextPosition", string(TextPosition))
1801
1802 var pos = TextPosition.new()
1803 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1804 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001805 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001806enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001807
Bram Moolenaar554d0312023-01-05 19:59:18 +00001808def Test_interface_basics()
1809 var lines =<< trim END
1810 vim9script
1811 interface Something
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001812 this.ro_var: string
1813 public this.rw_var: list<number>
Bram Moolenaar554d0312023-01-05 19:59:18 +00001814 def GetCount(): number
1815 endinterface
1816 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001817 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001818
1819 lines =<< trim END
1820 interface SomethingWrong
1821 static count = 7
1822 endinterface
1823 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001824 v9.CheckSourceFailure(lines, 'E1342:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001825
1826 lines =<< trim END
1827 vim9script
1828
1829 interface Some
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001830 this.value: number
1831 def Method(value: number)
1832 endinterface
1833 END
h-east61378a12023-04-18 19:07:29 +01001834 # The argument name and the object member name are the same, but this is not a
1835 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001836 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001837
1838 lines =<< trim END
1839 vim9script
1840 interface somethingWrong
1841 static count = 7
1842 endinterface
1843 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001844 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001845
1846 lines =<< trim END
1847 vim9script
1848 interface SomethingWrong
1849 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001850 this.count = 7
Bram Moolenaar554d0312023-01-05 19:59:18 +00001851 def GetCount(): number
1852 endinterface
1853 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001854 v9.CheckSourceFailure(lines, 'E1344:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001855
1856 lines =<< trim END
1857 vim9script
1858 interface SomethingWrong
1859 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001860 this.count: number
Bram Moolenaar554d0312023-01-05 19:59:18 +00001861 def GetCount(): number
1862 return 5
1863 enddef
1864 endinterface
1865 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001866 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001867
1868 lines =<< trim END
1869 vim9script
1870 export interface EnterExit
1871 def Enter(): void
1872 def Exit(): void
1873 endinterface
1874 END
1875 writefile(lines, 'XdefIntf.vim', 'D')
1876
1877 lines =<< trim END
1878 vim9script
1879 import './XdefIntf.vim' as defIntf
1880 export def With(ee: defIntf.EnterExit, F: func)
1881 ee.Enter()
1882 try
1883 F()
1884 finally
1885 ee.Exit()
1886 endtry
1887 enddef
1888 END
1889 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001890
1891 var imported =<< trim END
1892 vim9script
1893 export abstract class EnterExit
1894 def Enter(): void
1895 enddef
1896 def Exit(): void
1897 enddef
1898 endclass
1899 END
1900 writefile(imported, 'XdefIntf2.vim', 'D')
1901
1902 lines[1] = " import './XdefIntf2.vim' as defIntf"
1903 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001904enddef
1905
Bram Moolenaar94674f22023-01-06 18:42:20 +00001906def Test_class_implements_interface()
1907 var lines =<< trim END
1908 vim9script
1909
1910 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001911 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001912 def Method(nr: number)
1913 endinterface
1914
1915 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001916 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001917 def Method(nr: number)
1918 echo nr
1919 enddef
1920 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001921
1922 interface Another
1923 this.member: string
1924 endinterface
1925
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001926 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001927 this.member = 'abc'
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001928 this.count = 20
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001929 def Method(nr: number)
1930 echo nr
1931 enddef
1932 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001933 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001934 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00001935
1936 lines =<< trim END
1937 vim9script
1938
1939 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001940 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001941 endinterface
1942
1943 class SomeImpl implements Some implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001944 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001945 endclass
1946 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001947 v9.CheckSourceFailure(lines, 'E1350:')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001948
1949 lines =<< trim END
1950 vim9script
1951
1952 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001953 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001954 endinterface
1955
1956 class SomeImpl implements Some, Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001957 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001958 endclass
1959 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001960 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001961
1962 lines =<< trim END
1963 vim9script
1964
1965 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001966 this.counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001967 def Method(nr: number)
1968 endinterface
1969
1970 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001971 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001972 def Method(nr: number)
1973 echo nr
1974 enddef
1975 endclass
1976 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001977 v9.CheckSourceFailure(lines, 'E1348: Member "counter" of interface "Some" is not implemented')
Bram Moolenaar94674f22023-01-06 18:42:20 +00001978
1979 lines =<< trim END
1980 vim9script
1981
1982 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001983 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001984 def Methods(nr: number)
1985 endinterface
1986
1987 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001988 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001989 def Method(nr: number)
1990 echo nr
1991 enddef
1992 endclass
1993 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001994 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001995
1996 # Check different order of members in class and interface works.
1997 lines =<< trim END
1998 vim9script
1999
2000 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002001 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002002 this.errpos: number
2003 endinterface
2004
2005 # order of members is opposite of interface
2006 class Failure implements Result
2007 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002008 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002009 endclass
2010
2011 def Test()
2012 var result: Result = Failure.new()
2013
2014 assert_equal('label', result.label)
2015 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002016
2017 result.label = 'different'
2018 assert_equal('different', result.label)
2019 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002020 enddef
2021
2022 Test()
2023 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002024 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002025
2026 # Interface name after "extends" doesn't end in a space or NUL character
2027 lines =<< trim END
2028 vim9script
2029 interface A
2030 endinterface
2031 class B extends A"
2032 endclass
2033 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002034 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002035
2036 # Trailing characters after a class name
2037 lines =<< trim END
2038 vim9script
2039 class A bbb
2040 endclass
2041 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002042 v9.CheckSourceFailure(lines, 'E488:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002043
2044 # using "implements" with a non-existing class
2045 lines =<< trim END
2046 vim9script
2047 class A implements B
2048 endclass
2049 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002050 v9.CheckSourceFailure(lines, 'E1346:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002051
2052 # using "implements" with a regular class
2053 lines =<< trim END
2054 vim9script
2055 class A
2056 endclass
2057 class B implements A
2058 endclass
2059 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002060 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002061
2062 # using "implements" with a variable
2063 lines =<< trim END
2064 vim9script
2065 var T: number = 10
2066 class A implements T
2067 endclass
2068 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002069 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002070
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002071 # implements should be followed by a white space
2072 lines =<< trim END
2073 vim9script
2074 interface A
2075 endinterface
2076 class B implements A;
2077 endclass
2078 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002079 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002080
LemonBoyc5d27442023-08-19 13:02:35 +02002081 lines =<< trim END
2082 vim9script
2083
2084 interface One
LemonBoyc5d27442023-08-19 13:02:35 +02002085 def IsEven(nr: number): bool
2086 endinterface
2087 class Two implements One
2088 def IsEven(nr: number): string
2089 enddef
2090 endclass
2091 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002092 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02002093
2094 lines =<< trim END
2095 vim9script
2096
2097 interface One
2098 def IsEven(nr: number): bool
2099 endinterface
2100 class Two implements One
2101 def IsEven(nr: bool): bool
2102 enddef
2103 endclass
2104 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002105 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02002106
2107 lines =<< trim END
2108 vim9script
2109
2110 interface One
2111 def IsEven(nr: number): bool
2112 endinterface
2113 class Two implements One
2114 def IsEven(nr: number, ...extra: list<number>): bool
2115 enddef
2116 endclass
2117 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002118 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
Ernie Raelcf138d42023-09-06 20:45:03 +02002119
2120 # access superclass interface members from subclass, mix variable order
2121 lines =<< trim END
2122 vim9script
2123
2124 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002125 public this.mvar1: number
2126 public this.mvar2: number
2127 endinterface
2128
2129 # NOTE: the order is swapped
2130 class A implements I1
2131 public this.mvar2: number
2132 public this.mvar1: number
2133 public static svar2: number
2134 public static svar1: number
2135 def new()
2136 svar1 = 11
2137 svar2 = 12
2138 this.mvar1 = 111
2139 this.mvar2 = 112
2140 enddef
2141 endclass
2142
2143 class B extends A
2144 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002145 this.mvar1 = 121
2146 this.mvar2 = 122
2147 enddef
2148 endclass
2149
2150 class C extends B
2151 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002152 this.mvar1 = 131
2153 this.mvar2 = 132
2154 enddef
2155 endclass
2156
Ernie Raelcf138d42023-09-06 20:45:03 +02002157 def F2(i: I1): list<number>
2158 return [ i.mvar1, i.mvar2 ]
2159 enddef
2160
2161 var oa = A.new()
2162 var ob = B.new()
2163 var oc = C.new()
2164
Ernie Raelcf138d42023-09-06 20:45:03 +02002165 assert_equal([111, 112], F2(oa))
2166 assert_equal([121, 122], F2(ob))
2167 assert_equal([131, 132], F2(oc))
2168 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002169 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002170
2171 # Access superclass interface members from subclass, mix variable order.
2172 # Two interfaces, one on A, one on B; each has both kinds of variables
2173 lines =<< trim END
2174 vim9script
2175
2176 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002177 public this.mvar1: number
2178 public this.mvar2: number
2179 endinterface
2180
2181 interface I2
Ernie Raelcf138d42023-09-06 20:45:03 +02002182 public this.mvar3: number
2183 public this.mvar4: number
2184 endinterface
2185
2186 class A implements I1
2187 public static svar1: number
2188 public static svar2: number
2189 public this.mvar1: number
2190 public this.mvar2: number
2191 def new()
2192 svar1 = 11
2193 svar2 = 12
2194 this.mvar1 = 111
2195 this.mvar2 = 112
2196 enddef
2197 endclass
2198
2199 class B extends A implements I2
2200 public static svar3: number
2201 public static svar4: number
2202 public this.mvar3: number
2203 public this.mvar4: number
2204 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002205 svar3 = 23
2206 svar4 = 24
2207 this.mvar1 = 121
2208 this.mvar2 = 122
2209 this.mvar3 = 123
2210 this.mvar4 = 124
2211 enddef
2212 endclass
2213
2214 class C extends B
2215 public static svar5: number
2216 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002217 svar5 = 1001
2218 this.mvar1 = 131
2219 this.mvar2 = 132
2220 this.mvar3 = 133
2221 this.mvar4 = 134
2222 enddef
2223 endclass
2224
Ernie Raelcf138d42023-09-06 20:45:03 +02002225 def F2(i: I1): list<number>
2226 return [ i.mvar1, i.mvar2 ]
2227 enddef
2228
Ernie Raelcf138d42023-09-06 20:45:03 +02002229 def F4(i: I2): list<number>
2230 return [ i.mvar3, i.mvar4 ]
2231 enddef
2232
Ernie Raelcf138d42023-09-06 20:45:03 +02002233 var oa = A.new()
2234 var ob = B.new()
2235 var oc = C.new()
2236
Ernie Raelcf138d42023-09-06 20:45:03 +02002237 assert_equal([[111, 112]], [F2(oa)])
2238 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2239 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002240 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002241 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002242enddef
2243
Bram Moolenaard0200c82023-01-28 15:19:40 +00002244def Test_call_interface_method()
2245 var lines =<< trim END
2246 vim9script
2247 interface Base
2248 def Enter(): void
2249 endinterface
2250
2251 class Child implements Base
2252 def Enter(): void
2253 g:result ..= 'child'
2254 enddef
2255 endclass
2256
2257 def F(obj: Base)
2258 obj.Enter()
2259 enddef
2260
2261 g:result = ''
2262 F(Child.new())
2263 assert_equal('child', g:result)
2264 unlet g:result
2265 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002266 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002267
2268 lines =<< trim END
2269 vim9script
2270 class Base
2271 def Enter(): void
2272 g:result ..= 'base'
2273 enddef
2274 endclass
2275
2276 class Child extends Base
2277 def Enter(): void
2278 g:result ..= 'child'
2279 enddef
2280 endclass
2281
2282 def F(obj: Base)
2283 obj.Enter()
2284 enddef
2285
2286 g:result = ''
2287 F(Child.new())
2288 assert_equal('child', g:result)
2289 unlet g:result
2290 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002291 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002292
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002293 # method of interface returns a value
2294 lines =<< trim END
2295 vim9script
2296 interface Base
2297 def Enter(): string
2298 endinterface
2299
2300 class Child implements Base
2301 def Enter(): string
2302 g:result ..= 'child'
2303 return "/resource"
2304 enddef
2305 endclass
2306
2307 def F(obj: Base)
2308 var r = obj.Enter()
2309 g:result ..= r
2310 enddef
2311
2312 g:result = ''
2313 F(Child.new())
2314 assert_equal('child/resource', g:result)
2315 unlet g:result
2316 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002317 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002318
2319 lines =<< trim END
2320 vim9script
2321 class Base
2322 def Enter(): string
2323 return null_string
2324 enddef
2325 endclass
2326
2327 class Child extends Base
2328 def Enter(): string
2329 g:result ..= 'child'
2330 return "/resource"
2331 enddef
2332 endclass
2333
2334 def F(obj: Base)
2335 var r = obj.Enter()
2336 g:result ..= r
2337 enddef
2338
2339 g:result = ''
2340 F(Child.new())
2341 assert_equal('child/resource', g:result)
2342 unlet g:result
2343 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002344 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002345
2346
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002347 # No class that implements the interface.
2348 lines =<< trim END
2349 vim9script
2350
2351 interface IWithEE
2352 def Enter(): any
2353 def Exit(): void
2354 endinterface
2355
2356 def With1(ee: IWithEE, F: func)
2357 var r = ee.Enter()
2358 enddef
2359
2360 defcompile
2361 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002362 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002363enddef
2364
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002365def Test_class_used_as_type()
2366 var lines =<< trim END
2367 vim9script
2368
2369 class Point
2370 this.x = 0
2371 this.y = 0
2372 endclass
2373
2374 var p: Point
2375 p = Point.new(2, 33)
2376 assert_equal(2, p.x)
2377 assert_equal(33, p.y)
2378 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002379 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002380
2381 lines =<< trim END
2382 vim9script
2383
2384 interface HasX
2385 this.x: number
2386 endinterface
2387
2388 class Point implements HasX
2389 this.x = 0
2390 this.y = 0
2391 endclass
2392
2393 var p: Point
2394 p = Point.new(2, 33)
2395 var hx = p
2396 assert_equal(2, hx.x)
2397 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002398 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002399
2400 lines =<< trim END
2401 vim9script
2402
2403 class Point
2404 this.x = 0
2405 this.y = 0
2406 endclass
2407
2408 var p: Point
2409 p = 'text'
2410 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002411 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002412enddef
2413
Bram Moolenaar83677162023-01-08 19:54:10 +00002414def Test_class_extends()
2415 var lines =<< trim END
2416 vim9script
2417 class Base
2418 this.one = 1
2419 def GetOne(): number
2420 return this.one
2421 enddef
2422 endclass
2423 class Child extends Base
2424 this.two = 2
2425 def GetTotal(): number
2426 return this.one + this.two
2427 enddef
2428 endclass
2429 var o = Child.new()
2430 assert_equal(1, o.one)
2431 assert_equal(2, o.two)
2432 assert_equal(1, o.GetOne())
2433 assert_equal(3, o.GetTotal())
2434 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002435 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002436
2437 lines =<< trim END
2438 vim9script
2439 class Base
2440 this.one = 1
2441 endclass
2442 class Child extends Base
2443 this.two = 2
2444 endclass
2445 var o = Child.new(3, 44)
2446 assert_equal(3, o.one)
2447 assert_equal(44, o.two)
2448 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002449 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002450
2451 lines =<< trim END
2452 vim9script
2453 class Base
2454 this.one = 1
2455 endclass
2456 class Child extends Base extends Base
2457 this.two = 2
2458 endclass
2459 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002460 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
Bram Moolenaar83677162023-01-08 19:54:10 +00002461
2462 lines =<< trim END
2463 vim9script
2464 class Child extends BaseClass
2465 this.two = 2
2466 endclass
2467 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002468 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
Bram Moolenaar83677162023-01-08 19:54:10 +00002469
2470 lines =<< trim END
2471 vim9script
2472 var SomeVar = 99
2473 class Child extends SomeVar
2474 this.two = 2
2475 endclass
2476 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002477 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002478
2479 lines =<< trim END
2480 vim9script
2481 class Base
2482 this.name: string
2483 def ToString(): string
2484 return this.name
2485 enddef
2486 endclass
2487
2488 class Child extends Base
2489 this.age: number
2490 def ToString(): string
2491 return super.ToString() .. ': ' .. this.age
2492 enddef
2493 endclass
2494
2495 var o = Child.new('John', 42)
2496 assert_equal('John: 42', o.ToString())
2497 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002498 v9.CheckSourceSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002499
2500 lines =<< trim END
2501 vim9script
2502 class Child
2503 this.age: number
2504 def ToString(): number
2505 return this.age
2506 enddef
2507 def ToString(): string
2508 return this.age
2509 enddef
2510 endclass
2511 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002512 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002513
2514 lines =<< trim END
2515 vim9script
2516 class Child
2517 this.age: number
2518 def ToString(): string
2519 return super .ToString() .. ': ' .. this.age
2520 enddef
2521 endclass
2522 var o = Child.new(42)
2523 echo o.ToString()
2524 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002525 v9.CheckSourceFailure(lines, 'E1356:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002526
2527 lines =<< trim END
2528 vim9script
2529 class Base
2530 this.name: string
2531 def ToString(): string
2532 return this.name
2533 enddef
2534 endclass
2535
2536 var age = 42
2537 def ToString(): string
2538 return super.ToString() .. ': ' .. age
2539 enddef
2540 echo ToString()
2541 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002542 v9.CheckSourceFailure(lines, 'E1357:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002543
2544 lines =<< trim END
2545 vim9script
2546 class Child
2547 this.age: number
2548 def ToString(): string
2549 return super.ToString() .. ': ' .. this.age
2550 enddef
2551 endclass
2552 var o = Child.new(42)
2553 echo o.ToString()
2554 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002555 v9.CheckSourceFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002556
2557 lines =<< trim END
2558 vim9script
2559 class Base
2560 this.name: string
2561 static def ToString(): string
2562 return 'Base class'
2563 enddef
2564 endclass
2565
2566 class Child extends Base
2567 this.age: number
2568 def ToString(): string
2569 return Base.ToString() .. ': ' .. this.age
2570 enddef
2571 endclass
2572
2573 var o = Child.new('John', 42)
2574 assert_equal('Base class: 42', o.ToString())
2575 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002576 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002577
2578 lines =<< trim END
2579 vim9script
2580 class Base
2581 this.value = 1
2582 def new(init: number)
2583 this.value = number + 1
2584 enddef
2585 endclass
2586 class Child extends Base
2587 def new()
2588 this.new(3)
2589 enddef
2590 endclass
2591 var c = Child.new()
2592 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002593 v9.CheckSourceFailure(lines, 'E1375: Class member "new" accessible only using class "Child"')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002594
2595 # base class with more than one object member
2596 lines =<< trim END
2597 vim9script
2598
2599 class Result
2600 this.success: bool
2601 this.value: any = null
2602 endclass
2603
2604 class Success extends Result
2605 def new(this.value = v:none)
2606 this.success = true
2607 enddef
2608 endclass
2609
2610 var v = Success.new('asdf')
2611 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2612 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002613 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002614
2615 # class name after "extends" doesn't end in a space or NUL character
2616 lines =<< trim END
2617 vim9script
2618 class A
2619 endclass
2620 class B extends A"
2621 endclass
2622 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002623 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002624enddef
2625
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002626def Test_using_base_class()
2627 var lines =<< trim END
2628 vim9script
2629
2630 class BaseEE
2631 def Enter(): any
2632 return null
2633 enddef
2634 def Exit(resource: any): void
2635 enddef
2636 endclass
2637
2638 class ChildEE extends BaseEE
2639 def Enter(): any
2640 return 42
2641 enddef
2642
2643 def Exit(resource: number): void
2644 g:result ..= '/exit'
2645 enddef
2646 endclass
2647
2648 def With(ee: BaseEE)
2649 var r = ee.Enter()
2650 try
2651 g:result ..= r
2652 finally
2653 g:result ..= '/finally'
2654 ee.Exit(r)
2655 endtry
2656 enddef
2657
2658 g:result = ''
2659 With(ChildEE.new())
2660 assert_equal('42/finally/exit', g:result)
2661 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002662 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002663 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002664
2665 # Using super, Child invokes Base method which has optional arg. #12471
2666 lines =<< trim END
2667 vim9script
2668
2669 class Base
2670 this.success: bool = false
2671 def Method(arg = 0)
2672 this.success = true
2673 enddef
2674 endclass
2675
2676 class Child extends Base
2677 def new()
2678 super.Method()
2679 enddef
2680 endclass
2681
2682 var obj = Child.new()
2683 assert_equal(true, obj.success)
2684 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002685 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002686enddef
2687
2688
Bram Moolenaara86655a2023-01-12 17:06:27 +00002689def Test_class_import()
2690 var lines =<< trim END
2691 vim9script
2692 export class Animal
2693 this.kind: string
2694 this.name: string
2695 endclass
2696 END
2697 writefile(lines, 'Xanimal.vim', 'D')
2698
2699 lines =<< trim END
2700 vim9script
2701 import './Xanimal.vim' as animal
2702
2703 var a: animal.Animal
2704 a = animal.Animal.new('fish', 'Eric')
2705 assert_equal('fish', a.kind)
2706 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002707
2708 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2709 assert_equal('cat', b.kind)
2710 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002711 END
2712 v9.CheckScriptSuccess(lines)
2713enddef
2714
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002715def Test_abstract_class()
2716 var lines =<< trim END
2717 vim9script
2718 abstract class Base
2719 this.name: string
2720 endclass
2721 class Person extends Base
2722 this.age: number
2723 endclass
2724 var p: Base = Person.new('Peter', 42)
2725 assert_equal('Peter', p.name)
2726 assert_equal(42, p.age)
2727 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002728 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002729
2730 lines =<< trim END
2731 vim9script
2732 abstract class Base
2733 this.name: string
2734 endclass
2735 class Person extends Base
2736 this.age: number
2737 endclass
2738 var p = Base.new('Peter')
2739 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002740 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002741
2742 lines =<< trim END
2743 abstract class Base
2744 this.name: string
2745 endclass
2746 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002747 v9.CheckSourceFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002748
2749 # Abstract class cannot have a "new" function
2750 lines =<< trim END
2751 vim9script
2752 abstract class Base
2753 def new()
2754 enddef
2755 endclass
2756 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002757 v9.CheckSourceFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002758enddef
2759
Bram Moolenaar486fc252023-01-18 14:51:07 +00002760def Test_closure_in_class()
2761 var lines =<< trim END
2762 vim9script
2763
2764 class Foo
2765 this.y: list<string> = ['B']
2766
2767 def new()
2768 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2769 enddef
2770 endclass
2771
2772 Foo.new()
2773 assert_equal(['A'], g:result)
2774 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002775 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00002776enddef
2777
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002778def Test_call_constructor_from_legacy()
2779 var lines =<< trim END
2780 vim9script
2781
2782 var newCalled = 'false'
2783
2784 class A
2785 def new()
2786 newCalled = 'true'
2787 enddef
2788 endclass
2789
2790 export def F(options = {}): any
2791 return A
2792 enddef
2793
2794 g:p = F()
2795 legacy call p.new()
2796 assert_equal('true', newCalled)
2797 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002798 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002799enddef
2800
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002801def Test_defer_with_object()
2802 var lines =<< trim END
2803 vim9script
2804
2805 class CWithEE
2806 def Enter()
2807 g:result ..= "entered/"
2808 enddef
2809 def Exit()
2810 g:result ..= "exited"
2811 enddef
2812 endclass
2813
2814 def With(ee: CWithEE, F: func)
2815 ee.Enter()
2816 defer ee.Exit()
2817 F()
2818 enddef
2819
2820 g:result = ''
2821 var obj = CWithEE.new()
2822 obj->With(() => {
2823 g:result ..= "called/"
2824 })
2825 assert_equal('entered/called/exited', g:result)
2826 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002827 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002828 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002829
2830 lines =<< trim END
2831 vim9script
2832
2833 class BaseWithEE
2834 def Enter()
2835 g:result ..= "entered-base/"
2836 enddef
2837 def Exit()
2838 g:result ..= "exited-base"
2839 enddef
2840 endclass
2841
2842 class CWithEE extends BaseWithEE
2843 def Enter()
2844 g:result ..= "entered-child/"
2845 enddef
2846 def Exit()
2847 g:result ..= "exited-child"
2848 enddef
2849 endclass
2850
2851 def With(ee: BaseWithEE, F: func)
2852 ee.Enter()
2853 defer ee.Exit()
2854 F()
2855 enddef
2856
2857 g:result = ''
2858 var obj = CWithEE.new()
2859 obj->With(() => {
2860 g:result ..= "called/"
2861 })
2862 assert_equal('entered-child/called/exited-child', g:result)
2863 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002864 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00002865 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002866enddef
2867
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002868" The following test used to crash Vim (Github issue #12676)
2869def Test_extends_method_crashes_vim()
2870 var lines =<< trim END
2871 vim9script
2872
2873 class Observer
2874 endclass
2875
2876 class Property
2877 this.value: any
2878
2879 def Set(v: any)
2880 if v != this.value
2881 this.value = v
2882 endif
2883 enddef
2884
2885 def Register(observer: Observer)
2886 enddef
2887 endclass
2888
2889 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002890 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002891 endclass
2892
2893 def Observe(obj: Property, who: Observer)
2894 obj.Register(who)
2895 enddef
2896
2897 var p = Bool.new(false)
2898 var myObserver = Observer.new()
2899
2900 Observe(p, myObserver)
2901
2902 p.Set(true)
2903 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002904 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002905enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002906
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002907" Test for calling a method in a class that is extended
2908def Test_call_method_in_extended_class()
2909 var lines =<< trim END
2910 vim9script
2911
2912 var prop_init_called = false
2913 var prop_register_called = false
2914
2915 class Property
2916 def Init()
2917 prop_init_called = true
2918 enddef
2919
2920 def Register()
2921 prop_register_called = true
2922 enddef
2923 endclass
2924
2925 class Bool extends Property
2926 endclass
2927
2928 def Observe(obj: Property)
2929 obj.Register()
2930 enddef
2931
2932 var p = Property.new()
2933 Observe(p)
2934
2935 p.Init()
2936 assert_true(prop_init_called)
2937 assert_true(prop_register_called)
2938 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002939 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002940enddef
2941
LemonBoyafe04662023-08-23 21:08:11 +02002942def Test_instanceof()
2943 var lines =<< trim END
2944 vim9script
2945
2946 class Base1
2947 endclass
2948
2949 class Base2 extends Base1
2950 endclass
2951
2952 interface Intf1
2953 endinterface
2954
2955 class Mix1 implements Intf1
2956 endclass
2957
2958 class Base3 extends Mix1
2959 endclass
2960
2961 var b1 = Base1.new()
2962 var b2 = Base2.new()
2963 var b3 = Base3.new()
2964
2965 assert_true(instanceof(b1, Base1))
2966 assert_true(instanceof(b2, Base1))
2967 assert_false(instanceof(b1, Base2))
2968 assert_true(instanceof(b3, Mix1))
2969 assert_false(instanceof(b3, []))
2970 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002971
2972 def Foo()
2973 var a1 = Base1.new()
2974 var a2 = Base2.new()
2975 var a3 = Base3.new()
2976
2977 assert_true(instanceof(a1, Base1))
2978 assert_true(instanceof(a2, Base1))
2979 assert_false(instanceof(a1, Base2))
2980 assert_true(instanceof(a3, Mix1))
2981 assert_false(instanceof(a3, []))
2982 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2983 enddef
2984 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002985 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002986 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02002987enddef
2988
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002989" Test for calling a method in the parent class that is extended partially.
2990" This used to fail with the 'E118: Too many arguments for function: Text' error
2991" message (Github issue #12524).
2992def Test_call_method_in_parent_class()
2993 var lines =<< trim END
2994 vim9script
2995
2996 class Widget
2997 this._lnum: number = 1
2998
2999 def SetY(lnum: number)
3000 this._lnum = lnum
3001 enddef
3002
3003 def Text(): string
3004 return ''
3005 enddef
3006 endclass
3007
3008 class Foo extends Widget
3009 def Text(): string
3010 return '<Foo>'
3011 enddef
3012 endclass
3013
3014 def Stack(w1: Widget, w2: Widget): list<Widget>
3015 w1.SetY(1)
3016 w2.SetY(2)
3017 return [w1, w2]
3018 enddef
3019
3020 var foo1 = Foo.new()
3021 var foo2 = Foo.new()
3022 var l = Stack(foo1, foo2)
3023 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003024 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003025enddef
3026
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003027" Test for calling methods from three levels of classes
3028def Test_multi_level_method_call()
3029 var lines =<< trim END
3030 vim9script
3031
3032 var A_func1: number = 0
3033 var A_func2: number = 0
3034 var A_func3: number = 0
3035 var B_func2: number = 0
3036 var B_func3: number = 0
3037 var C_func3: number = 0
3038
3039 class A
3040 def Func1()
3041 A_func1 += 1
3042 enddef
3043
3044 def Func2()
3045 A_func2 += 1
3046 enddef
3047
3048 def Func3()
3049 A_func3 += 1
3050 enddef
3051 endclass
3052
3053 class B extends A
3054 def Func2()
3055 B_func2 += 1
3056 enddef
3057
3058 def Func3()
3059 B_func3 += 1
3060 enddef
3061 endclass
3062
3063 class C extends B
3064 def Func3()
3065 C_func3 += 1
3066 enddef
3067 endclass
3068
3069 def A_CallFuncs(a: A)
3070 a.Func1()
3071 a.Func2()
3072 a.Func3()
3073 enddef
3074
3075 def B_CallFuncs(b: B)
3076 b.Func1()
3077 b.Func2()
3078 b.Func3()
3079 enddef
3080
3081 def C_CallFuncs(c: C)
3082 c.Func1()
3083 c.Func2()
3084 c.Func3()
3085 enddef
3086
3087 var cobj = C.new()
3088 A_CallFuncs(cobj)
3089 B_CallFuncs(cobj)
3090 C_CallFuncs(cobj)
3091 assert_equal(3, A_func1)
3092 assert_equal(0, A_func2)
3093 assert_equal(0, A_func3)
3094 assert_equal(3, B_func2)
3095 assert_equal(0, B_func3)
3096 assert_equal(3, C_func3)
3097 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003098 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003099enddef
3100
3101" Test for using members from three levels of classes
3102def Test_multi_level_member_access()
3103 var lines =<< trim END
3104 vim9script
3105
3106 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003107 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003108 endclass
3109
3110 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003111 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003112 endclass
3113
3114 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003115 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003116 endclass
3117
3118 def A_members(a: A)
3119 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003120 enddef
3121
3122 def B_members(b: B)
3123 b.val1 += 1
3124 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003125 enddef
3126
3127 def C_members(c: C)
3128 c.val1 += 1
3129 c.val2 += 1
3130 c.val3 += 1
3131 enddef
3132
3133 var cobj = C.new()
3134 A_members(cobj)
3135 B_members(cobj)
3136 C_members(cobj)
3137 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003138 assert_equal(2, cobj.val2)
3139 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003140 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003141 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003142enddef
3143
LemonBoy0ffc17a2023-08-20 18:09:11 +02003144" Test expansion of <stack> with class methods.
3145def Test_stack_expansion_with_methods()
3146 var lines =<< trim END
3147 vim9script
3148
3149 class C
3150 def M1()
3151 F0()
3152 enddef
3153 endclass
3154
3155 def F0()
3156 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3157 enddef
3158
3159 def F()
3160 C.new().M1()
3161 enddef
3162
3163 F()
3164 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003165 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003166enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003167
3168" Test the return type of the new() constructor
3169def Test_new_return_type()
3170 # new() uses the default return type and there is no return statement
3171 var lines =<< trim END
3172 vim9script
3173
3174 class C
3175 this._bufnr: number
3176
3177 def new(this._bufnr)
3178 if !bufexists(this._bufnr)
3179 this._bufnr = -1
3180 endif
3181 enddef
3182 endclass
3183
3184 var c = C.new(12345)
3185 assert_equal('object<C>', typename(c))
3186
3187 var v1: C
3188 v1 = C.new(12345)
3189 assert_equal('object<C>', typename(v1))
3190
3191 def F()
3192 var v2: C
3193 v2 = C.new(12345)
3194 assert_equal('object<C>', typename(v2))
3195 enddef
3196 F()
3197 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003198 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003199
3200 # new() uses the default return type and an empty 'return' statement
3201 lines =<< trim END
3202 vim9script
3203
3204 class C
3205 this._bufnr: number
3206
3207 def new(this._bufnr)
3208 if !bufexists(this._bufnr)
3209 this._bufnr = -1
3210 return
3211 endif
3212 enddef
3213 endclass
3214
3215 var c = C.new(12345)
3216 assert_equal('object<C>', typename(c))
3217
3218 var v1: C
3219 v1 = C.new(12345)
3220 assert_equal('object<C>', typename(v1))
3221
3222 def F()
3223 var v2: C
3224 v2 = C.new(12345)
3225 assert_equal('object<C>', typename(v2))
3226 enddef
3227 F()
3228 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003229 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003230
3231 # new() uses "any" return type and returns "this"
3232 lines =<< trim END
3233 vim9script
3234
3235 class C
3236 this._bufnr: number
3237
3238 def new(this._bufnr): any
3239 if !bufexists(this._bufnr)
3240 this._bufnr = -1
3241 return this
3242 endif
3243 enddef
3244 endclass
3245 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003246 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003247
3248 # new() uses 'Dict' return type and returns a Dict
3249 lines =<< trim END
3250 vim9script
3251
3252 class C
3253 this._state: dict<any>
3254
3255 def new(): dict<any>
3256 this._state = {}
3257 return this._state
3258 enddef
3259 endclass
3260
3261 var c = C.new()
3262 assert_equal('object<C>', typename(c))
3263 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003264 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003265enddef
3266
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003267" Test for checking a member initialization type at run time.
3268def Test_runtime_type_check_for_member_init()
3269 var lines =<< trim END
3270 vim9script
3271
3272 var retnum: bool = false
3273
3274 def F(): any
3275 retnum = !retnum
3276 if retnum
3277 return 1
3278 else
3279 return "hello"
3280 endif
3281 enddef
3282
3283 class C
3284 this._foo: bool = F()
3285 endclass
3286
3287 var c1 = C.new()
3288 var c2 = C.new()
3289 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003290 v9.CheckSourceFailure(lines, 'E1012:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003291enddef
3292
3293" Test for locking a variable referring to an object and reassigning to another
3294" object.
3295def Test_object_lockvar()
3296 var lines =<< trim END
3297 vim9script
3298
3299 class C
3300 this.val: number
3301 def new(this.val)
3302 enddef
3303 endclass
3304
3305 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3306 lockvar 2 some_dict
3307
3308 var current: C
3309 current = some_dict['c']
3310 assert_equal(3, current.val)
3311 current = some_dict['b']
3312 assert_equal(2, current.val)
3313
3314 def F()
3315 current = some_dict['c']
3316 enddef
3317
3318 def G()
3319 current = some_dict['b']
3320 enddef
3321
3322 F()
3323 assert_equal(3, current.val)
3324 G()
3325 assert_equal(2, current.val)
3326 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003327 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003328enddef
3329
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003330" Test for a private object method
3331def Test_private_object_method()
3332 # Try calling a private method using an object (at the script level)
3333 var lines =<< trim END
3334 vim9script
3335
3336 class A
3337 def _Foo(): number
3338 return 1234
3339 enddef
3340 endclass
3341 var a = A.new()
3342 a._Foo()
3343 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003344 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003345
3346 # Try calling a private method using an object (from a def function)
3347 lines =<< trim END
3348 vim9script
3349
3350 class A
3351 def _Foo(): number
3352 return 1234
3353 enddef
3354 endclass
3355 def T()
3356 var a = A.new()
3357 a._Foo()
3358 enddef
3359 T()
3360 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003361 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003362
3363 # Use a private method from another object method (in script context)
3364 lines =<< trim END
3365 vim9script
3366
3367 class A
3368 def _Foo(): number
3369 return 1234
3370 enddef
3371 def Bar(): number
3372 return this._Foo()
3373 enddef
3374 endclass
3375 var a = A.new()
3376 assert_equal(1234, a.Bar())
3377 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003378 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003379
3380 # Use a private method from another object method (def function context)
3381 lines =<< trim END
3382 vim9script
3383
3384 class A
3385 def _Foo(): number
3386 return 1234
3387 enddef
3388 def Bar(): number
3389 return this._Foo()
3390 enddef
3391 endclass
3392 def T()
3393 var a = A.new()
3394 assert_equal(1234, a.Bar())
3395 enddef
3396 T()
3397 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003398 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003399
3400 # Try calling a private method without the "this" prefix
3401 lines =<< trim END
3402 vim9script
3403
3404 class A
3405 def _Foo(): number
3406 return 1234
3407 enddef
3408 def Bar(): number
3409 return _Foo()
3410 enddef
3411 endclass
3412 var a = A.new()
3413 a.Bar()
3414 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003415 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003416
3417 # Try calling a private method using the class name
3418 lines =<< trim END
3419 vim9script
3420
3421 class A
3422 def _Foo(): number
3423 return 1234
3424 enddef
3425 endclass
3426 A._Foo()
3427 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003428 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003429
3430 # Try to use "public" keyword when defining a private method
3431 lines =<< trim END
3432 vim9script
3433
3434 class A
3435 public def _Foo()
3436 enddef
3437 endclass
3438 var a = A.new()
3439 a._Foo()
3440 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003441 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003442
3443 # Define two private methods with the same name
3444 lines =<< trim END
3445 vim9script
3446
3447 class A
3448 def _Foo()
3449 enddef
3450 def _Foo()
3451 enddef
3452 endclass
3453 var a = A.new()
3454 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003455 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003456
3457 # Define a private method and a object method with the same name
3458 lines =<< trim END
3459 vim9script
3460
3461 class A
3462 def _Foo()
3463 enddef
3464 def Foo()
3465 enddef
3466 endclass
3467 var a = A.new()
3468 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003469 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003470
3471 # Define an object method and a private method with the same name
3472 lines =<< trim END
3473 vim9script
3474
3475 class A
3476 def Foo()
3477 enddef
3478 def _Foo()
3479 enddef
3480 endclass
3481 var a = A.new()
3482 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003483 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003484
3485 # Call a public method and a private method from a private method
3486 lines =<< trim END
3487 vim9script
3488
3489 class A
3490 def Foo(): number
3491 return 100
3492 enddef
3493 def _Bar(): number
3494 return 200
3495 enddef
3496 def _Baz()
3497 assert_equal(100, this.Foo())
3498 assert_equal(200, this._Bar())
3499 enddef
3500 def T()
3501 this._Baz()
3502 enddef
3503 endclass
3504 var a = A.new()
3505 a.T()
3506 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003507 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003508
3509 # Try calling a private method from another class
3510 lines =<< trim END
3511 vim9script
3512
3513 class A
3514 def _Foo(): number
3515 return 100
3516 enddef
3517 endclass
3518 class B
3519 def Foo(): number
3520 var a = A.new()
3521 a._Foo()
3522 enddef
3523 endclass
3524 var b = B.new()
3525 b.Foo()
3526 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003527 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003528
3529 # Call a private object method from a child class object method
3530 lines =<< trim END
3531 vim9script
3532 class A
3533 def _Foo(): number
3534 return 1234
3535 enddef
3536 endclass
3537 class B extends A
3538 def Bar()
3539 enddef
3540 endclass
3541 class C extends B
3542 def Baz(): number
3543 return this._Foo()
3544 enddef
3545 endclass
3546 var c = C.new()
3547 assert_equal(1234, c.Baz())
3548 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003549 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003550
3551 # Call a private object method from a child class object
3552 lines =<< trim END
3553 vim9script
3554 class A
3555 def _Foo(): number
3556 return 1234
3557 enddef
3558 endclass
3559 class B extends A
3560 def Bar()
3561 enddef
3562 endclass
3563 class C extends B
3564 def Baz(): number
3565 enddef
3566 endclass
3567 var c = C.new()
3568 assert_equal(1234, c._Foo())
3569 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003570 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003571
3572 # Using "_" prefix in a method name should fail outside of a class
3573 lines =<< trim END
3574 vim9script
3575 def _Foo(): number
3576 return 1234
3577 enddef
3578 var a = _Foo()
3579 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003580 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003581enddef
3582
3583" Test for an private class method
3584def Test_private_class_method()
3585 # Try calling a class private method (at the script level)
3586 var lines =<< trim END
3587 vim9script
3588
3589 class A
3590 static def _Foo(): number
3591 return 1234
3592 enddef
3593 endclass
3594 A._Foo()
3595 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003596 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003597
3598 # Try calling a class private method (from a def function)
3599 lines =<< trim END
3600 vim9script
3601
3602 class A
3603 static def _Foo(): number
3604 return 1234
3605 enddef
3606 endclass
3607 def T()
3608 A._Foo()
3609 enddef
3610 T()
3611 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003612 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003613
3614 # Try calling a class private method using an object (at the script level)
3615 lines =<< trim END
3616 vim9script
3617
3618 class A
3619 static def _Foo(): number
3620 return 1234
3621 enddef
3622 endclass
3623 var a = A.new()
3624 a._Foo()
3625 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003626 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003627
3628 # Try calling a class private method using an object (from a def function)
3629 lines =<< trim END
3630 vim9script
3631
3632 class A
3633 static def _Foo(): number
3634 return 1234
3635 enddef
3636 endclass
3637 def T()
3638 var a = A.new()
3639 a._Foo()
3640 enddef
3641 T()
3642 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003643 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003644
3645 # Use a class private method from an object method
3646 lines =<< trim END
3647 vim9script
3648
3649 class A
3650 static def _Foo(): number
3651 return 1234
3652 enddef
3653 def Bar()
3654 assert_equal(1234, A._Foo())
3655 enddef
3656 endclass
3657 var a = A.new()
3658 a.Bar()
3659 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003660 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003661
3662 # Use a class private method from another class private method
3663 lines =<< trim END
3664 vim9script
3665
3666 class A
3667 static def _Foo1(): number
3668 return 1234
3669 enddef
3670 static def _Foo2()
3671 assert_equal(1234, A._Foo1())
3672 enddef
3673 def Bar()
3674 A._Foo2()
3675 enddef
3676 endclass
3677 var a = A.new()
3678 a.Bar()
3679 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003680 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003681
3682 # Declare a class method and a class private method with the same name
3683 lines =<< trim END
3684 vim9script
3685
3686 class A
3687 static def _Foo()
3688 enddef
3689 static def Foo()
3690 enddef
3691 endclass
3692 var a = A.new()
3693 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003694 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003695
3696 # Try calling a class private method from another class
3697 lines =<< trim END
3698 vim9script
3699
3700 class A
3701 static def _Foo(): number
3702 return 1234
3703 enddef
3704 endclass
3705 class B
3706 def Foo(): number
3707 return A._Foo()
3708 enddef
3709 endclass
3710 var b = B.new()
3711 assert_equal(1234, b.Foo())
3712 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003713 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003714
3715 # Call a private class method from a child class object method
3716 lines =<< trim END
3717 vim9script
3718 class A
3719 static def _Foo(): number
3720 return 1234
3721 enddef
3722 endclass
3723 class B extends A
3724 def Bar()
3725 enddef
3726 endclass
3727 class C extends B
3728 def Baz(): number
3729 return A._Foo()
3730 enddef
3731 endclass
3732 var c = C.new()
3733 assert_equal(1234, c.Baz())
3734 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003735 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003736
3737 # Call a private class method from a child class private class method
3738 lines =<< trim END
3739 vim9script
3740 class A
3741 static def _Foo(): number
3742 return 1234
3743 enddef
3744 endclass
3745 class B extends A
3746 def Bar()
3747 enddef
3748 endclass
3749 class C extends B
3750 static def Baz(): number
3751 return A._Foo()
3752 enddef
3753 endclass
3754 assert_equal(1234, C.Baz())
3755 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003756 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003757
3758 # Call a private class method from a child class object
3759 lines =<< trim END
3760 vim9script
3761 class A
3762 static def _Foo(): number
3763 return 1234
3764 enddef
3765 endclass
3766 class B extends A
3767 def Bar()
3768 enddef
3769 endclass
3770 class C extends B
3771 def Baz(): number
3772 enddef
3773 endclass
3774 var c = C.new()
3775 assert_equal(1234, C._Foo())
3776 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003777 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003778enddef
3779
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003780" Test for using the return value of a class/object method as a function
3781" argument.
3782def Test_objmethod_funcarg()
3783 var lines =<< trim END
3784 vim9script
3785
3786 class C
3787 def Foo(): string
3788 return 'foo'
3789 enddef
3790 endclass
3791
3792 def Bar(a: number, s: string): string
3793 return s
3794 enddef
3795
3796 def Baz(c: C)
3797 assert_equal('foo', Bar(10, c.Foo()))
3798 enddef
3799
3800 var t = C.new()
3801 Baz(t)
3802 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003803 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003804
3805 lines =<< trim END
3806 vim9script
3807
3808 class C
3809 static def Foo(): string
3810 return 'foo'
3811 enddef
3812 endclass
3813
3814 def Bar(a: number, s: string): string
3815 return s
3816 enddef
3817
3818 def Baz()
3819 assert_equal('foo', Bar(10, C.Foo()))
3820 enddef
3821
3822 Baz()
3823 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003824 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003825enddef
3826
Ernie Raelcf138d42023-09-06 20:45:03 +02003827def Test_static_inheritence()
3828 # subclasses get their own static copy
3829 var lines =<< trim END
3830 vim9script
3831
3832 class A
3833 static _svar: number
3834 this._mvar: number
3835 def new()
3836 _svar = 1
3837 this._mvar = 101
3838 enddef
3839 def AccessObject(): number
3840 return this._mvar
3841 enddef
3842 def AccessStaticThroughObject(): number
3843 return _svar
3844 enddef
3845 endclass
3846
3847 class B extends A
3848 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003849 this._mvar = 102
3850 enddef
3851 endclass
3852
3853 class C extends B
3854 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003855 this._mvar = 103
3856 enddef
3857
3858 def AccessPrivateStaticThroughClassName(): number
3859 assert_equal(1, A._svar)
Ernie Raelcf138d42023-09-06 20:45:03 +02003860 return 444
3861 enddef
3862 endclass
3863
3864 var oa = A.new()
3865 var ob = B.new()
3866 var oc = C.new()
3867 assert_equal(101, oa.AccessObject())
3868 assert_equal(102, ob.AccessObject())
3869 assert_equal(103, oc.AccessObject())
3870
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003871 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private member: _svar')
Ernie Raelcf138d42023-09-06 20:45:03 +02003872
3873 # verify object properly resolves to correct static
3874 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003875 assert_equal(1, ob.AccessStaticThroughObject())
3876 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02003877 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003878 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02003879enddef
3880
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003881" Test for declaring duplicate object and class members
3882def Test_dup_member_variable()
3883 # Duplicate member variable
3884 var lines =<< trim END
3885 vim9script
3886 class C
3887 this.val = 10
3888 this.val = 20
3889 endclass
3890 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003891 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003892
3893 # Duplicate private member variable
3894 lines =<< trim END
3895 vim9script
3896 class C
3897 this._val = 10
3898 this._val = 20
3899 endclass
3900 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003901 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003902
3903 # Duplicate public member variable
3904 lines =<< trim END
3905 vim9script
3906 class C
3907 public this.val = 10
3908 public this.val = 20
3909 endclass
3910 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003911 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003912
3913 # Duplicate private member variable
3914 lines =<< trim END
3915 vim9script
3916 class C
3917 this.val = 10
3918 this._val = 20
3919 endclass
3920 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003921 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003922
3923 # Duplicate public and private member variable
3924 lines =<< trim END
3925 vim9script
3926 class C
3927 this._val = 20
3928 public this.val = 10
3929 endclass
3930 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003931 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003932
3933 # Duplicate class member variable
3934 lines =<< trim END
3935 vim9script
3936 class C
3937 static s: string = "abc"
3938 static _s: string = "def"
3939 endclass
3940 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003941 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003942
3943 # Duplicate public and private class member variable
3944 lines =<< trim END
3945 vim9script
3946 class C
3947 public static s: string = "abc"
3948 static _s: string = "def"
3949 endclass
3950 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003951 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003952
3953 # Duplicate class and object member variable
3954 lines =<< trim END
3955 vim9script
3956 class C
3957 static val = 10
3958 this.val = 20
3959 def new()
3960 enddef
3961 endclass
3962 var c = C.new()
3963 assert_equal(10, C.val)
3964 assert_equal(20, c.val)
3965 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003966 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003967
3968 # Duplicate object member variable in a derived class
3969 lines =<< trim END
3970 vim9script
3971 class A
3972 this.val = 10
3973 endclass
3974 class B extends A
3975 endclass
3976 class C extends B
3977 this.val = 20
3978 endclass
3979 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003980 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003981
3982 # Duplicate object private member variable in a derived class
3983 lines =<< trim END
3984 vim9script
3985 class A
3986 this._val = 10
3987 endclass
3988 class B extends A
3989 endclass
3990 class C extends B
3991 this._val = 20
3992 endclass
3993 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003994 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003995
3996 # Duplicate object private member variable in a derived class
3997 lines =<< trim END
3998 vim9script
3999 class A
4000 this.val = 10
4001 endclass
4002 class B extends A
4003 endclass
4004 class C extends B
4005 this._val = 20
4006 endclass
4007 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004008 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004009
4010 # Duplicate object member variable in a derived class
4011 lines =<< trim END
4012 vim9script
4013 class A
4014 this._val = 10
4015 endclass
4016 class B extends A
4017 endclass
4018 class C extends B
4019 this.val = 20
4020 endclass
4021 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004022 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004023
4024 # Two member variables with a common prefix
4025 lines =<< trim END
4026 vim9script
4027 class A
4028 public static svar2: number
4029 public static svar: number
4030 endclass
4031 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004032 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004033enddef
4034
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004035" Test for accessing a private member outside a class in a def function
4036def Test_private_member_access_outside_class()
4037 # private object member variable
4038 var lines =<< trim END
4039 vim9script
4040 class A
4041 this._val = 10
4042 def GetVal(): number
4043 return this._val
4044 enddef
4045 endclass
4046 def T()
4047 var a = A.new()
4048 a._val = 20
4049 enddef
4050 T()
4051 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004052 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004053
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004054 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004055 lines =<< trim END
4056 vim9script
4057 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004058 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004059 endclass
4060 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004061 var a = A.new()
4062 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004063 enddef
4064 T()
4065 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004066 v9.CheckSourceFailure(lines, 'E1089: Unknown variable: _a')
Ernie Rael18143d32023-09-04 22:30:41 +02004067
4068 # private static member variable
4069 lines =<< trim END
4070 vim9script
4071 class A
4072 static _val = 10
4073 endclass
4074 def T()
4075 var a = A.new()
4076 var x = a._val
4077 enddef
4078 T()
4079 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004080 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004081
4082 # private static member variable
4083 lines =<< trim END
4084 vim9script
4085 class A
4086 static _val = 10
4087 endclass
4088 def T()
4089 var a = A.new()
4090 a._val = 3
4091 enddef
4092 T()
4093 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004094 v9.CheckSourceFailure(lines, 'E1374: Class member "_val" accessible only inside class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004095
4096 # private static class variable
4097 lines =<< trim END
4098 vim9script
4099 class A
4100 static _val = 10
4101 endclass
4102 def T()
4103 var x = A._val
4104 enddef
4105 T()
4106 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004107 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004108
4109 # private static class variable
4110 lines =<< trim END
4111 vim9script
4112 class A
4113 static _val = 10
4114 endclass
4115 def T()
4116 A._val = 3
4117 enddef
4118 T()
4119 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004120 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004121enddef
4122
4123" Test for changing the member access of an interface in a implementation class
4124def Test_change_interface_member_access()
4125 var lines =<< trim END
4126 vim9script
4127 interface A
4128 public this.val: number
4129 endinterface
4130 class B implements A
4131 this.val = 10
4132 endclass
4133 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004134 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004135
4136 lines =<< trim END
4137 vim9script
4138 interface A
4139 this.val: number
4140 endinterface
4141 class B implements A
4142 public this.val = 10
4143 endclass
4144 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004145 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004146enddef
4147
4148" Test for trying to change a readonly member from a def function
4149def Test_readonly_member_change_in_def_func()
4150 var lines =<< trim END
4151 vim9script
4152 class A
4153 this.val: number
4154 endclass
4155 def T()
4156 var a = A.new()
4157 a.val = 20
4158 enddef
4159 T()
4160 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004161 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004162enddef
4163
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004164" Test for reading and writing a class member from a def function
4165def Test_modify_class_member_from_def_function()
4166 var lines =<< trim END
4167 vim9script
4168 class A
4169 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004170 public static var2: list<number> = [1, 2]
4171 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004172 static _priv_var4: number = 40
4173 endclass
4174 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004175 assert_equal([1, 2], A.var2)
4176 assert_equal({a: 1, b: 2}, A.var3)
4177 A.var2 = [3, 4]
4178 A.var3 = {c: 3, d: 4}
4179 assert_equal([3, 4], A.var2)
4180 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004181 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4182 enddef
4183 T()
4184 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004185 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004186enddef
4187
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004188" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004189def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004190 var lines =<< trim END
4191 vim9script
4192 class A
4193 public static svar1: list<number> = [1]
4194 public static svar2: list<number> = [2]
4195 endclass
4196
4197 A.svar1->add(3)
4198 A.svar2->add(4)
4199 assert_equal([1, 3], A.svar1)
4200 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004201
4202 def Foo()
4203 A.svar1->add(7)
4204 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004205 assert_equal([1, 3, 7], A.svar1)
4206 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004207 enddef
4208 Foo()
4209 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004210 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004211
4212 # Cannot read from a class variable using an object in script context
4213 lines =<< trim END
4214 vim9script
4215 class A
4216 public this.var1: number
4217 public static svar2: list<number> = [1]
4218 endclass
4219
4220 var a = A.new()
4221 echo a.svar2
4222 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004223 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004224
4225 # Cannot write to a class variable using an object in script context
4226 lines =<< trim END
4227 vim9script
4228 class A
4229 public this.var1: number
4230 public static svar2: list<number> = [1]
4231 endclass
4232
4233 var a = A.new()
4234 a.svar2 = [2]
4235 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004236 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004237
4238 # Cannot read from a class variable using an object in def method context
4239 lines =<< trim END
4240 vim9script
4241 class A
4242 public this.var1: number
4243 public static svar2: list<number> = [1]
4244 endclass
4245
4246 def T()
4247 var a = A.new()
4248 echo a.svar2
4249 enddef
4250 T()
4251 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004252 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004253
4254 # Cannot write to a class variable using an object in def method context
4255 lines =<< trim END
4256 vim9script
4257 class A
4258 public this.var1: number
4259 public static svar2: list<number> = [1]
4260 endclass
4261
4262 def T()
4263 var a = A.new()
4264 a.svar2 = [2]
4265 enddef
4266 T()
4267 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004268 v9.CheckSourceFailure(lines, 'E1374: Class member "svar2" accessible only inside class "A"')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004269enddef
4270
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004271" Test for using a interface method using a child object
4272def Test_interface_method_from_child()
4273 var lines =<< trim END
4274 vim9script
4275
4276 interface A
4277 def Foo(): string
4278 endinterface
4279
4280 class B implements A
4281 def Foo(): string
4282 return 'foo'
4283 enddef
4284 endclass
4285
4286 class C extends B
4287 def Bar(): string
4288 return 'bar'
4289 enddef
4290 endclass
4291
4292 def T1(a: A)
4293 assert_equal('foo', a.Foo())
4294 enddef
4295
4296 def T2(b: B)
4297 assert_equal('foo', b.Foo())
4298 enddef
4299
4300 var c = C.new()
4301 T1(c)
4302 T2(c)
4303 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004304 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004305enddef
4306
4307" Test for using an interface method using a child object when it is overridden
4308" by the child class.
4309" FIXME: This test fails.
4310" def Test_interface_overridden_method_from_child()
4311" var lines =<< trim END
4312" vim9script
4313"
4314" interface A
4315" def Foo(): string
4316" endinterface
4317"
4318" class B implements A
4319" def Foo(): string
4320" return 'b-foo'
4321" enddef
4322" endclass
4323"
4324" class C extends B
4325" def Bar(): string
4326" return 'bar'
4327" enddef
4328" def Foo(): string
4329" return 'c-foo'
4330" enddef
4331" endclass
4332"
4333" def T1(a: A)
4334" assert_equal('c-foo', a.Foo())
4335" enddef
4336"
4337" def T2(b: B)
4338" assert_equal('c-foo', b.Foo())
4339" enddef
4340"
4341" var c = C.new()
4342" T1(c)
4343" T2(c)
4344" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004345" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004346" enddef
4347
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004348" Test for abstract methods
4349def Test_abstract_method()
4350 # Use two abstract methods
4351 var lines =<< trim END
4352 vim9script
4353 abstract class A
4354 def M1(): number
4355 return 10
4356 enddef
4357 abstract def M2(): number
4358 abstract def M3(): number
4359 endclass
4360 class B extends A
4361 def M2(): number
4362 return 20
4363 enddef
4364 def M3(): number
4365 return 30
4366 enddef
4367 endclass
4368 var b = B.new()
4369 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4370 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004371 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004372
4373 # Don't define an abstract method
4374 lines =<< trim END
4375 vim9script
4376 abstract class A
4377 abstract def Foo()
4378 endclass
4379 class B extends A
4380 endclass
4381 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004382 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004383
4384 # Use abstract method in a concrete class
4385 lines =<< trim END
4386 vim9script
4387 class A
4388 abstract def Foo()
4389 endclass
4390 class B extends A
4391 endclass
4392 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004393 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004394
4395 # Use abstract method in an interface
4396 lines =<< trim END
4397 vim9script
4398 interface A
4399 abstract def Foo()
4400 endinterface
4401 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004402 def Foo()
4403 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004404 endclass
4405 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004406 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004407
4408 # Abbreviate the "abstract" keyword
4409 lines =<< trim END
4410 vim9script
4411 class A
4412 abs def Foo()
4413 endclass
4414 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004415 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004416
4417 # Use "abstract" with a member variable
4418 lines =<< trim END
4419 vim9script
4420 abstract class A
4421 abstract this.val = 10
4422 endclass
4423 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004424 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004425
4426 # Use a static abstract method
4427 lines =<< trim END
4428 vim9script
4429 abstract class A
4430 abstract static def Foo(): number
4431 endclass
4432 class B extends A
4433 static def Foo(): number
4434 return 4
4435 enddef
4436 endclass
4437 assert_equal(4, B.Foo())
4438 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004439 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004440
4441 # Type mismatch between abstract method and concrete method
4442 lines =<< trim END
4443 vim9script
4444 abstract class A
4445 abstract def Foo(a: string, b: number): list<number>
4446 endclass
4447 class B extends A
4448 def Foo(a: number, b: string): list<string>
4449 return []
4450 enddef
4451 endclass
4452 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004453 v9.CheckSourceFailure(lines, 'E1383: Method "Foo": type mismatch, expected func(string, number): list<number> but got func(number, string): list<string>')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004454
4455 # Use an abstract class to invoke an abstract method
4456 # FIXME: This should fail
4457 lines =<< trim END
4458 vim9script
4459 abstract class A
4460 abstract static def Foo()
4461 endclass
4462 A.Foo()
4463 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004464 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004465
4466 # Invoke an abstract method from a def function
4467 lines =<< trim END
4468 vim9script
4469 abstract class A
4470 abstract def Foo(): list<number>
4471 endclass
4472 class B extends A
4473 def Foo(): list<number>
4474 return [3, 5]
4475 enddef
4476 endclass
4477 def Bar(c: B)
4478 assert_equal([3, 5], c.Foo())
4479 enddef
4480 var b = B.new()
4481 Bar(b)
4482 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004483 v9.CheckSourceSuccess(lines)
4484enddef
4485
4486" Test for calling a class method from a subclass
4487def Test_class_method_call_from_subclass()
4488 # class method call from a subclass
4489 var lines =<< trim END
4490 vim9script
4491
4492 class A
4493 static def Foo()
4494 echo "foo"
4495 enddef
4496 endclass
4497
4498 class B extends A
4499 def Bar()
4500 Foo()
4501 enddef
4502 endclass
4503
4504 var b = B.new()
4505 b.Bar()
4506 END
4507 v9.CheckSourceFailure(lines, 'E1374: Class member "Foo" accessible only inside class "A"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004508enddef
4509
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004510" Test for calling a class method using an object in a def function context and
4511" script context.
4512def Test_class_method_call_using_object()
4513 # script context
4514 var lines =<< trim END
4515 vim9script
4516 class A
4517 static def Foo(): list<string>
4518 return ['a', 'b']
4519 enddef
4520 def Bar()
4521 assert_equal(['a', 'b'], A.Foo())
4522 assert_equal(['a', 'b'], Foo())
4523 enddef
4524 endclass
4525
4526 def T()
4527 assert_equal(['a', 'b'], A.Foo())
4528 var t_a = A.new()
4529 t_a.Bar()
4530 enddef
4531
4532 assert_equal(['a', 'b'], A.Foo())
4533 var a = A.new()
4534 a.Bar()
4535 T()
4536 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004537 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004538
4539 # script context
4540 lines =<< trim END
4541 vim9script
4542 class A
4543 static def Foo(): string
4544 return 'foo'
4545 enddef
4546 endclass
4547
4548 var a = A.new()
4549 assert_equal('foo', a.Foo())
4550 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004551 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004552
4553 # def function context
4554 lines =<< trim END
4555 vim9script
4556 class A
4557 static def Foo(): string
4558 return 'foo'
4559 enddef
4560 endclass
4561
4562 def T()
4563 var a = A.new()
4564 assert_equal('foo', a.Foo())
4565 enddef
4566 T()
4567 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004568 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
4569enddef
4570
4571def Test_class_variable()
4572 var lines =<< trim END
4573 vim9script
4574
4575 class A
4576 public static val: number = 10
4577 static def ClassFunc()
4578 assert_equal(10, val)
4579 enddef
4580 def ObjFunc()
4581 assert_equal(10, val)
4582 enddef
4583 endclass
4584
4585 class B extends A
4586 endclass
4587
4588 assert_equal(10, A.val)
4589 A.ClassFunc()
4590 var a = A.new()
4591 a.ObjFunc()
4592 var b = B.new()
4593 b.ObjFunc()
4594
4595 def T1(a1: A)
4596 a1.ObjFunc()
4597 A.ClassFunc()
4598 enddef
4599 T1(b)
4600
4601 A.val = 20
4602 assert_equal(20, A.val)
4603 END
4604 v9.CheckSourceSuccess(lines)
4605
4606 # Modifying a parent class variable from a child class method
4607 lines =<< trim END
4608 vim9script
4609
4610 class A
4611 static val: number = 10
4612 endclass
4613
4614 class B extends A
4615 static def ClassFunc()
4616 val = 20
4617 enddef
4618 endclass
4619 B.ClassFunc()
4620 END
4621 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4622
4623 # Reading a parent class variable from a child class method
4624 lines =<< trim END
4625 vim9script
4626
4627 class A
4628 static val: number = 10
4629 endclass
4630
4631 class B extends A
4632 static def ClassFunc()
4633 var i = val
4634 enddef
4635 endclass
4636 B.ClassFunc()
4637 END
4638 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4639
4640 # Modifying a parent class variable from a child object method
4641 lines =<< trim END
4642 vim9script
4643
4644 class A
4645 static val: number = 10
4646 endclass
4647
4648 class B extends A
4649 def ObjFunc()
4650 val = 20
4651 enddef
4652 endclass
4653 var b = B.new()
4654 b.ObjFunc()
4655 END
4656 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4657
4658 # Reading a parent class variable from a child object method
4659 lines =<< trim END
4660 vim9script
4661
4662 class A
4663 static val: number = 10
4664 endclass
4665
4666 class B extends A
4667 def ObjFunc()
4668 var i = val
4669 enddef
4670 endclass
4671 var b = B.new()
4672 b.ObjFunc()
4673 END
4674 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4675
4676 # Modifying a class variable using an object at script level
4677 lines =<< trim END
4678 vim9script
4679
4680 class A
4681 static val: number = 10
4682 endclass
4683 var a = A.new()
4684 a.val = 20
4685 END
4686 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4687
4688 # Reading a class variable using an object at script level
4689 lines =<< trim END
4690 vim9script
4691
4692 class A
4693 static val: number = 10
4694 endclass
4695 var a = A.new()
4696 var i = a.val
4697 END
4698 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4699
4700 # Modifying a class variable using an object at function level
4701 lines =<< trim END
4702 vim9script
4703
4704 class A
4705 static val: number = 10
4706 endclass
4707
4708 def T()
4709 var a = A.new()
4710 a.val = 20
4711 enddef
4712 T()
4713 END
4714 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4715
4716 # Reading a class variable using an object at function level
4717 lines =<< trim END
4718 vim9script
4719
4720 class A
4721 static val: number = 10
4722 endclass
4723 def T()
4724 var a = A.new()
4725 var i = a.val
4726 enddef
4727 T()
4728 END
4729 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4730enddef
4731
4732" Test for using a duplicate class method and class variable in a child class
4733def Test_dup_class_member()
4734 # duplicate class variable, class method and overridden object method
4735 var lines =<< trim END
4736 vim9script
4737 class A
4738 static sval = 100
4739 static def Check()
4740 assert_equal(100, sval)
4741 enddef
4742 def GetVal(): number
4743 return sval
4744 enddef
4745 endclass
4746
4747 class B extends A
4748 static sval = 200
4749 static def Check()
4750 assert_equal(200, sval)
4751 enddef
4752 def GetVal(): number
4753 return sval
4754 enddef
4755 endclass
4756
4757 def T1(aa: A): number
4758 return aa.GetVal()
4759 enddef
4760
4761 def T2(bb: B): number
4762 return bb.GetVal()
4763 enddef
4764
4765 assert_equal(100, A.sval)
4766 assert_equal(200, B.sval)
4767 var a = A.new()
4768 assert_equal(100, a.GetVal())
4769 var b = B.new()
4770 assert_equal(200, b.GetVal())
4771 assert_equal(200, T1(b))
4772 assert_equal(200, T2(b))
4773 END
4774 v9.CheckSourceSuccess(lines)
4775
4776 # duplicate class variable and class method
4777 lines =<< trim END
4778 vim9script
4779 class A
4780 static sval = 100
4781 static def Check()
4782 assert_equal(100, sval)
4783 enddef
4784 def GetVal(): number
4785 return sval
4786 enddef
4787 endclass
4788
4789 class B extends A
4790 static sval = 200
4791 static def Check()
4792 assert_equal(200, sval)
4793 enddef
4794 endclass
4795
4796 def T1(aa: A): number
4797 return aa.GetVal()
4798 enddef
4799
4800 def T2(bb: B): number
4801 return bb.GetVal()
4802 enddef
4803
4804 assert_equal(100, A.sval)
4805 assert_equal(200, B.sval)
4806 var a = A.new()
4807 assert_equal(100, a.GetVal())
4808 var b = B.new()
4809 assert_equal(100, b.GetVal())
4810 assert_equal(100, T1(b))
4811 assert_equal(100, T2(b))
4812 END
4813 v9.CheckSourceSuccess(lines)
4814enddef
4815
4816" Test for calling an instance method using the class
4817def Test_instance_method_call_using_class()
4818 # Invoke an object method using a class in script context
4819 var lines =<< trim END
4820 vim9script
4821 class A
4822 def Foo()
4823 echo "foo"
4824 enddef
4825 endclass
4826 A.Foo()
4827 END
4828 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4829
4830 # Invoke an object method using a class in def function context
4831 lines =<< trim END
4832 vim9script
4833 class A
4834 def Foo()
4835 echo "foo"
4836 enddef
4837 endclass
4838 def T()
4839 A.Foo()
4840 enddef
4841 T()
4842 END
4843 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4844enddef
4845
4846" Test for duplicate class method and instance method
4847def Test_dup_classmethod_objmethod()
4848 # Duplicate instance method
4849 var lines =<< trim END
4850 vim9script
4851 class A
4852 static def Foo()
4853 enddef
4854 def Foo()
4855 enddef
4856 endclass
4857 END
4858 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
4859
4860 # Duplicate private instance method
4861 lines =<< trim END
4862 vim9script
4863 class A
4864 static def Foo()
4865 enddef
4866 def _Foo()
4867 enddef
4868 endclass
4869 END
4870 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
4871
4872 # Duplicate class method
4873 lines =<< trim END
4874 vim9script
4875 class A
4876 def Foo()
4877 enddef
4878 static def Foo()
4879 enddef
4880 endclass
4881 END
4882 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
4883
4884 # Duplicate private class method
4885 lines =<< trim END
4886 vim9script
4887 class A
4888 def Foo()
4889 enddef
4890 static def _Foo()
4891 enddef
4892 endclass
4893 END
4894 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
4895
4896 # Duplicate private class and object method
4897 lines =<< trim END
4898 vim9script
4899 class A
4900 def _Foo()
4901 enddef
4902 static def _Foo()
4903 enddef
4904 endclass
4905 END
4906 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
4907enddef
4908
4909" Test for an instance method access level comparison with parent instance
4910" methods.
4911def Test_instance_method_access_level()
4912 # Private method in subclass
4913 var lines =<< trim END
4914 vim9script
4915 class A
4916 def Foo()
4917 enddef
4918 endclass
4919 class B extends A
4920 endclass
4921 class C extends B
4922 def _Foo()
4923 enddef
4924 endclass
4925 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004926 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004927
4928 # Public method in subclass
4929 lines =<< trim END
4930 vim9script
4931 class A
4932 def _Foo()
4933 enddef
4934 endclass
4935 class B extends A
4936 endclass
4937 class C extends B
4938 def Foo()
4939 enddef
4940 endclass
4941 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004942 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004943enddef
4944
4945def Test_extend_empty_class()
4946 var lines =<< trim END
4947 vim9script
4948 class A
4949 endclass
4950 class B extends A
4951 endclass
4952 class C extends B
4953 public static rw_class_var = 1
4954 public this.rw_obj_var = 2
4955 static def ClassMethod(): number
4956 return 3
4957 enddef
4958 def ObjMethod(): number
4959 return 4
4960 enddef
4961 endclass
4962 assert_equal(1, C.rw_class_var)
4963 assert_equal(3, C.ClassMethod())
4964 var c = C.new()
4965 assert_equal(2, c.rw_obj_var)
4966 assert_equal(4, c.ObjMethod())
4967 END
4968 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004969enddef
4970
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004971" A interface cannot have a static variable or a static method or a private
4972" variable or a private method
4973def Test_interface_with_unsupported_members()
4974 var lines =<< trim END
4975 vim9script
4976 interface A
4977 static num: number
4978 endinterface
4979 END
4980 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface')
4981
4982 lines =<< trim END
4983 vim9script
4984 interface A
4985 static _num: number
4986 endinterface
4987 END
4988 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface')
4989
4990 lines =<< trim END
4991 vim9script
4992 interface A
4993 public static num: number
4994 endinterface
4995 END
4996 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface')
4997
4998 lines =<< trim END
4999 vim9script
5000 interface A
5001 public static _num: number
5002 endinterface
5003 END
5004 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface')
5005
5006 lines =<< trim END
5007 vim9script
5008 interface A
5009 static def Foo(d: dict<any>): list<string>
5010 endinterface
5011 END
5012 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface')
5013
5014 lines =<< trim END
5015 vim9script
5016 interface A
5017 static def _Foo(d: dict<any>): list<string>
5018 endinterface
5019 END
5020 v9.CheckSourceFailure(lines, 'E1378: Static cannot be used in an interface')
5021
5022 lines =<< trim END
5023 vim9script
5024 interface A
5025 this._Foo: list<string>
5026 endinterface
5027 END
5028 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface')
5029
5030 lines =<< trim END
5031 vim9script
5032 interface A
5033 def _Foo(d: dict<any>): list<string>
5034 endinterface
5035 END
5036 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface')
5037enddef
5038
5039" Test for extending an interface
5040def Test_extend_interface()
5041 var lines =<< trim END
5042 vim9script
5043 interface A
5044 this.var1: list<string>
5045 def Foo()
5046 endinterface
5047 interface B extends A
5048 public this.var2: dict<string>
5049 def Bar()
5050 endinterface
5051 class C implements A, B
5052 this.var1 = [1, 2]
5053 def Foo()
5054 enddef
5055 public this.var2 = {a: '1'}
5056 def Bar()
5057 enddef
5058 endclass
5059 END
5060 v9.CheckSourceSuccess(lines)
5061
5062 lines =<< trim END
5063 vim9script
5064 interface A
5065 def Foo()
5066 endinterface
5067 interface B extends A
5068 public this.var2: dict<string>
5069 endinterface
5070 class C implements A, B
5071 public this.var2 = {a: '1'}
5072 endclass
5073 END
5074 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented')
5075
5076 lines =<< trim END
5077 vim9script
5078 interface A
5079 def Foo()
5080 endinterface
5081 interface B extends A
5082 public this.var2: dict<string>
5083 endinterface
5084 class C implements A, B
5085 def Foo()
5086 enddef
5087 endclass
5088 END
5089 v9.CheckSourceFailure(lines, 'E1348: Member "var2" of interface "B" is not implemented')
5090
5091 # interface cannot extend a class
5092 lines =<< trim END
5093 vim9script
5094 class A
5095 endclass
5096 interface B extends A
5097 endinterface
5098 END
5099 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5100
5101 # class cannot extend an interface
5102 lines =<< trim END
5103 vim9script
5104 interface A
5105 endinterface
5106 class B extends A
5107 endclass
5108 END
5109 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5110
5111 # interface cannot implement another interface
5112 lines =<< trim END
5113 vim9script
5114 interface A
5115 endinterface
5116 interface B implements A
5117 endinterface
5118 END
5119 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"')
5120
5121 # interface cannot extend multiple interfaces
5122 lines =<< trim END
5123 vim9script
5124 interface A
5125 endinterface
5126 interface B
5127 endinterface
5128 interface C extends A, B
5129 endinterface
5130 END
5131 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B')
5132
5133 # Variable type in an extended interface is of different type
5134 lines =<< trim END
5135 vim9script
5136 interface A
5137 this.val1: number
5138 endinterface
5139 interface B extends A
5140 this.val2: string
5141 endinterface
5142 interface C extends B
5143 this.val1: string
5144 this.val2: number
5145 endinterface
5146 END
5147 v9.CheckSourceFailure(lines, 'E1382: Member "val1": type mismatch, expected number but got string')
5148enddef
5149
5150" Test for a child class implementing an interface when some of the methods are
5151" defined in the parent class.
5152def Test_child_class_implements_interface()
5153 var lines =<< trim END
5154 vim9script
5155
5156 interface Intf
5157 def F1(): list<list<number>>
5158 def F2(): list<list<number>>
5159 def F3(): list<list<number>>
5160 this.var1: list<dict<number>>
5161 this.var2: list<dict<number>>
5162 this.var3: list<dict<number>>
5163 endinterface
5164
5165 class A
5166 def A1()
5167 enddef
5168 def F3(): list<list<number>>
5169 return [[3]]
5170 enddef
5171 this.v1: list<list<number>> = [[0]]
5172 this.var3 = [{c: 30}]
5173 endclass
5174
5175 class B extends A
5176 def B1()
5177 enddef
5178 def F2(): list<list<number>>
5179 return [[2]]
5180 enddef
5181 this.v2: list<list<number>> = [[0]]
5182 this.var2 = [{b: 20}]
5183 endclass
5184
5185 class C extends B implements Intf
5186 def C1()
5187 enddef
5188 def F1(): list<list<number>>
5189 return [[1]]
5190 enddef
5191 this.v3: list<list<number>> = [[0]]
5192 this.var1 = [{a: 10}]
5193 endclass
5194
5195 def T(if: Intf)
5196 assert_equal([[1]], if.F1())
5197 assert_equal([[2]], if.F2())
5198 assert_equal([[3]], if.F3())
5199 assert_equal([{a: 10}], if.var1)
5200 assert_equal([{b: 20}], if.var2)
5201 assert_equal([{c: 30}], if.var3)
5202 enddef
5203
5204 var c = C.new()
5205 T(c)
5206 assert_equal([[1]], c.F1())
5207 assert_equal([[2]], c.F2())
5208 assert_equal([[3]], c.F3())
5209 assert_equal([{a: 10}], c.var1)
5210 assert_equal([{b: 20}], c.var2)
5211 assert_equal([{c: 30}], c.var3)
5212 END
5213 v9.CheckSourceSuccess(lines)
5214
5215 # One of the interface methods is not found
5216 lines =<< trim END
5217 vim9script
5218
5219 interface Intf
5220 def F1()
5221 def F2()
5222 def F3()
5223 endinterface
5224
5225 class A
5226 def A1()
5227 enddef
5228 endclass
5229
5230 class B extends A
5231 def B1()
5232 enddef
5233 def F2()
5234 enddef
5235 endclass
5236
5237 class C extends B implements Intf
5238 def C1()
5239 enddef
5240 def F1()
5241 enddef
5242 endclass
5243 END
5244 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented')
5245
5246 # One of the interface methods is of different type
5247 lines =<< trim END
5248 vim9script
5249
5250 interface Intf
5251 def F1()
5252 def F2()
5253 def F3()
5254 endinterface
5255
5256 class A
5257 def F3(): number
5258 return 0
5259 enddef
5260 def A1()
5261 enddef
5262 endclass
5263
5264 class B extends A
5265 def B1()
5266 enddef
5267 def F2()
5268 enddef
5269 endclass
5270
5271 class C extends B implements Intf
5272 def C1()
5273 enddef
5274 def F1()
5275 enddef
5276 endclass
5277 END
5278 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number')
5279
5280 # One of the interface variables is not present
5281 lines =<< trim END
5282 vim9script
5283
5284 interface Intf
5285 this.var1: list<dict<number>>
5286 this.var2: list<dict<number>>
5287 this.var3: list<dict<number>>
5288 endinterface
5289
5290 class A
5291 this.v1: list<list<number>> = [[0]]
5292 endclass
5293
5294 class B extends A
5295 this.v2: list<list<number>> = [[0]]
5296 this.var2 = [{b: 20}]
5297 endclass
5298
5299 class C extends B implements Intf
5300 this.v3: list<list<number>> = [[0]]
5301 this.var1 = [{a: 10}]
5302 endclass
5303 END
5304 v9.CheckSourceFailure(lines, 'E1348: Member "var3" of interface "Intf" is not implemented')
5305
5306 # One of the interface variables is of different type
5307 lines =<< trim END
5308 vim9script
5309
5310 interface Intf
5311 this.var1: list<dict<number>>
5312 this.var2: list<dict<number>>
5313 this.var3: list<dict<number>>
5314 endinterface
5315
5316 class A
5317 this.v1: list<list<number>> = [[0]]
5318 this.var3: list<dict<string>>
5319 endclass
5320
5321 class B extends A
5322 this.v2: list<list<number>> = [[0]]
5323 this.var2 = [{b: 20}]
5324 endclass
5325
5326 class C extends B implements Intf
5327 this.v3: list<list<number>> = [[0]]
5328 this.var1 = [{a: 10}]
5329 endclass
5330 END
5331 v9.CheckSourceFailure(lines, 'E1382: Member "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>')
5332enddef
5333
5334" Test for extending an interface with duplicate variables and methods
5335def Test_interface_extends_with_dup_members()
5336 var lines =<< trim END
5337 vim9script
5338 interface A
5339 this.n1: number
5340 def Foo1(): number
5341 endinterface
5342 interface B extends A
5343 this.n2: number
5344 this.n1: number
5345 def Foo2(): number
5346 def Foo1(): number
5347 endinterface
5348 class C implements B
5349 this.n1 = 10
5350 this.n2 = 20
5351 def Foo1(): number
5352 return 30
5353 enddef
5354 def Foo2(): number
5355 return 40
5356 enddef
5357 endclass
5358 def T1(a: A)
5359 assert_equal(10, a.n1)
5360 assert_equal(30, a.Foo1())
5361 enddef
5362 def T2(b: B)
5363 assert_equal(10, b.n1)
5364 assert_equal(20, b.n2)
5365 assert_equal(30, b.Foo1())
5366 assert_equal(40, b.Foo2())
5367 enddef
5368 var c = C.new()
5369 T1(c)
5370 T2(c)
5371 END
5372 v9.CheckSourceSuccess(lines)
5373enddef
5374
5375" Test for using "any" type for a variable in a sub-class while it has a
5376" concrete type in the interface
5377def Test_implements_using_var_type_any()
5378 var lines =<< trim END
5379 vim9script
5380 interface A
5381 this.val: list<dict<string>>
5382 endinterface
5383 class B implements A
5384 this.val = [{a: '1'}, {b: '2'}]
5385 endclass
5386 var b = B.new()
5387 assert_equal([{a: '1'}, {b: '2'}], b.val)
5388 END
5389 v9.CheckSourceSuccess(lines)
5390
5391 # initialize instance variable using a different type
5392 lines =<< trim END
5393 vim9script
5394 interface A
5395 this.val: list<dict<string>>
5396 endinterface
5397 class B implements A
5398 this.val = {a: 1, b: 2}
5399 endclass
5400 var b = B.new()
5401 END
5402 v9.CheckSourceFailure(lines, 'E1382: Member "val": type mismatch, expected list<dict<string>> but got dict<number>')
5403enddef
5404
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005405" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker