blob: c272aab396e2d33bfa33570788a9ca216595af0d [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
h-eastdb385522023-09-28 22:18:19 +0200959 vim9script
960
961 class C
962 this.str: string
963 def MethodA(this.str)
964 enddef
965 endclass
966 END
967 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.str" except with the "new" method')
968
969 lines =<< trim END
h-eastb895b0f2023-09-24 15:46:31 +0200970 vim9script
971
972 class C
973 this.str: string
974 def new(str: any)
975 enddef
976 endclass
977
978 def Check()
979 try
980 var c = C.new(1)
981 catch
982 assert_report($'Unexpected exception was caught: {v:exception}')
983 endtry
984 enddef
985
986 Check()
987 END
988 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900989enddef
990
Bram Moolenaar74e12742022-12-13 21:14:28 +0000991def Test_class_object_member_inits()
992 var lines =<< trim END
993 vim9script
994 class TextPosition
995 this.lnum: number
996 this.col = 1
997 this.addcol: number = 2
998 endclass
999
1000 var pos = TextPosition.new()
1001 assert_equal(0, pos.lnum)
1002 assert_equal(1, pos.col)
1003 assert_equal(2, pos.addcol)
1004 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001005 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001006
1007 lines =<< trim END
1008 vim9script
1009 class TextPosition
1010 this.lnum
1011 this.col = 1
1012 endclass
1013 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001014 v9.CheckSourceFailure(lines, 'E1022:')
Bram Moolenaar74e12742022-12-13 21:14:28 +00001015
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001016 # If the type is not specified for a member, then it should be set during
1017 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +00001018 lines =<< trim END
1019 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001020
1021 var init_count = 0
1022 def Init(): string
1023 init_count += 1
1024 return 'foo'
1025 enddef
1026
1027 class A
1028 this.str1 = Init()
1029 this.str2: string = Init()
Bram Moolenaar74e12742022-12-13 21:14:28 +00001030 this.col = 1
1031 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001032
1033 assert_equal(init_count, 0)
1034 var a = A.new()
1035 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001036 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001037 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001038
1039 # Test for initializing an object member with an unknown variable/type
1040 lines =<< trim END
1041 vim9script
1042 class A
1043 this.value = init_val
1044 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001045 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001046 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001047 v9.CheckSourceFailure(lines, 'E1001:')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001048
1049 # Test for initializing an object member with an special type
1050 lines =<< trim END
1051 vim9script
1052 class A
1053 this.value: void
1054 endclass
1055 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001056 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void')
Bram Moolenaar74e12742022-12-13 21:14:28 +00001057enddef
1058
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001059" Test for instance variable access
1060def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001061 var lines =<< trim END
1062 vim9script
1063 class Triple
1064 this._one = 1
1065 this.two = 2
1066 public this.three = 3
1067
1068 def GetOne(): number
1069 return this._one
1070 enddef
1071 endclass
1072
1073 var trip = Triple.new()
1074 assert_equal(1, trip.GetOne())
1075 assert_equal(2, trip.two)
1076 assert_equal(3, trip.three)
1077 assert_fails('echo trip._one', 'E1333')
1078
1079 assert_fails('trip._one = 11', 'E1333')
1080 assert_fails('trip.two = 22', 'E1335')
1081 trip.three = 33
1082 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001083
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001084 assert_fails('trip.four = 4', 'E1326')
Bram Moolenaard505d172022-12-18 21:42:55 +00001085 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001086 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001087
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001088 # Test for a public member variable name beginning with an underscore
1089 lines =<< trim END
1090 vim9script
1091 class A
1092 public this._val = 10
1093 endclass
1094 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001095 v9.CheckSourceFailure(lines, 'E1332:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001096
Bram Moolenaar590162c2022-12-24 21:24:06 +00001097 lines =<< trim END
1098 vim9script
1099
1100 class MyCar
1101 this.make: string
Bram Moolenaar574950d2023-01-03 19:08:50 +00001102 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001103
1104 def new(make_arg: string)
1105 this.make = make_arg
1106 enddef
1107
1108 def GetMake(): string
1109 return $"make = {this.make}"
1110 enddef
Bram Moolenaar574950d2023-01-03 19:08:50 +00001111 def GetAge(): number
1112 return this.age
1113 enddef
Bram Moolenaar590162c2022-12-24 21:24:06 +00001114 endclass
1115
1116 var c = MyCar.new("abc")
1117 assert_equal('make = abc', c.GetMake())
1118
1119 c = MyCar.new("def")
1120 assert_equal('make = def', c.GetMake())
1121
1122 var c2 = MyCar.new("123")
1123 assert_equal('make = 123', c2.GetMake())
Bram Moolenaar574950d2023-01-03 19:08:50 +00001124
1125 def CheckCar()
1126 assert_equal("make = def", c.GetMake())
1127 assert_equal(5, c.GetAge())
1128 enddef
1129 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001130 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001131 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001132
1133 lines =<< trim END
1134 vim9script
1135
1136 class MyCar
1137 this.make: string
1138
1139 def new(make_arg: string)
1140 this.make = make_arg
1141 enddef
1142 endclass
1143
1144 var c = MyCar.new("abc")
1145 var c = MyCar.new("def")
1146 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001147 v9.CheckSourceFailure(lines, 'E1041:')
Bram Moolenaarb149d222023-01-24 13:03:37 +00001148
1149 lines =<< trim END
1150 vim9script
1151
1152 class Foo
1153 this.x: list<number> = []
1154
1155 def Add(n: number): any
1156 this.x->add(n)
1157 return this
1158 enddef
1159 endclass
1160
1161 echo Foo.new().Add(1).Add(2).x
1162 echo Foo.new().Add(1).Add(2)
1163 .x
1164 echo Foo.new().Add(1)
1165 .Add(2).x
1166 echo Foo.new()
1167 .Add(1).Add(2).x
1168 echo Foo.new()
1169 .Add(1)
1170 .Add(2)
1171 .x
1172 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001173 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001174
1175 # Test for "public" cannot be abbreviated
1176 lines =<< trim END
1177 vim9script
1178 class Something
1179 pub this.val = 1
1180 endclass
1181 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001182 v9.CheckSourceFailure(lines, 'E1065:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001183
1184 # Test for "public" keyword must be followed by "this" or "static".
1185 lines =<< trim END
1186 vim9script
1187 class Something
1188 public val = 1
1189 endclass
1190 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001191 v9.CheckSourceFailure(lines, 'E1331:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001192
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001193 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001194 lines =<< trim END
1195 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001196 class A
1197 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001198 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001199 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001200 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001201 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001202
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001203 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001204 lines =<< trim END
1205 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001206 class A
1207 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001208 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001209 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001210 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001211 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001212
1213 # Modify a instance variable using the class name in a def function
1214 lines =<< trim END
1215 vim9script
1216 class A
1217 public this.val = 1
1218 endclass
1219 def T()
1220 A.val = 1
1221 enddef
1222 T()
1223 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001224 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001225
1226 # Read a instance variable using the class name in a def function
1227 lines =<< trim END
1228 vim9script
1229 class A
1230 public this.val = 1
1231 endclass
1232 def T()
1233 var i = A.val
1234 enddef
1235 T()
1236 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001237 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object')
Ernie Raelcf138d42023-09-06 20:45:03 +02001238
1239 # Access from child class extending a class:
1240 lines =<< trim END
1241 vim9script
1242 class A
1243 this.ro_obj_var = 10
1244 public this.rw_obj_var = 20
1245 this._priv_obj_var = 30
Ernie Raelcf138d42023-09-06 20:45:03 +02001246 endclass
1247
1248 class B extends A
1249 def Foo()
1250 var x: number
1251 x = this.ro_obj_var
1252 this.ro_obj_var = 0
1253 x = this.rw_obj_var
1254 this.rw_obj_var = 0
1255 x = this._priv_obj_var
1256 this._priv_obj_var = 0
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001257 enddef
1258 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001259
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001260 var b = B.new()
1261 b.Foo()
1262 END
1263 v9.CheckSourceSuccess(lines)
1264enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001265
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001266" Test for class variable access
1267def Test_class_variable_access()
1268 # Test for "static" cannot be abbreviated
1269 var lines =<< trim END
1270 vim9script
1271 class Something
1272 stat this.val = 1
1273 endclass
1274 END
1275 v9.CheckSourceFailure(lines, 'E1065:')
1276
1277 # Test for "static" cannot be followed by "this".
1278 lines =<< trim END
1279 vim9script
1280 class Something
1281 static this.val = 1
1282 endclass
1283 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001284 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a variable name')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001285
1286 # Test for "static" cannot be followed by "public".
1287 lines =<< trim END
1288 vim9script
1289 class Something
1290 static public val = 1
1291 endclass
1292 END
1293 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
1294
1295 # A readonly class variable cannot be modified from a child class
1296 lines =<< trim END
1297 vim9script
1298 class A
1299 static ro_class_var = 40
1300 endclass
1301
1302 class B extends A
1303 def Foo()
1304 A.ro_class_var = 50
1305 enddef
1306 endclass
1307
1308 var b = B.new()
1309 b.Foo()
1310 END
Ernie Rael696270b2023-09-21 16:42:28 +02001311 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001312
1313 # A private class variable cannot be accessed from a child class
1314 lines =<< trim END
1315 vim9script
1316 class A
1317 static _priv_class_var = 60
1318 endclass
1319
1320 class B extends A
1321 def Foo()
1322 var i = A._priv_class_var
1323 enddef
1324 endclass
1325
1326 var b = B.new()
1327 b.Foo()
1328 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001329 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _priv_class_var')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001330
1331 # A private class variable cannot be modified from a child class
1332 lines =<< trim END
1333 vim9script
1334 class A
1335 static _priv_class_var = 60
1336 endclass
1337
1338 class B extends A
1339 def Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001340 A._priv_class_var = 0
1341 enddef
1342 endclass
1343
1344 var b = B.new()
1345 b.Foo()
1346 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001347 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _priv_class_var')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001348
1349 # Access from child class extending a class and from script context
1350 lines =<< trim END
1351 vim9script
1352 class A
1353 static ro_class_var = 10
1354 public static rw_class_var = 20
1355 static _priv_class_var = 30
1356 endclass
1357
1358 class B extends A
1359 def Foo()
1360 var x: number
1361 x = A.ro_class_var
1362 assert_equal(10, x)
1363 x = A.rw_class_var
1364 assert_equal(25, x)
1365 A.rw_class_var = 20
1366 assert_equal(20, A.rw_class_var)
1367 enddef
1368 endclass
1369
1370 assert_equal(10, A.ro_class_var)
1371 assert_equal(20, A.rw_class_var)
1372 A.rw_class_var = 25
1373 assert_equal(25, A.rw_class_var)
1374 var b = B.new()
1375 b.Foo()
1376 END
1377 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001378enddef
1379
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001380def Test_class_object_compare()
1381 var class_lines =<< trim END
1382 vim9script
1383 class Item
1384 this.nr = 0
1385 this.name = 'xx'
1386 endclass
1387 END
1388
1389 # used at the script level and in a compiled function
1390 var test_lines =<< trim END
1391 var i1 = Item.new()
1392 assert_equal(i1, i1)
1393 assert_true(i1 is i1)
1394 var i2 = Item.new()
1395 assert_equal(i1, i2)
1396 assert_false(i1 is i2)
1397 var i3 = Item.new(0, 'xx')
1398 assert_equal(i1, i3)
1399
1400 var io1 = Item.new(1, 'xx')
1401 assert_notequal(i1, io1)
1402 var io2 = Item.new(0, 'yy')
1403 assert_notequal(i1, io2)
1404 END
1405
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001406 v9.CheckSourceSuccess(class_lines + test_lines)
1407 v9.CheckSourceSuccess(
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001408 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001409
1410 for op in ['>', '>=', '<', '<=', '=~', '!~']
1411 var op_lines = [
1412 'var i1 = Item.new()',
1413 'var i2 = Item.new()',
1414 'echo i1 ' .. op .. ' i2',
1415 ]
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001416 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
1417 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001418 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001419 endfor
1420enddef
1421
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001422def Test_object_type()
1423 var lines =<< trim END
1424 vim9script
1425
1426 class One
1427 this.one = 1
1428 endclass
1429 class Two
1430 this.two = 2
1431 endclass
1432 class TwoMore extends Two
1433 this.more = 9
1434 endclass
1435
1436 var o: One = One.new()
1437 var t: Two = Two.new()
1438 var m: TwoMore = TwoMore.new()
1439 var tm: Two = TwoMore.new()
1440
1441 t = m
1442 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001443 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001444
1445 lines =<< trim END
1446 vim9script
1447
1448 class One
1449 this.one = 1
1450 endclass
1451 class Two
1452 this.two = 2
1453 endclass
1454
1455 var o: One = Two.new()
1456 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001457 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001458
1459 lines =<< trim END
1460 vim9script
1461
1462 interface One
1463 def GetMember(): number
1464 endinterface
1465 class Two implements One
1466 this.one = 1
1467 def GetMember(): number
1468 return this.one
1469 enddef
1470 endclass
1471
1472 var o: One = Two.new(5)
1473 assert_equal(5, o.GetMember())
1474 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001475 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001476
1477 lines =<< trim END
1478 vim9script
1479
1480 class Num
1481 this.n: number = 0
1482 endclass
1483
1484 def Ref(name: string): func(Num): Num
1485 return (arg: Num): Num => {
1486 return eval(name)(arg)
1487 }
1488 enddef
1489
1490 const Fn = Ref('Double')
1491 var Double = (m: Num): Num => Num.new(m.n * 2)
1492
1493 echo Fn(Num.new(4))
1494 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001495 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001496enddef
1497
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001498def Test_class_member()
1499 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001500 var lines =<< trim END
1501 vim9script
1502 class TextPos
1503 this.lnum = 1
1504 this.col = 1
1505 static counter = 0
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001506 static _secret = 7
1507 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001508
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001509 static def AddToCounter(nr: number)
Bram Moolenaard505d172022-12-18 21:42:55 +00001510 counter += nr
1511 enddef
1512 endclass
1513
1514 assert_equal(0, TextPos.counter)
1515 TextPos.AddToCounter(3)
1516 assert_equal(3, TextPos.counter)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001517 assert_fails('echo TextPos.noSuchMember', 'E1337:')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001518
Bram Moolenaar3259ff32023-01-04 18:54:09 +00001519 def GetCounter(): number
1520 return TextPos.counter
1521 enddef
1522 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001523
Bram Moolenaarf54cedd2022-12-23 17:56:27 +00001524 assert_fails('TextPos.noSuchMember = 2', 'E1337:')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001525 assert_fails('TextPos.counter = 5', 'E1335:')
1526 assert_fails('TextPos.counter += 5', 'E1335:')
1527
1528 assert_fails('echo TextPos._secret', 'E1333:')
1529 assert_fails('TextPos._secret = 8', 'E1333:')
1530
1531 assert_equal(42, TextPos.anybody)
1532 TextPos.anybody = 12
1533 assert_equal(12, TextPos.anybody)
1534 TextPos.anybody += 5
1535 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001536 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001537 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001538
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001539 # example in the help
1540 lines =<< trim END
1541 vim9script
1542 class OtherThing
1543 this.size: number
1544 static totalSize: number
1545
1546 def new(this.size)
1547 totalSize += this.size
1548 enddef
1549 endclass
1550 assert_equal(0, OtherThing.totalSize)
1551 var to3 = OtherThing.new(3)
1552 assert_equal(3, OtherThing.totalSize)
1553 var to7 = OtherThing.new(7)
1554 assert_equal(10, OtherThing.totalSize)
1555 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001556 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001557
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001558 # using static class member twice
1559 lines =<< trim END
1560 vim9script
1561
1562 class HTML
1563 static author: string = 'John Doe'
1564
1565 static def MacroSubstitute(s: string): string
1566 return substitute(s, '{{author}}', author, 'gi')
1567 enddef
1568 endclass
1569
1570 assert_equal('some text', HTML.MacroSubstitute('some text'))
1571 assert_equal('some text', HTML.MacroSubstitute('some text'))
1572 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001573 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001574
Bram Moolenaar62a69232023-01-24 15:07:04 +00001575 # access private member in lambda
1576 lines =<< trim END
1577 vim9script
1578
1579 class Foo
1580 this._x: number = 0
1581
1582 def Add(n: number): number
1583 const F = (): number => this._x + n
1584 return F()
1585 enddef
1586 endclass
1587
1588 var foo = Foo.new()
1589 assert_equal(5, foo.Add(5))
1590 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001591 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001592
h-east2bd6a092023-05-19 19:01:17 +01001593 # access private member in lambda body
1594 lines =<< trim END
1595 vim9script
1596
1597 class Foo
1598 this._x: number = 6
1599
1600 def Add(n: number): number
1601 var Lam = () => {
1602 this._x = this._x + n
1603 }
1604 Lam()
1605 return this._x
1606 enddef
1607 endclass
1608
1609 var foo = Foo.new()
1610 assert_equal(13, foo.Add(7))
1611 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001612 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001613
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001614 # check shadowing
1615 lines =<< trim END
1616 vim9script
1617
1618 class Some
1619 static count = 0
1620 def Method(count: number)
1621 echo count
1622 enddef
1623 endclass
1624
1625 var s = Some.new()
1626 s.Method(7)
1627 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001628 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001629
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001630 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001631 lines =<< trim END
1632 vim9script
1633
1634 class Some
1635 static count = 0
1636 def Method(arg: number)
1637 var count = 3
1638 echo arg count
1639 enddef
1640 endclass
1641
1642 var s = Some.new()
1643 s.Method(7)
1644 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001645 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001646
1647 # Test for using an invalid type for a member variable
1648 lines =<< trim END
1649 vim9script
1650 class A
1651 this.val: xxx
1652 endclass
1653 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001654 v9.CheckSourceFailure(lines, 'E1010:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001655
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001656 # Test for setting a member on a null object
1657 lines =<< trim END
1658 vim9script
1659 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001660 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001661 endclass
1662
1663 def F()
1664 var obj: A
1665 obj.val = ""
1666 enddef
1667 F()
1668 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001669 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001670
1671 # Test for accessing a member on a null object
1672 lines =<< trim END
1673 vim9script
1674 class A
1675 this.val: string
1676 endclass
1677
1678 def F()
1679 var obj: A
1680 echo obj.val
1681 enddef
1682 F()
1683 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001684 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001685
1686 # Test for setting a member on a null object, at script level
1687 lines =<< trim END
1688 vim9script
1689 class A
Gianmaria Bajo6ad4a602023-08-31 20:55:35 +02001690 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001691 endclass
1692
1693 var obj: A
1694 obj.val = ""
1695 END
1696 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001697 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001698
1699 # Test for accessing a member on a null object, at script level
1700 lines =<< trim END
1701 vim9script
1702 class A
1703 this.val: string
1704 endclass
1705
1706 var obj: A
1707 echo obj.val
1708 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001709 v9.CheckSourceFailure(lines, 'E1360: Using a null object')
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001710
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001711 # Test for no space before or after the '=' when initializing a member
1712 # variable
1713 lines =<< trim END
1714 vim9script
1715 class A
1716 this.val: number= 10
1717 endclass
1718 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001719 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001720 lines =<< trim END
1721 vim9script
1722 class A
1723 this.val: number =10
1724 endclass
1725 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001726 v9.CheckSourceFailure(lines, 'E1004:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001727
1728 # Access a non-existing member
1729 lines =<< trim END
1730 vim9script
1731 class A
1732 endclass
1733 var a = A.new()
1734 var v = a.bar
1735 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001736 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "A": bar')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001737enddef
1738
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001739func Test_class_garbagecollect()
1740 let lines =<< trim END
1741 vim9script
1742
1743 class Point
1744 this.p = [2, 3]
1745 static pl = ['a', 'b']
1746 static pd = {a: 'a', b: 'b'}
1747 endclass
1748
1749 echo Point.pl Point.pd
1750 call test_garbagecollect_now()
1751 echo Point.pl Point.pd
1752 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001753 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001754
1755 let lines =<< trim END
1756 vim9script
1757
1758 interface View
1759 endinterface
1760
1761 class Widget
1762 this.view: View
1763 endclass
1764
1765 class MyView implements View
1766 this.widget: Widget
1767
1768 def new()
1769 # this will result in a circular reference to this object
1770 this.widget = Widget.new(this)
1771 enddef
1772 endclass
1773
1774 var view = MyView.new()
1775
1776 # overwrite "view", will be garbage-collected next
1777 view = MyView.new()
1778 test_garbagecollect_now()
1779 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001780 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001781endfunc
1782
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001783" Test interface garbage collection
1784func Test_interface_garbagecollect()
1785 let lines =<< trim END
1786 vim9script
1787
1788 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001789 this.ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001790
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001791 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001792 endinterface
1793
1794 class A implements I
1795 static ro_class_var: number = 10
1796 public static rw_class_var: number = 20
1797 static _priv_class_var: number = 30
1798 this.ro_obj_var: number = 40
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001799 this._priv_obj_var: number = 60
1800
1801 static def _ClassBar(): number
1802 return _priv_class_var
1803 enddef
1804
1805 static def ClassFoo(): number
1806 return ro_class_var + rw_class_var + A._ClassBar()
1807 enddef
1808
1809 def _ObjBar(): number
1810 return this._priv_obj_var
1811 enddef
1812
1813 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001814 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001815 enddef
1816 endclass
1817
1818 assert_equal(60, A.ClassFoo())
1819 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001820 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001821 test_garbagecollect_now()
1822 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001823 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001824 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001825 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001826endfunc
1827
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001828def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001829 var lines =<< trim END
1830 vim9script
1831 class Value
1832 this.value = 0
1833 static objects = 0
1834
1835 def new(v: number)
1836 this.value = v
1837 ++objects
1838 enddef
1839
1840 static def GetCount(): number
1841 return objects
1842 enddef
1843 endclass
1844
1845 assert_equal(0, Value.GetCount())
1846 var v1 = Value.new(2)
1847 assert_equal(1, Value.GetCount())
1848 var v2 = Value.new(7)
1849 assert_equal(2, Value.GetCount())
1850 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001851 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001852
1853 # Test for cleaning up after a class definition failure when using class
1854 # functions.
1855 lines =<< trim END
1856 vim9script
1857 class A
1858 static def Foo()
1859 enddef
1860 aaa
1861 endclass
1862 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001863 v9.CheckSourceFailure(lines, 'E1318:')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001864
1865 # Test for calling a class method from another class method without the class
1866 # name prefix.
1867 lines =<< trim END
1868 vim9script
1869 class A
1870 static myList: list<number> = [1]
1871 static def Foo(n: number)
1872 myList->add(n)
1873 enddef
1874 static def Bar()
1875 Foo(2)
1876 enddef
1877 def Baz()
1878 Foo(3)
1879 enddef
1880 endclass
1881 A.Bar()
1882 var a = A.new()
1883 a.Baz()
1884 assert_equal([1, 2, 3], A.myList)
1885 END
1886 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001887enddef
1888
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001889def Test_class_defcompile()
1890 var lines =<< trim END
1891 vim9script
1892
1893 class C
1894 def Fo(i: number): string
1895 return i
1896 enddef
1897 endclass
1898
1899 defcompile C.Fo
1900 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001901 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001902
1903 lines =<< trim END
1904 vim9script
1905
1906 class C
1907 static def Fc(): number
1908 return 'x'
1909 enddef
1910 endclass
1911
1912 defcompile C.Fc
1913 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001914 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001915
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001916 lines =<< trim END
1917 vim9script
1918
1919 class C
1920 static def new()
1921 enddef
1922 endclass
1923
1924 defcompile C.new
1925 END
RestorerZ7fe8f432023-09-24 23:21:24 +02001926 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static')
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02001927
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001928 # Trying to compile a function using a non-existing class variable
1929 lines =<< trim END
1930 vim9script
1931 defcompile x.Foo()
1932 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001933 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001934
1935 # Trying to compile a function using a variable which is not a class
1936 lines =<< trim END
1937 vim9script
1938 var x: number
1939 defcompile x.Foo()
1940 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001941 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001942
1943 # Trying to compile a function without specifying the name
1944 lines =<< trim END
1945 vim9script
1946 class A
1947 endclass
1948 defcompile A.
1949 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001950 v9.CheckSourceFailure(lines, 'E475:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001951
1952 # Trying to compile a non-existing class object member function
1953 lines =<< trim END
1954 vim9script
1955 class A
1956 endclass
1957 var a = A.new()
1958 defcompile a.Foo()
1959 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001960 v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00001961enddef
1962
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001963def Test_class_object_to_string()
1964 var lines =<< trim END
1965 vim9script
1966 class TextPosition
1967 this.lnum = 1
1968 this.col = 22
1969 endclass
1970
1971 assert_equal("class TextPosition", string(TextPosition))
1972
1973 var pos = TextPosition.new()
1974 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
1975 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001976 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00001977enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00001978
Bram Moolenaar554d0312023-01-05 19:59:18 +00001979def Test_interface_basics()
1980 var lines =<< trim END
1981 vim9script
1982 interface Something
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001983 this.ro_var: list<number>
Bram Moolenaar554d0312023-01-05 19:59:18 +00001984 def GetCount(): number
1985 endinterface
1986 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001987 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00001988
1989 lines =<< trim END
1990 interface SomethingWrong
1991 static count = 7
1992 endinterface
1993 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001994 v9.CheckSourceFailure(lines, 'E1342:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00001995
1996 lines =<< trim END
1997 vim9script
1998
1999 interface Some
Bram Moolenaard40f00c2023-01-13 17:36:49 +00002000 this.value: number
2001 def Method(value: number)
2002 endinterface
2003 END
h-east61378a12023-04-18 19:07:29 +01002004 # The argument name and the object member name are the same, but this is not a
2005 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002006 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002007
2008 lines =<< trim END
2009 vim9script
2010 interface somethingWrong
2011 static count = 7
2012 endinterface
2013 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002014 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
Bram Moolenaar554d0312023-01-05 19:59:18 +00002015
2016 lines =<< trim END
2017 vim9script
2018 interface SomethingWrong
2019 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002020 this.count = 7
Bram Moolenaar554d0312023-01-05 19:59:18 +00002021 def GetCount(): number
2022 endinterface
2023 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002024 v9.CheckSourceFailure(lines, 'E1344:')
Bram Moolenaar554d0312023-01-05 19:59:18 +00002025
2026 lines =<< trim END
2027 vim9script
2028 interface SomethingWrong
2029 this.value: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002030 this.count: number
Bram Moolenaar554d0312023-01-05 19:59:18 +00002031 def GetCount(): number
2032 return 5
2033 enddef
2034 endinterface
2035 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002036 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002037
2038 lines =<< trim END
2039 vim9script
2040 export interface EnterExit
2041 def Enter(): void
2042 def Exit(): void
2043 endinterface
2044 END
2045 writefile(lines, 'XdefIntf.vim', 'D')
2046
2047 lines =<< trim END
2048 vim9script
2049 import './XdefIntf.vim' as defIntf
2050 export def With(ee: defIntf.EnterExit, F: func)
2051 ee.Enter()
2052 try
2053 F()
2054 finally
2055 ee.Exit()
2056 endtry
2057 enddef
2058 END
2059 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002060
2061 var imported =<< trim END
2062 vim9script
2063 export abstract class EnterExit
2064 def Enter(): void
2065 enddef
2066 def Exit(): void
2067 enddef
2068 endclass
2069 END
2070 writefile(imported, 'XdefIntf2.vim', 'D')
2071
2072 lines[1] = " import './XdefIntf2.vim' as defIntf"
2073 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002074enddef
2075
Bram Moolenaar94674f22023-01-06 18:42:20 +00002076def Test_class_implements_interface()
2077 var lines =<< trim END
2078 vim9script
2079
2080 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002081 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002082 def Method(nr: number)
2083 endinterface
2084
2085 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002086 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002087 def Method(nr: number)
2088 echo nr
2089 enddef
2090 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002091
2092 interface Another
2093 this.member: string
2094 endinterface
2095
Bram Moolenaar83ae6152023-02-25 19:59:31 +00002096 class AnotherImpl implements Some, Another
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002097 this.member = 'abc'
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002098 this.count = 20
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002099 def Method(nr: number)
2100 echo nr
2101 enddef
2102 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002103 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002104 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002105
2106 lines =<< trim END
2107 vim9script
2108
2109 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002110 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002111 endinterface
2112
2113 class SomeImpl implements Some implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002114 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002115 endclass
2116 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002117 v9.CheckSourceFailure(lines, 'E1350:')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002118
2119 lines =<< trim END
2120 vim9script
2121
2122 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002123 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002124 endinterface
2125
2126 class SomeImpl implements Some, Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002127 this.count: number
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002128 endclass
2129 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002130 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002131
2132 lines =<< trim END
2133 vim9script
2134
2135 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002136 this.counter: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002137 def Method(nr: number)
2138 endinterface
2139
2140 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002141 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002142 def Method(nr: number)
2143 echo nr
2144 enddef
2145 endclass
2146 END
RestorerZ7fe8f432023-09-24 23:21:24 +02002147 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented')
Bram Moolenaar94674f22023-01-06 18:42:20 +00002148
2149 lines =<< trim END
2150 vim9script
2151
2152 interface Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002153 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002154 def Methods(nr: number)
2155 endinterface
2156
2157 class SomeImpl implements Some
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002158 this.count: number
Bram Moolenaar94674f22023-01-06 18:42:20 +00002159 def Method(nr: number)
2160 echo nr
2161 enddef
2162 endclass
2163 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002164 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented')
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002165
2166 # Check different order of members in class and interface works.
2167 lines =<< trim END
2168 vim9script
2169
2170 interface Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002171 this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002172 this.errpos: number
2173 endinterface
2174
2175 # order of members is opposite of interface
2176 class Failure implements Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002177 public this.lnum: number = 5
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002178 this.errpos: number = 42
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002179 this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002180 endclass
2181
2182 def Test()
2183 var result: Result = Failure.new()
2184
2185 assert_equal('label', result.label)
2186 assert_equal(42, result.errpos)
2187 enddef
2188
2189 Test()
2190 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002191 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002192
2193 # Interface name after "extends" doesn't end in a space or NUL character
2194 lines =<< trim END
2195 vim9script
2196 interface A
2197 endinterface
2198 class B extends A"
2199 endclass
2200 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002201 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002202
2203 # Trailing characters after a class name
2204 lines =<< trim END
2205 vim9script
2206 class A bbb
2207 endclass
2208 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002209 v9.CheckSourceFailure(lines, 'E488:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002210
2211 # using "implements" with a non-existing class
2212 lines =<< trim END
2213 vim9script
2214 class A implements B
2215 endclass
2216 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002217 v9.CheckSourceFailure(lines, 'E1346:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002218
2219 # using "implements" with a regular class
2220 lines =<< trim END
2221 vim9script
2222 class A
2223 endclass
2224 class B implements A
2225 endclass
2226 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002227 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002228
2229 # using "implements" with a variable
2230 lines =<< trim END
2231 vim9script
2232 var T: number = 10
2233 class A implements T
2234 endclass
2235 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002236 v9.CheckSourceFailure(lines, 'E1347:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002237
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002238 # implements should be followed by a white space
2239 lines =<< trim END
2240 vim9script
2241 interface A
2242 endinterface
2243 class B implements A;
2244 endclass
2245 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002246 v9.CheckSourceFailure(lines, 'E1315:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002247
LemonBoyc5d27442023-08-19 13:02:35 +02002248 lines =<< trim END
2249 vim9script
2250
2251 interface One
LemonBoyc5d27442023-08-19 13:02:35 +02002252 def IsEven(nr: number): bool
2253 endinterface
2254 class Two implements One
2255 def IsEven(nr: number): string
2256 enddef
2257 endclass
2258 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002259 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
LemonBoyc5d27442023-08-19 13:02:35 +02002260
2261 lines =<< trim END
2262 vim9script
2263
2264 interface One
2265 def IsEven(nr: number): bool
2266 endinterface
2267 class Two implements One
2268 def IsEven(nr: bool): bool
2269 enddef
2270 endclass
2271 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002272 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
LemonBoyc5d27442023-08-19 13:02:35 +02002273
2274 lines =<< trim END
2275 vim9script
2276
2277 interface One
2278 def IsEven(nr: number): bool
2279 endinterface
2280 class Two implements One
2281 def IsEven(nr: number, ...extra: list<number>): bool
2282 enddef
2283 endclass
2284 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02002285 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 +02002286
2287 # access superclass interface members from subclass, mix variable order
2288 lines =<< trim END
2289 vim9script
2290
2291 interface I1
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002292 this.mvar1: number
2293 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002294 endinterface
2295
2296 # NOTE: the order is swapped
2297 class A implements I1
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002298 this.mvar2: number
2299 this.mvar1: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002300 public static svar2: number
2301 public static svar1: number
2302 def new()
2303 svar1 = 11
2304 svar2 = 12
2305 this.mvar1 = 111
2306 this.mvar2 = 112
2307 enddef
2308 endclass
2309
2310 class B extends A
2311 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002312 this.mvar1 = 121
2313 this.mvar2 = 122
2314 enddef
2315 endclass
2316
2317 class C extends B
2318 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002319 this.mvar1 = 131
2320 this.mvar2 = 132
2321 enddef
2322 endclass
2323
Ernie Raelcf138d42023-09-06 20:45:03 +02002324 def F2(i: I1): list<number>
2325 return [ i.mvar1, i.mvar2 ]
2326 enddef
2327
2328 var oa = A.new()
2329 var ob = B.new()
2330 var oc = C.new()
2331
Ernie Raelcf138d42023-09-06 20:45:03 +02002332 assert_equal([111, 112], F2(oa))
2333 assert_equal([121, 122], F2(ob))
2334 assert_equal([131, 132], F2(oc))
2335 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002336 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002337
2338 # Access superclass interface members from subclass, mix variable order.
2339 # Two interfaces, one on A, one on B; each has both kinds of variables
2340 lines =<< trim END
2341 vim9script
2342
2343 interface I1
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002344 this.mvar1: number
2345 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002346 endinterface
2347
2348 interface I2
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002349 this.mvar3: number
2350 this.mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002351 endinterface
2352
2353 class A implements I1
2354 public static svar1: number
2355 public static svar2: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002356 this.mvar1: number
2357 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002358 def new()
2359 svar1 = 11
2360 svar2 = 12
2361 this.mvar1 = 111
2362 this.mvar2 = 112
2363 enddef
2364 endclass
2365
2366 class B extends A implements I2
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002367 static svar3: number
2368 static svar4: number
2369 this.mvar3: number
2370 this.mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002371 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002372 svar3 = 23
2373 svar4 = 24
2374 this.mvar1 = 121
2375 this.mvar2 = 122
2376 this.mvar3 = 123
2377 this.mvar4 = 124
2378 enddef
2379 endclass
2380
2381 class C extends B
2382 public static svar5: number
2383 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02002384 svar5 = 1001
2385 this.mvar1 = 131
2386 this.mvar2 = 132
2387 this.mvar3 = 133
2388 this.mvar4 = 134
2389 enddef
2390 endclass
2391
Ernie Raelcf138d42023-09-06 20:45:03 +02002392 def F2(i: I1): list<number>
2393 return [ i.mvar1, i.mvar2 ]
2394 enddef
2395
Ernie Raelcf138d42023-09-06 20:45:03 +02002396 def F4(i: I2): list<number>
2397 return [ i.mvar3, i.mvar4 ]
2398 enddef
2399
Ernie Raelcf138d42023-09-06 20:45:03 +02002400 var oa = A.new()
2401 var ob = B.new()
2402 var oc = C.new()
2403
Ernie Raelcf138d42023-09-06 20:45:03 +02002404 assert_equal([[111, 112]], [F2(oa)])
2405 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2406 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002407 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002408 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002409
2410 # Using two interface names without a space after the ","
2411 lines =<< trim END
2412 vim9script
2413 interface A
2414 endinterface
2415 interface B
2416 endinterface
2417 class C implements A,B
2418 endclass
2419 END
2420 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2421
2422 # No interface name after a comma
2423 lines =<< trim END
2424 vim9script
2425 interface A
2426 endinterface
2427 class B implements A,
2428 endclass
2429 END
2430 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2431
2432 # No interface name after implements
2433 lines =<< trim END
2434 vim9script
2435 class A implements
2436 endclass
2437 END
2438 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002439enddef
2440
Bram Moolenaard0200c82023-01-28 15:19:40 +00002441def Test_call_interface_method()
2442 var lines =<< trim END
2443 vim9script
2444 interface Base
2445 def Enter(): void
2446 endinterface
2447
2448 class Child implements Base
2449 def Enter(): void
2450 g:result ..= 'child'
2451 enddef
2452 endclass
2453
2454 def F(obj: Base)
2455 obj.Enter()
2456 enddef
2457
2458 g:result = ''
2459 F(Child.new())
2460 assert_equal('child', g:result)
2461 unlet g:result
2462 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002463 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002464
2465 lines =<< trim END
2466 vim9script
2467 class Base
2468 def Enter(): void
2469 g:result ..= 'base'
2470 enddef
2471 endclass
2472
2473 class Child extends Base
2474 def Enter(): void
2475 g:result ..= 'child'
2476 enddef
2477 endclass
2478
2479 def F(obj: Base)
2480 obj.Enter()
2481 enddef
2482
2483 g:result = ''
2484 F(Child.new())
2485 assert_equal('child', g:result)
2486 unlet g:result
2487 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002488 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002489
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002490 # method of interface returns a value
2491 lines =<< trim END
2492 vim9script
2493 interface Base
2494 def Enter(): string
2495 endinterface
2496
2497 class Child implements Base
2498 def Enter(): string
2499 g:result ..= 'child'
2500 return "/resource"
2501 enddef
2502 endclass
2503
2504 def F(obj: Base)
2505 var r = obj.Enter()
2506 g:result ..= r
2507 enddef
2508
2509 g:result = ''
2510 F(Child.new())
2511 assert_equal('child/resource', g:result)
2512 unlet g:result
2513 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002514 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002515
2516 lines =<< trim END
2517 vim9script
2518 class Base
2519 def Enter(): string
2520 return null_string
2521 enddef
2522 endclass
2523
2524 class Child extends Base
2525 def Enter(): string
2526 g:result ..= 'child'
2527 return "/resource"
2528 enddef
2529 endclass
2530
2531 def F(obj: Base)
2532 var r = obj.Enter()
2533 g:result ..= r
2534 enddef
2535
2536 g:result = ''
2537 F(Child.new())
2538 assert_equal('child/resource', g:result)
2539 unlet g:result
2540 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002541 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002542
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002543 # No class that implements the interface.
2544 lines =<< trim END
2545 vim9script
2546
2547 interface IWithEE
2548 def Enter(): any
2549 def Exit(): void
2550 endinterface
2551
2552 def With1(ee: IWithEE, F: func)
2553 var r = ee.Enter()
2554 enddef
2555
2556 defcompile
2557 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002558 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002559enddef
2560
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002561def Test_class_used_as_type()
2562 var lines =<< trim END
2563 vim9script
2564
2565 class Point
2566 this.x = 0
2567 this.y = 0
2568 endclass
2569
2570 var p: Point
2571 p = Point.new(2, 33)
2572 assert_equal(2, p.x)
2573 assert_equal(33, p.y)
2574 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002575 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002576
2577 lines =<< trim END
2578 vim9script
2579
2580 interface HasX
2581 this.x: number
2582 endinterface
2583
2584 class Point implements HasX
2585 this.x = 0
2586 this.y = 0
2587 endclass
2588
2589 var p: Point
2590 p = Point.new(2, 33)
2591 var hx = p
2592 assert_equal(2, hx.x)
2593 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002594 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002595
2596 lines =<< trim END
2597 vim9script
2598
2599 class Point
2600 this.x = 0
2601 this.y = 0
2602 endclass
2603
2604 var p: Point
2605 p = 'text'
2606 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002607 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002608enddef
2609
Bram Moolenaar83677162023-01-08 19:54:10 +00002610def Test_class_extends()
2611 var lines =<< trim END
2612 vim9script
2613 class Base
2614 this.one = 1
2615 def GetOne(): number
2616 return this.one
2617 enddef
2618 endclass
2619 class Child extends Base
2620 this.two = 2
2621 def GetTotal(): number
2622 return this.one + this.two
2623 enddef
2624 endclass
2625 var o = Child.new()
2626 assert_equal(1, o.one)
2627 assert_equal(2, o.two)
2628 assert_equal(1, o.GetOne())
2629 assert_equal(3, o.GetTotal())
2630 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002631 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002632
2633 lines =<< trim END
2634 vim9script
2635 class Base
2636 this.one = 1
2637 endclass
2638 class Child extends Base
2639 this.two = 2
2640 endclass
2641 var o = Child.new(3, 44)
2642 assert_equal(3, o.one)
2643 assert_equal(44, o.two)
2644 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002645 v9.CheckSourceSuccess(lines)
Bram Moolenaar83677162023-01-08 19:54:10 +00002646
2647 lines =<< trim END
2648 vim9script
2649 class Base
2650 this.one = 1
2651 endclass
2652 class Child extends Base extends Base
2653 this.two = 2
2654 endclass
2655 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002656 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
Bram Moolenaar83677162023-01-08 19:54:10 +00002657
2658 lines =<< trim END
2659 vim9script
2660 class Child extends BaseClass
2661 this.two = 2
2662 endclass
2663 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002664 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
Bram Moolenaar83677162023-01-08 19:54:10 +00002665
2666 lines =<< trim END
2667 vim9script
2668 var SomeVar = 99
2669 class Child extends SomeVar
2670 this.two = 2
2671 endclass
2672 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002673 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
Bram Moolenaar58b40092023-01-11 15:59:05 +00002674
2675 lines =<< trim END
2676 vim9script
2677 class Base
2678 this.name: string
2679 def ToString(): string
2680 return this.name
2681 enddef
2682 endclass
2683
2684 class Child extends Base
2685 this.age: number
2686 def ToString(): string
2687 return super.ToString() .. ': ' .. this.age
2688 enddef
2689 endclass
2690
2691 var o = Child.new('John', 42)
2692 assert_equal('John: 42', o.ToString())
2693 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002694 v9.CheckSourceSuccess(lines)
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002695
2696 lines =<< trim END
2697 vim9script
2698 class Child
2699 this.age: number
2700 def ToString(): number
2701 return this.age
2702 enddef
2703 def ToString(): string
2704 return this.age
2705 enddef
2706 endclass
2707 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002708 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002709
2710 lines =<< trim END
2711 vim9script
2712 class Child
2713 this.age: number
2714 def ToString(): string
2715 return super .ToString() .. ': ' .. this.age
2716 enddef
2717 endclass
2718 var o = Child.new(42)
2719 echo o.ToString()
2720 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002721 v9.CheckSourceFailure(lines, 'E1356:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002722
2723 lines =<< trim END
2724 vim9script
2725 class Base
2726 this.name: string
2727 def ToString(): string
2728 return this.name
2729 enddef
2730 endclass
2731
2732 var age = 42
2733 def ToString(): string
2734 return super.ToString() .. ': ' .. age
2735 enddef
2736 echo ToString()
2737 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002738 v9.CheckSourceFailure(lines, 'E1357:')
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002739
2740 lines =<< trim END
2741 vim9script
2742 class Child
2743 this.age: number
2744 def ToString(): string
2745 return super.ToString() .. ': ' .. this.age
2746 enddef
2747 endclass
2748 var o = Child.new(42)
2749 echo o.ToString()
2750 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002751 v9.CheckSourceFailure(lines, 'E1358:')
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002752
2753 lines =<< trim END
2754 vim9script
2755 class Base
2756 this.name: string
2757 static def ToString(): string
2758 return 'Base class'
2759 enddef
2760 endclass
2761
2762 class Child extends Base
2763 this.age: number
2764 def ToString(): string
2765 return Base.ToString() .. ': ' .. this.age
2766 enddef
2767 endclass
2768
2769 var o = Child.new('John', 42)
2770 assert_equal('Base class: 42', o.ToString())
2771 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002772 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002773
2774 lines =<< trim END
2775 vim9script
2776 class Base
2777 this.value = 1
2778 def new(init: number)
2779 this.value = number + 1
2780 enddef
2781 endclass
2782 class Child extends Base
2783 def new()
2784 this.new(3)
2785 enddef
2786 endclass
2787 var c = Child.new()
2788 END
RestorerZ7fe8f432023-09-24 23:21:24 +02002789 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"')
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002790
2791 # base class with more than one object member
2792 lines =<< trim END
2793 vim9script
2794
2795 class Result
2796 this.success: bool
2797 this.value: any = null
2798 endclass
2799
2800 class Success extends Result
2801 def new(this.value = v:none)
2802 this.success = true
2803 enddef
2804 endclass
2805
2806 var v = Success.new('asdf')
2807 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
2808 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002809 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002810
2811 # class name after "extends" doesn't end in a space or NUL character
2812 lines =<< trim END
2813 vim9script
2814 class A
2815 endclass
2816 class B extends A"
2817 endclass
2818 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002819 v9.CheckSourceFailure(lines, 'E1315:')
Bram Moolenaar83677162023-01-08 19:54:10 +00002820enddef
2821
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002822def Test_using_base_class()
2823 var lines =<< trim END
2824 vim9script
2825
2826 class BaseEE
2827 def Enter(): any
2828 return null
2829 enddef
2830 def Exit(resource: any): void
2831 enddef
2832 endclass
2833
2834 class ChildEE extends BaseEE
2835 def Enter(): any
2836 return 42
2837 enddef
2838
2839 def Exit(resource: number): void
2840 g:result ..= '/exit'
2841 enddef
2842 endclass
2843
2844 def With(ee: BaseEE)
2845 var r = ee.Enter()
2846 try
2847 g:result ..= r
2848 finally
2849 g:result ..= '/finally'
2850 ee.Exit(r)
2851 endtry
2852 enddef
2853
2854 g:result = ''
2855 With(ChildEE.new())
2856 assert_equal('42/finally/exit', g:result)
2857 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002858 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002859 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002860
2861 # Using super, Child invokes Base method which has optional arg. #12471
2862 lines =<< trim END
2863 vim9script
2864
2865 class Base
2866 this.success: bool = false
2867 def Method(arg = 0)
2868 this.success = true
2869 enddef
2870 endclass
2871
2872 class Child extends Base
2873 def new()
2874 super.Method()
2875 enddef
2876 endclass
2877
2878 var obj = Child.new()
2879 assert_equal(true, obj.success)
2880 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002881 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002882enddef
2883
Bram Moolenaara86655a2023-01-12 17:06:27 +00002884def Test_class_import()
2885 var lines =<< trim END
2886 vim9script
2887 export class Animal
2888 this.kind: string
2889 this.name: string
2890 endclass
2891 END
2892 writefile(lines, 'Xanimal.vim', 'D')
2893
2894 lines =<< trim END
2895 vim9script
2896 import './Xanimal.vim' as animal
2897
2898 var a: animal.Animal
2899 a = animal.Animal.new('fish', 'Eric')
2900 assert_equal('fish', a.kind)
2901 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00002902
2903 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
2904 assert_equal('cat', b.kind)
2905 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00002906 END
2907 v9.CheckScriptSuccess(lines)
2908enddef
2909
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002910def Test_abstract_class()
2911 var lines =<< trim END
2912 vim9script
2913 abstract class Base
2914 this.name: string
2915 endclass
2916 class Person extends Base
2917 this.age: number
2918 endclass
2919 var p: Base = Person.new('Peter', 42)
2920 assert_equal('Peter', p.name)
2921 assert_equal(42, p.age)
2922 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002923 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002924
2925 lines =<< trim END
2926 vim9script
2927 abstract class Base
2928 this.name: string
2929 endclass
2930 class Person extends Base
2931 this.age: number
2932 endclass
2933 var p = Base.new('Peter')
2934 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002935 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002936
2937 lines =<< trim END
2938 abstract class Base
2939 this.name: string
2940 endclass
2941 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002942 v9.CheckSourceFailure(lines, 'E1316:')
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002943
2944 # Abstract class cannot have a "new" function
2945 lines =<< trim END
2946 vim9script
2947 abstract class Base
2948 def new()
2949 enddef
2950 endclass
2951 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002952 v9.CheckSourceFailure(lines, 'E1359:')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00002953enddef
2954
Bram Moolenaar486fc252023-01-18 14:51:07 +00002955def Test_closure_in_class()
2956 var lines =<< trim END
2957 vim9script
2958
2959 class Foo
2960 this.y: list<string> = ['B']
2961
2962 def new()
2963 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
2964 enddef
2965 endclass
2966
2967 Foo.new()
2968 assert_equal(['A'], g:result)
2969 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002970 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00002971enddef
2972
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002973def Test_call_constructor_from_legacy()
2974 var lines =<< trim END
2975 vim9script
2976
2977 var newCalled = 'false'
2978
2979 class A
2980 def new()
2981 newCalled = 'true'
2982 enddef
2983 endclass
2984
2985 export def F(options = {}): any
2986 return A
2987 enddef
2988
2989 g:p = F()
2990 legacy call p.new()
2991 assert_equal('true', newCalled)
2992 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002993 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01002994enddef
2995
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00002996def Test_defer_with_object()
2997 var lines =<< trim END
2998 vim9script
2999
3000 class CWithEE
3001 def Enter()
3002 g:result ..= "entered/"
3003 enddef
3004 def Exit()
3005 g:result ..= "exited"
3006 enddef
3007 endclass
3008
3009 def With(ee: CWithEE, F: func)
3010 ee.Enter()
3011 defer ee.Exit()
3012 F()
3013 enddef
3014
3015 g:result = ''
3016 var obj = CWithEE.new()
3017 obj->With(() => {
3018 g:result ..= "called/"
3019 })
3020 assert_equal('entered/called/exited', g:result)
3021 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003022 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003023 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003024
3025 lines =<< trim END
3026 vim9script
3027
3028 class BaseWithEE
3029 def Enter()
3030 g:result ..= "entered-base/"
3031 enddef
3032 def Exit()
3033 g:result ..= "exited-base"
3034 enddef
3035 endclass
3036
3037 class CWithEE extends BaseWithEE
3038 def Enter()
3039 g:result ..= "entered-child/"
3040 enddef
3041 def Exit()
3042 g:result ..= "exited-child"
3043 enddef
3044 endclass
3045
3046 def With(ee: BaseWithEE, F: func)
3047 ee.Enter()
3048 defer ee.Exit()
3049 F()
3050 enddef
3051
3052 g:result = ''
3053 var obj = CWithEE.new()
3054 obj->With(() => {
3055 g:result ..= "called/"
3056 })
3057 assert_equal('entered-child/called/exited-child', g:result)
3058 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003059 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003060 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003061enddef
3062
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003063" The following test used to crash Vim (Github issue #12676)
3064def Test_extends_method_crashes_vim()
3065 var lines =<< trim END
3066 vim9script
3067
3068 class Observer
3069 endclass
3070
3071 class Property
3072 this.value: any
3073
3074 def Set(v: any)
3075 if v != this.value
3076 this.value = v
3077 endif
3078 enddef
3079
3080 def Register(observer: Observer)
3081 enddef
3082 endclass
3083
3084 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003085 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003086 endclass
3087
3088 def Observe(obj: Property, who: Observer)
3089 obj.Register(who)
3090 enddef
3091
3092 var p = Bool.new(false)
3093 var myObserver = Observer.new()
3094
3095 Observe(p, myObserver)
3096
3097 p.Set(true)
3098 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003099 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003100enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003101
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003102" Test for calling a method in a class that is extended
3103def Test_call_method_in_extended_class()
3104 var lines =<< trim END
3105 vim9script
3106
3107 var prop_init_called = false
3108 var prop_register_called = false
3109
3110 class Property
3111 def Init()
3112 prop_init_called = true
3113 enddef
3114
3115 def Register()
3116 prop_register_called = true
3117 enddef
3118 endclass
3119
3120 class Bool extends Property
3121 endclass
3122
3123 def Observe(obj: Property)
3124 obj.Register()
3125 enddef
3126
3127 var p = Property.new()
3128 Observe(p)
3129
3130 p.Init()
3131 assert_true(prop_init_called)
3132 assert_true(prop_register_called)
3133 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003134 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003135enddef
3136
LemonBoyafe04662023-08-23 21:08:11 +02003137def Test_instanceof()
3138 var lines =<< trim END
3139 vim9script
3140
3141 class Base1
3142 endclass
3143
3144 class Base2 extends Base1
3145 endclass
3146
3147 interface Intf1
3148 endinterface
3149
3150 class Mix1 implements Intf1
3151 endclass
3152
3153 class Base3 extends Mix1
3154 endclass
3155
3156 var b1 = Base1.new()
3157 var b2 = Base2.new()
3158 var b3 = Base3.new()
3159
3160 assert_true(instanceof(b1, Base1))
3161 assert_true(instanceof(b2, Base1))
3162 assert_false(instanceof(b1, Base2))
3163 assert_true(instanceof(b3, Mix1))
3164 assert_false(instanceof(b3, []))
3165 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003166
3167 def Foo()
3168 var a1 = Base1.new()
3169 var a2 = Base2.new()
3170 var a3 = Base3.new()
3171
3172 assert_true(instanceof(a1, Base1))
3173 assert_true(instanceof(a2, Base1))
3174 assert_false(instanceof(a1, Base2))
3175 assert_true(instanceof(a3, Mix1))
3176 assert_false(instanceof(a3, []))
3177 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
3178 enddef
3179 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003180
3181 var o_null: Base1
3182 assert_false(instanceof(o_null, Base1))
3183
LemonBoyafe04662023-08-23 21:08:11 +02003184 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003185 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02003186enddef
3187
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003188" Test for calling a method in the parent class that is extended partially.
3189" This used to fail with the 'E118: Too many arguments for function: Text' error
3190" message (Github issue #12524).
3191def Test_call_method_in_parent_class()
3192 var lines =<< trim END
3193 vim9script
3194
3195 class Widget
3196 this._lnum: number = 1
3197
3198 def SetY(lnum: number)
3199 this._lnum = lnum
3200 enddef
3201
3202 def Text(): string
3203 return ''
3204 enddef
3205 endclass
3206
3207 class Foo extends Widget
3208 def Text(): string
3209 return '<Foo>'
3210 enddef
3211 endclass
3212
3213 def Stack(w1: Widget, w2: Widget): list<Widget>
3214 w1.SetY(1)
3215 w2.SetY(2)
3216 return [w1, w2]
3217 enddef
3218
3219 var foo1 = Foo.new()
3220 var foo2 = Foo.new()
3221 var l = Stack(foo1, foo2)
3222 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003223 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003224enddef
3225
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003226" Test for calling methods from three levels of classes
3227def Test_multi_level_method_call()
3228 var lines =<< trim END
3229 vim9script
3230
3231 var A_func1: number = 0
3232 var A_func2: number = 0
3233 var A_func3: number = 0
3234 var B_func2: number = 0
3235 var B_func3: number = 0
3236 var C_func3: number = 0
3237
3238 class A
3239 def Func1()
3240 A_func1 += 1
3241 enddef
3242
3243 def Func2()
3244 A_func2 += 1
3245 enddef
3246
3247 def Func3()
3248 A_func3 += 1
3249 enddef
3250 endclass
3251
3252 class B extends A
3253 def Func2()
3254 B_func2 += 1
3255 enddef
3256
3257 def Func3()
3258 B_func3 += 1
3259 enddef
3260 endclass
3261
3262 class C extends B
3263 def Func3()
3264 C_func3 += 1
3265 enddef
3266 endclass
3267
3268 def A_CallFuncs(a: A)
3269 a.Func1()
3270 a.Func2()
3271 a.Func3()
3272 enddef
3273
3274 def B_CallFuncs(b: B)
3275 b.Func1()
3276 b.Func2()
3277 b.Func3()
3278 enddef
3279
3280 def C_CallFuncs(c: C)
3281 c.Func1()
3282 c.Func2()
3283 c.Func3()
3284 enddef
3285
3286 var cobj = C.new()
3287 A_CallFuncs(cobj)
3288 B_CallFuncs(cobj)
3289 C_CallFuncs(cobj)
3290 assert_equal(3, A_func1)
3291 assert_equal(0, A_func2)
3292 assert_equal(0, A_func3)
3293 assert_equal(3, B_func2)
3294 assert_equal(0, B_func3)
3295 assert_equal(3, C_func3)
3296 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003297 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003298enddef
3299
3300" Test for using members from three levels of classes
3301def Test_multi_level_member_access()
3302 var lines =<< trim END
3303 vim9script
3304
3305 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003306 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003307 endclass
3308
3309 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003310 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003311 endclass
3312
3313 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003314 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003315 endclass
3316
3317 def A_members(a: A)
3318 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003319 enddef
3320
3321 def B_members(b: B)
3322 b.val1 += 1
3323 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003324 enddef
3325
3326 def C_members(c: C)
3327 c.val1 += 1
3328 c.val2 += 1
3329 c.val3 += 1
3330 enddef
3331
3332 var cobj = C.new()
3333 A_members(cobj)
3334 B_members(cobj)
3335 C_members(cobj)
3336 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003337 assert_equal(2, cobj.val2)
3338 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003339 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003340 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003341enddef
3342
LemonBoy0ffc17a2023-08-20 18:09:11 +02003343" Test expansion of <stack> with class methods.
3344def Test_stack_expansion_with_methods()
3345 var lines =<< trim END
3346 vim9script
3347
3348 class C
3349 def M1()
3350 F0()
3351 enddef
3352 endclass
3353
3354 def F0()
3355 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3356 enddef
3357
3358 def F()
3359 C.new().M1()
3360 enddef
3361
3362 F()
3363 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003364 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003365enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003366
3367" Test the return type of the new() constructor
3368def Test_new_return_type()
3369 # new() uses the default return type and there is no return statement
3370 var lines =<< trim END
3371 vim9script
3372
3373 class C
3374 this._bufnr: number
3375
3376 def new(this._bufnr)
3377 if !bufexists(this._bufnr)
3378 this._bufnr = -1
3379 endif
3380 enddef
3381 endclass
3382
3383 var c = C.new(12345)
3384 assert_equal('object<C>', typename(c))
3385
3386 var v1: C
3387 v1 = C.new(12345)
3388 assert_equal('object<C>', typename(v1))
3389
3390 def F()
3391 var v2: C
3392 v2 = C.new(12345)
3393 assert_equal('object<C>', typename(v2))
3394 enddef
3395 F()
3396 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003397 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003398
3399 # new() uses the default return type and an empty 'return' statement
3400 lines =<< trim END
3401 vim9script
3402
3403 class C
3404 this._bufnr: number
3405
3406 def new(this._bufnr)
3407 if !bufexists(this._bufnr)
3408 this._bufnr = -1
3409 return
3410 endif
3411 enddef
3412 endclass
3413
3414 var c = C.new(12345)
3415 assert_equal('object<C>', typename(c))
3416
3417 var v1: C
3418 v1 = C.new(12345)
3419 assert_equal('object<C>', typename(v1))
3420
3421 def F()
3422 var v2: C
3423 v2 = C.new(12345)
3424 assert_equal('object<C>', typename(v2))
3425 enddef
3426 F()
3427 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003428 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003429
3430 # new() uses "any" return type and returns "this"
3431 lines =<< trim END
3432 vim9script
3433
3434 class C
3435 this._bufnr: number
3436
3437 def new(this._bufnr): any
3438 if !bufexists(this._bufnr)
3439 this._bufnr = -1
3440 return this
3441 endif
3442 enddef
3443 endclass
3444 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003445 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003446
3447 # new() uses 'Dict' return type and returns a Dict
3448 lines =<< trim END
3449 vim9script
3450
3451 class C
3452 this._state: dict<any>
3453
3454 def new(): dict<any>
3455 this._state = {}
3456 return this._state
3457 enddef
3458 endclass
3459
3460 var c = C.new()
3461 assert_equal('object<C>', typename(c))
3462 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003463 v9.CheckSourceFailure(lines, 'E1365:')
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003464enddef
3465
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003466" Test for checking a member initialization type at run time.
3467def Test_runtime_type_check_for_member_init()
3468 var lines =<< trim END
3469 vim9script
3470
3471 var retnum: bool = false
3472
3473 def F(): any
3474 retnum = !retnum
3475 if retnum
3476 return 1
3477 else
3478 return "hello"
3479 endif
3480 enddef
3481
3482 class C
3483 this._foo: bool = F()
3484 endclass
3485
3486 var c1 = C.new()
3487 var c2 = C.new()
3488 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003489 v9.CheckSourceFailure(lines, 'E1012:')
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003490enddef
3491
3492" Test for locking a variable referring to an object and reassigning to another
3493" object.
3494def Test_object_lockvar()
3495 var lines =<< trim END
3496 vim9script
3497
3498 class C
3499 this.val: number
3500 def new(this.val)
3501 enddef
3502 endclass
3503
3504 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3505 lockvar 2 some_dict
3506
3507 var current: C
3508 current = some_dict['c']
3509 assert_equal(3, current.val)
3510 current = some_dict['b']
3511 assert_equal(2, current.val)
3512
3513 def F()
3514 current = some_dict['c']
3515 enddef
3516
3517 def G()
3518 current = some_dict['b']
3519 enddef
3520
3521 F()
3522 assert_equal(3, current.val)
3523 G()
3524 assert_equal(2, current.val)
3525 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003526 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003527enddef
3528
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003529" Test for a private object method
3530def Test_private_object_method()
3531 # Try calling a private method using an object (at the script level)
3532 var lines =<< trim END
3533 vim9script
3534
3535 class A
3536 def _Foo(): number
3537 return 1234
3538 enddef
3539 endclass
3540 var a = A.new()
3541 a._Foo()
3542 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003543 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003544
3545 # Try calling a private method using an object (from a def function)
3546 lines =<< trim END
3547 vim9script
3548
3549 class A
3550 def _Foo(): number
3551 return 1234
3552 enddef
3553 endclass
3554 def T()
3555 var a = A.new()
3556 a._Foo()
3557 enddef
3558 T()
3559 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003560 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003561
3562 # Use a private method from another object method (in script context)
3563 lines =<< trim END
3564 vim9script
3565
3566 class A
3567 def _Foo(): number
3568 return 1234
3569 enddef
3570 def Bar(): number
3571 return this._Foo()
3572 enddef
3573 endclass
3574 var a = A.new()
3575 assert_equal(1234, a.Bar())
3576 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003577 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003578
3579 # Use a private method from another object method (def function context)
3580 lines =<< trim END
3581 vim9script
3582
3583 class A
3584 def _Foo(): number
3585 return 1234
3586 enddef
3587 def Bar(): number
3588 return this._Foo()
3589 enddef
3590 endclass
3591 def T()
3592 var a = A.new()
3593 assert_equal(1234, a.Bar())
3594 enddef
3595 T()
3596 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003597 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003598
3599 # Try calling a private method without the "this" prefix
3600 lines =<< trim END
3601 vim9script
3602
3603 class A
3604 def _Foo(): number
3605 return 1234
3606 enddef
3607 def Bar(): number
3608 return _Foo()
3609 enddef
3610 endclass
3611 var a = A.new()
3612 a.Bar()
3613 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003614 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003615
3616 # Try calling a private method using the class name
3617 lines =<< trim END
3618 vim9script
3619
3620 class A
3621 def _Foo(): number
3622 return 1234
3623 enddef
3624 endclass
3625 A._Foo()
3626 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003627 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003628
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003629 # Define two private methods with the same name
3630 lines =<< trim END
3631 vim9script
3632
3633 class A
3634 def _Foo()
3635 enddef
3636 def _Foo()
3637 enddef
3638 endclass
3639 var a = A.new()
3640 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003641 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003642
3643 # Define a private method and a object method with the same name
3644 lines =<< trim END
3645 vim9script
3646
3647 class A
3648 def _Foo()
3649 enddef
3650 def Foo()
3651 enddef
3652 endclass
3653 var a = A.new()
3654 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003655 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003656
3657 # Define an object method and a private method with the same name
3658 lines =<< trim END
3659 vim9script
3660
3661 class A
3662 def Foo()
3663 enddef
3664 def _Foo()
3665 enddef
3666 endclass
3667 var a = A.new()
3668 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003669 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003670
3671 # Call a public method and a private method from a private method
3672 lines =<< trim END
3673 vim9script
3674
3675 class A
3676 def Foo(): number
3677 return 100
3678 enddef
3679 def _Bar(): number
3680 return 200
3681 enddef
3682 def _Baz()
3683 assert_equal(100, this.Foo())
3684 assert_equal(200, this._Bar())
3685 enddef
3686 def T()
3687 this._Baz()
3688 enddef
3689 endclass
3690 var a = A.new()
3691 a.T()
3692 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003693 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003694
3695 # Try calling a private method from another class
3696 lines =<< trim END
3697 vim9script
3698
3699 class A
3700 def _Foo(): number
3701 return 100
3702 enddef
3703 endclass
3704 class B
3705 def Foo(): number
3706 var a = A.new()
3707 a._Foo()
3708 enddef
3709 endclass
3710 var b = B.new()
3711 b.Foo()
3712 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003713 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003714
3715 # Call a private object method from a child class object method
3716 lines =<< trim END
3717 vim9script
3718 class A
3719 def _Foo(): number
3720 return 1234
3721 enddef
3722 endclass
3723 class B extends A
3724 def Bar()
3725 enddef
3726 endclass
3727 class C extends B
3728 def Baz(): number
3729 return this._Foo()
3730 enddef
3731 endclass
3732 var c = C.new()
3733 assert_equal(1234, c.Baz())
3734 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003735 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003736
3737 # Call a private object method from a child class object
3738 lines =<< trim END
3739 vim9script
3740 class A
3741 def _Foo(): number
3742 return 1234
3743 enddef
3744 endclass
3745 class B extends A
3746 def Bar()
3747 enddef
3748 endclass
3749 class C extends B
3750 def Baz(): number
3751 enddef
3752 endclass
3753 var c = C.new()
3754 assert_equal(1234, c._Foo())
3755 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003756 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003757
3758 # Using "_" prefix in a method name should fail outside of a class
3759 lines =<< trim END
3760 vim9script
3761 def _Foo(): number
3762 return 1234
3763 enddef
3764 var a = _Foo()
3765 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003766 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003767enddef
3768
3769" Test for an private class method
3770def Test_private_class_method()
3771 # Try calling a class private method (at the script level)
3772 var lines =<< trim END
3773 vim9script
3774
3775 class A
3776 static def _Foo(): number
3777 return 1234
3778 enddef
3779 endclass
3780 A._Foo()
3781 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003782 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003783
3784 # Try calling a class private method (from a def function)
3785 lines =<< trim END
3786 vim9script
3787
3788 class A
3789 static def _Foo(): number
3790 return 1234
3791 enddef
3792 endclass
3793 def T()
3794 A._Foo()
3795 enddef
3796 T()
3797 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003798 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003799
3800 # Try calling a class private method using an object (at the script level)
3801 lines =<< trim END
3802 vim9script
3803
3804 class A
3805 static def _Foo(): number
3806 return 1234
3807 enddef
3808 endclass
3809 var a = A.new()
3810 a._Foo()
3811 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003812 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003813
3814 # Try calling a class private method using an object (from a def function)
3815 lines =<< trim END
3816 vim9script
3817
3818 class A
3819 static def _Foo(): number
3820 return 1234
3821 enddef
3822 endclass
3823 def T()
3824 var a = A.new()
3825 a._Foo()
3826 enddef
3827 T()
3828 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003829 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003830
3831 # Use a class private method from an object method
3832 lines =<< trim END
3833 vim9script
3834
3835 class A
3836 static def _Foo(): number
3837 return 1234
3838 enddef
3839 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003840 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003841 enddef
3842 endclass
3843 var a = A.new()
3844 a.Bar()
3845 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003846 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003847
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003848 # Use a class private method from another class private method without the
3849 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003850 lines =<< trim END
3851 vim9script
3852
3853 class A
3854 static def _Foo1(): number
3855 return 1234
3856 enddef
3857 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003858 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003859 enddef
3860 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02003861 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003862 enddef
3863 endclass
3864 var a = A.new()
3865 a.Bar()
3866 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003867 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003868
3869 # Declare a class method and a class private method with the same name
3870 lines =<< trim END
3871 vim9script
3872
3873 class A
3874 static def _Foo()
3875 enddef
3876 static def Foo()
3877 enddef
3878 endclass
3879 var a = A.new()
3880 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003881 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003882
3883 # Try calling a class private method from another class
3884 lines =<< trim END
3885 vim9script
3886
3887 class A
3888 static def _Foo(): number
3889 return 1234
3890 enddef
3891 endclass
3892 class B
3893 def Foo(): number
3894 return A._Foo()
3895 enddef
3896 endclass
3897 var b = B.new()
3898 assert_equal(1234, b.Foo())
3899 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003900 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003901
3902 # Call a private class method from a child class object method
3903 lines =<< trim END
3904 vim9script
3905 class A
3906 static def _Foo(): number
3907 return 1234
3908 enddef
3909 endclass
3910 class B extends A
3911 def Bar()
3912 enddef
3913 endclass
3914 class C extends B
3915 def Baz(): number
3916 return A._Foo()
3917 enddef
3918 endclass
3919 var c = C.new()
3920 assert_equal(1234, c.Baz())
3921 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003922 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003923
3924 # Call a private class method from a child class private class method
3925 lines =<< trim END
3926 vim9script
3927 class A
3928 static def _Foo(): number
3929 return 1234
3930 enddef
3931 endclass
3932 class B extends A
3933 def Bar()
3934 enddef
3935 endclass
3936 class C extends B
3937 static def Baz(): number
3938 return A._Foo()
3939 enddef
3940 endclass
3941 assert_equal(1234, C.Baz())
3942 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003943 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003944
3945 # Call a private class method from a child class object
3946 lines =<< trim END
3947 vim9script
3948 class A
3949 static def _Foo(): number
3950 return 1234
3951 enddef
3952 endclass
3953 class B extends A
3954 def Bar()
3955 enddef
3956 endclass
3957 class C extends B
3958 def Baz(): number
3959 enddef
3960 endclass
3961 var c = C.new()
3962 assert_equal(1234, C._Foo())
3963 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003964 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02003965enddef
3966
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003967" Test for using the return value of a class/object method as a function
3968" argument.
3969def Test_objmethod_funcarg()
3970 var lines =<< trim END
3971 vim9script
3972
3973 class C
3974 def Foo(): string
3975 return 'foo'
3976 enddef
3977 endclass
3978
3979 def Bar(a: number, s: string): string
3980 return s
3981 enddef
3982
3983 def Baz(c: C)
3984 assert_equal('foo', Bar(10, c.Foo()))
3985 enddef
3986
3987 var t = C.new()
3988 Baz(t)
3989 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003990 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02003991
3992 lines =<< trim END
3993 vim9script
3994
3995 class C
3996 static def Foo(): string
3997 return 'foo'
3998 enddef
3999 endclass
4000
4001 def Bar(a: number, s: string): string
4002 return s
4003 enddef
4004
4005 def Baz()
4006 assert_equal('foo', Bar(10, C.Foo()))
4007 enddef
4008
4009 Baz()
4010 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004011 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004012enddef
4013
Ernie Raelcf138d42023-09-06 20:45:03 +02004014def Test_static_inheritence()
4015 # subclasses get their own static copy
4016 var lines =<< trim END
4017 vim9script
4018
4019 class A
4020 static _svar: number
4021 this._mvar: number
4022 def new()
4023 _svar = 1
4024 this._mvar = 101
4025 enddef
4026 def AccessObject(): number
4027 return this._mvar
4028 enddef
4029 def AccessStaticThroughObject(): number
4030 return _svar
4031 enddef
4032 endclass
4033
4034 class B extends A
4035 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02004036 this._mvar = 102
4037 enddef
4038 endclass
4039
4040 class C extends B
4041 def new()
Ernie Raelcf138d42023-09-06 20:45:03 +02004042 this._mvar = 103
4043 enddef
4044
4045 def AccessPrivateStaticThroughClassName(): number
4046 assert_equal(1, A._svar)
Ernie Raelcf138d42023-09-06 20:45:03 +02004047 return 444
4048 enddef
4049 endclass
4050
4051 var oa = A.new()
4052 var ob = B.new()
4053 var oc = C.new()
4054 assert_equal(101, oa.AccessObject())
4055 assert_equal(102, ob.AccessObject())
4056 assert_equal(103, oc.AccessObject())
4057
RestorerZ7fe8f432023-09-24 23:21:24 +02004058 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private variable: _svar')
Ernie Raelcf138d42023-09-06 20:45:03 +02004059
4060 # verify object properly resolves to correct static
4061 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004062 assert_equal(1, ob.AccessStaticThroughObject())
4063 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02004064 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004065 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02004066enddef
4067
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004068" Test for declaring duplicate object and class members
4069def Test_dup_member_variable()
4070 # Duplicate member variable
4071 var lines =<< trim END
4072 vim9script
4073 class C
4074 this.val = 10
4075 this.val = 20
4076 endclass
4077 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004078 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004079
4080 # Duplicate private member variable
4081 lines =<< trim END
4082 vim9script
4083 class C
4084 this._val = 10
4085 this._val = 20
4086 endclass
4087 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004088 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004089
4090 # Duplicate public member variable
4091 lines =<< trim END
4092 vim9script
4093 class C
4094 public this.val = 10
4095 public this.val = 20
4096 endclass
4097 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004098 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004099
4100 # Duplicate private member variable
4101 lines =<< trim END
4102 vim9script
4103 class C
4104 this.val = 10
4105 this._val = 20
4106 endclass
4107 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004108 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004109
4110 # Duplicate public and private member variable
4111 lines =<< trim END
4112 vim9script
4113 class C
4114 this._val = 20
4115 public this.val = 10
4116 endclass
4117 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004118 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004119
4120 # Duplicate class member variable
4121 lines =<< trim END
4122 vim9script
4123 class C
4124 static s: string = "abc"
4125 static _s: string = "def"
4126 endclass
4127 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004128 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004129
4130 # Duplicate public and private class member variable
4131 lines =<< trim END
4132 vim9script
4133 class C
4134 public static s: string = "abc"
4135 static _s: string = "def"
4136 endclass
4137 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004138 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s')
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004139
4140 # Duplicate class and object member variable
4141 lines =<< trim END
4142 vim9script
4143 class C
4144 static val = 10
4145 this.val = 20
4146 def new()
4147 enddef
4148 endclass
4149 var c = C.new()
4150 assert_equal(10, C.val)
4151 assert_equal(20, c.val)
4152 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004153 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004154
4155 # Duplicate object member variable in a derived class
4156 lines =<< trim END
4157 vim9script
4158 class A
4159 this.val = 10
4160 endclass
4161 class B extends A
4162 endclass
4163 class C extends B
4164 this.val = 20
4165 endclass
4166 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004167 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004168
4169 # Duplicate object private member variable in a derived class
4170 lines =<< trim END
4171 vim9script
4172 class A
4173 this._val = 10
4174 endclass
4175 class B extends A
4176 endclass
4177 class C extends B
4178 this._val = 20
4179 endclass
4180 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004181 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004182
4183 # Duplicate object private member variable in a derived class
4184 lines =<< trim END
4185 vim9script
4186 class A
4187 this.val = 10
4188 endclass
4189 class B extends A
4190 endclass
4191 class C extends B
4192 this._val = 20
4193 endclass
4194 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004195 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val')
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004196
4197 # Duplicate object member variable in a derived class
4198 lines =<< trim END
4199 vim9script
4200 class A
4201 this._val = 10
4202 endclass
4203 class B extends A
4204 endclass
4205 class C extends B
4206 this.val = 20
4207 endclass
4208 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004209 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004210
4211 # Two member variables with a common prefix
4212 lines =<< trim END
4213 vim9script
4214 class A
4215 public static svar2: number
4216 public static svar: number
4217 endclass
4218 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004219 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004220enddef
4221
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004222" Test for accessing a private member outside a class in a def function
4223def Test_private_member_access_outside_class()
4224 # private object member variable
4225 var lines =<< trim END
4226 vim9script
4227 class A
4228 this._val = 10
4229 def GetVal(): number
4230 return this._val
4231 enddef
4232 endclass
4233 def T()
4234 var a = A.new()
4235 a._val = 20
4236 enddef
4237 T()
4238 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004239 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _val')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004240
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004241 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004242 lines =<< trim END
4243 vim9script
4244 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004245 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004246 endclass
4247 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004248 var a = A.new()
4249 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004250 enddef
4251 T()
4252 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004253 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "A": _a')
Ernie Rael18143d32023-09-04 22:30:41 +02004254
4255 # private static member variable
4256 lines =<< trim END
4257 vim9script
4258 class A
4259 static _val = 10
4260 endclass
4261 def T()
4262 var a = A.new()
4263 var x = a._val
4264 enddef
4265 T()
4266 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004267 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004268
4269 # private static member variable
4270 lines =<< trim END
4271 vim9script
4272 class A
4273 static _val = 10
4274 endclass
4275 def T()
4276 var a = A.new()
4277 a._val = 3
4278 enddef
4279 T()
4280 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004281 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"')
Ernie Rael18143d32023-09-04 22:30:41 +02004282
4283 # private static class variable
4284 lines =<< trim END
4285 vim9script
4286 class A
4287 static _val = 10
4288 endclass
4289 def T()
4290 var x = A._val
4291 enddef
4292 T()
4293 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004294 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _val')
Ernie Rael18143d32023-09-04 22:30:41 +02004295
4296 # private static class variable
4297 lines =<< trim END
4298 vim9script
4299 class A
4300 static _val = 10
4301 endclass
4302 def T()
4303 A._val = 3
4304 enddef
4305 T()
4306 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004307 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable: _val')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004308enddef
4309
4310" Test for changing the member access of an interface in a implementation class
4311def Test_change_interface_member_access()
4312 var lines =<< trim END
4313 vim9script
4314 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02004315 this.val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004316 endinterface
4317 class B implements A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02004318 public this.val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004319 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 +02004322
4323 lines =<< trim END
4324 vim9script
4325 interface A
4326 this.val: number
4327 endinterface
4328 class B implements A
4329 public this.val = 10
4330 endclass
4331 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004332 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different')
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004333enddef
4334
4335" Test for trying to change a readonly member from a def function
4336def Test_readonly_member_change_in_def_func()
4337 var lines =<< trim END
4338 vim9script
4339 class A
4340 this.val: number
4341 endclass
4342 def T()
4343 var a = A.new()
4344 a.val = 20
4345 enddef
4346 T()
4347 END
Ernie Rael696270b2023-09-21 16:42:28 +02004348 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable')
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004349enddef
4350
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004351" Test for reading and writing a class member from a def function
4352def Test_modify_class_member_from_def_function()
4353 var lines =<< trim END
4354 vim9script
4355 class A
4356 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004357 public static var2: list<number> = [1, 2]
4358 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004359 static _priv_var4: number = 40
4360 endclass
4361 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02004362 assert_equal([1, 2], A.var2)
4363 assert_equal({a: 1, b: 2}, A.var3)
4364 A.var2 = [3, 4]
4365 A.var3 = {c: 3, d: 4}
4366 assert_equal([3, 4], A.var2)
4367 assert_equal({c: 3, d: 4}, A.var3)
RestorerZ7fe8f432023-09-24 23:21:24 +02004368 assert_fails('echo A._priv_var4', 'E1333: Cannot access private variable: _priv_var4')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004369 enddef
4370 T()
4371 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004372 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02004373enddef
4374
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004375" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004376def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004377 var lines =<< trim END
4378 vim9script
4379 class A
4380 public static svar1: list<number> = [1]
4381 public static svar2: list<number> = [2]
4382 endclass
4383
4384 A.svar1->add(3)
4385 A.svar2->add(4)
4386 assert_equal([1, 3], A.svar1)
4387 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004388
4389 def Foo()
4390 A.svar1->add(7)
4391 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004392 assert_equal([1, 3, 7], A.svar1)
4393 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004394 enddef
4395 Foo()
4396 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004397 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004398
4399 # Cannot read from a class variable using an object in script context
4400 lines =<< trim END
4401 vim9script
4402 class A
4403 public this.var1: number
4404 public static svar2: list<number> = [1]
4405 endclass
4406
4407 var a = A.new()
4408 echo a.svar2
4409 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004410 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004411
4412 # Cannot write to a class variable using an object in script context
4413 lines =<< trim END
4414 vim9script
4415 class A
4416 public this.var1: number
4417 public static svar2: list<number> = [1]
4418 endclass
4419
4420 var a = A.new()
4421 a.svar2 = [2]
4422 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004423 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004424
4425 # Cannot read from a class variable using an object in def method context
4426 lines =<< trim END
4427 vim9script
4428 class A
4429 public this.var1: number
4430 public static svar2: list<number> = [1]
4431 endclass
4432
4433 def T()
4434 var a = A.new()
4435 echo a.svar2
4436 enddef
4437 T()
4438 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004439 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02004440
4441 # Cannot write to a class variable using an object in def method context
4442 lines =<< trim END
4443 vim9script
4444 class A
4445 public this.var1: number
4446 public static svar2: list<number> = [1]
4447 endclass
4448
4449 def T()
4450 var a = A.new()
4451 a.svar2 = [2]
4452 enddef
4453 T()
4454 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004455 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"')
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004456enddef
4457
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004458" Test for using a interface method using a child object
4459def Test_interface_method_from_child()
4460 var lines =<< trim END
4461 vim9script
4462
4463 interface A
4464 def Foo(): string
4465 endinterface
4466
4467 class B implements A
4468 def Foo(): string
4469 return 'foo'
4470 enddef
4471 endclass
4472
4473 class C extends B
4474 def Bar(): string
4475 return 'bar'
4476 enddef
4477 endclass
4478
4479 def T1(a: A)
4480 assert_equal('foo', a.Foo())
4481 enddef
4482
4483 def T2(b: B)
4484 assert_equal('foo', b.Foo())
4485 enddef
4486
4487 var c = C.new()
4488 T1(c)
4489 T2(c)
4490 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004491 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004492enddef
4493
4494" Test for using an interface method using a child object when it is overridden
4495" by the child class.
4496" FIXME: This test fails.
4497" def Test_interface_overridden_method_from_child()
4498" var lines =<< trim END
4499" vim9script
4500"
4501" interface A
4502" def Foo(): string
4503" endinterface
4504"
4505" class B implements A
4506" def Foo(): string
4507" return 'b-foo'
4508" enddef
4509" endclass
4510"
4511" class C extends B
4512" def Bar(): string
4513" return 'bar'
4514" enddef
4515" def Foo(): string
4516" return 'c-foo'
4517" enddef
4518" endclass
4519"
4520" def T1(a: A)
4521" assert_equal('c-foo', a.Foo())
4522" enddef
4523"
4524" def T2(b: B)
4525" assert_equal('c-foo', b.Foo())
4526" enddef
4527"
4528" var c = C.new()
4529" T1(c)
4530" T2(c)
4531" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004532" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02004533" enddef
4534
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004535" Test for abstract methods
4536def Test_abstract_method()
4537 # Use two abstract methods
4538 var lines =<< trim END
4539 vim9script
4540 abstract class A
4541 def M1(): number
4542 return 10
4543 enddef
4544 abstract def M2(): number
4545 abstract def M3(): number
4546 endclass
4547 class B extends A
4548 def M2(): number
4549 return 20
4550 enddef
4551 def M3(): number
4552 return 30
4553 enddef
4554 endclass
4555 var b = B.new()
4556 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
4557 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004558 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004559
4560 # Don't define an abstract method
4561 lines =<< trim END
4562 vim9script
4563 abstract 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, 'E1373: Abstract method "Foo" is not implemented')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004570
4571 # Use abstract method in a concrete class
4572 lines =<< trim END
4573 vim9script
4574 class A
4575 abstract def Foo()
4576 endclass
4577 class B extends A
4578 endclass
4579 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004580 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004581
4582 # Use abstract method in an interface
4583 lines =<< trim END
4584 vim9script
4585 interface A
4586 abstract def Foo()
4587 endinterface
4588 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004589 def Foo()
4590 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004591 endclass
4592 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004593 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004594
4595 # Abbreviate the "abstract" keyword
4596 lines =<< trim END
4597 vim9script
4598 class A
4599 abs def Foo()
4600 endclass
4601 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004602 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004603
4604 # Use "abstract" with a member variable
4605 lines =<< trim END
4606 vim9script
4607 abstract class A
4608 abstract this.val = 10
4609 endclass
4610 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004611 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004612
4613 # Use a static abstract method
4614 lines =<< trim END
4615 vim9script
4616 abstract class A
4617 abstract static def Foo(): number
4618 endclass
4619 class B extends A
4620 static def Foo(): number
4621 return 4
4622 enddef
4623 endclass
4624 assert_equal(4, B.Foo())
4625 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004626 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004627
4628 # Type mismatch between abstract method and concrete method
4629 lines =<< trim END
4630 vim9script
4631 abstract class A
4632 abstract def Foo(a: string, b: number): list<number>
4633 endclass
4634 class B extends A
4635 def Foo(a: number, b: string): list<string>
4636 return []
4637 enddef
4638 endclass
4639 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02004640 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 +02004641
4642 # Use an abstract class to invoke an abstract method
4643 # FIXME: This should fail
4644 lines =<< trim END
4645 vim9script
4646 abstract class A
4647 abstract static def Foo()
4648 endclass
4649 A.Foo()
4650 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004651 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004652
4653 # Invoke an abstract method from a def function
4654 lines =<< trim END
4655 vim9script
4656 abstract class A
4657 abstract def Foo(): list<number>
4658 endclass
4659 class B extends A
4660 def Foo(): list<number>
4661 return [3, 5]
4662 enddef
4663 endclass
4664 def Bar(c: B)
4665 assert_equal([3, 5], c.Foo())
4666 enddef
4667 var b = B.new()
4668 Bar(b)
4669 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004670 v9.CheckSourceSuccess(lines)
4671enddef
4672
4673" Test for calling a class method from a subclass
4674def Test_class_method_call_from_subclass()
4675 # class method call from a subclass
4676 var lines =<< trim END
4677 vim9script
4678
4679 class A
4680 static def Foo()
4681 echo "foo"
4682 enddef
4683 endclass
4684
4685 class B extends A
4686 def Bar()
4687 Foo()
4688 enddef
4689 endclass
4690
4691 var b = B.new()
4692 b.Bar()
4693 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004694 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"')
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02004695enddef
4696
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004697" Test for calling a class method using an object in a def function context and
4698" script context.
4699def Test_class_method_call_using_object()
4700 # script context
4701 var lines =<< trim END
4702 vim9script
4703 class A
4704 static def Foo(): list<string>
4705 return ['a', 'b']
4706 enddef
4707 def Bar()
4708 assert_equal(['a', 'b'], A.Foo())
4709 assert_equal(['a', 'b'], Foo())
4710 enddef
4711 endclass
4712
4713 def T()
4714 assert_equal(['a', 'b'], A.Foo())
4715 var t_a = A.new()
4716 t_a.Bar()
4717 enddef
4718
4719 assert_equal(['a', 'b'], A.Foo())
4720 var a = A.new()
4721 a.Bar()
4722 T()
4723 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004724 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004725
4726 # script context
4727 lines =<< trim END
4728 vim9script
4729 class A
4730 static def Foo(): string
4731 return 'foo'
4732 enddef
4733 endclass
4734
4735 var a = A.new()
4736 assert_equal('foo', a.Foo())
4737 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004738 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"')
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02004739
4740 # def function context
4741 lines =<< trim END
4742 vim9script
4743 class A
4744 static def Foo(): string
4745 return 'foo'
4746 enddef
4747 endclass
4748
4749 def T()
4750 var a = A.new()
4751 assert_equal('foo', a.Foo())
4752 enddef
4753 T()
4754 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004755 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004756enddef
4757
4758def Test_class_variable()
4759 var lines =<< trim END
4760 vim9script
4761
4762 class A
4763 public static val: number = 10
4764 static def ClassFunc()
4765 assert_equal(10, val)
4766 enddef
4767 def ObjFunc()
4768 assert_equal(10, val)
4769 enddef
4770 endclass
4771
4772 class B extends A
4773 endclass
4774
4775 assert_equal(10, A.val)
4776 A.ClassFunc()
4777 var a = A.new()
4778 a.ObjFunc()
4779 var b = B.new()
4780 b.ObjFunc()
4781
4782 def T1(a1: A)
4783 a1.ObjFunc()
4784 A.ClassFunc()
4785 enddef
4786 T1(b)
4787
4788 A.val = 20
4789 assert_equal(20, A.val)
4790 END
4791 v9.CheckSourceSuccess(lines)
4792
4793 # Modifying a parent class variable from a child class method
4794 lines =<< trim END
4795 vim9script
4796
4797 class A
4798 static val: number = 10
4799 endclass
4800
4801 class B extends A
4802 static def ClassFunc()
4803 val = 20
4804 enddef
4805 endclass
4806 B.ClassFunc()
4807 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004808 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004809
4810 # Reading a parent class variable from a child class method
4811 lines =<< trim END
4812 vim9script
4813
4814 class A
4815 static val: number = 10
4816 endclass
4817
4818 class B extends A
4819 static def ClassFunc()
4820 var i = val
4821 enddef
4822 endclass
4823 B.ClassFunc()
4824 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004825 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004826
4827 # Modifying a parent class variable from a child object method
4828 lines =<< trim END
4829 vim9script
4830
4831 class A
4832 static val: number = 10
4833 endclass
4834
4835 class B extends A
4836 def ObjFunc()
4837 val = 20
4838 enddef
4839 endclass
4840 var b = B.new()
4841 b.ObjFunc()
4842 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004843 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004844
4845 # Reading a parent class variable from a child object method
4846 lines =<< trim END
4847 vim9script
4848
4849 class A
4850 static val: number = 10
4851 endclass
4852
4853 class B extends A
4854 def ObjFunc()
4855 var i = val
4856 enddef
4857 endclass
4858 var b = B.new()
4859 b.ObjFunc()
4860 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004861 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004862
4863 # Modifying a class variable using an object at script level
4864 lines =<< trim END
4865 vim9script
4866
4867 class A
4868 static val: number = 10
4869 endclass
4870 var a = A.new()
4871 a.val = 20
4872 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004873 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004874
4875 # Reading a class variable using an object at script level
4876 lines =<< trim END
4877 vim9script
4878
4879 class A
4880 static val: number = 10
4881 endclass
4882 var a = A.new()
4883 var i = a.val
4884 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004885 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004886
4887 # Modifying a class variable using an object at function level
4888 lines =<< trim END
4889 vim9script
4890
4891 class A
4892 static val: number = 10
4893 endclass
4894
4895 def T()
4896 var a = A.new()
4897 a.val = 20
4898 enddef
4899 T()
4900 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004901 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004902
4903 # Reading a class variable using an object at function level
4904 lines =<< trim END
4905 vim9script
4906
4907 class A
4908 static val: number = 10
4909 endclass
4910 def T()
4911 var a = A.new()
4912 var i = a.val
4913 enddef
4914 T()
4915 END
RestorerZ7fe8f432023-09-24 23:21:24 +02004916 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004917enddef
4918
4919" Test for using a duplicate class method and class variable in a child class
4920def Test_dup_class_member()
4921 # duplicate class variable, class method and overridden object method
4922 var lines =<< trim END
4923 vim9script
4924 class A
4925 static sval = 100
4926 static def Check()
4927 assert_equal(100, sval)
4928 enddef
4929 def GetVal(): number
4930 return sval
4931 enddef
4932 endclass
4933
4934 class B extends A
4935 static sval = 200
4936 static def Check()
4937 assert_equal(200, sval)
4938 enddef
4939 def GetVal(): number
4940 return sval
4941 enddef
4942 endclass
4943
4944 def T1(aa: A): number
4945 return aa.GetVal()
4946 enddef
4947
4948 def T2(bb: B): number
4949 return bb.GetVal()
4950 enddef
4951
4952 assert_equal(100, A.sval)
4953 assert_equal(200, B.sval)
4954 var a = A.new()
4955 assert_equal(100, a.GetVal())
4956 var b = B.new()
4957 assert_equal(200, b.GetVal())
4958 assert_equal(200, T1(b))
4959 assert_equal(200, T2(b))
4960 END
4961 v9.CheckSourceSuccess(lines)
4962
4963 # duplicate class variable and class method
4964 lines =<< trim END
4965 vim9script
4966 class A
4967 static sval = 100
4968 static def Check()
4969 assert_equal(100, sval)
4970 enddef
4971 def GetVal(): number
4972 return sval
4973 enddef
4974 endclass
4975
4976 class B extends A
4977 static sval = 200
4978 static def Check()
4979 assert_equal(200, sval)
4980 enddef
4981 endclass
4982
4983 def T1(aa: A): number
4984 return aa.GetVal()
4985 enddef
4986
4987 def T2(bb: B): number
4988 return bb.GetVal()
4989 enddef
4990
4991 assert_equal(100, A.sval)
4992 assert_equal(200, B.sval)
4993 var a = A.new()
4994 assert_equal(100, a.GetVal())
4995 var b = B.new()
4996 assert_equal(100, b.GetVal())
4997 assert_equal(100, T1(b))
4998 assert_equal(100, T2(b))
4999 END
5000 v9.CheckSourceSuccess(lines)
5001enddef
5002
5003" Test for calling an instance method using the class
5004def Test_instance_method_call_using_class()
5005 # Invoke an object method using a class in script context
5006 var lines =<< trim END
5007 vim9script
5008 class A
5009 def Foo()
5010 echo "foo"
5011 enddef
5012 endclass
5013 A.Foo()
5014 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005015 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005016
5017 # Invoke an object method using a class in def function context
5018 lines =<< trim END
5019 vim9script
5020 class A
5021 def Foo()
5022 echo "foo"
5023 enddef
5024 endclass
5025 def T()
5026 A.Foo()
5027 enddef
5028 T()
5029 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005030 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005031enddef
5032
5033" Test for duplicate class method and instance method
5034def Test_dup_classmethod_objmethod()
5035 # Duplicate instance method
5036 var lines =<< trim END
5037 vim9script
5038 class A
5039 static def Foo()
5040 enddef
5041 def Foo()
5042 enddef
5043 endclass
5044 END
5045 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
5046
5047 # Duplicate private instance method
5048 lines =<< trim END
5049 vim9script
5050 class A
5051 static def Foo()
5052 enddef
5053 def _Foo()
5054 enddef
5055 endclass
5056 END
5057 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5058
5059 # Duplicate class method
5060 lines =<< trim END
5061 vim9script
5062 class A
5063 def Foo()
5064 enddef
5065 static def Foo()
5066 enddef
5067 endclass
5068 END
5069 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
5070
5071 # Duplicate private class method
5072 lines =<< trim END
5073 vim9script
5074 class A
5075 def Foo()
5076 enddef
5077 static def _Foo()
5078 enddef
5079 endclass
5080 END
5081 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5082
5083 # Duplicate private class and object method
5084 lines =<< trim END
5085 vim9script
5086 class A
5087 def _Foo()
5088 enddef
5089 static def _Foo()
5090 enddef
5091 endclass
5092 END
5093 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
5094enddef
5095
5096" Test for an instance method access level comparison with parent instance
5097" methods.
5098def Test_instance_method_access_level()
5099 # Private method in subclass
5100 var lines =<< trim END
5101 vim9script
5102 class A
5103 def Foo()
5104 enddef
5105 endclass
5106 class B extends A
5107 endclass
5108 class C extends B
5109 def _Foo()
5110 enddef
5111 endclass
5112 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005113 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005114
5115 # Public method in subclass
5116 lines =<< trim END
5117 vim9script
5118 class A
5119 def _Foo()
5120 enddef
5121 endclass
5122 class B extends A
5123 endclass
5124 class C extends B
5125 def Foo()
5126 enddef
5127 endclass
5128 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005129 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"')
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005130enddef
5131
5132def Test_extend_empty_class()
5133 var lines =<< trim END
5134 vim9script
5135 class A
5136 endclass
5137 class B extends A
5138 endclass
5139 class C extends B
5140 public static rw_class_var = 1
5141 public this.rw_obj_var = 2
5142 static def ClassMethod(): number
5143 return 3
5144 enddef
5145 def ObjMethod(): number
5146 return 4
5147 enddef
5148 endclass
5149 assert_equal(1, C.rw_class_var)
5150 assert_equal(3, C.ClassMethod())
5151 var c = C.new()
5152 assert_equal(2, c.rw_obj_var)
5153 assert_equal(4, c.ObjMethod())
5154 END
5155 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005156enddef
5157
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005158" A interface cannot have a static variable or a static method or a private
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005159" variable or a private method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005160def Test_interface_with_unsupported_members()
5161 var lines =<< trim END
5162 vim9script
5163 interface A
5164 static num: number
5165 endinterface
5166 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005167 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005168
5169 lines =<< trim END
5170 vim9script
5171 interface A
5172 static _num: number
5173 endinterface
5174 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005175 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005176
5177 lines =<< trim END
5178 vim9script
5179 interface A
5180 public static num: number
5181 endinterface
5182 END
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005183 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005184
5185 lines =<< trim END
5186 vim9script
5187 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005188 public static num: number
5189 endinterface
5190 END
5191 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface')
5192
5193 lines =<< trim END
5194 vim9script
5195 interface A
5196 static _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005197 endinterface
5198 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005199 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005200
5201 lines =<< trim END
5202 vim9script
5203 interface A
5204 static def Foo(d: dict<any>): list<string>
5205 endinterface
5206 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005207 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005208
5209 lines =<< trim END
5210 vim9script
5211 interface A
5212 static def _Foo(d: dict<any>): list<string>
5213 endinterface
5214 END
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005215 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005216
5217 lines =<< trim END
5218 vim9script
5219 interface A
5220 this._Foo: list<string>
5221 endinterface
5222 END
5223 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface')
5224
5225 lines =<< trim END
5226 vim9script
5227 interface A
5228 def _Foo(d: dict<any>): list<string>
5229 endinterface
5230 END
5231 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface')
5232enddef
5233
5234" Test for extending an interface
5235def Test_extend_interface()
5236 var lines =<< trim END
5237 vim9script
5238 interface A
5239 this.var1: list<string>
5240 def Foo()
5241 endinterface
5242 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005243 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005244 def Bar()
5245 endinterface
5246 class C implements A, B
5247 this.var1 = [1, 2]
5248 def Foo()
5249 enddef
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005250 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005251 def Bar()
5252 enddef
5253 endclass
5254 END
5255 v9.CheckSourceSuccess(lines)
5256
5257 lines =<< trim END
5258 vim9script
5259 interface A
5260 def Foo()
5261 endinterface
5262 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005263 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005264 endinterface
5265 class C implements A, B
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005266 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005267 endclass
5268 END
5269 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented')
5270
5271 lines =<< trim END
5272 vim9script
5273 interface A
5274 def Foo()
5275 endinterface
5276 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005277 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005278 endinterface
5279 class C implements A, B
5280 def Foo()
5281 enddef
5282 endclass
5283 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005284 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005285
5286 # interface cannot extend a class
5287 lines =<< trim END
5288 vim9script
5289 class A
5290 endclass
5291 interface B extends A
5292 endinterface
5293 END
5294 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5295
5296 # class cannot extend an interface
5297 lines =<< trim END
5298 vim9script
5299 interface A
5300 endinterface
5301 class B extends A
5302 endclass
5303 END
5304 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
5305
5306 # interface cannot implement another interface
5307 lines =<< trim END
5308 vim9script
5309 interface A
5310 endinterface
5311 interface B implements A
5312 endinterface
5313 END
5314 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"')
5315
5316 # interface cannot extend multiple interfaces
5317 lines =<< trim END
5318 vim9script
5319 interface A
5320 endinterface
5321 interface B
5322 endinterface
5323 interface C extends A, B
5324 endinterface
5325 END
5326 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B')
5327
5328 # Variable type in an extended interface is of different type
5329 lines =<< trim END
5330 vim9script
5331 interface A
5332 this.val1: number
5333 endinterface
5334 interface B extends A
5335 this.val2: string
5336 endinterface
5337 interface C extends B
5338 this.val1: string
5339 this.val2: number
5340 endinterface
5341 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005342 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005343enddef
5344
5345" Test for a child class implementing an interface when some of the methods are
5346" defined in the parent class.
5347def Test_child_class_implements_interface()
5348 var lines =<< trim END
5349 vim9script
5350
5351 interface Intf
5352 def F1(): list<list<number>>
5353 def F2(): list<list<number>>
5354 def F3(): list<list<number>>
5355 this.var1: list<dict<number>>
5356 this.var2: list<dict<number>>
5357 this.var3: list<dict<number>>
5358 endinterface
5359
5360 class A
5361 def A1()
5362 enddef
5363 def F3(): list<list<number>>
5364 return [[3]]
5365 enddef
5366 this.v1: list<list<number>> = [[0]]
5367 this.var3 = [{c: 30}]
5368 endclass
5369
5370 class B extends A
5371 def B1()
5372 enddef
5373 def F2(): list<list<number>>
5374 return [[2]]
5375 enddef
5376 this.v2: list<list<number>> = [[0]]
5377 this.var2 = [{b: 20}]
5378 endclass
5379
5380 class C extends B implements Intf
5381 def C1()
5382 enddef
5383 def F1(): list<list<number>>
5384 return [[1]]
5385 enddef
5386 this.v3: list<list<number>> = [[0]]
5387 this.var1 = [{a: 10}]
5388 endclass
5389
5390 def T(if: Intf)
5391 assert_equal([[1]], if.F1())
5392 assert_equal([[2]], if.F2())
5393 assert_equal([[3]], if.F3())
5394 assert_equal([{a: 10}], if.var1)
5395 assert_equal([{b: 20}], if.var2)
5396 assert_equal([{c: 30}], if.var3)
5397 enddef
5398
5399 var c = C.new()
5400 T(c)
5401 assert_equal([[1]], c.F1())
5402 assert_equal([[2]], c.F2())
5403 assert_equal([[3]], c.F3())
5404 assert_equal([{a: 10}], c.var1)
5405 assert_equal([{b: 20}], c.var2)
5406 assert_equal([{c: 30}], c.var3)
5407 END
5408 v9.CheckSourceSuccess(lines)
5409
5410 # One of the interface methods is not found
5411 lines =<< trim END
5412 vim9script
5413
5414 interface Intf
5415 def F1()
5416 def F2()
5417 def F3()
5418 endinterface
5419
5420 class A
5421 def A1()
5422 enddef
5423 endclass
5424
5425 class B extends A
5426 def B1()
5427 enddef
5428 def F2()
5429 enddef
5430 endclass
5431
5432 class C extends B implements Intf
5433 def C1()
5434 enddef
5435 def F1()
5436 enddef
5437 endclass
5438 END
5439 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented')
5440
5441 # One of the interface methods is of different type
5442 lines =<< trim END
5443 vim9script
5444
5445 interface Intf
5446 def F1()
5447 def F2()
5448 def F3()
5449 endinterface
5450
5451 class A
5452 def F3(): number
5453 return 0
5454 enddef
5455 def A1()
5456 enddef
5457 endclass
5458
5459 class B extends A
5460 def B1()
5461 enddef
5462 def F2()
5463 enddef
5464 endclass
5465
5466 class C extends B implements Intf
5467 def C1()
5468 enddef
5469 def F1()
5470 enddef
5471 endclass
5472 END
5473 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number')
5474
5475 # One of the interface variables is not present
5476 lines =<< trim END
5477 vim9script
5478
5479 interface Intf
5480 this.var1: list<dict<number>>
5481 this.var2: list<dict<number>>
5482 this.var3: list<dict<number>>
5483 endinterface
5484
5485 class A
5486 this.v1: list<list<number>> = [[0]]
5487 endclass
5488
5489 class B extends A
5490 this.v2: list<list<number>> = [[0]]
5491 this.var2 = [{b: 20}]
5492 endclass
5493
5494 class C extends B implements Intf
5495 this.v3: list<list<number>> = [[0]]
5496 this.var1 = [{a: 10}]
5497 endclass
5498 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005499 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005500
5501 # One of the interface variables is of different type
5502 lines =<< trim END
5503 vim9script
5504
5505 interface Intf
5506 this.var1: list<dict<number>>
5507 this.var2: list<dict<number>>
5508 this.var3: list<dict<number>>
5509 endinterface
5510
5511 class A
5512 this.v1: list<list<number>> = [[0]]
5513 this.var3: list<dict<string>>
5514 endclass
5515
5516 class B extends A
5517 this.v2: list<list<number>> = [[0]]
5518 this.var2 = [{b: 20}]
5519 endclass
5520
5521 class C extends B implements Intf
5522 this.v3: list<list<number>> = [[0]]
5523 this.var1 = [{a: 10}]
5524 endclass
5525 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005526 v9.CheckSourceFailure(lines, 'E1382: Variable "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005527enddef
5528
5529" Test for extending an interface with duplicate variables and methods
5530def Test_interface_extends_with_dup_members()
5531 var lines =<< trim END
5532 vim9script
5533 interface A
5534 this.n1: number
5535 def Foo1(): number
5536 endinterface
5537 interface B extends A
5538 this.n2: number
5539 this.n1: number
5540 def Foo2(): number
5541 def Foo1(): number
5542 endinterface
5543 class C implements B
5544 this.n1 = 10
5545 this.n2 = 20
5546 def Foo1(): number
5547 return 30
5548 enddef
5549 def Foo2(): number
5550 return 40
5551 enddef
5552 endclass
5553 def T1(a: A)
5554 assert_equal(10, a.n1)
5555 assert_equal(30, a.Foo1())
5556 enddef
5557 def T2(b: B)
5558 assert_equal(10, b.n1)
5559 assert_equal(20, b.n2)
5560 assert_equal(30, b.Foo1())
5561 assert_equal(40, b.Foo2())
5562 enddef
5563 var c = C.new()
5564 T1(c)
5565 T2(c)
5566 END
5567 v9.CheckSourceSuccess(lines)
5568enddef
5569
5570" Test for using "any" type for a variable in a sub-class while it has a
5571" concrete type in the interface
5572def Test_implements_using_var_type_any()
5573 var lines =<< trim END
5574 vim9script
5575 interface A
5576 this.val: list<dict<string>>
5577 endinterface
5578 class B implements A
5579 this.val = [{a: '1'}, {b: '2'}]
5580 endclass
5581 var b = B.new()
5582 assert_equal([{a: '1'}, {b: '2'}], b.val)
5583 END
5584 v9.CheckSourceSuccess(lines)
5585
5586 # initialize instance variable using a different type
5587 lines =<< trim END
5588 vim9script
5589 interface A
5590 this.val: list<dict<string>>
5591 endinterface
5592 class B implements A
5593 this.val = {a: 1, b: 2}
5594 endclass
5595 var b = B.new()
5596 END
RestorerZ7fe8f432023-09-24 23:21:24 +02005597 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>')
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005598enddef
5599
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005600" Test for assigning to a member variable in a nested class
5601def Test_nested_object_assignment()
5602 var lines =<< trim END
5603 vim9script
5604
5605 class A
5606 this.value: number
5607 endclass
5608
5609 class B
5610 this.a: A = A.new()
5611 endclass
5612
5613 class C
5614 this.b: B = B.new()
5615 endclass
5616
5617 class D
5618 this.c: C = C.new()
5619 endclass
5620
5621 def T(da: D)
5622 da.c.b.a.value = 10
5623 enddef
5624
5625 var d = D.new()
5626 T(d)
5627 END
Ernie Rael696270b2023-09-21 16:42:28 +02005628 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable')
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005629enddef
5630
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02005631" Test for calling methods using a null object
5632def Test_null_object_method_call()
5633 # Calling a object method using a null object in script context
5634 var lines =<< trim END
5635 vim9script
5636
5637 class C
5638 def Foo()
5639 assert_report('This method should not be executed')
5640 enddef
5641 endclass
5642
5643 var o: C
5644 o.Foo()
5645 END
5646 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
5647
5648 # Calling a object method using a null object in def function context
5649 lines =<< trim END
5650 vim9script
5651
5652 class C
5653 def Foo()
5654 assert_report('This method should not be executed')
5655 enddef
5656 endclass
5657
5658 def T()
5659 var o: C
5660 o.Foo()
5661 enddef
5662 T()
5663 END
5664 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5665
5666 # Calling a object method through another class method using a null object in
5667 # script context
5668 lines =<< trim END
5669 vim9script
5670
5671 class C
5672 def Foo()
5673 assert_report('This method should not be executed')
5674 enddef
5675
5676 static def Bar(o_any: any)
5677 var o_typed: C = o_any
5678 o_typed.Foo()
5679 enddef
5680 endclass
5681
5682 var o: C
5683 C.Bar(o)
5684 END
5685 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5686
5687 # Calling a object method through another class method using a null object in
5688 # def function context
5689 lines =<< trim END
5690 vim9script
5691
5692 class C
5693 def Foo()
5694 assert_report('This method should not be executed')
5695 enddef
5696
5697 static def Bar(o_any: any)
5698 var o_typed: C = o_any
5699 o_typed.Foo()
5700 enddef
5701 endclass
5702
5703 def T()
5704 var o: C
5705 C.Bar(o)
5706 enddef
5707 T()
5708 END
5709 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
5710enddef
5711
5712" Test for using a dict as an object member
5713def Test_dict_object_member()
5714 var lines =<< trim END
5715 vim9script
5716
5717 class Context
5718 public this.state: dict<number> = {}
5719 def GetState(): dict<number>
5720 return this.state
5721 enddef
5722 endclass
5723
5724 var ctx = Context.new()
5725 ctx.state->extend({a: 1})
5726 ctx.state['b'] = 2
5727 assert_equal({a: 1, b: 2}, ctx.GetState())
5728
5729 def F()
5730 ctx.state['c'] = 3
5731 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
5732 enddef
5733 F()
5734 assert_equal(3, ctx.state.c)
5735 ctx.state.c = 4
5736 assert_equal(4, ctx.state.c)
5737 END
5738 v9.CheckSourceSuccess(lines)
5739enddef
5740
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02005741" The following test was failing after 9.0.1914. This was caused by using a
5742" freed object from a previous method call.
5743def Test_freed_object_from_previous_method_call()
5744 var lines =<< trim END
5745 vim9script
5746
5747 class Context
5748 endclass
5749
5750 class Result
5751 endclass
5752
5753 def Failure(): Result
5754 return Result.new()
5755 enddef
5756
5757 def GetResult(ctx: Context): Result
5758 return Failure()
5759 enddef
5760
5761 def Test_GetResult()
5762 var ctx = Context.new()
5763 var result = GetResult(ctx)
5764 enddef
5765
5766 Test_GetResult()
5767 END
5768 v9.CheckSourceSuccess(lines)
5769enddef
5770
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005771" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker