blob: 763b5a539b958eb69d4f054888ca8640da4edd35 [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()
616 END
617 v9.CheckSourceSuccess(lines)
618enddef
619
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000620def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200621 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000622 var lines =<< trim END
623 vim9script
624
625 class Foo
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200626 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000627
628 def Add(n: number)
629 this.x += n
630 enddef
631 endclass
632
633 var f = Foo.new(3)
634 f.Add(17)
635 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100636
637 def AddToFoo(obj: Foo)
638 obj.x += 3
639 enddef
640
641 AddToFoo(f)
642 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000643 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200644 v9.CheckSourceSuccess(lines)
Ernie Rael18143d32023-09-04 22:30:41 +0200645
646 # do the same thing, but through an interface
647 lines =<< trim END
648 vim9script
649
650 interface I
651 public this.x: number
652 endinterface
653
654 class Foo implements I
655 public this.x: number
656
657 def Add(n: number)
658 var i: I = this
659 i.x += n
660 enddef
661 endclass
662
663 var f = Foo.new(3)
664 f.Add(17)
665 assert_equal(20, f.x)
666
667 def AddToFoo(i: I)
668 i.x += 3
669 enddef
670
671 AddToFoo(f)
672 assert_equal(23, f.x)
673 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200674 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000675enddef
676
Bram Moolenaarf4508042023-01-15 16:54:57 +0000677def Test_list_of_objects()
678 var lines =<< trim END
679 vim9script
680
681 class Foo
682 def Add()
683 enddef
684 endclass
685
686 def ProcessList(fooList: list<Foo>)
687 for foo in fooList
688 foo.Add()
689 endfor
690 enddef
691
692 var l: list<Foo> = [Foo.new()]
693 ProcessList(l)
694 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200695 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000696enddef
697
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000698def Test_expr_after_using_object()
699 var lines =<< trim END
700 vim9script
701
702 class Something
703 this.label: string = ''
704 endclass
705
706 def Foo(): Something
707 var v = Something.new()
708 echo 'in Foo(): ' .. typename(v)
709 return v
710 enddef
711
712 Foo()
713 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200714 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000715enddef
716
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000717def Test_class_default_new()
718 var lines =<< trim END
719 vim9script
720
721 class TextPosition
722 this.lnum: number = 1
723 this.col: number = 1
724 endclass
725
726 var pos = TextPosition.new()
727 assert_equal(1, pos.lnum)
728 assert_equal(1, pos.col)
729
730 pos = TextPosition.new(v:none, v:none)
731 assert_equal(1, pos.lnum)
732 assert_equal(1, pos.col)
733
734 pos = TextPosition.new(3, 22)
735 assert_equal(3, pos.lnum)
736 assert_equal(22, pos.col)
737
738 pos = TextPosition.new(v:none, 33)
739 assert_equal(1, pos.lnum)
740 assert_equal(33, pos.col)
741 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200742 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000743
744 lines =<< trim END
745 vim9script
746 class Person
747 this.name: string
748 this.age: number = 42
749 this.education: string = "unknown"
750
751 def new(this.name, this.age = v:none, this.education = v:none)
752 enddef
753 endclass
754
755 var piet = Person.new("Piet")
756 assert_equal("Piet", piet.name)
757 assert_equal(42, piet.age)
758 assert_equal("unknown", piet.education)
759
760 var chris = Person.new("Chris", 4, "none")
761 assert_equal("Chris", chris.name)
762 assert_equal(4, chris.age)
763 assert_equal("none", chris.education)
764 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200765 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000766
767 lines =<< trim END
768 vim9script
769 class Person
770 this.name: string
771 this.age: number = 42
772 this.education: string = "unknown"
773
774 def new(this.name, this.age = v:none, this.education = v:none)
775 enddef
776 endclass
777
778 var missing = Person.new()
779 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200780 v9.CheckSourceFailure(lines, 'E119:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200781
782 # Using a specific value to initialize an instance variable in the new()
783 # method.
784 lines =<< trim END
785 vim9script
786 class A
787 this.val: string
788 def new(this.val = 'a')
789 enddef
790 endclass
791 END
792 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'")
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000793enddef
794
h-east2261c892023-08-16 21:49:54 +0900795def Test_class_new_with_object_member()
796 var lines =<< trim END
797 vim9script
798
799 class C
800 this.str: string
801 this.num: number
802 def new(this.str, this.num)
803 enddef
804 def newVals(this.str, this.num)
805 enddef
806 endclass
807
808 def Check()
809 try
810 var c = C.new('cats', 2)
811 assert_equal('cats', c.str)
812 assert_equal(2, c.num)
813
814 c = C.newVals('dogs', 4)
815 assert_equal('dogs', c.str)
816 assert_equal(4, c.num)
817 catch
818 assert_report($'Unexpected exception was caught: {v:exception}')
819 endtry
820 enddef
821
822 Check()
823 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200824 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900825
826 lines =<< trim END
827 vim9script
828
829 class C
830 this.str: string
831 this.num: number
832 def new(this.str, this.num)
833 enddef
834 endclass
835
836 def Check()
837 try
838 var c = C.new(1, 2)
839 catch
840 assert_report($'Unexpected exception was caught: {v:exception}')
841 endtry
842 enddef
843
844 Check()
845 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200846 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900847
848 lines =<< trim END
849 vim9script
850
851 class C
852 this.str: string
853 this.num: number
854 def newVals(this.str, this.num)
855 enddef
856 endclass
857
858 def Check()
859 try
860 var c = C.newVals('dogs', 'apes')
861 catch
862 assert_report($'Unexpected exception was caught: {v:exception}')
863 endtry
864 enddef
865
866 Check()
867 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200868 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900869enddef
870
Bram Moolenaar74e12742022-12-13 21:14:28 +0000871def Test_class_object_member_inits()
872 var lines =<< trim END
873 vim9script
874 class TextPosition
875 this.lnum: number
876 this.col = 1
877 this.addcol: number = 2
878 endclass
879
880 var pos = TextPosition.new()
881 assert_equal(0, pos.lnum)
882 assert_equal(1, pos.col)
883 assert_equal(2, pos.addcol)
884 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200885 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000886
887 lines =<< trim END
888 vim9script
889 class TextPosition
890 this.lnum
891 this.col = 1
892 endclass
893 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200894 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000895
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200896 # If the type is not specified for a member, then it should be set during
897 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000898 lines =<< trim END
899 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200900
901 var init_count = 0
902 def Init(): string
903 init_count += 1
904 return 'foo'
905 enddef
906
907 class A
908 this.str1 = Init()
909 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000910 this.col = 1
911 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200912
913 assert_equal(init_count, 0)
914 var a = A.new()
915 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000916 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200917 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200918
919 # Test for initializing an object member with an unknown variable/type
920 lines =<< trim END
921 vim9script
922 class A
923 this.value = init_val
924 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200925 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200926 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200927 v9.CheckSourceFailure(lines, 'E1001:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200928
929 # Test for initializing an object member with an special type
930 lines =<< trim END
931 vim9script
932 class A
933 this.value: void
934 endclass
935 END
936 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object member: void')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000937enddef
938
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200939" Test for instance variable access
940def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +0000941 var lines =<< trim END
942 vim9script
943 class Triple
944 this._one = 1
945 this.two = 2
946 public this.three = 3
947
948 def GetOne(): number
949 return this._one
950 enddef
951 endclass
952
953 var trip = Triple.new()
954 assert_equal(1, trip.GetOne())
955 assert_equal(2, trip.two)
956 assert_equal(3, trip.three)
957 assert_fails('echo trip._one', 'E1333')
958
959 assert_fails('trip._one = 11', 'E1333')
960 assert_fails('trip.two = 22', 'E1335')
961 trip.three = 33
962 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +0000963
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200964 assert_fails('trip.four = 4', 'E1326')
Bram Moolenaard505d172022-12-18 21:42:55 +0000965 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200966 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +0000967
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200968 # Test for a public member variable name beginning with an underscore
969 lines =<< trim END
970 vim9script
971 class A
972 public this._val = 10
973 endclass
974 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200975 v9.CheckSourceFailure(lines, 'E1332:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200976
Bram Moolenaar590162c2022-12-24 21:24:06 +0000977 lines =<< trim END
978 vim9script
979
980 class MyCar
981 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +0000982 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +0000983
984 def new(make_arg: string)
985 this.make = make_arg
986 enddef
987
988 def GetMake(): string
989 return $"make = {this.make}"
990 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +0000991 def GetAge(): number
992 return this.age
993 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +0000994 endclass
995
996 var c = MyCar.new("abc")
997 assert_equal('make = abc', c.GetMake())
998
999 c = MyCar.new("def")
1000 assert_equal('make = def', c.GetMake())
1001
1002 var c2 = MyCar.new("123")
1003 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +00001004
1005 def CheckCar()
1006 assert_equal("make = def", c.GetMake())
1007 assert_equal(5, c.GetAge())
1008 enddef
1009 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001010 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001011 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001012
1013 lines =<< trim END
1014 vim9script
1015
1016 class MyCar
1017 this.make: string
1018
1019 def new(make_arg: string)
1020 this.make = make_arg
1021 enddef
1022 endclass
1023
1024 var c = MyCar.new("abc")
1025 var c = MyCar.new("def")
1026 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001027 v9.CheckSourceFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +00001028
1029 lines =<< trim END
1030 vim9script
1031
1032 class Foo
1033 this.x: list<number> = []
1034
1035 def Add(n: number): any
1036 this.x->add(n)
1037 return this
1038 enddef
1039 endclass
1040
1041 echo Foo.new().Add(1).Add(2).x
1042 echo Foo.new().Add(1).Add(2)
1043 .x
1044 echo Foo.new().Add(1)
1045 .Add(2).x
1046 echo Foo.new()
1047 .Add(1).Add(2).x
1048 echo Foo.new()
1049 .Add(1)
1050 .Add(2)
1051 .x
1052 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001053 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001054
1055 # Test for "public" cannot be abbreviated
1056 lines =<< trim END
1057 vim9script
1058 class Something
1059 pub this.val = 1
1060 endclass
1061 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001062 v9.CheckSourceFailure(lines, 'E1065:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001063
1064 # Test for "public" keyword must be followed by "this" or "static".
1065 lines =<< trim END
1066 vim9script
1067 class Something
1068 public val = 1
1069 endclass
1070 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001071 v9.CheckSourceFailure(lines, 'E1331:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001072
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001073 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001074 lines =<< trim END
1075 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001076 class A
1077 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001078 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001079 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001080 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001081 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001082
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001083 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001084 lines =<< trim END
1085 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001086 class A
1087 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001088 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001089 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001090 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001091 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1092
1093 # Modify a instance variable using the class name in a def function
1094 lines =<< trim END
1095 vim9script
1096 class A
1097 public this.val = 1
1098 endclass
1099 def T()
1100 A.val = 1
1101 enddef
1102 T()
1103 END
1104 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1105
1106 # Read a instance variable using the class name in a def function
1107 lines =<< trim END
1108 vim9script
1109 class A
1110 public this.val = 1
1111 endclass
1112 def T()
1113 var i = A.val
1114 enddef
1115 T()
1116 END
1117 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Ernie Raelcf138d42023-09-06 20:45:03 +02001118
1119 # Access from child class extending a class:
1120 lines =<< trim END
1121 vim9script
1122 class A
1123 this.ro_obj_var = 10
1124 public this.rw_obj_var = 20
1125 this._priv_obj_var = 30
Ernie Raelcf138d42023-09-06 20:45:03 +02001126 endclass
1127
1128 class B extends A
1129 def Foo()
1130 var x: number
1131 x = this.ro_obj_var
1132 this.ro_obj_var = 0
1133 x = this.rw_obj_var
1134 this.rw_obj_var = 0
1135 x = this._priv_obj_var
1136 this._priv_obj_var = 0
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001137 enddef
1138 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001139
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001140 var b = B.new()
1141 b.Foo()
1142 END
1143 v9.CheckSourceSuccess(lines)
1144enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001145
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001146" Test for class variable access
1147def Test_class_variable_access()
1148 # Test for "static" cannot be abbreviated
1149 var lines =<< trim END
1150 vim9script
1151 class Something
1152 stat this.val = 1
1153 endclass
1154 END
1155 v9.CheckSourceFailure(lines, 'E1065:')
1156
1157 # Test for "static" cannot be followed by "this".
1158 lines =<< trim END
1159 vim9script
1160 class Something
1161 static this.val = 1
1162 endclass
1163 END
1164 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
1165
1166 # Test for "static" cannot be followed by "public".
1167 lines =<< trim END
1168 vim9script
1169 class Something
1170 static public val = 1
1171 endclass
1172 END
1173 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
1174
1175 # A readonly class variable cannot be modified from a child class
1176 lines =<< trim END
1177 vim9script
1178 class A
1179 static ro_class_var = 40
1180 endclass
1181
1182 class B extends A
1183 def Foo()
1184 A.ro_class_var = 50
1185 enddef
1186 endclass
1187
1188 var b = B.new()
1189 b.Foo()
1190 END
1191 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "ro_class_var"')
1192
1193 # A private class variable cannot be accessed from a child class
1194 lines =<< trim END
1195 vim9script
1196 class A
1197 static _priv_class_var = 60
1198 endclass
1199
1200 class B extends A
1201 def Foo()
1202 var i = A._priv_class_var
1203 enddef
1204 endclass
1205
1206 var b = B.new()
1207 b.Foo()
1208 END
1209 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1210
1211 # A private class variable cannot be modified from a child class
1212 lines =<< trim END
1213 vim9script
1214 class A
1215 static _priv_class_var = 60
1216 endclass
1217
1218 class B extends A
1219 def Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001220 A._priv_class_var = 0
1221 enddef
1222 endclass
1223
1224 var b = B.new()
1225 b.Foo()
1226 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001227 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1228
1229 # Access from child class extending a class and from script context
1230 lines =<< trim END
1231 vim9script
1232 class A
1233 static ro_class_var = 10
1234 public static rw_class_var = 20
1235 static _priv_class_var = 30
1236 endclass
1237
1238 class B extends A
1239 def Foo()
1240 var x: number
1241 x = A.ro_class_var
1242 assert_equal(10, x)
1243 x = A.rw_class_var
1244 assert_equal(25, x)
1245 A.rw_class_var = 20
1246 assert_equal(20, A.rw_class_var)
1247 enddef
1248 endclass
1249
1250 assert_equal(10, A.ro_class_var)
1251 assert_equal(20, A.rw_class_var)
1252 A.rw_class_var = 25
1253 assert_equal(25, A.rw_class_var)
1254 var b = B.new()
1255 b.Foo()
1256 END
1257 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001258enddef
1259
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001260def Test_class_object_compare()
1261 var class_lines =<< trim END
1262 vim9script
1263 class Item
1264 this.nr = 0
1265 this.name = 'xx'
1266 endclass
1267 END
1268
1269 # used at the script level and in a compiled function
1270 var test_lines =<< trim END
1271 var i1 = Item.new()
1272 assert_equal(i1, i1)
1273 assert_true(i1 is i1)
1274 var i2 = Item.new()
1275 assert_equal(i1, i2)
1276 assert_false(i1 is i2)
1277 var i3 = Item.new(0, 'xx')
1278 assert_equal(i1, i3)
1279
1280 var io1 = Item.new(1, 'xx')
1281 assert_notequal(i1, io1)
1282 var io2 = Item.new(0, 'yy')
1283 assert_notequal(i1, io2)
1284 END
1285
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001286 v9.CheckSourceSuccess(class_lines + test_lines)
1287 v9.CheckSourceSuccess(
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001288 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001289
1290 for op in ['>', '>=', '<', '<=', '=~', '!~']
1291 var op_lines = [
1292 'var i1 = Item.new()',
1293 'var i2 = Item.new()',
1294 'echo i1 ' .. op .. ' i2',
1295 ]
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001296 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
1297 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001298 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001299 endfor
1300enddef
1301
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001302def Test_object_type()
1303 var lines =<< trim END
1304 vim9script
1305
1306 class One
1307 this.one = 1
1308 endclass
1309 class Two
1310 this.two = 2
1311 endclass
1312 class TwoMore extends Two
1313 this.more = 9
1314 endclass
1315
1316 var o: One = One.new()
1317 var t: Two = Two.new()
1318 var m: TwoMore = TwoMore.new()
1319 var tm: Two = TwoMore.new()
1320
1321 t = m
1322 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001323 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001324
1325 lines =<< trim END
1326 vim9script
1327
1328 class One
1329 this.one = 1
1330 endclass
1331 class Two
1332 this.two = 2
1333 endclass
1334
1335 var o: One = Two.new()
1336 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001337 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001338
1339 lines =<< trim END
1340 vim9script
1341
1342 interface One
1343 def GetMember(): number
1344 endinterface
1345 class Two implements One
1346 this.one = 1
1347 def GetMember(): number
1348 return this.one
1349 enddef
1350 endclass
1351
1352 var o: One = Two.new(5)
1353 assert_equal(5, o.GetMember())
1354 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001355 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001356
1357 lines =<< trim END
1358 vim9script
1359
1360 class Num
1361 this.n: number = 0
1362 endclass
1363
1364 def Ref(name: string): func(Num): Num
1365 return (arg: Num): Num => {
1366 return eval(name)(arg)
1367 }
1368 enddef
1369
1370 const Fn = Ref('Double')
1371 var Double = (m: Num): Num => Num.new(m.n * 2)
1372
1373 echo Fn(Num.new(4))
1374 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001375 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001376enddef
1377
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001378def Test_class_member()
1379 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001380 var lines =<< trim END
1381 vim9script
1382 class TextPos
1383 this.lnum = 1
1384 this.col = 1
1385 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001386 static _secret = 7
1387 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001388
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001389 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001390 counter += nr
1391 enddef
1392 endclass
1393
1394 assert_equal(0, TextPos.counter)
1395 TextPos.AddToCounter(3)
1396 assert_equal(3, TextPos.counter)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001397 assert_fails('echo TextPos.noSuchMember', 'E1337:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001398
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001399 def GetCounter(): number
1400 return TextPos.counter
1401 enddef
1402 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001403
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001404 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001405 assert_fails('TextPos.counter = 5', 'E1335:')
1406 assert_fails('TextPos.counter += 5', 'E1335:')
1407
1408 assert_fails('echo TextPos._secret', 'E1333:')
1409 assert_fails('TextPos._secret = 8', 'E1333:')
1410
1411 assert_equal(42, TextPos.anybody)
1412 TextPos.anybody = 12
1413 assert_equal(12, TextPos.anybody)
1414 TextPos.anybody += 5
1415 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001416 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001417 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001418
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001419 # example in the help
1420 lines =<< trim END
1421 vim9script
1422 class OtherThing
1423 this.size: number
1424 static totalSize: number
1425
1426 def new(this.size)
1427 totalSize += this.size
1428 enddef
1429 endclass
1430 assert_equal(0, OtherThing.totalSize)
1431 var to3 = OtherThing.new(3)
1432 assert_equal(3, OtherThing.totalSize)
1433 var to7 = OtherThing.new(7)
1434 assert_equal(10, OtherThing.totalSize)
1435 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001436 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001437
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001438 # using static class member twice
1439 lines =<< trim END
1440 vim9script
1441
1442 class HTML
1443 static author: string = 'John Doe'
1444
1445 static def MacroSubstitute(s: string): string
1446 return substitute(s, '{{author}}', author, 'gi')
1447 enddef
1448 endclass
1449
1450 assert_equal('some text', HTML.MacroSubstitute('some text'))
1451 assert_equal('some text', HTML.MacroSubstitute('some text'))
1452 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001453 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001454
Bram Moolenaar62a69232023-01-24 15:07:04 +00001455 # access private member in lambda
1456 lines =<< trim END
1457 vim9script
1458
1459 class Foo
1460 this._x: number = 0
1461
1462 def Add(n: number): number
1463 const F = (): number => this._x + n
1464 return F()
1465 enddef
1466 endclass
1467
1468 var foo = Foo.new()
1469 assert_equal(5, foo.Add(5))
1470 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001471 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001472
h-east2bd6a092023-05-19 19:01:17 +01001473 # access private member in lambda body
1474 lines =<< trim END
1475 vim9script
1476
1477 class Foo
1478 this._x: number = 6
1479
1480 def Add(n: number): number
1481 var Lam = () => {
1482 this._x = this._x + n
1483 }
1484 Lam()
1485 return this._x
1486 enddef
1487 endclass
1488
1489 var foo = Foo.new()
1490 assert_equal(13, foo.Add(7))
1491 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001492 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001493
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001494 # check shadowing
1495 lines =<< trim END
1496 vim9script
1497
1498 class Some
1499 static count = 0
1500 def Method(count: number)
1501 echo count
1502 enddef
1503 endclass
1504
1505 var s = Some.new()
1506 s.Method(7)
1507 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001508 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001509
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001510 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001511 lines =<< trim END
1512 vim9script
1513
1514 class Some
1515 static count = 0
1516 def Method(arg: number)
1517 var count = 3
1518 echo arg count
1519 enddef
1520 endclass
1521
1522 var s = Some.new()
1523 s.Method(7)
1524 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001525 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001526
1527 # Test for using an invalid type for a member variable
1528 lines =<< trim END
1529 vim9script
1530 class A
1531 this.val: xxx
1532 endclass
1533 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001534 v9.CheckSourceFailure(lines, 'E1010:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001535
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001536 # Test for setting a member on a null object
1537 lines =<< trim END
1538 vim9script
1539 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001540 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001541 endclass
1542
1543 def F()
1544 var obj: A
1545 obj.val = ""
1546 enddef
1547 F()
1548 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001549 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001550
1551 # Test for accessing a member on a null object
1552 lines =<< trim END
1553 vim9script
1554 class A
1555 this.val: string
1556 endclass
1557
1558 def F()
1559 var obj: A
1560 echo obj.val
1561 enddef
1562 F()
1563 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001564 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001565
1566 # Test for setting a member on a null object, at script level
1567 lines =<< trim END
1568 vim9script
1569 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001570 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001571 endclass
1572
1573 var obj: A
1574 obj.val = ""
1575 END
1576 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001577 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001578
1579 # Test for accessing a member on a null object, at script level
1580 lines =<< trim END
1581 vim9script
1582 class A
1583 this.val: string
1584 endclass
1585
1586 var obj: A
1587 echo obj.val
1588 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001589 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001590
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001591 # Test for no space before or after the '=' when initializing a member
1592 # variable
1593 lines =<< trim END
1594 vim9script
1595 class A
1596 this.val: number= 10
1597 endclass
1598 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001599 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001600 lines =<< trim END
1601 vim9script
1602 class A
1603 this.val: number =10
1604 endclass
1605 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001606 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001607
1608 # Access a non-existing member
1609 lines =<< trim END
1610 vim9script
1611 class A
1612 endclass
1613 var a = A.new()
1614 var v = a.bar
1615 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001616 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": bar')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001617enddef
1618
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001619func Test_class_garbagecollect()
1620 let lines =<< trim END
1621 vim9script
1622
1623 class Point
1624 this.p = [2, 3]
1625 static pl = ['a', 'b']
1626 static pd = {a: 'a', b: 'b'}
1627 endclass
1628
1629 echo Point.pl Point.pd
1630 call test_garbagecollect_now()
1631 echo Point.pl Point.pd
1632 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001633 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001634
1635 let lines =<< trim END
1636 vim9script
1637
1638 interface View
1639 endinterface
1640
1641 class Widget
1642 this.view: View
1643 endclass
1644
1645 class MyView implements View
1646 this.widget: Widget
1647
1648 def new()
1649 # this will result in a circular reference to this object
1650 this.widget = Widget.new(this)
1651 enddef
1652 endclass
1653
1654 var view = MyView.new()
1655
1656 # overwrite "view", will be garbage-collected next
1657 view = MyView.new()
1658 test_garbagecollect_now()
1659 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001660 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001661endfunc
1662
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001663" Test interface garbage collection
1664func Test_interface_garbagecollect()
1665 let lines =<< trim END
1666 vim9script
1667
1668 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001669 this.ro_obj_var: number
1670 public this.rw_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001671
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001672 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001673 endinterface
1674
1675 class A implements I
1676 static ro_class_var: number = 10
1677 public static rw_class_var: number = 20
1678 static _priv_class_var: number = 30
1679 this.ro_obj_var: number = 40
1680 public this.rw_obj_var: number = 50
1681 this._priv_obj_var: number = 60
1682
1683 static def _ClassBar(): number
1684 return _priv_class_var
1685 enddef
1686
1687 static def ClassFoo(): number
1688 return ro_class_var + rw_class_var + A._ClassBar()
1689 enddef
1690
1691 def _ObjBar(): number
1692 return this._priv_obj_var
1693 enddef
1694
1695 def ObjFoo(): number
1696 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1697 enddef
1698 endclass
1699
1700 assert_equal(60, A.ClassFoo())
1701 var o = A.new()
1702 assert_equal(150, o.ObjFoo())
1703 test_garbagecollect_now()
1704 assert_equal(60, A.ClassFoo())
1705 assert_equal(150, o.ObjFoo())
1706 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001707 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001708endfunc
1709
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001710def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001711 var lines =<< trim END
1712 vim9script
1713 class Value
1714 this.value = 0
1715 static objects = 0
1716
1717 def new(v: number)
1718 this.value = v
1719 ++objects
1720 enddef
1721
1722 static def GetCount(): number
1723 return objects
1724 enddef
1725 endclass
1726
1727 assert_equal(0, Value.GetCount())
1728 var v1 = Value.new(2)
1729 assert_equal(1, Value.GetCount())
1730 var v2 = Value.new(7)
1731 assert_equal(2, Value.GetCount())
1732 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001733 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001734
1735 # Test for cleaning up after a class definition failure when using class
1736 # functions.
1737 lines =<< trim END
1738 vim9script
1739 class A
1740 static def Foo()
1741 enddef
1742 aaa
1743 endclass
1744 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001745 v9.CheckSourceFailure(lines, 'E1318:')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001746
1747 # Test for calling a class method from another class method without the class
1748 # name prefix.
1749 lines =<< trim END
1750 vim9script
1751 class A
1752 static myList: list<number> = [1]
1753 static def Foo(n: number)
1754 myList->add(n)
1755 enddef
1756 static def Bar()
1757 Foo(2)
1758 enddef
1759 def Baz()
1760 Foo(3)
1761 enddef
1762 endclass
1763 A.Bar()
1764 var a = A.new()
1765 a.Baz()
1766 assert_equal([1, 2, 3], A.myList)
1767 END
1768 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001769enddef
1770
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001771def Test_class_defcompile()
1772 var lines =<< trim END
1773 vim9script
1774
1775 class C
1776 def Fo(i: number): string
1777 return i
1778 enddef
1779 endclass
1780
1781 defcompile C.Fo
1782 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001783 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001784
1785 lines =<< trim END
1786 vim9script
1787
1788 class C
1789 static def Fc(): number
1790 return 'x'
1791 enddef
1792 endclass
1793
1794 defcompile C.Fc
1795 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001796 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001797
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001798 lines =<< trim END
1799 vim9script
1800
1801 class C
1802 static def new()
1803 enddef
1804 endclass
1805
1806 defcompile C.new
1807 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001808 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" function as static')
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001809
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001810 # Trying to compile a function using a non-existing class variable
1811 lines =<< trim END
1812 vim9script
1813 defcompile x.Foo()
1814 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001815 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001816
1817 # Trying to compile a function using a variable which is not a class
1818 lines =<< trim END
1819 vim9script
1820 var x: number
1821 defcompile x.Foo()
1822 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001823 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001824
1825 # Trying to compile a function without specifying the name
1826 lines =<< trim END
1827 vim9script
1828 class A
1829 endclass
1830 defcompile A.
1831 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001832 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001833
1834 # Trying to compile a non-existing class object member function
1835 lines =<< trim END
1836 vim9script
1837 class A
1838 endclass
1839 var a = A.new()
1840 defcompile a.Foo()
1841 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001842 v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001843enddef
1844
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001845def Test_class_object_to_string()
1846 var lines =<< trim END
1847 vim9script
1848 class TextPosition
1849 this.lnum = 1
1850 this.col = 22
1851 endclass
1852
1853 assert_equal("class TextPosition", string(TextPosition))
1854
1855 var pos = TextPosition.new()
1856 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1857 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001858 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001859enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001860
Bram Moolenaar554d0312023-01-05 19:59:18 +00001861def Test_interface_basics()
1862 var lines =<< trim END
1863 vim9script
1864 interface Something
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001865 this.ro_var: string
1866 public this.rw_var: list<number>
Bram Moolenaar554d0312023-01-05 19:59:18 +00001867 def GetCount(): number
1868 endinterface
1869 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001870 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001871
1872 lines =<< trim END
1873 interface SomethingWrong
1874 static count = 7
1875 endinterface
1876 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001877 v9.CheckSourceFailure(lines, 'E1342:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001878
1879 lines =<< trim END
1880 vim9script
1881
1882 interface Some
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001883 this.value: number
1884 def Method(value: number)
1885 endinterface
1886 END
h-east61378a12023-04-18 19:07:29 +01001887 # The argument name and the object member name are the same, but this is not a
1888 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001889 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001890
1891 lines =<< trim END
1892 vim9script
1893 interface somethingWrong
1894 static count = 7
1895 endinterface
1896 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001897 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001898
1899 lines =<< trim END
1900 vim9script
1901 interface SomethingWrong
1902 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001903 this.count = 7
Bram Moolenaar554d0312023-01-05 19:59:18 +00001904 def GetCount(): number
1905 endinterface
1906 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001907 v9.CheckSourceFailure(lines, 'E1344:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001908
1909 lines =<< trim END
1910 vim9script
1911 interface SomethingWrong
1912 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001913 this.count: number
Bram Moolenaar554d0312023-01-05 19:59:18 +00001914 def GetCount(): number
1915 return 5
1916 enddef
1917 endinterface
1918 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001919 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001920
1921 lines =<< trim END
1922 vim9script
1923 export interface EnterExit
1924 def Enter(): void
1925 def Exit(): void
1926 endinterface
1927 END
1928 writefile(lines, 'XdefIntf.vim', 'D')
1929
1930 lines =<< trim END
1931 vim9script
1932 import './XdefIntf.vim' as defIntf
1933 export def With(ee: defIntf.EnterExit, F: func)
1934 ee.Enter()
1935 try
1936 F()
1937 finally
1938 ee.Exit()
1939 endtry
1940 enddef
1941 END
1942 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00001943
1944 var imported =<< trim END
1945 vim9script
1946 export abstract class EnterExit
1947 def Enter(): void
1948 enddef
1949 def Exit(): void
1950 enddef
1951 endclass
1952 END
1953 writefile(imported, 'XdefIntf2.vim', 'D')
1954
1955 lines[1] = " import './XdefIntf2.vim' as defIntf"
1956 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001957enddef
1958
Bram Moolenaar94674f22023-01-06 18:42:20 +00001959def Test_class_implements_interface()
1960 var lines =<< trim END
1961 vim9script
1962
1963 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001964 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001965 def Method(nr: number)
1966 endinterface
1967
1968 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001969 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00001970 def Method(nr: number)
1971 echo nr
1972 enddef
1973 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001974
1975 interface Another
1976 this.member: string
1977 endinterface
1978
Bram Moolenaar83ae6152023-02-25 19:59:31 +00001979 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001980 this.member = 'abc'
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001981 this.count = 20
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001982 def Method(nr: number)
1983 echo nr
1984 enddef
1985 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00001986 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001987 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00001988
1989 lines =<< trim END
1990 vim9script
1991
1992 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001993 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001994 endinterface
1995
1996 class SomeImpl implements Some implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001997 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00001998 endclass
1999 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002000 v9.CheckSourceFailure(lines, 'E1350:')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002001
2002 lines =<< trim END
2003 vim9script
2004
2005 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002006 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002007 endinterface
2008
2009 class SomeImpl implements Some, Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002010 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002011 endclass
2012 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002013 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002014
2015 lines =<< trim END
2016 vim9script
2017
2018 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002019 this.counter: 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
2029 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002030 v9.CheckSourceFailure(lines, 'E1348: Member "counter" of interface "Some" is not implemented')
Bram Moolenaar94674f22023-01-06 18:42:20 +00002031
2032 lines =<< trim END
2033 vim9script
2034
2035 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002036 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002037 def Methods(nr: number)
2038 endinterface
2039
2040 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002041 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002042 def Method(nr: number)
2043 echo nr
2044 enddef
2045 endclass
2046 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002047 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002048
2049 # Check different order of members in class and interface works.
2050 lines =<< trim END
2051 vim9script
2052
2053 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002054 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002055 this.errpos: number
2056 endinterface
2057
2058 # order of members is opposite of interface
2059 class Failure implements Result
2060 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002061 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002062 endclass
2063
2064 def Test()
2065 var result: Result = Failure.new()
2066
2067 assert_equal('label', result.label)
2068 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002069
2070 result.label = 'different'
2071 assert_equal('different', result.label)
2072 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002073 enddef
2074
2075 Test()
2076 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002077 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002078
2079 # Interface name after "extends" doesn't end in a space or NUL character
2080 lines =<< trim END
2081 vim9script
2082 interface A
2083 endinterface
2084 class B extends A"
2085 endclass
2086 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002087 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002088
2089 # Trailing characters after a class name
2090 lines =<< trim END
2091 vim9script
2092 class A bbb
2093 endclass
2094 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002095 v9.CheckSourceFailure(lines, 'E488:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002096
2097 # using "implements" with a non-existing class
2098 lines =<< trim END
2099 vim9script
2100 class A implements B
2101 endclass
2102 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002103 v9.CheckSourceFailure(lines, 'E1346:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002104
2105 # using "implements" with a regular class
2106 lines =<< trim END
2107 vim9script
2108 class A
2109 endclass
2110 class B implements A
2111 endclass
2112 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002113 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002114
2115 # using "implements" with a variable
2116 lines =<< trim END
2117 vim9script
2118 var T: number = 10
2119 class A implements T
2120 endclass
2121 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002122 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002123
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002124 # implements should be followed by a white space
2125 lines =<< trim END
2126 vim9script
2127 interface A
2128 endinterface
2129 class B implements A;
2130 endclass
2131 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002132 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002133
LemonBoyc5d27442023-08-19 13:02:35 +02002134 lines =<< trim END
2135 vim9script
2136
2137 interface One
LemonBoyc5d27442023-08-19 13:02:35 +02002138 def IsEven(nr: number): bool
2139 endinterface
2140 class Two implements One
2141 def IsEven(nr: number): string
2142 enddef
2143 endclass
2144 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002145 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02002146
2147 lines =<< trim END
2148 vim9script
2149
2150 interface One
2151 def IsEven(nr: number): bool
2152 endinterface
2153 class Two implements One
2154 def IsEven(nr: bool): bool
2155 enddef
2156 endclass
2157 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002158 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02002159
2160 lines =<< trim END
2161 vim9script
2162
2163 interface One
2164 def IsEven(nr: number): bool
2165 endinterface
2166 class Two implements One
2167 def IsEven(nr: number, ...extra: list<number>): bool
2168 enddef
2169 endclass
2170 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002171 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 +02002172
2173 # access superclass interface members from subclass, mix variable order
2174 lines =<< trim END
2175 vim9script
2176
2177 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002178 public this.mvar1: number
2179 public this.mvar2: number
2180 endinterface
2181
2182 # NOTE: the order is swapped
2183 class A implements I1
2184 public this.mvar2: number
2185 public this.mvar1: number
2186 public static svar2: number
2187 public static svar1: number
2188 def new()
2189 svar1 = 11
2190 svar2 = 12
2191 this.mvar1 = 111
2192 this.mvar2 = 112
2193 enddef
2194 endclass
2195
2196 class B extends A
2197 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002198 this.mvar1 = 121
2199 this.mvar2 = 122
2200 enddef
2201 endclass
2202
2203 class C extends B
2204 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002205 this.mvar1 = 131
2206 this.mvar2 = 132
2207 enddef
2208 endclass
2209
Ernie Raelcf138d42023-09-06 20:45:03 +02002210 def F2(i: I1): list<number>
2211 return [ i.mvar1, i.mvar2 ]
2212 enddef
2213
2214 var oa = A.new()
2215 var ob = B.new()
2216 var oc = C.new()
2217
Ernie Raelcf138d42023-09-06 20:45:03 +02002218 assert_equal([111, 112], F2(oa))
2219 assert_equal([121, 122], F2(ob))
2220 assert_equal([131, 132], F2(oc))
2221 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002222 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002223
2224 # Access superclass interface members from subclass, mix variable order.
2225 # Two interfaces, one on A, one on B; each has both kinds of variables
2226 lines =<< trim END
2227 vim9script
2228
2229 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002230 public this.mvar1: number
2231 public this.mvar2: number
2232 endinterface
2233
2234 interface I2
Ernie Raelcf138d42023-09-06 20:45:03 +02002235 public this.mvar3: number
2236 public this.mvar4: number
2237 endinterface
2238
2239 class A implements I1
2240 public static svar1: number
2241 public static svar2: number
2242 public this.mvar1: number
2243 public this.mvar2: number
2244 def new()
2245 svar1 = 11
2246 svar2 = 12
2247 this.mvar1 = 111
2248 this.mvar2 = 112
2249 enddef
2250 endclass
2251
2252 class B extends A implements I2
2253 public static svar3: number
2254 public static svar4: number
2255 public this.mvar3: number
2256 public this.mvar4: number
2257 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002258 svar3 = 23
2259 svar4 = 24
2260 this.mvar1 = 121
2261 this.mvar2 = 122
2262 this.mvar3 = 123
2263 this.mvar4 = 124
2264 enddef
2265 endclass
2266
2267 class C extends B
2268 public static svar5: number
2269 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002270 svar5 = 1001
2271 this.mvar1 = 131
2272 this.mvar2 = 132
2273 this.mvar3 = 133
2274 this.mvar4 = 134
2275 enddef
2276 endclass
2277
Ernie Raelcf138d42023-09-06 20:45:03 +02002278 def F2(i: I1): list<number>
2279 return [ i.mvar1, i.mvar2 ]
2280 enddef
2281
Ernie Raelcf138d42023-09-06 20:45:03 +02002282 def F4(i: I2): list<number>
2283 return [ i.mvar3, i.mvar4 ]
2284 enddef
2285
Ernie Raelcf138d42023-09-06 20:45:03 +02002286 var oa = A.new()
2287 var ob = B.new()
2288 var oc = C.new()
2289
Ernie Raelcf138d42023-09-06 20:45:03 +02002290 assert_equal([[111, 112]], [F2(oa)])
2291 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2292 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002293 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002294 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002295enddef
2296
Bram Moolenaard0200c82023-01-28 15:19:40 +00002297def Test_call_interface_method()
2298 var lines =<< trim END
2299 vim9script
2300 interface Base
2301 def Enter(): void
2302 endinterface
2303
2304 class Child implements Base
2305 def Enter(): void
2306 g:result ..= 'child'
2307 enddef
2308 endclass
2309
2310 def F(obj: Base)
2311 obj.Enter()
2312 enddef
2313
2314 g:result = ''
2315 F(Child.new())
2316 assert_equal('child', g:result)
2317 unlet g:result
2318 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002319 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002320
2321 lines =<< trim END
2322 vim9script
2323 class Base
2324 def Enter(): void
2325 g:result ..= 'base'
2326 enddef
2327 endclass
2328
2329 class Child extends Base
2330 def Enter(): void
2331 g:result ..= 'child'
2332 enddef
2333 endclass
2334
2335 def F(obj: Base)
2336 obj.Enter()
2337 enddef
2338
2339 g:result = ''
2340 F(Child.new())
2341 assert_equal('child', g:result)
2342 unlet g:result
2343 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002344 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002345
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002346 # method of interface returns a value
2347 lines =<< trim END
2348 vim9script
2349 interface Base
2350 def Enter(): string
2351 endinterface
2352
2353 class Child implements Base
2354 def Enter(): string
2355 g:result ..= 'child'
2356 return "/resource"
2357 enddef
2358 endclass
2359
2360 def F(obj: Base)
2361 var r = obj.Enter()
2362 g:result ..= r
2363 enddef
2364
2365 g:result = ''
2366 F(Child.new())
2367 assert_equal('child/resource', g:result)
2368 unlet g:result
2369 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002370 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002371
2372 lines =<< trim END
2373 vim9script
2374 class Base
2375 def Enter(): string
2376 return null_string
2377 enddef
2378 endclass
2379
2380 class Child extends Base
2381 def Enter(): string
2382 g:result ..= 'child'
2383 return "/resource"
2384 enddef
2385 endclass
2386
2387 def F(obj: Base)
2388 var r = obj.Enter()
2389 g:result ..= r
2390 enddef
2391
2392 g:result = ''
2393 F(Child.new())
2394 assert_equal('child/resource', g:result)
2395 unlet g:result
2396 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002397 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002398
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002399 # No class that implements the interface.
2400 lines =<< trim END
2401 vim9script
2402
2403 interface IWithEE
2404 def Enter(): any
2405 def Exit(): void
2406 endinterface
2407
2408 def With1(ee: IWithEE, F: func)
2409 var r = ee.Enter()
2410 enddef
2411
2412 defcompile
2413 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002414 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002415enddef
2416
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002417def Test_class_used_as_type()
2418 var lines =<< trim END
2419 vim9script
2420
2421 class Point
2422 this.x = 0
2423 this.y = 0
2424 endclass
2425
2426 var p: Point
2427 p = Point.new(2, 33)
2428 assert_equal(2, p.x)
2429 assert_equal(33, p.y)
2430 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002431 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002432
2433 lines =<< trim END
2434 vim9script
2435
2436 interface HasX
2437 this.x: number
2438 endinterface
2439
2440 class Point implements HasX
2441 this.x = 0
2442 this.y = 0
2443 endclass
2444
2445 var p: Point
2446 p = Point.new(2, 33)
2447 var hx = p
2448 assert_equal(2, hx.x)
2449 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002450 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002451
2452 lines =<< trim END
2453 vim9script
2454
2455 class Point
2456 this.x = 0
2457 this.y = 0
2458 endclass
2459
2460 var p: Point
2461 p = 'text'
2462 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002463 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002464enddef
2465
Bram Moolenaar83677162023-01-08 19:54:10 +00002466def Test_class_extends()
2467 var lines =<< trim END
2468 vim9script
2469 class Base
2470 this.one = 1
2471 def GetOne(): number
2472 return this.one
2473 enddef
2474 endclass
2475 class Child extends Base
2476 this.two = 2
2477 def GetTotal(): number
2478 return this.one + this.two
2479 enddef
2480 endclass
2481 var o = Child.new()
2482 assert_equal(1, o.one)
2483 assert_equal(2, o.two)
2484 assert_equal(1, o.GetOne())
2485 assert_equal(3, o.GetTotal())
2486 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002487 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002488
2489 lines =<< trim END
2490 vim9script
2491 class Base
2492 this.one = 1
2493 endclass
2494 class Child extends Base
2495 this.two = 2
2496 endclass
2497 var o = Child.new(3, 44)
2498 assert_equal(3, o.one)
2499 assert_equal(44, o.two)
2500 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002501 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002502
2503 lines =<< trim END
2504 vim9script
2505 class Base
2506 this.one = 1
2507 endclass
2508 class Child extends Base extends Base
2509 this.two = 2
2510 endclass
2511 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002512 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
Bram Moolenaar83677162023-01-08 19:54:10 +00002513
2514 lines =<< trim END
2515 vim9script
2516 class Child extends BaseClass
2517 this.two = 2
2518 endclass
2519 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002520 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
Bram Moolenaar83677162023-01-08 19:54:10 +00002521
2522 lines =<< trim END
2523 vim9script
2524 var SomeVar = 99
2525 class Child extends SomeVar
2526 this.two = 2
2527 endclass
2528 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002529 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002530
2531 lines =<< trim END
2532 vim9script
2533 class Base
2534 this.name: string
2535 def ToString(): string
2536 return this.name
2537 enddef
2538 endclass
2539
2540 class Child extends Base
2541 this.age: number
2542 def ToString(): string
2543 return super.ToString() .. ': ' .. this.age
2544 enddef
2545 endclass
2546
2547 var o = Child.new('John', 42)
2548 assert_equal('John: 42', o.ToString())
2549 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002550 v9.CheckSourceSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002551
2552 lines =<< trim END
2553 vim9script
2554 class Child
2555 this.age: number
2556 def ToString(): number
2557 return this.age
2558 enddef
2559 def ToString(): string
2560 return this.age
2561 enddef
2562 endclass
2563 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002564 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002565
2566 lines =<< trim END
2567 vim9script
2568 class Child
2569 this.age: number
2570 def ToString(): string
2571 return super .ToString() .. ': ' .. this.age
2572 enddef
2573 endclass
2574 var o = Child.new(42)
2575 echo o.ToString()
2576 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002577 v9.CheckSourceFailure(lines, 'E1356:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002578
2579 lines =<< trim END
2580 vim9script
2581 class Base
2582 this.name: string
2583 def ToString(): string
2584 return this.name
2585 enddef
2586 endclass
2587
2588 var age = 42
2589 def ToString(): string
2590 return super.ToString() .. ': ' .. age
2591 enddef
2592 echo ToString()
2593 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002594 v9.CheckSourceFailure(lines, 'E1357:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002595
2596 lines =<< trim END
2597 vim9script
2598 class Child
2599 this.age: number
2600 def ToString(): string
2601 return super.ToString() .. ': ' .. this.age
2602 enddef
2603 endclass
2604 var o = Child.new(42)
2605 echo o.ToString()
2606 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002607 v9.CheckSourceFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002608
2609 lines =<< trim END
2610 vim9script
2611 class Base
2612 this.name: string
2613 static def ToString(): string
2614 return 'Base class'
2615 enddef
2616 endclass
2617
2618 class Child extends Base
2619 this.age: number
2620 def ToString(): string
2621 return Base.ToString() .. ': ' .. this.age
2622 enddef
2623 endclass
2624
2625 var o = Child.new('John', 42)
2626 assert_equal('Base class: 42', o.ToString())
2627 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002628 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002629
2630 lines =<< trim END
2631 vim9script
2632 class Base
2633 this.value = 1
2634 def new(init: number)
2635 this.value = number + 1
2636 enddef
2637 endclass
2638 class Child extends Base
2639 def new()
2640 this.new(3)
2641 enddef
2642 endclass
2643 var c = Child.new()
2644 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002645 v9.CheckSourceFailure(lines, 'E1375: Class member "new" accessible only using class "Child"')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002646
2647 # base class with more than one object member
2648 lines =<< trim END
2649 vim9script
2650
2651 class Result
2652 this.success: bool
2653 this.value: any = null
2654 endclass
2655
2656 class Success extends Result
2657 def new(this.value = v:none)
2658 this.success = true
2659 enddef
2660 endclass
2661
2662 var v = Success.new('asdf')
2663 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2664 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002665 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002666
2667 # class name after "extends" doesn't end in a space or NUL character
2668 lines =<< trim END
2669 vim9script
2670 class A
2671 endclass
2672 class B extends A"
2673 endclass
2674 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002675 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002676enddef
2677
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002678def Test_using_base_class()
2679 var lines =<< trim END
2680 vim9script
2681
2682 class BaseEE
2683 def Enter(): any
2684 return null
2685 enddef
2686 def Exit(resource: any): void
2687 enddef
2688 endclass
2689
2690 class ChildEE extends BaseEE
2691 def Enter(): any
2692 return 42
2693 enddef
2694
2695 def Exit(resource: number): void
2696 g:result ..= '/exit'
2697 enddef
2698 endclass
2699
2700 def With(ee: BaseEE)
2701 var r = ee.Enter()
2702 try
2703 g:result ..= r
2704 finally
2705 g:result ..= '/finally'
2706 ee.Exit(r)
2707 endtry
2708 enddef
2709
2710 g:result = ''
2711 With(ChildEE.new())
2712 assert_equal('42/finally/exit', g:result)
2713 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002714 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002715 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002716
2717 # Using super, Child invokes Base method which has optional arg. #12471
2718 lines =<< trim END
2719 vim9script
2720
2721 class Base
2722 this.success: bool = false
2723 def Method(arg = 0)
2724 this.success = true
2725 enddef
2726 endclass
2727
2728 class Child extends Base
2729 def new()
2730 super.Method()
2731 enddef
2732 endclass
2733
2734 var obj = Child.new()
2735 assert_equal(true, obj.success)
2736 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002737 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002738enddef
2739
Bram Moolenaara86655a2023-01-12 17:06:27 +00002740def Test_class_import()
2741 var lines =<< trim END
2742 vim9script
2743 export class Animal
2744 this.kind: string
2745 this.name: string
2746 endclass
2747 END
2748 writefile(lines, 'Xanimal.vim', 'D')
2749
2750 lines =<< trim END
2751 vim9script
2752 import './Xanimal.vim' as animal
2753
2754 var a: animal.Animal
2755 a = animal.Animal.new('fish', 'Eric')
2756 assert_equal('fish', a.kind)
2757 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002758
2759 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2760 assert_equal('cat', b.kind)
2761 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002762 END
2763 v9.CheckScriptSuccess(lines)
2764enddef
2765
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002766def Test_abstract_class()
2767 var lines =<< trim END
2768 vim9script
2769 abstract class Base
2770 this.name: string
2771 endclass
2772 class Person extends Base
2773 this.age: number
2774 endclass
2775 var p: Base = Person.new('Peter', 42)
2776 assert_equal('Peter', p.name)
2777 assert_equal(42, p.age)
2778 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002779 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002780
2781 lines =<< trim END
2782 vim9script
2783 abstract class Base
2784 this.name: string
2785 endclass
2786 class Person extends Base
2787 this.age: number
2788 endclass
2789 var p = Base.new('Peter')
2790 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002791 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002792
2793 lines =<< trim END
2794 abstract class Base
2795 this.name: string
2796 endclass
2797 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002798 v9.CheckSourceFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002799
2800 # Abstract class cannot have a "new" function
2801 lines =<< trim END
2802 vim9script
2803 abstract class Base
2804 def new()
2805 enddef
2806 endclass
2807 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002808 v9.CheckSourceFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002809enddef
2810
Bram Moolenaar486fc252023-01-18 14:51:07 +00002811def Test_closure_in_class()
2812 var lines =<< trim END
2813 vim9script
2814
2815 class Foo
2816 this.y: list<string> = ['B']
2817
2818 def new()
2819 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2820 enddef
2821 endclass
2822
2823 Foo.new()
2824 assert_equal(['A'], g:result)
2825 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002826 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00002827enddef
2828
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002829def Test_call_constructor_from_legacy()
2830 var lines =<< trim END
2831 vim9script
2832
2833 var newCalled = 'false'
2834
2835 class A
2836 def new()
2837 newCalled = 'true'
2838 enddef
2839 endclass
2840
2841 export def F(options = {}): any
2842 return A
2843 enddef
2844
2845 g:p = F()
2846 legacy call p.new()
2847 assert_equal('true', newCalled)
2848 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002849 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002850enddef
2851
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002852def Test_defer_with_object()
2853 var lines =<< trim END
2854 vim9script
2855
2856 class CWithEE
2857 def Enter()
2858 g:result ..= "entered/"
2859 enddef
2860 def Exit()
2861 g:result ..= "exited"
2862 enddef
2863 endclass
2864
2865 def With(ee: CWithEE, F: func)
2866 ee.Enter()
2867 defer ee.Exit()
2868 F()
2869 enddef
2870
2871 g:result = ''
2872 var obj = CWithEE.new()
2873 obj->With(() => {
2874 g:result ..= "called/"
2875 })
2876 assert_equal('entered/called/exited', g:result)
2877 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002878 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002879 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002880
2881 lines =<< trim END
2882 vim9script
2883
2884 class BaseWithEE
2885 def Enter()
2886 g:result ..= "entered-base/"
2887 enddef
2888 def Exit()
2889 g:result ..= "exited-base"
2890 enddef
2891 endclass
2892
2893 class CWithEE extends BaseWithEE
2894 def Enter()
2895 g:result ..= "entered-child/"
2896 enddef
2897 def Exit()
2898 g:result ..= "exited-child"
2899 enddef
2900 endclass
2901
2902 def With(ee: BaseWithEE, F: func)
2903 ee.Enter()
2904 defer ee.Exit()
2905 F()
2906 enddef
2907
2908 g:result = ''
2909 var obj = CWithEE.new()
2910 obj->With(() => {
2911 g:result ..= "called/"
2912 })
2913 assert_equal('entered-child/called/exited-child', g:result)
2914 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002915 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00002916 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002917enddef
2918
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002919" The following test used to crash Vim (Github issue #12676)
2920def Test_extends_method_crashes_vim()
2921 var lines =<< trim END
2922 vim9script
2923
2924 class Observer
2925 endclass
2926
2927 class Property
2928 this.value: any
2929
2930 def Set(v: any)
2931 if v != this.value
2932 this.value = v
2933 endif
2934 enddef
2935
2936 def Register(observer: Observer)
2937 enddef
2938 endclass
2939
2940 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02002941 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002942 endclass
2943
2944 def Observe(obj: Property, who: Observer)
2945 obj.Register(who)
2946 enddef
2947
2948 var p = Bool.new(false)
2949 var myObserver = Observer.new()
2950
2951 Observe(p, myObserver)
2952
2953 p.Set(true)
2954 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002955 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002956enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002957
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002958" Test for calling a method in a class that is extended
2959def Test_call_method_in_extended_class()
2960 var lines =<< trim END
2961 vim9script
2962
2963 var prop_init_called = false
2964 var prop_register_called = false
2965
2966 class Property
2967 def Init()
2968 prop_init_called = true
2969 enddef
2970
2971 def Register()
2972 prop_register_called = true
2973 enddef
2974 endclass
2975
2976 class Bool extends Property
2977 endclass
2978
2979 def Observe(obj: Property)
2980 obj.Register()
2981 enddef
2982
2983 var p = Property.new()
2984 Observe(p)
2985
2986 p.Init()
2987 assert_true(prop_init_called)
2988 assert_true(prop_register_called)
2989 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002990 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02002991enddef
2992
LemonBoyafe04662023-08-23 21:08:11 +02002993def Test_instanceof()
2994 var lines =<< trim END
2995 vim9script
2996
2997 class Base1
2998 endclass
2999
3000 class Base2 extends Base1
3001 endclass
3002
3003 interface Intf1
3004 endinterface
3005
3006 class Mix1 implements Intf1
3007 endclass
3008
3009 class Base3 extends Mix1
3010 endclass
3011
3012 var b1 = Base1.new()
3013 var b2 = Base2.new()
3014 var b3 = Base3.new()
3015
3016 assert_true(instanceof(b1, Base1))
3017 assert_true(instanceof(b2, Base1))
3018 assert_false(instanceof(b1, Base2))
3019 assert_true(instanceof(b3, Mix1))
3020 assert_false(instanceof(b3, []))
3021 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003022
3023 def Foo()
3024 var a1 = Base1.new()
3025 var a2 = Base2.new()
3026 var a3 = Base3.new()
3027
3028 assert_true(instanceof(a1, Base1))
3029 assert_true(instanceof(a2, Base1))
3030 assert_false(instanceof(a1, Base2))
3031 assert_true(instanceof(a3, Mix1))
3032 assert_false(instanceof(a3, []))
3033 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
3034 enddef
3035 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003036
3037 var o_null: Base1
3038 assert_false(instanceof(o_null, Base1))
3039
LemonBoyafe04662023-08-23 21:08:11 +02003040 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003041 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02003042enddef
3043
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003044" Test for calling a method in the parent class that is extended partially.
3045" This used to fail with the 'E118: Too many arguments for function: Text' error
3046" message (Github issue #12524).
3047def Test_call_method_in_parent_class()
3048 var lines =<< trim END
3049 vim9script
3050
3051 class Widget
3052 this._lnum: number = 1
3053
3054 def SetY(lnum: number)
3055 this._lnum = lnum
3056 enddef
3057
3058 def Text(): string
3059 return ''
3060 enddef
3061 endclass
3062
3063 class Foo extends Widget
3064 def Text(): string
3065 return '<Foo>'
3066 enddef
3067 endclass
3068
3069 def Stack(w1: Widget, w2: Widget): list<Widget>
3070 w1.SetY(1)
3071 w2.SetY(2)
3072 return [w1, w2]
3073 enddef
3074
3075 var foo1 = Foo.new()
3076 var foo2 = Foo.new()
3077 var l = Stack(foo1, foo2)
3078 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003079 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003080enddef
3081
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003082" Test for calling methods from three levels of classes
3083def Test_multi_level_method_call()
3084 var lines =<< trim END
3085 vim9script
3086
3087 var A_func1: number = 0
3088 var A_func2: number = 0
3089 var A_func3: number = 0
3090 var B_func2: number = 0
3091 var B_func3: number = 0
3092 var C_func3: number = 0
3093
3094 class A
3095 def Func1()
3096 A_func1 += 1
3097 enddef
3098
3099 def Func2()
3100 A_func2 += 1
3101 enddef
3102
3103 def Func3()
3104 A_func3 += 1
3105 enddef
3106 endclass
3107
3108 class B extends A
3109 def Func2()
3110 B_func2 += 1
3111 enddef
3112
3113 def Func3()
3114 B_func3 += 1
3115 enddef
3116 endclass
3117
3118 class C extends B
3119 def Func3()
3120 C_func3 += 1
3121 enddef
3122 endclass
3123
3124 def A_CallFuncs(a: A)
3125 a.Func1()
3126 a.Func2()
3127 a.Func3()
3128 enddef
3129
3130 def B_CallFuncs(b: B)
3131 b.Func1()
3132 b.Func2()
3133 b.Func3()
3134 enddef
3135
3136 def C_CallFuncs(c: C)
3137 c.Func1()
3138 c.Func2()
3139 c.Func3()
3140 enddef
3141
3142 var cobj = C.new()
3143 A_CallFuncs(cobj)
3144 B_CallFuncs(cobj)
3145 C_CallFuncs(cobj)
3146 assert_equal(3, A_func1)
3147 assert_equal(0, A_func2)
3148 assert_equal(0, A_func3)
3149 assert_equal(3, B_func2)
3150 assert_equal(0, B_func3)
3151 assert_equal(3, C_func3)
3152 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003153 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003154enddef
3155
3156" Test for using members from three levels of classes
3157def Test_multi_level_member_access()
3158 var lines =<< trim END
3159 vim9script
3160
3161 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003162 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003163 endclass
3164
3165 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003166 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003167 endclass
3168
3169 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003170 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003171 endclass
3172
3173 def A_members(a: A)
3174 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003175 enddef
3176
3177 def B_members(b: B)
3178 b.val1 += 1
3179 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003180 enddef
3181
3182 def C_members(c: C)
3183 c.val1 += 1
3184 c.val2 += 1
3185 c.val3 += 1
3186 enddef
3187
3188 var cobj = C.new()
3189 A_members(cobj)
3190 B_members(cobj)
3191 C_members(cobj)
3192 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003193 assert_equal(2, cobj.val2)
3194 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003195 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003196 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003197enddef
3198
LemonBoy0ffc17a2023-08-20 18:09:11 +02003199" Test expansion of <stack> with class methods.
3200def Test_stack_expansion_with_methods()
3201 var lines =<< trim END
3202 vim9script
3203
3204 class C
3205 def M1()
3206 F0()
3207 enddef
3208 endclass
3209
3210 def F0()
3211 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3212 enddef
3213
3214 def F()
3215 C.new().M1()
3216 enddef
3217
3218 F()
3219 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003220 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003221enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003222
3223" Test the return type of the new() constructor
3224def Test_new_return_type()
3225 # new() uses the default return type and there is no return statement
3226 var lines =<< trim END
3227 vim9script
3228
3229 class C
3230 this._bufnr: number
3231
3232 def new(this._bufnr)
3233 if !bufexists(this._bufnr)
3234 this._bufnr = -1
3235 endif
3236 enddef
3237 endclass
3238
3239 var c = C.new(12345)
3240 assert_equal('object<C>', typename(c))
3241
3242 var v1: C
3243 v1 = C.new(12345)
3244 assert_equal('object<C>', typename(v1))
3245
3246 def F()
3247 var v2: C
3248 v2 = C.new(12345)
3249 assert_equal('object<C>', typename(v2))
3250 enddef
3251 F()
3252 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003253 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003254
3255 # new() uses the default return type and an empty 'return' statement
3256 lines =<< trim END
3257 vim9script
3258
3259 class C
3260 this._bufnr: number
3261
3262 def new(this._bufnr)
3263 if !bufexists(this._bufnr)
3264 this._bufnr = -1
3265 return
3266 endif
3267 enddef
3268 endclass
3269
3270 var c = C.new(12345)
3271 assert_equal('object<C>', typename(c))
3272
3273 var v1: C
3274 v1 = C.new(12345)
3275 assert_equal('object<C>', typename(v1))
3276
3277 def F()
3278 var v2: C
3279 v2 = C.new(12345)
3280 assert_equal('object<C>', typename(v2))
3281 enddef
3282 F()
3283 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003284 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003285
3286 # new() uses "any" return type and returns "this"
3287 lines =<< trim END
3288 vim9script
3289
3290 class C
3291 this._bufnr: number
3292
3293 def new(this._bufnr): any
3294 if !bufexists(this._bufnr)
3295 this._bufnr = -1
3296 return this
3297 endif
3298 enddef
3299 endclass
3300 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003301 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003302
3303 # new() uses 'Dict' return type and returns a Dict
3304 lines =<< trim END
3305 vim9script
3306
3307 class C
3308 this._state: dict<any>
3309
3310 def new(): dict<any>
3311 this._state = {}
3312 return this._state
3313 enddef
3314 endclass
3315
3316 var c = C.new()
3317 assert_equal('object<C>', typename(c))
3318 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003319 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003320enddef
3321
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003322" Test for checking a member initialization type at run time.
3323def Test_runtime_type_check_for_member_init()
3324 var lines =<< trim END
3325 vim9script
3326
3327 var retnum: bool = false
3328
3329 def F(): any
3330 retnum = !retnum
3331 if retnum
3332 return 1
3333 else
3334 return "hello"
3335 endif
3336 enddef
3337
3338 class C
3339 this._foo: bool = F()
3340 endclass
3341
3342 var c1 = C.new()
3343 var c2 = C.new()
3344 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003345 v9.CheckSourceFailure(lines, 'E1012:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003346enddef
3347
3348" Test for locking a variable referring to an object and reassigning to another
3349" object.
3350def Test_object_lockvar()
3351 var lines =<< trim END
3352 vim9script
3353
3354 class C
3355 this.val: number
3356 def new(this.val)
3357 enddef
3358 endclass
3359
3360 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3361 lockvar 2 some_dict
3362
3363 var current: C
3364 current = some_dict['c']
3365 assert_equal(3, current.val)
3366 current = some_dict['b']
3367 assert_equal(2, current.val)
3368
3369 def F()
3370 current = some_dict['c']
3371 enddef
3372
3373 def G()
3374 current = some_dict['b']
3375 enddef
3376
3377 F()
3378 assert_equal(3, current.val)
3379 G()
3380 assert_equal(2, current.val)
3381 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003382 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003383enddef
3384
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003385" Test for a private object method
3386def Test_private_object_method()
3387 # Try calling a private method using an object (at the script level)
3388 var lines =<< trim END
3389 vim9script
3390
3391 class A
3392 def _Foo(): number
3393 return 1234
3394 enddef
3395 endclass
3396 var a = A.new()
3397 a._Foo()
3398 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003399 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003400
3401 # Try calling a private method using an object (from a def function)
3402 lines =<< trim END
3403 vim9script
3404
3405 class A
3406 def _Foo(): number
3407 return 1234
3408 enddef
3409 endclass
3410 def T()
3411 var a = A.new()
3412 a._Foo()
3413 enddef
3414 T()
3415 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003416 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003417
3418 # Use a private method from another object method (in script context)
3419 lines =<< trim END
3420 vim9script
3421
3422 class A
3423 def _Foo(): number
3424 return 1234
3425 enddef
3426 def Bar(): number
3427 return this._Foo()
3428 enddef
3429 endclass
3430 var a = A.new()
3431 assert_equal(1234, a.Bar())
3432 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003433 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003434
3435 # Use a private method from another object method (def function context)
3436 lines =<< trim END
3437 vim9script
3438
3439 class A
3440 def _Foo(): number
3441 return 1234
3442 enddef
3443 def Bar(): number
3444 return this._Foo()
3445 enddef
3446 endclass
3447 def T()
3448 var a = A.new()
3449 assert_equal(1234, a.Bar())
3450 enddef
3451 T()
3452 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003453 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003454
3455 # Try calling a private method without the "this" prefix
3456 lines =<< trim END
3457 vim9script
3458
3459 class A
3460 def _Foo(): number
3461 return 1234
3462 enddef
3463 def Bar(): number
3464 return _Foo()
3465 enddef
3466 endclass
3467 var a = A.new()
3468 a.Bar()
3469 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003470 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003471
3472 # Try calling a private method using the class name
3473 lines =<< trim END
3474 vim9script
3475
3476 class A
3477 def _Foo(): number
3478 return 1234
3479 enddef
3480 endclass
3481 A._Foo()
3482 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003483 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003484
3485 # Try to use "public" keyword when defining a private method
3486 lines =<< trim END
3487 vim9script
3488
3489 class A
3490 public def _Foo()
3491 enddef
3492 endclass
3493 var a = A.new()
3494 a._Foo()
3495 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003496 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003497
3498 # Define two private methods with the same name
3499 lines =<< trim END
3500 vim9script
3501
3502 class A
3503 def _Foo()
3504 enddef
3505 def _Foo()
3506 enddef
3507 endclass
3508 var a = A.new()
3509 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003510 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003511
3512 # Define a private method and a object method with the same name
3513 lines =<< trim END
3514 vim9script
3515
3516 class A
3517 def _Foo()
3518 enddef
3519 def Foo()
3520 enddef
3521 endclass
3522 var a = A.new()
3523 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003524 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003525
3526 # Define an object method and a private method with the same name
3527 lines =<< trim END
3528 vim9script
3529
3530 class A
3531 def Foo()
3532 enddef
3533 def _Foo()
3534 enddef
3535 endclass
3536 var a = A.new()
3537 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003538 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003539
3540 # Call a public method and a private method from a private method
3541 lines =<< trim END
3542 vim9script
3543
3544 class A
3545 def Foo(): number
3546 return 100
3547 enddef
3548 def _Bar(): number
3549 return 200
3550 enddef
3551 def _Baz()
3552 assert_equal(100, this.Foo())
3553 assert_equal(200, this._Bar())
3554 enddef
3555 def T()
3556 this._Baz()
3557 enddef
3558 endclass
3559 var a = A.new()
3560 a.T()
3561 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003562 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003563
3564 # Try calling a private method from another class
3565 lines =<< trim END
3566 vim9script
3567
3568 class A
3569 def _Foo(): number
3570 return 100
3571 enddef
3572 endclass
3573 class B
3574 def Foo(): number
3575 var a = A.new()
3576 a._Foo()
3577 enddef
3578 endclass
3579 var b = B.new()
3580 b.Foo()
3581 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003582 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003583
3584 # Call a private object method from a child class object method
3585 lines =<< trim END
3586 vim9script
3587 class A
3588 def _Foo(): number
3589 return 1234
3590 enddef
3591 endclass
3592 class B extends A
3593 def Bar()
3594 enddef
3595 endclass
3596 class C extends B
3597 def Baz(): number
3598 return this._Foo()
3599 enddef
3600 endclass
3601 var c = C.new()
3602 assert_equal(1234, c.Baz())
3603 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003604 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003605
3606 # Call a private object method from a child class object
3607 lines =<< trim END
3608 vim9script
3609 class A
3610 def _Foo(): number
3611 return 1234
3612 enddef
3613 endclass
3614 class B extends A
3615 def Bar()
3616 enddef
3617 endclass
3618 class C extends B
3619 def Baz(): number
3620 enddef
3621 endclass
3622 var c = C.new()
3623 assert_equal(1234, c._Foo())
3624 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003625 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003626
3627 # Using "_" prefix in a method name should fail outside of a class
3628 lines =<< trim END
3629 vim9script
3630 def _Foo(): number
3631 return 1234
3632 enddef
3633 var a = _Foo()
3634 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003635 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003636enddef
3637
3638" Test for an private class method
3639def Test_private_class_method()
3640 # Try calling a class private method (at the script level)
3641 var lines =<< trim END
3642 vim9script
3643
3644 class A
3645 static def _Foo(): number
3646 return 1234
3647 enddef
3648 endclass
3649 A._Foo()
3650 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003651 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003652
3653 # Try calling a class private method (from a def function)
3654 lines =<< trim END
3655 vim9script
3656
3657 class A
3658 static def _Foo(): number
3659 return 1234
3660 enddef
3661 endclass
3662 def T()
3663 A._Foo()
3664 enddef
3665 T()
3666 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003667 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003668
3669 # Try calling a class private method using an object (at the script level)
3670 lines =<< trim END
3671 vim9script
3672
3673 class A
3674 static def _Foo(): number
3675 return 1234
3676 enddef
3677 endclass
3678 var a = A.new()
3679 a._Foo()
3680 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003681 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003682
3683 # Try calling a class private method using an object (from a def function)
3684 lines =<< trim END
3685 vim9script
3686
3687 class A
3688 static def _Foo(): number
3689 return 1234
3690 enddef
3691 endclass
3692 def T()
3693 var a = A.new()
3694 a._Foo()
3695 enddef
3696 T()
3697 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003698 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003699
3700 # Use a class private method from an object method
3701 lines =<< trim END
3702 vim9script
3703
3704 class A
3705 static def _Foo(): number
3706 return 1234
3707 enddef
3708 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003709 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003710 enddef
3711 endclass
3712 var a = A.new()
3713 a.Bar()
3714 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003715 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003716
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003717 # Use a class private method from another class private method without the
3718 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003719 lines =<< trim END
3720 vim9script
3721
3722 class A
3723 static def _Foo1(): number
3724 return 1234
3725 enddef
3726 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003727 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003728 enddef
3729 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003730 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003731 enddef
3732 endclass
3733 var a = A.new()
3734 a.Bar()
3735 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003736 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003737
3738 # Declare a class method and a class private method with the same name
3739 lines =<< trim END
3740 vim9script
3741
3742 class A
3743 static def _Foo()
3744 enddef
3745 static def Foo()
3746 enddef
3747 endclass
3748 var a = A.new()
3749 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003750 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003751
3752 # Try calling a class private method from another class
3753 lines =<< trim END
3754 vim9script
3755
3756 class A
3757 static def _Foo(): number
3758 return 1234
3759 enddef
3760 endclass
3761 class B
3762 def Foo(): number
3763 return A._Foo()
3764 enddef
3765 endclass
3766 var b = B.new()
3767 assert_equal(1234, b.Foo())
3768 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003769 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003770
3771 # Call a private class method from a child class object method
3772 lines =<< trim END
3773 vim9script
3774 class A
3775 static def _Foo(): number
3776 return 1234
3777 enddef
3778 endclass
3779 class B extends A
3780 def Bar()
3781 enddef
3782 endclass
3783 class C extends B
3784 def Baz(): number
3785 return A._Foo()
3786 enddef
3787 endclass
3788 var c = C.new()
3789 assert_equal(1234, c.Baz())
3790 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003791 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003792
3793 # Call a private class method from a child class private class method
3794 lines =<< trim END
3795 vim9script
3796 class A
3797 static def _Foo(): number
3798 return 1234
3799 enddef
3800 endclass
3801 class B extends A
3802 def Bar()
3803 enddef
3804 endclass
3805 class C extends B
3806 static def Baz(): number
3807 return A._Foo()
3808 enddef
3809 endclass
3810 assert_equal(1234, C.Baz())
3811 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003812 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003813
3814 # Call a private class method from a child class object
3815 lines =<< trim END
3816 vim9script
3817 class A
3818 static def _Foo(): number
3819 return 1234
3820 enddef
3821 endclass
3822 class B extends A
3823 def Bar()
3824 enddef
3825 endclass
3826 class C extends B
3827 def Baz(): number
3828 enddef
3829 endclass
3830 var c = C.new()
3831 assert_equal(1234, C._Foo())
3832 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003833 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003834enddef
3835
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003836" Test for using the return value of a class/object method as a function
3837" argument.
3838def Test_objmethod_funcarg()
3839 var lines =<< trim END
3840 vim9script
3841
3842 class C
3843 def Foo(): string
3844 return 'foo'
3845 enddef
3846 endclass
3847
3848 def Bar(a: number, s: string): string
3849 return s
3850 enddef
3851
3852 def Baz(c: C)
3853 assert_equal('foo', Bar(10, c.Foo()))
3854 enddef
3855
3856 var t = C.new()
3857 Baz(t)
3858 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003859 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003860
3861 lines =<< trim END
3862 vim9script
3863
3864 class C
3865 static def Foo(): string
3866 return 'foo'
3867 enddef
3868 endclass
3869
3870 def Bar(a: number, s: string): string
3871 return s
3872 enddef
3873
3874 def Baz()
3875 assert_equal('foo', Bar(10, C.Foo()))
3876 enddef
3877
3878 Baz()
3879 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003880 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003881enddef
3882
Ernie Raelcf138d42023-09-06 20:45:03 +02003883def Test_static_inheritence()
3884 # subclasses get their own static copy
3885 var lines =<< trim END
3886 vim9script
3887
3888 class A
3889 static _svar: number
3890 this._mvar: number
3891 def new()
3892 _svar = 1
3893 this._mvar = 101
3894 enddef
3895 def AccessObject(): number
3896 return this._mvar
3897 enddef
3898 def AccessStaticThroughObject(): number
3899 return _svar
3900 enddef
3901 endclass
3902
3903 class B extends A
3904 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003905 this._mvar = 102
3906 enddef
3907 endclass
3908
3909 class C extends B
3910 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003911 this._mvar = 103
3912 enddef
3913
3914 def AccessPrivateStaticThroughClassName(): number
3915 assert_equal(1, A._svar)
Ernie Raelcf138d42023-09-06 20:45:03 +02003916 return 444
3917 enddef
3918 endclass
3919
3920 var oa = A.new()
3921 var ob = B.new()
3922 var oc = C.new()
3923 assert_equal(101, oa.AccessObject())
3924 assert_equal(102, ob.AccessObject())
3925 assert_equal(103, oc.AccessObject())
3926
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003927 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private member: _svar')
Ernie Raelcf138d42023-09-06 20:45:03 +02003928
3929 # verify object properly resolves to correct static
3930 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003931 assert_equal(1, ob.AccessStaticThroughObject())
3932 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02003933 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003934 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02003935enddef
3936
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003937" Test for declaring duplicate object and class members
3938def Test_dup_member_variable()
3939 # Duplicate member variable
3940 var lines =<< trim END
3941 vim9script
3942 class C
3943 this.val = 10
3944 this.val = 20
3945 endclass
3946 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003947 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003948
3949 # Duplicate private member variable
3950 lines =<< trim END
3951 vim9script
3952 class C
3953 this._val = 10
3954 this._val = 20
3955 endclass
3956 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003957 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003958
3959 # Duplicate public member variable
3960 lines =<< trim END
3961 vim9script
3962 class C
3963 public this.val = 10
3964 public this.val = 20
3965 endclass
3966 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003967 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003968
3969 # Duplicate private member variable
3970 lines =<< trim END
3971 vim9script
3972 class C
3973 this.val = 10
3974 this._val = 20
3975 endclass
3976 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003977 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003978
3979 # Duplicate public and private member variable
3980 lines =<< trim END
3981 vim9script
3982 class C
3983 this._val = 20
3984 public this.val = 10
3985 endclass
3986 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003987 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003988
3989 # Duplicate class member variable
3990 lines =<< trim END
3991 vim9script
3992 class C
3993 static s: string = "abc"
3994 static _s: string = "def"
3995 endclass
3996 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003997 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02003998
3999 # Duplicate public and private class member variable
4000 lines =<< trim END
4001 vim9script
4002 class C
4003 public static s: string = "abc"
4004 static _s: string = "def"
4005 endclass
4006 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004007 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004008
4009 # Duplicate class and object member variable
4010 lines =<< trim END
4011 vim9script
4012 class C
4013 static val = 10
4014 this.val = 20
4015 def new()
4016 enddef
4017 endclass
4018 var c = C.new()
4019 assert_equal(10, C.val)
4020 assert_equal(20, c.val)
4021 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004022 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004023
4024 # Duplicate object member variable in a derived class
4025 lines =<< trim END
4026 vim9script
4027 class A
4028 this.val = 10
4029 endclass
4030 class B extends A
4031 endclass
4032 class C extends B
4033 this.val = 20
4034 endclass
4035 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004036 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004037
4038 # Duplicate object private member variable in a derived class
4039 lines =<< trim END
4040 vim9script
4041 class A
4042 this._val = 10
4043 endclass
4044 class B extends A
4045 endclass
4046 class C extends B
4047 this._val = 20
4048 endclass
4049 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004050 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004051
4052 # Duplicate object private member variable in a derived class
4053 lines =<< trim END
4054 vim9script
4055 class A
4056 this.val = 10
4057 endclass
4058 class B extends A
4059 endclass
4060 class C extends B
4061 this._val = 20
4062 endclass
4063 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004064 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004065
4066 # Duplicate object member variable in a derived class
4067 lines =<< trim END
4068 vim9script
4069 class A
4070 this._val = 10
4071 endclass
4072 class B extends A
4073 endclass
4074 class C extends B
4075 this.val = 20
4076 endclass
4077 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004078 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004079
4080 # Two member variables with a common prefix
4081 lines =<< trim END
4082 vim9script
4083 class A
4084 public static svar2: number
4085 public static svar: number
4086 endclass
4087 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004088 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004089enddef
4090
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004091" Test for accessing a private member outside a class in a def function
4092def Test_private_member_access_outside_class()
4093 # private object member variable
4094 var lines =<< trim END
4095 vim9script
4096 class A
4097 this._val = 10
4098 def GetVal(): number
4099 return this._val
4100 enddef
4101 endclass
4102 def T()
4103 var a = A.new()
4104 a._val = 20
4105 enddef
4106 T()
4107 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004108 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004109
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004110 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004111 lines =<< trim END
4112 vim9script
4113 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004114 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004115 endclass
4116 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004117 var a = A.new()
4118 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004119 enddef
4120 T()
4121 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004122 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": _a')
Ernie Rael18143d32023-09-04 22:30:41 +02004123
4124 # private static member variable
4125 lines =<< trim END
4126 vim9script
4127 class A
4128 static _val = 10
4129 endclass
4130 def T()
4131 var a = A.new()
4132 var x = a._val
4133 enddef
4134 T()
4135 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004136 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004137
4138 # private static member variable
4139 lines =<< trim END
4140 vim9script
4141 class A
4142 static _val = 10
4143 endclass
4144 def T()
4145 var a = A.new()
4146 a._val = 3
4147 enddef
4148 T()
4149 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004150 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004151
4152 # private static class variable
4153 lines =<< trim END
4154 vim9script
4155 class A
4156 static _val = 10
4157 endclass
4158 def T()
4159 var x = A._val
4160 enddef
4161 T()
4162 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004163 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004164
4165 # private static class variable
4166 lines =<< trim END
4167 vim9script
4168 class A
4169 static _val = 10
4170 endclass
4171 def T()
4172 A._val = 3
4173 enddef
4174 T()
4175 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004176 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004177enddef
4178
4179" Test for changing the member access of an interface in a implementation class
4180def Test_change_interface_member_access()
4181 var lines =<< trim END
4182 vim9script
4183 interface A
4184 public this.val: number
4185 endinterface
4186 class B implements A
4187 this.val = 10
4188 endclass
4189 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004190 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004191
4192 lines =<< trim END
4193 vim9script
4194 interface A
4195 this.val: number
4196 endinterface
4197 class B implements A
4198 public this.val = 10
4199 endclass
4200 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004201 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004202enddef
4203
4204" Test for trying to change a readonly member from a def function
4205def Test_readonly_member_change_in_def_func()
4206 var lines =<< trim END
4207 vim9script
4208 class A
4209 this.val: number
4210 endclass
4211 def T()
4212 var a = A.new()
4213 a.val = 20
4214 enddef
4215 T()
4216 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004217 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "val"')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004218enddef
4219
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004220" Test for reading and writing a class member from a def function
4221def Test_modify_class_member_from_def_function()
4222 var lines =<< trim END
4223 vim9script
4224 class A
4225 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004226 public static var2: list<number> = [1, 2]
4227 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004228 static _priv_var4: number = 40
4229 endclass
4230 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004231 assert_equal([1, 2], A.var2)
4232 assert_equal({a: 1, b: 2}, A.var3)
4233 A.var2 = [3, 4]
4234 A.var3 = {c: 3, d: 4}
4235 assert_equal([3, 4], A.var2)
4236 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004237 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4238 enddef
4239 T()
4240 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004241 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004242enddef
4243
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004244" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004245def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004246 var lines =<< trim END
4247 vim9script
4248 class A
4249 public static svar1: list<number> = [1]
4250 public static svar2: list<number> = [2]
4251 endclass
4252
4253 A.svar1->add(3)
4254 A.svar2->add(4)
4255 assert_equal([1, 3], A.svar1)
4256 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004257
4258 def Foo()
4259 A.svar1->add(7)
4260 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004261 assert_equal([1, 3, 7], A.svar1)
4262 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004263 enddef
4264 Foo()
4265 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004266 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004267
4268 # Cannot read from a class variable using an object in script context
4269 lines =<< trim END
4270 vim9script
4271 class A
4272 public this.var1: number
4273 public static svar2: list<number> = [1]
4274 endclass
4275
4276 var a = A.new()
4277 echo a.svar2
4278 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004279 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004280
4281 # Cannot write to a class variable using an object in script context
4282 lines =<< trim END
4283 vim9script
4284 class A
4285 public this.var1: number
4286 public static svar2: list<number> = [1]
4287 endclass
4288
4289 var a = A.new()
4290 a.svar2 = [2]
4291 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004292 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004293
4294 # Cannot read from a class variable using an object in def method context
4295 lines =<< trim END
4296 vim9script
4297 class A
4298 public this.var1: number
4299 public static svar2: list<number> = [1]
4300 endclass
4301
4302 def T()
4303 var a = A.new()
4304 echo a.svar2
4305 enddef
4306 T()
4307 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004308 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004309
4310 # Cannot write to a class variable using an object in def method context
4311 lines =<< trim END
4312 vim9script
4313 class A
4314 public this.var1: number
4315 public static svar2: list<number> = [1]
4316 endclass
4317
4318 def T()
4319 var a = A.new()
4320 a.svar2 = [2]
4321 enddef
4322 T()
4323 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004324 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004325enddef
4326
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004327" Test for using a interface method using a child object
4328def Test_interface_method_from_child()
4329 var lines =<< trim END
4330 vim9script
4331
4332 interface A
4333 def Foo(): string
4334 endinterface
4335
4336 class B implements A
4337 def Foo(): string
4338 return 'foo'
4339 enddef
4340 endclass
4341
4342 class C extends B
4343 def Bar(): string
4344 return 'bar'
4345 enddef
4346 endclass
4347
4348 def T1(a: A)
4349 assert_equal('foo', a.Foo())
4350 enddef
4351
4352 def T2(b: B)
4353 assert_equal('foo', b.Foo())
4354 enddef
4355
4356 var c = C.new()
4357 T1(c)
4358 T2(c)
4359 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004360 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004361enddef
4362
4363" Test for using an interface method using a child object when it is overridden
4364" by the child class.
4365" FIXME: This test fails.
4366" def Test_interface_overridden_method_from_child()
4367" var lines =<< trim END
4368" vim9script
4369"
4370" interface A
4371" def Foo(): string
4372" endinterface
4373"
4374" class B implements A
4375" def Foo(): string
4376" return 'b-foo'
4377" enddef
4378" endclass
4379"
4380" class C extends B
4381" def Bar(): string
4382" return 'bar'
4383" enddef
4384" def Foo(): string
4385" return 'c-foo'
4386" enddef
4387" endclass
4388"
4389" def T1(a: A)
4390" assert_equal('c-foo', a.Foo())
4391" enddef
4392"
4393" def T2(b: B)
4394" assert_equal('c-foo', b.Foo())
4395" enddef
4396"
4397" var c = C.new()
4398" T1(c)
4399" T2(c)
4400" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004401" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004402" enddef
4403
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004404" Test for abstract methods
4405def Test_abstract_method()
4406 # Use two abstract methods
4407 var lines =<< trim END
4408 vim9script
4409 abstract class A
4410 def M1(): number
4411 return 10
4412 enddef
4413 abstract def M2(): number
4414 abstract def M3(): number
4415 endclass
4416 class B extends A
4417 def M2(): number
4418 return 20
4419 enddef
4420 def M3(): number
4421 return 30
4422 enddef
4423 endclass
4424 var b = B.new()
4425 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4426 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004427 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004428
4429 # Don't define an abstract method
4430 lines =<< trim END
4431 vim9script
4432 abstract class A
4433 abstract def Foo()
4434 endclass
4435 class B extends A
4436 endclass
4437 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004438 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004439
4440 # Use abstract method in a concrete class
4441 lines =<< trim END
4442 vim9script
4443 class A
4444 abstract def Foo()
4445 endclass
4446 class B extends A
4447 endclass
4448 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004449 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004450
4451 # Use abstract method in an interface
4452 lines =<< trim END
4453 vim9script
4454 interface A
4455 abstract def Foo()
4456 endinterface
4457 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004458 def Foo()
4459 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004460 endclass
4461 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004462 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004463
4464 # Abbreviate the "abstract" keyword
4465 lines =<< trim END
4466 vim9script
4467 class A
4468 abs def Foo()
4469 endclass
4470 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004471 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004472
4473 # Use "abstract" with a member variable
4474 lines =<< trim END
4475 vim9script
4476 abstract class A
4477 abstract this.val = 10
4478 endclass
4479 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004480 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004481
4482 # Use a static abstract method
4483 lines =<< trim END
4484 vim9script
4485 abstract class A
4486 abstract static def Foo(): number
4487 endclass
4488 class B extends A
4489 static def Foo(): number
4490 return 4
4491 enddef
4492 endclass
4493 assert_equal(4, B.Foo())
4494 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004495 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004496
4497 # Type mismatch between abstract method and concrete method
4498 lines =<< trim END
4499 vim9script
4500 abstract class A
4501 abstract def Foo(a: string, b: number): list<number>
4502 endclass
4503 class B extends A
4504 def Foo(a: number, b: string): list<string>
4505 return []
4506 enddef
4507 endclass
4508 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004509 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 +02004510
4511 # Use an abstract class to invoke an abstract method
4512 # FIXME: This should fail
4513 lines =<< trim END
4514 vim9script
4515 abstract class A
4516 abstract static def Foo()
4517 endclass
4518 A.Foo()
4519 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004520 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004521
4522 # Invoke an abstract method from a def function
4523 lines =<< trim END
4524 vim9script
4525 abstract class A
4526 abstract def Foo(): list<number>
4527 endclass
4528 class B extends A
4529 def Foo(): list<number>
4530 return [3, 5]
4531 enddef
4532 endclass
4533 def Bar(c: B)
4534 assert_equal([3, 5], c.Foo())
4535 enddef
4536 var b = B.new()
4537 Bar(b)
4538 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004539 v9.CheckSourceSuccess(lines)
4540enddef
4541
4542" Test for calling a class method from a subclass
4543def Test_class_method_call_from_subclass()
4544 # class method call from a subclass
4545 var lines =<< trim END
4546 vim9script
4547
4548 class A
4549 static def Foo()
4550 echo "foo"
4551 enddef
4552 endclass
4553
4554 class B extends A
4555 def Bar()
4556 Foo()
4557 enddef
4558 endclass
4559
4560 var b = B.new()
4561 b.Bar()
4562 END
4563 v9.CheckSourceFailure(lines, 'E1374: Class member "Foo" accessible only inside class "A"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004564enddef
4565
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004566" Test for calling a class method using an object in a def function context and
4567" script context.
4568def Test_class_method_call_using_object()
4569 # script context
4570 var lines =<< trim END
4571 vim9script
4572 class A
4573 static def Foo(): list<string>
4574 return ['a', 'b']
4575 enddef
4576 def Bar()
4577 assert_equal(['a', 'b'], A.Foo())
4578 assert_equal(['a', 'b'], Foo())
4579 enddef
4580 endclass
4581
4582 def T()
4583 assert_equal(['a', 'b'], A.Foo())
4584 var t_a = A.new()
4585 t_a.Bar()
4586 enddef
4587
4588 assert_equal(['a', 'b'], A.Foo())
4589 var a = A.new()
4590 a.Bar()
4591 T()
4592 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004593 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004594
4595 # script context
4596 lines =<< trim END
4597 vim9script
4598 class A
4599 static def Foo(): string
4600 return 'foo'
4601 enddef
4602 endclass
4603
4604 var a = A.new()
4605 assert_equal('foo', a.Foo())
4606 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004607 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004608
4609 # def function context
4610 lines =<< trim END
4611 vim9script
4612 class A
4613 static def Foo(): string
4614 return 'foo'
4615 enddef
4616 endclass
4617
4618 def T()
4619 var a = A.new()
4620 assert_equal('foo', a.Foo())
4621 enddef
4622 T()
4623 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004624 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
4625enddef
4626
4627def Test_class_variable()
4628 var lines =<< trim END
4629 vim9script
4630
4631 class A
4632 public static val: number = 10
4633 static def ClassFunc()
4634 assert_equal(10, val)
4635 enddef
4636 def ObjFunc()
4637 assert_equal(10, val)
4638 enddef
4639 endclass
4640
4641 class B extends A
4642 endclass
4643
4644 assert_equal(10, A.val)
4645 A.ClassFunc()
4646 var a = A.new()
4647 a.ObjFunc()
4648 var b = B.new()
4649 b.ObjFunc()
4650
4651 def T1(a1: A)
4652 a1.ObjFunc()
4653 A.ClassFunc()
4654 enddef
4655 T1(b)
4656
4657 A.val = 20
4658 assert_equal(20, A.val)
4659 END
4660 v9.CheckSourceSuccess(lines)
4661
4662 # Modifying a parent class variable from a child class method
4663 lines =<< trim END
4664 vim9script
4665
4666 class A
4667 static val: number = 10
4668 endclass
4669
4670 class B extends A
4671 static def ClassFunc()
4672 val = 20
4673 enddef
4674 endclass
4675 B.ClassFunc()
4676 END
4677 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4678
4679 # Reading a parent class variable from a child class method
4680 lines =<< trim END
4681 vim9script
4682
4683 class A
4684 static val: number = 10
4685 endclass
4686
4687 class B extends A
4688 static def ClassFunc()
4689 var i = val
4690 enddef
4691 endclass
4692 B.ClassFunc()
4693 END
4694 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4695
4696 # Modifying a parent class variable from a child object method
4697 lines =<< trim END
4698 vim9script
4699
4700 class A
4701 static val: number = 10
4702 endclass
4703
4704 class B extends A
4705 def ObjFunc()
4706 val = 20
4707 enddef
4708 endclass
4709 var b = B.new()
4710 b.ObjFunc()
4711 END
4712 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4713
4714 # Reading a parent class variable from a child object method
4715 lines =<< trim END
4716 vim9script
4717
4718 class A
4719 static val: number = 10
4720 endclass
4721
4722 class B extends A
4723 def ObjFunc()
4724 var i = val
4725 enddef
4726 endclass
4727 var b = B.new()
4728 b.ObjFunc()
4729 END
4730 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4731
4732 # Modifying a class variable using an object at script level
4733 lines =<< trim END
4734 vim9script
4735
4736 class A
4737 static val: number = 10
4738 endclass
4739 var a = A.new()
4740 a.val = 20
4741 END
4742 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4743
4744 # Reading a class variable using an object at script level
4745 lines =<< trim END
4746 vim9script
4747
4748 class A
4749 static val: number = 10
4750 endclass
4751 var a = A.new()
4752 var i = a.val
4753 END
4754 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4755
4756 # Modifying a class variable using an object at function level
4757 lines =<< trim END
4758 vim9script
4759
4760 class A
4761 static val: number = 10
4762 endclass
4763
4764 def T()
4765 var a = A.new()
4766 a.val = 20
4767 enddef
4768 T()
4769 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004770 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004771
4772 # Reading a class variable using an object at function level
4773 lines =<< trim END
4774 vim9script
4775
4776 class A
4777 static val: number = 10
4778 endclass
4779 def T()
4780 var a = A.new()
4781 var i = a.val
4782 enddef
4783 T()
4784 END
4785 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4786enddef
4787
4788" Test for using a duplicate class method and class variable in a child class
4789def Test_dup_class_member()
4790 # duplicate class variable, class method and overridden object method
4791 var lines =<< trim END
4792 vim9script
4793 class A
4794 static sval = 100
4795 static def Check()
4796 assert_equal(100, sval)
4797 enddef
4798 def GetVal(): number
4799 return sval
4800 enddef
4801 endclass
4802
4803 class B extends A
4804 static sval = 200
4805 static def Check()
4806 assert_equal(200, sval)
4807 enddef
4808 def GetVal(): number
4809 return sval
4810 enddef
4811 endclass
4812
4813 def T1(aa: A): number
4814 return aa.GetVal()
4815 enddef
4816
4817 def T2(bb: B): number
4818 return bb.GetVal()
4819 enddef
4820
4821 assert_equal(100, A.sval)
4822 assert_equal(200, B.sval)
4823 var a = A.new()
4824 assert_equal(100, a.GetVal())
4825 var b = B.new()
4826 assert_equal(200, b.GetVal())
4827 assert_equal(200, T1(b))
4828 assert_equal(200, T2(b))
4829 END
4830 v9.CheckSourceSuccess(lines)
4831
4832 # duplicate class variable and class method
4833 lines =<< trim END
4834 vim9script
4835 class A
4836 static sval = 100
4837 static def Check()
4838 assert_equal(100, sval)
4839 enddef
4840 def GetVal(): number
4841 return sval
4842 enddef
4843 endclass
4844
4845 class B extends A
4846 static sval = 200
4847 static def Check()
4848 assert_equal(200, sval)
4849 enddef
4850 endclass
4851
4852 def T1(aa: A): number
4853 return aa.GetVal()
4854 enddef
4855
4856 def T2(bb: B): number
4857 return bb.GetVal()
4858 enddef
4859
4860 assert_equal(100, A.sval)
4861 assert_equal(200, B.sval)
4862 var a = A.new()
4863 assert_equal(100, a.GetVal())
4864 var b = B.new()
4865 assert_equal(100, b.GetVal())
4866 assert_equal(100, T1(b))
4867 assert_equal(100, T2(b))
4868 END
4869 v9.CheckSourceSuccess(lines)
4870enddef
4871
4872" Test for calling an instance method using the class
4873def Test_instance_method_call_using_class()
4874 # Invoke an object method using a class in script context
4875 var lines =<< trim END
4876 vim9script
4877 class A
4878 def Foo()
4879 echo "foo"
4880 enddef
4881 endclass
4882 A.Foo()
4883 END
4884 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4885
4886 # Invoke an object method using a class in def function context
4887 lines =<< trim END
4888 vim9script
4889 class A
4890 def Foo()
4891 echo "foo"
4892 enddef
4893 endclass
4894 def T()
4895 A.Foo()
4896 enddef
4897 T()
4898 END
4899 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4900enddef
4901
4902" Test for duplicate class method and instance method
4903def Test_dup_classmethod_objmethod()
4904 # Duplicate instance method
4905 var lines =<< trim END
4906 vim9script
4907 class A
4908 static def Foo()
4909 enddef
4910 def Foo()
4911 enddef
4912 endclass
4913 END
4914 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
4915
4916 # Duplicate private instance method
4917 lines =<< trim END
4918 vim9script
4919 class A
4920 static def Foo()
4921 enddef
4922 def _Foo()
4923 enddef
4924 endclass
4925 END
4926 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
4927
4928 # Duplicate class method
4929 lines =<< trim END
4930 vim9script
4931 class A
4932 def Foo()
4933 enddef
4934 static def Foo()
4935 enddef
4936 endclass
4937 END
4938 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
4939
4940 # Duplicate private class method
4941 lines =<< trim END
4942 vim9script
4943 class A
4944 def Foo()
4945 enddef
4946 static def _Foo()
4947 enddef
4948 endclass
4949 END
4950 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
4951
4952 # Duplicate private class and object method
4953 lines =<< trim END
4954 vim9script
4955 class A
4956 def _Foo()
4957 enddef
4958 static def _Foo()
4959 enddef
4960 endclass
4961 END
4962 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
4963enddef
4964
4965" Test for an instance method access level comparison with parent instance
4966" methods.
4967def Test_instance_method_access_level()
4968 # Private method in subclass
4969 var lines =<< trim END
4970 vim9script
4971 class A
4972 def Foo()
4973 enddef
4974 endclass
4975 class B extends A
4976 endclass
4977 class C extends B
4978 def _Foo()
4979 enddef
4980 endclass
4981 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004982 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004983
4984 # Public method in subclass
4985 lines =<< trim END
4986 vim9script
4987 class A
4988 def _Foo()
4989 enddef
4990 endclass
4991 class B extends A
4992 endclass
4993 class C extends B
4994 def Foo()
4995 enddef
4996 endclass
4997 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004998 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004999enddef
5000
5001def Test_extend_empty_class()
5002 var lines =<< trim END
5003 vim9script
5004 class A
5005 endclass
5006 class B extends A
5007 endclass
5008 class C extends B
5009 public static rw_class_var = 1
5010 public this.rw_obj_var = 2
5011 static def ClassMethod(): number
5012 return 3
5013 enddef
5014 def ObjMethod(): number
5015 return 4
5016 enddef
5017 endclass
5018 assert_equal(1, C.rw_class_var)
5019 assert_equal(3, C.ClassMethod())
5020 var c = C.new()
5021 assert_equal(2, c.rw_obj_var)
5022 assert_equal(4, c.ObjMethod())
5023 END
5024 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005025enddef
5026
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005027" A interface cannot have a static variable or a static method or a private
5028" variable or a private method
5029def Test_interface_with_unsupported_members()
5030 var lines =<< trim END
5031 vim9script
5032 interface A
5033 static num: number
5034 endinterface
5035 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005036 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005037
5038 lines =<< trim END
5039 vim9script
5040 interface A
5041 static _num: number
5042 endinterface
5043 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005044 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005045
5046 lines =<< trim END
5047 vim9script
5048 interface A
5049 public static num: number
5050 endinterface
5051 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005052 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005053
5054 lines =<< trim END
5055 vim9script
5056 interface A
5057 public static _num: number
5058 endinterface
5059 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005060 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005061
5062 lines =<< trim END
5063 vim9script
5064 interface A
5065 static def Foo(d: dict<any>): list<string>
5066 endinterface
5067 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005068 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005069
5070 lines =<< trim END
5071 vim9script
5072 interface A
5073 static def _Foo(d: dict<any>): list<string>
5074 endinterface
5075 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005076 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005077
5078 lines =<< trim END
5079 vim9script
5080 interface A
5081 this._Foo: list<string>
5082 endinterface
5083 END
5084 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface')
5085
5086 lines =<< trim END
5087 vim9script
5088 interface A
5089 def _Foo(d: dict<any>): list<string>
5090 endinterface
5091 END
5092 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface')
5093enddef
5094
5095" Test for extending an interface
5096def Test_extend_interface()
5097 var lines =<< trim END
5098 vim9script
5099 interface A
5100 this.var1: list<string>
5101 def Foo()
5102 endinterface
5103 interface B extends A
5104 public this.var2: dict<string>
5105 def Bar()
5106 endinterface
5107 class C implements A, B
5108 this.var1 = [1, 2]
5109 def Foo()
5110 enddef
5111 public this.var2 = {a: '1'}
5112 def Bar()
5113 enddef
5114 endclass
5115 END
5116 v9.CheckSourceSuccess(lines)
5117
5118 lines =<< trim END
5119 vim9script
5120 interface A
5121 def Foo()
5122 endinterface
5123 interface B extends A
5124 public this.var2: dict<string>
5125 endinterface
5126 class C implements A, B
5127 public this.var2 = {a: '1'}
5128 endclass
5129 END
5130 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented')
5131
5132 lines =<< trim END
5133 vim9script
5134 interface A
5135 def Foo()
5136 endinterface
5137 interface B extends A
5138 public this.var2: dict<string>
5139 endinterface
5140 class C implements A, B
5141 def Foo()
5142 enddef
5143 endclass
5144 END
5145 v9.CheckSourceFailure(lines, 'E1348: Member "var2" of interface "B" is not implemented')
5146
5147 # interface cannot extend a class
5148 lines =<< trim END
5149 vim9script
5150 class A
5151 endclass
5152 interface B extends A
5153 endinterface
5154 END
5155 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5156
5157 # class cannot extend an interface
5158 lines =<< trim END
5159 vim9script
5160 interface A
5161 endinterface
5162 class B extends A
5163 endclass
5164 END
5165 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5166
5167 # interface cannot implement another interface
5168 lines =<< trim END
5169 vim9script
5170 interface A
5171 endinterface
5172 interface B implements A
5173 endinterface
5174 END
5175 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"')
5176
5177 # interface cannot extend multiple interfaces
5178 lines =<< trim END
5179 vim9script
5180 interface A
5181 endinterface
5182 interface B
5183 endinterface
5184 interface C extends A, B
5185 endinterface
5186 END
5187 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B')
5188
5189 # Variable type in an extended interface is of different type
5190 lines =<< trim END
5191 vim9script
5192 interface A
5193 this.val1: number
5194 endinterface
5195 interface B extends A
5196 this.val2: string
5197 endinterface
5198 interface C extends B
5199 this.val1: string
5200 this.val2: number
5201 endinterface
5202 END
5203 v9.CheckSourceFailure(lines, 'E1382: Member "val1": type mismatch, expected number but got string')
5204enddef
5205
5206" Test for a child class implementing an interface when some of the methods are
5207" defined in the parent class.
5208def Test_child_class_implements_interface()
5209 var lines =<< trim END
5210 vim9script
5211
5212 interface Intf
5213 def F1(): list<list<number>>
5214 def F2(): list<list<number>>
5215 def F3(): list<list<number>>
5216 this.var1: list<dict<number>>
5217 this.var2: list<dict<number>>
5218 this.var3: list<dict<number>>
5219 endinterface
5220
5221 class A
5222 def A1()
5223 enddef
5224 def F3(): list<list<number>>
5225 return [[3]]
5226 enddef
5227 this.v1: list<list<number>> = [[0]]
5228 this.var3 = [{c: 30}]
5229 endclass
5230
5231 class B extends A
5232 def B1()
5233 enddef
5234 def F2(): list<list<number>>
5235 return [[2]]
5236 enddef
5237 this.v2: list<list<number>> = [[0]]
5238 this.var2 = [{b: 20}]
5239 endclass
5240
5241 class C extends B implements Intf
5242 def C1()
5243 enddef
5244 def F1(): list<list<number>>
5245 return [[1]]
5246 enddef
5247 this.v3: list<list<number>> = [[0]]
5248 this.var1 = [{a: 10}]
5249 endclass
5250
5251 def T(if: Intf)
5252 assert_equal([[1]], if.F1())
5253 assert_equal([[2]], if.F2())
5254 assert_equal([[3]], if.F3())
5255 assert_equal([{a: 10}], if.var1)
5256 assert_equal([{b: 20}], if.var2)
5257 assert_equal([{c: 30}], if.var3)
5258 enddef
5259
5260 var c = C.new()
5261 T(c)
5262 assert_equal([[1]], c.F1())
5263 assert_equal([[2]], c.F2())
5264 assert_equal([[3]], c.F3())
5265 assert_equal([{a: 10}], c.var1)
5266 assert_equal([{b: 20}], c.var2)
5267 assert_equal([{c: 30}], c.var3)
5268 END
5269 v9.CheckSourceSuccess(lines)
5270
5271 # One of the interface methods is not found
5272 lines =<< trim END
5273 vim9script
5274
5275 interface Intf
5276 def F1()
5277 def F2()
5278 def F3()
5279 endinterface
5280
5281 class A
5282 def A1()
5283 enddef
5284 endclass
5285
5286 class B extends A
5287 def B1()
5288 enddef
5289 def F2()
5290 enddef
5291 endclass
5292
5293 class C extends B implements Intf
5294 def C1()
5295 enddef
5296 def F1()
5297 enddef
5298 endclass
5299 END
5300 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented')
5301
5302 # One of the interface methods is of different type
5303 lines =<< trim END
5304 vim9script
5305
5306 interface Intf
5307 def F1()
5308 def F2()
5309 def F3()
5310 endinterface
5311
5312 class A
5313 def F3(): number
5314 return 0
5315 enddef
5316 def A1()
5317 enddef
5318 endclass
5319
5320 class B extends A
5321 def B1()
5322 enddef
5323 def F2()
5324 enddef
5325 endclass
5326
5327 class C extends B implements Intf
5328 def C1()
5329 enddef
5330 def F1()
5331 enddef
5332 endclass
5333 END
5334 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number')
5335
5336 # One of the interface variables is not present
5337 lines =<< trim END
5338 vim9script
5339
5340 interface Intf
5341 this.var1: list<dict<number>>
5342 this.var2: list<dict<number>>
5343 this.var3: list<dict<number>>
5344 endinterface
5345
5346 class A
5347 this.v1: list<list<number>> = [[0]]
5348 endclass
5349
5350 class B extends A
5351 this.v2: list<list<number>> = [[0]]
5352 this.var2 = [{b: 20}]
5353 endclass
5354
5355 class C extends B implements Intf
5356 this.v3: list<list<number>> = [[0]]
5357 this.var1 = [{a: 10}]
5358 endclass
5359 END
5360 v9.CheckSourceFailure(lines, 'E1348: Member "var3" of interface "Intf" is not implemented')
5361
5362 # One of the interface variables is of different type
5363 lines =<< trim END
5364 vim9script
5365
5366 interface Intf
5367 this.var1: list<dict<number>>
5368 this.var2: list<dict<number>>
5369 this.var3: list<dict<number>>
5370 endinterface
5371
5372 class A
5373 this.v1: list<list<number>> = [[0]]
5374 this.var3: list<dict<string>>
5375 endclass
5376
5377 class B extends A
5378 this.v2: list<list<number>> = [[0]]
5379 this.var2 = [{b: 20}]
5380 endclass
5381
5382 class C extends B implements Intf
5383 this.v3: list<list<number>> = [[0]]
5384 this.var1 = [{a: 10}]
5385 endclass
5386 END
5387 v9.CheckSourceFailure(lines, 'E1382: Member "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>')
5388enddef
5389
5390" Test for extending an interface with duplicate variables and methods
5391def Test_interface_extends_with_dup_members()
5392 var lines =<< trim END
5393 vim9script
5394 interface A
5395 this.n1: number
5396 def Foo1(): number
5397 endinterface
5398 interface B extends A
5399 this.n2: number
5400 this.n1: number
5401 def Foo2(): number
5402 def Foo1(): number
5403 endinterface
5404 class C implements B
5405 this.n1 = 10
5406 this.n2 = 20
5407 def Foo1(): number
5408 return 30
5409 enddef
5410 def Foo2(): number
5411 return 40
5412 enddef
5413 endclass
5414 def T1(a: A)
5415 assert_equal(10, a.n1)
5416 assert_equal(30, a.Foo1())
5417 enddef
5418 def T2(b: B)
5419 assert_equal(10, b.n1)
5420 assert_equal(20, b.n2)
5421 assert_equal(30, b.Foo1())
5422 assert_equal(40, b.Foo2())
5423 enddef
5424 var c = C.new()
5425 T1(c)
5426 T2(c)
5427 END
5428 v9.CheckSourceSuccess(lines)
5429enddef
5430
5431" Test for using "any" type for a variable in a sub-class while it has a
5432" concrete type in the interface
5433def Test_implements_using_var_type_any()
5434 var lines =<< trim END
5435 vim9script
5436 interface A
5437 this.val: list<dict<string>>
5438 endinterface
5439 class B implements A
5440 this.val = [{a: '1'}, {b: '2'}]
5441 endclass
5442 var b = B.new()
5443 assert_equal([{a: '1'}, {b: '2'}], b.val)
5444 END
5445 v9.CheckSourceSuccess(lines)
5446
5447 # initialize instance variable using a different type
5448 lines =<< trim END
5449 vim9script
5450 interface A
5451 this.val: list<dict<string>>
5452 endinterface
5453 class B implements A
5454 this.val = {a: 1, b: 2}
5455 endclass
5456 var b = B.new()
5457 END
5458 v9.CheckSourceFailure(lines, 'E1382: Member "val": type mismatch, expected list<dict<string>> but got dict<number>')
5459enddef
5460
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005461" Test for assigning to a member variable in a nested class
5462def Test_nested_object_assignment()
5463 var lines =<< trim END
5464 vim9script
5465
5466 class A
5467 this.value: number
5468 endclass
5469
5470 class B
5471 this.a: A = A.new()
5472 endclass
5473
5474 class C
5475 this.b: B = B.new()
5476 endclass
5477
5478 class D
5479 this.c: C = C.new()
5480 endclass
5481
5482 def T(da: D)
5483 da.c.b.a.value = 10
5484 enddef
5485
5486 var d = D.new()
5487 T(d)
5488 END
5489 v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "value"')
5490enddef
5491
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02005492" Test for calling methods using a null object
5493def Test_null_object_method_call()
5494 # Calling a object method using a null object in script context
5495 var lines =<< trim END
5496 vim9script
5497
5498 class C
5499 def Foo()
5500 assert_report('This method should not be executed')
5501 enddef
5502 endclass
5503
5504 var o: C
5505 o.Foo()
5506 END
5507 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
5508
5509 # Calling a object method using a null object in def function context
5510 lines =<< trim END
5511 vim9script
5512
5513 class C
5514 def Foo()
5515 assert_report('This method should not be executed')
5516 enddef
5517 endclass
5518
5519 def T()
5520 var o: C
5521 o.Foo()
5522 enddef
5523 T()
5524 END
5525 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5526
5527 # Calling a object method through another class method using a null object in
5528 # script context
5529 lines =<< trim END
5530 vim9script
5531
5532 class C
5533 def Foo()
5534 assert_report('This method should not be executed')
5535 enddef
5536
5537 static def Bar(o_any: any)
5538 var o_typed: C = o_any
5539 o_typed.Foo()
5540 enddef
5541 endclass
5542
5543 var o: C
5544 C.Bar(o)
5545 END
5546 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5547
5548 # Calling a object method through another class method using a null object in
5549 # def function context
5550 lines =<< trim END
5551 vim9script
5552
5553 class C
5554 def Foo()
5555 assert_report('This method should not be executed')
5556 enddef
5557
5558 static def Bar(o_any: any)
5559 var o_typed: C = o_any
5560 o_typed.Foo()
5561 enddef
5562 endclass
5563
5564 def T()
5565 var o: C
5566 C.Bar(o)
5567 enddef
5568 T()
5569 END
5570 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5571enddef
5572
5573" Test for using a dict as an object member
5574def Test_dict_object_member()
5575 var lines =<< trim END
5576 vim9script
5577
5578 class Context
5579 public this.state: dict<number> = {}
5580 def GetState(): dict<number>
5581 return this.state
5582 enddef
5583 endclass
5584
5585 var ctx = Context.new()
5586 ctx.state->extend({a: 1})
5587 ctx.state['b'] = 2
5588 assert_equal({a: 1, b: 2}, ctx.GetState())
5589
5590 def F()
5591 ctx.state['c'] = 3
5592 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
5593 enddef
5594 F()
5595 assert_equal(3, ctx.state.c)
5596 ctx.state.c = 4
5597 assert_equal(4, ctx.state.c)
5598 END
5599 v9.CheckSourceSuccess(lines)
5600enddef
5601
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005602" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker