blob: 1796f5f72e13f864751a7fc1ecad2aa068c103d2 [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
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000148 lines =<< trim END
149 vim9script
150
151 class TextPosition
152 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000153 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000154
Bram Moolenaar418b5472022-12-20 13:38:22 +0000155 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000156 def ToString(): string
157 return $'({this.lnum}, {this.col})'
158 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000159 endclass
160
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000161 # use the automatically generated new() method
162 var pos = TextPosition.new(2, 12)
163 assert_equal(2, pos.lnum)
164 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000165
166 # call an object method
167 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000168
169 assert_equal(v:t_class, type(TextPosition))
170 assert_equal(v:t_object, type(pos))
171 assert_equal('class<TextPosition>', typename(TextPosition))
172 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000173 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200174 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200175
176 # When referencing object methods, space cannot be used after a "."
177 lines =<< trim END
178 vim9script
179 class A
180 def Foo(): number
181 return 10
182 enddef
183 endclass
184 var a = A.new()
185 var v = a. Foo()
186 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200187 v9.CheckSourceFailure(lines, 'E1202:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200188
189 # Using an object without specifying a method or a member variable
190 lines =<< trim END
191 vim9script
192 class A
193 def Foo(): number
194 return 10
195 enddef
196 endclass
197 var a = A.new()
198 var v = a.
199 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200200 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200201
202 # Error when parsing the arguments of an object method.
203 lines =<< trim END
204 vim9script
205 class A
206 def Foo()
207 enddef
208 endclass
209 var a = A.new()
210 var v = a.Foo(,)
211 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200212 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200213
214 lines =<< trim END
215 vim9script
216 class A
217 this.y = {
218 X: 1
219 }
220 endclass
221 var a = A.new()
222 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200223 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000224enddef
225
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000226def Test_class_defined_twice()
227 # class defined twice should fail
228 var lines =<< trim END
229 vim9script
230 class There
231 endclass
232 class There
233 endclass
234 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200235 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"')
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000236
237 # one class, reload same script twice is OK
238 lines =<< trim END
239 vim9script
240 class There
241 endclass
242 END
243 writefile(lines, 'XclassTwice.vim', 'D')
244 source XclassTwice.vim
245 source XclassTwice.vim
246enddef
247
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000248def Test_returning_null_object()
249 # this was causing an internal error
250 var lines =<< trim END
251 vim9script
252
253 class BufferList
254 def Current(): any
255 return null_object
256 enddef
257 endclass
258
259 var buffers = BufferList.new()
260 echo buffers.Current()
261 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200262 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000263enddef
264
Bram Moolenaard13dd302023-03-11 20:56:35 +0000265def Test_using_null_class()
266 var lines =<< trim END
267 @_ = null_class.member
268 END
269 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
270enddef
271
Bram Moolenaar657aea72023-01-27 13:16:19 +0000272def Test_class_interface_wrong_end()
273 var lines =<< trim END
274 vim9script
275 abstract class SomeName
276 this.member = 'text'
277 endinterface
278 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200279 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000280
281 lines =<< trim END
282 vim9script
283 export interface AnotherName
284 this.member: string
285 endclass
286 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200287 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000288enddef
289
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000290def Test_object_not_set()
291 var lines =<< trim END
292 vim9script
293
294 class State
295 this.value = 'xyz'
296 endclass
297
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000298 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000299 var db = {'xyz': 789}
300 echo db[state.value]
301 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200302 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000303
304 lines =<< trim END
305 vim9script
306
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000307 class Class
308 this.id: string
309 def Method1()
310 echo 'Method1' .. this.id
311 enddef
312 endclass
313
314 var obj: Class
315 def Func()
316 obj.Method1()
317 enddef
318 Func()
319 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200320 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000321
322 lines =<< trim END
323 vim9script
324
Bram Moolenaar0917e862023-02-18 14:42:44 +0000325 class Background
326 this.background = 'dark'
327 endclass
328
329 class Colorscheme
330 this._bg: Background
331
332 def GetBackground(): string
333 return this._bg.background
334 enddef
335 endclass
336
337 var bg: Background # UNINITIALIZED
338 echo Colorscheme.new(bg).GetBackground()
339 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200340 v9.CheckSourceFailure(lines, 'E1360:')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000341
342 # TODO: this should not give an error but be handled at runtime
343 lines =<< trim END
344 vim9script
345
346 class Class
347 this.id: string
348 def Method1()
349 echo 'Method1' .. this.id
350 enddef
351 endclass
352
353 var obj = null_object
354 def Func()
355 obj.Method1()
356 enddef
357 Func()
358 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200359 v9.CheckSourceFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000360enddef
361
Ernie Rael5c018be2023-08-27 18:40:26 +0200362def Test_null_object_assign_compare()
363 var lines =<< trim END
364 vim9script
365
366 var nullo = null_object
367 def F(): any
368 return nullo
369 enddef
370 assert_equal('object<Unknown>', typename(F()))
371
372 var o0 = F()
373 assert_true(o0 == null_object)
374 assert_true(o0 == null)
375
376 var o1: any = nullo
377 assert_true(o1 == null_object)
378 assert_true(o1 == null)
379
380 def G()
381 var x = null_object
382 enddef
383
384 class C
385 endclass
386 var o2: C
387 assert_true(o2 == null_object)
388 assert_true(o2 == null)
389
390 o2 = null_object
391 assert_true(o2 == null)
392
393 o2 = C.new()
394 assert_true(o2 != null)
395
396 o2 = null_object
397 assert_true(o2 == null)
398 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200399 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200400enddef
401
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000402def Test_class_member_initializer()
403 var lines =<< trim END
404 vim9script
405
406 class TextPosition
407 this.lnum: number = 1
408 this.col: number = 1
409
Bram Moolenaar418b5472022-12-20 13:38:22 +0000410 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000411 def new(lnum: number)
412 this.lnum = lnum
413 enddef
414 endclass
415
416 var pos = TextPosition.new(3)
417 assert_equal(3, pos.lnum)
418 assert_equal(1, pos.col)
419
420 var instr = execute('disassemble TextPosition.new')
421 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000422 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000423 '\d PUSHNR 1\_s*' ..
424 '\d STORE_THIS 0\_s*' ..
425 '\d PUSHNR 1\_s*' ..
426 '\d STORE_THIS 1\_s*' ..
427 'this.lnum = lnum\_s*' ..
428 '\d LOAD arg\[-1]\_s*' ..
429 '\d PUSHNR 0\_s*' ..
430 '\d LOAD $0\_s*' ..
431 '\d\+ STOREINDEX object\_s*' ..
432 '\d\+ RETURN object.*',
433 instr)
434 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200435 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000436enddef
437
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000438def Test_member_any_used_as_object()
439 var lines =<< trim END
440 vim9script
441
442 class Inner
443 this.value: number = 0
444 endclass
445
446 class Outer
447 this.inner: any
448 endclass
449
450 def F(outer: Outer)
451 outer.inner.value = 1
452 enddef
453
454 var inner_obj = Inner.new(0)
455 var outer_obj = Outer.new(inner_obj)
456 F(outer_obj)
457 assert_equal(1, inner_obj.value)
458 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200459 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000460
461 lines =<< trim END
462 vim9script
463
464 class Inner
465 this.value: number = 0
466 endclass
467
468 class Outer
469 this.inner: Inner
470 endclass
471
472 def F(outer: Outer)
473 outer.inner.value = 1
474 enddef
475
476 def Test_assign_to_nested_typed_member()
477 var inner = Inner.new(0)
478 var outer = Outer.new(inner)
479 F(outer)
480 assert_equal(1, inner.value)
481 enddef
482
483 Test_assign_to_nested_typed_member()
484 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200485 v9.CheckSourceSuccess(lines)
486
487 # Try modifying a private variable using an "any" object
488 lines =<< trim END
489 vim9script
490
491 class Inner
492 this._value: string = ''
493 endclass
494
495 class Outer
496 this.inner: any
497 endclass
498
499 def F(outer: Outer)
500 outer.inner._value = 'b'
501 enddef
502
503 var inner_obj = Inner.new('a')
504 var outer_obj = Outer.new(inner_obj)
505 F(outer_obj)
506 END
507 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _value')
508
509 # Try modifying a non-existing variable using an "any" object
510 lines =<< trim END
511 vim9script
512
513 class Inner
514 this.value: string = ''
515 endclass
516
517 class Outer
518 this.inner: any
519 endclass
520
521 def F(outer: Outer)
522 outer.inner.someval = 'b'
523 enddef
524
525 var inner_obj = Inner.new('a')
526 var outer_obj = Outer.new(inner_obj)
527 F(outer_obj)
528 END
529 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Inner": someval')
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000530enddef
531
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000532def Test_assignment_with_operator()
533 var lines =<< trim END
534 vim9script
535
536 class Foo
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200537 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000538
539 def Add(n: number)
540 this.x += n
541 enddef
542 endclass
543
544 var f = Foo.new(3)
545 f.Add(17)
546 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100547
548 def AddToFoo(obj: Foo)
549 obj.x += 3
550 enddef
551
552 AddToFoo(f)
553 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000554 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200555 v9.CheckSourceSuccess(lines)
Ernie Rael18143d32023-09-04 22:30:41 +0200556
557 # do the same thing, but through an interface
558 lines =<< trim END
559 vim9script
560
561 interface I
562 public this.x: number
563 endinterface
564
565 class Foo implements I
566 public this.x: number
567
568 def Add(n: number)
569 var i: I = this
570 i.x += n
571 enddef
572 endclass
573
574 var f = Foo.new(3)
575 f.Add(17)
576 assert_equal(20, f.x)
577
578 def AddToFoo(i: I)
579 i.x += 3
580 enddef
581
582 AddToFoo(f)
583 assert_equal(23, f.x)
584 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200585 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000586enddef
587
Bram Moolenaarf4508042023-01-15 16:54:57 +0000588def Test_list_of_objects()
589 var lines =<< trim END
590 vim9script
591
592 class Foo
593 def Add()
594 enddef
595 endclass
596
597 def ProcessList(fooList: list<Foo>)
598 for foo in fooList
599 foo.Add()
600 endfor
601 enddef
602
603 var l: list<Foo> = [Foo.new()]
604 ProcessList(l)
605 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200606 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000607enddef
608
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000609def Test_expr_after_using_object()
610 var lines =<< trim END
611 vim9script
612
613 class Something
614 this.label: string = ''
615 endclass
616
617 def Foo(): Something
618 var v = Something.new()
619 echo 'in Foo(): ' .. typename(v)
620 return v
621 enddef
622
623 Foo()
624 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200625 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000626enddef
627
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000628def Test_class_default_new()
629 var lines =<< trim END
630 vim9script
631
632 class TextPosition
633 this.lnum: number = 1
634 this.col: number = 1
635 endclass
636
637 var pos = TextPosition.new()
638 assert_equal(1, pos.lnum)
639 assert_equal(1, pos.col)
640
641 pos = TextPosition.new(v:none, v:none)
642 assert_equal(1, pos.lnum)
643 assert_equal(1, pos.col)
644
645 pos = TextPosition.new(3, 22)
646 assert_equal(3, pos.lnum)
647 assert_equal(22, pos.col)
648
649 pos = TextPosition.new(v:none, 33)
650 assert_equal(1, pos.lnum)
651 assert_equal(33, pos.col)
652 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200653 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000654
655 lines =<< trim END
656 vim9script
657 class Person
658 this.name: string
659 this.age: number = 42
660 this.education: string = "unknown"
661
662 def new(this.name, this.age = v:none, this.education = v:none)
663 enddef
664 endclass
665
666 var piet = Person.new("Piet")
667 assert_equal("Piet", piet.name)
668 assert_equal(42, piet.age)
669 assert_equal("unknown", piet.education)
670
671 var chris = Person.new("Chris", 4, "none")
672 assert_equal("Chris", chris.name)
673 assert_equal(4, chris.age)
674 assert_equal("none", chris.education)
675 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200676 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000677
678 lines =<< trim END
679 vim9script
680 class Person
681 this.name: string
682 this.age: number = 42
683 this.education: string = "unknown"
684
685 def new(this.name, this.age = v:none, this.education = v:none)
686 enddef
687 endclass
688
689 var missing = Person.new()
690 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200691 v9.CheckSourceFailure(lines, 'E119:')
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000692enddef
693
h-east2261c892023-08-16 21:49:54 +0900694
695def Test_class_new_with_object_member()
696 var lines =<< trim END
697 vim9script
698
699 class C
700 this.str: string
701 this.num: number
702 def new(this.str, this.num)
703 enddef
704 def newVals(this.str, this.num)
705 enddef
706 endclass
707
708 def Check()
709 try
710 var c = C.new('cats', 2)
711 assert_equal('cats', c.str)
712 assert_equal(2, c.num)
713
714 c = C.newVals('dogs', 4)
715 assert_equal('dogs', c.str)
716 assert_equal(4, c.num)
717 catch
718 assert_report($'Unexpected exception was caught: {v:exception}')
719 endtry
720 enddef
721
722 Check()
723 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200724 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900725
726 lines =<< trim END
727 vim9script
728
729 class C
730 this.str: string
731 this.num: number
732 def new(this.str, this.num)
733 enddef
734 endclass
735
736 def Check()
737 try
738 var c = C.new(1, 2)
739 catch
740 assert_report($'Unexpected exception was caught: {v:exception}')
741 endtry
742 enddef
743
744 Check()
745 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200746 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900747
748 lines =<< trim END
749 vim9script
750
751 class C
752 this.str: string
753 this.num: number
754 def newVals(this.str, this.num)
755 enddef
756 endclass
757
758 def Check()
759 try
760 var c = C.newVals('dogs', 'apes')
761 catch
762 assert_report($'Unexpected exception was caught: {v:exception}')
763 endtry
764 enddef
765
766 Check()
767 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200768 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900769enddef
770
Bram Moolenaar74e12742022-12-13 21:14:28 +0000771def Test_class_object_member_inits()
772 var lines =<< trim END
773 vim9script
774 class TextPosition
775 this.lnum: number
776 this.col = 1
777 this.addcol: number = 2
778 endclass
779
780 var pos = TextPosition.new()
781 assert_equal(0, pos.lnum)
782 assert_equal(1, pos.col)
783 assert_equal(2, pos.addcol)
784 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200785 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000786
787 lines =<< trim END
788 vim9script
789 class TextPosition
790 this.lnum
791 this.col = 1
792 endclass
793 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200794 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000795
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200796 # If the type is not specified for a member, then it should be set during
797 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000798 lines =<< trim END
799 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200800
801 var init_count = 0
802 def Init(): string
803 init_count += 1
804 return 'foo'
805 enddef
806
807 class A
808 this.str1 = Init()
809 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000810 this.col = 1
811 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200812
813 assert_equal(init_count, 0)
814 var a = A.new()
815 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000816 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200817 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200818
819 # Test for initializing an object member with an unknown variable/type
820 lines =<< trim END
821 vim9script
822 class A
823 this.value = init_val
824 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200825 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200826 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200827 v9.CheckSourceFailure(lines, 'E1001:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000828enddef
829
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200830" Test for instance variable access
831def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000832 var lines =<< trim END
833 vim9script
834 class Triple
835 this._one = 1
836 this.two = 2
837 public this.three = 3
838
839 def GetOne(): number
840 return this._one
841 enddef
842 endclass
843
844 var trip = Triple.new()
845 assert_equal(1, trip.GetOne())
846 assert_equal(2, trip.two)
847 assert_equal(3, trip.three)
848 assert_fails('echo trip._one', 'E1333')
849
850 assert_fails('trip._one = 11', 'E1333')
851 assert_fails('trip.two = 22', 'E1335')
852 trip.three = 33
853 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000854
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200855 assert_fails('trip.four = 4', 'E1326')
Bram Moolenaard505d172022-12-18 21:42:55 +0000856 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200857 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000858
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200859 # Test for a public member variable name beginning with an underscore
860 lines =<< trim END
861 vim9script
862 class A
863 public this._val = 10
864 endclass
865 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200866 v9.CheckSourceFailure(lines, 'E1332:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200867
Bram Moolenaar590162c2022-12-24 21:24:06 +0000868 lines =<< trim END
869 vim9script
870
871 class MyCar
872 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000873 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000874
875 def new(make_arg: string)
876 this.make = make_arg
877 enddef
878
879 def GetMake(): string
880 return $"make = {this.make}"
881 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000882 def GetAge(): number
883 return this.age
884 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000885 endclass
886
887 var c = MyCar.new("abc")
888 assert_equal('make = abc', c.GetMake())
889
890 c = MyCar.new("def")
891 assert_equal('make = def', c.GetMake())
892
893 var c2 = MyCar.new("123")
894 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +0000895
896 def CheckCar()
897 assert_equal("make = def", c.GetMake())
898 assert_equal(5, c.GetAge())
899 enddef
900 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +0000901 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200902 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +0000903
904 lines =<< trim END
905 vim9script
906
907 class MyCar
908 this.make: string
909
910 def new(make_arg: string)
911 this.make = make_arg
912 enddef
913 endclass
914
915 var c = MyCar.new("abc")
916 var c = MyCar.new("def")
917 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200918 v9.CheckSourceFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +0000919
920 lines =<< trim END
921 vim9script
922
923 class Foo
924 this.x: list<number> = []
925
926 def Add(n: number): any
927 this.x->add(n)
928 return this
929 enddef
930 endclass
931
932 echo Foo.new().Add(1).Add(2).x
933 echo Foo.new().Add(1).Add(2)
934 .x
935 echo Foo.new().Add(1)
936 .Add(2).x
937 echo Foo.new()
938 .Add(1).Add(2).x
939 echo Foo.new()
940 .Add(1)
941 .Add(2)
942 .x
943 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200944 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200945
946 # Test for "public" cannot be abbreviated
947 lines =<< trim END
948 vim9script
949 class Something
950 pub this.val = 1
951 endclass
952 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200953 v9.CheckSourceFailure(lines, 'E1065:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200954
955 # Test for "public" keyword must be followed by "this" or "static".
956 lines =<< trim END
957 vim9script
958 class Something
959 public val = 1
960 endclass
961 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200962 v9.CheckSourceFailure(lines, 'E1331:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200963
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200964 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200965 lines =<< trim END
966 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200967 class A
968 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200969 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200970 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200971 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200972 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +0200973
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200974 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +0200975 lines =<< trim END
976 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200977 class A
978 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +0200979 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200980 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +0200981 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200982 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
983
984 # Modify a instance variable using the class name in a def function
985 lines =<< trim END
986 vim9script
987 class A
988 public this.val = 1
989 endclass
990 def T()
991 A.val = 1
992 enddef
993 T()
994 END
995 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
996
997 # Read a instance variable using the class name in a def function
998 lines =<< trim END
999 vim9script
1000 class A
1001 public this.val = 1
1002 endclass
1003 def T()
1004 var i = A.val
1005 enddef
1006 T()
1007 END
1008 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Ernie Raelcf138d42023-09-06 20:45:03 +02001009
1010 # Access from child class extending a class:
1011 lines =<< trim END
1012 vim9script
1013 class A
1014 this.ro_obj_var = 10
1015 public this.rw_obj_var = 20
1016 this._priv_obj_var = 30
Ernie Raelcf138d42023-09-06 20:45:03 +02001017 endclass
1018
1019 class B extends A
1020 def Foo()
1021 var x: number
1022 x = this.ro_obj_var
1023 this.ro_obj_var = 0
1024 x = this.rw_obj_var
1025 this.rw_obj_var = 0
1026 x = this._priv_obj_var
1027 this._priv_obj_var = 0
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001028 enddef
1029 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001030
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001031 var b = B.new()
1032 b.Foo()
1033 END
1034 v9.CheckSourceSuccess(lines)
1035enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001036
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001037" Test for class variable access
1038def Test_class_variable_access()
1039 # Test for "static" cannot be abbreviated
1040 var lines =<< trim END
1041 vim9script
1042 class Something
1043 stat this.val = 1
1044 endclass
1045 END
1046 v9.CheckSourceFailure(lines, 'E1065:')
1047
1048 # Test for "static" cannot be followed by "this".
1049 lines =<< trim END
1050 vim9script
1051 class Something
1052 static this.val = 1
1053 endclass
1054 END
1055 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
1056
1057 # Test for "static" cannot be followed by "public".
1058 lines =<< trim END
1059 vim9script
1060 class Something
1061 static public val = 1
1062 endclass
1063 END
1064 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
1065
1066 # A readonly class variable cannot be modified from a child class
1067 lines =<< trim END
1068 vim9script
1069 class A
1070 static ro_class_var = 40
1071 endclass
1072
1073 class B extends A
1074 def Foo()
1075 A.ro_class_var = 50
1076 enddef
1077 endclass
1078
1079 var b = B.new()
1080 b.Foo()
1081 END
1082 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "ro_class_var"')
1083
1084 # A private class variable cannot be accessed from a child class
1085 lines =<< trim END
1086 vim9script
1087 class A
1088 static _priv_class_var = 60
1089 endclass
1090
1091 class B extends A
1092 def Foo()
1093 var i = A._priv_class_var
1094 enddef
1095 endclass
1096
1097 var b = B.new()
1098 b.Foo()
1099 END
1100 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1101
1102 # A private class variable cannot be modified from a child class
1103 lines =<< trim END
1104 vim9script
1105 class A
1106 static _priv_class_var = 60
1107 endclass
1108
1109 class B extends A
1110 def Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001111 A._priv_class_var = 0
1112 enddef
1113 endclass
1114
1115 var b = B.new()
1116 b.Foo()
1117 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001118 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1119
1120 # Access from child class extending a class and from script context
1121 lines =<< trim END
1122 vim9script
1123 class A
1124 static ro_class_var = 10
1125 public static rw_class_var = 20
1126 static _priv_class_var = 30
1127 endclass
1128
1129 class B extends A
1130 def Foo()
1131 var x: number
1132 x = A.ro_class_var
1133 assert_equal(10, x)
1134 x = A.rw_class_var
1135 assert_equal(25, x)
1136 A.rw_class_var = 20
1137 assert_equal(20, A.rw_class_var)
1138 enddef
1139 endclass
1140
1141 assert_equal(10, A.ro_class_var)
1142 assert_equal(20, A.rw_class_var)
1143 A.rw_class_var = 25
1144 assert_equal(25, A.rw_class_var)
1145 var b = B.new()
1146 b.Foo()
1147 END
1148 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001149enddef
1150
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001151def Test_class_object_compare()
1152 var class_lines =<< trim END
1153 vim9script
1154 class Item
1155 this.nr = 0
1156 this.name = 'xx'
1157 endclass
1158 END
1159
1160 # used at the script level and in a compiled function
1161 var test_lines =<< trim END
1162 var i1 = Item.new()
1163 assert_equal(i1, i1)
1164 assert_true(i1 is i1)
1165 var i2 = Item.new()
1166 assert_equal(i1, i2)
1167 assert_false(i1 is i2)
1168 var i3 = Item.new(0, 'xx')
1169 assert_equal(i1, i3)
1170
1171 var io1 = Item.new(1, 'xx')
1172 assert_notequal(i1, io1)
1173 var io2 = Item.new(0, 'yy')
1174 assert_notequal(i1, io2)
1175 END
1176
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001177 v9.CheckSourceSuccess(class_lines + test_lines)
1178 v9.CheckSourceSuccess(
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001179 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001180
1181 for op in ['>', '>=', '<', '<=', '=~', '!~']
1182 var op_lines = [
1183 'var i1 = Item.new()',
1184 'var i2 = Item.new()',
1185 'echo i1 ' .. op .. ' i2',
1186 ]
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001187 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
1188 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001189 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001190 endfor
1191enddef
1192
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001193def Test_object_type()
1194 var lines =<< trim END
1195 vim9script
1196
1197 class One
1198 this.one = 1
1199 endclass
1200 class Two
1201 this.two = 2
1202 endclass
1203 class TwoMore extends Two
1204 this.more = 9
1205 endclass
1206
1207 var o: One = One.new()
1208 var t: Two = Two.new()
1209 var m: TwoMore = TwoMore.new()
1210 var tm: Two = TwoMore.new()
1211
1212 t = m
1213 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001214 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001215
1216 lines =<< trim END
1217 vim9script
1218
1219 class One
1220 this.one = 1
1221 endclass
1222 class Two
1223 this.two = 2
1224 endclass
1225
1226 var o: One = Two.new()
1227 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001228 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001229
1230 lines =<< trim END
1231 vim9script
1232
1233 interface One
1234 def GetMember(): number
1235 endinterface
1236 class Two implements One
1237 this.one = 1
1238 def GetMember(): number
1239 return this.one
1240 enddef
1241 endclass
1242
1243 var o: One = Two.new(5)
1244 assert_equal(5, o.GetMember())
1245 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001246 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001247
1248 lines =<< trim END
1249 vim9script
1250
1251 class Num
1252 this.n: number = 0
1253 endclass
1254
1255 def Ref(name: string): func(Num): Num
1256 return (arg: Num): Num => {
1257 return eval(name)(arg)
1258 }
1259 enddef
1260
1261 const Fn = Ref('Double')
1262 var Double = (m: Num): Num => Num.new(m.n * 2)
1263
1264 echo Fn(Num.new(4))
1265 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001266 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001267enddef
1268
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001269def Test_class_member()
1270 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001271 var lines =<< trim END
1272 vim9script
1273 class TextPos
1274 this.lnum = 1
1275 this.col = 1
1276 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001277 static _secret = 7
1278 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001279
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001280 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001281 counter += nr
1282 enddef
1283 endclass
1284
1285 assert_equal(0, TextPos.counter)
1286 TextPos.AddToCounter(3)
1287 assert_equal(3, TextPos.counter)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001288 assert_fails('echo TextPos.noSuchMember', 'E1337:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001289
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001290 def GetCounter(): number
1291 return TextPos.counter
1292 enddef
1293 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001294
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001295 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001296 assert_fails('TextPos.counter = 5', 'E1335:')
1297 assert_fails('TextPos.counter += 5', 'E1335:')
1298
1299 assert_fails('echo TextPos._secret', 'E1333:')
1300 assert_fails('TextPos._secret = 8', 'E1333:')
1301
1302 assert_equal(42, TextPos.anybody)
1303 TextPos.anybody = 12
1304 assert_equal(12, TextPos.anybody)
1305 TextPos.anybody += 5
1306 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001307 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001308 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001309
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001310 # example in the help
1311 lines =<< trim END
1312 vim9script
1313 class OtherThing
1314 this.size: number
1315 static totalSize: number
1316
1317 def new(this.size)
1318 totalSize += this.size
1319 enddef
1320 endclass
1321 assert_equal(0, OtherThing.totalSize)
1322 var to3 = OtherThing.new(3)
1323 assert_equal(3, OtherThing.totalSize)
1324 var to7 = OtherThing.new(7)
1325 assert_equal(10, OtherThing.totalSize)
1326 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001327 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001328
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001329 # using static class member twice
1330 lines =<< trim END
1331 vim9script
1332
1333 class HTML
1334 static author: string = 'John Doe'
1335
1336 static def MacroSubstitute(s: string): string
1337 return substitute(s, '{{author}}', author, 'gi')
1338 enddef
1339 endclass
1340
1341 assert_equal('some text', HTML.MacroSubstitute('some text'))
1342 assert_equal('some text', HTML.MacroSubstitute('some text'))
1343 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001344 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001345
Bram Moolenaar62a69232023-01-24 15:07:04 +00001346 # access private member in lambda
1347 lines =<< trim END
1348 vim9script
1349
1350 class Foo
1351 this._x: number = 0
1352
1353 def Add(n: number): number
1354 const F = (): number => this._x + n
1355 return F()
1356 enddef
1357 endclass
1358
1359 var foo = Foo.new()
1360 assert_equal(5, foo.Add(5))
1361 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001362 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001363
h-east2bd6a092023-05-19 19:01:17 +01001364 # access private member in lambda body
1365 lines =<< trim END
1366 vim9script
1367
1368 class Foo
1369 this._x: number = 6
1370
1371 def Add(n: number): number
1372 var Lam = () => {
1373 this._x = this._x + n
1374 }
1375 Lam()
1376 return this._x
1377 enddef
1378 endclass
1379
1380 var foo = Foo.new()
1381 assert_equal(13, foo.Add(7))
1382 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001383 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001384
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001385 # check shadowing
1386 lines =<< trim END
1387 vim9script
1388
1389 class Some
1390 static count = 0
1391 def Method(count: number)
1392 echo count
1393 enddef
1394 endclass
1395
1396 var s = Some.new()
1397 s.Method(7)
1398 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001399 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001400
1401 lines =<< trim END
1402 vim9script
1403
1404 class Some
1405 static count = 0
1406 def Method(arg: number)
1407 var count = 3
1408 echo arg count
1409 enddef
1410 endclass
1411
1412 var s = Some.new()
1413 s.Method(7)
1414 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001415 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001416
1417 # Test for using an invalid type for a member variable
1418 lines =<< trim END
1419 vim9script
1420 class A
1421 this.val: xxx
1422 endclass
1423 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001424 v9.CheckSourceFailure(lines, 'E1010:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001425
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001426 # Test for setting a member on a null object
1427 lines =<< trim END
1428 vim9script
1429 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001430 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001431 endclass
1432
1433 def F()
1434 var obj: A
1435 obj.val = ""
1436 enddef
1437 F()
1438 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001439 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001440
1441 # Test for accessing a member on a null object
1442 lines =<< trim END
1443 vim9script
1444 class A
1445 this.val: string
1446 endclass
1447
1448 def F()
1449 var obj: A
1450 echo obj.val
1451 enddef
1452 F()
1453 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001454 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001455
1456 # Test for setting a member on a null object, at script level
1457 lines =<< trim END
1458 vim9script
1459 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001460 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001461 endclass
1462
1463 var obj: A
1464 obj.val = ""
1465 END
1466 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001467 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001468
1469 # Test for accessing a member on a null object, at script level
1470 lines =<< trim END
1471 vim9script
1472 class A
1473 this.val: string
1474 endclass
1475
1476 var obj: A
1477 echo obj.val
1478 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001479 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001480
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001481 # Test for no space before or after the '=' when initializing a member
1482 # variable
1483 lines =<< trim END
1484 vim9script
1485 class A
1486 this.val: number= 10
1487 endclass
1488 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001489 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001490 lines =<< trim END
1491 vim9script
1492 class A
1493 this.val: number =10
1494 endclass
1495 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001496 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001497
1498 # Access a non-existing member
1499 lines =<< trim END
1500 vim9script
1501 class A
1502 endclass
1503 var a = A.new()
1504 var v = a.bar
1505 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001506 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": bar')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001507enddef
1508
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001509func Test_class_garbagecollect()
1510 let lines =<< trim END
1511 vim9script
1512
1513 class Point
1514 this.p = [2, 3]
1515 static pl = ['a', 'b']
1516 static pd = {a: 'a', b: 'b'}
1517 endclass
1518
1519 echo Point.pl Point.pd
1520 call test_garbagecollect_now()
1521 echo Point.pl Point.pd
1522 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001523 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001524
1525 let lines =<< trim END
1526 vim9script
1527
1528 interface View
1529 endinterface
1530
1531 class Widget
1532 this.view: View
1533 endclass
1534
1535 class MyView implements View
1536 this.widget: Widget
1537
1538 def new()
1539 # this will result in a circular reference to this object
1540 this.widget = Widget.new(this)
1541 enddef
1542 endclass
1543
1544 var view = MyView.new()
1545
1546 # overwrite "view", will be garbage-collected next
1547 view = MyView.new()
1548 test_garbagecollect_now()
1549 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001550 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001551endfunc
1552
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001553" Test interface garbage collection
1554func Test_interface_garbagecollect()
1555 let lines =<< trim END
1556 vim9script
1557
1558 interface I
1559 static ro_class_var: number
1560 public static rw_class_var: number
1561 static _priv_class_var: number
1562 this.ro_obj_var: number
1563 public this.rw_obj_var: number
1564 this._priv_obj_var: number
1565
1566 static def ClassFoo(): number
1567 static def _ClassBar(): number
1568 def ObjFoo(): number
1569 def _ObjBar(): number
1570 endinterface
1571
1572 class A implements I
1573 static ro_class_var: number = 10
1574 public static rw_class_var: number = 20
1575 static _priv_class_var: number = 30
1576 this.ro_obj_var: number = 40
1577 public this.rw_obj_var: number = 50
1578 this._priv_obj_var: number = 60
1579
1580 static def _ClassBar(): number
1581 return _priv_class_var
1582 enddef
1583
1584 static def ClassFoo(): number
1585 return ro_class_var + rw_class_var + A._ClassBar()
1586 enddef
1587
1588 def _ObjBar(): number
1589 return this._priv_obj_var
1590 enddef
1591
1592 def ObjFoo(): number
1593 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1594 enddef
1595 endclass
1596
1597 assert_equal(60, A.ClassFoo())
1598 var o = A.new()
1599 assert_equal(150, o.ObjFoo())
1600 test_garbagecollect_now()
1601 assert_equal(60, A.ClassFoo())
1602 assert_equal(150, o.ObjFoo())
1603 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001604 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001605endfunc
1606
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001607def Test_class_function()
1608 var lines =<< trim END
1609 vim9script
1610 class Value
1611 this.value = 0
1612 static objects = 0
1613
1614 def new(v: number)
1615 this.value = v
1616 ++objects
1617 enddef
1618
1619 static def GetCount(): number
1620 return objects
1621 enddef
1622 endclass
1623
1624 assert_equal(0, Value.GetCount())
1625 var v1 = Value.new(2)
1626 assert_equal(1, Value.GetCount())
1627 var v2 = Value.new(7)
1628 assert_equal(2, Value.GetCount())
1629 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001630 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001631
1632 # Test for cleaning up after a class definition failure when using class
1633 # functions.
1634 lines =<< trim END
1635 vim9script
1636 class A
1637 static def Foo()
1638 enddef
1639 aaa
1640 endclass
1641 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001642 v9.CheckSourceFailure(lines, 'E1318:')
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001643enddef
1644
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001645def Test_class_defcompile()
1646 var lines =<< trim END
1647 vim9script
1648
1649 class C
1650 def Fo(i: number): string
1651 return i
1652 enddef
1653 endclass
1654
1655 defcompile C.Fo
1656 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001657 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001658
1659 lines =<< trim END
1660 vim9script
1661
1662 class C
1663 static def Fc(): number
1664 return 'x'
1665 enddef
1666 endclass
1667
1668 defcompile C.Fc
1669 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001670 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001671
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001672 lines =<< trim END
1673 vim9script
1674
1675 class C
1676 static def new()
1677 enddef
1678 endclass
1679
1680 defcompile C.new
1681 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001682 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" function as static')
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001683
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001684 # Trying to compile a function using a non-existing class variable
1685 lines =<< trim END
1686 vim9script
1687 defcompile x.Foo()
1688 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001689 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001690
1691 # Trying to compile a function using a variable which is not a class
1692 lines =<< trim END
1693 vim9script
1694 var x: number
1695 defcompile x.Foo()
1696 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001697 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001698
1699 # Trying to compile a function without specifying the name
1700 lines =<< trim END
1701 vim9script
1702 class A
1703 endclass
1704 defcompile A.
1705 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001706 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001707
1708 # Trying to compile a non-existing class object member function
1709 lines =<< trim END
1710 vim9script
1711 class A
1712 endclass
1713 var a = A.new()
1714 defcompile a.Foo()
1715 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001716 v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001717enddef
1718
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001719def Test_class_object_to_string()
1720 var lines =<< trim END
1721 vim9script
1722 class TextPosition
1723 this.lnum = 1
1724 this.col = 22
1725 endclass
1726
1727 assert_equal("class TextPosition", string(TextPosition))
1728
1729 var pos = TextPosition.new()
1730 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1731 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001732 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001733enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001734
Bram Moolenaar554d0312023-01-05 19:59:18 +00001735def Test_interface_basics()
1736 var lines =<< trim END
1737 vim9script
1738 interface Something
1739 this.value: string
1740 static count: number
1741 def GetCount(): number
1742 endinterface
1743 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001744 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001745
1746 lines =<< trim END
1747 interface SomethingWrong
1748 static count = 7
1749 endinterface
1750 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001751 v9.CheckSourceFailure(lines, 'E1342:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001752
1753 lines =<< trim END
1754 vim9script
1755
1756 interface Some
1757 static count: number
1758 def Method(count: number)
1759 endinterface
1760 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001761 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001762
1763 lines =<< trim END
1764 vim9script
1765
1766 interface Some
1767 this.value: number
1768 def Method(value: number)
1769 endinterface
1770 END
h-east61378a12023-04-18 19:07:29 +01001771 # The argument name and the object member name are the same, but this is not a
1772 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001773 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001774
1775 lines =<< trim END
1776 vim9script
1777 interface somethingWrong
1778 static count = 7
1779 endinterface
1780 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001781 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001782
1783 lines =<< trim END
1784 vim9script
1785 interface SomethingWrong
1786 this.value: string
1787 static count = 7
1788 def GetCount(): number
1789 endinterface
1790 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001791 v9.CheckSourceFailure(lines, 'E1344:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001792
1793 lines =<< trim END
1794 vim9script
1795 interface SomethingWrong
1796 this.value: string
1797 static count: number
1798 def GetCount(): number
1799 return 5
1800 enddef
1801 endinterface
1802 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001803 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001804
1805 lines =<< trim END
1806 vim9script
1807 export interface EnterExit
1808 def Enter(): void
1809 def Exit(): void
1810 endinterface
1811 END
1812 writefile(lines, 'XdefIntf.vim', 'D')
1813
1814 lines =<< trim END
1815 vim9script
1816 import './XdefIntf.vim' as defIntf
1817 export def With(ee: defIntf.EnterExit, F: func)
1818 ee.Enter()
1819 try
1820 F()
1821 finally
1822 ee.Exit()
1823 endtry
1824 enddef
1825 END
1826 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001827
1828 var imported =<< trim END
1829 vim9script
1830 export abstract class EnterExit
1831 def Enter(): void
1832 enddef
1833 def Exit(): void
1834 enddef
1835 endclass
1836 END
1837 writefile(imported, 'XdefIntf2.vim', 'D')
1838
1839 lines[1] = " import './XdefIntf2.vim' as defIntf"
1840 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001841enddef
1842
Bram Moolenaar94674f22023-01-06 18:42:20 +00001843def Test_class_implements_interface()
1844 var lines =<< trim END
1845 vim9script
1846
1847 interface Some
1848 static count: number
1849 def Method(nr: number)
1850 endinterface
1851
1852 class SomeImpl implements Some
1853 static count: number
1854 def Method(nr: number)
1855 echo nr
1856 enddef
1857 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001858
1859 interface Another
1860 this.member: string
1861 endinterface
1862
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001863 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001864 this.member = 'abc'
1865 static count: number
1866 def Method(nr: number)
1867 echo nr
1868 enddef
1869 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001870 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001871 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00001872
1873 lines =<< trim END
1874 vim9script
1875
1876 interface Some
1877 static counter: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001878 endinterface
1879
1880 class SomeImpl implements Some implements Some
1881 static count: number
1882 endclass
1883 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001884 v9.CheckSourceFailure(lines, 'E1350:')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001885
1886 lines =<< trim END
1887 vim9script
1888
1889 interface Some
1890 static counter: number
1891 endinterface
1892
1893 class SomeImpl implements Some, Some
1894 static count: number
1895 endclass
1896 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001897 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001898
1899 lines =<< trim END
1900 vim9script
1901
1902 interface Some
1903 static counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001904 def Method(nr: number)
1905 endinterface
1906
1907 class SomeImpl implements Some
1908 static count: number
1909 def Method(nr: number)
1910 echo nr
1911 enddef
1912 endclass
1913 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001914 v9.CheckSourceFailure(lines, 'E1348: Member "counter" of interface "Some" not implemented')
Bram Moolenaar94674f22023-01-06 18:42:20 +00001915
1916 lines =<< trim END
1917 vim9script
1918
1919 interface Some
1920 static count: number
1921 def Methods(nr: number)
1922 endinterface
1923
1924 class SomeImpl implements Some
1925 static count: number
1926 def Method(nr: number)
1927 echo nr
1928 enddef
1929 endclass
1930 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001931 v9.CheckSourceFailure(lines, 'E1349: Function "Methods" of interface "Some" not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001932
1933 # Check different order of members in class and interface works.
1934 lines =<< trim END
1935 vim9script
1936
1937 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001938 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001939 this.errpos: number
1940 endinterface
1941
1942 # order of members is opposite of interface
1943 class Failure implements Result
1944 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001945 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001946 endclass
1947
1948 def Test()
1949 var result: Result = Failure.new()
1950
1951 assert_equal('label', result.label)
1952 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00001953
1954 result.label = 'different'
1955 assert_equal('different', result.label)
1956 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00001957 enddef
1958
1959 Test()
1960 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001961 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001962
1963 # Interface name after "extends" doesn't end in a space or NUL character
1964 lines =<< trim END
1965 vim9script
1966 interface A
1967 endinterface
1968 class B extends A"
1969 endclass
1970 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001971 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001972
1973 # Trailing characters after a class name
1974 lines =<< trim END
1975 vim9script
1976 class A bbb
1977 endclass
1978 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001979 v9.CheckSourceFailure(lines, 'E488:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001980
1981 # using "implements" with a non-existing class
1982 lines =<< trim END
1983 vim9script
1984 class A implements B
1985 endclass
1986 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001987 v9.CheckSourceFailure(lines, 'E1346:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001988
1989 # using "implements" with a regular class
1990 lines =<< trim END
1991 vim9script
1992 class A
1993 endclass
1994 class B implements A
1995 endclass
1996 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001997 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001998
1999 # using "implements" with a variable
2000 lines =<< trim END
2001 vim9script
2002 var T: number = 10
2003 class A implements T
2004 endclass
2005 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002006 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002007
2008 # all the class methods in an "interface" should be implemented
2009 lines =<< trim END
2010 vim9script
2011 interface A
2012 static def Foo()
2013 endinterface
2014 class B implements A
2015 endclass
2016 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002017 v9.CheckSourceFailure(lines, 'E1349:')
LemonBoyc5d27442023-08-19 13:02:35 +02002018
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002019 # implements should be followed by a white space
2020 lines =<< trim END
2021 vim9script
2022 interface A
2023 endinterface
2024 class B implements A;
2025 endclass
2026 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002027 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002028
LemonBoyc5d27442023-08-19 13:02:35 +02002029 lines =<< trim END
2030 vim9script
2031
2032 interface One
2033 static matching: bool
2034 static as_any: any
2035 static not_matching: number
2036 endinterface
2037 class Two implements One
2038 static not_matching: string
2039 static as_any: string
2040 static matching: bool
2041 endclass
2042 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002043 v9.CheckSourceFailure(lines, 'E1406: Member "not_matching": type mismatch, expected number but got string')
LemonBoyc5d27442023-08-19 13:02:35 +02002044
2045 lines =<< trim END
2046 vim9script
2047
2048 interface One
2049 def IsEven(nr: number): bool
2050 endinterface
2051 class Two implements One
2052 def IsEven(nr: number): string
2053 enddef
2054 endclass
2055 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002056 v9.CheckSourceFailure(lines, 'E1407: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02002057
2058 lines =<< trim END
2059 vim9script
2060
2061 interface One
2062 def IsEven(nr: number): bool
2063 endinterface
2064 class Two implements One
2065 def IsEven(nr: bool): bool
2066 enddef
2067 endclass
2068 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002069 v9.CheckSourceFailure(lines, 'E1407: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02002070
2071 lines =<< trim END
2072 vim9script
2073
2074 interface One
2075 def IsEven(nr: number): bool
2076 endinterface
2077 class Two implements One
2078 def IsEven(nr: number, ...extra: list<number>): bool
2079 enddef
2080 endclass
2081 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002082 v9.CheckSourceFailure(lines, 'E1407: Method "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
Ernie Raelcf138d42023-09-06 20:45:03 +02002083
2084 # access superclass interface members from subclass, mix variable order
2085 lines =<< trim END
2086 vim9script
2087
2088 interface I1
2089 public static svar1: number
2090 public static svar2: number
2091 public this.mvar1: number
2092 public this.mvar2: number
2093 endinterface
2094
2095 # NOTE: the order is swapped
2096 class A implements I1
2097 public this.mvar2: number
2098 public this.mvar1: number
2099 public static svar2: number
2100 public static svar1: number
2101 def new()
2102 svar1 = 11
2103 svar2 = 12
2104 this.mvar1 = 111
2105 this.mvar2 = 112
2106 enddef
2107 endclass
2108
2109 class B extends A
2110 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002111 this.mvar1 = 121
2112 this.mvar2 = 122
2113 enddef
2114 endclass
2115
2116 class C extends B
2117 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002118 this.mvar1 = 131
2119 this.mvar2 = 132
2120 enddef
2121 endclass
2122
Ernie Raelcf138d42023-09-06 20:45:03 +02002123 def F2(i: I1): list<number>
2124 return [ i.mvar1, i.mvar2 ]
2125 enddef
2126
2127 var oa = A.new()
2128 var ob = B.new()
2129 var oc = C.new()
2130
Ernie Raelcf138d42023-09-06 20:45:03 +02002131 assert_equal([111, 112], F2(oa))
2132 assert_equal([121, 122], F2(ob))
2133 assert_equal([131, 132], F2(oc))
2134 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002135 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002136
2137 # Access superclass interface members from subclass, mix variable order.
2138 # Two interfaces, one on A, one on B; each has both kinds of variables
2139 lines =<< trim END
2140 vim9script
2141
2142 interface I1
2143 public static svar1: number
2144 public static svar2: number
2145 public this.mvar1: number
2146 public this.mvar2: number
2147 endinterface
2148
2149 interface I2
2150 public static svar3: number
2151 public static svar4: number
2152 public this.mvar3: number
2153 public this.mvar4: number
2154 endinterface
2155
2156 class A implements I1
2157 public static svar1: number
2158 public static svar2: number
2159 public this.mvar1: number
2160 public this.mvar2: number
2161 def new()
2162 svar1 = 11
2163 svar2 = 12
2164 this.mvar1 = 111
2165 this.mvar2 = 112
2166 enddef
2167 endclass
2168
2169 class B extends A implements I2
2170 public static svar3: number
2171 public static svar4: number
2172 public this.mvar3: number
2173 public this.mvar4: number
2174 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002175 svar3 = 23
2176 svar4 = 24
2177 this.mvar1 = 121
2178 this.mvar2 = 122
2179 this.mvar3 = 123
2180 this.mvar4 = 124
2181 enddef
2182 endclass
2183
2184 class C extends B
2185 public static svar5: number
2186 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002187 svar5 = 1001
2188 this.mvar1 = 131
2189 this.mvar2 = 132
2190 this.mvar3 = 133
2191 this.mvar4 = 134
2192 enddef
2193 endclass
2194
Ernie Raelcf138d42023-09-06 20:45:03 +02002195 def F2(i: I1): list<number>
2196 return [ i.mvar1, i.mvar2 ]
2197 enddef
2198
Ernie Raelcf138d42023-09-06 20:45:03 +02002199 def F4(i: I2): list<number>
2200 return [ i.mvar3, i.mvar4 ]
2201 enddef
2202
Ernie Raelcf138d42023-09-06 20:45:03 +02002203 var oa = A.new()
2204 var ob = B.new()
2205 var oc = C.new()
2206
Ernie Raelcf138d42023-09-06 20:45:03 +02002207 assert_equal([[111, 112]], [F2(oa)])
2208 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2209 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002210 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002211 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002212enddef
2213
Bram Moolenaard0200c82023-01-28 15:19:40 +00002214def Test_call_interface_method()
2215 var lines =<< trim END
2216 vim9script
2217 interface Base
2218 def Enter(): void
2219 endinterface
2220
2221 class Child implements Base
2222 def Enter(): void
2223 g:result ..= 'child'
2224 enddef
2225 endclass
2226
2227 def F(obj: Base)
2228 obj.Enter()
2229 enddef
2230
2231 g:result = ''
2232 F(Child.new())
2233 assert_equal('child', g:result)
2234 unlet g:result
2235 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002236 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002237
2238 lines =<< trim END
2239 vim9script
2240 class Base
2241 def Enter(): void
2242 g:result ..= 'base'
2243 enddef
2244 endclass
2245
2246 class Child extends Base
2247 def Enter(): void
2248 g:result ..= 'child'
2249 enddef
2250 endclass
2251
2252 def F(obj: Base)
2253 obj.Enter()
2254 enddef
2255
2256 g:result = ''
2257 F(Child.new())
2258 assert_equal('child', g:result)
2259 unlet g:result
2260 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002261 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002262
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002263 # method of interface returns a value
2264 lines =<< trim END
2265 vim9script
2266 interface Base
2267 def Enter(): string
2268 endinterface
2269
2270 class Child implements Base
2271 def Enter(): string
2272 g:result ..= 'child'
2273 return "/resource"
2274 enddef
2275 endclass
2276
2277 def F(obj: Base)
2278 var r = obj.Enter()
2279 g:result ..= r
2280 enddef
2281
2282 g:result = ''
2283 F(Child.new())
2284 assert_equal('child/resource', g:result)
2285 unlet g:result
2286 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002287 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002288
2289 lines =<< trim END
2290 vim9script
2291 class Base
2292 def Enter(): string
2293 return null_string
2294 enddef
2295 endclass
2296
2297 class Child extends Base
2298 def Enter(): string
2299 g:result ..= 'child'
2300 return "/resource"
2301 enddef
2302 endclass
2303
2304 def F(obj: Base)
2305 var r = obj.Enter()
2306 g:result ..= r
2307 enddef
2308
2309 g:result = ''
2310 F(Child.new())
2311 assert_equal('child/resource', g:result)
2312 unlet g:result
2313 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002314 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002315
2316
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002317 # No class that implements the interface.
2318 lines =<< trim END
2319 vim9script
2320
2321 interface IWithEE
2322 def Enter(): any
2323 def Exit(): void
2324 endinterface
2325
2326 def With1(ee: IWithEE, F: func)
2327 var r = ee.Enter()
2328 enddef
2329
2330 defcompile
2331 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002332 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002333enddef
2334
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002335def Test_class_used_as_type()
2336 var lines =<< trim END
2337 vim9script
2338
2339 class Point
2340 this.x = 0
2341 this.y = 0
2342 endclass
2343
2344 var p: Point
2345 p = Point.new(2, 33)
2346 assert_equal(2, p.x)
2347 assert_equal(33, p.y)
2348 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002349 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002350
2351 lines =<< trim END
2352 vim9script
2353
2354 interface HasX
2355 this.x: number
2356 endinterface
2357
2358 class Point implements HasX
2359 this.x = 0
2360 this.y = 0
2361 endclass
2362
2363 var p: Point
2364 p = Point.new(2, 33)
2365 var hx = p
2366 assert_equal(2, hx.x)
2367 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002368 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002369
2370 lines =<< trim END
2371 vim9script
2372
2373 class Point
2374 this.x = 0
2375 this.y = 0
2376 endclass
2377
2378 var p: Point
2379 p = 'text'
2380 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002381 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002382enddef
2383
Bram Moolenaar83677162023-01-08 19:54:10 +00002384def Test_class_extends()
2385 var lines =<< trim END
2386 vim9script
2387 class Base
2388 this.one = 1
2389 def GetOne(): number
2390 return this.one
2391 enddef
2392 endclass
2393 class Child extends Base
2394 this.two = 2
2395 def GetTotal(): number
2396 return this.one + this.two
2397 enddef
2398 endclass
2399 var o = Child.new()
2400 assert_equal(1, o.one)
2401 assert_equal(2, o.two)
2402 assert_equal(1, o.GetOne())
2403 assert_equal(3, o.GetTotal())
2404 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002405 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002406
2407 lines =<< trim END
2408 vim9script
2409 class Base
2410 this.one = 1
2411 endclass
2412 class Child extends Base
2413 this.two = 2
2414 endclass
2415 var o = Child.new(3, 44)
2416 assert_equal(3, o.one)
2417 assert_equal(44, o.two)
2418 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002419 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002420
2421 lines =<< trim END
2422 vim9script
2423 class Base
2424 this.one = 1
2425 endclass
2426 class Child extends Base extends Base
2427 this.two = 2
2428 endclass
2429 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002430 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
Bram Moolenaar83677162023-01-08 19:54:10 +00002431
2432 lines =<< trim END
2433 vim9script
2434 class Child extends BaseClass
2435 this.two = 2
2436 endclass
2437 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002438 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
Bram Moolenaar83677162023-01-08 19:54:10 +00002439
2440 lines =<< trim END
2441 vim9script
2442 var SomeVar = 99
2443 class Child extends SomeVar
2444 this.two = 2
2445 endclass
2446 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002447 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002448
2449 lines =<< trim END
2450 vim9script
2451 class Base
2452 this.name: string
2453 def ToString(): string
2454 return this.name
2455 enddef
2456 endclass
2457
2458 class Child extends Base
2459 this.age: number
2460 def ToString(): string
2461 return super.ToString() .. ': ' .. this.age
2462 enddef
2463 endclass
2464
2465 var o = Child.new('John', 42)
2466 assert_equal('John: 42', o.ToString())
2467 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002468 v9.CheckSourceSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002469
2470 lines =<< trim END
2471 vim9script
2472 class Child
2473 this.age: number
2474 def ToString(): number
2475 return this.age
2476 enddef
2477 def ToString(): string
2478 return this.age
2479 enddef
2480 endclass
2481 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002482 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002483
2484 lines =<< trim END
2485 vim9script
2486 class Child
2487 this.age: number
2488 def ToString(): string
2489 return super .ToString() .. ': ' .. this.age
2490 enddef
2491 endclass
2492 var o = Child.new(42)
2493 echo o.ToString()
2494 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002495 v9.CheckSourceFailure(lines, 'E1356:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002496
2497 lines =<< trim END
2498 vim9script
2499 class Base
2500 this.name: string
2501 def ToString(): string
2502 return this.name
2503 enddef
2504 endclass
2505
2506 var age = 42
2507 def ToString(): string
2508 return super.ToString() .. ': ' .. age
2509 enddef
2510 echo ToString()
2511 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002512 v9.CheckSourceFailure(lines, 'E1357:')
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, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002526
2527 lines =<< trim END
2528 vim9script
2529 class Base
2530 this.name: string
2531 static def ToString(): string
2532 return 'Base class'
2533 enddef
2534 endclass
2535
2536 class Child extends Base
2537 this.age: number
2538 def ToString(): string
2539 return Base.ToString() .. ': ' .. this.age
2540 enddef
2541 endclass
2542
2543 var o = Child.new('John', 42)
2544 assert_equal('Base class: 42', o.ToString())
2545 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002546 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002547
2548 lines =<< trim END
2549 vim9script
2550 class Base
2551 this.value = 1
2552 def new(init: number)
2553 this.value = number + 1
2554 enddef
2555 endclass
2556 class Child extends Base
2557 def new()
2558 this.new(3)
2559 enddef
2560 endclass
2561 var c = Child.new()
2562 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002563 v9.CheckSourceFailure(lines, 'E1375: Class member "new" accessible only using class "Child"')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002564
2565 # base class with more than one object member
2566 lines =<< trim END
2567 vim9script
2568
2569 class Result
2570 this.success: bool
2571 this.value: any = null
2572 endclass
2573
2574 class Success extends Result
2575 def new(this.value = v:none)
2576 this.success = true
2577 enddef
2578 endclass
2579
2580 var v = Success.new('asdf')
2581 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2582 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002583 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002584
2585 # class name after "extends" doesn't end in a space or NUL character
2586 lines =<< trim END
2587 vim9script
2588 class A
2589 endclass
2590 class B extends A"
2591 endclass
2592 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002593 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002594enddef
2595
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002596def Test_using_base_class()
2597 var lines =<< trim END
2598 vim9script
2599
2600 class BaseEE
2601 def Enter(): any
2602 return null
2603 enddef
2604 def Exit(resource: any): void
2605 enddef
2606 endclass
2607
2608 class ChildEE extends BaseEE
2609 def Enter(): any
2610 return 42
2611 enddef
2612
2613 def Exit(resource: number): void
2614 g:result ..= '/exit'
2615 enddef
2616 endclass
2617
2618 def With(ee: BaseEE)
2619 var r = ee.Enter()
2620 try
2621 g:result ..= r
2622 finally
2623 g:result ..= '/finally'
2624 ee.Exit(r)
2625 endtry
2626 enddef
2627
2628 g:result = ''
2629 With(ChildEE.new())
2630 assert_equal('42/finally/exit', g:result)
2631 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002632 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002633 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002634
2635 # Using super, Child invokes Base method which has optional arg. #12471
2636 lines =<< trim END
2637 vim9script
2638
2639 class Base
2640 this.success: bool = false
2641 def Method(arg = 0)
2642 this.success = true
2643 enddef
2644 endclass
2645
2646 class Child extends Base
2647 def new()
2648 super.Method()
2649 enddef
2650 endclass
2651
2652 var obj = Child.new()
2653 assert_equal(true, obj.success)
2654 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002655 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002656enddef
2657
2658
Bram Moolenaara86655a2023-01-12 17:06:27 +00002659def Test_class_import()
2660 var lines =<< trim END
2661 vim9script
2662 export class Animal
2663 this.kind: string
2664 this.name: string
2665 endclass
2666 END
2667 writefile(lines, 'Xanimal.vim', 'D')
2668
2669 lines =<< trim END
2670 vim9script
2671 import './Xanimal.vim' as animal
2672
2673 var a: animal.Animal
2674 a = animal.Animal.new('fish', 'Eric')
2675 assert_equal('fish', a.kind)
2676 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002677
2678 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2679 assert_equal('cat', b.kind)
2680 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002681 END
2682 v9.CheckScriptSuccess(lines)
2683enddef
2684
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002685def Test_abstract_class()
2686 var lines =<< trim END
2687 vim9script
2688 abstract class Base
2689 this.name: string
2690 endclass
2691 class Person extends Base
2692 this.age: number
2693 endclass
2694 var p: Base = Person.new('Peter', 42)
2695 assert_equal('Peter', p.name)
2696 assert_equal(42, p.age)
2697 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002698 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002699
2700 lines =<< trim END
2701 vim9script
2702 abstract class Base
2703 this.name: string
2704 endclass
2705 class Person extends Base
2706 this.age: number
2707 endclass
2708 var p = Base.new('Peter')
2709 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002710 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002711
2712 lines =<< trim END
2713 abstract class Base
2714 this.name: string
2715 endclass
2716 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002717 v9.CheckSourceFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002718
2719 # Abstract class cannot have a "new" function
2720 lines =<< trim END
2721 vim9script
2722 abstract class Base
2723 def new()
2724 enddef
2725 endclass
2726 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002727 v9.CheckSourceFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002728enddef
2729
Bram Moolenaar486fc252023-01-18 14:51:07 +00002730def Test_closure_in_class()
2731 var lines =<< trim END
2732 vim9script
2733
2734 class Foo
2735 this.y: list<string> = ['B']
2736
2737 def new()
2738 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2739 enddef
2740 endclass
2741
2742 Foo.new()
2743 assert_equal(['A'], g:result)
2744 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002745 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00002746enddef
2747
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002748def Test_call_constructor_from_legacy()
2749 var lines =<< trim END
2750 vim9script
2751
2752 var newCalled = 'false'
2753
2754 class A
2755 def new()
2756 newCalled = 'true'
2757 enddef
2758 endclass
2759
2760 export def F(options = {}): any
2761 return A
2762 enddef
2763
2764 g:p = F()
2765 legacy call p.new()
2766 assert_equal('true', newCalled)
2767 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002768 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002769enddef
2770
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002771def Test_defer_with_object()
2772 var lines =<< trim END
2773 vim9script
2774
2775 class CWithEE
2776 def Enter()
2777 g:result ..= "entered/"
2778 enddef
2779 def Exit()
2780 g:result ..= "exited"
2781 enddef
2782 endclass
2783
2784 def With(ee: CWithEE, F: func)
2785 ee.Enter()
2786 defer ee.Exit()
2787 F()
2788 enddef
2789
2790 g:result = ''
2791 var obj = CWithEE.new()
2792 obj->With(() => {
2793 g:result ..= "called/"
2794 })
2795 assert_equal('entered/called/exited', g:result)
2796 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002797 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002798 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002799
2800 lines =<< trim END
2801 vim9script
2802
2803 class BaseWithEE
2804 def Enter()
2805 g:result ..= "entered-base/"
2806 enddef
2807 def Exit()
2808 g:result ..= "exited-base"
2809 enddef
2810 endclass
2811
2812 class CWithEE extends BaseWithEE
2813 def Enter()
2814 g:result ..= "entered-child/"
2815 enddef
2816 def Exit()
2817 g:result ..= "exited-child"
2818 enddef
2819 endclass
2820
2821 def With(ee: BaseWithEE, F: func)
2822 ee.Enter()
2823 defer ee.Exit()
2824 F()
2825 enddef
2826
2827 g:result = ''
2828 var obj = CWithEE.new()
2829 obj->With(() => {
2830 g:result ..= "called/"
2831 })
2832 assert_equal('entered-child/called/exited-child', g:result)
2833 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002834 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00002835 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002836enddef
2837
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002838" The following test used to crash Vim (Github issue #12676)
2839def Test_extends_method_crashes_vim()
2840 var lines =<< trim END
2841 vim9script
2842
2843 class Observer
2844 endclass
2845
2846 class Property
2847 this.value: any
2848
2849 def Set(v: any)
2850 if v != this.value
2851 this.value = v
2852 endif
2853 enddef
2854
2855 def Register(observer: Observer)
2856 enddef
2857 endclass
2858
2859 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002860 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002861 endclass
2862
2863 def Observe(obj: Property, who: Observer)
2864 obj.Register(who)
2865 enddef
2866
2867 var p = Bool.new(false)
2868 var myObserver = Observer.new()
2869
2870 Observe(p, myObserver)
2871
2872 p.Set(true)
2873 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002874 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002875enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002876
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002877" Test for calling a method in a class that is extended
2878def Test_call_method_in_extended_class()
2879 var lines =<< trim END
2880 vim9script
2881
2882 var prop_init_called = false
2883 var prop_register_called = false
2884
2885 class Property
2886 def Init()
2887 prop_init_called = true
2888 enddef
2889
2890 def Register()
2891 prop_register_called = true
2892 enddef
2893 endclass
2894
2895 class Bool extends Property
2896 endclass
2897
2898 def Observe(obj: Property)
2899 obj.Register()
2900 enddef
2901
2902 var p = Property.new()
2903 Observe(p)
2904
2905 p.Init()
2906 assert_true(prop_init_called)
2907 assert_true(prop_register_called)
2908 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002909 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002910enddef
2911
LemonBoyafe04662023-08-23 21:08:11 +02002912def Test_instanceof()
2913 var lines =<< trim END
2914 vim9script
2915
2916 class Base1
2917 endclass
2918
2919 class Base2 extends Base1
2920 endclass
2921
2922 interface Intf1
2923 endinterface
2924
2925 class Mix1 implements Intf1
2926 endclass
2927
2928 class Base3 extends Mix1
2929 endclass
2930
2931 var b1 = Base1.new()
2932 var b2 = Base2.new()
2933 var b3 = Base3.new()
2934
2935 assert_true(instanceof(b1, Base1))
2936 assert_true(instanceof(b2, Base1))
2937 assert_false(instanceof(b1, Base2))
2938 assert_true(instanceof(b3, Mix1))
2939 assert_false(instanceof(b3, []))
2940 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02002941
2942 def Foo()
2943 var a1 = Base1.new()
2944 var a2 = Base2.new()
2945 var a3 = Base3.new()
2946
2947 assert_true(instanceof(a1, Base1))
2948 assert_true(instanceof(a2, Base1))
2949 assert_false(instanceof(a1, Base2))
2950 assert_true(instanceof(a3, Mix1))
2951 assert_false(instanceof(a3, []))
2952 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
2953 enddef
2954 Foo()
LemonBoyafe04662023-08-23 21:08:11 +02002955 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002956 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02002957enddef
2958
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002959" Test for calling a method in the parent class that is extended partially.
2960" This used to fail with the 'E118: Too many arguments for function: Text' error
2961" message (Github issue #12524).
2962def Test_call_method_in_parent_class()
2963 var lines =<< trim END
2964 vim9script
2965
2966 class Widget
2967 this._lnum: number = 1
2968
2969 def SetY(lnum: number)
2970 this._lnum = lnum
2971 enddef
2972
2973 def Text(): string
2974 return ''
2975 enddef
2976 endclass
2977
2978 class Foo extends Widget
2979 def Text(): string
2980 return '<Foo>'
2981 enddef
2982 endclass
2983
2984 def Stack(w1: Widget, w2: Widget): list<Widget>
2985 w1.SetY(1)
2986 w2.SetY(2)
2987 return [w1, w2]
2988 enddef
2989
2990 var foo1 = Foo.new()
2991 var foo2 = Foo.new()
2992 var l = Stack(foo1, foo2)
2993 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002994 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02002995enddef
2996
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002997" Test for calling methods from three levels of classes
2998def Test_multi_level_method_call()
2999 var lines =<< trim END
3000 vim9script
3001
3002 var A_func1: number = 0
3003 var A_func2: number = 0
3004 var A_func3: number = 0
3005 var B_func2: number = 0
3006 var B_func3: number = 0
3007 var C_func3: number = 0
3008
3009 class A
3010 def Func1()
3011 A_func1 += 1
3012 enddef
3013
3014 def Func2()
3015 A_func2 += 1
3016 enddef
3017
3018 def Func3()
3019 A_func3 += 1
3020 enddef
3021 endclass
3022
3023 class B extends A
3024 def Func2()
3025 B_func2 += 1
3026 enddef
3027
3028 def Func3()
3029 B_func3 += 1
3030 enddef
3031 endclass
3032
3033 class C extends B
3034 def Func3()
3035 C_func3 += 1
3036 enddef
3037 endclass
3038
3039 def A_CallFuncs(a: A)
3040 a.Func1()
3041 a.Func2()
3042 a.Func3()
3043 enddef
3044
3045 def B_CallFuncs(b: B)
3046 b.Func1()
3047 b.Func2()
3048 b.Func3()
3049 enddef
3050
3051 def C_CallFuncs(c: C)
3052 c.Func1()
3053 c.Func2()
3054 c.Func3()
3055 enddef
3056
3057 var cobj = C.new()
3058 A_CallFuncs(cobj)
3059 B_CallFuncs(cobj)
3060 C_CallFuncs(cobj)
3061 assert_equal(3, A_func1)
3062 assert_equal(0, A_func2)
3063 assert_equal(0, A_func3)
3064 assert_equal(3, B_func2)
3065 assert_equal(0, B_func3)
3066 assert_equal(3, C_func3)
3067 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003068 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003069enddef
3070
3071" Test for using members from three levels of classes
3072def Test_multi_level_member_access()
3073 var lines =<< trim END
3074 vim9script
3075
3076 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003077 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003078 endclass
3079
3080 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003081 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003082 endclass
3083
3084 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003085 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003086 endclass
3087
3088 def A_members(a: A)
3089 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003090 enddef
3091
3092 def B_members(b: B)
3093 b.val1 += 1
3094 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003095 enddef
3096
3097 def C_members(c: C)
3098 c.val1 += 1
3099 c.val2 += 1
3100 c.val3 += 1
3101 enddef
3102
3103 var cobj = C.new()
3104 A_members(cobj)
3105 B_members(cobj)
3106 C_members(cobj)
3107 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003108 assert_equal(2, cobj.val2)
3109 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003110 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003111 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003112enddef
3113
LemonBoy0ffc17a2023-08-20 18:09:11 +02003114" Test expansion of <stack> with class methods.
3115def Test_stack_expansion_with_methods()
3116 var lines =<< trim END
3117 vim9script
3118
3119 class C
3120 def M1()
3121 F0()
3122 enddef
3123 endclass
3124
3125 def F0()
3126 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3127 enddef
3128
3129 def F()
3130 C.new().M1()
3131 enddef
3132
3133 F()
3134 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003135 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003136enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003137
3138" Test the return type of the new() constructor
3139def Test_new_return_type()
3140 # new() uses the default return type and there is no return statement
3141 var lines =<< trim END
3142 vim9script
3143
3144 class C
3145 this._bufnr: number
3146
3147 def new(this._bufnr)
3148 if !bufexists(this._bufnr)
3149 this._bufnr = -1
3150 endif
3151 enddef
3152 endclass
3153
3154 var c = C.new(12345)
3155 assert_equal('object<C>', typename(c))
3156
3157 var v1: C
3158 v1 = C.new(12345)
3159 assert_equal('object<C>', typename(v1))
3160
3161 def F()
3162 var v2: C
3163 v2 = C.new(12345)
3164 assert_equal('object<C>', typename(v2))
3165 enddef
3166 F()
3167 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003168 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003169
3170 # new() uses the default return type and an empty 'return' statement
3171 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 return
3181 endif
3182 enddef
3183 endclass
3184
3185 var c = C.new(12345)
3186 assert_equal('object<C>', typename(c))
3187
3188 var v1: C
3189 v1 = C.new(12345)
3190 assert_equal('object<C>', typename(v1))
3191
3192 def F()
3193 var v2: C
3194 v2 = C.new(12345)
3195 assert_equal('object<C>', typename(v2))
3196 enddef
3197 F()
3198 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003199 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003200
3201 # new() uses "any" return type and returns "this"
3202 lines =<< trim END
3203 vim9script
3204
3205 class C
3206 this._bufnr: number
3207
3208 def new(this._bufnr): any
3209 if !bufexists(this._bufnr)
3210 this._bufnr = -1
3211 return this
3212 endif
3213 enddef
3214 endclass
3215 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003216 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003217
3218 # new() uses 'Dict' return type and returns a Dict
3219 lines =<< trim END
3220 vim9script
3221
3222 class C
3223 this._state: dict<any>
3224
3225 def new(): dict<any>
3226 this._state = {}
3227 return this._state
3228 enddef
3229 endclass
3230
3231 var c = C.new()
3232 assert_equal('object<C>', typename(c))
3233 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003234 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003235enddef
3236
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003237" Test for checking a member initialization type at run time.
3238def Test_runtime_type_check_for_member_init()
3239 var lines =<< trim END
3240 vim9script
3241
3242 var retnum: bool = false
3243
3244 def F(): any
3245 retnum = !retnum
3246 if retnum
3247 return 1
3248 else
3249 return "hello"
3250 endif
3251 enddef
3252
3253 class C
3254 this._foo: bool = F()
3255 endclass
3256
3257 var c1 = C.new()
3258 var c2 = C.new()
3259 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003260 v9.CheckSourceFailure(lines, 'E1012:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003261enddef
3262
3263" Test for locking a variable referring to an object and reassigning to another
3264" object.
3265def Test_object_lockvar()
3266 var lines =<< trim END
3267 vim9script
3268
3269 class C
3270 this.val: number
3271 def new(this.val)
3272 enddef
3273 endclass
3274
3275 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3276 lockvar 2 some_dict
3277
3278 var current: C
3279 current = some_dict['c']
3280 assert_equal(3, current.val)
3281 current = some_dict['b']
3282 assert_equal(2, current.val)
3283
3284 def F()
3285 current = some_dict['c']
3286 enddef
3287
3288 def G()
3289 current = some_dict['b']
3290 enddef
3291
3292 F()
3293 assert_equal(3, current.val)
3294 G()
3295 assert_equal(2, current.val)
3296 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003297 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003298enddef
3299
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003300" Test for a private object method
3301def Test_private_object_method()
3302 # Try calling a private method using an object (at the script level)
3303 var lines =<< trim END
3304 vim9script
3305
3306 class A
3307 def _Foo(): number
3308 return 1234
3309 enddef
3310 endclass
3311 var a = A.new()
3312 a._Foo()
3313 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003314 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003315
3316 # Try calling a private method using an object (from a def function)
3317 lines =<< trim END
3318 vim9script
3319
3320 class A
3321 def _Foo(): number
3322 return 1234
3323 enddef
3324 endclass
3325 def T()
3326 var a = A.new()
3327 a._Foo()
3328 enddef
3329 T()
3330 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003331 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003332
3333 # Use a private method from another object method (in script context)
3334 lines =<< trim END
3335 vim9script
3336
3337 class A
3338 def _Foo(): number
3339 return 1234
3340 enddef
3341 def Bar(): number
3342 return this._Foo()
3343 enddef
3344 endclass
3345 var a = A.new()
3346 assert_equal(1234, a.Bar())
3347 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003348 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003349
3350 # Use a private method from another object method (def function context)
3351 lines =<< trim END
3352 vim9script
3353
3354 class A
3355 def _Foo(): number
3356 return 1234
3357 enddef
3358 def Bar(): number
3359 return this._Foo()
3360 enddef
3361 endclass
3362 def T()
3363 var a = A.new()
3364 assert_equal(1234, a.Bar())
3365 enddef
3366 T()
3367 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003368 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003369
3370 # Try calling a private method without the "this" prefix
3371 lines =<< trim END
3372 vim9script
3373
3374 class A
3375 def _Foo(): number
3376 return 1234
3377 enddef
3378 def Bar(): number
3379 return _Foo()
3380 enddef
3381 endclass
3382 var a = A.new()
3383 a.Bar()
3384 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003385 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003386
3387 # Try calling a private method using the class name
3388 lines =<< trim END
3389 vim9script
3390
3391 class A
3392 def _Foo(): number
3393 return 1234
3394 enddef
3395 endclass
3396 A._Foo()
3397 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003398 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003399
3400 # Try to use "public" keyword when defining a private method
3401 lines =<< trim END
3402 vim9script
3403
3404 class A
3405 public def _Foo()
3406 enddef
3407 endclass
3408 var a = A.new()
3409 a._Foo()
3410 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003411 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003412
3413 # Define two private methods with the same name
3414 lines =<< trim END
3415 vim9script
3416
3417 class A
3418 def _Foo()
3419 enddef
3420 def _Foo()
3421 enddef
3422 endclass
3423 var a = A.new()
3424 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003425 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003426
3427 # Define a private method and a object method with the same name
3428 lines =<< trim END
3429 vim9script
3430
3431 class A
3432 def _Foo()
3433 enddef
3434 def Foo()
3435 enddef
3436 endclass
3437 var a = A.new()
3438 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003439 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003440
3441 # Define an object method and a private method with the same name
3442 lines =<< trim END
3443 vim9script
3444
3445 class A
3446 def Foo()
3447 enddef
3448 def _Foo()
3449 enddef
3450 endclass
3451 var a = A.new()
3452 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003453 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003454
3455 # Call a public method and a private method from a private method
3456 lines =<< trim END
3457 vim9script
3458
3459 class A
3460 def Foo(): number
3461 return 100
3462 enddef
3463 def _Bar(): number
3464 return 200
3465 enddef
3466 def _Baz()
3467 assert_equal(100, this.Foo())
3468 assert_equal(200, this._Bar())
3469 enddef
3470 def T()
3471 this._Baz()
3472 enddef
3473 endclass
3474 var a = A.new()
3475 a.T()
3476 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003477 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003478
3479 # Try calling a private method from another class
3480 lines =<< trim END
3481 vim9script
3482
3483 class A
3484 def _Foo(): number
3485 return 100
3486 enddef
3487 endclass
3488 class B
3489 def Foo(): number
3490 var a = A.new()
3491 a._Foo()
3492 enddef
3493 endclass
3494 var b = B.new()
3495 b.Foo()
3496 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003497 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003498
3499 # Call a private object method from a child class object method
3500 lines =<< trim END
3501 vim9script
3502 class A
3503 def _Foo(): number
3504 return 1234
3505 enddef
3506 endclass
3507 class B extends A
3508 def Bar()
3509 enddef
3510 endclass
3511 class C extends B
3512 def Baz(): number
3513 return this._Foo()
3514 enddef
3515 endclass
3516 var c = C.new()
3517 assert_equal(1234, c.Baz())
3518 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003519 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003520
3521 # Call a private object method from a child class object
3522 lines =<< trim END
3523 vim9script
3524 class A
3525 def _Foo(): number
3526 return 1234
3527 enddef
3528 endclass
3529 class B extends A
3530 def Bar()
3531 enddef
3532 endclass
3533 class C extends B
3534 def Baz(): number
3535 enddef
3536 endclass
3537 var c = C.new()
3538 assert_equal(1234, c._Foo())
3539 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003540 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003541
3542 # Using "_" prefix in a method name should fail outside of a class
3543 lines =<< trim END
3544 vim9script
3545 def _Foo(): number
3546 return 1234
3547 enddef
3548 var a = _Foo()
3549 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003550 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003551enddef
3552
3553" Test for an private class method
3554def Test_private_class_method()
3555 # Try calling a class private method (at the script level)
3556 var lines =<< trim END
3557 vim9script
3558
3559 class A
3560 static def _Foo(): number
3561 return 1234
3562 enddef
3563 endclass
3564 A._Foo()
3565 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003566 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003567
3568 # Try calling a class private method (from a def function)
3569 lines =<< trim END
3570 vim9script
3571
3572 class A
3573 static def _Foo(): number
3574 return 1234
3575 enddef
3576 endclass
3577 def T()
3578 A._Foo()
3579 enddef
3580 T()
3581 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003582 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003583
3584 # Try calling a class private method using an object (at the script level)
3585 lines =<< trim END
3586 vim9script
3587
3588 class A
3589 static def _Foo(): number
3590 return 1234
3591 enddef
3592 endclass
3593 var a = A.new()
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 using an object (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 var a = A.new()
3609 a._Foo()
3610 enddef
3611 T()
3612 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003613 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003614
3615 # Use a class private method from an object method
3616 lines =<< trim END
3617 vim9script
3618
3619 class A
3620 static def _Foo(): number
3621 return 1234
3622 enddef
3623 def Bar()
3624 assert_equal(1234, A._Foo())
3625 enddef
3626 endclass
3627 var a = A.new()
3628 a.Bar()
3629 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003630 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003631
3632 # Use a class private method from another class private method
3633 lines =<< trim END
3634 vim9script
3635
3636 class A
3637 static def _Foo1(): number
3638 return 1234
3639 enddef
3640 static def _Foo2()
3641 assert_equal(1234, A._Foo1())
3642 enddef
3643 def Bar()
3644 A._Foo2()
3645 enddef
3646 endclass
3647 var a = A.new()
3648 a.Bar()
3649 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003650 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003651
3652 # Declare a class method and a class private method with the same name
3653 lines =<< trim END
3654 vim9script
3655
3656 class A
3657 static def _Foo()
3658 enddef
3659 static def Foo()
3660 enddef
3661 endclass
3662 var a = A.new()
3663 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003664 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003665
3666 # Try calling a class private method from another class
3667 lines =<< trim END
3668 vim9script
3669
3670 class A
3671 static def _Foo(): number
3672 return 1234
3673 enddef
3674 endclass
3675 class B
3676 def Foo(): number
3677 return A._Foo()
3678 enddef
3679 endclass
3680 var b = B.new()
3681 assert_equal(1234, b.Foo())
3682 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003683 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003684
3685 # Call a private class method from a child class object method
3686 lines =<< trim END
3687 vim9script
3688 class A
3689 static def _Foo(): number
3690 return 1234
3691 enddef
3692 endclass
3693 class B extends A
3694 def Bar()
3695 enddef
3696 endclass
3697 class C extends B
3698 def Baz(): number
3699 return A._Foo()
3700 enddef
3701 endclass
3702 var c = C.new()
3703 assert_equal(1234, c.Baz())
3704 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003705 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003706
3707 # Call a private class method from a child class private class method
3708 lines =<< trim END
3709 vim9script
3710 class A
3711 static def _Foo(): number
3712 return 1234
3713 enddef
3714 endclass
3715 class B extends A
3716 def Bar()
3717 enddef
3718 endclass
3719 class C extends B
3720 static def Baz(): number
3721 return A._Foo()
3722 enddef
3723 endclass
3724 assert_equal(1234, C.Baz())
3725 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003726 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003727
3728 # Call a private class method from a child class object
3729 lines =<< trim END
3730 vim9script
3731 class A
3732 static def _Foo(): number
3733 return 1234
3734 enddef
3735 endclass
3736 class B extends A
3737 def Bar()
3738 enddef
3739 endclass
3740 class C extends B
3741 def Baz(): number
3742 enddef
3743 endclass
3744 var c = C.new()
3745 assert_equal(1234, C._Foo())
3746 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003747 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003748enddef
3749
3750" Test for an interface private object_method
3751def Test_interface_private_object_method()
3752 # Implement an interface private method and use it from a public method
3753 var lines =<< trim END
3754 vim9script
3755 interface Intf
3756 def _Foo(): number
3757 endinterface
3758 class A implements Intf
3759 def _Foo(): number
3760 return 1234
3761 enddef
3762 def Bar(): number
3763 return this._Foo()
3764 enddef
3765 endclass
3766 var a = A.new()
3767 assert_equal(1234, a.Bar())
3768 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003769 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003770
3771 # Call an interface private class method (script context)
3772 lines =<< trim END
3773 vim9script
3774 interface Intf
3775 def _Foo(): number
3776 endinterface
3777 class A implements Intf
3778 def _Foo(): number
3779 return 1234
3780 enddef
3781 endclass
3782 var a = A.new()
3783 assert_equal(1234, a._Foo())
3784 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003785 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003786
3787 # Call an interface private class method (def context)
3788 lines =<< trim END
3789 vim9script
3790 interface Intf
3791 def _Foo(): number
3792 endinterface
3793 class A implements Intf
3794 def _Foo(): number
3795 return 1234
3796 enddef
3797 endclass
3798 def T()
3799 var a = A.new()
3800 assert_equal(1234, a._Foo())
3801 enddef
3802 T()
3803 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003804 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003805
3806 # Implement an interface private object method as a private class method
3807 lines =<< trim END
3808 vim9script
3809 interface Intf
3810 def _Foo(): number
3811 endinterface
3812 class A implements Intf
3813 static def _Foo(): number
3814 return 1234
3815 enddef
3816 endclass
3817 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003818 v9.CheckSourceFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003819enddef
3820
3821" Test for an interface private class method
3822def Test_interface_private_class_method()
3823 # Implement an interface private class method and use it from a public method
3824 var lines =<< trim END
3825 vim9script
3826 interface Intf
3827 static def _Foo(): number
3828 endinterface
3829 class A implements Intf
3830 static def _Foo(): number
3831 return 1234
3832 enddef
3833 def Bar(): number
3834 return A._Foo()
3835 enddef
3836 endclass
3837 var a = A.new()
3838 assert_equal(1234, a.Bar())
3839 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003840 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003841
3842 # Call an interface private class method (script context)
3843 lines =<< trim END
3844 vim9script
3845 interface Intf
3846 static def _Foo(): number
3847 endinterface
3848 class A implements Intf
3849 static def _Foo(): number
3850 return 1234
3851 enddef
3852 endclass
3853 assert_equal(1234, A._Foo())
3854 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003855 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo())')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003856
3857 # Call an interface private class method (def context)
3858 lines =<< trim END
3859 vim9script
3860 interface Intf
3861 static def _Foo(): number
3862 endinterface
3863 class A implements Intf
3864 static def _Foo(): number
3865 return 1234
3866 enddef
3867 endclass
3868 def T()
3869 assert_equal(1234, A._Foo())
3870 enddef
3871 T()
3872 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003873 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo())')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003874
3875 # Implement an interface private class method as a private object method
3876 lines =<< trim END
3877 vim9script
3878 interface Intf
3879 static def _Foo(): number
3880 endinterface
3881 class A implements Intf
3882 def _Foo(): number
3883 return 1234
3884 enddef
3885 endclass
3886 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003887 v9.CheckSourceFailure(lines, 'E1349: Function "_Foo" of interface "Intf" not implemented')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003888enddef
3889
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003890" Test for using the return value of a class/object method as a function
3891" argument.
3892def Test_objmethod_funcarg()
3893 var lines =<< trim END
3894 vim9script
3895
3896 class C
3897 def Foo(): string
3898 return 'foo'
3899 enddef
3900 endclass
3901
3902 def Bar(a: number, s: string): string
3903 return s
3904 enddef
3905
3906 def Baz(c: C)
3907 assert_equal('foo', Bar(10, c.Foo()))
3908 enddef
3909
3910 var t = C.new()
3911 Baz(t)
3912 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003913 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003914
3915 lines =<< trim END
3916 vim9script
3917
3918 class C
3919 static def Foo(): string
3920 return 'foo'
3921 enddef
3922 endclass
3923
3924 def Bar(a: number, s: string): string
3925 return s
3926 enddef
3927
3928 def Baz()
3929 assert_equal('foo', Bar(10, C.Foo()))
3930 enddef
3931
3932 Baz()
3933 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003934 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003935enddef
3936
Ernie Raelcf138d42023-09-06 20:45:03 +02003937def Test_static_inheritence()
3938 # subclasses get their own static copy
3939 var lines =<< trim END
3940 vim9script
3941
3942 class A
3943 static _svar: number
3944 this._mvar: number
3945 def new()
3946 _svar = 1
3947 this._mvar = 101
3948 enddef
3949 def AccessObject(): number
3950 return this._mvar
3951 enddef
3952 def AccessStaticThroughObject(): number
3953 return _svar
3954 enddef
3955 endclass
3956
3957 class B extends A
3958 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003959 this._mvar = 102
3960 enddef
3961 endclass
3962
3963 class C extends B
3964 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003965 this._mvar = 103
3966 enddef
3967
3968 def AccessPrivateStaticThroughClassName(): number
3969 assert_equal(1, A._svar)
Ernie Raelcf138d42023-09-06 20:45:03 +02003970 return 444
3971 enddef
3972 endclass
3973
3974 var oa = A.new()
3975 var ob = B.new()
3976 var oc = C.new()
3977 assert_equal(101, oa.AccessObject())
3978 assert_equal(102, ob.AccessObject())
3979 assert_equal(103, oc.AccessObject())
3980
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003981 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private member: _svar')
Ernie Raelcf138d42023-09-06 20:45:03 +02003982
3983 # verify object properly resolves to correct static
3984 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003985 assert_equal(1, ob.AccessStaticThroughObject())
3986 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02003987 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003988 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02003989enddef
3990
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003991" Test for declaring duplicate object and class members
3992def Test_dup_member_variable()
3993 # Duplicate member variable
3994 var lines =<< trim END
3995 vim9script
3996 class C
3997 this.val = 10
3998 this.val = 20
3999 endclass
4000 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004001 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004002
4003 # Duplicate private member variable
4004 lines =<< trim END
4005 vim9script
4006 class C
4007 this._val = 10
4008 this._val = 20
4009 endclass
4010 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004011 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004012
4013 # Duplicate public member variable
4014 lines =<< trim END
4015 vim9script
4016 class C
4017 public this.val = 10
4018 public this.val = 20
4019 endclass
4020 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004021 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004022
4023 # Duplicate private member variable
4024 lines =<< trim END
4025 vim9script
4026 class C
4027 this.val = 10
4028 this._val = 20
4029 endclass
4030 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004031 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004032
4033 # Duplicate public and private member variable
4034 lines =<< trim END
4035 vim9script
4036 class C
4037 this._val = 20
4038 public this.val = 10
4039 endclass
4040 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004041 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004042
4043 # Duplicate class member variable
4044 lines =<< trim END
4045 vim9script
4046 class C
4047 static s: string = "abc"
4048 static _s: string = "def"
4049 endclass
4050 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004051 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004052
4053 # Duplicate public and private class member variable
4054 lines =<< trim END
4055 vim9script
4056 class C
4057 public static s: string = "abc"
4058 static _s: string = "def"
4059 endclass
4060 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004061 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004062
4063 # Duplicate class and object member variable
4064 lines =<< trim END
4065 vim9script
4066 class C
4067 static val = 10
4068 this.val = 20
4069 def new()
4070 enddef
4071 endclass
4072 var c = C.new()
4073 assert_equal(10, C.val)
4074 assert_equal(20, c.val)
4075 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004076 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004077
4078 # Duplicate object member variable in a derived class
4079 lines =<< trim END
4080 vim9script
4081 class A
4082 this.val = 10
4083 endclass
4084 class B extends A
4085 endclass
4086 class C extends B
4087 this.val = 20
4088 endclass
4089 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004090 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004091
4092 # Duplicate object private member variable in a derived class
4093 lines =<< trim END
4094 vim9script
4095 class A
4096 this._val = 10
4097 endclass
4098 class B extends A
4099 endclass
4100 class C extends B
4101 this._val = 20
4102 endclass
4103 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004104 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004105
4106 # Duplicate object private member variable in a derived class
4107 lines =<< trim END
4108 vim9script
4109 class A
4110 this.val = 10
4111 endclass
4112 class B extends A
4113 endclass
4114 class C extends B
4115 this._val = 20
4116 endclass
4117 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004118 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004119
4120 # Duplicate object member variable in a derived class
4121 lines =<< trim END
4122 vim9script
4123 class A
4124 this._val = 10
4125 endclass
4126 class B extends A
4127 endclass
4128 class C extends B
4129 this.val = 20
4130 endclass
4131 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004132 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004133
4134 # Two member variables with a common prefix
4135 lines =<< trim END
4136 vim9script
4137 class A
4138 public static svar2: number
4139 public static svar: number
4140 endclass
4141 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004142 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004143enddef
4144
Ernie Rael18143d32023-09-04 22:30:41 +02004145def Test_interface_static_member_access()
4146 # In a class cannot read from interface static
4147 var lines =<< trim END
4148 vim9script
4149 interface I
4150 public static num: number
4151 endinterface
4152 class C implements I
4153 public static num = 3
4154 def F()
4155 var x = I.num
4156 enddef
4157 endclass
4158 C.new().F()
4159 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004160 v9.CheckSourceFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
Ernie Rael18143d32023-09-04 22:30:41 +02004161
4162 # In a class cannot write to interface static
4163 lines =<< trim END
4164 vim9script
4165 interface I
4166 public static num: number
4167 endinterface
4168 class C implements I
4169 public static num = 3
4170 def F()
4171 I.num = 7
4172 enddef
4173 endclass
4174 C.new().F()
4175 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004176 v9.CheckSourceFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
Ernie Rael18143d32023-09-04 22:30:41 +02004177
4178 # In a def cannot read from interface static
4179 lines =<< trim END
4180 vim9script
4181 interface I
4182 public static num: number
4183 endinterface
4184 def F()
4185 var x = I.num
4186 enddef
4187 F()
4188 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004189 v9.CheckSourceFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
Ernie Rael18143d32023-09-04 22:30:41 +02004190
4191 # In a def cannot write to interface static
4192 lines =<< trim END
4193 vim9script
4194 interface I
4195 public static num: number
4196 endinterface
4197 def F()
4198 I.num = 7
4199 enddef
4200 F()
4201 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004202 v9.CheckSourceFailure(lines, 'E1409: Cannot directly access interface "I" static member "num"')
Ernie Rael18143d32023-09-04 22:30:41 +02004203
4204 # script level cannot read interface static
4205 lines =<< trim END
4206 vim9script
4207 interface I
4208 public static s_var1: number
4209 endinterface
4210
4211 var x = I.s_var1
4212 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004213 v9.CheckSourceFailure(lines, 'E1409: Cannot directly access interface "I" static member "s_var1"')
Ernie Rael18143d32023-09-04 22:30:41 +02004214
4215 # script level cannot write interface static
4216 lines =<< trim END
4217 vim9script
4218 interface I
4219 public static s_var1: number
4220 endinterface
4221
4222 I.s_var1 = 3
4223 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004224 v9.CheckSourceFailure(lines, 'E1409: Cannot directly access interface "I" static member "I.s_var1 = 3"')
Ernie Rael18143d32023-09-04 22:30:41 +02004225
4226enddef
4227
4228def Test_static_member_access_outside_class()
4229 # Verify access of statics implemented from interface
4230 # in a :def (outside of a class)
4231 # Note the order of the static is different
4232 # between the interface and the class,
4233 # since they are allocated in order in each interface/class;
4234 # so the static index is mapped from interfaced to class as needed.
4235
4236 # Check reading statics
4237 var lines =<< trim END
4238 vim9script
4239
4240 interface I
4241 public static s_var1: number
4242 public static s_var2: number
4243 endinterface
4244
4245 class C implements I
4246 public static s_var2 = 2
4247 public static x_static = 7
4248 public static s_var1 = 1
4249 endclass
4250
4251 def F1(): number
4252 assert_equal(1, C.s_var1)
4253 assert_equal(2, C.s_var2)
4254 assert_equal(7, C.x_static)
4255 return 11
4256 enddef
4257
Ernie Rael18143d32023-09-04 22:30:41 +02004258 assert_equal(11, F1())
Ernie Rael18143d32023-09-04 22:30:41 +02004259 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004260 v9.CheckSourceSuccess(lines)
Ernie Rael18143d32023-09-04 22:30:41 +02004261enddef
4262
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004263" Test for accessing a private member outside a class in a def function
4264def Test_private_member_access_outside_class()
4265 # private object member variable
4266 var lines =<< trim END
4267 vim9script
4268 class A
4269 this._val = 10
4270 def GetVal(): number
4271 return this._val
4272 enddef
4273 endclass
4274 def T()
4275 var a = A.new()
4276 a._val = 20
4277 enddef
4278 T()
4279 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004280 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004281
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004282 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004283 lines =<< trim END
4284 vim9script
4285 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004286 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004287 endclass
4288 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004289 var a = A.new()
4290 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004291 enddef
4292 T()
4293 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004294 v9.CheckSourceFailure(lines, 'E1089: Unknown variable: _a')
Ernie Rael18143d32023-09-04 22:30:41 +02004295
4296 # private static member variable
4297 lines =<< trim END
4298 vim9script
4299 class A
4300 static _val = 10
4301 endclass
4302 def T()
4303 var a = A.new()
4304 var x = a._val
4305 enddef
4306 T()
4307 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004308 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004309
4310 # private static member variable
4311 lines =<< trim END
4312 vim9script
4313 class A
4314 static _val = 10
4315 endclass
4316 def T()
4317 var a = A.new()
4318 a._val = 3
4319 enddef
4320 T()
4321 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004322 v9.CheckSourceFailure(lines, 'E1374: Class member "_val" accessible only inside class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004323
4324 # private static class variable
4325 lines =<< trim END
4326 vim9script
4327 class A
4328 static _val = 10
4329 endclass
4330 def T()
4331 var x = A._val
4332 enddef
4333 T()
4334 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004335 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004336
4337 # private static class variable
4338 lines =<< trim END
4339 vim9script
4340 class A
4341 static _val = 10
4342 endclass
4343 def T()
4344 A._val = 3
4345 enddef
4346 T()
4347 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004348 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004349enddef
4350
4351" Test for changing the member access of an interface in a implementation class
4352def Test_change_interface_member_access()
4353 var lines =<< trim END
4354 vim9script
4355 interface A
4356 public this.val: number
4357 endinterface
4358 class B implements A
4359 this.val = 10
4360 endclass
4361 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004362 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004363
4364 lines =<< trim END
4365 vim9script
4366 interface A
4367 this.val: number
4368 endinterface
4369 class B implements A
4370 public this.val = 10
4371 endclass
4372 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004373 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004374enddef
4375
4376" Test for trying to change a readonly member from a def function
4377def Test_readonly_member_change_in_def_func()
4378 var lines =<< trim END
4379 vim9script
4380 class A
4381 this.val: number
4382 endclass
4383 def T()
4384 var a = A.new()
4385 a.val = 20
4386 enddef
4387 T()
4388 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004389 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004390enddef
4391
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004392" Test for reading and writing a class member from a def function
4393def Test_modify_class_member_from_def_function()
4394 var lines =<< trim END
4395 vim9script
4396 class A
4397 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004398 public static var2: list<number> = [1, 2]
4399 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004400 static _priv_var4: number = 40
4401 endclass
4402 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004403 assert_equal([1, 2], A.var2)
4404 assert_equal({a: 1, b: 2}, A.var3)
4405 A.var2 = [3, 4]
4406 A.var3 = {c: 3, d: 4}
4407 assert_equal([3, 4], A.var2)
4408 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004409 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4410 enddef
4411 T()
4412 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004413 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004414enddef
4415
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004416" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004417def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004418 var lines =<< trim END
4419 vim9script
4420 class A
4421 public static svar1: list<number> = [1]
4422 public static svar2: list<number> = [2]
4423 endclass
4424
4425 A.svar1->add(3)
4426 A.svar2->add(4)
4427 assert_equal([1, 3], A.svar1)
4428 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004429
4430 def Foo()
4431 A.svar1->add(7)
4432 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004433 assert_equal([1, 3, 7], A.svar1)
4434 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004435 enddef
4436 Foo()
4437 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004438 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004439
4440 # Cannot read from a class variable using an object in script context
4441 lines =<< trim END
4442 vim9script
4443 class A
4444 public this.var1: number
4445 public static svar2: list<number> = [1]
4446 endclass
4447
4448 var a = A.new()
4449 echo a.svar2
4450 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004451 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004452
4453 # Cannot write to a class variable using an object in script context
4454 lines =<< trim END
4455 vim9script
4456 class A
4457 public this.var1: number
4458 public static svar2: list<number> = [1]
4459 endclass
4460
4461 var a = A.new()
4462 a.svar2 = [2]
4463 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004464 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004465
4466 # Cannot read from a class variable using an object in def method context
4467 lines =<< trim END
4468 vim9script
4469 class A
4470 public this.var1: number
4471 public static svar2: list<number> = [1]
4472 endclass
4473
4474 def T()
4475 var a = A.new()
4476 echo a.svar2
4477 enddef
4478 T()
4479 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004480 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004481
4482 # Cannot write to a class variable using an object in def method context
4483 lines =<< trim END
4484 vim9script
4485 class A
4486 public this.var1: number
4487 public static svar2: list<number> = [1]
4488 endclass
4489
4490 def T()
4491 var a = A.new()
4492 a.svar2 = [2]
4493 enddef
4494 T()
4495 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004496 v9.CheckSourceFailure(lines, 'E1374: Class member "svar2" accessible only inside class "A"')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004497enddef
4498
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004499" Test for using a interface method using a child object
4500def Test_interface_method_from_child()
4501 var lines =<< trim END
4502 vim9script
4503
4504 interface A
4505 def Foo(): string
4506 endinterface
4507
4508 class B implements A
4509 def Foo(): string
4510 return 'foo'
4511 enddef
4512 endclass
4513
4514 class C extends B
4515 def Bar(): string
4516 return 'bar'
4517 enddef
4518 endclass
4519
4520 def T1(a: A)
4521 assert_equal('foo', a.Foo())
4522 enddef
4523
4524 def T2(b: B)
4525 assert_equal('foo', b.Foo())
4526 enddef
4527
4528 var c = C.new()
4529 T1(c)
4530 T2(c)
4531 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004532 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004533enddef
4534
4535" Test for using an interface method using a child object when it is overridden
4536" by the child class.
4537" FIXME: This test fails.
4538" def Test_interface_overridden_method_from_child()
4539" var lines =<< trim END
4540" vim9script
4541"
4542" interface A
4543" def Foo(): string
4544" endinterface
4545"
4546" class B implements A
4547" def Foo(): string
4548" return 'b-foo'
4549" enddef
4550" endclass
4551"
4552" class C extends B
4553" def Bar(): string
4554" return 'bar'
4555" enddef
4556" def Foo(): string
4557" return 'c-foo'
4558" enddef
4559" endclass
4560"
4561" def T1(a: A)
4562" assert_equal('c-foo', a.Foo())
4563" enddef
4564"
4565" def T2(b: B)
4566" assert_equal('c-foo', b.Foo())
4567" enddef
4568"
4569" var c = C.new()
4570" T1(c)
4571" T2(c)
4572" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004573" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004574" enddef
4575
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004576" Test for abstract methods
4577def Test_abstract_method()
4578 # Use two abstract methods
4579 var lines =<< trim END
4580 vim9script
4581 abstract class A
4582 def M1(): number
4583 return 10
4584 enddef
4585 abstract def M2(): number
4586 abstract def M3(): number
4587 endclass
4588 class B extends A
4589 def M2(): number
4590 return 20
4591 enddef
4592 def M3(): number
4593 return 30
4594 enddef
4595 endclass
4596 var b = B.new()
4597 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4598 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004599 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004600
4601 # Don't define an abstract method
4602 lines =<< trim END
4603 vim9script
4604 abstract class A
4605 abstract def Foo()
4606 endclass
4607 class B extends A
4608 endclass
4609 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004610 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004611
4612 # Use abstract method in a concrete class
4613 lines =<< trim END
4614 vim9script
4615 class A
4616 abstract def Foo()
4617 endclass
4618 class B extends A
4619 endclass
4620 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004621 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004622
4623 # Use abstract method in an interface
4624 lines =<< trim END
4625 vim9script
4626 interface A
4627 abstract def Foo()
4628 endinterface
4629 class B implements A
4630 endclass
4631 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004632 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004633
4634 # Abbreviate the "abstract" keyword
4635 lines =<< trim END
4636 vim9script
4637 class A
4638 abs def Foo()
4639 endclass
4640 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004641 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004642
4643 # Use "abstract" with a member variable
4644 lines =<< trim END
4645 vim9script
4646 abstract class A
4647 abstract this.val = 10
4648 endclass
4649 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004650 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004651
4652 # Use a static abstract method
4653 lines =<< trim END
4654 vim9script
4655 abstract class A
4656 abstract static def Foo(): number
4657 endclass
4658 class B extends A
4659 static def Foo(): number
4660 return 4
4661 enddef
4662 endclass
4663 assert_equal(4, B.Foo())
4664 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004665 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004666
4667 # Type mismatch between abstract method and concrete method
4668 lines =<< trim END
4669 vim9script
4670 abstract class A
4671 abstract def Foo(a: string, b: number): list<number>
4672 endclass
4673 class B extends A
4674 def Foo(a: number, b: string): list<string>
4675 return []
4676 enddef
4677 endclass
4678 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004679 v9.CheckSourceFailure(lines, 'E1407: Method "Foo": type mismatch, expected func(string, number): list<number> but got func(number, string): list<string>')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004680
4681 # Use an abstract class to invoke an abstract method
4682 # FIXME: This should fail
4683 lines =<< trim END
4684 vim9script
4685 abstract class A
4686 abstract static def Foo()
4687 endclass
4688 A.Foo()
4689 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004690 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004691
4692 # Invoke an abstract method from a def function
4693 lines =<< trim END
4694 vim9script
4695 abstract class A
4696 abstract def Foo(): list<number>
4697 endclass
4698 class B extends A
4699 def Foo(): list<number>
4700 return [3, 5]
4701 enddef
4702 endclass
4703 def Bar(c: B)
4704 assert_equal([3, 5], c.Foo())
4705 enddef
4706 var b = B.new()
4707 Bar(b)
4708 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004709 v9.CheckSourceSuccess(lines)
4710enddef
4711
4712" Test for calling a class method from a subclass
4713def Test_class_method_call_from_subclass()
4714 # class method call from a subclass
4715 var lines =<< trim END
4716 vim9script
4717
4718 class A
4719 static def Foo()
4720 echo "foo"
4721 enddef
4722 endclass
4723
4724 class B extends A
4725 def Bar()
4726 Foo()
4727 enddef
4728 endclass
4729
4730 var b = B.new()
4731 b.Bar()
4732 END
4733 v9.CheckSourceFailure(lines, 'E1374: Class member "Foo" accessible only inside class "A"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004734enddef
4735
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004736" Test for calling a class method using an object in a def function context and
4737" script context.
4738def Test_class_method_call_using_object()
4739 # script context
4740 var lines =<< trim END
4741 vim9script
4742 class A
4743 static def Foo(): list<string>
4744 return ['a', 'b']
4745 enddef
4746 def Bar()
4747 assert_equal(['a', 'b'], A.Foo())
4748 assert_equal(['a', 'b'], Foo())
4749 enddef
4750 endclass
4751
4752 def T()
4753 assert_equal(['a', 'b'], A.Foo())
4754 var t_a = A.new()
4755 t_a.Bar()
4756 enddef
4757
4758 assert_equal(['a', 'b'], A.Foo())
4759 var a = A.new()
4760 a.Bar()
4761 T()
4762 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004763 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004764
4765 # script context
4766 lines =<< trim END
4767 vim9script
4768 class A
4769 static def Foo(): string
4770 return 'foo'
4771 enddef
4772 endclass
4773
4774 var a = A.new()
4775 assert_equal('foo', a.Foo())
4776 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004777 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004778
4779 # def function context
4780 lines =<< trim END
4781 vim9script
4782 class A
4783 static def Foo(): string
4784 return 'foo'
4785 enddef
4786 endclass
4787
4788 def T()
4789 var a = A.new()
4790 assert_equal('foo', a.Foo())
4791 enddef
4792 T()
4793 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004794 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
4795enddef
4796
4797def Test_class_variable()
4798 var lines =<< trim END
4799 vim9script
4800
4801 class A
4802 public static val: number = 10
4803 static def ClassFunc()
4804 assert_equal(10, val)
4805 enddef
4806 def ObjFunc()
4807 assert_equal(10, val)
4808 enddef
4809 endclass
4810
4811 class B extends A
4812 endclass
4813
4814 assert_equal(10, A.val)
4815 A.ClassFunc()
4816 var a = A.new()
4817 a.ObjFunc()
4818 var b = B.new()
4819 b.ObjFunc()
4820
4821 def T1(a1: A)
4822 a1.ObjFunc()
4823 A.ClassFunc()
4824 enddef
4825 T1(b)
4826
4827 A.val = 20
4828 assert_equal(20, A.val)
4829 END
4830 v9.CheckSourceSuccess(lines)
4831
4832 # Modifying a parent class variable from a child class method
4833 lines =<< trim END
4834 vim9script
4835
4836 class A
4837 static val: number = 10
4838 endclass
4839
4840 class B extends A
4841 static def ClassFunc()
4842 val = 20
4843 enddef
4844 endclass
4845 B.ClassFunc()
4846 END
4847 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4848
4849 # Reading a parent class variable from a child class method
4850 lines =<< trim END
4851 vim9script
4852
4853 class A
4854 static val: number = 10
4855 endclass
4856
4857 class B extends A
4858 static def ClassFunc()
4859 var i = val
4860 enddef
4861 endclass
4862 B.ClassFunc()
4863 END
4864 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4865
4866 # Modifying a parent class variable from a child object method
4867 lines =<< trim END
4868 vim9script
4869
4870 class A
4871 static val: number = 10
4872 endclass
4873
4874 class B extends A
4875 def ObjFunc()
4876 val = 20
4877 enddef
4878 endclass
4879 var b = B.new()
4880 b.ObjFunc()
4881 END
4882 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4883
4884 # Reading a parent class variable from a child object method
4885 lines =<< trim END
4886 vim9script
4887
4888 class A
4889 static val: number = 10
4890 endclass
4891
4892 class B extends A
4893 def ObjFunc()
4894 var i = val
4895 enddef
4896 endclass
4897 var b = B.new()
4898 b.ObjFunc()
4899 END
4900 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4901
4902 # Modifying a class variable using an object at script level
4903 lines =<< trim END
4904 vim9script
4905
4906 class A
4907 static val: number = 10
4908 endclass
4909 var a = A.new()
4910 a.val = 20
4911 END
4912 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4913
4914 # Reading a class variable using an object at script level
4915 lines =<< trim END
4916 vim9script
4917
4918 class A
4919 static val: number = 10
4920 endclass
4921 var a = A.new()
4922 var i = a.val
4923 END
4924 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4925
4926 # Modifying a class variable using an object at function level
4927 lines =<< trim END
4928 vim9script
4929
4930 class A
4931 static val: number = 10
4932 endclass
4933
4934 def T()
4935 var a = A.new()
4936 a.val = 20
4937 enddef
4938 T()
4939 END
4940 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4941
4942 # Reading a class variable using an object at function level
4943 lines =<< trim END
4944 vim9script
4945
4946 class A
4947 static val: number = 10
4948 endclass
4949 def T()
4950 var a = A.new()
4951 var i = a.val
4952 enddef
4953 T()
4954 END
4955 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4956enddef
4957
4958" Test for using a duplicate class method and class variable in a child class
4959def Test_dup_class_member()
4960 # duplicate class variable, class method and overridden object method
4961 var lines =<< trim END
4962 vim9script
4963 class A
4964 static sval = 100
4965 static def Check()
4966 assert_equal(100, sval)
4967 enddef
4968 def GetVal(): number
4969 return sval
4970 enddef
4971 endclass
4972
4973 class B extends A
4974 static sval = 200
4975 static def Check()
4976 assert_equal(200, sval)
4977 enddef
4978 def GetVal(): number
4979 return sval
4980 enddef
4981 endclass
4982
4983 def T1(aa: A): number
4984 return aa.GetVal()
4985 enddef
4986
4987 def T2(bb: B): number
4988 return bb.GetVal()
4989 enddef
4990
4991 assert_equal(100, A.sval)
4992 assert_equal(200, B.sval)
4993 var a = A.new()
4994 assert_equal(100, a.GetVal())
4995 var b = B.new()
4996 assert_equal(200, b.GetVal())
4997 assert_equal(200, T1(b))
4998 assert_equal(200, T2(b))
4999 END
5000 v9.CheckSourceSuccess(lines)
5001
5002 # duplicate class variable and class method
5003 lines =<< trim END
5004 vim9script
5005 class A
5006 static sval = 100
5007 static def Check()
5008 assert_equal(100, sval)
5009 enddef
5010 def GetVal(): number
5011 return sval
5012 enddef
5013 endclass
5014
5015 class B extends A
5016 static sval = 200
5017 static def Check()
5018 assert_equal(200, sval)
5019 enddef
5020 endclass
5021
5022 def T1(aa: A): number
5023 return aa.GetVal()
5024 enddef
5025
5026 def T2(bb: B): number
5027 return bb.GetVal()
5028 enddef
5029
5030 assert_equal(100, A.sval)
5031 assert_equal(200, B.sval)
5032 var a = A.new()
5033 assert_equal(100, a.GetVal())
5034 var b = B.new()
5035 assert_equal(100, b.GetVal())
5036 assert_equal(100, T1(b))
5037 assert_equal(100, T2(b))
5038 END
5039 v9.CheckSourceSuccess(lines)
5040enddef
5041
5042" Test for calling an instance method using the class
5043def Test_instance_method_call_using_class()
5044 # Invoke an object method using a class in script context
5045 var lines =<< trim END
5046 vim9script
5047 class A
5048 def Foo()
5049 echo "foo"
5050 enddef
5051 endclass
5052 A.Foo()
5053 END
5054 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
5055
5056 # Invoke an object method using a class in def function context
5057 lines =<< trim END
5058 vim9script
5059 class A
5060 def Foo()
5061 echo "foo"
5062 enddef
5063 endclass
5064 def T()
5065 A.Foo()
5066 enddef
5067 T()
5068 END
5069 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
5070enddef
5071
5072" Test for duplicate class method and instance method
5073def Test_dup_classmethod_objmethod()
5074 # Duplicate instance method
5075 var lines =<< trim END
5076 vim9script
5077 class A
5078 static def Foo()
5079 enddef
5080 def Foo()
5081 enddef
5082 endclass
5083 END
5084 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
5085
5086 # Duplicate private instance method
5087 lines =<< trim END
5088 vim9script
5089 class A
5090 static def Foo()
5091 enddef
5092 def _Foo()
5093 enddef
5094 endclass
5095 END
5096 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5097
5098 # Duplicate class method
5099 lines =<< trim END
5100 vim9script
5101 class A
5102 def Foo()
5103 enddef
5104 static def Foo()
5105 enddef
5106 endclass
5107 END
5108 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
5109
5110 # Duplicate private class method
5111 lines =<< trim END
5112 vim9script
5113 class A
5114 def Foo()
5115 enddef
5116 static def _Foo()
5117 enddef
5118 endclass
5119 END
5120 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5121
5122 # Duplicate private class and object method
5123 lines =<< trim END
5124 vim9script
5125 class A
5126 def _Foo()
5127 enddef
5128 static def _Foo()
5129 enddef
5130 endclass
5131 END
5132 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5133enddef
5134
5135" Test for an instance method access level comparison with parent instance
5136" methods.
5137def Test_instance_method_access_level()
5138 # Private method in subclass
5139 var lines =<< trim END
5140 vim9script
5141 class A
5142 def Foo()
5143 enddef
5144 endclass
5145 class B extends A
5146 endclass
5147 class C extends B
5148 def _Foo()
5149 enddef
5150 endclass
5151 END
5152 v9.CheckSourceFailure(lines, 'E1378: Access level of method "_Foo" is different in class "A"')
5153
5154 # Public method in subclass
5155 lines =<< trim END
5156 vim9script
5157 class A
5158 def _Foo()
5159 enddef
5160 endclass
5161 class B extends A
5162 endclass
5163 class C extends B
5164 def Foo()
5165 enddef
5166 endclass
5167 END
5168 v9.CheckSourceFailure(lines, 'E1378: Access level of method "Foo" is different in class "A"')
5169enddef
5170
5171def Test_extend_empty_class()
5172 var lines =<< trim END
5173 vim9script
5174 class A
5175 endclass
5176 class B extends A
5177 endclass
5178 class C extends B
5179 public static rw_class_var = 1
5180 public this.rw_obj_var = 2
5181 static def ClassMethod(): number
5182 return 3
5183 enddef
5184 def ObjMethod(): number
5185 return 4
5186 enddef
5187 endclass
5188 assert_equal(1, C.rw_class_var)
5189 assert_equal(3, C.ClassMethod())
5190 var c = C.new()
5191 assert_equal(2, c.rw_obj_var)
5192 assert_equal(4, c.ObjMethod())
5193 END
5194 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005195enddef
5196
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005197" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker