blob: 2fd66c937f8ef279d321945423475e3b9c6ee669 [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
RestorerZ7fe8f432023-09-24 23:21:24 +0200135 v9.CheckSourceFailure(lines, 'E1326: Variable 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
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200294 vim9script
295 class A
296 this.y = {
297 X: 1
298 }
299 endclass
300 var a = A.new()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200301 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200302 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000303enddef
304
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200305" Tests for object/class methods in a class
306def Test_class_def_method()
307 # Using the "public" keyword when defining an object method
308 var lines =<< trim END
309 vim9script
310 class A
311 public def Foo()
312 enddef
313 endclass
314 END
315 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"', 3)
316
317 # Using the "public" keyword when defining a class method
318 lines =<< trim END
319 vim9script
320 class A
321 public static def Foo()
322 enddef
323 endclass
324 END
325 v9.CheckSourceFailure(lines, 'E1388: Public keyword not supported for a method', 3)
326
327 # Using the "public" keyword when defining an object private method
328 lines =<< trim END
329 vim9script
330 class A
331 public def _Foo()
332 enddef
333 endclass
334 END
335 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"', 3)
336
337 # Using the "public" keyword when defining a class private method
338 lines =<< trim END
339 vim9script
340 class A
341 public static def _Foo()
342 enddef
343 endclass
344 END
345 v9.CheckSourceFailure(lines, 'E1388: Public keyword not supported for a method', 3)
346
347 # Using a "def" keyword without an object method name
348 lines =<< trim END
349 vim9script
350 class A
351 def
352 enddef
353 endclass
354 END
355 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: def', 3)
356
357 # Using a "def" keyword without a class method name
358 lines =<< trim END
359 vim9script
360 class A
361 static def
362 enddef
363 endclass
364 END
365 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: static def', 3)
366enddef
367
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000368def Test_class_defined_twice()
369 # class defined twice should fail
370 var lines =<< trim END
371 vim9script
372 class There
373 endclass
374 class There
375 endclass
376 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200377 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"')
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000378
379 # one class, reload same script twice is OK
380 lines =<< trim END
381 vim9script
382 class There
383 endclass
384 END
385 writefile(lines, 'XclassTwice.vim', 'D')
386 source XclassTwice.vim
387 source XclassTwice.vim
388enddef
389
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000390def Test_returning_null_object()
391 # this was causing an internal error
392 var lines =<< trim END
393 vim9script
394
395 class BufferList
396 def Current(): any
397 return null_object
398 enddef
399 endclass
400
401 var buffers = BufferList.new()
402 echo buffers.Current()
403 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200404 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000405enddef
406
Bram Moolenaard13dd302023-03-11 20:56:35 +0000407def Test_using_null_class()
408 var lines =<< trim END
409 @_ = null_class.member
410 END
411 v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
412enddef
413
Bram Moolenaar657aea72023-01-27 13:16:19 +0000414def Test_class_interface_wrong_end()
415 var lines =<< trim END
416 vim9script
417 abstract class SomeName
418 this.member = 'text'
419 endinterface
420 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200421 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000422
423 lines =<< trim END
424 vim9script
425 export interface AnotherName
426 this.member: string
427 endclass
428 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200429 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
Bram Moolenaar657aea72023-01-27 13:16:19 +0000430enddef
431
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000432def Test_object_not_set()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200433 # Use an uninitialized object in script context
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000434 var lines =<< trim END
435 vim9script
436
437 class State
438 this.value = 'xyz'
439 endclass
440
Bram Moolenaarf2017f22023-02-17 21:29:57 +0000441 var state: State
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000442 var db = {'xyz': 789}
443 echo db[state.value]
444 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200445 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaar0917e862023-02-18 14:42:44 +0000446
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200447 # Use an uninitialized object from a def function
Bram Moolenaar0917e862023-02-18 14:42:44 +0000448 lines =<< trim END
449 vim9script
450
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000451 class Class
452 this.id: string
453 def Method1()
454 echo 'Method1' .. this.id
455 enddef
456 endclass
457
458 var obj: Class
459 def Func()
460 obj.Method1()
461 enddef
462 Func()
463 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200464 v9.CheckSourceFailure(lines, 'E1360:')
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000465
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200466 # Pass an uninitialized object variable to a "new" function and try to call an
467 # object method.
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000468 lines =<< trim END
469 vim9script
470
Bram Moolenaar0917e862023-02-18 14:42:44 +0000471 class Background
472 this.background = 'dark'
473 endclass
474
475 class Colorscheme
476 this._bg: Background
477
478 def GetBackground(): string
479 return this._bg.background
480 enddef
481 endclass
482
483 var bg: Background # UNINITIALIZED
484 echo Colorscheme.new(bg).GetBackground()
485 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200486 v9.CheckSourceFailure(lines, 'E1360:')
Ernie Raelf77a7f72023-03-03 15:05:30 +0000487
488 # TODO: this should not give an error but be handled at runtime
489 lines =<< trim END
490 vim9script
491
492 class Class
493 this.id: string
494 def Method1()
495 echo 'Method1' .. this.id
496 enddef
497 endclass
498
499 var obj = null_object
500 def Func()
501 obj.Method1()
502 enddef
503 Func()
504 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200505 v9.CheckSourceFailure(lines, 'E1363:')
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000506enddef
507
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200508" Null object assignment and comparison
Ernie Rael5c018be2023-08-27 18:40:26 +0200509def Test_null_object_assign_compare()
510 var lines =<< trim END
511 vim9script
512
513 var nullo = null_object
514 def F(): any
515 return nullo
516 enddef
517 assert_equal('object<Unknown>', typename(F()))
518
519 var o0 = F()
520 assert_true(o0 == null_object)
521 assert_true(o0 == null)
522
523 var o1: any = nullo
524 assert_true(o1 == null_object)
525 assert_true(o1 == null)
526
527 def G()
528 var x = null_object
529 enddef
530
531 class C
532 endclass
533 var o2: C
534 assert_true(o2 == null_object)
535 assert_true(o2 == null)
536
537 o2 = null_object
538 assert_true(o2 == null)
539
540 o2 = C.new()
541 assert_true(o2 != null)
542
543 o2 = null_object
544 assert_true(o2 == null)
545 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200546 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200547enddef
548
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200549" Test for object member initialization and disassembly
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000550def Test_class_member_initializer()
551 var lines =<< trim END
552 vim9script
553
554 class TextPosition
555 this.lnum: number = 1
556 this.col: number = 1
557
Bram Moolenaar418b5472022-12-20 13:38:22 +0000558 # constructor with only the line number
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000559 def new(lnum: number)
560 this.lnum = lnum
561 enddef
562 endclass
563
564 var pos = TextPosition.new(3)
565 assert_equal(3, pos.lnum)
566 assert_equal(1, pos.col)
567
568 var instr = execute('disassemble TextPosition.new')
569 assert_match('new\_s*' ..
Bram Moolenaar3ea8a1b2022-12-10 19:03:51 +0000570 '0 NEW TextPosition size \d\+\_s*' ..
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000571 '\d PUSHNR 1\_s*' ..
572 '\d STORE_THIS 0\_s*' ..
573 '\d PUSHNR 1\_s*' ..
574 '\d STORE_THIS 1\_s*' ..
575 'this.lnum = lnum\_s*' ..
576 '\d LOAD arg\[-1]\_s*' ..
577 '\d PUSHNR 0\_s*' ..
578 '\d LOAD $0\_s*' ..
579 '\d\+ STOREINDEX object\_s*' ..
580 '\d\+ RETURN object.*',
581 instr)
582 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200583 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000584enddef
585
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000586def Test_member_any_used_as_object()
587 var lines =<< trim END
588 vim9script
589
590 class Inner
591 this.value: number = 0
592 endclass
593
594 class Outer
595 this.inner: any
596 endclass
597
598 def F(outer: Outer)
599 outer.inner.value = 1
600 enddef
601
602 var inner_obj = Inner.new(0)
603 var outer_obj = Outer.new(inner_obj)
604 F(outer_obj)
605 assert_equal(1, inner_obj.value)
606 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200607 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000608
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200609 # Try modifying a private variable using an "any" object
610 lines =<< trim END
611 vim9script
612
613 class Inner
614 this._value: string = ''
615 endclass
616
617 class Outer
618 this.inner: any
619 endclass
620
621 def F(outer: Outer)
622 outer.inner._value = 'b'
623 enddef
624
625 var inner_obj = Inner.new('a')
626 var outer_obj = Outer.new(inner_obj)
627 F(outer_obj)
628 END
RestorerZ7fe8f432023-09-24 23:21:24 +0200629 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _value')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200630
631 # Try modifying a non-existing variable using an "any" object
632 lines =<< trim END
633 vim9script
634
635 class Inner
636 this.value: string = ''
637 endclass
638
639 class Outer
640 this.inner: any
641 endclass
642
643 def F(outer: Outer)
644 outer.inner.someval = 'b'
645 enddef
646
647 var inner_obj = Inner.new('a')
648 var outer_obj = Outer.new(inner_obj)
649 F(outer_obj)
650 END
RestorerZ7fe8f432023-09-24 23:21:24 +0200651 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "Inner": someval')
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000652enddef
653
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200654" Nested assignment to a object variable which is of another class type
655def Test_assignment_nested_type()
656 var lines =<< trim END
657 vim9script
658
659 class Inner
660 public this.value: number = 0
661 endclass
662
663 class Outer
664 this.inner: Inner
665 endclass
666
667 def F(outer: Outer)
668 outer.inner.value = 1
669 enddef
670
671 def Test_assign_to_nested_typed_member()
672 var inner = Inner.new(0)
673 var outer = Outer.new(inner)
674 F(outer)
675 assert_equal(1, inner.value)
676 enddef
677
678 Test_assign_to_nested_typed_member()
Ernie Rael98e68c02023-09-20 20:13:06 +0200679
680 var script_inner = Inner.new(0)
681 var script_outer = Outer.new(script_inner)
682 script_outer.inner.value = 1
683 assert_equal(1, script_inner.value)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200684 END
685 v9.CheckSourceSuccess(lines)
Ernie Rael98e68c02023-09-20 20:13:06 +0200686
687 # Assignment where target item is read only in :def
688 lines =<< trim END
689 vim9script
690
691 class Inner
692 this.value: number = 0
693 endclass
694
695 class Outer
696 this.inner: Inner
697 endclass
698
699 def F(outer: Outer)
700 outer.inner.value = 1
701 enddef
702
703 def Test_assign_to_nested_typed_member()
704 var inner = Inner.new(0)
705 var outer = Outer.new(inner)
706 F(outer)
707 assert_equal(1, inner.value)
708 enddef
709
710 Test_assign_to_nested_typed_member()
711 END
Ernie Rael696270b2023-09-21 16:42:28 +0200712 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable')
Ernie Rael98e68c02023-09-20 20:13:06 +0200713
714 # Assignment where target item is read only script level
715 lines =<< trim END
716 vim9script
717
718 class Inner
719 this.value: number = 0
720 endclass
721
722 class Outer
723 this.inner: Inner
724 endclass
725
726 def F(outer: Outer)
727 outer.inner.value = 1
728 enddef
729
730 var script_inner = Inner.new(0)
731 var script_outer = Outer.new(script_inner)
732 script_outer.inner.value = 1
733 assert_equal(1, script_inner.value)
734 END
Ernie Rael696270b2023-09-21 16:42:28 +0200735 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200736enddef
737
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000738def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200739 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000740 var lines =<< trim END
741 vim9script
742
743 class Foo
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +0200744 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000745
746 def Add(n: number)
747 this.x += n
748 enddef
749 endclass
750
751 var f = Foo.new(3)
752 f.Add(17)
753 assert_equal(20, f.x)
Bram Moolenaar22363c62023-04-24 17:15:25 +0100754
755 def AddToFoo(obj: Foo)
756 obj.x += 3
757 enddef
758
759 AddToFoo(f)
760 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000761 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200762 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000763enddef
764
Bram Moolenaarf4508042023-01-15 16:54:57 +0000765def Test_list_of_objects()
766 var lines =<< trim END
767 vim9script
768
769 class Foo
770 def Add()
771 enddef
772 endclass
773
774 def ProcessList(fooList: list<Foo>)
775 for foo in fooList
776 foo.Add()
777 endfor
778 enddef
779
780 var l: list<Foo> = [Foo.new()]
781 ProcessList(l)
782 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200783 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000784enddef
785
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000786def Test_expr_after_using_object()
787 var lines =<< trim END
788 vim9script
789
790 class Something
791 this.label: string = ''
792 endclass
793
794 def Foo(): Something
795 var v = Something.new()
796 echo 'in Foo(): ' .. typename(v)
797 return v
798 enddef
799
800 Foo()
801 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200802 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000803enddef
804
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000805def Test_class_default_new()
806 var lines =<< trim END
807 vim9script
808
809 class TextPosition
810 this.lnum: number = 1
811 this.col: number = 1
812 endclass
813
814 var pos = TextPosition.new()
815 assert_equal(1, pos.lnum)
816 assert_equal(1, pos.col)
817
818 pos = TextPosition.new(v:none, v:none)
819 assert_equal(1, pos.lnum)
820 assert_equal(1, pos.col)
821
822 pos = TextPosition.new(3, 22)
823 assert_equal(3, pos.lnum)
824 assert_equal(22, pos.col)
825
826 pos = TextPosition.new(v:none, 33)
827 assert_equal(1, pos.lnum)
828 assert_equal(33, pos.col)
829 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200830 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000831
832 lines =<< trim END
833 vim9script
834 class Person
835 this.name: string
836 this.age: number = 42
837 this.education: string = "unknown"
838
839 def new(this.name, this.age = v:none, this.education = v:none)
840 enddef
841 endclass
842
843 var piet = Person.new("Piet")
844 assert_equal("Piet", piet.name)
845 assert_equal(42, piet.age)
846 assert_equal("unknown", piet.education)
847
848 var chris = Person.new("Chris", 4, "none")
849 assert_equal("Chris", chris.name)
850 assert_equal(4, chris.age)
851 assert_equal("none", chris.education)
852 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200853 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000854
855 lines =<< trim END
856 vim9script
857 class Person
858 this.name: string
859 this.age: number = 42
860 this.education: string = "unknown"
861
862 def new(this.name, this.age = v:none, this.education = v:none)
863 enddef
864 endclass
865
866 var missing = Person.new()
867 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200868 v9.CheckSourceFailure(lines, 'E119:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200869
870 # Using a specific value to initialize an instance variable in the new()
871 # method.
872 lines =<< trim END
873 vim9script
874 class A
875 this.val: string
876 def new(this.val = 'a')
877 enddef
878 endclass
879 END
880 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'")
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000881enddef
882
h-east2261c892023-08-16 21:49:54 +0900883def Test_class_new_with_object_member()
884 var lines =<< trim END
885 vim9script
886
887 class C
888 this.str: string
889 this.num: number
890 def new(this.str, this.num)
891 enddef
892 def newVals(this.str, this.num)
893 enddef
894 endclass
895
896 def Check()
897 try
898 var c = C.new('cats', 2)
899 assert_equal('cats', c.str)
900 assert_equal(2, c.num)
901
902 c = C.newVals('dogs', 4)
903 assert_equal('dogs', c.str)
904 assert_equal(4, c.num)
905 catch
906 assert_report($'Unexpected exception was caught: {v:exception}')
907 endtry
908 enddef
909
910 Check()
911 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200912 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900913
914 lines =<< trim END
915 vim9script
916
917 class C
918 this.str: string
919 this.num: number
920 def new(this.str, this.num)
921 enddef
922 endclass
923
924 def Check()
925 try
926 var c = C.new(1, 2)
927 catch
928 assert_report($'Unexpected exception was caught: {v:exception}')
929 endtry
930 enddef
931
932 Check()
933 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200934 v9.CheckSourceFailure(lines, 'E1013:')
h-east2261c892023-08-16 21:49:54 +0900935
936 lines =<< trim END
937 vim9script
938
939 class C
940 this.str: string
941 this.num: number
942 def newVals(this.str, this.num)
943 enddef
944 endclass
945
946 def Check()
947 try
948 var c = C.newVals('dogs', 'apes')
949 catch
950 assert_report($'Unexpected exception was caught: {v:exception}')
951 endtry
952 enddef
953
954 Check()
955 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200956 v9.CheckSourceFailure(lines, 'E1013:')
h-eastb895b0f2023-09-24 15:46:31 +0200957
958 lines =<< trim END
959 vim9script
960
961 class C
962 this.str: string
963 def new(str: any)
964 enddef
965 endclass
966
967 def Check()
968 try
969 var c = C.new(1)
970 catch
971 assert_report($'Unexpected exception was caught: {v:exception}')
972 endtry
973 enddef
974
975 Check()
976 END
977 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900978enddef
979
Bram Moolenaar74e12742022-12-13 21:14:28 +0000980def Test_class_object_member_inits()
981 var lines =<< trim END
982 vim9script
983 class TextPosition
984 this.lnum: number
985 this.col = 1
986 this.addcol: number = 2
987 endclass
988
989 var pos = TextPosition.new()
990 assert_equal(0, pos.lnum)
991 assert_equal(1, pos.col)
992 assert_equal(2, pos.addcol)
993 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200994 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000995
996 lines =<< trim END
997 vim9script
998 class TextPosition
999 this.lnum
1000 this.col = 1
1001 endclass
1002 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001003 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar74e12742022-12-13 21:14:28 +00001004
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001005 # If the type is not specified for a member, then it should be set during
1006 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +00001007 lines =<< trim END
1008 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001009
1010 var init_count = 0
1011 def Init(): string
1012 init_count += 1
1013 return 'foo'
1014 enddef
1015
1016 class A
1017 this.str1 = Init()
1018 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +00001019 this.col = 1
1020 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001021
1022 assert_equal(init_count, 0)
1023 var a = A.new()
1024 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001025 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001026 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001027
1028 # Test for initializing an object member with an unknown variable/type
1029 lines =<< trim END
1030 vim9script
1031 class A
1032 this.value = init_val
1033 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001034 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001035 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001036 v9.CheckSourceFailure(lines, 'E1001:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001037
1038 # Test for initializing an object member with an special type
1039 lines =<< trim END
1040 vim9script
1041 class A
1042 this.value: void
1043 endclass
1044 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001045 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void')
Bram Moolenaar74e12742022-12-13 21:14:28 +00001046enddef
1047
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001048" Test for instance variable access
1049def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001050 var lines =<< trim END
1051 vim9script
1052 class Triple
1053 this._one = 1
1054 this.two = 2
1055 public this.three = 3
1056
1057 def GetOne(): number
1058 return this._one
1059 enddef
1060 endclass
1061
1062 var trip = Triple.new()
1063 assert_equal(1, trip.GetOne())
1064 assert_equal(2, trip.two)
1065 assert_equal(3, trip.three)
1066 assert_fails('echo trip._one', 'E1333')
1067
1068 assert_fails('trip._one = 11', 'E1333')
1069 assert_fails('trip.two = 22', 'E1335')
1070 trip.three = 33
1071 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001072
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001073 assert_fails('trip.four = 4', 'E1326')
Bram Moolenaard505d172022-12-18 21:42:55 +00001074 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001075 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001076
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001077 # Test for a public member variable name beginning with an underscore
1078 lines =<< trim END
1079 vim9script
1080 class A
1081 public this._val = 10
1082 endclass
1083 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001084 v9.CheckSourceFailure(lines, 'E1332:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001085
Bram Moolenaar590162c2022-12-24 21:24:06 +00001086 lines =<< trim END
1087 vim9script
1088
1089 class MyCar
1090 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +00001091 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001092
1093 def new(make_arg: string)
1094 this.make = make_arg
1095 enddef
1096
1097 def GetMake(): string
1098 return $"make = {this.make}"
1099 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +00001100 def GetAge(): number
1101 return this.age
1102 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +00001103 endclass
1104
1105 var c = MyCar.new("abc")
1106 assert_equal('make = abc', c.GetMake())
1107
1108 c = MyCar.new("def")
1109 assert_equal('make = def', c.GetMake())
1110
1111 var c2 = MyCar.new("123")
1112 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +00001113
1114 def CheckCar()
1115 assert_equal("make = def", c.GetMake())
1116 assert_equal(5, c.GetAge())
1117 enddef
1118 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001119 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001120 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001121
1122 lines =<< trim END
1123 vim9script
1124
1125 class MyCar
1126 this.make: string
1127
1128 def new(make_arg: string)
1129 this.make = make_arg
1130 enddef
1131 endclass
1132
1133 var c = MyCar.new("abc")
1134 var c = MyCar.new("def")
1135 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001136 v9.CheckSourceFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +00001137
1138 lines =<< trim END
1139 vim9script
1140
1141 class Foo
1142 this.x: list<number> = []
1143
1144 def Add(n: number): any
1145 this.x->add(n)
1146 return this
1147 enddef
1148 endclass
1149
1150 echo Foo.new().Add(1).Add(2).x
1151 echo Foo.new().Add(1).Add(2)
1152 .x
1153 echo Foo.new().Add(1)
1154 .Add(2).x
1155 echo Foo.new()
1156 .Add(1).Add(2).x
1157 echo Foo.new()
1158 .Add(1)
1159 .Add(2)
1160 .x
1161 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001162 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001163
1164 # Test for "public" cannot be abbreviated
1165 lines =<< trim END
1166 vim9script
1167 class Something
1168 pub this.val = 1
1169 endclass
1170 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001171 v9.CheckSourceFailure(lines, 'E1065:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001172
1173 # Test for "public" keyword must be followed by "this" or "static".
1174 lines =<< trim END
1175 vim9script
1176 class Something
1177 public val = 1
1178 endclass
1179 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001180 v9.CheckSourceFailure(lines, 'E1331:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001181
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001182 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001183 lines =<< trim END
1184 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001185 class A
1186 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001187 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001188 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001189 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001190 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001191
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001192 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001193 lines =<< trim END
1194 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001195 class A
1196 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001197 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001198 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001199 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001200 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001201
1202 # Modify a instance variable using the class name in a def function
1203 lines =<< trim END
1204 vim9script
1205 class A
1206 public this.val = 1
1207 endclass
1208 def T()
1209 A.val = 1
1210 enddef
1211 T()
1212 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001213 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001214
1215 # Read a instance variable using the class name in a def function
1216 lines =<< trim END
1217 vim9script
1218 class A
1219 public this.val = 1
1220 endclass
1221 def T()
1222 var i = A.val
1223 enddef
1224 T()
1225 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001226 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Ernie Raelcf138d42023-09-06 20:45:03 +02001227
1228 # Access from child class extending a class:
1229 lines =<< trim END
1230 vim9script
1231 class A
1232 this.ro_obj_var = 10
1233 public this.rw_obj_var = 20
1234 this._priv_obj_var = 30
Ernie Raelcf138d42023-09-06 20:45:03 +02001235 endclass
1236
1237 class B extends A
1238 def Foo()
1239 var x: number
1240 x = this.ro_obj_var
1241 this.ro_obj_var = 0
1242 x = this.rw_obj_var
1243 this.rw_obj_var = 0
1244 x = this._priv_obj_var
1245 this._priv_obj_var = 0
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001246 enddef
1247 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001248
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001249 var b = B.new()
1250 b.Foo()
1251 END
1252 v9.CheckSourceSuccess(lines)
1253enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001254
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001255" Test for class variable access
1256def Test_class_variable_access()
1257 # Test for "static" cannot be abbreviated
1258 var lines =<< trim END
1259 vim9script
1260 class Something
1261 stat this.val = 1
1262 endclass
1263 END
1264 v9.CheckSourceFailure(lines, 'E1065:')
1265
1266 # Test for "static" cannot be followed by "this".
1267 lines =<< trim END
1268 vim9script
1269 class Something
1270 static this.val = 1
1271 endclass
1272 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001273 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a variable name')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001274
1275 # Test for "static" cannot be followed by "public".
1276 lines =<< trim END
1277 vim9script
1278 class Something
1279 static public val = 1
1280 endclass
1281 END
1282 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
1283
1284 # A readonly class variable cannot be modified from a child class
1285 lines =<< trim END
1286 vim9script
1287 class A
1288 static ro_class_var = 40
1289 endclass
1290
1291 class B extends A
1292 def Foo()
1293 A.ro_class_var = 50
1294 enddef
1295 endclass
1296
1297 var b = B.new()
1298 b.Foo()
1299 END
Ernie Rael696270b2023-09-21 16:42:28 +02001300 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001301
1302 # A private class variable cannot be accessed from a child class
1303 lines =<< trim END
1304 vim9script
1305 class A
1306 static _priv_class_var = 60
1307 endclass
1308
1309 class B extends A
1310 def Foo()
1311 var i = A._priv_class_var
1312 enddef
1313 endclass
1314
1315 var b = B.new()
1316 b.Foo()
1317 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001318 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _priv_class_var')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001319
1320 # A private class variable cannot be modified from a child class
1321 lines =<< trim END
1322 vim9script
1323 class A
1324 static _priv_class_var = 60
1325 endclass
1326
1327 class B extends A
1328 def Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001329 A._priv_class_var = 0
1330 enddef
1331 endclass
1332
1333 var b = B.new()
1334 b.Foo()
1335 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001336 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _priv_class_var')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001337
1338 # Access from child class extending a class and from script context
1339 lines =<< trim END
1340 vim9script
1341 class A
1342 static ro_class_var = 10
1343 public static rw_class_var = 20
1344 static _priv_class_var = 30
1345 endclass
1346
1347 class B extends A
1348 def Foo()
1349 var x: number
1350 x = A.ro_class_var
1351 assert_equal(10, x)
1352 x = A.rw_class_var
1353 assert_equal(25, x)
1354 A.rw_class_var = 20
1355 assert_equal(20, A.rw_class_var)
1356 enddef
1357 endclass
1358
1359 assert_equal(10, A.ro_class_var)
1360 assert_equal(20, A.rw_class_var)
1361 A.rw_class_var = 25
1362 assert_equal(25, A.rw_class_var)
1363 var b = B.new()
1364 b.Foo()
1365 END
1366 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001367enddef
1368
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001369def Test_class_object_compare()
1370 var class_lines =<< trim END
1371 vim9script
1372 class Item
1373 this.nr = 0
1374 this.name = 'xx'
1375 endclass
1376 END
1377
1378 # used at the script level and in a compiled function
1379 var test_lines =<< trim END
1380 var i1 = Item.new()
1381 assert_equal(i1, i1)
1382 assert_true(i1 is i1)
1383 var i2 = Item.new()
1384 assert_equal(i1, i2)
1385 assert_false(i1 is i2)
1386 var i3 = Item.new(0, 'xx')
1387 assert_equal(i1, i3)
1388
1389 var io1 = Item.new(1, 'xx')
1390 assert_notequal(i1, io1)
1391 var io2 = Item.new(0, 'yy')
1392 assert_notequal(i1, io2)
1393 END
1394
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001395 v9.CheckSourceSuccess(class_lines + test_lines)
1396 v9.CheckSourceSuccess(
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001397 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001398
1399 for op in ['>', '>=', '<', '<=', '=~', '!~']
1400 var op_lines = [
1401 'var i1 = Item.new()',
1402 'var i2 = Item.new()',
1403 'echo i1 ' .. op .. ' i2',
1404 ]
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001405 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
1406 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001407 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001408 endfor
1409enddef
1410
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001411def Test_object_type()
1412 var lines =<< trim END
1413 vim9script
1414
1415 class One
1416 this.one = 1
1417 endclass
1418 class Two
1419 this.two = 2
1420 endclass
1421 class TwoMore extends Two
1422 this.more = 9
1423 endclass
1424
1425 var o: One = One.new()
1426 var t: Two = Two.new()
1427 var m: TwoMore = TwoMore.new()
1428 var tm: Two = TwoMore.new()
1429
1430 t = m
1431 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001432 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001433
1434 lines =<< trim END
1435 vim9script
1436
1437 class One
1438 this.one = 1
1439 endclass
1440 class Two
1441 this.two = 2
1442 endclass
1443
1444 var o: One = Two.new()
1445 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001446 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001447
1448 lines =<< trim END
1449 vim9script
1450
1451 interface One
1452 def GetMember(): number
1453 endinterface
1454 class Two implements One
1455 this.one = 1
1456 def GetMember(): number
1457 return this.one
1458 enddef
1459 endclass
1460
1461 var o: One = Two.new(5)
1462 assert_equal(5, o.GetMember())
1463 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001464 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001465
1466 lines =<< trim END
1467 vim9script
1468
1469 class Num
1470 this.n: number = 0
1471 endclass
1472
1473 def Ref(name: string): func(Num): Num
1474 return (arg: Num): Num => {
1475 return eval(name)(arg)
1476 }
1477 enddef
1478
1479 const Fn = Ref('Double')
1480 var Double = (m: Num): Num => Num.new(m.n * 2)
1481
1482 echo Fn(Num.new(4))
1483 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001484 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001485enddef
1486
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001487def Test_class_member()
1488 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001489 var lines =<< trim END
1490 vim9script
1491 class TextPos
1492 this.lnum = 1
1493 this.col = 1
1494 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001495 static _secret = 7
1496 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001497
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001498 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001499 counter += nr
1500 enddef
1501 endclass
1502
1503 assert_equal(0, TextPos.counter)
1504 TextPos.AddToCounter(3)
1505 assert_equal(3, TextPos.counter)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001506 assert_fails('echo TextPos.noSuchMember', 'E1337:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001507
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001508 def GetCounter(): number
1509 return TextPos.counter
1510 enddef
1511 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001512
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001513 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001514 assert_fails('TextPos.counter = 5', 'E1335:')
1515 assert_fails('TextPos.counter += 5', 'E1335:')
1516
1517 assert_fails('echo TextPos._secret', 'E1333:')
1518 assert_fails('TextPos._secret = 8', 'E1333:')
1519
1520 assert_equal(42, TextPos.anybody)
1521 TextPos.anybody = 12
1522 assert_equal(12, TextPos.anybody)
1523 TextPos.anybody += 5
1524 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001525 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001526 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001527
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001528 # example in the help
1529 lines =<< trim END
1530 vim9script
1531 class OtherThing
1532 this.size: number
1533 static totalSize: number
1534
1535 def new(this.size)
1536 totalSize += this.size
1537 enddef
1538 endclass
1539 assert_equal(0, OtherThing.totalSize)
1540 var to3 = OtherThing.new(3)
1541 assert_equal(3, OtherThing.totalSize)
1542 var to7 = OtherThing.new(7)
1543 assert_equal(10, OtherThing.totalSize)
1544 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001545 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001546
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001547 # using static class member twice
1548 lines =<< trim END
1549 vim9script
1550
1551 class HTML
1552 static author: string = 'John Doe'
1553
1554 static def MacroSubstitute(s: string): string
1555 return substitute(s, '{{author}}', author, 'gi')
1556 enddef
1557 endclass
1558
1559 assert_equal('some text', HTML.MacroSubstitute('some text'))
1560 assert_equal('some text', HTML.MacroSubstitute('some text'))
1561 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001562 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001563
Bram Moolenaar62a69232023-01-24 15:07:04 +00001564 # access private member in lambda
1565 lines =<< trim END
1566 vim9script
1567
1568 class Foo
1569 this._x: number = 0
1570
1571 def Add(n: number): number
1572 const F = (): number => this._x + n
1573 return F()
1574 enddef
1575 endclass
1576
1577 var foo = Foo.new()
1578 assert_equal(5, foo.Add(5))
1579 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001580 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001581
h-east2bd6a092023-05-19 19:01:17 +01001582 # access private member in lambda body
1583 lines =<< trim END
1584 vim9script
1585
1586 class Foo
1587 this._x: number = 6
1588
1589 def Add(n: number): number
1590 var Lam = () => {
1591 this._x = this._x + n
1592 }
1593 Lam()
1594 return this._x
1595 enddef
1596 endclass
1597
1598 var foo = Foo.new()
1599 assert_equal(13, foo.Add(7))
1600 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001601 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001602
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001603 # check shadowing
1604 lines =<< trim END
1605 vim9script
1606
1607 class Some
1608 static count = 0
1609 def Method(count: number)
1610 echo count
1611 enddef
1612 endclass
1613
1614 var s = Some.new()
1615 s.Method(7)
1616 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001617 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001618
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001619 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001620 lines =<< trim END
1621 vim9script
1622
1623 class Some
1624 static count = 0
1625 def Method(arg: number)
1626 var count = 3
1627 echo arg count
1628 enddef
1629 endclass
1630
1631 var s = Some.new()
1632 s.Method(7)
1633 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001634 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001635
1636 # Test for using an invalid type for a member variable
1637 lines =<< trim END
1638 vim9script
1639 class A
1640 this.val: xxx
1641 endclass
1642 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001643 v9.CheckSourceFailure(lines, 'E1010:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001644
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001645 # Test for setting a member on a null object
1646 lines =<< trim END
1647 vim9script
1648 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001649 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001650 endclass
1651
1652 def F()
1653 var obj: A
1654 obj.val = ""
1655 enddef
1656 F()
1657 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001658 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001659
1660 # Test for accessing a member on a null object
1661 lines =<< trim END
1662 vim9script
1663 class A
1664 this.val: string
1665 endclass
1666
1667 def F()
1668 var obj: A
1669 echo obj.val
1670 enddef
1671 F()
1672 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001673 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001674
1675 # Test for setting a member on a null object, at script level
1676 lines =<< trim END
1677 vim9script
1678 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001679 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001680 endclass
1681
1682 var obj: A
1683 obj.val = ""
1684 END
1685 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001686 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001687
1688 # Test for accessing a member on a null object, at script level
1689 lines =<< trim END
1690 vim9script
1691 class A
1692 this.val: string
1693 endclass
1694
1695 var obj: A
1696 echo obj.val
1697 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001698 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001699
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001700 # Test for no space before or after the '=' when initializing a member
1701 # variable
1702 lines =<< trim END
1703 vim9script
1704 class A
1705 this.val: number= 10
1706 endclass
1707 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001708 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001709 lines =<< trim END
1710 vim9script
1711 class A
1712 this.val: number =10
1713 endclass
1714 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001715 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001716
1717 # Access a non-existing member
1718 lines =<< trim END
1719 vim9script
1720 class A
1721 endclass
1722 var a = A.new()
1723 var v = a.bar
1724 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001725 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "A": bar')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001726enddef
1727
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001728func Test_class_garbagecollect()
1729 let lines =<< trim END
1730 vim9script
1731
1732 class Point
1733 this.p = [2, 3]
1734 static pl = ['a', 'b']
1735 static pd = {a: 'a', b: 'b'}
1736 endclass
1737
1738 echo Point.pl Point.pd
1739 call test_garbagecollect_now()
1740 echo Point.pl Point.pd
1741 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001742 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001743
1744 let lines =<< trim END
1745 vim9script
1746
1747 interface View
1748 endinterface
1749
1750 class Widget
1751 this.view: View
1752 endclass
1753
1754 class MyView implements View
1755 this.widget: Widget
1756
1757 def new()
1758 # this will result in a circular reference to this object
1759 this.widget = Widget.new(this)
1760 enddef
1761 endclass
1762
1763 var view = MyView.new()
1764
1765 # overwrite "view", will be garbage-collected next
1766 view = MyView.new()
1767 test_garbagecollect_now()
1768 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001769 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001770endfunc
1771
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001772" Test interface garbage collection
1773func Test_interface_garbagecollect()
1774 let lines =<< trim END
1775 vim9script
1776
1777 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001778 this.ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001779
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001780 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001781 endinterface
1782
1783 class A implements I
1784 static ro_class_var: number = 10
1785 public static rw_class_var: number = 20
1786 static _priv_class_var: number = 30
1787 this.ro_obj_var: number = 40
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001788 this._priv_obj_var: number = 60
1789
1790 static def _ClassBar(): number
1791 return _priv_class_var
1792 enddef
1793
1794 static def ClassFoo(): number
1795 return ro_class_var + rw_class_var + A._ClassBar()
1796 enddef
1797
1798 def _ObjBar(): number
1799 return this._priv_obj_var
1800 enddef
1801
1802 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001803 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001804 enddef
1805 endclass
1806
1807 assert_equal(60, A.ClassFoo())
1808 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001809 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001810 test_garbagecollect_now()
1811 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001812 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001813 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001814 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001815endfunc
1816
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001817def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001818 var lines =<< trim END
1819 vim9script
1820 class Value
1821 this.value = 0
1822 static objects = 0
1823
1824 def new(v: number)
1825 this.value = v
1826 ++objects
1827 enddef
1828
1829 static def GetCount(): number
1830 return objects
1831 enddef
1832 endclass
1833
1834 assert_equal(0, Value.GetCount())
1835 var v1 = Value.new(2)
1836 assert_equal(1, Value.GetCount())
1837 var v2 = Value.new(7)
1838 assert_equal(2, Value.GetCount())
1839 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001840 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001841
1842 # Test for cleaning up after a class definition failure when using class
1843 # functions.
1844 lines =<< trim END
1845 vim9script
1846 class A
1847 static def Foo()
1848 enddef
1849 aaa
1850 endclass
1851 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001852 v9.CheckSourceFailure(lines, 'E1318:')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001853
1854 # Test for calling a class method from another class method without the class
1855 # name prefix.
1856 lines =<< trim END
1857 vim9script
1858 class A
1859 static myList: list<number> = [1]
1860 static def Foo(n: number)
1861 myList->add(n)
1862 enddef
1863 static def Bar()
1864 Foo(2)
1865 enddef
1866 def Baz()
1867 Foo(3)
1868 enddef
1869 endclass
1870 A.Bar()
1871 var a = A.new()
1872 a.Baz()
1873 assert_equal([1, 2, 3], A.myList)
1874 END
1875 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001876enddef
1877
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001878def Test_class_defcompile()
1879 var lines =<< trim END
1880 vim9script
1881
1882 class C
1883 def Fo(i: number): string
1884 return i
1885 enddef
1886 endclass
1887
1888 defcompile C.Fo
1889 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001890 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001891
1892 lines =<< trim END
1893 vim9script
1894
1895 class C
1896 static def Fc(): number
1897 return 'x'
1898 enddef
1899 endclass
1900
1901 defcompile C.Fc
1902 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001903 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001904
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001905 lines =<< trim END
1906 vim9script
1907
1908 class C
1909 static def new()
1910 enddef
1911 endclass
1912
1913 defcompile C.new
1914 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001915 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static')
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001916
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001917 # Trying to compile a function using a non-existing class variable
1918 lines =<< trim END
1919 vim9script
1920 defcompile x.Foo()
1921 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001922 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001923
1924 # Trying to compile a function using a variable which is not a class
1925 lines =<< trim END
1926 vim9script
1927 var x: number
1928 defcompile x.Foo()
1929 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001930 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001931
1932 # Trying to compile a function without specifying the name
1933 lines =<< trim END
1934 vim9script
1935 class A
1936 endclass
1937 defcompile A.
1938 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001939 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001940
1941 # Trying to compile a non-existing class object member function
1942 lines =<< trim END
1943 vim9script
1944 class A
1945 endclass
1946 var a = A.new()
1947 defcompile a.Foo()
1948 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001949 v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001950enddef
1951
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001952def Test_class_object_to_string()
1953 var lines =<< trim END
1954 vim9script
1955 class TextPosition
1956 this.lnum = 1
1957 this.col = 22
1958 endclass
1959
1960 assert_equal("class TextPosition", string(TextPosition))
1961
1962 var pos = TextPosition.new()
1963 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1964 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001965 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001966enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001967
Bram Moolenaar554d0312023-01-05 19:59:18 +00001968def Test_interface_basics()
1969 var lines =<< trim END
1970 vim9script
1971 interface Something
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001972 this.ro_var: list<number>
Bram Moolenaar554d0312023-01-05 19:59:18 +00001973 def GetCount(): number
1974 endinterface
1975 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001976 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001977
1978 lines =<< trim END
1979 interface SomethingWrong
1980 static count = 7
1981 endinterface
1982 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001983 v9.CheckSourceFailure(lines, 'E1342:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001984
1985 lines =<< trim END
1986 vim9script
1987
1988 interface Some
Bram Moolenaard40f00c2023-01-13 17:36:49 +00001989 this.value: number
1990 def Method(value: number)
1991 endinterface
1992 END
h-east61378a12023-04-18 19:07:29 +01001993 # The argument name and the object member name are the same, but this is not a
1994 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001995 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001996
1997 lines =<< trim END
1998 vim9script
1999 interface somethingWrong
2000 static count = 7
2001 endinterface
2002 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002003 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
Bram Moolenaar554d0312023-01-05 19:59:18 +00002004
2005 lines =<< trim END
2006 vim9script
2007 interface SomethingWrong
2008 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002009 this.count = 7
Bram Moolenaar554d0312023-01-05 19:59:18 +00002010 def GetCount(): number
2011 endinterface
2012 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002013 v9.CheckSourceFailure(lines, 'E1344:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00002014
2015 lines =<< trim END
2016 vim9script
2017 interface SomethingWrong
2018 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002019 this.count: number
Bram Moolenaar554d0312023-01-05 19:59:18 +00002020 def GetCount(): number
2021 return 5
2022 enddef
2023 endinterface
2024 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002025 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002026
2027 lines =<< trim END
2028 vim9script
2029 export interface EnterExit
2030 def Enter(): void
2031 def Exit(): void
2032 endinterface
2033 END
2034 writefile(lines, 'XdefIntf.vim', 'D')
2035
2036 lines =<< trim END
2037 vim9script
2038 import './XdefIntf.vim' as defIntf
2039 export def With(ee: defIntf.EnterExit, F: func)
2040 ee.Enter()
2041 try
2042 F()
2043 finally
2044 ee.Exit()
2045 endtry
2046 enddef
2047 END
2048 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002049
2050 var imported =<< trim END
2051 vim9script
2052 export abstract class EnterExit
2053 def Enter(): void
2054 enddef
2055 def Exit(): void
2056 enddef
2057 endclass
2058 END
2059 writefile(imported, 'XdefIntf2.vim', 'D')
2060
2061 lines[1] = " import './XdefIntf2.vim' as defIntf"
2062 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002063enddef
2064
Bram Moolenaar94674f22023-01-06 18:42:20 +00002065def Test_class_implements_interface()
2066 var lines =<< trim END
2067 vim9script
2068
2069 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002070 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002071 def Method(nr: number)
2072 endinterface
2073
2074 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002075 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002076 def Method(nr: number)
2077 echo nr
2078 enddef
2079 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002080
2081 interface Another
2082 this.member: string
2083 endinterface
2084
Bram Moolenaar83ae6152023-02-25 19:59:31 +00002085 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002086 this.member = 'abc'
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002087 this.count = 20
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002088 def Method(nr: number)
2089 echo nr
2090 enddef
2091 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002092 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002093 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002094
2095 lines =<< trim END
2096 vim9script
2097
2098 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002099 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002100 endinterface
2101
2102 class SomeImpl implements Some implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002103 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002104 endclass
2105 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002106 v9.CheckSourceFailure(lines, 'E1350:')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002107
2108 lines =<< trim END
2109 vim9script
2110
2111 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002112 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002113 endinterface
2114
2115 class SomeImpl implements Some, Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002116 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002117 endclass
2118 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002119 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002120
2121 lines =<< trim END
2122 vim9script
2123
2124 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002125 this.counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002126 def Method(nr: number)
2127 endinterface
2128
2129 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002130 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002131 def Method(nr: number)
2132 echo nr
2133 enddef
2134 endclass
2135 END
RestorerZ7fe8f432023-09-24 23:21:24 +02002136 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented')
Bram Moolenaar94674f22023-01-06 18:42:20 +00002137
2138 lines =<< trim END
2139 vim9script
2140
2141 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002142 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002143 def Methods(nr: number)
2144 endinterface
2145
2146 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002147 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002148 def Method(nr: number)
2149 echo nr
2150 enddef
2151 endclass
2152 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002153 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002154
2155 # Check different order of members in class and interface works.
2156 lines =<< trim END
2157 vim9script
2158
2159 interface Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002160 this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002161 this.errpos: number
2162 endinterface
2163
2164 # order of members is opposite of interface
2165 class Failure implements Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002166 public this.lnum: number = 5
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002167 this.errpos: number = 42
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002168 this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002169 endclass
2170
2171 def Test()
2172 var result: Result = Failure.new()
2173
2174 assert_equal('label', result.label)
2175 assert_equal(42, result.errpos)
2176 enddef
2177
2178 Test()
2179 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002180 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002181
2182 # Interface name after "extends" doesn't end in a space or NUL character
2183 lines =<< trim END
2184 vim9script
2185 interface A
2186 endinterface
2187 class B extends A"
2188 endclass
2189 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002190 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002191
2192 # Trailing characters after a class name
2193 lines =<< trim END
2194 vim9script
2195 class A bbb
2196 endclass
2197 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002198 v9.CheckSourceFailure(lines, 'E488:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002199
2200 # using "implements" with a non-existing class
2201 lines =<< trim END
2202 vim9script
2203 class A implements B
2204 endclass
2205 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002206 v9.CheckSourceFailure(lines, 'E1346:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002207
2208 # using "implements" with a regular class
2209 lines =<< trim END
2210 vim9script
2211 class A
2212 endclass
2213 class B implements A
2214 endclass
2215 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002216 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002217
2218 # using "implements" with a variable
2219 lines =<< trim END
2220 vim9script
2221 var T: number = 10
2222 class A implements T
2223 endclass
2224 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002225 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002226
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002227 # implements should be followed by a white space
2228 lines =<< trim END
2229 vim9script
2230 interface A
2231 endinterface
2232 class B implements A;
2233 endclass
2234 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002235 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002236
LemonBoyc5d27442023-08-19 13:02:35 +02002237 lines =<< trim END
2238 vim9script
2239
2240 interface One
LemonBoyc5d27442023-08-19 13:02:35 +02002241 def IsEven(nr: number): bool
2242 endinterface
2243 class Two implements One
2244 def IsEven(nr: number): string
2245 enddef
2246 endclass
2247 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002248 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02002249
2250 lines =<< trim END
2251 vim9script
2252
2253 interface One
2254 def IsEven(nr: number): bool
2255 endinterface
2256 class Two implements One
2257 def IsEven(nr: bool): bool
2258 enddef
2259 endclass
2260 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002261 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02002262
2263 lines =<< trim END
2264 vim9script
2265
2266 interface One
2267 def IsEven(nr: number): bool
2268 endinterface
2269 class Two implements One
2270 def IsEven(nr: number, ...extra: list<number>): bool
2271 enddef
2272 endclass
2273 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002274 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 +02002275
2276 # access superclass interface members from subclass, mix variable order
2277 lines =<< trim END
2278 vim9script
2279
2280 interface I1
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002281 this.mvar1: number
2282 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002283 endinterface
2284
2285 # NOTE: the order is swapped
2286 class A implements I1
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002287 this.mvar2: number
2288 this.mvar1: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002289 public static svar2: number
2290 public static svar1: number
2291 def new()
2292 svar1 = 11
2293 svar2 = 12
2294 this.mvar1 = 111
2295 this.mvar2 = 112
2296 enddef
2297 endclass
2298
2299 class B extends A
2300 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002301 this.mvar1 = 121
2302 this.mvar2 = 122
2303 enddef
2304 endclass
2305
2306 class C extends B
2307 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002308 this.mvar1 = 131
2309 this.mvar2 = 132
2310 enddef
2311 endclass
2312
Ernie Raelcf138d42023-09-06 20:45:03 +02002313 def F2(i: I1): list<number>
2314 return [ i.mvar1, i.mvar2 ]
2315 enddef
2316
2317 var oa = A.new()
2318 var ob = B.new()
2319 var oc = C.new()
2320
Ernie Raelcf138d42023-09-06 20:45:03 +02002321 assert_equal([111, 112], F2(oa))
2322 assert_equal([121, 122], F2(ob))
2323 assert_equal([131, 132], F2(oc))
2324 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002325 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002326
2327 # Access superclass interface members from subclass, mix variable order.
2328 # Two interfaces, one on A, one on B; each has both kinds of variables
2329 lines =<< trim END
2330 vim9script
2331
2332 interface I1
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002333 this.mvar1: number
2334 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002335 endinterface
2336
2337 interface I2
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002338 this.mvar3: number
2339 this.mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002340 endinterface
2341
2342 class A implements I1
2343 public static svar1: number
2344 public static svar2: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002345 this.mvar1: number
2346 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002347 def new()
2348 svar1 = 11
2349 svar2 = 12
2350 this.mvar1 = 111
2351 this.mvar2 = 112
2352 enddef
2353 endclass
2354
2355 class B extends A implements I2
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002356 static svar3: number
2357 static svar4: number
2358 this.mvar3: number
2359 this.mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002360 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002361 svar3 = 23
2362 svar4 = 24
2363 this.mvar1 = 121
2364 this.mvar2 = 122
2365 this.mvar3 = 123
2366 this.mvar4 = 124
2367 enddef
2368 endclass
2369
2370 class C extends B
2371 public static svar5: number
2372 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002373 svar5 = 1001
2374 this.mvar1 = 131
2375 this.mvar2 = 132
2376 this.mvar3 = 133
2377 this.mvar4 = 134
2378 enddef
2379 endclass
2380
Ernie Raelcf138d42023-09-06 20:45:03 +02002381 def F2(i: I1): list<number>
2382 return [ i.mvar1, i.mvar2 ]
2383 enddef
2384
Ernie Raelcf138d42023-09-06 20:45:03 +02002385 def F4(i: I2): list<number>
2386 return [ i.mvar3, i.mvar4 ]
2387 enddef
2388
Ernie Raelcf138d42023-09-06 20:45:03 +02002389 var oa = A.new()
2390 var ob = B.new()
2391 var oc = C.new()
2392
Ernie Raelcf138d42023-09-06 20:45:03 +02002393 assert_equal([[111, 112]], [F2(oa)])
2394 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2395 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002396 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002397 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002398
2399 # Using two interface names without a space after the ","
2400 lines =<< trim END
2401 vim9script
2402 interface A
2403 endinterface
2404 interface B
2405 endinterface
2406 class C implements A,B
2407 endclass
2408 END
2409 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2410
2411 # No interface name after a comma
2412 lines =<< trim END
2413 vim9script
2414 interface A
2415 endinterface
2416 class B implements A,
2417 endclass
2418 END
2419 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2420
2421 # No interface name after implements
2422 lines =<< trim END
2423 vim9script
2424 class A implements
2425 endclass
2426 END
2427 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002428enddef
2429
Bram Moolenaard0200c82023-01-28 15:19:40 +00002430def Test_call_interface_method()
2431 var lines =<< trim END
2432 vim9script
2433 interface Base
2434 def Enter(): void
2435 endinterface
2436
2437 class Child implements Base
2438 def Enter(): void
2439 g:result ..= 'child'
2440 enddef
2441 endclass
2442
2443 def F(obj: Base)
2444 obj.Enter()
2445 enddef
2446
2447 g:result = ''
2448 F(Child.new())
2449 assert_equal('child', g:result)
2450 unlet g:result
2451 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002452 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002453
2454 lines =<< trim END
2455 vim9script
2456 class Base
2457 def Enter(): void
2458 g:result ..= 'base'
2459 enddef
2460 endclass
2461
2462 class Child extends Base
2463 def Enter(): void
2464 g:result ..= 'child'
2465 enddef
2466 endclass
2467
2468 def F(obj: Base)
2469 obj.Enter()
2470 enddef
2471
2472 g:result = ''
2473 F(Child.new())
2474 assert_equal('child', g:result)
2475 unlet g:result
2476 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002477 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002478
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002479 # method of interface returns a value
2480 lines =<< trim END
2481 vim9script
2482 interface Base
2483 def Enter(): string
2484 endinterface
2485
2486 class Child implements Base
2487 def Enter(): string
2488 g:result ..= 'child'
2489 return "/resource"
2490 enddef
2491 endclass
2492
2493 def F(obj: Base)
2494 var r = obj.Enter()
2495 g:result ..= r
2496 enddef
2497
2498 g:result = ''
2499 F(Child.new())
2500 assert_equal('child/resource', g:result)
2501 unlet g:result
2502 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002503 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002504
2505 lines =<< trim END
2506 vim9script
2507 class Base
2508 def Enter(): string
2509 return null_string
2510 enddef
2511 endclass
2512
2513 class Child extends Base
2514 def Enter(): string
2515 g:result ..= 'child'
2516 return "/resource"
2517 enddef
2518 endclass
2519
2520 def F(obj: Base)
2521 var r = obj.Enter()
2522 g:result ..= r
2523 enddef
2524
2525 g:result = ''
2526 F(Child.new())
2527 assert_equal('child/resource', g:result)
2528 unlet g:result
2529 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002530 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002531
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002532 # No class that implements the interface.
2533 lines =<< trim END
2534 vim9script
2535
2536 interface IWithEE
2537 def Enter(): any
2538 def Exit(): void
2539 endinterface
2540
2541 def With1(ee: IWithEE, F: func)
2542 var r = ee.Enter()
2543 enddef
2544
2545 defcompile
2546 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002547 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002548enddef
2549
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002550def Test_class_used_as_type()
2551 var lines =<< trim END
2552 vim9script
2553
2554 class Point
2555 this.x = 0
2556 this.y = 0
2557 endclass
2558
2559 var p: Point
2560 p = Point.new(2, 33)
2561 assert_equal(2, p.x)
2562 assert_equal(33, p.y)
2563 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002564 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002565
2566 lines =<< trim END
2567 vim9script
2568
2569 interface HasX
2570 this.x: number
2571 endinterface
2572
2573 class Point implements HasX
2574 this.x = 0
2575 this.y = 0
2576 endclass
2577
2578 var p: Point
2579 p = Point.new(2, 33)
2580 var hx = p
2581 assert_equal(2, hx.x)
2582 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002583 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002584
2585 lines =<< trim END
2586 vim9script
2587
2588 class Point
2589 this.x = 0
2590 this.y = 0
2591 endclass
2592
2593 var p: Point
2594 p = 'text'
2595 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002596 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002597enddef
2598
Bram Moolenaar83677162023-01-08 19:54:10 +00002599def Test_class_extends()
2600 var lines =<< trim END
2601 vim9script
2602 class Base
2603 this.one = 1
2604 def GetOne(): number
2605 return this.one
2606 enddef
2607 endclass
2608 class Child extends Base
2609 this.two = 2
2610 def GetTotal(): number
2611 return this.one + this.two
2612 enddef
2613 endclass
2614 var o = Child.new()
2615 assert_equal(1, o.one)
2616 assert_equal(2, o.two)
2617 assert_equal(1, o.GetOne())
2618 assert_equal(3, o.GetTotal())
2619 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002620 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002621
2622 lines =<< trim END
2623 vim9script
2624 class Base
2625 this.one = 1
2626 endclass
2627 class Child extends Base
2628 this.two = 2
2629 endclass
2630 var o = Child.new(3, 44)
2631 assert_equal(3, o.one)
2632 assert_equal(44, o.two)
2633 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002634 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002635
2636 lines =<< trim END
2637 vim9script
2638 class Base
2639 this.one = 1
2640 endclass
2641 class Child extends Base extends Base
2642 this.two = 2
2643 endclass
2644 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002645 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
Bram Moolenaar83677162023-01-08 19:54:10 +00002646
2647 lines =<< trim END
2648 vim9script
2649 class Child extends BaseClass
2650 this.two = 2
2651 endclass
2652 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002653 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
Bram Moolenaar83677162023-01-08 19:54:10 +00002654
2655 lines =<< trim END
2656 vim9script
2657 var SomeVar = 99
2658 class Child extends SomeVar
2659 this.two = 2
2660 endclass
2661 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002662 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002663
2664 lines =<< trim END
2665 vim9script
2666 class Base
2667 this.name: string
2668 def ToString(): string
2669 return this.name
2670 enddef
2671 endclass
2672
2673 class Child extends Base
2674 this.age: number
2675 def ToString(): string
2676 return super.ToString() .. ': ' .. this.age
2677 enddef
2678 endclass
2679
2680 var o = Child.new('John', 42)
2681 assert_equal('John: 42', o.ToString())
2682 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002683 v9.CheckSourceSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002684
2685 lines =<< trim END
2686 vim9script
2687 class Child
2688 this.age: number
2689 def ToString(): number
2690 return this.age
2691 enddef
2692 def ToString(): string
2693 return this.age
2694 enddef
2695 endclass
2696 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002697 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002698
2699 lines =<< trim END
2700 vim9script
2701 class Child
2702 this.age: number
2703 def ToString(): string
2704 return super .ToString() .. ': ' .. this.age
2705 enddef
2706 endclass
2707 var o = Child.new(42)
2708 echo o.ToString()
2709 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002710 v9.CheckSourceFailure(lines, 'E1356:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002711
2712 lines =<< trim END
2713 vim9script
2714 class Base
2715 this.name: string
2716 def ToString(): string
2717 return this.name
2718 enddef
2719 endclass
2720
2721 var age = 42
2722 def ToString(): string
2723 return super.ToString() .. ': ' .. age
2724 enddef
2725 echo ToString()
2726 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002727 v9.CheckSourceFailure(lines, 'E1357:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002728
2729 lines =<< trim END
2730 vim9script
2731 class Child
2732 this.age: number
2733 def ToString(): string
2734 return super.ToString() .. ': ' .. this.age
2735 enddef
2736 endclass
2737 var o = Child.new(42)
2738 echo o.ToString()
2739 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002740 v9.CheckSourceFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002741
2742 lines =<< trim END
2743 vim9script
2744 class Base
2745 this.name: string
2746 static def ToString(): string
2747 return 'Base class'
2748 enddef
2749 endclass
2750
2751 class Child extends Base
2752 this.age: number
2753 def ToString(): string
2754 return Base.ToString() .. ': ' .. this.age
2755 enddef
2756 endclass
2757
2758 var o = Child.new('John', 42)
2759 assert_equal('Base class: 42', o.ToString())
2760 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002761 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002762
2763 lines =<< trim END
2764 vim9script
2765 class Base
2766 this.value = 1
2767 def new(init: number)
2768 this.value = number + 1
2769 enddef
2770 endclass
2771 class Child extends Base
2772 def new()
2773 this.new(3)
2774 enddef
2775 endclass
2776 var c = Child.new()
2777 END
RestorerZ7fe8f432023-09-24 23:21:24 +02002778 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002779
2780 # base class with more than one object member
2781 lines =<< trim END
2782 vim9script
2783
2784 class Result
2785 this.success: bool
2786 this.value: any = null
2787 endclass
2788
2789 class Success extends Result
2790 def new(this.value = v:none)
2791 this.success = true
2792 enddef
2793 endclass
2794
2795 var v = Success.new('asdf')
2796 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2797 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002798 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002799
2800 # class name after "extends" doesn't end in a space or NUL character
2801 lines =<< trim END
2802 vim9script
2803 class A
2804 endclass
2805 class B extends A"
2806 endclass
2807 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002808 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002809enddef
2810
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002811def Test_using_base_class()
2812 var lines =<< trim END
2813 vim9script
2814
2815 class BaseEE
2816 def Enter(): any
2817 return null
2818 enddef
2819 def Exit(resource: any): void
2820 enddef
2821 endclass
2822
2823 class ChildEE extends BaseEE
2824 def Enter(): any
2825 return 42
2826 enddef
2827
2828 def Exit(resource: number): void
2829 g:result ..= '/exit'
2830 enddef
2831 endclass
2832
2833 def With(ee: BaseEE)
2834 var r = ee.Enter()
2835 try
2836 g:result ..= r
2837 finally
2838 g:result ..= '/finally'
2839 ee.Exit(r)
2840 endtry
2841 enddef
2842
2843 g:result = ''
2844 With(ChildEE.new())
2845 assert_equal('42/finally/exit', g:result)
2846 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002847 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002848 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002849
2850 # Using super, Child invokes Base method which has optional arg. #12471
2851 lines =<< trim END
2852 vim9script
2853
2854 class Base
2855 this.success: bool = false
2856 def Method(arg = 0)
2857 this.success = true
2858 enddef
2859 endclass
2860
2861 class Child extends Base
2862 def new()
2863 super.Method()
2864 enddef
2865 endclass
2866
2867 var obj = Child.new()
2868 assert_equal(true, obj.success)
2869 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002870 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002871enddef
2872
Bram Moolenaara86655a2023-01-12 17:06:27 +00002873def Test_class_import()
2874 var lines =<< trim END
2875 vim9script
2876 export class Animal
2877 this.kind: string
2878 this.name: string
2879 endclass
2880 END
2881 writefile(lines, 'Xanimal.vim', 'D')
2882
2883 lines =<< trim END
2884 vim9script
2885 import './Xanimal.vim' as animal
2886
2887 var a: animal.Animal
2888 a = animal.Animal.new('fish', 'Eric')
2889 assert_equal('fish', a.kind)
2890 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002891
2892 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2893 assert_equal('cat', b.kind)
2894 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002895 END
2896 v9.CheckScriptSuccess(lines)
2897enddef
2898
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002899def Test_abstract_class()
2900 var lines =<< trim END
2901 vim9script
2902 abstract class Base
2903 this.name: string
2904 endclass
2905 class Person extends Base
2906 this.age: number
2907 endclass
2908 var p: Base = Person.new('Peter', 42)
2909 assert_equal('Peter', p.name)
2910 assert_equal(42, p.age)
2911 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002912 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002913
2914 lines =<< trim END
2915 vim9script
2916 abstract class Base
2917 this.name: string
2918 endclass
2919 class Person extends Base
2920 this.age: number
2921 endclass
2922 var p = Base.new('Peter')
2923 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002924 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002925
2926 lines =<< trim END
2927 abstract class Base
2928 this.name: string
2929 endclass
2930 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002931 v9.CheckSourceFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002932
2933 # Abstract class cannot have a "new" function
2934 lines =<< trim END
2935 vim9script
2936 abstract class Base
2937 def new()
2938 enddef
2939 endclass
2940 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002941 v9.CheckSourceFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002942enddef
2943
Bram Moolenaar486fc252023-01-18 14:51:07 +00002944def Test_closure_in_class()
2945 var lines =<< trim END
2946 vim9script
2947
2948 class Foo
2949 this.y: list<string> = ['B']
2950
2951 def new()
2952 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2953 enddef
2954 endclass
2955
2956 Foo.new()
2957 assert_equal(['A'], g:result)
2958 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002959 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00002960enddef
2961
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002962def Test_call_constructor_from_legacy()
2963 var lines =<< trim END
2964 vim9script
2965
2966 var newCalled = 'false'
2967
2968 class A
2969 def new()
2970 newCalled = 'true'
2971 enddef
2972 endclass
2973
2974 export def F(options = {}): any
2975 return A
2976 enddef
2977
2978 g:p = F()
2979 legacy call p.new()
2980 assert_equal('true', newCalled)
2981 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002982 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002983enddef
2984
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002985def Test_defer_with_object()
2986 var lines =<< trim END
2987 vim9script
2988
2989 class CWithEE
2990 def Enter()
2991 g:result ..= "entered/"
2992 enddef
2993 def Exit()
2994 g:result ..= "exited"
2995 enddef
2996 endclass
2997
2998 def With(ee: CWithEE, F: func)
2999 ee.Enter()
3000 defer ee.Exit()
3001 F()
3002 enddef
3003
3004 g:result = ''
3005 var obj = CWithEE.new()
3006 obj->With(() => {
3007 g:result ..= "called/"
3008 })
3009 assert_equal('entered/called/exited', g:result)
3010 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003011 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003012 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003013
3014 lines =<< trim END
3015 vim9script
3016
3017 class BaseWithEE
3018 def Enter()
3019 g:result ..= "entered-base/"
3020 enddef
3021 def Exit()
3022 g:result ..= "exited-base"
3023 enddef
3024 endclass
3025
3026 class CWithEE extends BaseWithEE
3027 def Enter()
3028 g:result ..= "entered-child/"
3029 enddef
3030 def Exit()
3031 g:result ..= "exited-child"
3032 enddef
3033 endclass
3034
3035 def With(ee: BaseWithEE, F: func)
3036 ee.Enter()
3037 defer ee.Exit()
3038 F()
3039 enddef
3040
3041 g:result = ''
3042 var obj = CWithEE.new()
3043 obj->With(() => {
3044 g:result ..= "called/"
3045 })
3046 assert_equal('entered-child/called/exited-child', g:result)
3047 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003048 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003049 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003050enddef
3051
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003052" The following test used to crash Vim (Github issue #12676)
3053def Test_extends_method_crashes_vim()
3054 var lines =<< trim END
3055 vim9script
3056
3057 class Observer
3058 endclass
3059
3060 class Property
3061 this.value: any
3062
3063 def Set(v: any)
3064 if v != this.value
3065 this.value = v
3066 endif
3067 enddef
3068
3069 def Register(observer: Observer)
3070 enddef
3071 endclass
3072
3073 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003074 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003075 endclass
3076
3077 def Observe(obj: Property, who: Observer)
3078 obj.Register(who)
3079 enddef
3080
3081 var p = Bool.new(false)
3082 var myObserver = Observer.new()
3083
3084 Observe(p, myObserver)
3085
3086 p.Set(true)
3087 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003088 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003089enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003090
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003091" Test for calling a method in a class that is extended
3092def Test_call_method_in_extended_class()
3093 var lines =<< trim END
3094 vim9script
3095
3096 var prop_init_called = false
3097 var prop_register_called = false
3098
3099 class Property
3100 def Init()
3101 prop_init_called = true
3102 enddef
3103
3104 def Register()
3105 prop_register_called = true
3106 enddef
3107 endclass
3108
3109 class Bool extends Property
3110 endclass
3111
3112 def Observe(obj: Property)
3113 obj.Register()
3114 enddef
3115
3116 var p = Property.new()
3117 Observe(p)
3118
3119 p.Init()
3120 assert_true(prop_init_called)
3121 assert_true(prop_register_called)
3122 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003123 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003124enddef
3125
LemonBoyafe04662023-08-23 21:08:11 +02003126def Test_instanceof()
3127 var lines =<< trim END
3128 vim9script
3129
3130 class Base1
3131 endclass
3132
3133 class Base2 extends Base1
3134 endclass
3135
3136 interface Intf1
3137 endinterface
3138
3139 class Mix1 implements Intf1
3140 endclass
3141
3142 class Base3 extends Mix1
3143 endclass
3144
3145 var b1 = Base1.new()
3146 var b2 = Base2.new()
3147 var b3 = Base3.new()
3148
3149 assert_true(instanceof(b1, Base1))
3150 assert_true(instanceof(b2, Base1))
3151 assert_false(instanceof(b1, Base2))
3152 assert_true(instanceof(b3, Mix1))
3153 assert_false(instanceof(b3, []))
3154 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003155
3156 def Foo()
3157 var a1 = Base1.new()
3158 var a2 = Base2.new()
3159 var a3 = Base3.new()
3160
3161 assert_true(instanceof(a1, Base1))
3162 assert_true(instanceof(a2, Base1))
3163 assert_false(instanceof(a1, Base2))
3164 assert_true(instanceof(a3, Mix1))
3165 assert_false(instanceof(a3, []))
3166 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
3167 enddef
3168 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003169
3170 var o_null: Base1
3171 assert_false(instanceof(o_null, Base1))
3172
LemonBoyafe04662023-08-23 21:08:11 +02003173 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003174 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02003175enddef
3176
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003177" Test for calling a method in the parent class that is extended partially.
3178" This used to fail with the 'E118: Too many arguments for function: Text' error
3179" message (Github issue #12524).
3180def Test_call_method_in_parent_class()
3181 var lines =<< trim END
3182 vim9script
3183
3184 class Widget
3185 this._lnum: number = 1
3186
3187 def SetY(lnum: number)
3188 this._lnum = lnum
3189 enddef
3190
3191 def Text(): string
3192 return ''
3193 enddef
3194 endclass
3195
3196 class Foo extends Widget
3197 def Text(): string
3198 return '<Foo>'
3199 enddef
3200 endclass
3201
3202 def Stack(w1: Widget, w2: Widget): list<Widget>
3203 w1.SetY(1)
3204 w2.SetY(2)
3205 return [w1, w2]
3206 enddef
3207
3208 var foo1 = Foo.new()
3209 var foo2 = Foo.new()
3210 var l = Stack(foo1, foo2)
3211 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003212 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003213enddef
3214
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003215" Test for calling methods from three levels of classes
3216def Test_multi_level_method_call()
3217 var lines =<< trim END
3218 vim9script
3219
3220 var A_func1: number = 0
3221 var A_func2: number = 0
3222 var A_func3: number = 0
3223 var B_func2: number = 0
3224 var B_func3: number = 0
3225 var C_func3: number = 0
3226
3227 class A
3228 def Func1()
3229 A_func1 += 1
3230 enddef
3231
3232 def Func2()
3233 A_func2 += 1
3234 enddef
3235
3236 def Func3()
3237 A_func3 += 1
3238 enddef
3239 endclass
3240
3241 class B extends A
3242 def Func2()
3243 B_func2 += 1
3244 enddef
3245
3246 def Func3()
3247 B_func3 += 1
3248 enddef
3249 endclass
3250
3251 class C extends B
3252 def Func3()
3253 C_func3 += 1
3254 enddef
3255 endclass
3256
3257 def A_CallFuncs(a: A)
3258 a.Func1()
3259 a.Func2()
3260 a.Func3()
3261 enddef
3262
3263 def B_CallFuncs(b: B)
3264 b.Func1()
3265 b.Func2()
3266 b.Func3()
3267 enddef
3268
3269 def C_CallFuncs(c: C)
3270 c.Func1()
3271 c.Func2()
3272 c.Func3()
3273 enddef
3274
3275 var cobj = C.new()
3276 A_CallFuncs(cobj)
3277 B_CallFuncs(cobj)
3278 C_CallFuncs(cobj)
3279 assert_equal(3, A_func1)
3280 assert_equal(0, A_func2)
3281 assert_equal(0, A_func3)
3282 assert_equal(3, B_func2)
3283 assert_equal(0, B_func3)
3284 assert_equal(3, C_func3)
3285 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003286 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003287enddef
3288
3289" Test for using members from three levels of classes
3290def Test_multi_level_member_access()
3291 var lines =<< trim END
3292 vim9script
3293
3294 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003295 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003296 endclass
3297
3298 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003299 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003300 endclass
3301
3302 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003303 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003304 endclass
3305
3306 def A_members(a: A)
3307 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003308 enddef
3309
3310 def B_members(b: B)
3311 b.val1 += 1
3312 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003313 enddef
3314
3315 def C_members(c: C)
3316 c.val1 += 1
3317 c.val2 += 1
3318 c.val3 += 1
3319 enddef
3320
3321 var cobj = C.new()
3322 A_members(cobj)
3323 B_members(cobj)
3324 C_members(cobj)
3325 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003326 assert_equal(2, cobj.val2)
3327 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003328 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003329 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003330enddef
3331
LemonBoy0ffc17a2023-08-20 18:09:11 +02003332" Test expansion of <stack> with class methods.
3333def Test_stack_expansion_with_methods()
3334 var lines =<< trim END
3335 vim9script
3336
3337 class C
3338 def M1()
3339 F0()
3340 enddef
3341 endclass
3342
3343 def F0()
3344 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3345 enddef
3346
3347 def F()
3348 C.new().M1()
3349 enddef
3350
3351 F()
3352 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003353 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003354enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003355
3356" Test the return type of the new() constructor
3357def Test_new_return_type()
3358 # new() uses the default return type and there is no return statement
3359 var lines =<< trim END
3360 vim9script
3361
3362 class C
3363 this._bufnr: number
3364
3365 def new(this._bufnr)
3366 if !bufexists(this._bufnr)
3367 this._bufnr = -1
3368 endif
3369 enddef
3370 endclass
3371
3372 var c = C.new(12345)
3373 assert_equal('object<C>', typename(c))
3374
3375 var v1: C
3376 v1 = C.new(12345)
3377 assert_equal('object<C>', typename(v1))
3378
3379 def F()
3380 var v2: C
3381 v2 = C.new(12345)
3382 assert_equal('object<C>', typename(v2))
3383 enddef
3384 F()
3385 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003386 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003387
3388 # new() uses the default return type and an empty 'return' statement
3389 lines =<< trim END
3390 vim9script
3391
3392 class C
3393 this._bufnr: number
3394
3395 def new(this._bufnr)
3396 if !bufexists(this._bufnr)
3397 this._bufnr = -1
3398 return
3399 endif
3400 enddef
3401 endclass
3402
3403 var c = C.new(12345)
3404 assert_equal('object<C>', typename(c))
3405
3406 var v1: C
3407 v1 = C.new(12345)
3408 assert_equal('object<C>', typename(v1))
3409
3410 def F()
3411 var v2: C
3412 v2 = C.new(12345)
3413 assert_equal('object<C>', typename(v2))
3414 enddef
3415 F()
3416 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003417 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003418
3419 # new() uses "any" return type and returns "this"
3420 lines =<< trim END
3421 vim9script
3422
3423 class C
3424 this._bufnr: number
3425
3426 def new(this._bufnr): any
3427 if !bufexists(this._bufnr)
3428 this._bufnr = -1
3429 return this
3430 endif
3431 enddef
3432 endclass
3433 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003434 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003435
3436 # new() uses 'Dict' return type and returns a Dict
3437 lines =<< trim END
3438 vim9script
3439
3440 class C
3441 this._state: dict<any>
3442
3443 def new(): dict<any>
3444 this._state = {}
3445 return this._state
3446 enddef
3447 endclass
3448
3449 var c = C.new()
3450 assert_equal('object<C>', typename(c))
3451 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003452 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003453enddef
3454
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003455" Test for checking a member initialization type at run time.
3456def Test_runtime_type_check_for_member_init()
3457 var lines =<< trim END
3458 vim9script
3459
3460 var retnum: bool = false
3461
3462 def F(): any
3463 retnum = !retnum
3464 if retnum
3465 return 1
3466 else
3467 return "hello"
3468 endif
3469 enddef
3470
3471 class C
3472 this._foo: bool = F()
3473 endclass
3474
3475 var c1 = C.new()
3476 var c2 = C.new()
3477 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003478 v9.CheckSourceFailure(lines, 'E1012:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003479enddef
3480
3481" Test for locking a variable referring to an object and reassigning to another
3482" object.
3483def Test_object_lockvar()
3484 var lines =<< trim END
3485 vim9script
3486
3487 class C
3488 this.val: number
3489 def new(this.val)
3490 enddef
3491 endclass
3492
3493 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3494 lockvar 2 some_dict
3495
3496 var current: C
3497 current = some_dict['c']
3498 assert_equal(3, current.val)
3499 current = some_dict['b']
3500 assert_equal(2, current.val)
3501
3502 def F()
3503 current = some_dict['c']
3504 enddef
3505
3506 def G()
3507 current = some_dict['b']
3508 enddef
3509
3510 F()
3511 assert_equal(3, current.val)
3512 G()
3513 assert_equal(2, current.val)
3514 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003515 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003516enddef
3517
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003518" Test for a private object method
3519def Test_private_object_method()
3520 # Try calling a private method using an object (at the script level)
3521 var lines =<< trim END
3522 vim9script
3523
3524 class A
3525 def _Foo(): number
3526 return 1234
3527 enddef
3528 endclass
3529 var a = A.new()
3530 a._Foo()
3531 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003532 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003533
3534 # Try calling a private method using an object (from a def function)
3535 lines =<< trim END
3536 vim9script
3537
3538 class A
3539 def _Foo(): number
3540 return 1234
3541 enddef
3542 endclass
3543 def T()
3544 var a = A.new()
3545 a._Foo()
3546 enddef
3547 T()
3548 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003549 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003550
3551 # Use a private method from another object method (in script context)
3552 lines =<< trim END
3553 vim9script
3554
3555 class A
3556 def _Foo(): number
3557 return 1234
3558 enddef
3559 def Bar(): number
3560 return this._Foo()
3561 enddef
3562 endclass
3563 var a = A.new()
3564 assert_equal(1234, a.Bar())
3565 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003566 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003567
3568 # Use a private method from another object method (def function context)
3569 lines =<< trim END
3570 vim9script
3571
3572 class A
3573 def _Foo(): number
3574 return 1234
3575 enddef
3576 def Bar(): number
3577 return this._Foo()
3578 enddef
3579 endclass
3580 def T()
3581 var a = A.new()
3582 assert_equal(1234, a.Bar())
3583 enddef
3584 T()
3585 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003586 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003587
3588 # Try calling a private method without the "this" prefix
3589 lines =<< trim END
3590 vim9script
3591
3592 class A
3593 def _Foo(): number
3594 return 1234
3595 enddef
3596 def Bar(): number
3597 return _Foo()
3598 enddef
3599 endclass
3600 var a = A.new()
3601 a.Bar()
3602 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003603 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003604
3605 # Try calling a private method using the class name
3606 lines =<< trim END
3607 vim9script
3608
3609 class A
3610 def _Foo(): number
3611 return 1234
3612 enddef
3613 endclass
3614 A._Foo()
3615 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003616 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003617
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003618 # Define two private methods with the same name
3619 lines =<< trim END
3620 vim9script
3621
3622 class A
3623 def _Foo()
3624 enddef
3625 def _Foo()
3626 enddef
3627 endclass
3628 var a = A.new()
3629 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003630 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003631
3632 # Define a private method and a object method with the same name
3633 lines =<< trim END
3634 vim9script
3635
3636 class A
3637 def _Foo()
3638 enddef
3639 def Foo()
3640 enddef
3641 endclass
3642 var a = A.new()
3643 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003644 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003645
3646 # Define an object method and a private method with the same name
3647 lines =<< trim END
3648 vim9script
3649
3650 class A
3651 def Foo()
3652 enddef
3653 def _Foo()
3654 enddef
3655 endclass
3656 var a = A.new()
3657 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003658 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003659
3660 # Call a public method and a private method from a private method
3661 lines =<< trim END
3662 vim9script
3663
3664 class A
3665 def Foo(): number
3666 return 100
3667 enddef
3668 def _Bar(): number
3669 return 200
3670 enddef
3671 def _Baz()
3672 assert_equal(100, this.Foo())
3673 assert_equal(200, this._Bar())
3674 enddef
3675 def T()
3676 this._Baz()
3677 enddef
3678 endclass
3679 var a = A.new()
3680 a.T()
3681 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003682 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003683
3684 # Try calling a private method from another class
3685 lines =<< trim END
3686 vim9script
3687
3688 class A
3689 def _Foo(): number
3690 return 100
3691 enddef
3692 endclass
3693 class B
3694 def Foo(): number
3695 var a = A.new()
3696 a._Foo()
3697 enddef
3698 endclass
3699 var b = B.new()
3700 b.Foo()
3701 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003702 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003703
3704 # Call a private object method from a child class object method
3705 lines =<< trim END
3706 vim9script
3707 class A
3708 def _Foo(): number
3709 return 1234
3710 enddef
3711 endclass
3712 class B extends A
3713 def Bar()
3714 enddef
3715 endclass
3716 class C extends B
3717 def Baz(): number
3718 return this._Foo()
3719 enddef
3720 endclass
3721 var c = C.new()
3722 assert_equal(1234, c.Baz())
3723 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003724 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003725
3726 # Call a private object method from a child class object
3727 lines =<< trim END
3728 vim9script
3729 class A
3730 def _Foo(): number
3731 return 1234
3732 enddef
3733 endclass
3734 class B extends A
3735 def Bar()
3736 enddef
3737 endclass
3738 class C extends B
3739 def Baz(): number
3740 enddef
3741 endclass
3742 var c = C.new()
3743 assert_equal(1234, c._Foo())
3744 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003745 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003746
3747 # Using "_" prefix in a method name should fail outside of a class
3748 lines =<< trim END
3749 vim9script
3750 def _Foo(): number
3751 return 1234
3752 enddef
3753 var a = _Foo()
3754 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003755 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003756enddef
3757
3758" Test for an private class method
3759def Test_private_class_method()
3760 # Try calling a class private method (at the script level)
3761 var lines =<< trim END
3762 vim9script
3763
3764 class A
3765 static def _Foo(): number
3766 return 1234
3767 enddef
3768 endclass
3769 A._Foo()
3770 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003771 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003772
3773 # Try calling a class private method (from a def function)
3774 lines =<< trim END
3775 vim9script
3776
3777 class A
3778 static def _Foo(): number
3779 return 1234
3780 enddef
3781 endclass
3782 def T()
3783 A._Foo()
3784 enddef
3785 T()
3786 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003787 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003788
3789 # Try calling a class private method using an object (at the script level)
3790 lines =<< trim END
3791 vim9script
3792
3793 class A
3794 static def _Foo(): number
3795 return 1234
3796 enddef
3797 endclass
3798 var a = A.new()
3799 a._Foo()
3800 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003801 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003802
3803 # Try calling a class private method using an object (from a def function)
3804 lines =<< trim END
3805 vim9script
3806
3807 class A
3808 static def _Foo(): number
3809 return 1234
3810 enddef
3811 endclass
3812 def T()
3813 var a = A.new()
3814 a._Foo()
3815 enddef
3816 T()
3817 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003818 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003819
3820 # Use a class private method from an object method
3821 lines =<< trim END
3822 vim9script
3823
3824 class A
3825 static def _Foo(): number
3826 return 1234
3827 enddef
3828 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003829 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003830 enddef
3831 endclass
3832 var a = A.new()
3833 a.Bar()
3834 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003835 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003836
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003837 # Use a class private method from another class private method without the
3838 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003839 lines =<< trim END
3840 vim9script
3841
3842 class A
3843 static def _Foo1(): number
3844 return 1234
3845 enddef
3846 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003847 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003848 enddef
3849 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003850 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003851 enddef
3852 endclass
3853 var a = A.new()
3854 a.Bar()
3855 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003856 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003857
3858 # Declare a class method and a class private method with the same name
3859 lines =<< trim END
3860 vim9script
3861
3862 class A
3863 static def _Foo()
3864 enddef
3865 static def Foo()
3866 enddef
3867 endclass
3868 var a = A.new()
3869 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003870 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003871
3872 # Try calling a class private method from another class
3873 lines =<< trim END
3874 vim9script
3875
3876 class A
3877 static def _Foo(): number
3878 return 1234
3879 enddef
3880 endclass
3881 class B
3882 def Foo(): number
3883 return A._Foo()
3884 enddef
3885 endclass
3886 var b = B.new()
3887 assert_equal(1234, b.Foo())
3888 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003889 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003890
3891 # Call a private class method from a child class object method
3892 lines =<< trim END
3893 vim9script
3894 class A
3895 static def _Foo(): number
3896 return 1234
3897 enddef
3898 endclass
3899 class B extends A
3900 def Bar()
3901 enddef
3902 endclass
3903 class C extends B
3904 def Baz(): number
3905 return A._Foo()
3906 enddef
3907 endclass
3908 var c = C.new()
3909 assert_equal(1234, c.Baz())
3910 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003911 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003912
3913 # Call a private class method from a child class private class method
3914 lines =<< trim END
3915 vim9script
3916 class A
3917 static def _Foo(): number
3918 return 1234
3919 enddef
3920 endclass
3921 class B extends A
3922 def Bar()
3923 enddef
3924 endclass
3925 class C extends B
3926 static def Baz(): number
3927 return A._Foo()
3928 enddef
3929 endclass
3930 assert_equal(1234, C.Baz())
3931 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003932 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003933
3934 # Call a private class method from a child class object
3935 lines =<< trim END
3936 vim9script
3937 class A
3938 static def _Foo(): number
3939 return 1234
3940 enddef
3941 endclass
3942 class B extends A
3943 def Bar()
3944 enddef
3945 endclass
3946 class C extends B
3947 def Baz(): number
3948 enddef
3949 endclass
3950 var c = C.new()
3951 assert_equal(1234, C._Foo())
3952 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003953 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003954enddef
3955
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003956" Test for using the return value of a class/object method as a function
3957" argument.
3958def Test_objmethod_funcarg()
3959 var lines =<< trim END
3960 vim9script
3961
3962 class C
3963 def Foo(): string
3964 return 'foo'
3965 enddef
3966 endclass
3967
3968 def Bar(a: number, s: string): string
3969 return s
3970 enddef
3971
3972 def Baz(c: C)
3973 assert_equal('foo', Bar(10, c.Foo()))
3974 enddef
3975
3976 var t = C.new()
3977 Baz(t)
3978 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003979 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003980
3981 lines =<< trim END
3982 vim9script
3983
3984 class C
3985 static def Foo(): string
3986 return 'foo'
3987 enddef
3988 endclass
3989
3990 def Bar(a: number, s: string): string
3991 return s
3992 enddef
3993
3994 def Baz()
3995 assert_equal('foo', Bar(10, C.Foo()))
3996 enddef
3997
3998 Baz()
3999 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004000 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004001enddef
4002
Ernie Raelcf138d42023-09-06 20:45:03 +02004003def Test_static_inheritence()
4004 # subclasses get their own static copy
4005 var lines =<< trim END
4006 vim9script
4007
4008 class A
4009 static _svar: number
4010 this._mvar: number
4011 def new()
4012 _svar = 1
4013 this._mvar = 101
4014 enddef
4015 def AccessObject(): number
4016 return this._mvar
4017 enddef
4018 def AccessStaticThroughObject(): number
4019 return _svar
4020 enddef
4021 endclass
4022
4023 class B extends A
4024 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02004025 this._mvar = 102
4026 enddef
4027 endclass
4028
4029 class C extends B
4030 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02004031 this._mvar = 103
4032 enddef
4033
4034 def AccessPrivateStaticThroughClassName(): number
4035 assert_equal(1, A._svar)
Ernie Raelcf138d42023-09-06 20:45:03 +02004036 return 444
4037 enddef
4038 endclass
4039
4040 var oa = A.new()
4041 var ob = B.new()
4042 var oc = C.new()
4043 assert_equal(101, oa.AccessObject())
4044 assert_equal(102, ob.AccessObject())
4045 assert_equal(103, oc.AccessObject())
4046
RestorerZ7fe8f432023-09-24 23:21:24 +02004047 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private variable: _svar')
Ernie Raelcf138d42023-09-06 20:45:03 +02004048
4049 # verify object properly resolves to correct static
4050 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004051 assert_equal(1, ob.AccessStaticThroughObject())
4052 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02004053 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004054 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02004055enddef
4056
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004057" Test for declaring duplicate object and class members
4058def Test_dup_member_variable()
4059 # Duplicate member variable
4060 var lines =<< trim END
4061 vim9script
4062 class C
4063 this.val = 10
4064 this.val = 20
4065 endclass
4066 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004067 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004068
4069 # Duplicate private member variable
4070 lines =<< trim END
4071 vim9script
4072 class C
4073 this._val = 10
4074 this._val = 20
4075 endclass
4076 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004077 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004078
4079 # Duplicate public member variable
4080 lines =<< trim END
4081 vim9script
4082 class C
4083 public this.val = 10
4084 public this.val = 20
4085 endclass
4086 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004087 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004088
4089 # Duplicate private member variable
4090 lines =<< trim END
4091 vim9script
4092 class C
4093 this.val = 10
4094 this._val = 20
4095 endclass
4096 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004097 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004098
4099 # Duplicate public and private member variable
4100 lines =<< trim END
4101 vim9script
4102 class C
4103 this._val = 20
4104 public this.val = 10
4105 endclass
4106 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004107 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004108
4109 # Duplicate class member variable
4110 lines =<< trim END
4111 vim9script
4112 class C
4113 static s: string = "abc"
4114 static _s: string = "def"
4115 endclass
4116 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004117 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004118
4119 # Duplicate public and private class member variable
4120 lines =<< trim END
4121 vim9script
4122 class C
4123 public static s: string = "abc"
4124 static _s: string = "def"
4125 endclass
4126 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004127 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004128
4129 # Duplicate class and object member variable
4130 lines =<< trim END
4131 vim9script
4132 class C
4133 static val = 10
4134 this.val = 20
4135 def new()
4136 enddef
4137 endclass
4138 var c = C.new()
4139 assert_equal(10, C.val)
4140 assert_equal(20, c.val)
4141 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004142 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004143
4144 # Duplicate object member variable in a derived class
4145 lines =<< trim END
4146 vim9script
4147 class A
4148 this.val = 10
4149 endclass
4150 class B extends A
4151 endclass
4152 class C extends B
4153 this.val = 20
4154 endclass
4155 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004156 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004157
4158 # Duplicate object private member variable in a derived class
4159 lines =<< trim END
4160 vim9script
4161 class A
4162 this._val = 10
4163 endclass
4164 class B extends A
4165 endclass
4166 class C extends B
4167 this._val = 20
4168 endclass
4169 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004170 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004171
4172 # Duplicate object private member variable in a derived class
4173 lines =<< trim END
4174 vim9script
4175 class A
4176 this.val = 10
4177 endclass
4178 class B extends A
4179 endclass
4180 class C extends B
4181 this._val = 20
4182 endclass
4183 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004184 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004185
4186 # Duplicate object member variable in a derived class
4187 lines =<< trim END
4188 vim9script
4189 class A
4190 this._val = 10
4191 endclass
4192 class B extends A
4193 endclass
4194 class C extends B
4195 this.val = 20
4196 endclass
4197 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004198 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004199
4200 # Two member variables with a common prefix
4201 lines =<< trim END
4202 vim9script
4203 class A
4204 public static svar2: number
4205 public static svar: number
4206 endclass
4207 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004208 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004209enddef
4210
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004211" Test for accessing a private member outside a class in a def function
4212def Test_private_member_access_outside_class()
4213 # private object member variable
4214 var lines =<< trim END
4215 vim9script
4216 class A
4217 this._val = 10
4218 def GetVal(): number
4219 return this._val
4220 enddef
4221 endclass
4222 def T()
4223 var a = A.new()
4224 a._val = 20
4225 enddef
4226 T()
4227 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004228 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _val')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004229
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004230 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004231 lines =<< trim END
4232 vim9script
4233 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004234 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004235 endclass
4236 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004237 var a = A.new()
4238 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004239 enddef
4240 T()
4241 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004242 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "A": _a')
Ernie Rael18143d32023-09-04 22:30:41 +02004243
4244 # private static member variable
4245 lines =<< trim END
4246 vim9script
4247 class A
4248 static _val = 10
4249 endclass
4250 def T()
4251 var a = A.new()
4252 var x = a._val
4253 enddef
4254 T()
4255 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004256 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004257
4258 # private static member variable
4259 lines =<< trim END
4260 vim9script
4261 class A
4262 static _val = 10
4263 endclass
4264 def T()
4265 var a = A.new()
4266 a._val = 3
4267 enddef
4268 T()
4269 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004270 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004271
4272 # private static class variable
4273 lines =<< trim END
4274 vim9script
4275 class A
4276 static _val = 10
4277 endclass
4278 def T()
4279 var x = A._val
4280 enddef
4281 T()
4282 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004283 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004284
4285 # private static class variable
4286 lines =<< trim END
4287 vim9script
4288 class A
4289 static _val = 10
4290 endclass
4291 def T()
4292 A._val = 3
4293 enddef
4294 T()
4295 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004296 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004297enddef
4298
4299" Test for changing the member access of an interface in a implementation class
4300def Test_change_interface_member_access()
4301 var lines =<< trim END
4302 vim9script
4303 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02004304 this.val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004305 endinterface
4306 class B implements A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02004307 public this.val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004308 endclass
4309 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004310 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004311
4312 lines =<< trim END
4313 vim9script
4314 interface A
4315 this.val: number
4316 endinterface
4317 class B implements A
4318 public this.val = 10
4319 endclass
4320 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004321 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004322enddef
4323
4324" Test for trying to change a readonly member from a def function
4325def Test_readonly_member_change_in_def_func()
4326 var lines =<< trim END
4327 vim9script
4328 class A
4329 this.val: number
4330 endclass
4331 def T()
4332 var a = A.new()
4333 a.val = 20
4334 enddef
4335 T()
4336 END
Ernie Rael696270b2023-09-21 16:42:28 +02004337 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004338enddef
4339
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004340" Test for reading and writing a class member from a def function
4341def Test_modify_class_member_from_def_function()
4342 var lines =<< trim END
4343 vim9script
4344 class A
4345 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004346 public static var2: list<number> = [1, 2]
4347 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004348 static _priv_var4: number = 40
4349 endclass
4350 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004351 assert_equal([1, 2], A.var2)
4352 assert_equal({a: 1, b: 2}, A.var3)
4353 A.var2 = [3, 4]
4354 A.var3 = {c: 3, d: 4}
4355 assert_equal([3, 4], A.var2)
4356 assert_equal({c: 3, d: 4}, A.var3)
RestorerZ7fe8f432023-09-24 23:21:24 +02004357 assert_fails('echo A._priv_var4', 'E1333: Cannot access private variable: _priv_var4')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004358 enddef
4359 T()
4360 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004361 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004362enddef
4363
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004364" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004365def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004366 var lines =<< trim END
4367 vim9script
4368 class A
4369 public static svar1: list<number> = [1]
4370 public static svar2: list<number> = [2]
4371 endclass
4372
4373 A.svar1->add(3)
4374 A.svar2->add(4)
4375 assert_equal([1, 3], A.svar1)
4376 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004377
4378 def Foo()
4379 A.svar1->add(7)
4380 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004381 assert_equal([1, 3, 7], A.svar1)
4382 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004383 enddef
4384 Foo()
4385 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004386 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004387
4388 # Cannot read from a class variable using an object in script context
4389 lines =<< trim END
4390 vim9script
4391 class A
4392 public this.var1: number
4393 public static svar2: list<number> = [1]
4394 endclass
4395
4396 var a = A.new()
4397 echo a.svar2
4398 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004399 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004400
4401 # Cannot write to a class variable using an object in script context
4402 lines =<< trim END
4403 vim9script
4404 class A
4405 public this.var1: number
4406 public static svar2: list<number> = [1]
4407 endclass
4408
4409 var a = A.new()
4410 a.svar2 = [2]
4411 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004412 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004413
4414 # Cannot read from a class variable using an object in def method context
4415 lines =<< trim END
4416 vim9script
4417 class A
4418 public this.var1: number
4419 public static svar2: list<number> = [1]
4420 endclass
4421
4422 def T()
4423 var a = A.new()
4424 echo a.svar2
4425 enddef
4426 T()
4427 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004428 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004429
4430 # Cannot write to a class variable using an object in def method context
4431 lines =<< trim END
4432 vim9script
4433 class A
4434 public this.var1: number
4435 public static svar2: list<number> = [1]
4436 endclass
4437
4438 def T()
4439 var a = A.new()
4440 a.svar2 = [2]
4441 enddef
4442 T()
4443 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004444 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004445enddef
4446
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004447" Test for using a interface method using a child object
4448def Test_interface_method_from_child()
4449 var lines =<< trim END
4450 vim9script
4451
4452 interface A
4453 def Foo(): string
4454 endinterface
4455
4456 class B implements A
4457 def Foo(): string
4458 return 'foo'
4459 enddef
4460 endclass
4461
4462 class C extends B
4463 def Bar(): string
4464 return 'bar'
4465 enddef
4466 endclass
4467
4468 def T1(a: A)
4469 assert_equal('foo', a.Foo())
4470 enddef
4471
4472 def T2(b: B)
4473 assert_equal('foo', b.Foo())
4474 enddef
4475
4476 var c = C.new()
4477 T1(c)
4478 T2(c)
4479 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004480 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004481enddef
4482
4483" Test for using an interface method using a child object when it is overridden
4484" by the child class.
4485" FIXME: This test fails.
4486" def Test_interface_overridden_method_from_child()
4487" var lines =<< trim END
4488" vim9script
4489"
4490" interface A
4491" def Foo(): string
4492" endinterface
4493"
4494" class B implements A
4495" def Foo(): string
4496" return 'b-foo'
4497" enddef
4498" endclass
4499"
4500" class C extends B
4501" def Bar(): string
4502" return 'bar'
4503" enddef
4504" def Foo(): string
4505" return 'c-foo'
4506" enddef
4507" endclass
4508"
4509" def T1(a: A)
4510" assert_equal('c-foo', a.Foo())
4511" enddef
4512"
4513" def T2(b: B)
4514" assert_equal('c-foo', b.Foo())
4515" enddef
4516"
4517" var c = C.new()
4518" T1(c)
4519" T2(c)
4520" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004521" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004522" enddef
4523
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004524" Test for abstract methods
4525def Test_abstract_method()
4526 # Use two abstract methods
4527 var lines =<< trim END
4528 vim9script
4529 abstract class A
4530 def M1(): number
4531 return 10
4532 enddef
4533 abstract def M2(): number
4534 abstract def M3(): number
4535 endclass
4536 class B extends A
4537 def M2(): number
4538 return 20
4539 enddef
4540 def M3(): number
4541 return 30
4542 enddef
4543 endclass
4544 var b = B.new()
4545 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4546 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004547 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004548
4549 # Don't define an abstract method
4550 lines =<< trim END
4551 vim9script
4552 abstract class A
4553 abstract def Foo()
4554 endclass
4555 class B extends A
4556 endclass
4557 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004558 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004559
4560 # Use abstract method in a concrete class
4561 lines =<< trim END
4562 vim9script
4563 class A
4564 abstract def Foo()
4565 endclass
4566 class B extends A
4567 endclass
4568 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004569 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004570
4571 # Use abstract method in an interface
4572 lines =<< trim END
4573 vim9script
4574 interface A
4575 abstract def Foo()
4576 endinterface
4577 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004578 def Foo()
4579 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004580 endclass
4581 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004582 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004583
4584 # Abbreviate the "abstract" keyword
4585 lines =<< trim END
4586 vim9script
4587 class A
4588 abs def Foo()
4589 endclass
4590 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004591 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004592
4593 # Use "abstract" with a member variable
4594 lines =<< trim END
4595 vim9script
4596 abstract class A
4597 abstract this.val = 10
4598 endclass
4599 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004600 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004601
4602 # Use a static abstract method
4603 lines =<< trim END
4604 vim9script
4605 abstract class A
4606 abstract static def Foo(): number
4607 endclass
4608 class B extends A
4609 static def Foo(): number
4610 return 4
4611 enddef
4612 endclass
4613 assert_equal(4, B.Foo())
4614 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004615 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004616
4617 # Type mismatch between abstract method and concrete method
4618 lines =<< trim END
4619 vim9script
4620 abstract class A
4621 abstract def Foo(a: string, b: number): list<number>
4622 endclass
4623 class B extends A
4624 def Foo(a: number, b: string): list<string>
4625 return []
4626 enddef
4627 endclass
4628 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004629 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 +02004630
4631 # Use an abstract class to invoke an abstract method
4632 # FIXME: This should fail
4633 lines =<< trim END
4634 vim9script
4635 abstract class A
4636 abstract static def Foo()
4637 endclass
4638 A.Foo()
4639 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004640 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004641
4642 # Invoke an abstract method from a def function
4643 lines =<< trim END
4644 vim9script
4645 abstract class A
4646 abstract def Foo(): list<number>
4647 endclass
4648 class B extends A
4649 def Foo(): list<number>
4650 return [3, 5]
4651 enddef
4652 endclass
4653 def Bar(c: B)
4654 assert_equal([3, 5], c.Foo())
4655 enddef
4656 var b = B.new()
4657 Bar(b)
4658 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004659 v9.CheckSourceSuccess(lines)
4660enddef
4661
4662" Test for calling a class method from a subclass
4663def Test_class_method_call_from_subclass()
4664 # class method call from a subclass
4665 var lines =<< trim END
4666 vim9script
4667
4668 class A
4669 static def Foo()
4670 echo "foo"
4671 enddef
4672 endclass
4673
4674 class B extends A
4675 def Bar()
4676 Foo()
4677 enddef
4678 endclass
4679
4680 var b = B.new()
4681 b.Bar()
4682 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004683 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004684enddef
4685
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004686" Test for calling a class method using an object in a def function context and
4687" script context.
4688def Test_class_method_call_using_object()
4689 # script context
4690 var lines =<< trim END
4691 vim9script
4692 class A
4693 static def Foo(): list<string>
4694 return ['a', 'b']
4695 enddef
4696 def Bar()
4697 assert_equal(['a', 'b'], A.Foo())
4698 assert_equal(['a', 'b'], Foo())
4699 enddef
4700 endclass
4701
4702 def T()
4703 assert_equal(['a', 'b'], A.Foo())
4704 var t_a = A.new()
4705 t_a.Bar()
4706 enddef
4707
4708 assert_equal(['a', 'b'], A.Foo())
4709 var a = A.new()
4710 a.Bar()
4711 T()
4712 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004713 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004714
4715 # script context
4716 lines =<< trim END
4717 vim9script
4718 class A
4719 static def Foo(): string
4720 return 'foo'
4721 enddef
4722 endclass
4723
4724 var a = A.new()
4725 assert_equal('foo', a.Foo())
4726 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004727 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"')
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004728
4729 # def function context
4730 lines =<< trim END
4731 vim9script
4732 class A
4733 static def Foo(): string
4734 return 'foo'
4735 enddef
4736 endclass
4737
4738 def T()
4739 var a = A.new()
4740 assert_equal('foo', a.Foo())
4741 enddef
4742 T()
4743 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004744 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004745enddef
4746
4747def Test_class_variable()
4748 var lines =<< trim END
4749 vim9script
4750
4751 class A
4752 public static val: number = 10
4753 static def ClassFunc()
4754 assert_equal(10, val)
4755 enddef
4756 def ObjFunc()
4757 assert_equal(10, val)
4758 enddef
4759 endclass
4760
4761 class B extends A
4762 endclass
4763
4764 assert_equal(10, A.val)
4765 A.ClassFunc()
4766 var a = A.new()
4767 a.ObjFunc()
4768 var b = B.new()
4769 b.ObjFunc()
4770
4771 def T1(a1: A)
4772 a1.ObjFunc()
4773 A.ClassFunc()
4774 enddef
4775 T1(b)
4776
4777 A.val = 20
4778 assert_equal(20, A.val)
4779 END
4780 v9.CheckSourceSuccess(lines)
4781
4782 # Modifying a parent class variable from a child class method
4783 lines =<< trim END
4784 vim9script
4785
4786 class A
4787 static val: number = 10
4788 endclass
4789
4790 class B extends A
4791 static def ClassFunc()
4792 val = 20
4793 enddef
4794 endclass
4795 B.ClassFunc()
4796 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004797 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004798
4799 # Reading a parent class variable from a child class method
4800 lines =<< trim END
4801 vim9script
4802
4803 class A
4804 static val: number = 10
4805 endclass
4806
4807 class B extends A
4808 static def ClassFunc()
4809 var i = val
4810 enddef
4811 endclass
4812 B.ClassFunc()
4813 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004814 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004815
4816 # Modifying a parent class variable from a child object method
4817 lines =<< trim END
4818 vim9script
4819
4820 class A
4821 static val: number = 10
4822 endclass
4823
4824 class B extends A
4825 def ObjFunc()
4826 val = 20
4827 enddef
4828 endclass
4829 var b = B.new()
4830 b.ObjFunc()
4831 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004832 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004833
4834 # Reading a parent class variable from a child object method
4835 lines =<< trim END
4836 vim9script
4837
4838 class A
4839 static val: number = 10
4840 endclass
4841
4842 class B extends A
4843 def ObjFunc()
4844 var i = val
4845 enddef
4846 endclass
4847 var b = B.new()
4848 b.ObjFunc()
4849 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004850 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004851
4852 # Modifying a class variable using an object at script level
4853 lines =<< trim END
4854 vim9script
4855
4856 class A
4857 static val: number = 10
4858 endclass
4859 var a = A.new()
4860 a.val = 20
4861 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004862 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004863
4864 # Reading a class variable using an object at script level
4865 lines =<< trim END
4866 vim9script
4867
4868 class A
4869 static val: number = 10
4870 endclass
4871 var a = A.new()
4872 var i = a.val
4873 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004874 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004875
4876 # Modifying a class variable using an object at function level
4877 lines =<< trim END
4878 vim9script
4879
4880 class A
4881 static val: number = 10
4882 endclass
4883
4884 def T()
4885 var a = A.new()
4886 a.val = 20
4887 enddef
4888 T()
4889 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004890 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004891
4892 # Reading a class variable using an object at function level
4893 lines =<< trim END
4894 vim9script
4895
4896 class A
4897 static val: number = 10
4898 endclass
4899 def T()
4900 var a = A.new()
4901 var i = a.val
4902 enddef
4903 T()
4904 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004905 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004906enddef
4907
4908" Test for using a duplicate class method and class variable in a child class
4909def Test_dup_class_member()
4910 # duplicate class variable, class method and overridden object method
4911 var lines =<< trim END
4912 vim9script
4913 class A
4914 static sval = 100
4915 static def Check()
4916 assert_equal(100, sval)
4917 enddef
4918 def GetVal(): number
4919 return sval
4920 enddef
4921 endclass
4922
4923 class B extends A
4924 static sval = 200
4925 static def Check()
4926 assert_equal(200, sval)
4927 enddef
4928 def GetVal(): number
4929 return sval
4930 enddef
4931 endclass
4932
4933 def T1(aa: A): number
4934 return aa.GetVal()
4935 enddef
4936
4937 def T2(bb: B): number
4938 return bb.GetVal()
4939 enddef
4940
4941 assert_equal(100, A.sval)
4942 assert_equal(200, B.sval)
4943 var a = A.new()
4944 assert_equal(100, a.GetVal())
4945 var b = B.new()
4946 assert_equal(200, b.GetVal())
4947 assert_equal(200, T1(b))
4948 assert_equal(200, T2(b))
4949 END
4950 v9.CheckSourceSuccess(lines)
4951
4952 # duplicate class variable and class method
4953 lines =<< trim END
4954 vim9script
4955 class A
4956 static sval = 100
4957 static def Check()
4958 assert_equal(100, sval)
4959 enddef
4960 def GetVal(): number
4961 return sval
4962 enddef
4963 endclass
4964
4965 class B extends A
4966 static sval = 200
4967 static def Check()
4968 assert_equal(200, sval)
4969 enddef
4970 endclass
4971
4972 def T1(aa: A): number
4973 return aa.GetVal()
4974 enddef
4975
4976 def T2(bb: B): number
4977 return bb.GetVal()
4978 enddef
4979
4980 assert_equal(100, A.sval)
4981 assert_equal(200, B.sval)
4982 var a = A.new()
4983 assert_equal(100, a.GetVal())
4984 var b = B.new()
4985 assert_equal(100, b.GetVal())
4986 assert_equal(100, T1(b))
4987 assert_equal(100, T2(b))
4988 END
4989 v9.CheckSourceSuccess(lines)
4990enddef
4991
4992" Test for calling an instance method using the class
4993def Test_instance_method_call_using_class()
4994 # Invoke an object method using a class in script context
4995 var lines =<< trim END
4996 vim9script
4997 class A
4998 def Foo()
4999 echo "foo"
5000 enddef
5001 endclass
5002 A.Foo()
5003 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005004 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005005
5006 # Invoke an object method using a class in def function context
5007 lines =<< trim END
5008 vim9script
5009 class A
5010 def Foo()
5011 echo "foo"
5012 enddef
5013 endclass
5014 def T()
5015 A.Foo()
5016 enddef
5017 T()
5018 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005019 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005020enddef
5021
5022" Test for duplicate class method and instance method
5023def Test_dup_classmethod_objmethod()
5024 # Duplicate instance method
5025 var lines =<< trim END
5026 vim9script
5027 class A
5028 static def Foo()
5029 enddef
5030 def Foo()
5031 enddef
5032 endclass
5033 END
5034 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
5035
5036 # Duplicate private instance method
5037 lines =<< trim END
5038 vim9script
5039 class A
5040 static def Foo()
5041 enddef
5042 def _Foo()
5043 enddef
5044 endclass
5045 END
5046 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5047
5048 # Duplicate class method
5049 lines =<< trim END
5050 vim9script
5051 class A
5052 def Foo()
5053 enddef
5054 static def Foo()
5055 enddef
5056 endclass
5057 END
5058 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
5059
5060 # Duplicate private class method
5061 lines =<< trim END
5062 vim9script
5063 class A
5064 def Foo()
5065 enddef
5066 static def _Foo()
5067 enddef
5068 endclass
5069 END
5070 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5071
5072 # Duplicate private class and object method
5073 lines =<< trim END
5074 vim9script
5075 class A
5076 def _Foo()
5077 enddef
5078 static def _Foo()
5079 enddef
5080 endclass
5081 END
5082 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5083enddef
5084
5085" Test for an instance method access level comparison with parent instance
5086" methods.
5087def Test_instance_method_access_level()
5088 # Private method in subclass
5089 var lines =<< trim END
5090 vim9script
5091 class A
5092 def Foo()
5093 enddef
5094 endclass
5095 class B extends A
5096 endclass
5097 class C extends B
5098 def _Foo()
5099 enddef
5100 endclass
5101 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005102 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005103
5104 # Public method in subclass
5105 lines =<< trim END
5106 vim9script
5107 class A
5108 def _Foo()
5109 enddef
5110 endclass
5111 class B extends A
5112 endclass
5113 class C extends B
5114 def Foo()
5115 enddef
5116 endclass
5117 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005118 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005119enddef
5120
5121def Test_extend_empty_class()
5122 var lines =<< trim END
5123 vim9script
5124 class A
5125 endclass
5126 class B extends A
5127 endclass
5128 class C extends B
5129 public static rw_class_var = 1
5130 public this.rw_obj_var = 2
5131 static def ClassMethod(): number
5132 return 3
5133 enddef
5134 def ObjMethod(): number
5135 return 4
5136 enddef
5137 endclass
5138 assert_equal(1, C.rw_class_var)
5139 assert_equal(3, C.ClassMethod())
5140 var c = C.new()
5141 assert_equal(2, c.rw_obj_var)
5142 assert_equal(4, c.ObjMethod())
5143 END
5144 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005145enddef
5146
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005147" A interface cannot have a static variable or a static method or a private
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005148" variable or a private method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005149def Test_interface_with_unsupported_members()
5150 var lines =<< trim END
5151 vim9script
5152 interface A
5153 static num: number
5154 endinterface
5155 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005156 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005157
5158 lines =<< trim END
5159 vim9script
5160 interface A
5161 static _num: number
5162 endinterface
5163 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005164 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005165
5166 lines =<< trim END
5167 vim9script
5168 interface A
5169 public static num: number
5170 endinterface
5171 END
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005172 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005173
5174 lines =<< trim END
5175 vim9script
5176 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005177 public static num: number
5178 endinterface
5179 END
5180 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface')
5181
5182 lines =<< trim END
5183 vim9script
5184 interface A
5185 static _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005186 endinterface
5187 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005188 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005189
5190 lines =<< trim END
5191 vim9script
5192 interface A
5193 static def Foo(d: dict<any>): list<string>
5194 endinterface
5195 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005196 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005197
5198 lines =<< trim END
5199 vim9script
5200 interface A
5201 static def _Foo(d: dict<any>): list<string>
5202 endinterface
5203 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005204 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005205
5206 lines =<< trim END
5207 vim9script
5208 interface A
5209 this._Foo: list<string>
5210 endinterface
5211 END
5212 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface')
5213
5214 lines =<< trim END
5215 vim9script
5216 interface A
5217 def _Foo(d: dict<any>): list<string>
5218 endinterface
5219 END
5220 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface')
5221enddef
5222
5223" Test for extending an interface
5224def Test_extend_interface()
5225 var lines =<< trim END
5226 vim9script
5227 interface A
5228 this.var1: list<string>
5229 def Foo()
5230 endinterface
5231 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005232 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005233 def Bar()
5234 endinterface
5235 class C implements A, B
5236 this.var1 = [1, 2]
5237 def Foo()
5238 enddef
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005239 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005240 def Bar()
5241 enddef
5242 endclass
5243 END
5244 v9.CheckSourceSuccess(lines)
5245
5246 lines =<< trim END
5247 vim9script
5248 interface A
5249 def Foo()
5250 endinterface
5251 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005252 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005253 endinterface
5254 class C implements A, B
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005255 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005256 endclass
5257 END
5258 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented')
5259
5260 lines =<< trim END
5261 vim9script
5262 interface A
5263 def Foo()
5264 endinterface
5265 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005266 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005267 endinterface
5268 class C implements A, B
5269 def Foo()
5270 enddef
5271 endclass
5272 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005273 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005274
5275 # interface cannot extend a class
5276 lines =<< trim END
5277 vim9script
5278 class A
5279 endclass
5280 interface B extends A
5281 endinterface
5282 END
5283 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5284
5285 # class cannot extend an interface
5286 lines =<< trim END
5287 vim9script
5288 interface A
5289 endinterface
5290 class B extends A
5291 endclass
5292 END
5293 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5294
5295 # interface cannot implement another interface
5296 lines =<< trim END
5297 vim9script
5298 interface A
5299 endinterface
5300 interface B implements A
5301 endinterface
5302 END
5303 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"')
5304
5305 # interface cannot extend multiple interfaces
5306 lines =<< trim END
5307 vim9script
5308 interface A
5309 endinterface
5310 interface B
5311 endinterface
5312 interface C extends A, B
5313 endinterface
5314 END
5315 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B')
5316
5317 # Variable type in an extended interface is of different type
5318 lines =<< trim END
5319 vim9script
5320 interface A
5321 this.val1: number
5322 endinterface
5323 interface B extends A
5324 this.val2: string
5325 endinterface
5326 interface C extends B
5327 this.val1: string
5328 this.val2: number
5329 endinterface
5330 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005331 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005332enddef
5333
5334" Test for a child class implementing an interface when some of the methods are
5335" defined in the parent class.
5336def Test_child_class_implements_interface()
5337 var lines =<< trim END
5338 vim9script
5339
5340 interface Intf
5341 def F1(): list<list<number>>
5342 def F2(): list<list<number>>
5343 def F3(): list<list<number>>
5344 this.var1: list<dict<number>>
5345 this.var2: list<dict<number>>
5346 this.var3: list<dict<number>>
5347 endinterface
5348
5349 class A
5350 def A1()
5351 enddef
5352 def F3(): list<list<number>>
5353 return [[3]]
5354 enddef
5355 this.v1: list<list<number>> = [[0]]
5356 this.var3 = [{c: 30}]
5357 endclass
5358
5359 class B extends A
5360 def B1()
5361 enddef
5362 def F2(): list<list<number>>
5363 return [[2]]
5364 enddef
5365 this.v2: list<list<number>> = [[0]]
5366 this.var2 = [{b: 20}]
5367 endclass
5368
5369 class C extends B implements Intf
5370 def C1()
5371 enddef
5372 def F1(): list<list<number>>
5373 return [[1]]
5374 enddef
5375 this.v3: list<list<number>> = [[0]]
5376 this.var1 = [{a: 10}]
5377 endclass
5378
5379 def T(if: Intf)
5380 assert_equal([[1]], if.F1())
5381 assert_equal([[2]], if.F2())
5382 assert_equal([[3]], if.F3())
5383 assert_equal([{a: 10}], if.var1)
5384 assert_equal([{b: 20}], if.var2)
5385 assert_equal([{c: 30}], if.var3)
5386 enddef
5387
5388 var c = C.new()
5389 T(c)
5390 assert_equal([[1]], c.F1())
5391 assert_equal([[2]], c.F2())
5392 assert_equal([[3]], c.F3())
5393 assert_equal([{a: 10}], c.var1)
5394 assert_equal([{b: 20}], c.var2)
5395 assert_equal([{c: 30}], c.var3)
5396 END
5397 v9.CheckSourceSuccess(lines)
5398
5399 # One of the interface methods is not found
5400 lines =<< trim END
5401 vim9script
5402
5403 interface Intf
5404 def F1()
5405 def F2()
5406 def F3()
5407 endinterface
5408
5409 class A
5410 def A1()
5411 enddef
5412 endclass
5413
5414 class B extends A
5415 def B1()
5416 enddef
5417 def F2()
5418 enddef
5419 endclass
5420
5421 class C extends B implements Intf
5422 def C1()
5423 enddef
5424 def F1()
5425 enddef
5426 endclass
5427 END
5428 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented')
5429
5430 # One of the interface methods is of different type
5431 lines =<< trim END
5432 vim9script
5433
5434 interface Intf
5435 def F1()
5436 def F2()
5437 def F3()
5438 endinterface
5439
5440 class A
5441 def F3(): number
5442 return 0
5443 enddef
5444 def A1()
5445 enddef
5446 endclass
5447
5448 class B extends A
5449 def B1()
5450 enddef
5451 def F2()
5452 enddef
5453 endclass
5454
5455 class C extends B implements Intf
5456 def C1()
5457 enddef
5458 def F1()
5459 enddef
5460 endclass
5461 END
5462 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number')
5463
5464 # One of the interface variables is not present
5465 lines =<< trim END
5466 vim9script
5467
5468 interface Intf
5469 this.var1: list<dict<number>>
5470 this.var2: list<dict<number>>
5471 this.var3: list<dict<number>>
5472 endinterface
5473
5474 class A
5475 this.v1: list<list<number>> = [[0]]
5476 endclass
5477
5478 class B extends A
5479 this.v2: list<list<number>> = [[0]]
5480 this.var2 = [{b: 20}]
5481 endclass
5482
5483 class C extends B implements Intf
5484 this.v3: list<list<number>> = [[0]]
5485 this.var1 = [{a: 10}]
5486 endclass
5487 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005488 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005489
5490 # One of the interface variables is of different type
5491 lines =<< trim END
5492 vim9script
5493
5494 interface Intf
5495 this.var1: list<dict<number>>
5496 this.var2: list<dict<number>>
5497 this.var3: list<dict<number>>
5498 endinterface
5499
5500 class A
5501 this.v1: list<list<number>> = [[0]]
5502 this.var3: list<dict<string>>
5503 endclass
5504
5505 class B extends A
5506 this.v2: list<list<number>> = [[0]]
5507 this.var2 = [{b: 20}]
5508 endclass
5509
5510 class C extends B implements Intf
5511 this.v3: list<list<number>> = [[0]]
5512 this.var1 = [{a: 10}]
5513 endclass
5514 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005515 v9.CheckSourceFailure(lines, 'E1382: Variable "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005516enddef
5517
5518" Test for extending an interface with duplicate variables and methods
5519def Test_interface_extends_with_dup_members()
5520 var lines =<< trim END
5521 vim9script
5522 interface A
5523 this.n1: number
5524 def Foo1(): number
5525 endinterface
5526 interface B extends A
5527 this.n2: number
5528 this.n1: number
5529 def Foo2(): number
5530 def Foo1(): number
5531 endinterface
5532 class C implements B
5533 this.n1 = 10
5534 this.n2 = 20
5535 def Foo1(): number
5536 return 30
5537 enddef
5538 def Foo2(): number
5539 return 40
5540 enddef
5541 endclass
5542 def T1(a: A)
5543 assert_equal(10, a.n1)
5544 assert_equal(30, a.Foo1())
5545 enddef
5546 def T2(b: B)
5547 assert_equal(10, b.n1)
5548 assert_equal(20, b.n2)
5549 assert_equal(30, b.Foo1())
5550 assert_equal(40, b.Foo2())
5551 enddef
5552 var c = C.new()
5553 T1(c)
5554 T2(c)
5555 END
5556 v9.CheckSourceSuccess(lines)
5557enddef
5558
5559" Test for using "any" type for a variable in a sub-class while it has a
5560" concrete type in the interface
5561def Test_implements_using_var_type_any()
5562 var lines =<< trim END
5563 vim9script
5564 interface A
5565 this.val: list<dict<string>>
5566 endinterface
5567 class B implements A
5568 this.val = [{a: '1'}, {b: '2'}]
5569 endclass
5570 var b = B.new()
5571 assert_equal([{a: '1'}, {b: '2'}], b.val)
5572 END
5573 v9.CheckSourceSuccess(lines)
5574
5575 # initialize instance variable using a different type
5576 lines =<< trim END
5577 vim9script
5578 interface A
5579 this.val: list<dict<string>>
5580 endinterface
5581 class B implements A
5582 this.val = {a: 1, b: 2}
5583 endclass
5584 var b = B.new()
5585 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005586 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005587enddef
5588
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005589" Test for assigning to a member variable in a nested class
5590def Test_nested_object_assignment()
5591 var lines =<< trim END
5592 vim9script
5593
5594 class A
5595 this.value: number
5596 endclass
5597
5598 class B
5599 this.a: A = A.new()
5600 endclass
5601
5602 class C
5603 this.b: B = B.new()
5604 endclass
5605
5606 class D
5607 this.c: C = C.new()
5608 endclass
5609
5610 def T(da: D)
5611 da.c.b.a.value = 10
5612 enddef
5613
5614 var d = D.new()
5615 T(d)
5616 END
Ernie Rael696270b2023-09-21 16:42:28 +02005617 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005618enddef
5619
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02005620" Test for calling methods using a null object
5621def Test_null_object_method_call()
5622 # Calling a object method using a null object in script context
5623 var lines =<< trim END
5624 vim9script
5625
5626 class C
5627 def Foo()
5628 assert_report('This method should not be executed')
5629 enddef
5630 endclass
5631
5632 var o: C
5633 o.Foo()
5634 END
5635 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
5636
5637 # Calling a object method using a null object in def function context
5638 lines =<< trim END
5639 vim9script
5640
5641 class C
5642 def Foo()
5643 assert_report('This method should not be executed')
5644 enddef
5645 endclass
5646
5647 def T()
5648 var o: C
5649 o.Foo()
5650 enddef
5651 T()
5652 END
5653 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5654
5655 # Calling a object method through another class method using a null object in
5656 # script context
5657 lines =<< trim END
5658 vim9script
5659
5660 class C
5661 def Foo()
5662 assert_report('This method should not be executed')
5663 enddef
5664
5665 static def Bar(o_any: any)
5666 var o_typed: C = o_any
5667 o_typed.Foo()
5668 enddef
5669 endclass
5670
5671 var o: C
5672 C.Bar(o)
5673 END
5674 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5675
5676 # Calling a object method through another class method using a null object in
5677 # def function context
5678 lines =<< trim END
5679 vim9script
5680
5681 class C
5682 def Foo()
5683 assert_report('This method should not be executed')
5684 enddef
5685
5686 static def Bar(o_any: any)
5687 var o_typed: C = o_any
5688 o_typed.Foo()
5689 enddef
5690 endclass
5691
5692 def T()
5693 var o: C
5694 C.Bar(o)
5695 enddef
5696 T()
5697 END
5698 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5699enddef
5700
5701" Test for using a dict as an object member
5702def Test_dict_object_member()
5703 var lines =<< trim END
5704 vim9script
5705
5706 class Context
5707 public this.state: dict<number> = {}
5708 def GetState(): dict<number>
5709 return this.state
5710 enddef
5711 endclass
5712
5713 var ctx = Context.new()
5714 ctx.state->extend({a: 1})
5715 ctx.state['b'] = 2
5716 assert_equal({a: 1, b: 2}, ctx.GetState())
5717
5718 def F()
5719 ctx.state['c'] = 3
5720 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
5721 enddef
5722 F()
5723 assert_equal(3, ctx.state.c)
5724 ctx.state.c = 4
5725 assert_equal(4, ctx.state.c)
5726 END
5727 v9.CheckSourceSuccess(lines)
5728enddef
5729
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02005730" The following test was failing after 9.0.1914. This was caused by using a
5731" freed object from a previous method call.
5732def Test_freed_object_from_previous_method_call()
5733 var lines =<< trim END
5734 vim9script
5735
5736 class Context
5737 endclass
5738
5739 class Result
5740 endclass
5741
5742 def Failure(): Result
5743 return Result.new()
5744 enddef
5745
5746 def GetResult(ctx: Context): Result
5747 return Failure()
5748 enddef
5749
5750 def Test_GetResult()
5751 var ctx = Context.new()
5752 var result = GetResult(ctx)
5753 enddef
5754
5755 Test_GetResult()
5756 END
5757 v9.CheckSourceSuccess(lines)
5758enddef
5759
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005760" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker