blob: 87679d814a9afcbbf70c5c1cb9b304fe19ecb272 [file] [log] [blame]
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001" Test Vim9 classes
2
3source check.vim
4import './vim9.vim' as v9
5
6def Test_class_basic()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007 # Class supported only in "vim9script"
Bram Moolenaar00b28d62022-12-08 15:32:33 +00008 var lines =<< trim END
9 class NotWorking
10 endclass
11 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020012 v9.CheckSourceFailure(lines, 'E1316:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000013
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020014 # First character in a class name should be capitalized.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000015 lines =<< trim END
16 vim9script
17 class notWorking
18 endclass
19 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020020 v9.CheckSourceFailure(lines, 'E1314:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000021
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020022 # Only alphanumeric characters are supported in a class name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000023 lines =<< trim END
24 vim9script
25 class Not@working
26 endclass
27 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020028 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000029
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020030 # Unsupported keyword (instead of class)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000031 lines =<< trim END
32 vim9script
33 abstract noclass Something
34 endclass
35 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020036 v9.CheckSourceFailure(lines, 'E475:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000037
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020038 # Only the completed word "class" should be recognized
Bram Moolenaar00b28d62022-12-08 15:32:33 +000039 lines =<< trim END
40 vim9script
41 abstract classy Something
42 endclass
43 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020044 v9.CheckSourceFailure(lines, 'E475:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000045
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020046 # The complete "endclass" should be specified.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000047 lines =<< trim END
48 vim9script
49 class Something
50 endcl
51 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020052 v9.CheckSourceFailure(lines, 'E1065:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000053
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020054 # Additional words after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000055 lines =<< trim END
56 vim9script
57 class Something
Bram Moolenaar94722c52023-01-28 19:19:03 +000058 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000059 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020060 v9.CheckSourceFailure(lines, 'E488:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000061
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020062 # Additional commands after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000063 lines =<< trim END
64 vim9script
65 class Something
66 endclass | echo 'done'
67 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020068 v9.CheckSourceFailure(lines, 'E488:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000069
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020070 # Use "this" without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000071 lines =<< trim END
72 vim9script
73 class Something
74 this
75 endclass
76 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020077 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000078
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020079 # Use "this." without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000080 lines =<< trim END
81 vim9script
82 class Something
83 this.
84 endclass
85 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020086 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000087
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020088 # Space between "this" and ".<variable>"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000089 lines =<< trim END
90 vim9script
91 class Something
92 this .count
93 endclass
94 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +020095 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +000096
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020097 # Space between "this." and the member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000098 lines =<< trim END
99 vim9script
100 class Something
101 this. count
102 endclass
103 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200104 v9.CheckSourceFailure(lines, 'E1317:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000105
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200106 # Use "that" instead of "this"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000107 lines =<< trim END
108 vim9script
109 class Something
110 this.count: number
111 that.count
112 endclass
113 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200114 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000115
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200116 # Member variable without a type or initialization
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000117 lines =<< trim END
118 vim9script
119 class Something
120 this.count
121 endclass
122 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200123 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000124
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200125 # Use a non-existing member variable in new()
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000126 lines =<< trim END
127 vim9script
128 class Something
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000129 def new()
130 this.state = 0
131 enddef
132 endclass
133 var obj = Something.new()
134 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200135 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Something": state')
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000136
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200137 # Space before ":" in a member variable declaration
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000138 lines =<< trim END
139 vim9script
140 class Something
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000141 this.count : number
142 endclass
143 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200144 v9.CheckSourceFailure(lines, 'E1059:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000145
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200146 # No space after ":" in a member variable declaration
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000147 lines =<< trim END
148 vim9script
149 class Something
150 this.count:number
151 endclass
152 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200153 v9.CheckSourceFailure(lines, 'E1069:')
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000154
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200155 # Test for unsupported comment specifier
156 lines =<< trim END
157 vim9script
158 class Something
159 # comment
160 #{
161 endclass
162 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200163 v9.CheckSourceFailure(lines, 'E1170:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200164
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200165 # Test for using class as a bool
166 lines =<< trim END
167 vim9script
168 class A
169 endclass
170 if A
171 endif
172 END
173 v9.CheckSourceFailure(lines, 'E1319: Using a class as a Number')
174
175 # Test for using object as a bool
176 lines =<< trim END
177 vim9script
178 class A
179 endclass
180 var a = A.new()
181 if a
182 endif
183 END
184 v9.CheckSourceFailure(lines, 'E1320: Using an object as a Number')
185
186 # Test for using class as a float
187 lines =<< trim END
188 vim9script
189 class A
190 endclass
191 sort([1.1, A], 'f')
192 END
193 v9.CheckSourceFailure(lines, 'E1321: Using a class as a Float')
194
195 # Test for using object as a float
196 lines =<< trim END
197 vim9script
198 class A
199 endclass
200 var a = A.new()
201 sort([1.1, a], 'f')
202 END
203 v9.CheckSourceFailure(lines, 'E1322: Using an object as a Float')
204
205 # Test for using class as a string
206 lines =<< trim END
207 vim9script
208 class A
209 endclass
210 :exe 'call ' .. A
211 END
212 v9.CheckSourceFailure(lines, 'E1323: Using a class as a String')
213
214 # Test for using object as a string
215 lines =<< trim END
216 vim9script
217 class A
218 endclass
219 var a = A.new()
220 :exe 'call ' .. a
221 END
222 v9.CheckSourceFailure(lines, 'E1324: Using an object as a String')
223
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200224 # Test creating a class with member variables and methods, calling a object
225 # method. Check for using type() and typename() with a class and an object.
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000226 lines =<< trim END
227 vim9script
228
229 class TextPosition
230 this.lnum: number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000231 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000232
Bram Moolenaar418b5472022-12-20 13:38:22 +0000233 # make a nicely formatted string
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000234 def ToString(): string
235 return $'({this.lnum}, {this.col})'
236 enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000237 endclass
238
Bram Moolenaard28d7b92022-12-08 20:42:00 +0000239 # use the automatically generated new() method
240 var pos = TextPosition.new(2, 12)
241 assert_equal(2, pos.lnum)
242 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000243
244 # call an object method
245 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000246
247 assert_equal(v:t_class, type(TextPosition))
248 assert_equal(v:t_object, type(pos))
249 assert_equal('class<TextPosition>', typename(TextPosition))
250 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000251 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200252 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200253
254 # When referencing object methods, space cannot be used after a "."
255 lines =<< trim END
256 vim9script
257 class A
258 def Foo(): number
259 return 10
260 enddef
261 endclass
262 var a = A.new()
263 var v = a. Foo()
264 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200265 v9.CheckSourceFailure(lines, 'E1202:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200266
267 # Using an object without specifying a method or a member variable
268 lines =<< trim END
269 vim9script
270 class A
271 def Foo(): number
272 return 10
273 enddef
274 endclass
275 var a = A.new()
276 var v = a.
277 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200278 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200279
280 # Error when parsing the arguments of an object method.
281 lines =<< trim END
282 vim9script
283 class A
284 def Foo()
285 enddef
286 endclass
287 var a = A.new()
288 var v = a.Foo(,)
289 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200290 v9.CheckSourceFailure(lines, 'E15:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200291
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200292 # Use a multi-line initialization for a member variable
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200293 lines =<< trim END
294 vim9script
295 class A
296 this.y = {
297 X: 1
298 }
299 endclass
300 var a = A.new()
301 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200302 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000303enddef
304
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000305def Test_class_defined_twice()
306 # class defined twice should fail
307 var lines =<< trim END
308 vim9script
309 class There
310 endclass
311 class There
312 endclass
313 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200314 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"')
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000315
316 # one class, reload same script twice is OK
317 lines =<< trim END
318 vim9script
319 class There
320 endclass
321 END
322 writefile(lines, 'XclassTwice.vim', 'D')
323 source XclassTwice.vim
324 source XclassTwice.vim
325enddef
326
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000327def Test_returning_null_object()
328 # this was causing an internal error
329 var lines =<< trim END
330 vim9script
331
332 class BufferList
333 def Current(): any
334 return null_object
335 enddef
336 endclass
337
338 var buffers = BufferList.new()
339 echo buffers.Current()
340 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200341 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000342enddef
343
Bram Moolenaard13dd302023-03-11 20:56:35 +0000344def Test_using_null_class()
345 var lines =<< trim END
346 @_ = null_class.member
347 END
348 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
349enddef
350
Bram Moolenaar657aea72023-01-27 13:16:19 +0000351def Test_class_interface_wrong_end()
352 var lines =<< trim END
353 vim9script
354 abstract class SomeName
355 this.member = 'text'
356 endinterface
357 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200358 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000359
360 lines =<< trim END
361 vim9script
362 export interface AnotherName
363 this.member: string
364 endclass
365 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200366 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000367enddef
368
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000369def Test_object_not_set()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200370 # Use an uninitialized object in script context
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000371 var lines =<< trim END
372 vim9script
373
374 class State
375 this.value = 'xyz'
376 endclass
377
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000378 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000379 var db = {'xyz': 789}
380 echo db[state.value]
381 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200382 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000383
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200384 # Use an uninitialized object from a def function
Bram Moolenaar0917e862023-02-18 14:42:44 +0000385 lines =<< trim END
386 vim9script
387
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000388 class Class
389 this.id: string
390 def Method1()
391 echo 'Method1' .. this.id
392 enddef
393 endclass
394
395 var obj: Class
396 def Func()
397 obj.Method1()
398 enddef
399 Func()
400 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200401 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000402
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200403 # Pass an uninitialized object variable to a "new" function and try to call an
404 # object method.
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000405 lines =<< trim END
406 vim9script
407
Bram Moolenaar0917e862023-02-18 14:42:44 +0000408 class Background
409 this.background = 'dark'
410 endclass
411
412 class Colorscheme
413 this._bg: Background
414
415 def GetBackground(): string
416 return this._bg.background
417 enddef
418 endclass
419
420 var bg: Background # UNINITIALIZED
421 echo Colorscheme.new(bg).GetBackground()
422 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200423 v9.CheckSourceFailure(lines, 'E1360:')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000424
425 # TODO: this should not give an error but be handled at runtime
426 lines =<< trim END
427 vim9script
428
429 class Class
430 this.id: string
431 def Method1()
432 echo 'Method1' .. this.id
433 enddef
434 endclass
435
436 var obj = null_object
437 def Func()
438 obj.Method1()
439 enddef
440 Func()
441 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200442 v9.CheckSourceFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000443enddef
444
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200445" Null object assignment and comparison
Ernie Rael5c018be2023-08-27 18:40:26 +0200446def Test_null_object_assign_compare()
447 var lines =<< trim END
448 vim9script
449
450 var nullo = null_object
451 def F(): any
452 return nullo
453 enddef
454 assert_equal('object<Unknown>', typename(F()))
455
456 var o0 = F()
457 assert_true(o0 == null_object)
458 assert_true(o0 == null)
459
460 var o1: any = nullo
461 assert_true(o1 == null_object)
462 assert_true(o1 == null)
463
464 def G()
465 var x = null_object
466 enddef
467
468 class C
469 endclass
470 var o2: C
471 assert_true(o2 == null_object)
472 assert_true(o2 == null)
473
474 o2 = null_object
475 assert_true(o2 == null)
476
477 o2 = C.new()
478 assert_true(o2 != null)
479
480 o2 = null_object
481 assert_true(o2 == null)
482 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200483 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200484enddef
485
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200486" Test for object member initialization and disassembly
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000487def Test_class_member_initializer()
488 var lines =<< trim END
489 vim9script
490
491 class TextPosition
492 this.lnum: number = 1
493 this.col: number = 1
494
Bram Moolenaar418b5472022-12-20 13:38:22 +0000495 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000496 def new(lnum: number)
497 this.lnum = lnum
498 enddef
499 endclass
500
501 var pos = TextPosition.new(3)
502 assert_equal(3, pos.lnum)
503 assert_equal(1, pos.col)
504
505 var instr = execute('disassemble TextPosition.new')
506 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000507 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000508 '\d PUSHNR 1\_s*' ..
509 '\d STORE_THIS 0\_s*' ..
510 '\d PUSHNR 1\_s*' ..
511 '\d STORE_THIS 1\_s*' ..
512 'this.lnum = lnum\_s*' ..
513 '\d LOAD arg\[-1]\_s*' ..
514 '\d PUSHNR 0\_s*' ..
515 '\d LOAD $0\_s*' ..
516 '\d\+ STOREINDEX object\_s*' ..
517 '\d\+ RETURN object.*',
518 instr)
519 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200520 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000521enddef
522
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000523def Test_member_any_used_as_object()
524 var lines =<< trim END
525 vim9script
526
527 class Inner
528 this.value: number = 0
529 endclass
530
531 class Outer
532 this.inner: any
533 endclass
534
535 def F(outer: Outer)
536 outer.inner.value = 1
537 enddef
538
539 var inner_obj = Inner.new(0)
540 var outer_obj = Outer.new(inner_obj)
541 F(outer_obj)
542 assert_equal(1, inner_obj.value)
543 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200544 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000545
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200546 # Try modifying a private variable using an "any" object
547 lines =<< trim END
548 vim9script
549
550 class Inner
551 this._value: string = ''
552 endclass
553
554 class Outer
555 this.inner: any
556 endclass
557
558 def F(outer: Outer)
559 outer.inner._value = 'b'
560 enddef
561
562 var inner_obj = Inner.new('a')
563 var outer_obj = Outer.new(inner_obj)
564 F(outer_obj)
565 END
566 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _value')
567
568 # Try modifying a non-existing variable using an "any" object
569 lines =<< trim END
570 vim9script
571
572 class Inner
573 this.value: string = ''
574 endclass
575
576 class Outer
577 this.inner: any
578 endclass
579
580 def F(outer: Outer)
581 outer.inner.someval = 'b'
582 enddef
583
584 var inner_obj = Inner.new('a')
585 var outer_obj = Outer.new(inner_obj)
586 F(outer_obj)
587 END
588 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Inner": someval')
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000589enddef
590
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200591" Nested assignment to a object variable which is of another class type
592def Test_assignment_nested_type()
593 var lines =<< trim END
594 vim9script
595
596 class Inner
597 public this.value: number = 0
598 endclass
599
600 class Outer
601 this.inner: Inner
602 endclass
603
604 def F(outer: Outer)
605 outer.inner.value = 1
606 enddef
607
608 def Test_assign_to_nested_typed_member()
609 var inner = Inner.new(0)
610 var outer = Outer.new(inner)
611 F(outer)
612 assert_equal(1, inner.value)
613 enddef
614
615 Test_assign_to_nested_typed_member()
Ernie Rael98e68c02023-09-20 20:13:06 +0200616
617 var script_inner = Inner.new(0)
618 var script_outer = Outer.new(script_inner)
619 script_outer.inner.value = 1
620 assert_equal(1, script_inner.value)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200621 END
622 v9.CheckSourceSuccess(lines)
Ernie Rael98e68c02023-09-20 20:13:06 +0200623
624 # Assignment where target item is read only in :def
625 lines =<< trim END
626 vim9script
627
628 class Inner
629 this.value: number = 0
630 endclass
631
632 class Outer
633 this.inner: Inner
634 endclass
635
636 def F(outer: Outer)
637 outer.inner.value = 1
638 enddef
639
640 def Test_assign_to_nested_typed_member()
641 var inner = Inner.new(0)
642 var outer = Outer.new(inner)
643 F(outer)
644 assert_equal(1, inner.value)
645 enddef
646
647 Test_assign_to_nested_typed_member()
648 END
Ernie Rael696270b2023-09-21 16:42:28 +0200649 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable')
Ernie Rael98e68c02023-09-20 20:13:06 +0200650
651 # Assignment where target item is read only script level
652 lines =<< trim END
653 vim9script
654
655 class Inner
656 this.value: number = 0
657 endclass
658
659 class Outer
660 this.inner: Inner
661 endclass
662
663 def F(outer: Outer)
664 outer.inner.value = 1
665 enddef
666
667 var script_inner = Inner.new(0)
668 var script_outer = Outer.new(script_inner)
669 script_outer.inner.value = 1
670 assert_equal(1, script_inner.value)
671 END
Ernie Rael696270b2023-09-21 16:42:28 +0200672 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200673enddef
674
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000675def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200676 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000677 var lines =<< trim END
678 vim9script
679
680 class Foo
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200681 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000682
683 def Add(n: number)
684 this.x += n
685 enddef
686 endclass
687
688 var f = Foo.new(3)
689 f.Add(17)
690 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100691
692 def AddToFoo(obj: Foo)
693 obj.x += 3
694 enddef
695
696 AddToFoo(f)
697 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000698 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200699 v9.CheckSourceSuccess(lines)
Ernie Rael18143d32023-09-04 22:30:41 +0200700
701 # do the same thing, but through an interface
702 lines =<< trim END
703 vim9script
704
705 interface I
706 public this.x: number
707 endinterface
708
709 class Foo implements I
710 public this.x: number
711
712 def Add(n: number)
713 var i: I = this
714 i.x += n
715 enddef
716 endclass
717
718 var f = Foo.new(3)
719 f.Add(17)
720 assert_equal(20, f.x)
721
722 def AddToFoo(i: I)
723 i.x += 3
724 enddef
725
726 AddToFoo(f)
727 assert_equal(23, f.x)
728 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200729 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000730enddef
731
Bram Moolenaarf4508042023-01-15 16:54:57 +0000732def Test_list_of_objects()
733 var lines =<< trim END
734 vim9script
735
736 class Foo
737 def Add()
738 enddef
739 endclass
740
741 def ProcessList(fooList: list<Foo>)
742 for foo in fooList
743 foo.Add()
744 endfor
745 enddef
746
747 var l: list<Foo> = [Foo.new()]
748 ProcessList(l)
749 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200750 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000751enddef
752
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000753def Test_expr_after_using_object()
754 var lines =<< trim END
755 vim9script
756
757 class Something
758 this.label: string = ''
759 endclass
760
761 def Foo(): Something
762 var v = Something.new()
763 echo 'in Foo(): ' .. typename(v)
764 return v
765 enddef
766
767 Foo()
768 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200769 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000770enddef
771
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000772def Test_class_default_new()
773 var lines =<< trim END
774 vim9script
775
776 class TextPosition
777 this.lnum: number = 1
778 this.col: number = 1
779 endclass
780
781 var pos = TextPosition.new()
782 assert_equal(1, pos.lnum)
783 assert_equal(1, pos.col)
784
785 pos = TextPosition.new(v:none, v:none)
786 assert_equal(1, pos.lnum)
787 assert_equal(1, pos.col)
788
789 pos = TextPosition.new(3, 22)
790 assert_equal(3, pos.lnum)
791 assert_equal(22, pos.col)
792
793 pos = TextPosition.new(v:none, 33)
794 assert_equal(1, pos.lnum)
795 assert_equal(33, pos.col)
796 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200797 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000798
799 lines =<< trim END
800 vim9script
801 class Person
802 this.name: string
803 this.age: number = 42
804 this.education: string = "unknown"
805
806 def new(this.name, this.age = v:none, this.education = v:none)
807 enddef
808 endclass
809
810 var piet = Person.new("Piet")
811 assert_equal("Piet", piet.name)
812 assert_equal(42, piet.age)
813 assert_equal("unknown", piet.education)
814
815 var chris = Person.new("Chris", 4, "none")
816 assert_equal("Chris", chris.name)
817 assert_equal(4, chris.age)
818 assert_equal("none", chris.education)
819 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200820 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000821
822 lines =<< trim END
823 vim9script
824 class Person
825 this.name: string
826 this.age: number = 42
827 this.education: string = "unknown"
828
829 def new(this.name, this.age = v:none, this.education = v:none)
830 enddef
831 endclass
832
833 var missing = Person.new()
834 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200835 v9.CheckSourceFailure(lines, 'E119:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200836
837 # Using a specific value to initialize an instance variable in the new()
838 # method.
839 lines =<< trim END
840 vim9script
841 class A
842 this.val: string
843 def new(this.val = 'a')
844 enddef
845 endclass
846 END
847 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'")
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000848enddef
849
h-east2261c892023-08-16 21:49:54 +0900850def Test_class_new_with_object_member()
851 var lines =<< trim END
852 vim9script
853
854 class C
855 this.str: string
856 this.num: number
857 def new(this.str, this.num)
858 enddef
859 def newVals(this.str, this.num)
860 enddef
861 endclass
862
863 def Check()
864 try
865 var c = C.new('cats', 2)
866 assert_equal('cats', c.str)
867 assert_equal(2, c.num)
868
869 c = C.newVals('dogs', 4)
870 assert_equal('dogs', c.str)
871 assert_equal(4, c.num)
872 catch
873 assert_report($'Unexpected exception was caught: {v:exception}')
874 endtry
875 enddef
876
877 Check()
878 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200879 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900880
881 lines =<< trim END
882 vim9script
883
884 class C
885 this.str: string
886 this.num: number
887 def new(this.str, this.num)
888 enddef
889 endclass
890
891 def Check()
892 try
893 var c = C.new(1, 2)
894 catch
895 assert_report($'Unexpected exception was caught: {v:exception}')
896 endtry
897 enddef
898
899 Check()
900 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200901 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900902
903 lines =<< trim END
904 vim9script
905
906 class C
907 this.str: string
908 this.num: number
909 def newVals(this.str, this.num)
910 enddef
911 endclass
912
913 def Check()
914 try
915 var c = C.newVals('dogs', 'apes')
916 catch
917 assert_report($'Unexpected exception was caught: {v:exception}')
918 endtry
919 enddef
920
921 Check()
922 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200923 v9.CheckSourceFailure(lines, 'E1013:')
h-eastb895b0f2023-09-24 15:46:31 +0200924
925 lines =<< trim END
926 vim9script
927
928 class C
929 this.str: string
930 def new(str: any)
931 enddef
932 endclass
933
934 def Check()
935 try
936 var c = C.new(1)
937 catch
938 assert_report($'Unexpected exception was caught: {v:exception}')
939 endtry
940 enddef
941
942 Check()
943 END
944 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900945enddef
946
Bram Moolenaar74e12742022-12-13 21:14:28 +0000947def Test_class_object_member_inits()
948 var lines =<< trim END
949 vim9script
950 class TextPosition
951 this.lnum: number
952 this.col = 1
953 this.addcol: number = 2
954 endclass
955
956 var pos = TextPosition.new()
957 assert_equal(0, pos.lnum)
958 assert_equal(1, pos.col)
959 assert_equal(2, pos.addcol)
960 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200961 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000962
963 lines =<< trim END
964 vim9script
965 class TextPosition
966 this.lnum
967 this.col = 1
968 endclass
969 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200970 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar74e12742022-12-13 21:14:28 +0000971
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200972 # If the type is not specified for a member, then it should be set during
973 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +0000974 lines =<< trim END
975 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200976
977 var init_count = 0
978 def Init(): string
979 init_count += 1
980 return 'foo'
981 enddef
982
983 class A
984 this.str1 = Init()
985 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000986 this.col = 1
987 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200988
989 assert_equal(init_count, 0)
990 var a = A.new()
991 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000992 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200993 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200994
995 # Test for initializing an object member with an unknown variable/type
996 lines =<< trim END
997 vim9script
998 class A
999 this.value = init_val
1000 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001001 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001002 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001003 v9.CheckSourceFailure(lines, 'E1001:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001004
1005 # Test for initializing an object member with an special type
1006 lines =<< trim END
1007 vim9script
1008 class A
1009 this.value: void
1010 endclass
1011 END
1012 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object member: void')
Bram Moolenaar74e12742022-12-13 21:14:28 +00001013enddef
1014
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001015" Test for instance variable access
1016def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001017 var lines =<< trim END
1018 vim9script
1019 class Triple
1020 this._one = 1
1021 this.two = 2
1022 public this.three = 3
1023
1024 def GetOne(): number
1025 return this._one
1026 enddef
1027 endclass
1028
1029 var trip = Triple.new()
1030 assert_equal(1, trip.GetOne())
1031 assert_equal(2, trip.two)
1032 assert_equal(3, trip.three)
1033 assert_fails('echo trip._one', 'E1333')
1034
1035 assert_fails('trip._one = 11', 'E1333')
1036 assert_fails('trip.two = 22', 'E1335')
1037 trip.three = 33
1038 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001039
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001040 assert_fails('trip.four = 4', 'E1326')
Bram Moolenaard505d172022-12-18 21:42:55 +00001041 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001042 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001043
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001044 # Test for a public member variable name beginning with an underscore
1045 lines =<< trim END
1046 vim9script
1047 class A
1048 public this._val = 10
1049 endclass
1050 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001051 v9.CheckSourceFailure(lines, 'E1332:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001052
Bram Moolenaar590162c2022-12-24 21:24:06 +00001053 lines =<< trim END
1054 vim9script
1055
1056 class MyCar
1057 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +00001058 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001059
1060 def new(make_arg: string)
1061 this.make = make_arg
1062 enddef
1063
1064 def GetMake(): string
1065 return $"make = {this.make}"
1066 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +00001067 def GetAge(): number
1068 return this.age
1069 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +00001070 endclass
1071
1072 var c = MyCar.new("abc")
1073 assert_equal('make = abc', c.GetMake())
1074
1075 c = MyCar.new("def")
1076 assert_equal('make = def', c.GetMake())
1077
1078 var c2 = MyCar.new("123")
1079 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +00001080
1081 def CheckCar()
1082 assert_equal("make = def", c.GetMake())
1083 assert_equal(5, c.GetAge())
1084 enddef
1085 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001086 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001087 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001088
1089 lines =<< trim END
1090 vim9script
1091
1092 class MyCar
1093 this.make: string
1094
1095 def new(make_arg: string)
1096 this.make = make_arg
1097 enddef
1098 endclass
1099
1100 var c = MyCar.new("abc")
1101 var c = MyCar.new("def")
1102 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001103 v9.CheckSourceFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +00001104
1105 lines =<< trim END
1106 vim9script
1107
1108 class Foo
1109 this.x: list<number> = []
1110
1111 def Add(n: number): any
1112 this.x->add(n)
1113 return this
1114 enddef
1115 endclass
1116
1117 echo Foo.new().Add(1).Add(2).x
1118 echo Foo.new().Add(1).Add(2)
1119 .x
1120 echo Foo.new().Add(1)
1121 .Add(2).x
1122 echo Foo.new()
1123 .Add(1).Add(2).x
1124 echo Foo.new()
1125 .Add(1)
1126 .Add(2)
1127 .x
1128 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001129 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001130
1131 # Test for "public" cannot be abbreviated
1132 lines =<< trim END
1133 vim9script
1134 class Something
1135 pub this.val = 1
1136 endclass
1137 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001138 v9.CheckSourceFailure(lines, 'E1065:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001139
1140 # Test for "public" keyword must be followed by "this" or "static".
1141 lines =<< trim END
1142 vim9script
1143 class Something
1144 public val = 1
1145 endclass
1146 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001147 v9.CheckSourceFailure(lines, 'E1331:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001148
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001149 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001150 lines =<< trim END
1151 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001152 class A
1153 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001154 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001155 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001156 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001157 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001158
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001159 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001160 lines =<< trim END
1161 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001162 class A
1163 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001164 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001165 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001166 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001167 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1168
1169 # Modify a instance variable using the class name in a def function
1170 lines =<< trim END
1171 vim9script
1172 class A
1173 public this.val = 1
1174 endclass
1175 def T()
1176 A.val = 1
1177 enddef
1178 T()
1179 END
1180 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
1181
1182 # Read a instance variable using the class name in a def function
1183 lines =<< trim END
1184 vim9script
1185 class A
1186 public this.val = 1
1187 endclass
1188 def T()
1189 var i = A.val
1190 enddef
1191 T()
1192 END
1193 v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
Ernie Raelcf138d42023-09-06 20:45:03 +02001194
1195 # Access from child class extending a class:
1196 lines =<< trim END
1197 vim9script
1198 class A
1199 this.ro_obj_var = 10
1200 public this.rw_obj_var = 20
1201 this._priv_obj_var = 30
Ernie Raelcf138d42023-09-06 20:45:03 +02001202 endclass
1203
1204 class B extends A
1205 def Foo()
1206 var x: number
1207 x = this.ro_obj_var
1208 this.ro_obj_var = 0
1209 x = this.rw_obj_var
1210 this.rw_obj_var = 0
1211 x = this._priv_obj_var
1212 this._priv_obj_var = 0
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001213 enddef
1214 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001215
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001216 var b = B.new()
1217 b.Foo()
1218 END
1219 v9.CheckSourceSuccess(lines)
1220enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001221
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001222" Test for class variable access
1223def Test_class_variable_access()
1224 # Test for "static" cannot be abbreviated
1225 var lines =<< trim END
1226 vim9script
1227 class Something
1228 stat this.val = 1
1229 endclass
1230 END
1231 v9.CheckSourceFailure(lines, 'E1065:')
1232
1233 # Test for "static" cannot be followed by "this".
1234 lines =<< trim END
1235 vim9script
1236 class Something
1237 static this.val = 1
1238 endclass
1239 END
1240 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
1241
1242 # Test for "static" cannot be followed by "public".
1243 lines =<< trim END
1244 vim9script
1245 class Something
1246 static public val = 1
1247 endclass
1248 END
1249 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
1250
1251 # A readonly class variable cannot be modified from a child class
1252 lines =<< trim END
1253 vim9script
1254 class A
1255 static ro_class_var = 40
1256 endclass
1257
1258 class B extends A
1259 def Foo()
1260 A.ro_class_var = 50
1261 enddef
1262 endclass
1263
1264 var b = B.new()
1265 b.Foo()
1266 END
Ernie Rael696270b2023-09-21 16:42:28 +02001267 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001268
1269 # A private class variable cannot be accessed from a child class
1270 lines =<< trim END
1271 vim9script
1272 class A
1273 static _priv_class_var = 60
1274 endclass
1275
1276 class B extends A
1277 def Foo()
1278 var i = A._priv_class_var
1279 enddef
1280 endclass
1281
1282 var b = B.new()
1283 b.Foo()
1284 END
1285 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1286
1287 # A private class variable cannot be modified from a child class
1288 lines =<< trim END
1289 vim9script
1290 class A
1291 static _priv_class_var = 60
1292 endclass
1293
1294 class B extends A
1295 def Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001296 A._priv_class_var = 0
1297 enddef
1298 endclass
1299
1300 var b = B.new()
1301 b.Foo()
1302 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001303 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
1304
1305 # Access from child class extending a class and from script context
1306 lines =<< trim END
1307 vim9script
1308 class A
1309 static ro_class_var = 10
1310 public static rw_class_var = 20
1311 static _priv_class_var = 30
1312 endclass
1313
1314 class B extends A
1315 def Foo()
1316 var x: number
1317 x = A.ro_class_var
1318 assert_equal(10, x)
1319 x = A.rw_class_var
1320 assert_equal(25, x)
1321 A.rw_class_var = 20
1322 assert_equal(20, A.rw_class_var)
1323 enddef
1324 endclass
1325
1326 assert_equal(10, A.ro_class_var)
1327 assert_equal(20, A.rw_class_var)
1328 A.rw_class_var = 25
1329 assert_equal(25, A.rw_class_var)
1330 var b = B.new()
1331 b.Foo()
1332 END
1333 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001334enddef
1335
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001336def Test_class_object_compare()
1337 var class_lines =<< trim END
1338 vim9script
1339 class Item
1340 this.nr = 0
1341 this.name = 'xx'
1342 endclass
1343 END
1344
1345 # used at the script level and in a compiled function
1346 var test_lines =<< trim END
1347 var i1 = Item.new()
1348 assert_equal(i1, i1)
1349 assert_true(i1 is i1)
1350 var i2 = Item.new()
1351 assert_equal(i1, i2)
1352 assert_false(i1 is i2)
1353 var i3 = Item.new(0, 'xx')
1354 assert_equal(i1, i3)
1355
1356 var io1 = Item.new(1, 'xx')
1357 assert_notequal(i1, io1)
1358 var io2 = Item.new(0, 'yy')
1359 assert_notequal(i1, io2)
1360 END
1361
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001362 v9.CheckSourceSuccess(class_lines + test_lines)
1363 v9.CheckSourceSuccess(
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001364 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001365
1366 for op in ['>', '>=', '<', '<=', '=~', '!~']
1367 var op_lines = [
1368 'var i1 = Item.new()',
1369 'var i2 = Item.new()',
1370 'echo i1 ' .. op .. ' i2',
1371 ]
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001372 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
1373 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001374 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001375 endfor
1376enddef
1377
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001378def Test_object_type()
1379 var lines =<< trim END
1380 vim9script
1381
1382 class One
1383 this.one = 1
1384 endclass
1385 class Two
1386 this.two = 2
1387 endclass
1388 class TwoMore extends Two
1389 this.more = 9
1390 endclass
1391
1392 var o: One = One.new()
1393 var t: Two = Two.new()
1394 var m: TwoMore = TwoMore.new()
1395 var tm: Two = TwoMore.new()
1396
1397 t = m
1398 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001399 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001400
1401 lines =<< trim END
1402 vim9script
1403
1404 class One
1405 this.one = 1
1406 endclass
1407 class Two
1408 this.two = 2
1409 endclass
1410
1411 var o: One = Two.new()
1412 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001413 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001414
1415 lines =<< trim END
1416 vim9script
1417
1418 interface One
1419 def GetMember(): number
1420 endinterface
1421 class Two implements One
1422 this.one = 1
1423 def GetMember(): number
1424 return this.one
1425 enddef
1426 endclass
1427
1428 var o: One = Two.new(5)
1429 assert_equal(5, o.GetMember())
1430 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001431 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001432
1433 lines =<< trim END
1434 vim9script
1435
1436 class Num
1437 this.n: number = 0
1438 endclass
1439
1440 def Ref(name: string): func(Num): Num
1441 return (arg: Num): Num => {
1442 return eval(name)(arg)
1443 }
1444 enddef
1445
1446 const Fn = Ref('Double')
1447 var Double = (m: Num): Num => Num.new(m.n * 2)
1448
1449 echo Fn(Num.new(4))
1450 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001451 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001452enddef
1453
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001454def Test_class_member()
1455 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001456 var lines =<< trim END
1457 vim9script
1458 class TextPos
1459 this.lnum = 1
1460 this.col = 1
1461 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001462 static _secret = 7
1463 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001464
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001465 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001466 counter += nr
1467 enddef
1468 endclass
1469
1470 assert_equal(0, TextPos.counter)
1471 TextPos.AddToCounter(3)
1472 assert_equal(3, TextPos.counter)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001473 assert_fails('echo TextPos.noSuchMember', 'E1337:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001474
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001475 def GetCounter(): number
1476 return TextPos.counter
1477 enddef
1478 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001479
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001480 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001481 assert_fails('TextPos.counter = 5', 'E1335:')
1482 assert_fails('TextPos.counter += 5', 'E1335:')
1483
1484 assert_fails('echo TextPos._secret', 'E1333:')
1485 assert_fails('TextPos._secret = 8', 'E1333:')
1486
1487 assert_equal(42, TextPos.anybody)
1488 TextPos.anybody = 12
1489 assert_equal(12, TextPos.anybody)
1490 TextPos.anybody += 5
1491 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001492 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001493 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001494
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001495 # example in the help
1496 lines =<< trim END
1497 vim9script
1498 class OtherThing
1499 this.size: number
1500 static totalSize: number
1501
1502 def new(this.size)
1503 totalSize += this.size
1504 enddef
1505 endclass
1506 assert_equal(0, OtherThing.totalSize)
1507 var to3 = OtherThing.new(3)
1508 assert_equal(3, OtherThing.totalSize)
1509 var to7 = OtherThing.new(7)
1510 assert_equal(10, OtherThing.totalSize)
1511 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001512 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001513
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001514 # using static class member twice
1515 lines =<< trim END
1516 vim9script
1517
1518 class HTML
1519 static author: string = 'John Doe'
1520
1521 static def MacroSubstitute(s: string): string
1522 return substitute(s, '{{author}}', author, 'gi')
1523 enddef
1524 endclass
1525
1526 assert_equal('some text', HTML.MacroSubstitute('some text'))
1527 assert_equal('some text', HTML.MacroSubstitute('some text'))
1528 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001529 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001530
Bram Moolenaar62a69232023-01-24 15:07:04 +00001531 # access private member in lambda
1532 lines =<< trim END
1533 vim9script
1534
1535 class Foo
1536 this._x: number = 0
1537
1538 def Add(n: number): number
1539 const F = (): number => this._x + n
1540 return F()
1541 enddef
1542 endclass
1543
1544 var foo = Foo.new()
1545 assert_equal(5, foo.Add(5))
1546 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001547 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001548
h-east2bd6a092023-05-19 19:01:17 +01001549 # access private member in lambda body
1550 lines =<< trim END
1551 vim9script
1552
1553 class Foo
1554 this._x: number = 6
1555
1556 def Add(n: number): number
1557 var Lam = () => {
1558 this._x = this._x + n
1559 }
1560 Lam()
1561 return this._x
1562 enddef
1563 endclass
1564
1565 var foo = Foo.new()
1566 assert_equal(13, foo.Add(7))
1567 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001568 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001569
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001570 # check shadowing
1571 lines =<< trim END
1572 vim9script
1573
1574 class Some
1575 static count = 0
1576 def Method(count: number)
1577 echo count
1578 enddef
1579 endclass
1580
1581 var s = Some.new()
1582 s.Method(7)
1583 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001584 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001585
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001586 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001587 lines =<< trim END
1588 vim9script
1589
1590 class Some
1591 static count = 0
1592 def Method(arg: number)
1593 var count = 3
1594 echo arg count
1595 enddef
1596 endclass
1597
1598 var s = Some.new()
1599 s.Method(7)
1600 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001601 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001602
1603 # Test for using an invalid type for a member variable
1604 lines =<< trim END
1605 vim9script
1606 class A
1607 this.val: xxx
1608 endclass
1609 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001610 v9.CheckSourceFailure(lines, 'E1010:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001611
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001612 # Test for setting a member on a null object
1613 lines =<< trim END
1614 vim9script
1615 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001616 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001617 endclass
1618
1619 def F()
1620 var obj: A
1621 obj.val = ""
1622 enddef
1623 F()
1624 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001625 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001626
1627 # Test for accessing a member on a null object
1628 lines =<< trim END
1629 vim9script
1630 class A
1631 this.val: string
1632 endclass
1633
1634 def F()
1635 var obj: A
1636 echo obj.val
1637 enddef
1638 F()
1639 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001640 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001641
1642 # Test for setting a member on a null object, at script level
1643 lines =<< trim END
1644 vim9script
1645 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001646 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001647 endclass
1648
1649 var obj: A
1650 obj.val = ""
1651 END
1652 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001653 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001654
1655 # Test for accessing a member on a null object, at script level
1656 lines =<< trim END
1657 vim9script
1658 class A
1659 this.val: string
1660 endclass
1661
1662 var obj: A
1663 echo obj.val
1664 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001665 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001666
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001667 # Test for no space before or after the '=' when initializing a member
1668 # variable
1669 lines =<< trim END
1670 vim9script
1671 class A
1672 this.val: number= 10
1673 endclass
1674 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001675 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001676 lines =<< trim END
1677 vim9script
1678 class A
1679 this.val: number =10
1680 endclass
1681 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001682 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001683
1684 # Access a non-existing member
1685 lines =<< trim END
1686 vim9script
1687 class A
1688 endclass
1689 var a = A.new()
1690 var v = a.bar
1691 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001692 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": bar')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001693enddef
1694
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001695func Test_class_garbagecollect()
1696 let lines =<< trim END
1697 vim9script
1698
1699 class Point
1700 this.p = [2, 3]
1701 static pl = ['a', 'b']
1702 static pd = {a: 'a', b: 'b'}
1703 endclass
1704
1705 echo Point.pl Point.pd
1706 call test_garbagecollect_now()
1707 echo Point.pl Point.pd
1708 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001709 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001710
1711 let lines =<< trim END
1712 vim9script
1713
1714 interface View
1715 endinterface
1716
1717 class Widget
1718 this.view: View
1719 endclass
1720
1721 class MyView implements View
1722 this.widget: Widget
1723
1724 def new()
1725 # this will result in a circular reference to this object
1726 this.widget = Widget.new(this)
1727 enddef
1728 endclass
1729
1730 var view = MyView.new()
1731
1732 # overwrite "view", will be garbage-collected next
1733 view = MyView.new()
1734 test_garbagecollect_now()
1735 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001736 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001737endfunc
1738
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001739" Test interface garbage collection
1740func Test_interface_garbagecollect()
1741 let lines =<< trim END
1742 vim9script
1743
1744 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001745 this.ro_obj_var: number
1746 public this.rw_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001747
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001748 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001749 endinterface
1750
1751 class A implements I
1752 static ro_class_var: number = 10
1753 public static rw_class_var: number = 20
1754 static _priv_class_var: number = 30
1755 this.ro_obj_var: number = 40
1756 public this.rw_obj_var: number = 50
1757 this._priv_obj_var: number = 60
1758
1759 static def _ClassBar(): number
1760 return _priv_class_var
1761 enddef
1762
1763 static def ClassFoo(): number
1764 return ro_class_var + rw_class_var + A._ClassBar()
1765 enddef
1766
1767 def _ObjBar(): number
1768 return this._priv_obj_var
1769 enddef
1770
1771 def ObjFoo(): number
1772 return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
1773 enddef
1774 endclass
1775
1776 assert_equal(60, A.ClassFoo())
1777 var o = A.new()
1778 assert_equal(150, o.ObjFoo())
1779 test_garbagecollect_now()
1780 assert_equal(60, A.ClassFoo())
1781 assert_equal(150, o.ObjFoo())
1782 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001783 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001784endfunc
1785
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001786def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001787 var lines =<< trim END
1788 vim9script
1789 class Value
1790 this.value = 0
1791 static objects = 0
1792
1793 def new(v: number)
1794 this.value = v
1795 ++objects
1796 enddef
1797
1798 static def GetCount(): number
1799 return objects
1800 enddef
1801 endclass
1802
1803 assert_equal(0, Value.GetCount())
1804 var v1 = Value.new(2)
1805 assert_equal(1, Value.GetCount())
1806 var v2 = Value.new(7)
1807 assert_equal(2, Value.GetCount())
1808 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001809 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001810
1811 # Test for cleaning up after a class definition failure when using class
1812 # functions.
1813 lines =<< trim END
1814 vim9script
1815 class A
1816 static def Foo()
1817 enddef
1818 aaa
1819 endclass
1820 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001821 v9.CheckSourceFailure(lines, 'E1318:')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001822
1823 # Test for calling a class method from another class method without the class
1824 # name prefix.
1825 lines =<< trim END
1826 vim9script
1827 class A
1828 static myList: list<number> = [1]
1829 static def Foo(n: number)
1830 myList->add(n)
1831 enddef
1832 static def Bar()
1833 Foo(2)
1834 enddef
1835 def Baz()
1836 Foo(3)
1837 enddef
1838 endclass
1839 A.Bar()
1840 var a = A.new()
1841 a.Baz()
1842 assert_equal([1, 2, 3], A.myList)
1843 END
1844 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001845enddef
1846
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001847def Test_class_defcompile()
1848 var lines =<< trim END
1849 vim9script
1850
1851 class C
1852 def Fo(i: number): string
1853 return i
1854 enddef
1855 endclass
1856
1857 defcompile C.Fo
1858 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001859 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001860
1861 lines =<< trim END
1862 vim9script
1863
1864 class C
1865 static def Fc(): number
1866 return 'x'
1867 enddef
1868 endclass
1869
1870 defcompile C.Fc
1871 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001872 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001873
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001874 lines =<< trim END
1875 vim9script
1876
1877 class C
1878 static def new()
1879 enddef
1880 endclass
1881
1882 defcompile C.new
1883 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001884 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" function as static')
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001885
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001886 # Trying to compile a function using a non-existing class variable
1887 lines =<< trim END
1888 vim9script
1889 defcompile x.Foo()
1890 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001891 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001892
1893 # Trying to compile a function using a variable which is not a class
1894 lines =<< trim END
1895 vim9script
1896 var x: number
1897 defcompile x.Foo()
1898 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001899 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001900
1901 # Trying to compile a function without specifying the name
1902 lines =<< trim END
1903 vim9script
1904 class A
1905 endclass
1906 defcompile A.
1907 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001908 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001909
1910 # Trying to compile a non-existing class object member function
1911 lines =<< trim END
1912 vim9script
1913 class A
1914 endclass
1915 var a = A.new()
1916 defcompile a.Foo()
1917 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001918 v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001919enddef
1920
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001921def Test_class_object_to_string()
1922 var lines =<< trim END
1923 vim9script
1924 class TextPosition
1925 this.lnum = 1
1926 this.col = 22
1927 endclass
1928
1929 assert_equal("class TextPosition", string(TextPosition))
1930
1931 var pos = TextPosition.new()
1932 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1933 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001934 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001935enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001936
Bram Moolenaar554d0312023-01-05 19:59:18 +00001937def Test_interface_basics()
1938 var lines =<< trim END
1939 vim9script
1940 interface Something
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001941 this.ro_var: string
1942 public this.rw_var: list<number>
Bram Moolenaar554d0312023-01-05 19:59:18 +00001943 def GetCount(): number
1944 endinterface
1945 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001946 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001947
1948 lines =<< trim END
1949 interface SomethingWrong
1950 static count = 7
1951 endinterface
1952 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001953 v9.CheckSourceFailure(lines, 'E1342:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001954
1955 lines =<< trim END
1956 vim9script
1957
1958 interface Some
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001959 this.value: number
1960 def Method(value: number)
1961 endinterface
1962 END
h-east61378a12023-04-18 19:07:29 +01001963 # The argument name and the object member name are the same, but this is not a
1964 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001965 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001966
1967 lines =<< trim END
1968 vim9script
1969 interface somethingWrong
1970 static count = 7
1971 endinterface
1972 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001973 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001974
1975 lines =<< trim END
1976 vim9script
1977 interface SomethingWrong
1978 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001979 this.count = 7
Bram Moolenaar554d0312023-01-05 19:59:18 +00001980 def GetCount(): number
1981 endinterface
1982 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001983 v9.CheckSourceFailure(lines, 'E1344:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001984
1985 lines =<< trim END
1986 vim9script
1987 interface SomethingWrong
1988 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001989 this.count: number
Bram Moolenaar554d0312023-01-05 19:59:18 +00001990 def GetCount(): number
1991 return 5
1992 enddef
1993 endinterface
1994 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001995 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00001996
1997 lines =<< trim END
1998 vim9script
1999 export interface EnterExit
2000 def Enter(): void
2001 def Exit(): void
2002 endinterface
2003 END
2004 writefile(lines, 'XdefIntf.vim', 'D')
2005
2006 lines =<< trim END
2007 vim9script
2008 import './XdefIntf.vim' as defIntf
2009 export def With(ee: defIntf.EnterExit, F: func)
2010 ee.Enter()
2011 try
2012 F()
2013 finally
2014 ee.Exit()
2015 endtry
2016 enddef
2017 END
2018 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002019
2020 var imported =<< trim END
2021 vim9script
2022 export abstract class EnterExit
2023 def Enter(): void
2024 enddef
2025 def Exit(): void
2026 enddef
2027 endclass
2028 END
2029 writefile(imported, 'XdefIntf2.vim', 'D')
2030
2031 lines[1] = " import './XdefIntf2.vim' as defIntf"
2032 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002033enddef
2034
Bram Moolenaar94674f22023-01-06 18:42:20 +00002035def Test_class_implements_interface()
2036 var lines =<< trim END
2037 vim9script
2038
2039 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002040 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002041 def Method(nr: number)
2042 endinterface
2043
2044 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002045 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002046 def Method(nr: number)
2047 echo nr
2048 enddef
2049 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002050
2051 interface Another
2052 this.member: string
2053 endinterface
2054
Bram Moolenaar83ae6152023-02-25 19:59:31 +00002055 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002056 this.member = 'abc'
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002057 this.count = 20
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002058 def Method(nr: number)
2059 echo nr
2060 enddef
2061 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002062 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002063 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002064
2065 lines =<< trim END
2066 vim9script
2067
2068 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002069 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002070 endinterface
2071
2072 class SomeImpl implements Some implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002073 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002074 endclass
2075 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002076 v9.CheckSourceFailure(lines, 'E1350:')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002077
2078 lines =<< trim END
2079 vim9script
2080
2081 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002082 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002083 endinterface
2084
2085 class SomeImpl implements Some, Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002086 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002087 endclass
2088 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002089 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002090
2091 lines =<< trim END
2092 vim9script
2093
2094 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002095 this.counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002096 def Method(nr: number)
2097 endinterface
2098
2099 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002100 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002101 def Method(nr: number)
2102 echo nr
2103 enddef
2104 endclass
2105 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002106 v9.CheckSourceFailure(lines, 'E1348: Member "counter" of interface "Some" is not implemented')
Bram Moolenaar94674f22023-01-06 18:42:20 +00002107
2108 lines =<< trim END
2109 vim9script
2110
2111 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002112 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002113 def Methods(nr: number)
2114 endinterface
2115
2116 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002117 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002118 def Method(nr: number)
2119 echo nr
2120 enddef
2121 endclass
2122 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002123 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002124
2125 # Check different order of members in class and interface works.
2126 lines =<< trim END
2127 vim9script
2128
2129 interface Result
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002130 public this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002131 this.errpos: number
2132 endinterface
2133
2134 # order of members is opposite of interface
2135 class Failure implements Result
2136 this.errpos: number = 42
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002137 public this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002138 endclass
2139
2140 def Test()
2141 var result: Result = Failure.new()
2142
2143 assert_equal('label', result.label)
2144 assert_equal(42, result.errpos)
Bram Moolenaarf7d1c6e2023-01-16 20:47:57 +00002145
2146 result.label = 'different'
2147 assert_equal('different', result.label)
2148 assert_equal(42, result.errpos)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002149 enddef
2150
2151 Test()
2152 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002153 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002154
2155 # Interface name after "extends" doesn't end in a space or NUL character
2156 lines =<< trim END
2157 vim9script
2158 interface A
2159 endinterface
2160 class B extends A"
2161 endclass
2162 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002163 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002164
2165 # Trailing characters after a class name
2166 lines =<< trim END
2167 vim9script
2168 class A bbb
2169 endclass
2170 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002171 v9.CheckSourceFailure(lines, 'E488:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002172
2173 # using "implements" with a non-existing class
2174 lines =<< trim END
2175 vim9script
2176 class A implements B
2177 endclass
2178 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002179 v9.CheckSourceFailure(lines, 'E1346:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002180
2181 # using "implements" with a regular class
2182 lines =<< trim END
2183 vim9script
2184 class A
2185 endclass
2186 class B implements A
2187 endclass
2188 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002189 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002190
2191 # using "implements" with a variable
2192 lines =<< trim END
2193 vim9script
2194 var T: number = 10
2195 class A implements T
2196 endclass
2197 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002198 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002199
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002200 # implements should be followed by a white space
2201 lines =<< trim END
2202 vim9script
2203 interface A
2204 endinterface
2205 class B implements A;
2206 endclass
2207 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002208 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002209
LemonBoyc5d27442023-08-19 13:02:35 +02002210 lines =<< trim END
2211 vim9script
2212
2213 interface One
LemonBoyc5d27442023-08-19 13:02:35 +02002214 def IsEven(nr: number): bool
2215 endinterface
2216 class Two implements One
2217 def IsEven(nr: number): string
2218 enddef
2219 endclass
2220 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002221 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02002222
2223 lines =<< trim END
2224 vim9script
2225
2226 interface One
2227 def IsEven(nr: number): bool
2228 endinterface
2229 class Two implements One
2230 def IsEven(nr: bool): bool
2231 enddef
2232 endclass
2233 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002234 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02002235
2236 lines =<< trim END
2237 vim9script
2238
2239 interface One
2240 def IsEven(nr: number): bool
2241 endinterface
2242 class Two implements One
2243 def IsEven(nr: number, ...extra: list<number>): bool
2244 enddef
2245 endclass
2246 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002247 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 +02002248
2249 # access superclass interface members from subclass, mix variable order
2250 lines =<< trim END
2251 vim9script
2252
2253 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002254 public this.mvar1: number
2255 public this.mvar2: number
2256 endinterface
2257
2258 # NOTE: the order is swapped
2259 class A implements I1
2260 public this.mvar2: number
2261 public this.mvar1: number
2262 public static svar2: number
2263 public static svar1: number
2264 def new()
2265 svar1 = 11
2266 svar2 = 12
2267 this.mvar1 = 111
2268 this.mvar2 = 112
2269 enddef
2270 endclass
2271
2272 class B extends A
2273 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002274 this.mvar1 = 121
2275 this.mvar2 = 122
2276 enddef
2277 endclass
2278
2279 class C extends B
2280 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002281 this.mvar1 = 131
2282 this.mvar2 = 132
2283 enddef
2284 endclass
2285
Ernie Raelcf138d42023-09-06 20:45:03 +02002286 def F2(i: I1): list<number>
2287 return [ i.mvar1, i.mvar2 ]
2288 enddef
2289
2290 var oa = A.new()
2291 var ob = B.new()
2292 var oc = C.new()
2293
Ernie Raelcf138d42023-09-06 20:45:03 +02002294 assert_equal([111, 112], F2(oa))
2295 assert_equal([121, 122], F2(ob))
2296 assert_equal([131, 132], F2(oc))
2297 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002298 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002299
2300 # Access superclass interface members from subclass, mix variable order.
2301 # Two interfaces, one on A, one on B; each has both kinds of variables
2302 lines =<< trim END
2303 vim9script
2304
2305 interface I1
Ernie Raelcf138d42023-09-06 20:45:03 +02002306 public this.mvar1: number
2307 public this.mvar2: number
2308 endinterface
2309
2310 interface I2
Ernie Raelcf138d42023-09-06 20:45:03 +02002311 public this.mvar3: number
2312 public this.mvar4: number
2313 endinterface
2314
2315 class A implements I1
2316 public static svar1: number
2317 public static svar2: number
2318 public this.mvar1: number
2319 public this.mvar2: number
2320 def new()
2321 svar1 = 11
2322 svar2 = 12
2323 this.mvar1 = 111
2324 this.mvar2 = 112
2325 enddef
2326 endclass
2327
2328 class B extends A implements I2
2329 public static svar3: number
2330 public static svar4: number
2331 public this.mvar3: number
2332 public this.mvar4: number
2333 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002334 svar3 = 23
2335 svar4 = 24
2336 this.mvar1 = 121
2337 this.mvar2 = 122
2338 this.mvar3 = 123
2339 this.mvar4 = 124
2340 enddef
2341 endclass
2342
2343 class C extends B
2344 public static svar5: number
2345 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002346 svar5 = 1001
2347 this.mvar1 = 131
2348 this.mvar2 = 132
2349 this.mvar3 = 133
2350 this.mvar4 = 134
2351 enddef
2352 endclass
2353
Ernie Raelcf138d42023-09-06 20:45:03 +02002354 def F2(i: I1): list<number>
2355 return [ i.mvar1, i.mvar2 ]
2356 enddef
2357
Ernie Raelcf138d42023-09-06 20:45:03 +02002358 def F4(i: I2): list<number>
2359 return [ i.mvar3, i.mvar4 ]
2360 enddef
2361
Ernie Raelcf138d42023-09-06 20:45:03 +02002362 var oa = A.new()
2363 var ob = B.new()
2364 var oc = C.new()
2365
Ernie Raelcf138d42023-09-06 20:45:03 +02002366 assert_equal([[111, 112]], [F2(oa)])
2367 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2368 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002369 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002370 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002371enddef
2372
Bram Moolenaard0200c82023-01-28 15:19:40 +00002373def Test_call_interface_method()
2374 var lines =<< trim END
2375 vim9script
2376 interface Base
2377 def Enter(): void
2378 endinterface
2379
2380 class Child implements Base
2381 def Enter(): void
2382 g:result ..= 'child'
2383 enddef
2384 endclass
2385
2386 def F(obj: Base)
2387 obj.Enter()
2388 enddef
2389
2390 g:result = ''
2391 F(Child.new())
2392 assert_equal('child', g:result)
2393 unlet g:result
2394 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002395 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002396
2397 lines =<< trim END
2398 vim9script
2399 class Base
2400 def Enter(): void
2401 g:result ..= 'base'
2402 enddef
2403 endclass
2404
2405 class Child extends Base
2406 def Enter(): void
2407 g:result ..= 'child'
2408 enddef
2409 endclass
2410
2411 def F(obj: Base)
2412 obj.Enter()
2413 enddef
2414
2415 g:result = ''
2416 F(Child.new())
2417 assert_equal('child', g:result)
2418 unlet g:result
2419 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002420 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002421
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002422 # method of interface returns a value
2423 lines =<< trim END
2424 vim9script
2425 interface Base
2426 def Enter(): string
2427 endinterface
2428
2429 class Child implements Base
2430 def Enter(): string
2431 g:result ..= 'child'
2432 return "/resource"
2433 enddef
2434 endclass
2435
2436 def F(obj: Base)
2437 var r = obj.Enter()
2438 g:result ..= r
2439 enddef
2440
2441 g:result = ''
2442 F(Child.new())
2443 assert_equal('child/resource', g:result)
2444 unlet g:result
2445 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002446 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002447
2448 lines =<< trim END
2449 vim9script
2450 class Base
2451 def Enter(): string
2452 return null_string
2453 enddef
2454 endclass
2455
2456 class Child extends Base
2457 def Enter(): string
2458 g:result ..= 'child'
2459 return "/resource"
2460 enddef
2461 endclass
2462
2463 def F(obj: Base)
2464 var r = obj.Enter()
2465 g:result ..= r
2466 enddef
2467
2468 g:result = ''
2469 F(Child.new())
2470 assert_equal('child/resource', g:result)
2471 unlet g:result
2472 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002473 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002474
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002475 # No class that implements the interface.
2476 lines =<< trim END
2477 vim9script
2478
2479 interface IWithEE
2480 def Enter(): any
2481 def Exit(): void
2482 endinterface
2483
2484 def With1(ee: IWithEE, F: func)
2485 var r = ee.Enter()
2486 enddef
2487
2488 defcompile
2489 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002490 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002491enddef
2492
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002493def Test_class_used_as_type()
2494 var lines =<< trim END
2495 vim9script
2496
2497 class Point
2498 this.x = 0
2499 this.y = 0
2500 endclass
2501
2502 var p: Point
2503 p = Point.new(2, 33)
2504 assert_equal(2, p.x)
2505 assert_equal(33, p.y)
2506 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002507 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002508
2509 lines =<< trim END
2510 vim9script
2511
2512 interface HasX
2513 this.x: number
2514 endinterface
2515
2516 class Point implements HasX
2517 this.x = 0
2518 this.y = 0
2519 endclass
2520
2521 var p: Point
2522 p = Point.new(2, 33)
2523 var hx = p
2524 assert_equal(2, hx.x)
2525 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002526 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002527
2528 lines =<< trim END
2529 vim9script
2530
2531 class Point
2532 this.x = 0
2533 this.y = 0
2534 endclass
2535
2536 var p: Point
2537 p = 'text'
2538 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002539 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002540enddef
2541
Bram Moolenaar83677162023-01-08 19:54:10 +00002542def Test_class_extends()
2543 var lines =<< trim END
2544 vim9script
2545 class Base
2546 this.one = 1
2547 def GetOne(): number
2548 return this.one
2549 enddef
2550 endclass
2551 class Child extends Base
2552 this.two = 2
2553 def GetTotal(): number
2554 return this.one + this.two
2555 enddef
2556 endclass
2557 var o = Child.new()
2558 assert_equal(1, o.one)
2559 assert_equal(2, o.two)
2560 assert_equal(1, o.GetOne())
2561 assert_equal(3, o.GetTotal())
2562 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002563 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002564
2565 lines =<< trim END
2566 vim9script
2567 class Base
2568 this.one = 1
2569 endclass
2570 class Child extends Base
2571 this.two = 2
2572 endclass
2573 var o = Child.new(3, 44)
2574 assert_equal(3, o.one)
2575 assert_equal(44, o.two)
2576 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002577 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002578
2579 lines =<< trim END
2580 vim9script
2581 class Base
2582 this.one = 1
2583 endclass
2584 class Child extends Base extends Base
2585 this.two = 2
2586 endclass
2587 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002588 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
Bram Moolenaar83677162023-01-08 19:54:10 +00002589
2590 lines =<< trim END
2591 vim9script
2592 class Child extends BaseClass
2593 this.two = 2
2594 endclass
2595 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002596 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
Bram Moolenaar83677162023-01-08 19:54:10 +00002597
2598 lines =<< trim END
2599 vim9script
2600 var SomeVar = 99
2601 class Child extends SomeVar
2602 this.two = 2
2603 endclass
2604 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002605 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002606
2607 lines =<< trim END
2608 vim9script
2609 class Base
2610 this.name: string
2611 def ToString(): string
2612 return this.name
2613 enddef
2614 endclass
2615
2616 class Child extends Base
2617 this.age: number
2618 def ToString(): string
2619 return super.ToString() .. ': ' .. this.age
2620 enddef
2621 endclass
2622
2623 var o = Child.new('John', 42)
2624 assert_equal('John: 42', o.ToString())
2625 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002626 v9.CheckSourceSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002627
2628 lines =<< trim END
2629 vim9script
2630 class Child
2631 this.age: number
2632 def ToString(): number
2633 return this.age
2634 enddef
2635 def ToString(): string
2636 return this.age
2637 enddef
2638 endclass
2639 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002640 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002641
2642 lines =<< trim END
2643 vim9script
2644 class Child
2645 this.age: number
2646 def ToString(): string
2647 return super .ToString() .. ': ' .. this.age
2648 enddef
2649 endclass
2650 var o = Child.new(42)
2651 echo o.ToString()
2652 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002653 v9.CheckSourceFailure(lines, 'E1356:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002654
2655 lines =<< trim END
2656 vim9script
2657 class Base
2658 this.name: string
2659 def ToString(): string
2660 return this.name
2661 enddef
2662 endclass
2663
2664 var age = 42
2665 def ToString(): string
2666 return super.ToString() .. ': ' .. age
2667 enddef
2668 echo ToString()
2669 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002670 v9.CheckSourceFailure(lines, 'E1357:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002671
2672 lines =<< trim END
2673 vim9script
2674 class Child
2675 this.age: number
2676 def ToString(): string
2677 return super.ToString() .. ': ' .. this.age
2678 enddef
2679 endclass
2680 var o = Child.new(42)
2681 echo o.ToString()
2682 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002683 v9.CheckSourceFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002684
2685 lines =<< trim END
2686 vim9script
2687 class Base
2688 this.name: string
2689 static def ToString(): string
2690 return 'Base class'
2691 enddef
2692 endclass
2693
2694 class Child extends Base
2695 this.age: number
2696 def ToString(): string
2697 return Base.ToString() .. ': ' .. this.age
2698 enddef
2699 endclass
2700
2701 var o = Child.new('John', 42)
2702 assert_equal('Base class: 42', o.ToString())
2703 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002704 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002705
2706 lines =<< trim END
2707 vim9script
2708 class Base
2709 this.value = 1
2710 def new(init: number)
2711 this.value = number + 1
2712 enddef
2713 endclass
2714 class Child extends Base
2715 def new()
2716 this.new(3)
2717 enddef
2718 endclass
2719 var c = Child.new()
2720 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002721 v9.CheckSourceFailure(lines, 'E1375: Class member "new" accessible only using class "Child"')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002722
2723 # base class with more than one object member
2724 lines =<< trim END
2725 vim9script
2726
2727 class Result
2728 this.success: bool
2729 this.value: any = null
2730 endclass
2731
2732 class Success extends Result
2733 def new(this.value = v:none)
2734 this.success = true
2735 enddef
2736 endclass
2737
2738 var v = Success.new('asdf')
2739 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2740 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002741 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002742
2743 # class name after "extends" doesn't end in a space or NUL character
2744 lines =<< trim END
2745 vim9script
2746 class A
2747 endclass
2748 class B extends A"
2749 endclass
2750 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002751 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002752enddef
2753
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002754def Test_using_base_class()
2755 var lines =<< trim END
2756 vim9script
2757
2758 class BaseEE
2759 def Enter(): any
2760 return null
2761 enddef
2762 def Exit(resource: any): void
2763 enddef
2764 endclass
2765
2766 class ChildEE extends BaseEE
2767 def Enter(): any
2768 return 42
2769 enddef
2770
2771 def Exit(resource: number): void
2772 g:result ..= '/exit'
2773 enddef
2774 endclass
2775
2776 def With(ee: BaseEE)
2777 var r = ee.Enter()
2778 try
2779 g:result ..= r
2780 finally
2781 g:result ..= '/finally'
2782 ee.Exit(r)
2783 endtry
2784 enddef
2785
2786 g:result = ''
2787 With(ChildEE.new())
2788 assert_equal('42/finally/exit', g:result)
2789 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002790 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002791 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002792
2793 # Using super, Child invokes Base method which has optional arg. #12471
2794 lines =<< trim END
2795 vim9script
2796
2797 class Base
2798 this.success: bool = false
2799 def Method(arg = 0)
2800 this.success = true
2801 enddef
2802 endclass
2803
2804 class Child extends Base
2805 def new()
2806 super.Method()
2807 enddef
2808 endclass
2809
2810 var obj = Child.new()
2811 assert_equal(true, obj.success)
2812 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002813 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002814enddef
2815
Bram Moolenaara86655a2023-01-12 17:06:27 +00002816def Test_class_import()
2817 var lines =<< trim END
2818 vim9script
2819 export class Animal
2820 this.kind: string
2821 this.name: string
2822 endclass
2823 END
2824 writefile(lines, 'Xanimal.vim', 'D')
2825
2826 lines =<< trim END
2827 vim9script
2828 import './Xanimal.vim' as animal
2829
2830 var a: animal.Animal
2831 a = animal.Animal.new('fish', 'Eric')
2832 assert_equal('fish', a.kind)
2833 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002834
2835 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2836 assert_equal('cat', b.kind)
2837 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002838 END
2839 v9.CheckScriptSuccess(lines)
2840enddef
2841
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002842def Test_abstract_class()
2843 var lines =<< trim END
2844 vim9script
2845 abstract class Base
2846 this.name: string
2847 endclass
2848 class Person extends Base
2849 this.age: number
2850 endclass
2851 var p: Base = Person.new('Peter', 42)
2852 assert_equal('Peter', p.name)
2853 assert_equal(42, p.age)
2854 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002855 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002856
2857 lines =<< trim END
2858 vim9script
2859 abstract class Base
2860 this.name: string
2861 endclass
2862 class Person extends Base
2863 this.age: number
2864 endclass
2865 var p = Base.new('Peter')
2866 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002867 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002868
2869 lines =<< trim END
2870 abstract class Base
2871 this.name: string
2872 endclass
2873 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002874 v9.CheckSourceFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002875
2876 # Abstract class cannot have a "new" function
2877 lines =<< trim END
2878 vim9script
2879 abstract class Base
2880 def new()
2881 enddef
2882 endclass
2883 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002884 v9.CheckSourceFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002885enddef
2886
Bram Moolenaar486fc252023-01-18 14:51:07 +00002887def Test_closure_in_class()
2888 var lines =<< trim END
2889 vim9script
2890
2891 class Foo
2892 this.y: list<string> = ['B']
2893
2894 def new()
2895 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2896 enddef
2897 endclass
2898
2899 Foo.new()
2900 assert_equal(['A'], g:result)
2901 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002902 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00002903enddef
2904
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002905def Test_call_constructor_from_legacy()
2906 var lines =<< trim END
2907 vim9script
2908
2909 var newCalled = 'false'
2910
2911 class A
2912 def new()
2913 newCalled = 'true'
2914 enddef
2915 endclass
2916
2917 export def F(options = {}): any
2918 return A
2919 enddef
2920
2921 g:p = F()
2922 legacy call p.new()
2923 assert_equal('true', newCalled)
2924 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002925 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002926enddef
2927
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002928def Test_defer_with_object()
2929 var lines =<< trim END
2930 vim9script
2931
2932 class CWithEE
2933 def Enter()
2934 g:result ..= "entered/"
2935 enddef
2936 def Exit()
2937 g:result ..= "exited"
2938 enddef
2939 endclass
2940
2941 def With(ee: CWithEE, F: func)
2942 ee.Enter()
2943 defer ee.Exit()
2944 F()
2945 enddef
2946
2947 g:result = ''
2948 var obj = CWithEE.new()
2949 obj->With(() => {
2950 g:result ..= "called/"
2951 })
2952 assert_equal('entered/called/exited', g:result)
2953 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002954 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002955 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00002956
2957 lines =<< trim END
2958 vim9script
2959
2960 class BaseWithEE
2961 def Enter()
2962 g:result ..= "entered-base/"
2963 enddef
2964 def Exit()
2965 g:result ..= "exited-base"
2966 enddef
2967 endclass
2968
2969 class CWithEE extends BaseWithEE
2970 def Enter()
2971 g:result ..= "entered-child/"
2972 enddef
2973 def Exit()
2974 g:result ..= "exited-child"
2975 enddef
2976 endclass
2977
2978 def With(ee: BaseWithEE, F: func)
2979 ee.Enter()
2980 defer ee.Exit()
2981 F()
2982 enddef
2983
2984 g:result = ''
2985 var obj = CWithEE.new()
2986 obj->With(() => {
2987 g:result ..= "called/"
2988 })
2989 assert_equal('entered-child/called/exited-child', g:result)
2990 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002991 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00002992 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002993enddef
2994
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02002995" The following test used to crash Vim (Github issue #12676)
2996def Test_extends_method_crashes_vim()
2997 var lines =<< trim END
2998 vim9script
2999
3000 class Observer
3001 endclass
3002
3003 class Property
3004 this.value: any
3005
3006 def Set(v: any)
3007 if v != this.value
3008 this.value = v
3009 endif
3010 enddef
3011
3012 def Register(observer: Observer)
3013 enddef
3014 endclass
3015
3016 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003017 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003018 endclass
3019
3020 def Observe(obj: Property, who: Observer)
3021 obj.Register(who)
3022 enddef
3023
3024 var p = Bool.new(false)
3025 var myObserver = Observer.new()
3026
3027 Observe(p, myObserver)
3028
3029 p.Set(true)
3030 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003031 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003032enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003033
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003034" Test for calling a method in a class that is extended
3035def Test_call_method_in_extended_class()
3036 var lines =<< trim END
3037 vim9script
3038
3039 var prop_init_called = false
3040 var prop_register_called = false
3041
3042 class Property
3043 def Init()
3044 prop_init_called = true
3045 enddef
3046
3047 def Register()
3048 prop_register_called = true
3049 enddef
3050 endclass
3051
3052 class Bool extends Property
3053 endclass
3054
3055 def Observe(obj: Property)
3056 obj.Register()
3057 enddef
3058
3059 var p = Property.new()
3060 Observe(p)
3061
3062 p.Init()
3063 assert_true(prop_init_called)
3064 assert_true(prop_register_called)
3065 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003066 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003067enddef
3068
LemonBoyafe04662023-08-23 21:08:11 +02003069def Test_instanceof()
3070 var lines =<< trim END
3071 vim9script
3072
3073 class Base1
3074 endclass
3075
3076 class Base2 extends Base1
3077 endclass
3078
3079 interface Intf1
3080 endinterface
3081
3082 class Mix1 implements Intf1
3083 endclass
3084
3085 class Base3 extends Mix1
3086 endclass
3087
3088 var b1 = Base1.new()
3089 var b2 = Base2.new()
3090 var b3 = Base3.new()
3091
3092 assert_true(instanceof(b1, Base1))
3093 assert_true(instanceof(b2, Base1))
3094 assert_false(instanceof(b1, Base2))
3095 assert_true(instanceof(b3, Mix1))
3096 assert_false(instanceof(b3, []))
3097 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003098
3099 def Foo()
3100 var a1 = Base1.new()
3101 var a2 = Base2.new()
3102 var a3 = Base3.new()
3103
3104 assert_true(instanceof(a1, Base1))
3105 assert_true(instanceof(a2, Base1))
3106 assert_false(instanceof(a1, Base2))
3107 assert_true(instanceof(a3, Mix1))
3108 assert_false(instanceof(a3, []))
3109 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
3110 enddef
3111 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003112
3113 var o_null: Base1
3114 assert_false(instanceof(o_null, Base1))
3115
LemonBoyafe04662023-08-23 21:08:11 +02003116 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003117 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02003118enddef
3119
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003120" Test for calling a method in the parent class that is extended partially.
3121" This used to fail with the 'E118: Too many arguments for function: Text' error
3122" message (Github issue #12524).
3123def Test_call_method_in_parent_class()
3124 var lines =<< trim END
3125 vim9script
3126
3127 class Widget
3128 this._lnum: number = 1
3129
3130 def SetY(lnum: number)
3131 this._lnum = lnum
3132 enddef
3133
3134 def Text(): string
3135 return ''
3136 enddef
3137 endclass
3138
3139 class Foo extends Widget
3140 def Text(): string
3141 return '<Foo>'
3142 enddef
3143 endclass
3144
3145 def Stack(w1: Widget, w2: Widget): list<Widget>
3146 w1.SetY(1)
3147 w2.SetY(2)
3148 return [w1, w2]
3149 enddef
3150
3151 var foo1 = Foo.new()
3152 var foo2 = Foo.new()
3153 var l = Stack(foo1, foo2)
3154 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003155 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003156enddef
3157
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003158" Test for calling methods from three levels of classes
3159def Test_multi_level_method_call()
3160 var lines =<< trim END
3161 vim9script
3162
3163 var A_func1: number = 0
3164 var A_func2: number = 0
3165 var A_func3: number = 0
3166 var B_func2: number = 0
3167 var B_func3: number = 0
3168 var C_func3: number = 0
3169
3170 class A
3171 def Func1()
3172 A_func1 += 1
3173 enddef
3174
3175 def Func2()
3176 A_func2 += 1
3177 enddef
3178
3179 def Func3()
3180 A_func3 += 1
3181 enddef
3182 endclass
3183
3184 class B extends A
3185 def Func2()
3186 B_func2 += 1
3187 enddef
3188
3189 def Func3()
3190 B_func3 += 1
3191 enddef
3192 endclass
3193
3194 class C extends B
3195 def Func3()
3196 C_func3 += 1
3197 enddef
3198 endclass
3199
3200 def A_CallFuncs(a: A)
3201 a.Func1()
3202 a.Func2()
3203 a.Func3()
3204 enddef
3205
3206 def B_CallFuncs(b: B)
3207 b.Func1()
3208 b.Func2()
3209 b.Func3()
3210 enddef
3211
3212 def C_CallFuncs(c: C)
3213 c.Func1()
3214 c.Func2()
3215 c.Func3()
3216 enddef
3217
3218 var cobj = C.new()
3219 A_CallFuncs(cobj)
3220 B_CallFuncs(cobj)
3221 C_CallFuncs(cobj)
3222 assert_equal(3, A_func1)
3223 assert_equal(0, A_func2)
3224 assert_equal(0, A_func3)
3225 assert_equal(3, B_func2)
3226 assert_equal(0, B_func3)
3227 assert_equal(3, C_func3)
3228 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003229 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003230enddef
3231
3232" Test for using members from three levels of classes
3233def Test_multi_level_member_access()
3234 var lines =<< trim END
3235 vim9script
3236
3237 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003238 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003239 endclass
3240
3241 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003242 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003243 endclass
3244
3245 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003246 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003247 endclass
3248
3249 def A_members(a: A)
3250 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003251 enddef
3252
3253 def B_members(b: B)
3254 b.val1 += 1
3255 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003256 enddef
3257
3258 def C_members(c: C)
3259 c.val1 += 1
3260 c.val2 += 1
3261 c.val3 += 1
3262 enddef
3263
3264 var cobj = C.new()
3265 A_members(cobj)
3266 B_members(cobj)
3267 C_members(cobj)
3268 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003269 assert_equal(2, cobj.val2)
3270 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003271 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003272 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003273enddef
3274
LemonBoy0ffc17a2023-08-20 18:09:11 +02003275" Test expansion of <stack> with class methods.
3276def Test_stack_expansion_with_methods()
3277 var lines =<< trim END
3278 vim9script
3279
3280 class C
3281 def M1()
3282 F0()
3283 enddef
3284 endclass
3285
3286 def F0()
3287 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3288 enddef
3289
3290 def F()
3291 C.new().M1()
3292 enddef
3293
3294 F()
3295 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003296 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003297enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003298
3299" Test the return type of the new() constructor
3300def Test_new_return_type()
3301 # new() uses the default return type and there is no return statement
3302 var lines =<< trim END
3303 vim9script
3304
3305 class C
3306 this._bufnr: number
3307
3308 def new(this._bufnr)
3309 if !bufexists(this._bufnr)
3310 this._bufnr = -1
3311 endif
3312 enddef
3313 endclass
3314
3315 var c = C.new(12345)
3316 assert_equal('object<C>', typename(c))
3317
3318 var v1: C
3319 v1 = C.new(12345)
3320 assert_equal('object<C>', typename(v1))
3321
3322 def F()
3323 var v2: C
3324 v2 = C.new(12345)
3325 assert_equal('object<C>', typename(v2))
3326 enddef
3327 F()
3328 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003329 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003330
3331 # new() uses the default return type and an empty 'return' statement
3332 lines =<< trim END
3333 vim9script
3334
3335 class C
3336 this._bufnr: number
3337
3338 def new(this._bufnr)
3339 if !bufexists(this._bufnr)
3340 this._bufnr = -1
3341 return
3342 endif
3343 enddef
3344 endclass
3345
3346 var c = C.new(12345)
3347 assert_equal('object<C>', typename(c))
3348
3349 var v1: C
3350 v1 = C.new(12345)
3351 assert_equal('object<C>', typename(v1))
3352
3353 def F()
3354 var v2: C
3355 v2 = C.new(12345)
3356 assert_equal('object<C>', typename(v2))
3357 enddef
3358 F()
3359 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003360 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003361
3362 # new() uses "any" return type and returns "this"
3363 lines =<< trim END
3364 vim9script
3365
3366 class C
3367 this._bufnr: number
3368
3369 def new(this._bufnr): any
3370 if !bufexists(this._bufnr)
3371 this._bufnr = -1
3372 return this
3373 endif
3374 enddef
3375 endclass
3376 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003377 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003378
3379 # new() uses 'Dict' return type and returns a Dict
3380 lines =<< trim END
3381 vim9script
3382
3383 class C
3384 this._state: dict<any>
3385
3386 def new(): dict<any>
3387 this._state = {}
3388 return this._state
3389 enddef
3390 endclass
3391
3392 var c = C.new()
3393 assert_equal('object<C>', typename(c))
3394 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003395 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003396enddef
3397
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003398" Test for checking a member initialization type at run time.
3399def Test_runtime_type_check_for_member_init()
3400 var lines =<< trim END
3401 vim9script
3402
3403 var retnum: bool = false
3404
3405 def F(): any
3406 retnum = !retnum
3407 if retnum
3408 return 1
3409 else
3410 return "hello"
3411 endif
3412 enddef
3413
3414 class C
3415 this._foo: bool = F()
3416 endclass
3417
3418 var c1 = C.new()
3419 var c2 = C.new()
3420 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003421 v9.CheckSourceFailure(lines, 'E1012:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003422enddef
3423
3424" Test for locking a variable referring to an object and reassigning to another
3425" object.
3426def Test_object_lockvar()
3427 var lines =<< trim END
3428 vim9script
3429
3430 class C
3431 this.val: number
3432 def new(this.val)
3433 enddef
3434 endclass
3435
3436 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3437 lockvar 2 some_dict
3438
3439 var current: C
3440 current = some_dict['c']
3441 assert_equal(3, current.val)
3442 current = some_dict['b']
3443 assert_equal(2, current.val)
3444
3445 def F()
3446 current = some_dict['c']
3447 enddef
3448
3449 def G()
3450 current = some_dict['b']
3451 enddef
3452
3453 F()
3454 assert_equal(3, current.val)
3455 G()
3456 assert_equal(2, current.val)
3457 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003458 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003459enddef
3460
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003461" Test for a private object method
3462def Test_private_object_method()
3463 # Try calling a private method using an object (at the script level)
3464 var lines =<< trim END
3465 vim9script
3466
3467 class A
3468 def _Foo(): number
3469 return 1234
3470 enddef
3471 endclass
3472 var a = A.new()
3473 a._Foo()
3474 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003475 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003476
3477 # Try calling a private method using an object (from a def function)
3478 lines =<< trim END
3479 vim9script
3480
3481 class A
3482 def _Foo(): number
3483 return 1234
3484 enddef
3485 endclass
3486 def T()
3487 var a = A.new()
3488 a._Foo()
3489 enddef
3490 T()
3491 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003492 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003493
3494 # Use a private method from another object method (in script context)
3495 lines =<< trim END
3496 vim9script
3497
3498 class A
3499 def _Foo(): number
3500 return 1234
3501 enddef
3502 def Bar(): number
3503 return this._Foo()
3504 enddef
3505 endclass
3506 var a = A.new()
3507 assert_equal(1234, a.Bar())
3508 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003509 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003510
3511 # Use a private method from another object method (def function context)
3512 lines =<< trim END
3513 vim9script
3514
3515 class A
3516 def _Foo(): number
3517 return 1234
3518 enddef
3519 def Bar(): number
3520 return this._Foo()
3521 enddef
3522 endclass
3523 def T()
3524 var a = A.new()
3525 assert_equal(1234, a.Bar())
3526 enddef
3527 T()
3528 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003529 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003530
3531 # Try calling a private method without the "this" prefix
3532 lines =<< trim END
3533 vim9script
3534
3535 class A
3536 def _Foo(): number
3537 return 1234
3538 enddef
3539 def Bar(): number
3540 return _Foo()
3541 enddef
3542 endclass
3543 var a = A.new()
3544 a.Bar()
3545 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003546 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003547
3548 # Try calling a private method using the class name
3549 lines =<< trim END
3550 vim9script
3551
3552 class A
3553 def _Foo(): number
3554 return 1234
3555 enddef
3556 endclass
3557 A._Foo()
3558 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003559 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003560
3561 # Try to use "public" keyword when defining a private method
3562 lines =<< trim END
3563 vim9script
3564
3565 class A
3566 public def _Foo()
3567 enddef
3568 endclass
3569 var a = A.new()
3570 a._Foo()
3571 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003572 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003573
3574 # Define two private methods with the same name
3575 lines =<< trim END
3576 vim9script
3577
3578 class A
3579 def _Foo()
3580 enddef
3581 def _Foo()
3582 enddef
3583 endclass
3584 var a = A.new()
3585 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003586 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003587
3588 # Define a private method and a object method with the same name
3589 lines =<< trim END
3590 vim9script
3591
3592 class A
3593 def _Foo()
3594 enddef
3595 def Foo()
3596 enddef
3597 endclass
3598 var a = A.new()
3599 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003600 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003601
3602 # Define an object method and a private method with the same name
3603 lines =<< trim END
3604 vim9script
3605
3606 class A
3607 def Foo()
3608 enddef
3609 def _Foo()
3610 enddef
3611 endclass
3612 var a = A.new()
3613 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003614 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003615
3616 # Call a public method and a private method from a private method
3617 lines =<< trim END
3618 vim9script
3619
3620 class A
3621 def Foo(): number
3622 return 100
3623 enddef
3624 def _Bar(): number
3625 return 200
3626 enddef
3627 def _Baz()
3628 assert_equal(100, this.Foo())
3629 assert_equal(200, this._Bar())
3630 enddef
3631 def T()
3632 this._Baz()
3633 enddef
3634 endclass
3635 var a = A.new()
3636 a.T()
3637 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003638 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003639
3640 # Try calling a private method from another class
3641 lines =<< trim END
3642 vim9script
3643
3644 class A
3645 def _Foo(): number
3646 return 100
3647 enddef
3648 endclass
3649 class B
3650 def Foo(): number
3651 var a = A.new()
3652 a._Foo()
3653 enddef
3654 endclass
3655 var b = B.new()
3656 b.Foo()
3657 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003658 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003659
3660 # Call a private object method from a child class object method
3661 lines =<< trim END
3662 vim9script
3663 class A
3664 def _Foo(): number
3665 return 1234
3666 enddef
3667 endclass
3668 class B extends A
3669 def Bar()
3670 enddef
3671 endclass
3672 class C extends B
3673 def Baz(): number
3674 return this._Foo()
3675 enddef
3676 endclass
3677 var c = C.new()
3678 assert_equal(1234, c.Baz())
3679 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003680 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003681
3682 # Call a private object method from a child class object
3683 lines =<< trim END
3684 vim9script
3685 class A
3686 def _Foo(): number
3687 return 1234
3688 enddef
3689 endclass
3690 class B extends A
3691 def Bar()
3692 enddef
3693 endclass
3694 class C extends B
3695 def Baz(): number
3696 enddef
3697 endclass
3698 var c = C.new()
3699 assert_equal(1234, c._Foo())
3700 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003701 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003702
3703 # Using "_" prefix in a method name should fail outside of a class
3704 lines =<< trim END
3705 vim9script
3706 def _Foo(): number
3707 return 1234
3708 enddef
3709 var a = _Foo()
3710 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003711 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003712enddef
3713
3714" Test for an private class method
3715def Test_private_class_method()
3716 # Try calling a class private method (at the script level)
3717 var lines =<< trim END
3718 vim9script
3719
3720 class A
3721 static def _Foo(): number
3722 return 1234
3723 enddef
3724 endclass
3725 A._Foo()
3726 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003727 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003728
3729 # Try calling a class private method (from a def function)
3730 lines =<< trim END
3731 vim9script
3732
3733 class A
3734 static def _Foo(): number
3735 return 1234
3736 enddef
3737 endclass
3738 def T()
3739 A._Foo()
3740 enddef
3741 T()
3742 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003743 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003744
3745 # Try calling a class private method using an object (at the script level)
3746 lines =<< trim END
3747 vim9script
3748
3749 class A
3750 static def _Foo(): number
3751 return 1234
3752 enddef
3753 endclass
3754 var a = A.new()
3755 a._Foo()
3756 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003757 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003758
3759 # Try calling a class private method using an object (from a def function)
3760 lines =<< trim END
3761 vim9script
3762
3763 class A
3764 static def _Foo(): number
3765 return 1234
3766 enddef
3767 endclass
3768 def T()
3769 var a = A.new()
3770 a._Foo()
3771 enddef
3772 T()
3773 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003774 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003775
3776 # Use a class private method from an object method
3777 lines =<< trim END
3778 vim9script
3779
3780 class A
3781 static def _Foo(): number
3782 return 1234
3783 enddef
3784 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003785 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003786 enddef
3787 endclass
3788 var a = A.new()
3789 a.Bar()
3790 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003791 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003792
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003793 # Use a class private method from another class private method without the
3794 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003795 lines =<< trim END
3796 vim9script
3797
3798 class A
3799 static def _Foo1(): number
3800 return 1234
3801 enddef
3802 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003803 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003804 enddef
3805 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003806 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003807 enddef
3808 endclass
3809 var a = A.new()
3810 a.Bar()
3811 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003812 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003813
3814 # Declare a class method and a class private method with the same name
3815 lines =<< trim END
3816 vim9script
3817
3818 class A
3819 static def _Foo()
3820 enddef
3821 static def Foo()
3822 enddef
3823 endclass
3824 var a = A.new()
3825 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003826 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003827
3828 # Try calling a class private method from another class
3829 lines =<< trim END
3830 vim9script
3831
3832 class A
3833 static def _Foo(): number
3834 return 1234
3835 enddef
3836 endclass
3837 class B
3838 def Foo(): number
3839 return A._Foo()
3840 enddef
3841 endclass
3842 var b = B.new()
3843 assert_equal(1234, b.Foo())
3844 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003845 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003846
3847 # Call a private class method from a child class object method
3848 lines =<< trim END
3849 vim9script
3850 class A
3851 static def _Foo(): number
3852 return 1234
3853 enddef
3854 endclass
3855 class B extends A
3856 def Bar()
3857 enddef
3858 endclass
3859 class C extends B
3860 def Baz(): number
3861 return A._Foo()
3862 enddef
3863 endclass
3864 var c = C.new()
3865 assert_equal(1234, c.Baz())
3866 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003867 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003868
3869 # Call a private class method from a child class private class method
3870 lines =<< trim END
3871 vim9script
3872 class A
3873 static def _Foo(): number
3874 return 1234
3875 enddef
3876 endclass
3877 class B extends A
3878 def Bar()
3879 enddef
3880 endclass
3881 class C extends B
3882 static def Baz(): number
3883 return A._Foo()
3884 enddef
3885 endclass
3886 assert_equal(1234, C.Baz())
3887 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003888 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003889
3890 # Call a private class method from a child class object
3891 lines =<< trim END
3892 vim9script
3893 class A
3894 static def _Foo(): number
3895 return 1234
3896 enddef
3897 endclass
3898 class B extends A
3899 def Bar()
3900 enddef
3901 endclass
3902 class C extends B
3903 def Baz(): number
3904 enddef
3905 endclass
3906 var c = C.new()
3907 assert_equal(1234, C._Foo())
3908 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003909 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003910enddef
3911
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003912" Test for using the return value of a class/object method as a function
3913" argument.
3914def Test_objmethod_funcarg()
3915 var lines =<< trim END
3916 vim9script
3917
3918 class C
3919 def Foo(): string
3920 return 'foo'
3921 enddef
3922 endclass
3923
3924 def Bar(a: number, s: string): string
3925 return s
3926 enddef
3927
3928 def Baz(c: C)
3929 assert_equal('foo', Bar(10, c.Foo()))
3930 enddef
3931
3932 var t = C.new()
3933 Baz(t)
3934 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003935 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003936
3937 lines =<< trim END
3938 vim9script
3939
3940 class C
3941 static def Foo(): string
3942 return 'foo'
3943 enddef
3944 endclass
3945
3946 def Bar(a: number, s: string): string
3947 return s
3948 enddef
3949
3950 def Baz()
3951 assert_equal('foo', Bar(10, C.Foo()))
3952 enddef
3953
3954 Baz()
3955 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003956 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003957enddef
3958
Ernie Raelcf138d42023-09-06 20:45:03 +02003959def Test_static_inheritence()
3960 # subclasses get their own static copy
3961 var lines =<< trim END
3962 vim9script
3963
3964 class A
3965 static _svar: number
3966 this._mvar: number
3967 def new()
3968 _svar = 1
3969 this._mvar = 101
3970 enddef
3971 def AccessObject(): number
3972 return this._mvar
3973 enddef
3974 def AccessStaticThroughObject(): number
3975 return _svar
3976 enddef
3977 endclass
3978
3979 class B extends A
3980 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003981 this._mvar = 102
3982 enddef
3983 endclass
3984
3985 class C extends B
3986 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02003987 this._mvar = 103
3988 enddef
3989
3990 def AccessPrivateStaticThroughClassName(): number
3991 assert_equal(1, A._svar)
Ernie Raelcf138d42023-09-06 20:45:03 +02003992 return 444
3993 enddef
3994 endclass
3995
3996 var oa = A.new()
3997 var ob = B.new()
3998 var oc = C.new()
3999 assert_equal(101, oa.AccessObject())
4000 assert_equal(102, ob.AccessObject())
4001 assert_equal(103, oc.AccessObject())
4002
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004003 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private member: _svar')
Ernie Raelcf138d42023-09-06 20:45:03 +02004004
4005 # verify object properly resolves to correct static
4006 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004007 assert_equal(1, ob.AccessStaticThroughObject())
4008 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02004009 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004010 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02004011enddef
4012
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004013" Test for declaring duplicate object and class members
4014def Test_dup_member_variable()
4015 # Duplicate member variable
4016 var lines =<< trim END
4017 vim9script
4018 class C
4019 this.val = 10
4020 this.val = 20
4021 endclass
4022 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004023 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004024
4025 # Duplicate private member variable
4026 lines =<< trim END
4027 vim9script
4028 class C
4029 this._val = 10
4030 this._val = 20
4031 endclass
4032 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004033 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004034
4035 # Duplicate public member variable
4036 lines =<< trim END
4037 vim9script
4038 class C
4039 public this.val = 10
4040 public this.val = 20
4041 endclass
4042 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004043 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004044
4045 # Duplicate private member variable
4046 lines =<< trim END
4047 vim9script
4048 class C
4049 this.val = 10
4050 this._val = 20
4051 endclass
4052 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004053 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004054
4055 # Duplicate public and private member variable
4056 lines =<< trim END
4057 vim9script
4058 class C
4059 this._val = 20
4060 public this.val = 10
4061 endclass
4062 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004063 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004064
4065 # Duplicate class member variable
4066 lines =<< trim END
4067 vim9script
4068 class C
4069 static s: string = "abc"
4070 static _s: string = "def"
4071 endclass
4072 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004073 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004074
4075 # Duplicate public and private class member variable
4076 lines =<< trim END
4077 vim9script
4078 class C
4079 public static s: string = "abc"
4080 static _s: string = "def"
4081 endclass
4082 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004083 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004084
4085 # Duplicate class and object member variable
4086 lines =<< trim END
4087 vim9script
4088 class C
4089 static val = 10
4090 this.val = 20
4091 def new()
4092 enddef
4093 endclass
4094 var c = C.new()
4095 assert_equal(10, C.val)
4096 assert_equal(20, c.val)
4097 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004098 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004099
4100 # Duplicate object member variable in a derived class
4101 lines =<< trim END
4102 vim9script
4103 class A
4104 this.val = 10
4105 endclass
4106 class B extends A
4107 endclass
4108 class C extends B
4109 this.val = 20
4110 endclass
4111 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004112 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004113
4114 # Duplicate object private member variable in a derived class
4115 lines =<< trim END
4116 vim9script
4117 class A
4118 this._val = 10
4119 endclass
4120 class B extends A
4121 endclass
4122 class C extends B
4123 this._val = 20
4124 endclass
4125 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004126 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004127
4128 # Duplicate object private member variable in a derived class
4129 lines =<< trim END
4130 vim9script
4131 class A
4132 this.val = 10
4133 endclass
4134 class B extends A
4135 endclass
4136 class C extends B
4137 this._val = 20
4138 endclass
4139 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004140 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004141
4142 # Duplicate object member variable in a derived class
4143 lines =<< trim END
4144 vim9script
4145 class A
4146 this._val = 10
4147 endclass
4148 class B extends A
4149 endclass
4150 class C extends B
4151 this.val = 20
4152 endclass
4153 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004154 v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004155
4156 # Two member variables with a common prefix
4157 lines =<< trim END
4158 vim9script
4159 class A
4160 public static svar2: number
4161 public static svar: number
4162 endclass
4163 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004164 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004165enddef
4166
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004167" Test for accessing a private member outside a class in a def function
4168def Test_private_member_access_outside_class()
4169 # private object member variable
4170 var lines =<< trim END
4171 vim9script
4172 class A
4173 this._val = 10
4174 def GetVal(): number
4175 return this._val
4176 enddef
4177 endclass
4178 def T()
4179 var a = A.new()
4180 a._val = 20
4181 enddef
4182 T()
4183 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004184 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004185
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004186 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004187 lines =<< trim END
4188 vim9script
4189 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004190 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004191 endclass
4192 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004193 var a = A.new()
4194 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004195 enddef
4196 T()
4197 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004198 v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": _a')
Ernie Rael18143d32023-09-04 22:30:41 +02004199
4200 # private static member variable
4201 lines =<< trim END
4202 vim9script
4203 class A
4204 static _val = 10
4205 endclass
4206 def T()
4207 var a = A.new()
4208 var x = a._val
4209 enddef
4210 T()
4211 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004212 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004213
4214 # private static member variable
4215 lines =<< trim END
4216 vim9script
4217 class A
4218 static _val = 10
4219 endclass
4220 def T()
4221 var a = A.new()
4222 a._val = 3
4223 enddef
4224 T()
4225 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004226 v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004227
4228 # private static class variable
4229 lines =<< trim END
4230 vim9script
4231 class A
4232 static _val = 10
4233 endclass
4234 def T()
4235 var x = A._val
4236 enddef
4237 T()
4238 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004239 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004240
4241 # private static class variable
4242 lines =<< trim END
4243 vim9script
4244 class A
4245 static _val = 10
4246 endclass
4247 def T()
4248 A._val = 3
4249 enddef
4250 T()
4251 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004252 v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004253enddef
4254
4255" Test for changing the member access of an interface in a implementation class
4256def Test_change_interface_member_access()
4257 var lines =<< trim END
4258 vim9script
4259 interface A
4260 public this.val: number
4261 endinterface
4262 class B implements A
4263 this.val = 10
4264 endclass
4265 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004266 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004267
4268 lines =<< trim END
4269 vim9script
4270 interface A
4271 this.val: number
4272 endinterface
4273 class B implements A
4274 public this.val = 10
4275 endclass
4276 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004277 v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004278enddef
4279
4280" Test for trying to change a readonly member from a def function
4281def Test_readonly_member_change_in_def_func()
4282 var lines =<< trim END
4283 vim9script
4284 class A
4285 this.val: number
4286 endclass
4287 def T()
4288 var a = A.new()
4289 a.val = 20
4290 enddef
4291 T()
4292 END
Ernie Rael696270b2023-09-21 16:42:28 +02004293 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004294enddef
4295
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004296" Test for reading and writing a class member from a def function
4297def Test_modify_class_member_from_def_function()
4298 var lines =<< trim END
4299 vim9script
4300 class A
4301 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004302 public static var2: list<number> = [1, 2]
4303 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004304 static _priv_var4: number = 40
4305 endclass
4306 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004307 assert_equal([1, 2], A.var2)
4308 assert_equal({a: 1, b: 2}, A.var3)
4309 A.var2 = [3, 4]
4310 A.var3 = {c: 3, d: 4}
4311 assert_equal([3, 4], A.var2)
4312 assert_equal({c: 3, d: 4}, A.var3)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004313 assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
4314 enddef
4315 T()
4316 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004317 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004318enddef
4319
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004320" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004321def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004322 var lines =<< trim END
4323 vim9script
4324 class A
4325 public static svar1: list<number> = [1]
4326 public static svar2: list<number> = [2]
4327 endclass
4328
4329 A.svar1->add(3)
4330 A.svar2->add(4)
4331 assert_equal([1, 3], A.svar1)
4332 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004333
4334 def Foo()
4335 A.svar1->add(7)
4336 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004337 assert_equal([1, 3, 7], A.svar1)
4338 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004339 enddef
4340 Foo()
4341 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004342 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004343
4344 # Cannot read from a class variable using an object in script context
4345 lines =<< trim END
4346 vim9script
4347 class A
4348 public this.var1: number
4349 public static svar2: list<number> = [1]
4350 endclass
4351
4352 var a = A.new()
4353 echo a.svar2
4354 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004355 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004356
4357 # Cannot write to a class variable using an object in script context
4358 lines =<< trim END
4359 vim9script
4360 class A
4361 public this.var1: number
4362 public static svar2: list<number> = [1]
4363 endclass
4364
4365 var a = A.new()
4366 a.svar2 = [2]
4367 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004368 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004369
4370 # Cannot read from a class variable using an object in def method context
4371 lines =<< trim END
4372 vim9script
4373 class A
4374 public this.var1: number
4375 public static svar2: list<number> = [1]
4376 endclass
4377
4378 def T()
4379 var a = A.new()
4380 echo a.svar2
4381 enddef
4382 T()
4383 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004384 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004385
4386 # Cannot write to a class variable using an object in def method context
4387 lines =<< trim END
4388 vim9script
4389 class A
4390 public this.var1: number
4391 public static svar2: list<number> = [1]
4392 endclass
4393
4394 def T()
4395 var a = A.new()
4396 a.svar2 = [2]
4397 enddef
4398 T()
4399 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004400 v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004401enddef
4402
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004403" Test for using a interface method using a child object
4404def Test_interface_method_from_child()
4405 var lines =<< trim END
4406 vim9script
4407
4408 interface A
4409 def Foo(): string
4410 endinterface
4411
4412 class B implements A
4413 def Foo(): string
4414 return 'foo'
4415 enddef
4416 endclass
4417
4418 class C extends B
4419 def Bar(): string
4420 return 'bar'
4421 enddef
4422 endclass
4423
4424 def T1(a: A)
4425 assert_equal('foo', a.Foo())
4426 enddef
4427
4428 def T2(b: B)
4429 assert_equal('foo', b.Foo())
4430 enddef
4431
4432 var c = C.new()
4433 T1(c)
4434 T2(c)
4435 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004436 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004437enddef
4438
4439" Test for using an interface method using a child object when it is overridden
4440" by the child class.
4441" FIXME: This test fails.
4442" def Test_interface_overridden_method_from_child()
4443" var lines =<< trim END
4444" vim9script
4445"
4446" interface A
4447" def Foo(): string
4448" endinterface
4449"
4450" class B implements A
4451" def Foo(): string
4452" return 'b-foo'
4453" enddef
4454" endclass
4455"
4456" class C extends B
4457" def Bar(): string
4458" return 'bar'
4459" enddef
4460" def Foo(): string
4461" return 'c-foo'
4462" enddef
4463" endclass
4464"
4465" def T1(a: A)
4466" assert_equal('c-foo', a.Foo())
4467" enddef
4468"
4469" def T2(b: B)
4470" assert_equal('c-foo', b.Foo())
4471" enddef
4472"
4473" var c = C.new()
4474" T1(c)
4475" T2(c)
4476" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004477" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004478" enddef
4479
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004480" Test for abstract methods
4481def Test_abstract_method()
4482 # Use two abstract methods
4483 var lines =<< trim END
4484 vim9script
4485 abstract class A
4486 def M1(): number
4487 return 10
4488 enddef
4489 abstract def M2(): number
4490 abstract def M3(): number
4491 endclass
4492 class B extends A
4493 def M2(): number
4494 return 20
4495 enddef
4496 def M3(): number
4497 return 30
4498 enddef
4499 endclass
4500 var b = B.new()
4501 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4502 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004503 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004504
4505 # Don't define an abstract method
4506 lines =<< trim END
4507 vim9script
4508 abstract class A
4509 abstract def Foo()
4510 endclass
4511 class B extends A
4512 endclass
4513 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004514 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004515
4516 # Use abstract method in a concrete class
4517 lines =<< trim END
4518 vim9script
4519 class A
4520 abstract def Foo()
4521 endclass
4522 class B extends A
4523 endclass
4524 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004525 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004526
4527 # Use abstract method in an interface
4528 lines =<< trim END
4529 vim9script
4530 interface A
4531 abstract def Foo()
4532 endinterface
4533 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004534 def Foo()
4535 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004536 endclass
4537 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004538 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004539
4540 # Abbreviate the "abstract" keyword
4541 lines =<< trim END
4542 vim9script
4543 class A
4544 abs def Foo()
4545 endclass
4546 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004547 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004548
4549 # Use "abstract" with a member variable
4550 lines =<< trim END
4551 vim9script
4552 abstract class A
4553 abstract this.val = 10
4554 endclass
4555 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004556 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004557
4558 # Use a static abstract method
4559 lines =<< trim END
4560 vim9script
4561 abstract class A
4562 abstract static def Foo(): number
4563 endclass
4564 class B extends A
4565 static def Foo(): number
4566 return 4
4567 enddef
4568 endclass
4569 assert_equal(4, B.Foo())
4570 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004571 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004572
4573 # Type mismatch between abstract method and concrete method
4574 lines =<< trim END
4575 vim9script
4576 abstract class A
4577 abstract def Foo(a: string, b: number): list<number>
4578 endclass
4579 class B extends A
4580 def Foo(a: number, b: string): list<string>
4581 return []
4582 enddef
4583 endclass
4584 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004585 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 +02004586
4587 # Use an abstract class to invoke an abstract method
4588 # FIXME: This should fail
4589 lines =<< trim END
4590 vim9script
4591 abstract class A
4592 abstract static def Foo()
4593 endclass
4594 A.Foo()
4595 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004596 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004597
4598 # Invoke an abstract method from a def function
4599 lines =<< trim END
4600 vim9script
4601 abstract class A
4602 abstract def Foo(): list<number>
4603 endclass
4604 class B extends A
4605 def Foo(): list<number>
4606 return [3, 5]
4607 enddef
4608 endclass
4609 def Bar(c: B)
4610 assert_equal([3, 5], c.Foo())
4611 enddef
4612 var b = B.new()
4613 Bar(b)
4614 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004615 v9.CheckSourceSuccess(lines)
4616enddef
4617
4618" Test for calling a class method from a subclass
4619def Test_class_method_call_from_subclass()
4620 # class method call from a subclass
4621 var lines =<< trim END
4622 vim9script
4623
4624 class A
4625 static def Foo()
4626 echo "foo"
4627 enddef
4628 endclass
4629
4630 class B extends A
4631 def Bar()
4632 Foo()
4633 enddef
4634 endclass
4635
4636 var b = B.new()
4637 b.Bar()
4638 END
4639 v9.CheckSourceFailure(lines, 'E1374: Class member "Foo" accessible only inside class "A"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004640enddef
4641
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004642" Test for calling a class method using an object in a def function context and
4643" script context.
4644def Test_class_method_call_using_object()
4645 # script context
4646 var lines =<< trim END
4647 vim9script
4648 class A
4649 static def Foo(): list<string>
4650 return ['a', 'b']
4651 enddef
4652 def Bar()
4653 assert_equal(['a', 'b'], A.Foo())
4654 assert_equal(['a', 'b'], Foo())
4655 enddef
4656 endclass
4657
4658 def T()
4659 assert_equal(['a', 'b'], A.Foo())
4660 var t_a = A.new()
4661 t_a.Bar()
4662 enddef
4663
4664 assert_equal(['a', 'b'], A.Foo())
4665 var a = A.new()
4666 a.Bar()
4667 T()
4668 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004669 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004670
4671 # script context
4672 lines =<< trim END
4673 vim9script
4674 class A
4675 static def Foo(): string
4676 return 'foo'
4677 enddef
4678 endclass
4679
4680 var a = A.new()
4681 assert_equal('foo', a.Foo())
4682 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004683 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004684
4685 # def function context
4686 lines =<< trim END
4687 vim9script
4688 class A
4689 static def Foo(): string
4690 return 'foo'
4691 enddef
4692 endclass
4693
4694 def T()
4695 var a = A.new()
4696 assert_equal('foo', a.Foo())
4697 enddef
4698 T()
4699 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004700 v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
4701enddef
4702
4703def Test_class_variable()
4704 var lines =<< trim END
4705 vim9script
4706
4707 class A
4708 public static val: number = 10
4709 static def ClassFunc()
4710 assert_equal(10, val)
4711 enddef
4712 def ObjFunc()
4713 assert_equal(10, val)
4714 enddef
4715 endclass
4716
4717 class B extends A
4718 endclass
4719
4720 assert_equal(10, A.val)
4721 A.ClassFunc()
4722 var a = A.new()
4723 a.ObjFunc()
4724 var b = B.new()
4725 b.ObjFunc()
4726
4727 def T1(a1: A)
4728 a1.ObjFunc()
4729 A.ClassFunc()
4730 enddef
4731 T1(b)
4732
4733 A.val = 20
4734 assert_equal(20, A.val)
4735 END
4736 v9.CheckSourceSuccess(lines)
4737
4738 # Modifying a parent class variable from a child class method
4739 lines =<< trim END
4740 vim9script
4741
4742 class A
4743 static val: number = 10
4744 endclass
4745
4746 class B extends A
4747 static def ClassFunc()
4748 val = 20
4749 enddef
4750 endclass
4751 B.ClassFunc()
4752 END
4753 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4754
4755 # Reading a parent class variable from a child class method
4756 lines =<< trim END
4757 vim9script
4758
4759 class A
4760 static val: number = 10
4761 endclass
4762
4763 class B extends A
4764 static def ClassFunc()
4765 var i = val
4766 enddef
4767 endclass
4768 B.ClassFunc()
4769 END
4770 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4771
4772 # Modifying a parent class variable from a child object method
4773 lines =<< trim END
4774 vim9script
4775
4776 class A
4777 static val: number = 10
4778 endclass
4779
4780 class B extends A
4781 def ObjFunc()
4782 val = 20
4783 enddef
4784 endclass
4785 var b = B.new()
4786 b.ObjFunc()
4787 END
4788 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4789
4790 # Reading a parent class variable from a child object method
4791 lines =<< trim END
4792 vim9script
4793
4794 class A
4795 static val: number = 10
4796 endclass
4797
4798 class B extends A
4799 def ObjFunc()
4800 var i = val
4801 enddef
4802 endclass
4803 var b = B.new()
4804 b.ObjFunc()
4805 END
4806 v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
4807
4808 # Modifying a class variable using an object at script level
4809 lines =<< trim END
4810 vim9script
4811
4812 class A
4813 static val: number = 10
4814 endclass
4815 var a = A.new()
4816 a.val = 20
4817 END
4818 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4819
4820 # Reading a class variable using an object at script level
4821 lines =<< trim END
4822 vim9script
4823
4824 class A
4825 static val: number = 10
4826 endclass
4827 var a = A.new()
4828 var i = a.val
4829 END
4830 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4831
4832 # Modifying a class variable using an object at function level
4833 lines =<< trim END
4834 vim9script
4835
4836 class A
4837 static val: number = 10
4838 endclass
4839
4840 def T()
4841 var a = A.new()
4842 a.val = 20
4843 enddef
4844 T()
4845 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004846 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004847
4848 # Reading a class variable using an object at function level
4849 lines =<< trim END
4850 vim9script
4851
4852 class A
4853 static val: number = 10
4854 endclass
4855 def T()
4856 var a = A.new()
4857 var i = a.val
4858 enddef
4859 T()
4860 END
4861 v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
4862enddef
4863
4864" Test for using a duplicate class method and class variable in a child class
4865def Test_dup_class_member()
4866 # duplicate class variable, class method and overridden object method
4867 var lines =<< trim END
4868 vim9script
4869 class A
4870 static sval = 100
4871 static def Check()
4872 assert_equal(100, sval)
4873 enddef
4874 def GetVal(): number
4875 return sval
4876 enddef
4877 endclass
4878
4879 class B extends A
4880 static sval = 200
4881 static def Check()
4882 assert_equal(200, sval)
4883 enddef
4884 def GetVal(): number
4885 return sval
4886 enddef
4887 endclass
4888
4889 def T1(aa: A): number
4890 return aa.GetVal()
4891 enddef
4892
4893 def T2(bb: B): number
4894 return bb.GetVal()
4895 enddef
4896
4897 assert_equal(100, A.sval)
4898 assert_equal(200, B.sval)
4899 var a = A.new()
4900 assert_equal(100, a.GetVal())
4901 var b = B.new()
4902 assert_equal(200, b.GetVal())
4903 assert_equal(200, T1(b))
4904 assert_equal(200, T2(b))
4905 END
4906 v9.CheckSourceSuccess(lines)
4907
4908 # duplicate class variable and class method
4909 lines =<< trim END
4910 vim9script
4911 class A
4912 static sval = 100
4913 static def Check()
4914 assert_equal(100, sval)
4915 enddef
4916 def GetVal(): number
4917 return sval
4918 enddef
4919 endclass
4920
4921 class B extends A
4922 static sval = 200
4923 static def Check()
4924 assert_equal(200, sval)
4925 enddef
4926 endclass
4927
4928 def T1(aa: A): number
4929 return aa.GetVal()
4930 enddef
4931
4932 def T2(bb: B): number
4933 return bb.GetVal()
4934 enddef
4935
4936 assert_equal(100, A.sval)
4937 assert_equal(200, B.sval)
4938 var a = A.new()
4939 assert_equal(100, a.GetVal())
4940 var b = B.new()
4941 assert_equal(100, b.GetVal())
4942 assert_equal(100, T1(b))
4943 assert_equal(100, T2(b))
4944 END
4945 v9.CheckSourceSuccess(lines)
4946enddef
4947
4948" Test for calling an instance method using the class
4949def Test_instance_method_call_using_class()
4950 # Invoke an object method using a class in script context
4951 var lines =<< trim END
4952 vim9script
4953 class A
4954 def Foo()
4955 echo "foo"
4956 enddef
4957 endclass
4958 A.Foo()
4959 END
4960 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4961
4962 # Invoke an object method using a class in def function context
4963 lines =<< trim END
4964 vim9script
4965 class A
4966 def Foo()
4967 echo "foo"
4968 enddef
4969 endclass
4970 def T()
4971 A.Foo()
4972 enddef
4973 T()
4974 END
4975 v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
4976enddef
4977
4978" Test for duplicate class method and instance method
4979def Test_dup_classmethod_objmethod()
4980 # Duplicate instance method
4981 var lines =<< trim END
4982 vim9script
4983 class A
4984 static def Foo()
4985 enddef
4986 def Foo()
4987 enddef
4988 endclass
4989 END
4990 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
4991
4992 # Duplicate private instance method
4993 lines =<< trim END
4994 vim9script
4995 class A
4996 static def Foo()
4997 enddef
4998 def _Foo()
4999 enddef
5000 endclass
5001 END
5002 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5003
5004 # Duplicate class method
5005 lines =<< trim END
5006 vim9script
5007 class A
5008 def Foo()
5009 enddef
5010 static def Foo()
5011 enddef
5012 endclass
5013 END
5014 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
5015
5016 # Duplicate private class method
5017 lines =<< trim END
5018 vim9script
5019 class A
5020 def Foo()
5021 enddef
5022 static def _Foo()
5023 enddef
5024 endclass
5025 END
5026 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5027
5028 # Duplicate private class and object method
5029 lines =<< trim END
5030 vim9script
5031 class A
5032 def _Foo()
5033 enddef
5034 static def _Foo()
5035 enddef
5036 endclass
5037 END
5038 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5039enddef
5040
5041" Test for an instance method access level comparison with parent instance
5042" methods.
5043def Test_instance_method_access_level()
5044 # Private method in subclass
5045 var lines =<< trim END
5046 vim9script
5047 class A
5048 def Foo()
5049 enddef
5050 endclass
5051 class B extends A
5052 endclass
5053 class C extends B
5054 def _Foo()
5055 enddef
5056 endclass
5057 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005058 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005059
5060 # Public method in subclass
5061 lines =<< trim END
5062 vim9script
5063 class A
5064 def _Foo()
5065 enddef
5066 endclass
5067 class B extends A
5068 endclass
5069 class C extends B
5070 def Foo()
5071 enddef
5072 endclass
5073 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005074 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005075enddef
5076
5077def Test_extend_empty_class()
5078 var lines =<< trim END
5079 vim9script
5080 class A
5081 endclass
5082 class B extends A
5083 endclass
5084 class C extends B
5085 public static rw_class_var = 1
5086 public this.rw_obj_var = 2
5087 static def ClassMethod(): number
5088 return 3
5089 enddef
5090 def ObjMethod(): number
5091 return 4
5092 enddef
5093 endclass
5094 assert_equal(1, C.rw_class_var)
5095 assert_equal(3, C.ClassMethod())
5096 var c = C.new()
5097 assert_equal(2, c.rw_obj_var)
5098 assert_equal(4, c.ObjMethod())
5099 END
5100 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005101enddef
5102
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005103" A interface cannot have a static variable or a static method or a private
5104" variable or a private method
5105def Test_interface_with_unsupported_members()
5106 var lines =<< trim END
5107 vim9script
5108 interface A
5109 static num: number
5110 endinterface
5111 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005112 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005113
5114 lines =<< trim END
5115 vim9script
5116 interface A
5117 static _num: number
5118 endinterface
5119 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005120 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005121
5122 lines =<< trim END
5123 vim9script
5124 interface A
5125 public static num: number
5126 endinterface
5127 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005128 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005129
5130 lines =<< trim END
5131 vim9script
5132 interface A
5133 public static _num: number
5134 endinterface
5135 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005136 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005137
5138 lines =<< trim END
5139 vim9script
5140 interface A
5141 static def Foo(d: dict<any>): list<string>
5142 endinterface
5143 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005144 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005145
5146 lines =<< trim END
5147 vim9script
5148 interface A
5149 static def _Foo(d: dict<any>): list<string>
5150 endinterface
5151 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005152 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005153
5154 lines =<< trim END
5155 vim9script
5156 interface A
5157 this._Foo: list<string>
5158 endinterface
5159 END
5160 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface')
5161
5162 lines =<< trim END
5163 vim9script
5164 interface A
5165 def _Foo(d: dict<any>): list<string>
5166 endinterface
5167 END
5168 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface')
5169enddef
5170
5171" Test for extending an interface
5172def Test_extend_interface()
5173 var lines =<< trim END
5174 vim9script
5175 interface A
5176 this.var1: list<string>
5177 def Foo()
5178 endinterface
5179 interface B extends A
5180 public this.var2: dict<string>
5181 def Bar()
5182 endinterface
5183 class C implements A, B
5184 this.var1 = [1, 2]
5185 def Foo()
5186 enddef
5187 public this.var2 = {a: '1'}
5188 def Bar()
5189 enddef
5190 endclass
5191 END
5192 v9.CheckSourceSuccess(lines)
5193
5194 lines =<< trim END
5195 vim9script
5196 interface A
5197 def Foo()
5198 endinterface
5199 interface B extends A
5200 public this.var2: dict<string>
5201 endinterface
5202 class C implements A, B
5203 public this.var2 = {a: '1'}
5204 endclass
5205 END
5206 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented')
5207
5208 lines =<< trim END
5209 vim9script
5210 interface A
5211 def Foo()
5212 endinterface
5213 interface B extends A
5214 public this.var2: dict<string>
5215 endinterface
5216 class C implements A, B
5217 def Foo()
5218 enddef
5219 endclass
5220 END
5221 v9.CheckSourceFailure(lines, 'E1348: Member "var2" of interface "B" is not implemented')
5222
5223 # interface cannot extend a class
5224 lines =<< trim END
5225 vim9script
5226 class A
5227 endclass
5228 interface B extends A
5229 endinterface
5230 END
5231 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5232
5233 # class cannot extend an interface
5234 lines =<< trim END
5235 vim9script
5236 interface A
5237 endinterface
5238 class B extends A
5239 endclass
5240 END
5241 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5242
5243 # interface cannot implement another interface
5244 lines =<< trim END
5245 vim9script
5246 interface A
5247 endinterface
5248 interface B implements A
5249 endinterface
5250 END
5251 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"')
5252
5253 # interface cannot extend multiple interfaces
5254 lines =<< trim END
5255 vim9script
5256 interface A
5257 endinterface
5258 interface B
5259 endinterface
5260 interface C extends A, B
5261 endinterface
5262 END
5263 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B')
5264
5265 # Variable type in an extended interface is of different type
5266 lines =<< trim END
5267 vim9script
5268 interface A
5269 this.val1: number
5270 endinterface
5271 interface B extends A
5272 this.val2: string
5273 endinterface
5274 interface C extends B
5275 this.val1: string
5276 this.val2: number
5277 endinterface
5278 END
5279 v9.CheckSourceFailure(lines, 'E1382: Member "val1": type mismatch, expected number but got string')
5280enddef
5281
5282" Test for a child class implementing an interface when some of the methods are
5283" defined in the parent class.
5284def Test_child_class_implements_interface()
5285 var lines =<< trim END
5286 vim9script
5287
5288 interface Intf
5289 def F1(): list<list<number>>
5290 def F2(): list<list<number>>
5291 def F3(): list<list<number>>
5292 this.var1: list<dict<number>>
5293 this.var2: list<dict<number>>
5294 this.var3: list<dict<number>>
5295 endinterface
5296
5297 class A
5298 def A1()
5299 enddef
5300 def F3(): list<list<number>>
5301 return [[3]]
5302 enddef
5303 this.v1: list<list<number>> = [[0]]
5304 this.var3 = [{c: 30}]
5305 endclass
5306
5307 class B extends A
5308 def B1()
5309 enddef
5310 def F2(): list<list<number>>
5311 return [[2]]
5312 enddef
5313 this.v2: list<list<number>> = [[0]]
5314 this.var2 = [{b: 20}]
5315 endclass
5316
5317 class C extends B implements Intf
5318 def C1()
5319 enddef
5320 def F1(): list<list<number>>
5321 return [[1]]
5322 enddef
5323 this.v3: list<list<number>> = [[0]]
5324 this.var1 = [{a: 10}]
5325 endclass
5326
5327 def T(if: Intf)
5328 assert_equal([[1]], if.F1())
5329 assert_equal([[2]], if.F2())
5330 assert_equal([[3]], if.F3())
5331 assert_equal([{a: 10}], if.var1)
5332 assert_equal([{b: 20}], if.var2)
5333 assert_equal([{c: 30}], if.var3)
5334 enddef
5335
5336 var c = C.new()
5337 T(c)
5338 assert_equal([[1]], c.F1())
5339 assert_equal([[2]], c.F2())
5340 assert_equal([[3]], c.F3())
5341 assert_equal([{a: 10}], c.var1)
5342 assert_equal([{b: 20}], c.var2)
5343 assert_equal([{c: 30}], c.var3)
5344 END
5345 v9.CheckSourceSuccess(lines)
5346
5347 # One of the interface methods is not found
5348 lines =<< trim END
5349 vim9script
5350
5351 interface Intf
5352 def F1()
5353 def F2()
5354 def F3()
5355 endinterface
5356
5357 class A
5358 def A1()
5359 enddef
5360 endclass
5361
5362 class B extends A
5363 def B1()
5364 enddef
5365 def F2()
5366 enddef
5367 endclass
5368
5369 class C extends B implements Intf
5370 def C1()
5371 enddef
5372 def F1()
5373 enddef
5374 endclass
5375 END
5376 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented')
5377
5378 # One of the interface methods is of different type
5379 lines =<< trim END
5380 vim9script
5381
5382 interface Intf
5383 def F1()
5384 def F2()
5385 def F3()
5386 endinterface
5387
5388 class A
5389 def F3(): number
5390 return 0
5391 enddef
5392 def A1()
5393 enddef
5394 endclass
5395
5396 class B extends A
5397 def B1()
5398 enddef
5399 def F2()
5400 enddef
5401 endclass
5402
5403 class C extends B implements Intf
5404 def C1()
5405 enddef
5406 def F1()
5407 enddef
5408 endclass
5409 END
5410 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number')
5411
5412 # One of the interface variables is not present
5413 lines =<< trim END
5414 vim9script
5415
5416 interface Intf
5417 this.var1: list<dict<number>>
5418 this.var2: list<dict<number>>
5419 this.var3: list<dict<number>>
5420 endinterface
5421
5422 class A
5423 this.v1: list<list<number>> = [[0]]
5424 endclass
5425
5426 class B extends A
5427 this.v2: list<list<number>> = [[0]]
5428 this.var2 = [{b: 20}]
5429 endclass
5430
5431 class C extends B implements Intf
5432 this.v3: list<list<number>> = [[0]]
5433 this.var1 = [{a: 10}]
5434 endclass
5435 END
5436 v9.CheckSourceFailure(lines, 'E1348: Member "var3" of interface "Intf" is not implemented')
5437
5438 # One of the interface variables is of different type
5439 lines =<< trim END
5440 vim9script
5441
5442 interface Intf
5443 this.var1: list<dict<number>>
5444 this.var2: list<dict<number>>
5445 this.var3: list<dict<number>>
5446 endinterface
5447
5448 class A
5449 this.v1: list<list<number>> = [[0]]
5450 this.var3: list<dict<string>>
5451 endclass
5452
5453 class B extends A
5454 this.v2: list<list<number>> = [[0]]
5455 this.var2 = [{b: 20}]
5456 endclass
5457
5458 class C extends B implements Intf
5459 this.v3: list<list<number>> = [[0]]
5460 this.var1 = [{a: 10}]
5461 endclass
5462 END
5463 v9.CheckSourceFailure(lines, 'E1382: Member "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>')
5464enddef
5465
5466" Test for extending an interface with duplicate variables and methods
5467def Test_interface_extends_with_dup_members()
5468 var lines =<< trim END
5469 vim9script
5470 interface A
5471 this.n1: number
5472 def Foo1(): number
5473 endinterface
5474 interface B extends A
5475 this.n2: number
5476 this.n1: number
5477 def Foo2(): number
5478 def Foo1(): number
5479 endinterface
5480 class C implements B
5481 this.n1 = 10
5482 this.n2 = 20
5483 def Foo1(): number
5484 return 30
5485 enddef
5486 def Foo2(): number
5487 return 40
5488 enddef
5489 endclass
5490 def T1(a: A)
5491 assert_equal(10, a.n1)
5492 assert_equal(30, a.Foo1())
5493 enddef
5494 def T2(b: B)
5495 assert_equal(10, b.n1)
5496 assert_equal(20, b.n2)
5497 assert_equal(30, b.Foo1())
5498 assert_equal(40, b.Foo2())
5499 enddef
5500 var c = C.new()
5501 T1(c)
5502 T2(c)
5503 END
5504 v9.CheckSourceSuccess(lines)
5505enddef
5506
5507" Test for using "any" type for a variable in a sub-class while it has a
5508" concrete type in the interface
5509def Test_implements_using_var_type_any()
5510 var lines =<< trim END
5511 vim9script
5512 interface A
5513 this.val: list<dict<string>>
5514 endinterface
5515 class B implements A
5516 this.val = [{a: '1'}, {b: '2'}]
5517 endclass
5518 var b = B.new()
5519 assert_equal([{a: '1'}, {b: '2'}], b.val)
5520 END
5521 v9.CheckSourceSuccess(lines)
5522
5523 # initialize instance variable using a different type
5524 lines =<< trim END
5525 vim9script
5526 interface A
5527 this.val: list<dict<string>>
5528 endinterface
5529 class B implements A
5530 this.val = {a: 1, b: 2}
5531 endclass
5532 var b = B.new()
5533 END
5534 v9.CheckSourceFailure(lines, 'E1382: Member "val": type mismatch, expected list<dict<string>> but got dict<number>')
5535enddef
5536
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005537" Test for assigning to a member variable in a nested class
5538def Test_nested_object_assignment()
5539 var lines =<< trim END
5540 vim9script
5541
5542 class A
5543 this.value: number
5544 endclass
5545
5546 class B
5547 this.a: A = A.new()
5548 endclass
5549
5550 class C
5551 this.b: B = B.new()
5552 endclass
5553
5554 class D
5555 this.c: C = C.new()
5556 endclass
5557
5558 def T(da: D)
5559 da.c.b.a.value = 10
5560 enddef
5561
5562 var d = D.new()
5563 T(d)
5564 END
Ernie Rael696270b2023-09-21 16:42:28 +02005565 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005566enddef
5567
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02005568" Test for calling methods using a null object
5569def Test_null_object_method_call()
5570 # Calling a object method using a null object in script context
5571 var lines =<< trim END
5572 vim9script
5573
5574 class C
5575 def Foo()
5576 assert_report('This method should not be executed')
5577 enddef
5578 endclass
5579
5580 var o: C
5581 o.Foo()
5582 END
5583 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
5584
5585 # Calling a object method using a null object in def function context
5586 lines =<< trim END
5587 vim9script
5588
5589 class C
5590 def Foo()
5591 assert_report('This method should not be executed')
5592 enddef
5593 endclass
5594
5595 def T()
5596 var o: C
5597 o.Foo()
5598 enddef
5599 T()
5600 END
5601 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5602
5603 # Calling a object method through another class method using a null object in
5604 # script context
5605 lines =<< trim END
5606 vim9script
5607
5608 class C
5609 def Foo()
5610 assert_report('This method should not be executed')
5611 enddef
5612
5613 static def Bar(o_any: any)
5614 var o_typed: C = o_any
5615 o_typed.Foo()
5616 enddef
5617 endclass
5618
5619 var o: C
5620 C.Bar(o)
5621 END
5622 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5623
5624 # Calling a object method through another class method using a null object in
5625 # def function context
5626 lines =<< trim END
5627 vim9script
5628
5629 class C
5630 def Foo()
5631 assert_report('This method should not be executed')
5632 enddef
5633
5634 static def Bar(o_any: any)
5635 var o_typed: C = o_any
5636 o_typed.Foo()
5637 enddef
5638 endclass
5639
5640 def T()
5641 var o: C
5642 C.Bar(o)
5643 enddef
5644 T()
5645 END
5646 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5647enddef
5648
5649" Test for using a dict as an object member
5650def Test_dict_object_member()
5651 var lines =<< trim END
5652 vim9script
5653
5654 class Context
5655 public this.state: dict<number> = {}
5656 def GetState(): dict<number>
5657 return this.state
5658 enddef
5659 endclass
5660
5661 var ctx = Context.new()
5662 ctx.state->extend({a: 1})
5663 ctx.state['b'] = 2
5664 assert_equal({a: 1, b: 2}, ctx.GetState())
5665
5666 def F()
5667 ctx.state['c'] = 3
5668 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
5669 enddef
5670 F()
5671 assert_equal(3, ctx.state.c)
5672 ctx.state.c = 4
5673 assert_equal(4, ctx.state.c)
5674 END
5675 v9.CheckSourceSuccess(lines)
5676enddef
5677
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005678" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker