blob: f57bf44d04624d72d5ba8f926b030f71355ad5ba [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()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007 # Class supported only in "vim9script"
Bram Moolenaar00b28d62022-12-08 15:32:33 +00008 var lines =<< trim END
9 class NotWorking
10 endclass
11 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020012 v9.CheckSourceFailure(lines, 'E1316:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000013
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020014 # First character in a class name should be capitalized.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000015 lines =<< trim END
16 vim9script
17 class notWorking
18 endclass
19 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020020 v9.CheckSourceFailure(lines, 'E1314:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000021
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020022 # Only alphanumeric characters are supported in a class name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000023 lines =<< trim END
24 vim9script
25 class Not@working
26 endclass
27 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020028 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000029
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020030 # Unsupported keyword (instead of class)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000031 lines =<< trim END
32 vim9script
33 abstract noclass Something
34 endclass
35 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020036 v9.CheckSourceFailure(lines, 'E475:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000037
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020038 # Only the completed word "class" should be recognized
Bram Moolenaar00b28d62022-12-08 15:32:33 +000039 lines =<< trim END
40 vim9script
41 abstract classy Something
42 endclass
43 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020044 v9.CheckSourceFailure(lines, 'E475:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000045
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020046 # The complete "endclass" should be specified.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000047 lines =<< trim END
48 vim9script
49 class Something
50 endcl
51 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020052 v9.CheckSourceFailure(lines, 'E1065:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000053
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020054 # Additional words after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000055 lines =<< trim END
56 vim9script
57 class Something
Bram Moolenaar94722c52023-01-28 19:19:03 +000058 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000059 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020060 v9.CheckSourceFailure(lines, 'E488:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000061
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020062 # Additional commands after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000063 lines =<< trim END
64 vim9script
65 class Something
66 endclass | echo 'done'
67 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020068 v9.CheckSourceFailure(lines, 'E488:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000069
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020070 # Use "this" without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000071 lines =<< trim END
72 vim9script
73 class Something
74 this
75 endclass
76 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020077 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000078
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020079 # Use "this." without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000080 lines =<< trim END
81 vim9script
82 class Something
83 this.
84 endclass
85 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020086 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000087
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020088 # Space between "this" and ".<variable>"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000089 lines =<< trim END
90 vim9script
91 class Something
92 this .count
93 endclass
94 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020095 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000096
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020097 # Space between "this." and the member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000098 lines =<< trim END
99 vim9script
100 class Something
101 this. count
102 endclass
103 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200104 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000105
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200106 # Use "that" instead of "this"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000107 lines =<< trim END
108 vim9script
109 class Something
110 this.count: number
111 that.count
112 endclass
113 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200114 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000115
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200116 # Member variable without a type or initialization
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000117 lines =<< trim END
118 vim9script
119 class Something
120 this.count
121 endclass
122 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200123 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000124
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200125 # Use a non-existing member variable in new()
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000126 lines =<< trim END
127 vim9script
128 class Something
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000129 def new()
130 this.state = 0
131 enddef
132 endclass
133 var obj = Something.new()
134 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200135 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Something": state')
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000136
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200137 # Space before ":" in a member variable declaration
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000138 lines =<< trim END
139 vim9script
140 class Something
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000141 this.count : number
142 endclass
143 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200144 v9.CheckSourceFailure(lines, 'E1059:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000145
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200146 # No space after ":" in a member variable declaration
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000147 lines =<< trim END
148 vim9script
149 class Something
150 this.count:number
151 endclass
152 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200153 v9.CheckSourceFailure(lines, 'E1069:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000154
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200155 # Test for unsupported comment specifier
156 lines =<< trim END
157 vim9script
158 class Something
159 # comment
160 #{
161 endclass
162 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200163 v9.CheckSourceFailure(lines, 'E1170:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200164
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200165 # Test for using class as a bool
166 lines =<< trim END
167 vim9script
168 class A
169 endclass
170 if A
171 endif
172 END
173 v9.CheckSourceFailure(lines, 'E1319: Using a class as a Number')
174
175 # Test for using object as a bool
176 lines =<< trim END
177 vim9script
178 class A
179 endclass
180 var a = A.new()
181 if a
182 endif
183 END
184 v9.CheckSourceFailure(lines, 'E1320: Using an object as a Number')
185
186 # Test for using class as a float
187 lines =<< trim END
188 vim9script
189 class A
190 endclass
191 sort([1.1, A], 'f')
192 END
193 v9.CheckSourceFailure(lines, 'E1321: Using a class as a Float')
194
195 # Test for using object as a float
196 lines =<< trim END
197 vim9script
198 class A
199 endclass
200 var a = A.new()
201 sort([1.1, a], 'f')
202 END
203 v9.CheckSourceFailure(lines, 'E1322: Using an object as a Float')
204
205 # Test for using class as a string
206 lines =<< trim END
207 vim9script
208 class A
209 endclass
210 :exe 'call ' .. A
211 END
212 v9.CheckSourceFailure(lines, 'E1323: Using a class as a String')
213
214 # Test for using object as a string
215 lines =<< trim END
216 vim9script
217 class A
218 endclass
219 var a = A.new()
220 :exe 'call ' .. a
221 END
222 v9.CheckSourceFailure(lines, 'E1324: Using an object as a String')
223
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200224 # Test creating a class with member variables and methods, calling a object
225 # method. Check for using type() and typename() with a class and an object.
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000226 lines =<< trim END
227 vim9script
228
229 class TextPosition
230 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000231 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000232
Bram Moolenaar418b5472022-12-20 13:38:22 +0000233 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000234 def ToString(): string
235 return $'({this.lnum}, {this.col})'
236 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000237 endclass
238
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000239 # use the automatically generated new() method
240 var pos = TextPosition.new(2, 12)
241 assert_equal(2, pos.lnum)
242 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000243
244 # call an object method
245 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000246
247 assert_equal(v:t_class, type(TextPosition))
248 assert_equal(v:t_object, type(pos))
249 assert_equal('class<TextPosition>', typename(TextPosition))
250 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000251 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200252 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200253
254 # When referencing object methods, space cannot be used after a "."
255 lines =<< trim END
256 vim9script
257 class A
258 def Foo(): number
259 return 10
260 enddef
261 endclass
262 var a = A.new()
263 var v = a. Foo()
264 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200265 v9.CheckSourceFailure(lines, 'E1202:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200266
267 # Using an object without specifying a method or a member variable
268 lines =<< trim END
269 vim9script
270 class A
271 def Foo(): number
272 return 10
273 enddef
274 endclass
275 var a = A.new()
276 var v = a.
277 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200278 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200279
280 # Error when parsing the arguments of an object method.
281 lines =<< trim END
282 vim9script
283 class A
284 def Foo()
285 enddef
286 endclass
287 var a = A.new()
288 var v = a.Foo(,)
289 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200290 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200291
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200292 # Use a multi-line initialization for a member variable
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200293 lines =<< trim END
294 vim9script
295 class A
296 this.y = {
297 X: 1
298 }
299 endclass
300 var a = A.new()
301 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200302 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000303enddef
304
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000305def Test_class_defined_twice()
306 # class defined twice should fail
307 var lines =<< trim END
308 vim9script
309 class There
310 endclass
311 class There
312 endclass
313 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200314 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"')
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000315
316 # one class, reload same script twice is OK
317 lines =<< trim END
318 vim9script
319 class There
320 endclass
321 END
322 writefile(lines, 'XclassTwice.vim', 'D')
323 source XclassTwice.vim
324 source XclassTwice.vim
325enddef
326
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000327def Test_returning_null_object()
328 # this was causing an internal error
329 var lines =<< trim END
330 vim9script
331
332 class BufferList
333 def Current(): any
334 return null_object
335 enddef
336 endclass
337
338 var buffers = BufferList.new()
339 echo buffers.Current()
340 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200341 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000342enddef
343
Bram Moolenaard13dd302023-03-11 20:56:35 +0000344def Test_using_null_class()
345 var lines =<< trim END
346 @_ = null_class.member
347 END
348 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
349enddef
350
Bram Moolenaar657aea72023-01-27 13:16:19 +0000351def Test_class_interface_wrong_end()
352 var lines =<< trim END
353 vim9script
354 abstract class SomeName
355 this.member = 'text'
356 endinterface
357 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200358 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000359
360 lines =<< trim END
361 vim9script
362 export interface AnotherName
363 this.member: string
364 endclass
365 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200366 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000367enddef
368
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000369def Test_object_not_set()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200370 # Use an uninitialized object in script context
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000371 var lines =<< trim END
372 vim9script
373
374 class State
375 this.value = 'xyz'
376 endclass
377
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000378 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000379 var db = {'xyz': 789}
380 echo db[state.value]
381 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200382 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000383
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200384 # Use an uninitialized object from a def function
Bram Moolenaar0917e862023-02-18 14:42:44 +0000385 lines =<< trim END
386 vim9script
387
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000388 class Class
389 this.id: string
390 def Method1()
391 echo 'Method1' .. this.id
392 enddef
393 endclass
394
395 var obj: Class
396 def Func()
397 obj.Method1()
398 enddef
399 Func()
400 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200401 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000402
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200403 # Pass an uninitialized object variable to a "new" function and try to call an
404 # object method.
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000405 lines =<< trim END
406 vim9script
407
Bram Moolenaar0917e862023-02-18 14:42:44 +0000408 class Background
409 this.background = 'dark'
410 endclass
411
412 class Colorscheme
413 this._bg: Background
414
415 def GetBackground(): string
416 return this._bg.background
417 enddef
418 endclass
419
420 var bg: Background # UNINITIALIZED
421 echo Colorscheme.new(bg).GetBackground()
422 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200423 v9.CheckSourceFailure(lines, 'E1360:')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000424
425 # TODO: this should not give an error but be handled at runtime
426 lines =<< trim END
427 vim9script
428
429 class Class
430 this.id: string
431 def Method1()
432 echo 'Method1' .. this.id
433 enddef
434 endclass
435
436 var obj = null_object
437 def Func()
438 obj.Method1()
439 enddef
440 Func()
441 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200442 v9.CheckSourceFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000443enddef
444
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200445" Null object assignment and comparison
Ernie Rael5c018be2023-08-27 18:40:26 +0200446def Test_null_object_assign_compare()
447 var lines =<< trim END
448 vim9script
449
450 var nullo = null_object
451 def F(): any
452 return nullo
453 enddef
454 assert_equal('object<Unknown>', typename(F()))
455
456 var o0 = F()
457 assert_true(o0 == null_object)
458 assert_true(o0 == null)
459
460 var o1: any = nullo
461 assert_true(o1 == null_object)
462 assert_true(o1 == null)
463
464 def G()
465 var x = null_object
466 enddef
467
468 class C
469 endclass
470 var o2: C
471 assert_true(o2 == null_object)
472 assert_true(o2 == null)
473
474 o2 = null_object
475 assert_true(o2 == null)
476
477 o2 = C.new()
478 assert_true(o2 != null)
479
480 o2 = null_object
481 assert_true(o2 == null)
482 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200483 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200484enddef
485
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200486" Test for object member initialization and disassembly
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000487def Test_class_member_initializer()
488 var lines =<< trim END
489 vim9script
490
491 class TextPosition
492 this.lnum: number = 1
493 this.col: number = 1
494
Bram Moolenaar418b5472022-12-20 13:38:22 +0000495 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000496 def new(lnum: number)
497 this.lnum = lnum
498 enddef
499 endclass
500
501 var pos = TextPosition.new(3)
502 assert_equal(3, pos.lnum)
503 assert_equal(1, pos.col)
504
505 var instr = execute('disassemble TextPosition.new')
506 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000507 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000508 '\d PUSHNR 1\_s*' ..
509 '\d STORE_THIS 0\_s*' ..
510 '\d PUSHNR 1\_s*' ..
511 '\d STORE_THIS 1\_s*' ..
512 'this.lnum = lnum\_s*' ..
513 '\d LOAD arg\[-1]\_s*' ..
514 '\d PUSHNR 0\_s*' ..
515 '\d LOAD $0\_s*' ..
516 '\d\+ STOREINDEX object\_s*' ..
517 '\d\+ RETURN object.*',
518 instr)
519 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200520 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000521enddef
522
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000523def Test_member_any_used_as_object()
524 var lines =<< trim END
525 vim9script
526
527 class Inner
528 this.value: number = 0
529 endclass
530
531 class Outer
532 this.inner: any
533 endclass
534
535 def F(outer: Outer)
536 outer.inner.value = 1
537 enddef
538
539 var inner_obj = Inner.new(0)
540 var outer_obj = Outer.new(inner_obj)
541 F(outer_obj)
542 assert_equal(1, inner_obj.value)
543 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200544 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000545
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200546 # Try modifying a private variable using an "any" object
547 lines =<< trim END
548 vim9script
549
550 class Inner
551 this._value: string = ''
552 endclass
553
554 class Outer
555 this.inner: any
556 endclass
557
558 def F(outer: Outer)
559 outer.inner._value = 'b'
560 enddef
561
562 var inner_obj = Inner.new('a')
563 var outer_obj = Outer.new(inner_obj)
564 F(outer_obj)
565 END
566 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _value')
567
568 # Try modifying a non-existing variable using an "any" object
569 lines =<< trim END
570 vim9script
571
572 class Inner
573 this.value: string = ''
574 endclass
575
576 class Outer
577 this.inner: any
578 endclass
579
580 def F(outer: Outer)
581 outer.inner.someval = 'b'
582 enddef
583
584 var inner_obj = Inner.new('a')
585 var outer_obj = Outer.new(inner_obj)
586 F(outer_obj)
587 END
588 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Inner": someval')
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000589enddef
590
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200591" Nested assignment to a object variable which is of another class type
592def Test_assignment_nested_type()
593 var lines =<< trim END
594 vim9script
595
596 class Inner
597 public this.value: number = 0
598 endclass
599
600 class Outer
601 this.inner: Inner
602 endclass
603
604 def F(outer: Outer)
605 outer.inner.value = 1
606 enddef
607
608 def Test_assign_to_nested_typed_member()
609 var inner = Inner.new(0)
610 var outer = Outer.new(inner)
611 F(outer)
612 assert_equal(1, inner.value)
613 enddef
614
615 Test_assign_to_nested_typed_member()
Ernie Rael98e68c02023-09-20 20:13:06 +0200616
617 var script_inner = Inner.new(0)
618 var script_outer = Outer.new(script_inner)
619 script_outer.inner.value = 1
620 assert_equal(1, script_inner.value)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200621 END
622 v9.CheckSourceSuccess(lines)
Ernie Rael98e68c02023-09-20 20:13:06 +0200623
624 # Assignment where target item is read only in :def
625 lines =<< trim END
626 vim9script
627
628 class Inner
629 this.value: number = 0
630 endclass
631
632 class Outer
633 this.inner: Inner
634 endclass
635
636 def F(outer: Outer)
637 outer.inner.value = 1
638 enddef
639
640 def Test_assign_to_nested_typed_member()
641 var inner = Inner.new(0)
642 var outer = Outer.new(inner)
643 F(outer)
644 assert_equal(1, inner.value)
645 enddef
646
647 Test_assign_to_nested_typed_member()
648 END
649 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "value"')
650
651 # Assignment where target item is read only script level
652 lines =<< trim END
653 vim9script
654
655 class Inner
656 this.value: number = 0
657 endclass
658
659 class Outer
660 this.inner: Inner
661 endclass
662
663 def F(outer: Outer)
664 outer.inner.value = 1
665 enddef
666
667 var script_inner = Inner.new(0)
668 var script_outer = Outer.new(script_inner)
669 script_outer.inner.value = 1
670 assert_equal(1, script_inner.value)
671 END
672 v9.CheckSourceFailure(lines, 'E1335: Member is not writable: value')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200673enddef
674
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000675def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200676 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000677 var lines =<< trim END
678 vim9script
679
680 class Foo
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200681 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000682
683 def Add(n: number)
684 this.x += n
685 enddef
686 endclass
687
688 var f = Foo.new(3)
689 f.Add(17)
690 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100691
692 def AddToFoo(obj: Foo)
693 obj.x += 3
694 enddef
695
696 AddToFoo(f)
697 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000698 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200699 v9.CheckSourceSuccess(lines)
Ernie Rael18143d32023-09-04 22:30:41 +0200700
701 # do the same thing, but through an interface
702 lines =<< trim END
703 vim9script
704
705 interface I
706 public this.x: number
707 endinterface
708
709 class Foo implements I
710 public this.x: number
711
712 def Add(n: number)
713 var i: I = this
714 i.x += n
715 enddef
716 endclass
717
718 var f = Foo.new(3)
719 f.Add(17)
720 assert_equal(20, f.x)
721
722 def AddToFoo(i: I)
723 i.x += 3
724 enddef
725
726 AddToFoo(f)
727 assert_equal(23, f.x)
728 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200729 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000730enddef
731
Bram Moolenaarf4508042023-01-15 16:54:57 +0000732def Test_list_of_objects()
733 var lines =<< trim END
734 vim9script
735
736 class Foo
737 def Add()
738 enddef
739 endclass
740
741 def ProcessList(fooList: list<Foo>)
742 for foo in fooList
743 foo.Add()
744 endfor
745 enddef
746
747 var l: list<Foo> = [Foo.new()]
748 ProcessList(l)
749 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200750 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000751enddef
752
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000753def Test_expr_after_using_object()
754 var lines =<< trim END
755 vim9script
756
757 class Something
758 this.label: string = ''
759 endclass
760
761 def Foo(): Something
762 var v = Something.new()
763 echo 'in Foo(): ' .. typename(v)
764 return v
765 enddef
766
767 Foo()
768 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200769 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000770enddef
771
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000772def Test_class_default_new()
773 var lines =<< trim END
774 vim9script
775
776 class TextPosition
777 this.lnum: number = 1
778 this.col: number = 1
779 endclass
780
781 var pos = TextPosition.new()
782 assert_equal(1, pos.lnum)
783 assert_equal(1, pos.col)
784
785 pos = TextPosition.new(v:none, v:none)
786 assert_equal(1, pos.lnum)
787 assert_equal(1, pos.col)
788
789 pos = TextPosition.new(3, 22)
790 assert_equal(3, pos.lnum)
791 assert_equal(22, pos.col)
792
793 pos = TextPosition.new(v:none, 33)
794 assert_equal(1, pos.lnum)
795 assert_equal(33, pos.col)
796 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200797 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000798
799 lines =<< trim END
800 vim9script
801 class Person
802 this.name: string
803 this.age: number = 42
804 this.education: string = "unknown"
805
806 def new(this.name, this.age = v:none, this.education = v:none)
807 enddef
808 endclass
809
810 var piet = Person.new("Piet")
811 assert_equal("Piet", piet.name)
812 assert_equal(42, piet.age)
813 assert_equal("unknown", piet.education)
814
815 var chris = Person.new("Chris", 4, "none")
816 assert_equal("Chris", chris.name)
817 assert_equal(4, chris.age)
818 assert_equal("none", chris.education)
819 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200820 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000821
822 lines =<< trim END
823 vim9script
824 class Person
825 this.name: string
826 this.age: number = 42
827 this.education: string = "unknown"
828
829 def new(this.name, this.age = v:none, this.education = v:none)
830 enddef
831 endclass
832
833 var missing = Person.new()
834 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200835 v9.CheckSourceFailure(lines, 'E119:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200836
837 # Using a specific value to initialize an instance variable in the new()
838 # method.
839 lines =<< trim END
840 vim9script
841 class A
842 this.val: string
843 def new(this.val = 'a')
844 enddef
845 endclass
846 END
847 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'")
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000848enddef
849
h-east2261c892023-08-16 21:49:54 +0900850def Test_class_new_with_object_member()
851 var lines =<< trim END
852 vim9script
853
854 class C
855 this.str: string
856 this.num: number
857 def new(this.str, this.num)
858 enddef
859 def newVals(this.str, this.num)
860 enddef
861 endclass
862
863 def Check()
864 try
865 var c = C.new('cats', 2)
866 assert_equal('cats', c.str)
867 assert_equal(2, c.num)
868
869 c = C.newVals('dogs', 4)
870 assert_equal('dogs', c.str)
871 assert_equal(4, c.num)
872 catch
873 assert_report($'Unexpected exception was caught: {v:exception}')
874 endtry
875 enddef
876
877 Check()
878 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200879 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900880
881 lines =<< trim END
882 vim9script
883
884 class C
885 this.str: string
886 this.num: number
887 def new(this.str, this.num)
888 enddef
889 endclass
890
891 def Check()
892 try
893 var c = C.new(1, 2)
894 catch
895 assert_report($'Unexpected exception was caught: {v:exception}')
896 endtry
897 enddef
898
899 Check()
900 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200901 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900902
903 lines =<< trim END
904 vim9script
905
906 class C
907 this.str: string
908 this.num: number
909 def newVals(this.str, this.num)
910 enddef
911 endclass
912
913 def Check()
914 try
915 var c = C.newVals('dogs', 'apes')
916 catch
917 assert_report($'Unexpected exception was caught: {v:exception}')
918 endtry
919 enddef
920
921 Check()
922 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200923 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900924enddef
925
Bram Moolenaar74e12742022-12-13 21:14:28 +0000926def Test_class_object_member_inits()
927 var lines =<< trim END
928 vim9script
929 class TextPosition
930 this.lnum: number
931 this.col = 1
932 this.addcol: number = 2
933 endclass
934
935 var pos = TextPosition.new()
936 assert_equal(0, pos.lnum)
937 assert_equal(1, pos.col)
938 assert_equal(2, pos.addcol)
939 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200940 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000941
942 lines =<< trim END
943 vim9script
944 class TextPosition
945 this.lnum
946 this.col = 1
947 endclass
948 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200949 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000950
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200951 # If the type is not specified for a member, then it should be set during
952 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000953 lines =<< trim END
954 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200955
956 var init_count = 0
957 def Init(): string
958 init_count += 1
959 return 'foo'
960 enddef
961
962 class A
963 this.str1 = Init()
964 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000965 this.col = 1
966 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200967
968 assert_equal(init_count, 0)
969 var a = A.new()
970 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000971 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200972 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200973
974 # Test for initializing an object member with an unknown variable/type
975 lines =<< trim END
976 vim9script
977 class A
978 this.value = init_val
979 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200980 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200981 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200982 v9.CheckSourceFailure(lines, 'E1001:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200983
984 # Test for initializing an object member with an special type
985 lines =<< trim END
986 vim9script
987 class A
988 this.value: void
989 endclass
990 END
991 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object member: void')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000992enddef
993
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200994" Test for instance variable access
995def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000996 var lines =<< trim END
997 vim9script
998 class Triple
999 this._one = 1
1000 this.two = 2
1001 public this.three = 3
1002
1003 def GetOne(): number
1004 return this._one
1005 enddef
1006 endclass
1007
1008 var trip = Triple.new()
1009 assert_equal(1, trip.GetOne())
1010 assert_equal(2, trip.two)
1011 assert_equal(3, trip.three)
1012 assert_fails('echo trip._one', 'E1333')
1013
1014 assert_fails('trip._one = 11', 'E1333')
1015 assert_fails('trip.two = 22', 'E1335')
1016 trip.three = 33
1017 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001018
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001019 assert_fails('trip.four = 4', 'E1326')
Bram Moolenaard505d172022-12-18 21:42:55 +00001020 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001021 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001022
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001023 # Test for a public member variable name beginning with an underscore
1024 lines =<< trim END
1025 vim9script
1026 class A
1027 public this._val = 10
1028 endclass
1029 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001030 v9.CheckSourceFailure(lines, 'E1332:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001031
Bram Moolenaar590162c2022-12-24 21:24:06 +00001032 lines =<< trim END
1033 vim9script
1034
1035 class MyCar
1036 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +00001037 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001038
1039 def new(make_arg: string)
1040 this.make = make_arg
1041 enddef
1042
1043 def GetMake(): string
1044 return $"make = {this.make}"
1045 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +00001046 def GetAge(): number
1047 return this.age
1048 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +00001049 endclass
1050
1051 var c = MyCar.new("abc")
1052 assert_equal('make = abc', c.GetMake())
1053
1054 c = MyCar.new("def")
1055 assert_equal('make = def', c.GetMake())
1056
1057 var c2 = MyCar.new("123")
1058 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +00001059
1060 def CheckCar()
1061 assert_equal("make = def", c.GetMake())
1062 assert_equal(5, c.GetAge())
1063 enddef
1064 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001065 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001066 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001067
1068 lines =<< trim END
1069 vim9script
1070
1071 class MyCar
1072 this.make: string
1073
1074 def new(make_arg: string)
1075 this.make = make_arg
1076 enddef
1077 endclass
1078
1079 var c = MyCar.new("abc")
1080 var c = MyCar.new("def")
1081 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001082 v9.CheckSourceFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +00001083
1084 lines =<< trim END
1085 vim9script
1086
1087 class Foo
1088 this.x: list<number> = []
1089
1090 def Add(n: number): any
1091 this.x->add(n)
1092 return this
1093 enddef
1094 endclass
1095
1096 echo Foo.new().Add(1).Add(2).x
1097 echo Foo.new().Add(1).Add(2)
1098 .x
1099 echo Foo.new().Add(1)
1100 .Add(2).x
1101 echo Foo.new()
1102 .Add(1).Add(2).x
1103 echo Foo.new()
1104 .Add(1)
1105 .Add(2)
1106 .x
1107 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001108 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001109
1110 # Test for "public" cannot be abbreviated
1111 lines =<< trim END
1112 vim9script
1113 class Something
1114 pub this.val = 1
1115 endclass
1116 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001117 v9.CheckSourceFailure(lines, 'E1065:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001118
1119 # Test for "public" keyword must be followed by "this" or "static".
1120 lines =<< trim END
1121 vim9script
1122 class Something
1123 public val = 1
1124 endclass
1125 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001126 v9.CheckSourceFailure(lines, 'E1331:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001127
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001128 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001129 lines =<< trim END
1130 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001131 class A
1132 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001133 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001134 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001135 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001136 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001137
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001138 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001139 lines =<< trim END
1140 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001141 class A
1142 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001143 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001144 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001145 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001146 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1147
1148 # Modify a instance variable using the class name in a def function
1149 lines =<< trim END
1150 vim9script
1151 class A
1152 public this.val = 1
1153 endclass
1154 def T()
1155 A.val = 1
1156 enddef
1157 T()
1158 END
1159 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1160
1161 # Read a instance variable using the class name in a def function
1162 lines =<< trim END
1163 vim9script
1164 class A
1165 public this.val = 1
1166 endclass
1167 def T()
1168 var i = A.val
1169 enddef
1170 T()
1171 END
1172 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Ernie Raelcf138d42023-09-06 20:45:03 +02001173
1174 # Access from child class extending a class:
1175 lines =<< trim END
1176 vim9script
1177 class A
1178 this.ro_obj_var = 10
1179 public this.rw_obj_var = 20
1180 this._priv_obj_var = 30
Ernie Raelcf138d42023-09-06 20:45:03 +02001181 endclass
1182
1183 class B extends A
1184 def Foo()
1185 var x: number
1186 x = this.ro_obj_var
1187 this.ro_obj_var = 0
1188 x = this.rw_obj_var
1189 this.rw_obj_var = 0
1190 x = this._priv_obj_var
1191 this._priv_obj_var = 0
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001192 enddef
1193 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001194
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001195 var b = B.new()
1196 b.Foo()
1197 END
1198 v9.CheckSourceSuccess(lines)
1199enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001201" Test for class variable access
1202def Test_class_variable_access()
1203 # Test for "static" cannot be abbreviated
1204 var lines =<< trim END
1205 vim9script
1206 class Something
1207 stat this.val = 1
1208 endclass
1209 END
1210 v9.CheckSourceFailure(lines, 'E1065:')
1211
1212 # Test for "static" cannot be followed by "this".
1213 lines =<< trim END
1214 vim9script
1215 class Something
1216 static this.val = 1
1217 endclass
1218 END
1219 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
1220
1221 # Test for "static" cannot be followed by "public".
1222 lines =<< trim END
1223 vim9script
1224 class Something
1225 static public val = 1
1226 endclass
1227 END
1228 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
1229
1230 # A readonly class variable cannot be modified from a child class
1231 lines =<< trim END
1232 vim9script
1233 class A
1234 static ro_class_var = 40
1235 endclass
1236
1237 class B extends A
1238 def Foo()
1239 A.ro_class_var = 50
1240 enddef
1241 endclass
1242
1243 var b = B.new()
1244 b.Foo()
1245 END
1246 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "ro_class_var"')
1247
1248 # A private class variable cannot be accessed from a child class
1249 lines =<< trim END
1250 vim9script
1251 class A
1252 static _priv_class_var = 60
1253 endclass
1254
1255 class B extends A
1256 def Foo()
1257 var i = A._priv_class_var
1258 enddef
1259 endclass
1260
1261 var b = B.new()
1262 b.Foo()
1263 END
1264 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1265
1266 # A private class variable cannot be modified from a child class
1267 lines =<< trim END
1268 vim9script
1269 class A
1270 static _priv_class_var = 60
1271 endclass
1272
1273 class B extends A
1274 def Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001275 A._priv_class_var = 0
1276 enddef
1277 endclass
1278
1279 var b = B.new()
1280 b.Foo()
1281 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001282 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1283
1284 # Access from child class extending a class and from script context
1285 lines =<< trim END
1286 vim9script
1287 class A
1288 static ro_class_var = 10
1289 public static rw_class_var = 20
1290 static _priv_class_var = 30
1291 endclass
1292
1293 class B extends A
1294 def Foo()
1295 var x: number
1296 x = A.ro_class_var
1297 assert_equal(10, x)
1298 x = A.rw_class_var
1299 assert_equal(25, x)
1300 A.rw_class_var = 20
1301 assert_equal(20, A.rw_class_var)
1302 enddef
1303 endclass
1304
1305 assert_equal(10, A.ro_class_var)
1306 assert_equal(20, A.rw_class_var)
1307 A.rw_class_var = 25
1308 assert_equal(25, A.rw_class_var)
1309 var b = B.new()
1310 b.Foo()
1311 END
1312 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001313enddef
1314
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001315def Test_class_object_compare()
1316 var class_lines =<< trim END
1317 vim9script
1318 class Item
1319 this.nr = 0
1320 this.name = 'xx'
1321 endclass
1322 END
1323
1324 # used at the script level and in a compiled function
1325 var test_lines =<< trim END
1326 var i1 = Item.new()
1327 assert_equal(i1, i1)
1328 assert_true(i1 is i1)
1329 var i2 = Item.new()
1330 assert_equal(i1, i2)
1331 assert_false(i1 is i2)
1332 var i3 = Item.new(0, 'xx')
1333 assert_equal(i1, i3)
1334
1335 var io1 = Item.new(1, 'xx')
1336 assert_notequal(i1, io1)
1337 var io2 = Item.new(0, 'yy')
1338 assert_notequal(i1, io2)
1339 END
1340
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001341 v9.CheckSourceSuccess(class_lines + test_lines)
1342 v9.CheckSourceSuccess(
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001343 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001344
1345 for op in ['>', '>=', '<', '<=', '=~', '!~']
1346 var op_lines = [
1347 'var i1 = Item.new()',
1348 'var i2 = Item.new()',
1349 'echo i1 ' .. op .. ' i2',
1350 ]
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001351 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
1352 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001353 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001354 endfor
1355enddef
1356
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001357def Test_object_type()
1358 var lines =<< trim END
1359 vim9script
1360
1361 class One
1362 this.one = 1
1363 endclass
1364 class Two
1365 this.two = 2
1366 endclass
1367 class TwoMore extends Two
1368 this.more = 9
1369 endclass
1370
1371 var o: One = One.new()
1372 var t: Two = Two.new()
1373 var m: TwoMore = TwoMore.new()
1374 var tm: Two = TwoMore.new()
1375
1376 t = m
1377 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001378 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001379
1380 lines =<< trim END
1381 vim9script
1382
1383 class One
1384 this.one = 1
1385 endclass
1386 class Two
1387 this.two = 2
1388 endclass
1389
1390 var o: One = Two.new()
1391 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001392 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001393
1394 lines =<< trim END
1395 vim9script
1396
1397 interface One
1398 def GetMember(): number
1399 endinterface
1400 class Two implements One
1401 this.one = 1
1402 def GetMember(): number
1403 return this.one
1404 enddef
1405 endclass
1406
1407 var o: One = Two.new(5)
1408 assert_equal(5, o.GetMember())
1409 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001410 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001411
1412 lines =<< trim END
1413 vim9script
1414
1415 class Num
1416 this.n: number = 0
1417 endclass
1418
1419 def Ref(name: string): func(Num): Num
1420 return (arg: Num): Num => {
1421 return eval(name)(arg)
1422 }
1423 enddef
1424
1425 const Fn = Ref('Double')
1426 var Double = (m: Num): Num => Num.new(m.n * 2)
1427
1428 echo Fn(Num.new(4))
1429 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001430 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001431enddef
1432
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001433def Test_class_member()
1434 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001435 var lines =<< trim END
1436 vim9script
1437 class TextPos
1438 this.lnum = 1
1439 this.col = 1
1440 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001441 static _secret = 7
1442 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001443
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001444 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001445 counter += nr
1446 enddef
1447 endclass
1448
1449 assert_equal(0, TextPos.counter)
1450 TextPos.AddToCounter(3)
1451 assert_equal(3, TextPos.counter)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001452 assert_fails('echo TextPos.noSuchMember', 'E1337:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001453
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001454 def GetCounter(): number
1455 return TextPos.counter
1456 enddef
1457 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001458
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001459 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001460 assert_fails('TextPos.counter = 5', 'E1335:')
1461 assert_fails('TextPos.counter += 5', 'E1335:')
1462
1463 assert_fails('echo TextPos._secret', 'E1333:')
1464 assert_fails('TextPos._secret = 8', 'E1333:')
1465
1466 assert_equal(42, TextPos.anybody)
1467 TextPos.anybody = 12
1468 assert_equal(12, TextPos.anybody)
1469 TextPos.anybody += 5
1470 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001471 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001472 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001473
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001474 # example in the help
1475 lines =<< trim END
1476 vim9script
1477 class OtherThing
1478 this.size: number
1479 static totalSize: number
1480
1481 def new(this.size)
1482 totalSize += this.size
1483 enddef
1484 endclass
1485 assert_equal(0, OtherThing.totalSize)
1486 var to3 = OtherThing.new(3)
1487 assert_equal(3, OtherThing.totalSize)
1488 var to7 = OtherThing.new(7)
1489 assert_equal(10, OtherThing.totalSize)
1490 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001491 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001492
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001493 # using static class member twice
1494 lines =<< trim END
1495 vim9script
1496
1497 class HTML
1498 static author: string = 'John Doe'
1499
1500 static def MacroSubstitute(s: string): string
1501 return substitute(s, '{{author}}', author, 'gi')
1502 enddef
1503 endclass
1504
1505 assert_equal('some text', HTML.MacroSubstitute('some text'))
1506 assert_equal('some text', HTML.MacroSubstitute('some text'))
1507 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001508 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001509
Bram Moolenaar62a69232023-01-24 15:07:04 +00001510 # access private member in lambda
1511 lines =<< trim END
1512 vim9script
1513
1514 class Foo
1515 this._x: number = 0
1516
1517 def Add(n: number): number
1518 const F = (): number => this._x + n
1519 return F()
1520 enddef
1521 endclass
1522
1523 var foo = Foo.new()
1524 assert_equal(5, foo.Add(5))
1525 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001526 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001527
h-east2bd6a092023-05-19 19:01:17 +01001528 # access private member in lambda body
1529 lines =<< trim END
1530 vim9script
1531
1532 class Foo
1533 this._x: number = 6
1534
1535 def Add(n: number): number
1536 var Lam = () => {
1537 this._x = this._x + n
1538 }
1539 Lam()
1540 return this._x
1541 enddef
1542 endclass
1543
1544 var foo = Foo.new()
1545 assert_equal(13, foo.Add(7))
1546 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001547 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001548
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001549 # check shadowing
1550 lines =<< trim END
1551 vim9script
1552
1553 class Some
1554 static count = 0
1555 def Method(count: number)
1556 echo count
1557 enddef
1558 endclass
1559
1560 var s = Some.new()
1561 s.Method(7)
1562 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001563 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001564
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001565 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001566 lines =<< trim END
1567 vim9script
1568
1569 class Some
1570 static count = 0
1571 def Method(arg: number)
1572 var count = 3
1573 echo arg count
1574 enddef
1575 endclass
1576
1577 var s = Some.new()
1578 s.Method(7)
1579 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001580 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001581
1582 # Test for using an invalid type for a member variable
1583 lines =<< trim END
1584 vim9script
1585 class A
1586 this.val: xxx
1587 endclass
1588 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001589 v9.CheckSourceFailure(lines, 'E1010:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001590
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001591 # Test for setting a member on a null object
1592 lines =<< trim END
1593 vim9script
1594 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001595 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001596 endclass
1597
1598 def F()
1599 var obj: A
1600 obj.val = ""
1601 enddef
1602 F()
1603 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001604 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001605
1606 # Test for accessing a member on a null object
1607 lines =<< trim END
1608 vim9script
1609 class A
1610 this.val: string
1611 endclass
1612
1613 def F()
1614 var obj: A
1615 echo obj.val
1616 enddef
1617 F()
1618 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001619 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001620
1621 # Test for setting a member on a null object, at script level
1622 lines =<< trim END
1623 vim9script
1624 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001625 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001626 endclass
1627
1628 var obj: A
1629 obj.val = ""
1630 END
1631 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001632 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001633
1634 # Test for accessing a member on a null object, at script level
1635 lines =<< trim END
1636 vim9script
1637 class A
1638 this.val: string
1639 endclass
1640
1641 var obj: A
1642 echo obj.val
1643 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001644 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001645
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001646 # Test for no space before or after the '=' when initializing a member
1647 # variable
1648 lines =<< trim END
1649 vim9script
1650 class A
1651 this.val: number= 10
1652 endclass
1653 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001654 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001655 lines =<< trim END
1656 vim9script
1657 class A
1658 this.val: number =10
1659 endclass
1660 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001661 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001662
1663 # Access a non-existing member
1664 lines =<< trim END
1665 vim9script
1666 class A
1667 endclass
1668 var a = A.new()
1669 var v = a.bar
1670 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001671 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": bar')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001672enddef
1673
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001674func Test_class_garbagecollect()
1675 let lines =<< trim END
1676 vim9script
1677
1678 class Point
1679 this.p = [2, 3]
1680 static pl = ['a', 'b']
1681 static pd = {a: 'a', b: 'b'}
1682 endclass
1683
1684 echo Point.pl Point.pd
1685 call test_garbagecollect_now()
1686 echo Point.pl Point.pd
1687 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001688 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001689
1690 let lines =<< trim END
1691 vim9script
1692
1693 interface View
1694 endinterface
1695
1696 class Widget
1697 this.view: View
1698 endclass
1699
1700 class MyView implements View
1701 this.widget: Widget
1702
1703 def new()
1704 # this will result in a circular reference to this object
1705 this.widget = Widget.new(this)
1706 enddef
1707 endclass
1708
1709 var view = MyView.new()
1710
1711 # overwrite "view", will be garbage-collected next
1712 view = MyView.new()
1713 test_garbagecollect_now()
1714 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001715 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001716endfunc
1717
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001718" Test interface garbage collection
1719func Test_interface_garbagecollect()
1720 let lines =<< trim END
1721 vim9script
1722
1723 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001724 this.ro_obj_var: number
1725 public this.rw_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001726
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001727 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001728 endinterface
1729
1730 class A implements I
1731 static ro_class_var: number = 10
1732 public static rw_class_var: number = 20
1733 static _priv_class_var: number = 30
1734 this.ro_obj_var: number = 40
1735 public this.rw_obj_var: number = 50
1736 this._priv_obj_var: number = 60
1737
1738 static def _ClassBar(): number
1739 return _priv_class_var
1740 enddef
1741
1742 static def ClassFoo(): number
1743 return ro_class_var + rw_class_var + A._ClassBar()
1744 enddef
1745
1746 def _ObjBar(): number
1747 return this._priv_obj_var
1748 enddef
1749
1750 def ObjFoo(): number
1751 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1752 enddef
1753 endclass
1754
1755 assert_equal(60, A.ClassFoo())
1756 var o = A.new()
1757 assert_equal(150, o.ObjFoo())
1758 test_garbagecollect_now()
1759 assert_equal(60, A.ClassFoo())
1760 assert_equal(150, o.ObjFoo())
1761 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001762 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001763endfunc
1764
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001765def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001766 var lines =<< trim END
1767 vim9script
1768 class Value
1769 this.value = 0
1770 static objects = 0
1771
1772 def new(v: number)
1773 this.value = v
1774 ++objects
1775 enddef
1776
1777 static def GetCount(): number
1778 return objects
1779 enddef
1780 endclass
1781
1782 assert_equal(0, Value.GetCount())
1783 var v1 = Value.new(2)
1784 assert_equal(1, Value.GetCount())
1785 var v2 = Value.new(7)
1786 assert_equal(2, Value.GetCount())
1787 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001788 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001789
1790 # Test for cleaning up after a class definition failure when using class
1791 # functions.
1792 lines =<< trim END
1793 vim9script
1794 class A
1795 static def Foo()
1796 enddef
1797 aaa
1798 endclass
1799 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001800 v9.CheckSourceFailure(lines, 'E1318:')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001801
1802 # Test for calling a class method from another class method without the class
1803 # name prefix.
1804 lines =<< trim END
1805 vim9script
1806 class A
1807 static myList: list<number> = [1]
1808 static def Foo(n: number)
1809 myList->add(n)
1810 enddef
1811 static def Bar()
1812 Foo(2)
1813 enddef
1814 def Baz()
1815 Foo(3)
1816 enddef
1817 endclass
1818 A.Bar()
1819 var a = A.new()
1820 a.Baz()
1821 assert_equal([1, 2, 3], A.myList)
1822 END
1823 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001824enddef
1825
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001826def Test_class_defcompile()
1827 var lines =<< trim END
1828 vim9script
1829
1830 class C
1831 def Fo(i: number): string
1832 return i
1833 enddef
1834 endclass
1835
1836 defcompile C.Fo
1837 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001838 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001839
1840 lines =<< trim END
1841 vim9script
1842
1843 class C
1844 static def Fc(): number
1845 return 'x'
1846 enddef
1847 endclass
1848
1849 defcompile C.Fc
1850 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001851 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001852
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001853 lines =<< trim END
1854 vim9script
1855
1856 class C
1857 static def new()
1858 enddef
1859 endclass
1860
1861 defcompile C.new
1862 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001863 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" function as static')
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001864
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001865 # Trying to compile a function using a non-existing class variable
1866 lines =<< trim END
1867 vim9script
1868 defcompile x.Foo()
1869 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001870 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001871
1872 # Trying to compile a function using a variable which is not a class
1873 lines =<< trim END
1874 vim9script
1875 var x: number
1876 defcompile x.Foo()
1877 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001878 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001879
1880 # Trying to compile a function without specifying the name
1881 lines =<< trim END
1882 vim9script
1883 class A
1884 endclass
1885 defcompile A.
1886 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001887 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001888
1889 # Trying to compile a non-existing class object member function
1890 lines =<< trim END
1891 vim9script
1892 class A
1893 endclass
1894 var a = A.new()
1895 defcompile a.Foo()
1896 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001897 v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001898enddef
1899
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001900def Test_class_object_to_string()
1901 var lines =<< trim END
1902 vim9script
1903 class TextPosition
1904 this.lnum = 1
1905 this.col = 22
1906 endclass
1907
1908 assert_equal("class TextPosition", string(TextPosition))
1909
1910 var pos = TextPosition.new()
1911 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1912 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001913 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001914enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001915
Bram Moolenaar554d0312023-01-05 19:59:18 +00001916def Test_interface_basics()
1917 var lines =<< trim END
1918 vim9script
1919 interface Something
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001920 this.ro_var: string
1921 public this.rw_var: list<number>
Bram Moolenaar554d0312023-01-05 19:59:18 +00001922 def GetCount(): number
1923 endinterface
1924 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001925 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001926
1927 lines =<< trim END
1928 interface SomethingWrong
1929 static count = 7
1930 endinterface
1931 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001932 v9.CheckSourceFailure(lines, 'E1342:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001933
1934 lines =<< trim END
1935 vim9script
1936
1937 interface Some
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001938 this.value: number
1939 def Method(value: number)
1940 endinterface
1941 END
h-east61378a12023-04-18 19:07:29 +01001942 # The argument name and the object member name are the same, but this is not a
1943 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001944 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001945
1946 lines =<< trim END
1947 vim9script
1948 interface somethingWrong
1949 static count = 7
1950 endinterface
1951 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001952 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001953
1954 lines =<< trim END
1955 vim9script
1956 interface SomethingWrong
1957 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001958 this.count = 7
Bram Moolenaar554d0312023-01-05 19:59:18 +00001959 def GetCount(): number
1960 endinterface
1961 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001962 v9.CheckSourceFailure(lines, 'E1344:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001963
1964 lines =<< trim END
1965 vim9script
1966 interface SomethingWrong
1967 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001968 this.count: number
Bram Moolenaar554d0312023-01-05 19:59:18 +00001969 def GetCount(): number
1970 return 5
1971 enddef
1972 endinterface
1973 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001974 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001975
1976 lines =<< trim END
1977 vim9script
1978 export interface EnterExit
1979 def Enter(): void
1980 def Exit(): void
1981 endinterface
1982 END
1983 writefile(lines, 'XdefIntf.vim', 'D')
1984
1985 lines =<< trim END
1986 vim9script
1987 import './XdefIntf.vim' as defIntf
1988 export def With(ee: defIntf.EnterExit, F: func)
1989 ee.Enter()
1990 try
1991 F()
1992 finally
1993 ee.Exit()
1994 endtry
1995 enddef
1996 END
1997 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001998
1999 var imported =<< trim END
2000 vim9script
2001 export abstract class EnterExit
2002 def Enter(): void
2003 enddef
2004 def Exit(): void
2005 enddef
2006 endclass
2007 END
2008 writefile(imported, 'XdefIntf2.vim', 'D')
2009
2010 lines[1] = " import './XdefIntf2.vim' as defIntf"
2011 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002012enddef
2013
Bram Moolenaar94674f22023-01-06 18:42:20 +00002014def Test_class_implements_interface()
2015 var lines =<< trim END
2016 vim9script
2017
2018 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002019 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002020 def Method(nr: number)
2021 endinterface
2022
2023 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002024 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002025 def Method(nr: number)
2026 echo nr
2027 enddef
2028 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002029
2030 interface Another
2031 this.member: string
2032 endinterface
2033
Bram Moolenaar83ae6152023-02-25 19:59:31 +00002034 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002035 this.member = 'abc'
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002036 this.count = 20
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002037 def Method(nr: number)
2038 echo nr
2039 enddef
2040 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002041 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002042 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002043
2044 lines =<< trim END
2045 vim9script
2046
2047 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002048 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002049 endinterface
2050
2051 class SomeImpl implements Some implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002052 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002053 endclass
2054 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002055 v9.CheckSourceFailure(lines, 'E1350:')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002056
2057 lines =<< trim END
2058 vim9script
2059
2060 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002061 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002062 endinterface
2063
2064 class SomeImpl implements Some, Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002065 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002066 endclass
2067 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002068 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002069
2070 lines =<< trim END
2071 vim9script
2072
2073 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002074 this.counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002075 def Method(nr: number)
2076 endinterface
2077
2078 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002079 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002080 def Method(nr: number)
2081 echo nr
2082 enddef
2083 endclass
2084 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002085 v9.CheckSourceFailure(lines, 'E1348: Member "counter" of interface "Some" is not implemented')
Bram Moolenaar94674f22023-01-06 18:42:20 +00002086
2087 lines =<< trim END
2088 vim9script
2089
2090 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002091 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002092 def Methods(nr: number)
2093 endinterface
2094
2095 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002096 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002097 def Method(nr: number)
2098 echo nr
2099 enddef
2100 endclass
2101 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002102 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002103
2104 # Check different order of members in class and interface works.
2105 lines =<< trim END
2106 vim9script
2107
2108 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002109 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002110 this.errpos: number
2111 endinterface
2112
2113 # order of members is opposite of interface
2114 class Failure implements Result
2115 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002116 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002117 endclass
2118
2119 def Test()
2120 var result: Result = Failure.new()
2121
2122 assert_equal('label', result.label)
2123 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002124
2125 result.label = 'different'
2126 assert_equal('different', result.label)
2127 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002128 enddef
2129
2130 Test()
2131 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002132 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002133
2134 # Interface name after "extends" doesn't end in a space or NUL character
2135 lines =<< trim END
2136 vim9script
2137 interface A
2138 endinterface
2139 class B extends A"
2140 endclass
2141 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002142 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002143
2144 # Trailing characters after a class name
2145 lines =<< trim END
2146 vim9script
2147 class A bbb
2148 endclass
2149 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002150 v9.CheckSourceFailure(lines, 'E488:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002151
2152 # using "implements" with a non-existing class
2153 lines =<< trim END
2154 vim9script
2155 class A implements B
2156 endclass
2157 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002158 v9.CheckSourceFailure(lines, 'E1346:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002159
2160 # using "implements" with a regular class
2161 lines =<< trim END
2162 vim9script
2163 class A
2164 endclass
2165 class B implements A
2166 endclass
2167 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002168 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002169
2170 # using "implements" with a variable
2171 lines =<< trim END
2172 vim9script
2173 var T: number = 10
2174 class A implements T
2175 endclass
2176 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002177 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002178
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002179 # implements should be followed by a white space
2180 lines =<< trim END
2181 vim9script
2182 interface A
2183 endinterface
2184 class B implements A;
2185 endclass
2186 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002187 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002188
LemonBoyc5d27442023-08-19 13:02:35 +02002189 lines =<< trim END
2190 vim9script
2191
2192 interface One
LemonBoyc5d27442023-08-19 13:02:35 +02002193 def IsEven(nr: number): bool
2194 endinterface
2195 class Two implements One
2196 def IsEven(nr: number): string
2197 enddef
2198 endclass
2199 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002200 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02002201
2202 lines =<< trim END
2203 vim9script
2204
2205 interface One
2206 def IsEven(nr: number): bool
2207 endinterface
2208 class Two implements One
2209 def IsEven(nr: bool): bool
2210 enddef
2211 endclass
2212 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002213 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02002214
2215 lines =<< trim END
2216 vim9script
2217
2218 interface One
2219 def IsEven(nr: number): bool
2220 endinterface
2221 class Two implements One
2222 def IsEven(nr: number, ...extra: list<number>): bool
2223 enddef
2224 endclass
2225 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002226 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
Ernie Raelcf138d42023-09-06 20:45:03 +02002227
2228 # access superclass interface members from subclass, mix variable order
2229 lines =<< trim END
2230 vim9script
2231
2232 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002233 public this.mvar1: number
2234 public this.mvar2: number
2235 endinterface
2236
2237 # NOTE: the order is swapped
2238 class A implements I1
2239 public this.mvar2: number
2240 public this.mvar1: number
2241 public static svar2: number
2242 public static svar1: number
2243 def new()
2244 svar1 = 11
2245 svar2 = 12
2246 this.mvar1 = 111
2247 this.mvar2 = 112
2248 enddef
2249 endclass
2250
2251 class B extends A
2252 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002253 this.mvar1 = 121
2254 this.mvar2 = 122
2255 enddef
2256 endclass
2257
2258 class C extends B
2259 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002260 this.mvar1 = 131
2261 this.mvar2 = 132
2262 enddef
2263 endclass
2264
Ernie Raelcf138d42023-09-06 20:45:03 +02002265 def F2(i: I1): list<number>
2266 return [ i.mvar1, i.mvar2 ]
2267 enddef
2268
2269 var oa = A.new()
2270 var ob = B.new()
2271 var oc = C.new()
2272
Ernie Raelcf138d42023-09-06 20:45:03 +02002273 assert_equal([111, 112], F2(oa))
2274 assert_equal([121, 122], F2(ob))
2275 assert_equal([131, 132], F2(oc))
2276 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002277 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002278
2279 # Access superclass interface members from subclass, mix variable order.
2280 # Two interfaces, one on A, one on B; each has both kinds of variables
2281 lines =<< trim END
2282 vim9script
2283
2284 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002285 public this.mvar1: number
2286 public this.mvar2: number
2287 endinterface
2288
2289 interface I2
Ernie Raelcf138d42023-09-06 20:45:03 +02002290 public this.mvar3: number
2291 public this.mvar4: number
2292 endinterface
2293
2294 class A implements I1
2295 public static svar1: number
2296 public static svar2: number
2297 public this.mvar1: number
2298 public this.mvar2: number
2299 def new()
2300 svar1 = 11
2301 svar2 = 12
2302 this.mvar1 = 111
2303 this.mvar2 = 112
2304 enddef
2305 endclass
2306
2307 class B extends A implements I2
2308 public static svar3: number
2309 public static svar4: number
2310 public this.mvar3: number
2311 public this.mvar4: number
2312 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002313 svar3 = 23
2314 svar4 = 24
2315 this.mvar1 = 121
2316 this.mvar2 = 122
2317 this.mvar3 = 123
2318 this.mvar4 = 124
2319 enddef
2320 endclass
2321
2322 class C extends B
2323 public static svar5: number
2324 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002325 svar5 = 1001
2326 this.mvar1 = 131
2327 this.mvar2 = 132
2328 this.mvar3 = 133
2329 this.mvar4 = 134
2330 enddef
2331 endclass
2332
Ernie Raelcf138d42023-09-06 20:45:03 +02002333 def F2(i: I1): list<number>
2334 return [ i.mvar1, i.mvar2 ]
2335 enddef
2336
Ernie Raelcf138d42023-09-06 20:45:03 +02002337 def F4(i: I2): list<number>
2338 return [ i.mvar3, i.mvar4 ]
2339 enddef
2340
Ernie Raelcf138d42023-09-06 20:45:03 +02002341 var oa = A.new()
2342 var ob = B.new()
2343 var oc = C.new()
2344
Ernie Raelcf138d42023-09-06 20:45:03 +02002345 assert_equal([[111, 112]], [F2(oa)])
2346 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2347 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002348 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002349 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002350enddef
2351
Bram Moolenaard0200c82023-01-28 15:19:40 +00002352def Test_call_interface_method()
2353 var lines =<< trim END
2354 vim9script
2355 interface Base
2356 def Enter(): void
2357 endinterface
2358
2359 class Child implements Base
2360 def Enter(): void
2361 g:result ..= 'child'
2362 enddef
2363 endclass
2364
2365 def F(obj: Base)
2366 obj.Enter()
2367 enddef
2368
2369 g:result = ''
2370 F(Child.new())
2371 assert_equal('child', g:result)
2372 unlet g:result
2373 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002374 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002375
2376 lines =<< trim END
2377 vim9script
2378 class Base
2379 def Enter(): void
2380 g:result ..= 'base'
2381 enddef
2382 endclass
2383
2384 class Child extends Base
2385 def Enter(): void
2386 g:result ..= 'child'
2387 enddef
2388 endclass
2389
2390 def F(obj: Base)
2391 obj.Enter()
2392 enddef
2393
2394 g:result = ''
2395 F(Child.new())
2396 assert_equal('child', g:result)
2397 unlet g:result
2398 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002399 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002400
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002401 # method of interface returns a value
2402 lines =<< trim END
2403 vim9script
2404 interface Base
2405 def Enter(): string
2406 endinterface
2407
2408 class Child implements Base
2409 def Enter(): string
2410 g:result ..= 'child'
2411 return "/resource"
2412 enddef
2413 endclass
2414
2415 def F(obj: Base)
2416 var r = obj.Enter()
2417 g:result ..= r
2418 enddef
2419
2420 g:result = ''
2421 F(Child.new())
2422 assert_equal('child/resource', g:result)
2423 unlet g:result
2424 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002425 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002426
2427 lines =<< trim END
2428 vim9script
2429 class Base
2430 def Enter(): string
2431 return null_string
2432 enddef
2433 endclass
2434
2435 class Child extends Base
2436 def Enter(): string
2437 g:result ..= 'child'
2438 return "/resource"
2439 enddef
2440 endclass
2441
2442 def F(obj: Base)
2443 var r = obj.Enter()
2444 g:result ..= r
2445 enddef
2446
2447 g:result = ''
2448 F(Child.new())
2449 assert_equal('child/resource', g:result)
2450 unlet g:result
2451 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002452 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002453
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002454 # No class that implements the interface.
2455 lines =<< trim END
2456 vim9script
2457
2458 interface IWithEE
2459 def Enter(): any
2460 def Exit(): void
2461 endinterface
2462
2463 def With1(ee: IWithEE, F: func)
2464 var r = ee.Enter()
2465 enddef
2466
2467 defcompile
2468 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002469 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002470enddef
2471
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002472def Test_class_used_as_type()
2473 var lines =<< trim END
2474 vim9script
2475
2476 class Point
2477 this.x = 0
2478 this.y = 0
2479 endclass
2480
2481 var p: Point
2482 p = Point.new(2, 33)
2483 assert_equal(2, p.x)
2484 assert_equal(33, p.y)
2485 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002486 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002487
2488 lines =<< trim END
2489 vim9script
2490
2491 interface HasX
2492 this.x: number
2493 endinterface
2494
2495 class Point implements HasX
2496 this.x = 0
2497 this.y = 0
2498 endclass
2499
2500 var p: Point
2501 p = Point.new(2, 33)
2502 var hx = p
2503 assert_equal(2, hx.x)
2504 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002505 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002506
2507 lines =<< trim END
2508 vim9script
2509
2510 class Point
2511 this.x = 0
2512 this.y = 0
2513 endclass
2514
2515 var p: Point
2516 p = 'text'
2517 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002518 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002519enddef
2520
Bram Moolenaar83677162023-01-08 19:54:10 +00002521def Test_class_extends()
2522 var lines =<< trim END
2523 vim9script
2524 class Base
2525 this.one = 1
2526 def GetOne(): number
2527 return this.one
2528 enddef
2529 endclass
2530 class Child extends Base
2531 this.two = 2
2532 def GetTotal(): number
2533 return this.one + this.two
2534 enddef
2535 endclass
2536 var o = Child.new()
2537 assert_equal(1, o.one)
2538 assert_equal(2, o.two)
2539 assert_equal(1, o.GetOne())
2540 assert_equal(3, o.GetTotal())
2541 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002542 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002543
2544 lines =<< trim END
2545 vim9script
2546 class Base
2547 this.one = 1
2548 endclass
2549 class Child extends Base
2550 this.two = 2
2551 endclass
2552 var o = Child.new(3, 44)
2553 assert_equal(3, o.one)
2554 assert_equal(44, o.two)
2555 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002556 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002557
2558 lines =<< trim END
2559 vim9script
2560 class Base
2561 this.one = 1
2562 endclass
2563 class Child extends Base extends Base
2564 this.two = 2
2565 endclass
2566 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002567 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
Bram Moolenaar83677162023-01-08 19:54:10 +00002568
2569 lines =<< trim END
2570 vim9script
2571 class Child extends BaseClass
2572 this.two = 2
2573 endclass
2574 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002575 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
Bram Moolenaar83677162023-01-08 19:54:10 +00002576
2577 lines =<< trim END
2578 vim9script
2579 var SomeVar = 99
2580 class Child extends SomeVar
2581 this.two = 2
2582 endclass
2583 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002584 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002585
2586 lines =<< trim END
2587 vim9script
2588 class Base
2589 this.name: string
2590 def ToString(): string
2591 return this.name
2592 enddef
2593 endclass
2594
2595 class Child extends Base
2596 this.age: number
2597 def ToString(): string
2598 return super.ToString() .. ': ' .. this.age
2599 enddef
2600 endclass
2601
2602 var o = Child.new('John', 42)
2603 assert_equal('John: 42', o.ToString())
2604 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002605 v9.CheckSourceSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002606
2607 lines =<< trim END
2608 vim9script
2609 class Child
2610 this.age: number
2611 def ToString(): number
2612 return this.age
2613 enddef
2614 def ToString(): string
2615 return this.age
2616 enddef
2617 endclass
2618 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002619 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002620
2621 lines =<< trim END
2622 vim9script
2623 class Child
2624 this.age: number
2625 def ToString(): string
2626 return super .ToString() .. ': ' .. this.age
2627 enddef
2628 endclass
2629 var o = Child.new(42)
2630 echo o.ToString()
2631 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002632 v9.CheckSourceFailure(lines, 'E1356:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002633
2634 lines =<< trim END
2635 vim9script
2636 class Base
2637 this.name: string
2638 def ToString(): string
2639 return this.name
2640 enddef
2641 endclass
2642
2643 var age = 42
2644 def ToString(): string
2645 return super.ToString() .. ': ' .. age
2646 enddef
2647 echo ToString()
2648 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002649 v9.CheckSourceFailure(lines, 'E1357:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002650
2651 lines =<< trim END
2652 vim9script
2653 class Child
2654 this.age: number
2655 def ToString(): string
2656 return super.ToString() .. ': ' .. this.age
2657 enddef
2658 endclass
2659 var o = Child.new(42)
2660 echo o.ToString()
2661 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002662 v9.CheckSourceFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002663
2664 lines =<< trim END
2665 vim9script
2666 class Base
2667 this.name: string
2668 static def ToString(): string
2669 return 'Base class'
2670 enddef
2671 endclass
2672
2673 class Child extends Base
2674 this.age: number
2675 def ToString(): string
2676 return Base.ToString() .. ': ' .. this.age
2677 enddef
2678 endclass
2679
2680 var o = Child.new('John', 42)
2681 assert_equal('Base class: 42', o.ToString())
2682 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002683 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002684
2685 lines =<< trim END
2686 vim9script
2687 class Base
2688 this.value = 1
2689 def new(init: number)
2690 this.value = number + 1
2691 enddef
2692 endclass
2693 class Child extends Base
2694 def new()
2695 this.new(3)
2696 enddef
2697 endclass
2698 var c = Child.new()
2699 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002700 v9.CheckSourceFailure(lines, 'E1375: Class member "new" accessible only using class "Child"')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002701
2702 # base class with more than one object member
2703 lines =<< trim END
2704 vim9script
2705
2706 class Result
2707 this.success: bool
2708 this.value: any = null
2709 endclass
2710
2711 class Success extends Result
2712 def new(this.value = v:none)
2713 this.success = true
2714 enddef
2715 endclass
2716
2717 var v = Success.new('asdf')
2718 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2719 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002720 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002721
2722 # class name after "extends" doesn't end in a space or NUL character
2723 lines =<< trim END
2724 vim9script
2725 class A
2726 endclass
2727 class B extends A"
2728 endclass
2729 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002730 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002731enddef
2732
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002733def Test_using_base_class()
2734 var lines =<< trim END
2735 vim9script
2736
2737 class BaseEE
2738 def Enter(): any
2739 return null
2740 enddef
2741 def Exit(resource: any): void
2742 enddef
2743 endclass
2744
2745 class ChildEE extends BaseEE
2746 def Enter(): any
2747 return 42
2748 enddef
2749
2750 def Exit(resource: number): void
2751 g:result ..= '/exit'
2752 enddef
2753 endclass
2754
2755 def With(ee: BaseEE)
2756 var r = ee.Enter()
2757 try
2758 g:result ..= r
2759 finally
2760 g:result ..= '/finally'
2761 ee.Exit(r)
2762 endtry
2763 enddef
2764
2765 g:result = ''
2766 With(ChildEE.new())
2767 assert_equal('42/finally/exit', g:result)
2768 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002769 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002770 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002771
2772 # Using super, Child invokes Base method which has optional arg. #12471
2773 lines =<< trim END
2774 vim9script
2775
2776 class Base
2777 this.success: bool = false
2778 def Method(arg = 0)
2779 this.success = true
2780 enddef
2781 endclass
2782
2783 class Child extends Base
2784 def new()
2785 super.Method()
2786 enddef
2787 endclass
2788
2789 var obj = Child.new()
2790 assert_equal(true, obj.success)
2791 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002792 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002793enddef
2794
Bram Moolenaara86655a2023-01-12 17:06:27 +00002795def Test_class_import()
2796 var lines =<< trim END
2797 vim9script
2798 export class Animal
2799 this.kind: string
2800 this.name: string
2801 endclass
2802 END
2803 writefile(lines, 'Xanimal.vim', 'D')
2804
2805 lines =<< trim END
2806 vim9script
2807 import './Xanimal.vim' as animal
2808
2809 var a: animal.Animal
2810 a = animal.Animal.new('fish', 'Eric')
2811 assert_equal('fish', a.kind)
2812 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002813
2814 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2815 assert_equal('cat', b.kind)
2816 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002817 END
2818 v9.CheckScriptSuccess(lines)
2819enddef
2820
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002821def Test_abstract_class()
2822 var lines =<< trim END
2823 vim9script
2824 abstract class Base
2825 this.name: string
2826 endclass
2827 class Person extends Base
2828 this.age: number
2829 endclass
2830 var p: Base = Person.new('Peter', 42)
2831 assert_equal('Peter', p.name)
2832 assert_equal(42, p.age)
2833 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002834 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002835
2836 lines =<< trim END
2837 vim9script
2838 abstract class Base
2839 this.name: string
2840 endclass
2841 class Person extends Base
2842 this.age: number
2843 endclass
2844 var p = Base.new('Peter')
2845 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002846 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002847
2848 lines =<< trim END
2849 abstract class Base
2850 this.name: string
2851 endclass
2852 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002853 v9.CheckSourceFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002854
2855 # Abstract class cannot have a "new" function
2856 lines =<< trim END
2857 vim9script
2858 abstract class Base
2859 def new()
2860 enddef
2861 endclass
2862 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002863 v9.CheckSourceFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002864enddef
2865
Bram Moolenaar486fc252023-01-18 14:51:07 +00002866def Test_closure_in_class()
2867 var lines =<< trim END
2868 vim9script
2869
2870 class Foo
2871 this.y: list<string> = ['B']
2872
2873 def new()
2874 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2875 enddef
2876 endclass
2877
2878 Foo.new()
2879 assert_equal(['A'], g:result)
2880 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002881 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00002882enddef
2883
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002884def Test_call_constructor_from_legacy()
2885 var lines =<< trim END
2886 vim9script
2887
2888 var newCalled = 'false'
2889
2890 class A
2891 def new()
2892 newCalled = 'true'
2893 enddef
2894 endclass
2895
2896 export def F(options = {}): any
2897 return A
2898 enddef
2899
2900 g:p = F()
2901 legacy call p.new()
2902 assert_equal('true', newCalled)
2903 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002904 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002905enddef
2906
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002907def Test_defer_with_object()
2908 var lines =<< trim END
2909 vim9script
2910
2911 class CWithEE
2912 def Enter()
2913 g:result ..= "entered/"
2914 enddef
2915 def Exit()
2916 g:result ..= "exited"
2917 enddef
2918 endclass
2919
2920 def With(ee: CWithEE, F: func)
2921 ee.Enter()
2922 defer ee.Exit()
2923 F()
2924 enddef
2925
2926 g:result = ''
2927 var obj = CWithEE.new()
2928 obj->With(() => {
2929 g:result ..= "called/"
2930 })
2931 assert_equal('entered/called/exited', g:result)
2932 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002933 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002934 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002935
2936 lines =<< trim END
2937 vim9script
2938
2939 class BaseWithEE
2940 def Enter()
2941 g:result ..= "entered-base/"
2942 enddef
2943 def Exit()
2944 g:result ..= "exited-base"
2945 enddef
2946 endclass
2947
2948 class CWithEE extends BaseWithEE
2949 def Enter()
2950 g:result ..= "entered-child/"
2951 enddef
2952 def Exit()
2953 g:result ..= "exited-child"
2954 enddef
2955 endclass
2956
2957 def With(ee: BaseWithEE, F: func)
2958 ee.Enter()
2959 defer ee.Exit()
2960 F()
2961 enddef
2962
2963 g:result = ''
2964 var obj = CWithEE.new()
2965 obj->With(() => {
2966 g:result ..= "called/"
2967 })
2968 assert_equal('entered-child/called/exited-child', g:result)
2969 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002970 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00002971 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002972enddef
2973
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002974" The following test used to crash Vim (Github issue #12676)
2975def Test_extends_method_crashes_vim()
2976 var lines =<< trim END
2977 vim9script
2978
2979 class Observer
2980 endclass
2981
2982 class Property
2983 this.value: any
2984
2985 def Set(v: any)
2986 if v != this.value
2987 this.value = v
2988 endif
2989 enddef
2990
2991 def Register(observer: Observer)
2992 enddef
2993 endclass
2994
2995 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002996 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002997 endclass
2998
2999 def Observe(obj: Property, who: Observer)
3000 obj.Register(who)
3001 enddef
3002
3003 var p = Bool.new(false)
3004 var myObserver = Observer.new()
3005
3006 Observe(p, myObserver)
3007
3008 p.Set(true)
3009 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003010 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003011enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003012
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003013" Test for calling a method in a class that is extended
3014def Test_call_method_in_extended_class()
3015 var lines =<< trim END
3016 vim9script
3017
3018 var prop_init_called = false
3019 var prop_register_called = false
3020
3021 class Property
3022 def Init()
3023 prop_init_called = true
3024 enddef
3025
3026 def Register()
3027 prop_register_called = true
3028 enddef
3029 endclass
3030
3031 class Bool extends Property
3032 endclass
3033
3034 def Observe(obj: Property)
3035 obj.Register()
3036 enddef
3037
3038 var p = Property.new()
3039 Observe(p)
3040
3041 p.Init()
3042 assert_true(prop_init_called)
3043 assert_true(prop_register_called)
3044 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003045 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003046enddef
3047
LemonBoyafe04662023-08-23 21:08:11 +02003048def Test_instanceof()
3049 var lines =<< trim END
3050 vim9script
3051
3052 class Base1
3053 endclass
3054
3055 class Base2 extends Base1
3056 endclass
3057
3058 interface Intf1
3059 endinterface
3060
3061 class Mix1 implements Intf1
3062 endclass
3063
3064 class Base3 extends Mix1
3065 endclass
3066
3067 var b1 = Base1.new()
3068 var b2 = Base2.new()
3069 var b3 = Base3.new()
3070
3071 assert_true(instanceof(b1, Base1))
3072 assert_true(instanceof(b2, Base1))
3073 assert_false(instanceof(b1, Base2))
3074 assert_true(instanceof(b3, Mix1))
3075 assert_false(instanceof(b3, []))
3076 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003077
3078 def Foo()
3079 var a1 = Base1.new()
3080 var a2 = Base2.new()
3081 var a3 = Base3.new()
3082
3083 assert_true(instanceof(a1, Base1))
3084 assert_true(instanceof(a2, Base1))
3085 assert_false(instanceof(a1, Base2))
3086 assert_true(instanceof(a3, Mix1))
3087 assert_false(instanceof(a3, []))
3088 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
3089 enddef
3090 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003091
3092 var o_null: Base1
3093 assert_false(instanceof(o_null, Base1))
3094
LemonBoyafe04662023-08-23 21:08:11 +02003095 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003096 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02003097enddef
3098
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003099" Test for calling a method in the parent class that is extended partially.
3100" This used to fail with the 'E118: Too many arguments for function: Text' error
3101" message (Github issue #12524).
3102def Test_call_method_in_parent_class()
3103 var lines =<< trim END
3104 vim9script
3105
3106 class Widget
3107 this._lnum: number = 1
3108
3109 def SetY(lnum: number)
3110 this._lnum = lnum
3111 enddef
3112
3113 def Text(): string
3114 return ''
3115 enddef
3116 endclass
3117
3118 class Foo extends Widget
3119 def Text(): string
3120 return '<Foo>'
3121 enddef
3122 endclass
3123
3124 def Stack(w1: Widget, w2: Widget): list<Widget>
3125 w1.SetY(1)
3126 w2.SetY(2)
3127 return [w1, w2]
3128 enddef
3129
3130 var foo1 = Foo.new()
3131 var foo2 = Foo.new()
3132 var l = Stack(foo1, foo2)
3133 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003134 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003135enddef
3136
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003137" Test for calling methods from three levels of classes
3138def Test_multi_level_method_call()
3139 var lines =<< trim END
3140 vim9script
3141
3142 var A_func1: number = 0
3143 var A_func2: number = 0
3144 var A_func3: number = 0
3145 var B_func2: number = 0
3146 var B_func3: number = 0
3147 var C_func3: number = 0
3148
3149 class A
3150 def Func1()
3151 A_func1 += 1
3152 enddef
3153
3154 def Func2()
3155 A_func2 += 1
3156 enddef
3157
3158 def Func3()
3159 A_func3 += 1
3160 enddef
3161 endclass
3162
3163 class B extends A
3164 def Func2()
3165 B_func2 += 1
3166 enddef
3167
3168 def Func3()
3169 B_func3 += 1
3170 enddef
3171 endclass
3172
3173 class C extends B
3174 def Func3()
3175 C_func3 += 1
3176 enddef
3177 endclass
3178
3179 def A_CallFuncs(a: A)
3180 a.Func1()
3181 a.Func2()
3182 a.Func3()
3183 enddef
3184
3185 def B_CallFuncs(b: B)
3186 b.Func1()
3187 b.Func2()
3188 b.Func3()
3189 enddef
3190
3191 def C_CallFuncs(c: C)
3192 c.Func1()
3193 c.Func2()
3194 c.Func3()
3195 enddef
3196
3197 var cobj = C.new()
3198 A_CallFuncs(cobj)
3199 B_CallFuncs(cobj)
3200 C_CallFuncs(cobj)
3201 assert_equal(3, A_func1)
3202 assert_equal(0, A_func2)
3203 assert_equal(0, A_func3)
3204 assert_equal(3, B_func2)
3205 assert_equal(0, B_func3)
3206 assert_equal(3, C_func3)
3207 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003208 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003209enddef
3210
3211" Test for using members from three levels of classes
3212def Test_multi_level_member_access()
3213 var lines =<< trim END
3214 vim9script
3215
3216 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003217 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003218 endclass
3219
3220 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003221 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003222 endclass
3223
3224 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003225 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003226 endclass
3227
3228 def A_members(a: A)
3229 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003230 enddef
3231
3232 def B_members(b: B)
3233 b.val1 += 1
3234 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003235 enddef
3236
3237 def C_members(c: C)
3238 c.val1 += 1
3239 c.val2 += 1
3240 c.val3 += 1
3241 enddef
3242
3243 var cobj = C.new()
3244 A_members(cobj)
3245 B_members(cobj)
3246 C_members(cobj)
3247 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003248 assert_equal(2, cobj.val2)
3249 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003250 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003251 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003252enddef
3253
LemonBoy0ffc17a2023-08-20 18:09:11 +02003254" Test expansion of <stack> with class methods.
3255def Test_stack_expansion_with_methods()
3256 var lines =<< trim END
3257 vim9script
3258
3259 class C
3260 def M1()
3261 F0()
3262 enddef
3263 endclass
3264
3265 def F0()
3266 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3267 enddef
3268
3269 def F()
3270 C.new().M1()
3271 enddef
3272
3273 F()
3274 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003275 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003276enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003277
3278" Test the return type of the new() constructor
3279def Test_new_return_type()
3280 # new() uses the default return type and there is no return statement
3281 var lines =<< trim END
3282 vim9script
3283
3284 class C
3285 this._bufnr: number
3286
3287 def new(this._bufnr)
3288 if !bufexists(this._bufnr)
3289 this._bufnr = -1
3290 endif
3291 enddef
3292 endclass
3293
3294 var c = C.new(12345)
3295 assert_equal('object<C>', typename(c))
3296
3297 var v1: C
3298 v1 = C.new(12345)
3299 assert_equal('object<C>', typename(v1))
3300
3301 def F()
3302 var v2: C
3303 v2 = C.new(12345)
3304 assert_equal('object<C>', typename(v2))
3305 enddef
3306 F()
3307 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003308 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003309
3310 # new() uses the default return type and an empty 'return' statement
3311 lines =<< trim END
3312 vim9script
3313
3314 class C
3315 this._bufnr: number
3316
3317 def new(this._bufnr)
3318 if !bufexists(this._bufnr)
3319 this._bufnr = -1
3320 return
3321 endif
3322 enddef
3323 endclass
3324
3325 var c = C.new(12345)
3326 assert_equal('object<C>', typename(c))
3327
3328 var v1: C
3329 v1 = C.new(12345)
3330 assert_equal('object<C>', typename(v1))
3331
3332 def F()
3333 var v2: C
3334 v2 = C.new(12345)
3335 assert_equal('object<C>', typename(v2))
3336 enddef
3337 F()
3338 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003339 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003340
3341 # new() uses "any" return type and returns "this"
3342 lines =<< trim END
3343 vim9script
3344
3345 class C
3346 this._bufnr: number
3347
3348 def new(this._bufnr): any
3349 if !bufexists(this._bufnr)
3350 this._bufnr = -1
3351 return this
3352 endif
3353 enddef
3354 endclass
3355 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003356 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003357
3358 # new() uses 'Dict' return type and returns a Dict
3359 lines =<< trim END
3360 vim9script
3361
3362 class C
3363 this._state: dict<any>
3364
3365 def new(): dict<any>
3366 this._state = {}
3367 return this._state
3368 enddef
3369 endclass
3370
3371 var c = C.new()
3372 assert_equal('object<C>', typename(c))
3373 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003374 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003375enddef
3376
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003377" Test for checking a member initialization type at run time.
3378def Test_runtime_type_check_for_member_init()
3379 var lines =<< trim END
3380 vim9script
3381
3382 var retnum: bool = false
3383
3384 def F(): any
3385 retnum = !retnum
3386 if retnum
3387 return 1
3388 else
3389 return "hello"
3390 endif
3391 enddef
3392
3393 class C
3394 this._foo: bool = F()
3395 endclass
3396
3397 var c1 = C.new()
3398 var c2 = C.new()
3399 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003400 v9.CheckSourceFailure(lines, 'E1012:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003401enddef
3402
3403" Test for locking a variable referring to an object and reassigning to another
3404" object.
3405def Test_object_lockvar()
3406 var lines =<< trim END
3407 vim9script
3408
3409 class C
3410 this.val: number
3411 def new(this.val)
3412 enddef
3413 endclass
3414
3415 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3416 lockvar 2 some_dict
3417
3418 var current: C
3419 current = some_dict['c']
3420 assert_equal(3, current.val)
3421 current = some_dict['b']
3422 assert_equal(2, current.val)
3423
3424 def F()
3425 current = some_dict['c']
3426 enddef
3427
3428 def G()
3429 current = some_dict['b']
3430 enddef
3431
3432 F()
3433 assert_equal(3, current.val)
3434 G()
3435 assert_equal(2, current.val)
3436 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003437 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003438enddef
3439
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003440" Test for a private object method
3441def Test_private_object_method()
3442 # Try calling a private method using an object (at the script level)
3443 var lines =<< trim END
3444 vim9script
3445
3446 class A
3447 def _Foo(): number
3448 return 1234
3449 enddef
3450 endclass
3451 var a = A.new()
3452 a._Foo()
3453 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003454 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003455
3456 # Try calling a private method using an object (from a def function)
3457 lines =<< trim END
3458 vim9script
3459
3460 class A
3461 def _Foo(): number
3462 return 1234
3463 enddef
3464 endclass
3465 def T()
3466 var a = A.new()
3467 a._Foo()
3468 enddef
3469 T()
3470 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003471 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003472
3473 # Use a private method from another object method (in script context)
3474 lines =<< trim END
3475 vim9script
3476
3477 class A
3478 def _Foo(): number
3479 return 1234
3480 enddef
3481 def Bar(): number
3482 return this._Foo()
3483 enddef
3484 endclass
3485 var a = A.new()
3486 assert_equal(1234, a.Bar())
3487 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003488 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003489
3490 # Use a private method from another object method (def function context)
3491 lines =<< trim END
3492 vim9script
3493
3494 class A
3495 def _Foo(): number
3496 return 1234
3497 enddef
3498 def Bar(): number
3499 return this._Foo()
3500 enddef
3501 endclass
3502 def T()
3503 var a = A.new()
3504 assert_equal(1234, a.Bar())
3505 enddef
3506 T()
3507 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003508 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003509
3510 # Try calling a private method without the "this" prefix
3511 lines =<< trim END
3512 vim9script
3513
3514 class A
3515 def _Foo(): number
3516 return 1234
3517 enddef
3518 def Bar(): number
3519 return _Foo()
3520 enddef
3521 endclass
3522 var a = A.new()
3523 a.Bar()
3524 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003525 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003526
3527 # Try calling a private method using the class name
3528 lines =<< trim END
3529 vim9script
3530
3531 class A
3532 def _Foo(): number
3533 return 1234
3534 enddef
3535 endclass
3536 A._Foo()
3537 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003538 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003539
3540 # Try to use "public" keyword when defining a private method
3541 lines =<< trim END
3542 vim9script
3543
3544 class A
3545 public def _Foo()
3546 enddef
3547 endclass
3548 var a = A.new()
3549 a._Foo()
3550 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003551 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003552
3553 # Define two private methods with the same name
3554 lines =<< trim END
3555 vim9script
3556
3557 class A
3558 def _Foo()
3559 enddef
3560 def _Foo()
3561 enddef
3562 endclass
3563 var a = A.new()
3564 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003565 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003566
3567 # Define a private method and a object method with the same name
3568 lines =<< trim END
3569 vim9script
3570
3571 class A
3572 def _Foo()
3573 enddef
3574 def Foo()
3575 enddef
3576 endclass
3577 var a = A.new()
3578 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003579 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003580
3581 # Define an object method and a private method with the same name
3582 lines =<< trim END
3583 vim9script
3584
3585 class A
3586 def Foo()
3587 enddef
3588 def _Foo()
3589 enddef
3590 endclass
3591 var a = A.new()
3592 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003593 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003594
3595 # Call a public method and a private method from a private method
3596 lines =<< trim END
3597 vim9script
3598
3599 class A
3600 def Foo(): number
3601 return 100
3602 enddef
3603 def _Bar(): number
3604 return 200
3605 enddef
3606 def _Baz()
3607 assert_equal(100, this.Foo())
3608 assert_equal(200, this._Bar())
3609 enddef
3610 def T()
3611 this._Baz()
3612 enddef
3613 endclass
3614 var a = A.new()
3615 a.T()
3616 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003617 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003618
3619 # Try calling a private method from another class
3620 lines =<< trim END
3621 vim9script
3622
3623 class A
3624 def _Foo(): number
3625 return 100
3626 enddef
3627 endclass
3628 class B
3629 def Foo(): number
3630 var a = A.new()
3631 a._Foo()
3632 enddef
3633 endclass
3634 var b = B.new()
3635 b.Foo()
3636 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003637 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003638
3639 # Call a private object method from a child class object method
3640 lines =<< trim END
3641 vim9script
3642 class A
3643 def _Foo(): number
3644 return 1234
3645 enddef
3646 endclass
3647 class B extends A
3648 def Bar()
3649 enddef
3650 endclass
3651 class C extends B
3652 def Baz(): number
3653 return this._Foo()
3654 enddef
3655 endclass
3656 var c = C.new()
3657 assert_equal(1234, c.Baz())
3658 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003659 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003660
3661 # Call a private object method from a child class object
3662 lines =<< trim END
3663 vim9script
3664 class A
3665 def _Foo(): number
3666 return 1234
3667 enddef
3668 endclass
3669 class B extends A
3670 def Bar()
3671 enddef
3672 endclass
3673 class C extends B
3674 def Baz(): number
3675 enddef
3676 endclass
3677 var c = C.new()
3678 assert_equal(1234, c._Foo())
3679 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003680 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003681
3682 # Using "_" prefix in a method name should fail outside of a class
3683 lines =<< trim END
3684 vim9script
3685 def _Foo(): number
3686 return 1234
3687 enddef
3688 var a = _Foo()
3689 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003690 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003691enddef
3692
3693" Test for an private class method
3694def Test_private_class_method()
3695 # Try calling a class private method (at the script level)
3696 var lines =<< trim END
3697 vim9script
3698
3699 class A
3700 static def _Foo(): number
3701 return 1234
3702 enddef
3703 endclass
3704 A._Foo()
3705 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003706 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003707
3708 # Try calling a class private method (from a def function)
3709 lines =<< trim END
3710 vim9script
3711
3712 class A
3713 static def _Foo(): number
3714 return 1234
3715 enddef
3716 endclass
3717 def T()
3718 A._Foo()
3719 enddef
3720 T()
3721 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003722 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003723
3724 # Try calling a class private method using an object (at the script level)
3725 lines =<< trim END
3726 vim9script
3727
3728 class A
3729 static def _Foo(): number
3730 return 1234
3731 enddef
3732 endclass
3733 var a = A.new()
3734 a._Foo()
3735 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003736 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003737
3738 # Try calling a class private method using an object (from a def function)
3739 lines =<< trim END
3740 vim9script
3741
3742 class A
3743 static def _Foo(): number
3744 return 1234
3745 enddef
3746 endclass
3747 def T()
3748 var a = A.new()
3749 a._Foo()
3750 enddef
3751 T()
3752 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003753 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003754
3755 # Use a class private method from an object method
3756 lines =<< trim END
3757 vim9script
3758
3759 class A
3760 static def _Foo(): number
3761 return 1234
3762 enddef
3763 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003764 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003765 enddef
3766 endclass
3767 var a = A.new()
3768 a.Bar()
3769 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003770 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003771
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003772 # Use a class private method from another class private method without the
3773 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003774 lines =<< trim END
3775 vim9script
3776
3777 class A
3778 static def _Foo1(): number
3779 return 1234
3780 enddef
3781 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003782 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003783 enddef
3784 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003785 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003786 enddef
3787 endclass
3788 var a = A.new()
3789 a.Bar()
3790 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003791 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003792
3793 # Declare a class method and a class private method with the same name
3794 lines =<< trim END
3795 vim9script
3796
3797 class A
3798 static def _Foo()
3799 enddef
3800 static def Foo()
3801 enddef
3802 endclass
3803 var a = A.new()
3804 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003805 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003806
3807 # Try calling a class private method from another class
3808 lines =<< trim END
3809 vim9script
3810
3811 class A
3812 static def _Foo(): number
3813 return 1234
3814 enddef
3815 endclass
3816 class B
3817 def Foo(): number
3818 return A._Foo()
3819 enddef
3820 endclass
3821 var b = B.new()
3822 assert_equal(1234, b.Foo())
3823 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003824 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003825
3826 # Call a private class method from a child class object method
3827 lines =<< trim END
3828 vim9script
3829 class A
3830 static def _Foo(): number
3831 return 1234
3832 enddef
3833 endclass
3834 class B extends A
3835 def Bar()
3836 enddef
3837 endclass
3838 class C extends B
3839 def Baz(): number
3840 return A._Foo()
3841 enddef
3842 endclass
3843 var c = C.new()
3844 assert_equal(1234, c.Baz())
3845 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003846 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003847
3848 # Call a private class method from a child class private class method
3849 lines =<< trim END
3850 vim9script
3851 class A
3852 static def _Foo(): number
3853 return 1234
3854 enddef
3855 endclass
3856 class B extends A
3857 def Bar()
3858 enddef
3859 endclass
3860 class C extends B
3861 static def Baz(): number
3862 return A._Foo()
3863 enddef
3864 endclass
3865 assert_equal(1234, C.Baz())
3866 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003867 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003868
3869 # Call a private class method from a child class object
3870 lines =<< trim END
3871 vim9script
3872 class A
3873 static def _Foo(): number
3874 return 1234
3875 enddef
3876 endclass
3877 class B extends A
3878 def Bar()
3879 enddef
3880 endclass
3881 class C extends B
3882 def Baz(): number
3883 enddef
3884 endclass
3885 var c = C.new()
3886 assert_equal(1234, C._Foo())
3887 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003888 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003889enddef
3890
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003891" Test for using the return value of a class/object method as a function
3892" argument.
3893def Test_objmethod_funcarg()
3894 var lines =<< trim END
3895 vim9script
3896
3897 class C
3898 def Foo(): string
3899 return 'foo'
3900 enddef
3901 endclass
3902
3903 def Bar(a: number, s: string): string
3904 return s
3905 enddef
3906
3907 def Baz(c: C)
3908 assert_equal('foo', Bar(10, c.Foo()))
3909 enddef
3910
3911 var t = C.new()
3912 Baz(t)
3913 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003914 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003915
3916 lines =<< trim END
3917 vim9script
3918
3919 class C
3920 static def Foo(): string
3921 return 'foo'
3922 enddef
3923 endclass
3924
3925 def Bar(a: number, s: string): string
3926 return s
3927 enddef
3928
3929 def Baz()
3930 assert_equal('foo', Bar(10, C.Foo()))
3931 enddef
3932
3933 Baz()
3934 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003935 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003936enddef
3937
Ernie Raelcf138d42023-09-06 20:45:03 +02003938def Test_static_inheritence()
3939 # subclasses get their own static copy
3940 var lines =<< trim END
3941 vim9script
3942
3943 class A
3944 static _svar: number
3945 this._mvar: number
3946 def new()
3947 _svar = 1
3948 this._mvar = 101
3949 enddef
3950 def AccessObject(): number
3951 return this._mvar
3952 enddef
3953 def AccessStaticThroughObject(): number
3954 return _svar
3955 enddef
3956 endclass
3957
3958 class B extends A
3959 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003960 this._mvar = 102
3961 enddef
3962 endclass
3963
3964 class C extends B
3965 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003966 this._mvar = 103
3967 enddef
3968
3969 def AccessPrivateStaticThroughClassName(): number
3970 assert_equal(1, A._svar)
Ernie Raelcf138d42023-09-06 20:45:03 +02003971 return 444
3972 enddef
3973 endclass
3974
3975 var oa = A.new()
3976 var ob = B.new()
3977 var oc = C.new()
3978 assert_equal(101, oa.AccessObject())
3979 assert_equal(102, ob.AccessObject())
3980 assert_equal(103, oc.AccessObject())
3981
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003982 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private member: _svar')
Ernie Raelcf138d42023-09-06 20:45:03 +02003983
3984 # verify object properly resolves to correct static
3985 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003986 assert_equal(1, ob.AccessStaticThroughObject())
3987 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02003988 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003989 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02003990enddef
3991
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003992" Test for declaring duplicate object and class members
3993def Test_dup_member_variable()
3994 # Duplicate member variable
3995 var lines =<< trim END
3996 vim9script
3997 class C
3998 this.val = 10
3999 this.val = 20
4000 endclass
4001 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004002 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004003
4004 # Duplicate private member variable
4005 lines =<< trim END
4006 vim9script
4007 class C
4008 this._val = 10
4009 this._val = 20
4010 endclass
4011 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004012 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004013
4014 # Duplicate public member variable
4015 lines =<< trim END
4016 vim9script
4017 class C
4018 public this.val = 10
4019 public this.val = 20
4020 endclass
4021 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004022 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004023
4024 # Duplicate private member variable
4025 lines =<< trim END
4026 vim9script
4027 class C
4028 this.val = 10
4029 this._val = 20
4030 endclass
4031 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004032 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004033
4034 # Duplicate public and private member variable
4035 lines =<< trim END
4036 vim9script
4037 class C
4038 this._val = 20
4039 public this.val = 10
4040 endclass
4041 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004042 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004043
4044 # Duplicate class member variable
4045 lines =<< trim END
4046 vim9script
4047 class C
4048 static s: string = "abc"
4049 static _s: string = "def"
4050 endclass
4051 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004052 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004053
4054 # Duplicate public and private class member variable
4055 lines =<< trim END
4056 vim9script
4057 class C
4058 public static s: string = "abc"
4059 static _s: string = "def"
4060 endclass
4061 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004062 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004063
4064 # Duplicate class and object member variable
4065 lines =<< trim END
4066 vim9script
4067 class C
4068 static val = 10
4069 this.val = 20
4070 def new()
4071 enddef
4072 endclass
4073 var c = C.new()
4074 assert_equal(10, C.val)
4075 assert_equal(20, c.val)
4076 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004077 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004078
4079 # Duplicate object member variable in a derived class
4080 lines =<< trim END
4081 vim9script
4082 class A
4083 this.val = 10
4084 endclass
4085 class B extends A
4086 endclass
4087 class C extends B
4088 this.val = 20
4089 endclass
4090 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004091 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004092
4093 # Duplicate object private member variable in a derived class
4094 lines =<< trim END
4095 vim9script
4096 class A
4097 this._val = 10
4098 endclass
4099 class B extends A
4100 endclass
4101 class C extends B
4102 this._val = 20
4103 endclass
4104 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004105 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004106
4107 # Duplicate object private member variable in a derived class
4108 lines =<< trim END
4109 vim9script
4110 class A
4111 this.val = 10
4112 endclass
4113 class B extends A
4114 endclass
4115 class C extends B
4116 this._val = 20
4117 endclass
4118 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004119 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004120
4121 # Duplicate object member variable in a derived class
4122 lines =<< trim END
4123 vim9script
4124 class A
4125 this._val = 10
4126 endclass
4127 class B extends A
4128 endclass
4129 class C extends B
4130 this.val = 20
4131 endclass
4132 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004133 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004134
4135 # Two member variables with a common prefix
4136 lines =<< trim END
4137 vim9script
4138 class A
4139 public static svar2: number
4140 public static svar: number
4141 endclass
4142 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004143 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004144enddef
4145
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004146" Test for accessing a private member outside a class in a def function
4147def Test_private_member_access_outside_class()
4148 # private object member variable
4149 var lines =<< trim END
4150 vim9script
4151 class A
4152 this._val = 10
4153 def GetVal(): number
4154 return this._val
4155 enddef
4156 endclass
4157 def T()
4158 var a = A.new()
4159 a._val = 20
4160 enddef
4161 T()
4162 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004163 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004164
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004165 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004166 lines =<< trim END
4167 vim9script
4168 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004169 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004170 endclass
4171 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004172 var a = A.new()
4173 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004174 enddef
4175 T()
4176 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004177 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": _a')
Ernie Rael18143d32023-09-04 22:30:41 +02004178
4179 # private static member variable
4180 lines =<< trim END
4181 vim9script
4182 class A
4183 static _val = 10
4184 endclass
4185 def T()
4186 var a = A.new()
4187 var x = a._val
4188 enddef
4189 T()
4190 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004191 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004192
4193 # private static member variable
4194 lines =<< trim END
4195 vim9script
4196 class A
4197 static _val = 10
4198 endclass
4199 def T()
4200 var a = A.new()
4201 a._val = 3
4202 enddef
4203 T()
4204 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004205 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004206
4207 # private static class variable
4208 lines =<< trim END
4209 vim9script
4210 class A
4211 static _val = 10
4212 endclass
4213 def T()
4214 var x = A._val
4215 enddef
4216 T()
4217 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004218 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004219
4220 # private static class variable
4221 lines =<< trim END
4222 vim9script
4223 class A
4224 static _val = 10
4225 endclass
4226 def T()
4227 A._val = 3
4228 enddef
4229 T()
4230 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004231 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004232enddef
4233
4234" Test for changing the member access of an interface in a implementation class
4235def Test_change_interface_member_access()
4236 var lines =<< trim END
4237 vim9script
4238 interface A
4239 public this.val: number
4240 endinterface
4241 class B implements A
4242 this.val = 10
4243 endclass
4244 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004245 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004246
4247 lines =<< trim END
4248 vim9script
4249 interface A
4250 this.val: number
4251 endinterface
4252 class B implements A
4253 public this.val = 10
4254 endclass
4255 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004256 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004257enddef
4258
4259" Test for trying to change a readonly member from a def function
4260def Test_readonly_member_change_in_def_func()
4261 var lines =<< trim END
4262 vim9script
4263 class A
4264 this.val: number
4265 endclass
4266 def T()
4267 var a = A.new()
4268 a.val = 20
4269 enddef
4270 T()
4271 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004272 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004273enddef
4274
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004275" Test for reading and writing a class member from a def function
4276def Test_modify_class_member_from_def_function()
4277 var lines =<< trim END
4278 vim9script
4279 class A
4280 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004281 public static var2: list<number> = [1, 2]
4282 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004283 static _priv_var4: number = 40
4284 endclass
4285 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004286 assert_equal([1, 2], A.var2)
4287 assert_equal({a: 1, b: 2}, A.var3)
4288 A.var2 = [3, 4]
4289 A.var3 = {c: 3, d: 4}
4290 assert_equal([3, 4], A.var2)
4291 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004292 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4293 enddef
4294 T()
4295 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004296 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004297enddef
4298
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004299" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004300def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004301 var lines =<< trim END
4302 vim9script
4303 class A
4304 public static svar1: list<number> = [1]
4305 public static svar2: list<number> = [2]
4306 endclass
4307
4308 A.svar1->add(3)
4309 A.svar2->add(4)
4310 assert_equal([1, 3], A.svar1)
4311 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004312
4313 def Foo()
4314 A.svar1->add(7)
4315 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004316 assert_equal([1, 3, 7], A.svar1)
4317 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004318 enddef
4319 Foo()
4320 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004321 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004322
4323 # Cannot read from a class variable using an object in script context
4324 lines =<< trim END
4325 vim9script
4326 class A
4327 public this.var1: number
4328 public static svar2: list<number> = [1]
4329 endclass
4330
4331 var a = A.new()
4332 echo a.svar2
4333 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004334 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004335
4336 # Cannot write to a class variable using an object in script context
4337 lines =<< trim END
4338 vim9script
4339 class A
4340 public this.var1: number
4341 public static svar2: list<number> = [1]
4342 endclass
4343
4344 var a = A.new()
4345 a.svar2 = [2]
4346 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004347 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004348
4349 # Cannot read from a class variable using an object in def method context
4350 lines =<< trim END
4351 vim9script
4352 class A
4353 public this.var1: number
4354 public static svar2: list<number> = [1]
4355 endclass
4356
4357 def T()
4358 var a = A.new()
4359 echo a.svar2
4360 enddef
4361 T()
4362 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004363 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004364
4365 # Cannot write to a class variable using an object in def method context
4366 lines =<< trim END
4367 vim9script
4368 class A
4369 public this.var1: number
4370 public static svar2: list<number> = [1]
4371 endclass
4372
4373 def T()
4374 var a = A.new()
4375 a.svar2 = [2]
4376 enddef
4377 T()
4378 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004379 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004380enddef
4381
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004382" Test for using a interface method using a child object
4383def Test_interface_method_from_child()
4384 var lines =<< trim END
4385 vim9script
4386
4387 interface A
4388 def Foo(): string
4389 endinterface
4390
4391 class B implements A
4392 def Foo(): string
4393 return 'foo'
4394 enddef
4395 endclass
4396
4397 class C extends B
4398 def Bar(): string
4399 return 'bar'
4400 enddef
4401 endclass
4402
4403 def T1(a: A)
4404 assert_equal('foo', a.Foo())
4405 enddef
4406
4407 def T2(b: B)
4408 assert_equal('foo', b.Foo())
4409 enddef
4410
4411 var c = C.new()
4412 T1(c)
4413 T2(c)
4414 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004415 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004416enddef
4417
4418" Test for using an interface method using a child object when it is overridden
4419" by the child class.
4420" FIXME: This test fails.
4421" def Test_interface_overridden_method_from_child()
4422" var lines =<< trim END
4423" vim9script
4424"
4425" interface A
4426" def Foo(): string
4427" endinterface
4428"
4429" class B implements A
4430" def Foo(): string
4431" return 'b-foo'
4432" enddef
4433" endclass
4434"
4435" class C extends B
4436" def Bar(): string
4437" return 'bar'
4438" enddef
4439" def Foo(): string
4440" return 'c-foo'
4441" enddef
4442" endclass
4443"
4444" def T1(a: A)
4445" assert_equal('c-foo', a.Foo())
4446" enddef
4447"
4448" def T2(b: B)
4449" assert_equal('c-foo', b.Foo())
4450" enddef
4451"
4452" var c = C.new()
4453" T1(c)
4454" T2(c)
4455" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004456" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004457" enddef
4458
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004459" Test for abstract methods
4460def Test_abstract_method()
4461 # Use two abstract methods
4462 var lines =<< trim END
4463 vim9script
4464 abstract class A
4465 def M1(): number
4466 return 10
4467 enddef
4468 abstract def M2(): number
4469 abstract def M3(): number
4470 endclass
4471 class B extends A
4472 def M2(): number
4473 return 20
4474 enddef
4475 def M3(): number
4476 return 30
4477 enddef
4478 endclass
4479 var b = B.new()
4480 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4481 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004482 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004483
4484 # Don't define an abstract method
4485 lines =<< trim END
4486 vim9script
4487 abstract class A
4488 abstract def Foo()
4489 endclass
4490 class B extends A
4491 endclass
4492 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004493 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004494
4495 # Use abstract method in a concrete class
4496 lines =<< trim END
4497 vim9script
4498 class A
4499 abstract def Foo()
4500 endclass
4501 class B extends A
4502 endclass
4503 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004504 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004505
4506 # Use abstract method in an interface
4507 lines =<< trim END
4508 vim9script
4509 interface A
4510 abstract def Foo()
4511 endinterface
4512 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004513 def Foo()
4514 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004515 endclass
4516 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004517 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004518
4519 # Abbreviate the "abstract" keyword
4520 lines =<< trim END
4521 vim9script
4522 class A
4523 abs def Foo()
4524 endclass
4525 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004526 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004527
4528 # Use "abstract" with a member variable
4529 lines =<< trim END
4530 vim9script
4531 abstract class A
4532 abstract this.val = 10
4533 endclass
4534 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004535 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004536
4537 # Use a static abstract method
4538 lines =<< trim END
4539 vim9script
4540 abstract class A
4541 abstract static def Foo(): number
4542 endclass
4543 class B extends A
4544 static def Foo(): number
4545 return 4
4546 enddef
4547 endclass
4548 assert_equal(4, B.Foo())
4549 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004550 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004551
4552 # Type mismatch between abstract method and concrete method
4553 lines =<< trim END
4554 vim9script
4555 abstract class A
4556 abstract def Foo(a: string, b: number): list<number>
4557 endclass
4558 class B extends A
4559 def Foo(a: number, b: string): list<string>
4560 return []
4561 enddef
4562 endclass
4563 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004564 v9.CheckSourceFailure(lines, 'E1383: Method "Foo": type mismatch, expected func(string, number): list<number> but got func(number, string): list<string>')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004565
4566 # Use an abstract class to invoke an abstract method
4567 # FIXME: This should fail
4568 lines =<< trim END
4569 vim9script
4570 abstract class A
4571 abstract static def Foo()
4572 endclass
4573 A.Foo()
4574 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004575 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004576
4577 # Invoke an abstract method from a def function
4578 lines =<< trim END
4579 vim9script
4580 abstract class A
4581 abstract def Foo(): list<number>
4582 endclass
4583 class B extends A
4584 def Foo(): list<number>
4585 return [3, 5]
4586 enddef
4587 endclass
4588 def Bar(c: B)
4589 assert_equal([3, 5], c.Foo())
4590 enddef
4591 var b = B.new()
4592 Bar(b)
4593 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004594 v9.CheckSourceSuccess(lines)
4595enddef
4596
4597" Test for calling a class method from a subclass
4598def Test_class_method_call_from_subclass()
4599 # class method call from a subclass
4600 var lines =<< trim END
4601 vim9script
4602
4603 class A
4604 static def Foo()
4605 echo "foo"
4606 enddef
4607 endclass
4608
4609 class B extends A
4610 def Bar()
4611 Foo()
4612 enddef
4613 endclass
4614
4615 var b = B.new()
4616 b.Bar()
4617 END
4618 v9.CheckSourceFailure(lines, 'E1374: Class member "Foo" accessible only inside class "A"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004619enddef
4620
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004621" Test for calling a class method using an object in a def function context and
4622" script context.
4623def Test_class_method_call_using_object()
4624 # script context
4625 var lines =<< trim END
4626 vim9script
4627 class A
4628 static def Foo(): list<string>
4629 return ['a', 'b']
4630 enddef
4631 def Bar()
4632 assert_equal(['a', 'b'], A.Foo())
4633 assert_equal(['a', 'b'], Foo())
4634 enddef
4635 endclass
4636
4637 def T()
4638 assert_equal(['a', 'b'], A.Foo())
4639 var t_a = A.new()
4640 t_a.Bar()
4641 enddef
4642
4643 assert_equal(['a', 'b'], A.Foo())
4644 var a = A.new()
4645 a.Bar()
4646 T()
4647 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004648 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004649
4650 # script context
4651 lines =<< trim END
4652 vim9script
4653 class A
4654 static def Foo(): string
4655 return 'foo'
4656 enddef
4657 endclass
4658
4659 var a = A.new()
4660 assert_equal('foo', a.Foo())
4661 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004662 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004663
4664 # def function context
4665 lines =<< trim END
4666 vim9script
4667 class A
4668 static def Foo(): string
4669 return 'foo'
4670 enddef
4671 endclass
4672
4673 def T()
4674 var a = A.new()
4675 assert_equal('foo', a.Foo())
4676 enddef
4677 T()
4678 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004679 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
4680enddef
4681
4682def Test_class_variable()
4683 var lines =<< trim END
4684 vim9script
4685
4686 class A
4687 public static val: number = 10
4688 static def ClassFunc()
4689 assert_equal(10, val)
4690 enddef
4691 def ObjFunc()
4692 assert_equal(10, val)
4693 enddef
4694 endclass
4695
4696 class B extends A
4697 endclass
4698
4699 assert_equal(10, A.val)
4700 A.ClassFunc()
4701 var a = A.new()
4702 a.ObjFunc()
4703 var b = B.new()
4704 b.ObjFunc()
4705
4706 def T1(a1: A)
4707 a1.ObjFunc()
4708 A.ClassFunc()
4709 enddef
4710 T1(b)
4711
4712 A.val = 20
4713 assert_equal(20, A.val)
4714 END
4715 v9.CheckSourceSuccess(lines)
4716
4717 # Modifying a parent class variable from a child class method
4718 lines =<< trim END
4719 vim9script
4720
4721 class A
4722 static val: number = 10
4723 endclass
4724
4725 class B extends A
4726 static def ClassFunc()
4727 val = 20
4728 enddef
4729 endclass
4730 B.ClassFunc()
4731 END
4732 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4733
4734 # Reading a parent class variable from a child class method
4735 lines =<< trim END
4736 vim9script
4737
4738 class A
4739 static val: number = 10
4740 endclass
4741
4742 class B extends A
4743 static def ClassFunc()
4744 var i = val
4745 enddef
4746 endclass
4747 B.ClassFunc()
4748 END
4749 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4750
4751 # Modifying a parent class variable from a child object method
4752 lines =<< trim END
4753 vim9script
4754
4755 class A
4756 static val: number = 10
4757 endclass
4758
4759 class B extends A
4760 def ObjFunc()
4761 val = 20
4762 enddef
4763 endclass
4764 var b = B.new()
4765 b.ObjFunc()
4766 END
4767 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4768
4769 # Reading a parent class variable from a child object method
4770 lines =<< trim END
4771 vim9script
4772
4773 class A
4774 static val: number = 10
4775 endclass
4776
4777 class B extends A
4778 def ObjFunc()
4779 var i = val
4780 enddef
4781 endclass
4782 var b = B.new()
4783 b.ObjFunc()
4784 END
4785 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4786
4787 # Modifying a class variable using an object at script level
4788 lines =<< trim END
4789 vim9script
4790
4791 class A
4792 static val: number = 10
4793 endclass
4794 var a = A.new()
4795 a.val = 20
4796 END
4797 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4798
4799 # Reading a class variable using an object at script level
4800 lines =<< trim END
4801 vim9script
4802
4803 class A
4804 static val: number = 10
4805 endclass
4806 var a = A.new()
4807 var i = a.val
4808 END
4809 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4810
4811 # Modifying a class variable using an object at function level
4812 lines =<< trim END
4813 vim9script
4814
4815 class A
4816 static val: number = 10
4817 endclass
4818
4819 def T()
4820 var a = A.new()
4821 a.val = 20
4822 enddef
4823 T()
4824 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004825 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004826
4827 # Reading a class variable using an object at function level
4828 lines =<< trim END
4829 vim9script
4830
4831 class A
4832 static val: number = 10
4833 endclass
4834 def T()
4835 var a = A.new()
4836 var i = a.val
4837 enddef
4838 T()
4839 END
4840 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4841enddef
4842
4843" Test for using a duplicate class method and class variable in a child class
4844def Test_dup_class_member()
4845 # duplicate class variable, class method and overridden object method
4846 var lines =<< trim END
4847 vim9script
4848 class A
4849 static sval = 100
4850 static def Check()
4851 assert_equal(100, sval)
4852 enddef
4853 def GetVal(): number
4854 return sval
4855 enddef
4856 endclass
4857
4858 class B extends A
4859 static sval = 200
4860 static def Check()
4861 assert_equal(200, sval)
4862 enddef
4863 def GetVal(): number
4864 return sval
4865 enddef
4866 endclass
4867
4868 def T1(aa: A): number
4869 return aa.GetVal()
4870 enddef
4871
4872 def T2(bb: B): number
4873 return bb.GetVal()
4874 enddef
4875
4876 assert_equal(100, A.sval)
4877 assert_equal(200, B.sval)
4878 var a = A.new()
4879 assert_equal(100, a.GetVal())
4880 var b = B.new()
4881 assert_equal(200, b.GetVal())
4882 assert_equal(200, T1(b))
4883 assert_equal(200, T2(b))
4884 END
4885 v9.CheckSourceSuccess(lines)
4886
4887 # duplicate class variable and class method
4888 lines =<< trim END
4889 vim9script
4890 class A
4891 static sval = 100
4892 static def Check()
4893 assert_equal(100, sval)
4894 enddef
4895 def GetVal(): number
4896 return sval
4897 enddef
4898 endclass
4899
4900 class B extends A
4901 static sval = 200
4902 static def Check()
4903 assert_equal(200, sval)
4904 enddef
4905 endclass
4906
4907 def T1(aa: A): number
4908 return aa.GetVal()
4909 enddef
4910
4911 def T2(bb: B): number
4912 return bb.GetVal()
4913 enddef
4914
4915 assert_equal(100, A.sval)
4916 assert_equal(200, B.sval)
4917 var a = A.new()
4918 assert_equal(100, a.GetVal())
4919 var b = B.new()
4920 assert_equal(100, b.GetVal())
4921 assert_equal(100, T1(b))
4922 assert_equal(100, T2(b))
4923 END
4924 v9.CheckSourceSuccess(lines)
4925enddef
4926
4927" Test for calling an instance method using the class
4928def Test_instance_method_call_using_class()
4929 # Invoke an object method using a class in script context
4930 var lines =<< trim END
4931 vim9script
4932 class A
4933 def Foo()
4934 echo "foo"
4935 enddef
4936 endclass
4937 A.Foo()
4938 END
4939 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4940
4941 # Invoke an object method using a class in def function context
4942 lines =<< trim END
4943 vim9script
4944 class A
4945 def Foo()
4946 echo "foo"
4947 enddef
4948 endclass
4949 def T()
4950 A.Foo()
4951 enddef
4952 T()
4953 END
4954 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4955enddef
4956
4957" Test for duplicate class method and instance method
4958def Test_dup_classmethod_objmethod()
4959 # Duplicate instance method
4960 var lines =<< trim END
4961 vim9script
4962 class A
4963 static def Foo()
4964 enddef
4965 def Foo()
4966 enddef
4967 endclass
4968 END
4969 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
4970
4971 # Duplicate private instance method
4972 lines =<< trim END
4973 vim9script
4974 class A
4975 static def Foo()
4976 enddef
4977 def _Foo()
4978 enddef
4979 endclass
4980 END
4981 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
4982
4983 # Duplicate class method
4984 lines =<< trim END
4985 vim9script
4986 class A
4987 def Foo()
4988 enddef
4989 static def Foo()
4990 enddef
4991 endclass
4992 END
4993 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
4994
4995 # Duplicate private class method
4996 lines =<< trim END
4997 vim9script
4998 class A
4999 def Foo()
5000 enddef
5001 static def _Foo()
5002 enddef
5003 endclass
5004 END
5005 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5006
5007 # Duplicate private class and object method
5008 lines =<< trim END
5009 vim9script
5010 class A
5011 def _Foo()
5012 enddef
5013 static def _Foo()
5014 enddef
5015 endclass
5016 END
5017 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5018enddef
5019
5020" Test for an instance method access level comparison with parent instance
5021" methods.
5022def Test_instance_method_access_level()
5023 # Private method in subclass
5024 var lines =<< trim END
5025 vim9script
5026 class A
5027 def Foo()
5028 enddef
5029 endclass
5030 class B extends A
5031 endclass
5032 class C extends B
5033 def _Foo()
5034 enddef
5035 endclass
5036 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005037 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005038
5039 # Public method in subclass
5040 lines =<< trim END
5041 vim9script
5042 class A
5043 def _Foo()
5044 enddef
5045 endclass
5046 class B extends A
5047 endclass
5048 class C extends B
5049 def Foo()
5050 enddef
5051 endclass
5052 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005053 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005054enddef
5055
5056def Test_extend_empty_class()
5057 var lines =<< trim END
5058 vim9script
5059 class A
5060 endclass
5061 class B extends A
5062 endclass
5063 class C extends B
5064 public static rw_class_var = 1
5065 public this.rw_obj_var = 2
5066 static def ClassMethod(): number
5067 return 3
5068 enddef
5069 def ObjMethod(): number
5070 return 4
5071 enddef
5072 endclass
5073 assert_equal(1, C.rw_class_var)
5074 assert_equal(3, C.ClassMethod())
5075 var c = C.new()
5076 assert_equal(2, c.rw_obj_var)
5077 assert_equal(4, c.ObjMethod())
5078 END
5079 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005080enddef
5081
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005082" A interface cannot have a static variable or a static method or a private
5083" variable or a private method
5084def Test_interface_with_unsupported_members()
5085 var lines =<< trim END
5086 vim9script
5087 interface A
5088 static num: number
5089 endinterface
5090 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005091 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005092
5093 lines =<< trim END
5094 vim9script
5095 interface A
5096 static _num: number
5097 endinterface
5098 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005099 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005100
5101 lines =<< trim END
5102 vim9script
5103 interface A
5104 public static num: number
5105 endinterface
5106 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005107 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005108
5109 lines =<< trim END
5110 vim9script
5111 interface A
5112 public static _num: number
5113 endinterface
5114 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005115 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005116
5117 lines =<< trim END
5118 vim9script
5119 interface A
5120 static def Foo(d: dict<any>): list<string>
5121 endinterface
5122 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005123 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005124
5125 lines =<< trim END
5126 vim9script
5127 interface A
5128 static def _Foo(d: dict<any>): list<string>
5129 endinterface
5130 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005131 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005132
5133 lines =<< trim END
5134 vim9script
5135 interface A
5136 this._Foo: list<string>
5137 endinterface
5138 END
5139 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface')
5140
5141 lines =<< trim END
5142 vim9script
5143 interface A
5144 def _Foo(d: dict<any>): list<string>
5145 endinterface
5146 END
5147 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface')
5148enddef
5149
5150" Test for extending an interface
5151def Test_extend_interface()
5152 var lines =<< trim END
5153 vim9script
5154 interface A
5155 this.var1: list<string>
5156 def Foo()
5157 endinterface
5158 interface B extends A
5159 public this.var2: dict<string>
5160 def Bar()
5161 endinterface
5162 class C implements A, B
5163 this.var1 = [1, 2]
5164 def Foo()
5165 enddef
5166 public this.var2 = {a: '1'}
5167 def Bar()
5168 enddef
5169 endclass
5170 END
5171 v9.CheckSourceSuccess(lines)
5172
5173 lines =<< trim END
5174 vim9script
5175 interface A
5176 def Foo()
5177 endinterface
5178 interface B extends A
5179 public this.var2: dict<string>
5180 endinterface
5181 class C implements A, B
5182 public this.var2 = {a: '1'}
5183 endclass
5184 END
5185 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented')
5186
5187 lines =<< trim END
5188 vim9script
5189 interface A
5190 def Foo()
5191 endinterface
5192 interface B extends A
5193 public this.var2: dict<string>
5194 endinterface
5195 class C implements A, B
5196 def Foo()
5197 enddef
5198 endclass
5199 END
5200 v9.CheckSourceFailure(lines, 'E1348: Member "var2" of interface "B" is not implemented')
5201
5202 # interface cannot extend a class
5203 lines =<< trim END
5204 vim9script
5205 class A
5206 endclass
5207 interface B extends A
5208 endinterface
5209 END
5210 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5211
5212 # class cannot extend an interface
5213 lines =<< trim END
5214 vim9script
5215 interface A
5216 endinterface
5217 class B extends A
5218 endclass
5219 END
5220 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5221
5222 # interface cannot implement another interface
5223 lines =<< trim END
5224 vim9script
5225 interface A
5226 endinterface
5227 interface B implements A
5228 endinterface
5229 END
5230 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"')
5231
5232 # interface cannot extend multiple interfaces
5233 lines =<< trim END
5234 vim9script
5235 interface A
5236 endinterface
5237 interface B
5238 endinterface
5239 interface C extends A, B
5240 endinterface
5241 END
5242 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B')
5243
5244 # Variable type in an extended interface is of different type
5245 lines =<< trim END
5246 vim9script
5247 interface A
5248 this.val1: number
5249 endinterface
5250 interface B extends A
5251 this.val2: string
5252 endinterface
5253 interface C extends B
5254 this.val1: string
5255 this.val2: number
5256 endinterface
5257 END
5258 v9.CheckSourceFailure(lines, 'E1382: Member "val1": type mismatch, expected number but got string')
5259enddef
5260
5261" Test for a child class implementing an interface when some of the methods are
5262" defined in the parent class.
5263def Test_child_class_implements_interface()
5264 var lines =<< trim END
5265 vim9script
5266
5267 interface Intf
5268 def F1(): list<list<number>>
5269 def F2(): list<list<number>>
5270 def F3(): list<list<number>>
5271 this.var1: list<dict<number>>
5272 this.var2: list<dict<number>>
5273 this.var3: list<dict<number>>
5274 endinterface
5275
5276 class A
5277 def A1()
5278 enddef
5279 def F3(): list<list<number>>
5280 return [[3]]
5281 enddef
5282 this.v1: list<list<number>> = [[0]]
5283 this.var3 = [{c: 30}]
5284 endclass
5285
5286 class B extends A
5287 def B1()
5288 enddef
5289 def F2(): list<list<number>>
5290 return [[2]]
5291 enddef
5292 this.v2: list<list<number>> = [[0]]
5293 this.var2 = [{b: 20}]
5294 endclass
5295
5296 class C extends B implements Intf
5297 def C1()
5298 enddef
5299 def F1(): list<list<number>>
5300 return [[1]]
5301 enddef
5302 this.v3: list<list<number>> = [[0]]
5303 this.var1 = [{a: 10}]
5304 endclass
5305
5306 def T(if: Intf)
5307 assert_equal([[1]], if.F1())
5308 assert_equal([[2]], if.F2())
5309 assert_equal([[3]], if.F3())
5310 assert_equal([{a: 10}], if.var1)
5311 assert_equal([{b: 20}], if.var2)
5312 assert_equal([{c: 30}], if.var3)
5313 enddef
5314
5315 var c = C.new()
5316 T(c)
5317 assert_equal([[1]], c.F1())
5318 assert_equal([[2]], c.F2())
5319 assert_equal([[3]], c.F3())
5320 assert_equal([{a: 10}], c.var1)
5321 assert_equal([{b: 20}], c.var2)
5322 assert_equal([{c: 30}], c.var3)
5323 END
5324 v9.CheckSourceSuccess(lines)
5325
5326 # One of the interface methods is not found
5327 lines =<< trim END
5328 vim9script
5329
5330 interface Intf
5331 def F1()
5332 def F2()
5333 def F3()
5334 endinterface
5335
5336 class A
5337 def A1()
5338 enddef
5339 endclass
5340
5341 class B extends A
5342 def B1()
5343 enddef
5344 def F2()
5345 enddef
5346 endclass
5347
5348 class C extends B implements Intf
5349 def C1()
5350 enddef
5351 def F1()
5352 enddef
5353 endclass
5354 END
5355 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented')
5356
5357 # One of the interface methods is of different type
5358 lines =<< trim END
5359 vim9script
5360
5361 interface Intf
5362 def F1()
5363 def F2()
5364 def F3()
5365 endinterface
5366
5367 class A
5368 def F3(): number
5369 return 0
5370 enddef
5371 def A1()
5372 enddef
5373 endclass
5374
5375 class B extends A
5376 def B1()
5377 enddef
5378 def F2()
5379 enddef
5380 endclass
5381
5382 class C extends B implements Intf
5383 def C1()
5384 enddef
5385 def F1()
5386 enddef
5387 endclass
5388 END
5389 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number')
5390
5391 # One of the interface variables is not present
5392 lines =<< trim END
5393 vim9script
5394
5395 interface Intf
5396 this.var1: list<dict<number>>
5397 this.var2: list<dict<number>>
5398 this.var3: list<dict<number>>
5399 endinterface
5400
5401 class A
5402 this.v1: list<list<number>> = [[0]]
5403 endclass
5404
5405 class B extends A
5406 this.v2: list<list<number>> = [[0]]
5407 this.var2 = [{b: 20}]
5408 endclass
5409
5410 class C extends B implements Intf
5411 this.v3: list<list<number>> = [[0]]
5412 this.var1 = [{a: 10}]
5413 endclass
5414 END
5415 v9.CheckSourceFailure(lines, 'E1348: Member "var3" of interface "Intf" is not implemented')
5416
5417 # One of the interface variables is of different type
5418 lines =<< trim END
5419 vim9script
5420
5421 interface Intf
5422 this.var1: list<dict<number>>
5423 this.var2: list<dict<number>>
5424 this.var3: list<dict<number>>
5425 endinterface
5426
5427 class A
5428 this.v1: list<list<number>> = [[0]]
5429 this.var3: list<dict<string>>
5430 endclass
5431
5432 class B extends A
5433 this.v2: list<list<number>> = [[0]]
5434 this.var2 = [{b: 20}]
5435 endclass
5436
5437 class C extends B implements Intf
5438 this.v3: list<list<number>> = [[0]]
5439 this.var1 = [{a: 10}]
5440 endclass
5441 END
5442 v9.CheckSourceFailure(lines, 'E1382: Member "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>')
5443enddef
5444
5445" Test for extending an interface with duplicate variables and methods
5446def Test_interface_extends_with_dup_members()
5447 var lines =<< trim END
5448 vim9script
5449 interface A
5450 this.n1: number
5451 def Foo1(): number
5452 endinterface
5453 interface B extends A
5454 this.n2: number
5455 this.n1: number
5456 def Foo2(): number
5457 def Foo1(): number
5458 endinterface
5459 class C implements B
5460 this.n1 = 10
5461 this.n2 = 20
5462 def Foo1(): number
5463 return 30
5464 enddef
5465 def Foo2(): number
5466 return 40
5467 enddef
5468 endclass
5469 def T1(a: A)
5470 assert_equal(10, a.n1)
5471 assert_equal(30, a.Foo1())
5472 enddef
5473 def T2(b: B)
5474 assert_equal(10, b.n1)
5475 assert_equal(20, b.n2)
5476 assert_equal(30, b.Foo1())
5477 assert_equal(40, b.Foo2())
5478 enddef
5479 var c = C.new()
5480 T1(c)
5481 T2(c)
5482 END
5483 v9.CheckSourceSuccess(lines)
5484enddef
5485
5486" Test for using "any" type for a variable in a sub-class while it has a
5487" concrete type in the interface
5488def Test_implements_using_var_type_any()
5489 var lines =<< trim END
5490 vim9script
5491 interface A
5492 this.val: list<dict<string>>
5493 endinterface
5494 class B implements A
5495 this.val = [{a: '1'}, {b: '2'}]
5496 endclass
5497 var b = B.new()
5498 assert_equal([{a: '1'}, {b: '2'}], b.val)
5499 END
5500 v9.CheckSourceSuccess(lines)
5501
5502 # initialize instance variable using a different type
5503 lines =<< trim END
5504 vim9script
5505 interface A
5506 this.val: list<dict<string>>
5507 endinterface
5508 class B implements A
5509 this.val = {a: 1, b: 2}
5510 endclass
5511 var b = B.new()
5512 END
5513 v9.CheckSourceFailure(lines, 'E1382: Member "val": type mismatch, expected list<dict<string>> but got dict<number>')
5514enddef
5515
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005516" Test for assigning to a member variable in a nested class
5517def Test_nested_object_assignment()
5518 var lines =<< trim END
5519 vim9script
5520
5521 class A
5522 this.value: number
5523 endclass
5524
5525 class B
5526 this.a: A = A.new()
5527 endclass
5528
5529 class C
5530 this.b: B = B.new()
5531 endclass
5532
5533 class D
5534 this.c: C = C.new()
5535 endclass
5536
5537 def T(da: D)
5538 da.c.b.a.value = 10
5539 enddef
5540
5541 var d = D.new()
5542 T(d)
5543 END
5544 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "value"')
5545enddef
5546
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02005547" Test for calling methods using a null object
5548def Test_null_object_method_call()
5549 # Calling a object method using a null object in script context
5550 var lines =<< trim END
5551 vim9script
5552
5553 class C
5554 def Foo()
5555 assert_report('This method should not be executed')
5556 enddef
5557 endclass
5558
5559 var o: C
5560 o.Foo()
5561 END
5562 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
5563
5564 # Calling a object method using a null object in def function context
5565 lines =<< trim END
5566 vim9script
5567
5568 class C
5569 def Foo()
5570 assert_report('This method should not be executed')
5571 enddef
5572 endclass
5573
5574 def T()
5575 var o: C
5576 o.Foo()
5577 enddef
5578 T()
5579 END
5580 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5581
5582 # Calling a object method through another class method using a null object in
5583 # script context
5584 lines =<< trim END
5585 vim9script
5586
5587 class C
5588 def Foo()
5589 assert_report('This method should not be executed')
5590 enddef
5591
5592 static def Bar(o_any: any)
5593 var o_typed: C = o_any
5594 o_typed.Foo()
5595 enddef
5596 endclass
5597
5598 var o: C
5599 C.Bar(o)
5600 END
5601 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5602
5603 # Calling a object method through another class method using a null object in
5604 # def function context
5605 lines =<< trim END
5606 vim9script
5607
5608 class C
5609 def Foo()
5610 assert_report('This method should not be executed')
5611 enddef
5612
5613 static def Bar(o_any: any)
5614 var o_typed: C = o_any
5615 o_typed.Foo()
5616 enddef
5617 endclass
5618
5619 def T()
5620 var o: C
5621 C.Bar(o)
5622 enddef
5623 T()
5624 END
5625 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5626enddef
5627
5628" Test for using a dict as an object member
5629def Test_dict_object_member()
5630 var lines =<< trim END
5631 vim9script
5632
5633 class Context
5634 public this.state: dict<number> = {}
5635 def GetState(): dict<number>
5636 return this.state
5637 enddef
5638 endclass
5639
5640 var ctx = Context.new()
5641 ctx.state->extend({a: 1})
5642 ctx.state['b'] = 2
5643 assert_equal({a: 1, b: 2}, ctx.GetState())
5644
5645 def F()
5646 ctx.state['c'] = 3
5647 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
5648 enddef
5649 F()
5650 assert_equal(3, ctx.state.c)
5651 ctx.state.c = 4
5652 assert_equal(4, ctx.state.c)
5653 END
5654 v9.CheckSourceSuccess(lines)
5655enddef
5656
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005657" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker