blob: 65fa977d86df6b691538adadcf01eba08ab6b2a0 [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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02009 class NotWorking
10 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000011 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020012 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020016 vim9script
17 class notWorking
18 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000019 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020020 v9.CheckSourceFailure(lines, 'E1314: Class name must start with an uppercase letter: notWorking', 2)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020024 vim9script
25 class Not@working
26 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000027 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020028 v9.CheckSourceFailure(lines, 'E1315: White space required after name: Not@working', 2)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020032 vim9script
33 abstract noclass Something
34 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000035 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020036 v9.CheckSourceFailure(lines, 'E475: Invalid argument: noclass Something', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000037
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +010038 # Only the complete word "class" should be recognized
Bram Moolenaar00b28d62022-12-08 15:32:33 +000039 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020040 vim9script
41 abstract classy Something
42 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000043 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020044 v9.CheckSourceFailure(lines, 'E475: Invalid argument: classy Something', 2)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020048 vim9script
49 class Something
50 endcl
Bram Moolenaar00b28d62022-12-08 15:32:33 +000051 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020052 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endcl', 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020056 vim9script
57 class Something
58 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000059 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020060 v9.CheckSourceFailure(lines, "E488: Trailing characters: school's out", 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020064 vim9script
65 class Something
66 endclass | echo 'done'
Bram Moolenaar00b28d62022-12-08 15:32:33 +000067 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020068 v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020072 vim9script
73 class Something
74 this
75 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000076 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020077 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: this', 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020081 vim9script
82 class Something
83 this.
84 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000085 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020086 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: this.', 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020090 vim9script
91 class Something
92 this .count
93 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000094 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020095 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: this .count', 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020099 vim9script
100 class Something
101 this. count
102 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000103 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200104 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: this. count', 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200108 vim9script
109 class Something
110 this.count: number
111 that.count
112 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000113 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200114 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count', 4)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200118 vim9script
119 class Something
120 this.count
121 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000122 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200123 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200127 vim9script
128 class Something
129 def new()
130 this.state = 0
131 enddef
132 endclass
133 var obj = Something.new()
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000134 END
Ernie Raeld4802ec2023-10-20 11:59:00 +0200135 v9.CheckSourceFailure(lines, 'E1326: Variable "state" not found in object "Something"', 1)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200139 vim9script
140 class Something
141 this.count : number
142 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000143 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200144 v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: count : number', 3)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200148 vim9script
149 class Something
150 this.count:number
151 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000152 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200153 v9.CheckSourceFailure(lines, "E1069: White space required after ':'", 3)
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 Lakshmananb90e3bc2023-09-28 23:06:48 +0200163 v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 3)
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
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200173 v9.CheckSourceFailure(lines, 'E1319: Using a Class as a Number', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200174
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
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200184 v9.CheckSourceFailure(lines, 'E1320: Using an Object as a Number', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200185
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
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200193 v9.CheckSourceFailure(lines, 'E1321: Using a Class as a Float', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200194
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
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200203 v9.CheckSourceFailure(lines, 'E1322: Using an Object as a Float', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200204
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
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200212 v9.CheckSourceFailure(lines, 'E1323: Using a Class as a String', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200213
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
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200222 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200223
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200227 vim9script
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000228
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200229 class TextPosition
230 this.lnum: number
231 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000232
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200233 # make a nicely formatted string
234 def ToString(): string
235 return $'({this.lnum}, {this.col})'
236 enddef
237 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000238
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200239 # 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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200244 # call an object method
245 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000246
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200247 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 Lakshmananb90e3bc2023-09-28 23:06:48 +0200265 v9.CheckSourceFailure(lines, "E1202: No white space allowed after '.'", 8)
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 Lakshmananb90e3bc2023-09-28 23:06:48 +0200278 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a."', 8)
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 Lakshmananb90e3bc2023-09-28 23:06:48 +0200290 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a.Foo(,)"', 7)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200371 vim9script
372 class There
373 endclass
374 class There
375 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000376 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200377 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"', 4)
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000378
379 # one class, reload same script twice is OK
380 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200381 vim9script
382 class There
383 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000384 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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200393 vim9script
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000394
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200395 class BufferList
396 def Current(): any
397 return null_object
398 enddef
399 endclass
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000400
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200401 var buffers = BufferList.new()
402 echo buffers.Current()
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000403 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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200409 @_ = null_class.member
Bram Moolenaard13dd302023-03-11 20:56:35 +0000410 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200411 v9.CheckDefExecAndScriptFailure(lines, ['E715: Dictionary required', 'E1363: Incomplete type'])
Bram Moolenaard13dd302023-03-11 20:56:35 +0000412enddef
413
Bram Moolenaar657aea72023-01-27 13:16:19 +0000414def Test_class_interface_wrong_end()
415 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200416 vim9script
417 abstract class SomeName
418 this.member = 'text'
419 endinterface
Bram Moolenaar657aea72023-01-27 13:16:19 +0000420 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200421 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass', 4)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000422
423 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200424 vim9script
425 export interface AnotherName
426 this.member: string
427 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +0000428 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200429 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface', 4)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200435 vim9script
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000436
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200437 class State
438 this.value = 'xyz'
439 endclass
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000440
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200441 var state: State
442 var db = {'xyz': 789}
443 echo db[state.value]
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000444 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200445 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 9)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200449 vim9script
Bram Moolenaar0917e862023-02-18 14:42:44 +0000450
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200451 class Class
452 this.id: string
453 def Method1()
454 echo 'Method1' .. this.id
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000455 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200456 endclass
457
458 var obj: Class
459 def Func()
460 obj.Method1()
461 enddef
462 Func()
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000463 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200464 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200469 vim9script
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000470
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200471 class Background
472 this.background = 'dark'
473 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000474
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200475 class Colorscheme
476 this._bg: Background
Bram Moolenaar0917e862023-02-18 14:42:44 +0000477
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200478 def GetBackground(): string
479 return this._bg.background
480 enddef
481 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000482
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200483 var bg: Background # UNINITIALIZED
484 echo Colorscheme.new(bg).GetBackground()
Bram Moolenaar0917e862023-02-18 14:42:44 +0000485 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200486 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200490 vim9script
Ernie Raelf77a7f72023-03-03 15:05:30 +0000491
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200492 class Class
493 this.id: string
494 def Method1()
495 echo 'Method1' .. this.id
Ernie Raelf77a7f72023-03-03 15:05:30 +0000496 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200497 endclass
498
499 var obj = null_object
500 def Func()
501 obj.Method1()
502 enddef
503 Func()
Ernie Raelf77a7f72023-03-03 15:05:30 +0000504 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200505 v9.CheckSourceFailure(lines, 'E1363: Incomplete type', 1)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200552 vim9script
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000553
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200554 class TextPosition
555 this.lnum: number = 1
556 this.col: number = 1
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000557
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200558 # constructor with only the line number
559 def new(lnum: number)
560 this.lnum = lnum
561 enddef
562 endclass
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000563
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200564 var pos = TextPosition.new(3)
565 assert_equal(3, pos.lnum)
566 assert_equal(1, pos.col)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000567
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200568 var instr = execute('disassemble TextPosition.new')
569 assert_match('new\_s*' ..
570 '0 NEW TextPosition size \d\+\_s*' ..
571 '\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)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000582 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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200588 vim9script
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000589
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200590 class Inner
591 this.value: number = 0
592 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000593
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200594 class Outer
595 this.inner: any
596 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000597
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200598 def F(outer: Outer)
599 outer.inner.value = 1
600 enddef
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000601
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200602 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)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000606 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
Ernie Rael64885642023-10-04 20:16:22 +0200629 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_value" in class "Inner"', 1)
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
Ernie Raeld4802ec2023-10-20 11:59:00 +0200651 v9.CheckSourceFailure(lines, 'E1326: Variable "someval" not found in object "Inner"', 1)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200712 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 1)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200735 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 17)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200741 vim9script
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000742
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200743 class Foo
744 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000745
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200746 def Add(n: number)
747 this.x += n
Bram Moolenaar22363c62023-04-24 17:15:25 +0100748 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200749 endclass
Bram Moolenaar22363c62023-04-24 17:15:25 +0100750
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200751 var f = Foo.new(3)
752 f.Add(17)
753 assert_equal(20, f.x)
754
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200767 vim9script
Bram Moolenaarf4508042023-01-15 16:54:57 +0000768
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200769 class Foo
770 def Add()
Bram Moolenaarf4508042023-01-15 16:54:57 +0000771 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200772 endclass
Bram Moolenaarf4508042023-01-15 16:54:57 +0000773
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200774 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)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000782 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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200788 vim9script
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000789
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200790 class Something
791 this.label: string = ''
792 endclass
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000793
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200794 def Foo(): Something
795 var v = Something.new()
796 echo 'in Foo(): ' .. typename(v)
797 return v
798 enddef
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000799
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200800 Foo()
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000801 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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200807 vim9script
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000808
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200809 class TextPosition
810 this.lnum: number = 1
811 this.col: number = 1
812 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000813
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200814 var pos = TextPosition.new()
815 assert_equal(1, pos.lnum)
816 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000817
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200818 pos = TextPosition.new(v:none, v:none)
819 assert_equal(1, pos.lnum)
820 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000821
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200822 pos = TextPosition.new(3, 22)
823 assert_equal(3, pos.lnum)
824 assert_equal(22, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000825
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200826 pos = TextPosition.new(v:none, 33)
827 assert_equal(1, pos.lnum)
828 assert_equal(33, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000829 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200830 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000831
832 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200833 vim9script
834 class Person
835 this.name: string
836 this.age: number = 42
837 this.education: string = "unknown"
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000838
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200839 def new(this.name, this.age = v:none, this.education = v:none)
840 enddef
841 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000842
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200843 var piet = Person.new("Piet")
844 assert_equal("Piet", piet.name)
845 assert_equal(42, piet.age)
846 assert_equal("unknown", piet.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000847
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200848 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)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000852 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200853 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000854
855 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200856 vim9script
857 class Person
858 this.name: string
859 this.age: number = 42
860 this.education: string = "unknown"
Bram Moolenaar74e12742022-12-13 21:14:28 +0000861
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200862 def new(this.name, this.age = v:none, this.education = v:none)
863 enddef
864 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +0000865
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200866 var missing = Person.new()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000867 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200868 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 11)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200873 vim9script
874 class A
875 this.val: string
876 def new(this.val = 'a')
877 enddef
878 endclass
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200879 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200880 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'", 4)
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200885 vim9script
h-east2261c892023-08-16 21:49:54 +0900886
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200887 class C
888 this.str: string
889 this.num: number
890 def new(this.str, this.num)
h-east2261c892023-08-16 21:49:54 +0900891 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200892 def newVals(this.str, this.num)
893 enddef
894 endclass
h-east2261c892023-08-16 21:49:54 +0900895
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200896 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()
h-east2261c892023-08-16 21:49:54 +0900911 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200912 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900913
914 lines =<< trim END
h-eastdb385522023-09-28 22:18:19 +0200915 vim9script
916
917 class C
918 this.str: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200919 this.num: number
920 def new(this.str, this.num)
h-eastdb385522023-09-28 22:18:19 +0200921 enddef
922 endclass
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200923
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()
h-eastdb385522023-09-28 22:18:19 +0200933 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200934 v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 2)
h-eastdb385522023-09-28 22:18:19 +0200935
936 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200937 vim9script
h-eastb895b0f2023-09-24 15:46:31 +0200938
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200939 class C
940 this.str: string
941 this.num: number
942 def newVals(this.str, this.num)
h-eastb895b0f2023-09-24 15:46:31 +0200943 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200944 endclass
h-eastb895b0f2023-09-24 15:46:31 +0200945
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200946 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
956 v9.CheckSourceFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string', 2)
957
958 lines =<< trim END
959 vim9script
960
961 class C
962 this.str: string
963 def new(str: any)
964 enddef
965 endclass
966
967 def Check()
968 try
969 var c = C.new(1)
970 catch
971 assert_report($'Unexpected exception was caught: {v:exception}')
972 endtry
973 enddef
974
975 Check()
h-eastb895b0f2023-09-24 15:46:31 +0200976 END
977 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +0200978
979 # Try using "this." argument in a class method
980 lines =<< trim END
981 vim9script
982 class A
983 this.val = 10
984 static def Foo(this.val: number)
985 enddef
986 endclass
987 END
988 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
989
990 # Try using "this." argument in an object method
991 lines =<< trim END
992 vim9script
993 class A
994 this.val = 10
995 def Foo(this.val: number)
996 enddef
997 endclass
998 END
999 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
h-east2261c892023-08-16 21:49:54 +09001000enddef
1001
Bram Moolenaar74e12742022-12-13 21:14:28 +00001002def Test_class_object_member_inits()
1003 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001004 vim9script
1005 class TextPosition
1006 this.lnum: number
1007 this.col = 1
1008 this.addcol: number = 2
1009 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001010
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001011 var pos = TextPosition.new()
1012 assert_equal(0, pos.lnum)
1013 assert_equal(1, pos.col)
1014 assert_equal(2, pos.addcol)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001015 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001016 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001017
1018 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001019 vim9script
1020 class TextPosition
1021 this.lnum
1022 this.col = 1
1023 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001024 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001025 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001026
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001027 # If the type is not specified for a member, then it should be set during
1028 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +00001029 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001030 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001031
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001032 var init_count = 0
1033 def Init(): string
1034 init_count += 1
1035 return 'foo'
1036 enddef
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001037
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001038 class A
1039 this.str1 = Init()
1040 this.str2: string = Init()
1041 this.col = 1
1042 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001043
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001044 assert_equal(init_count, 0)
1045 var a = A.new()
1046 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001047 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001048 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001049
1050 # Test for initializing an object member with an unknown variable/type
1051 lines =<< trim END
1052 vim9script
1053 class A
1054 this.value = init_val
1055 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001056 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001057 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001058 v9.CheckSourceFailure(lines, 'E1001: Variable not found: init_val', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001059
1060 # Test for initializing an object member with an special type
1061 lines =<< trim END
1062 vim9script
1063 class A
1064 this.value: void
1065 endclass
1066 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001067 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001068enddef
1069
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001070" Test for instance variable access
1071def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001072 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001073 vim9script
1074 class Triple
1075 this._one = 1
1076 this.two = 2
1077 public this.three = 3
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001078
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001079 def GetOne(): number
1080 return this._one
1081 enddef
1082 endclass
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001083
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001084 var trip = Triple.new()
1085 assert_equal(1, trip.GetOne())
1086 assert_equal(2, trip.two)
1087 assert_equal(3, trip.three)
Ernie Rael64885642023-10-04 20:16:22 +02001088 assert_fails('echo trip._one', 'E1333: Cannot access private variable "_one" in class "Triple"')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001089
Ernie Rael64885642023-10-04 20:16:22 +02001090 assert_fails('trip._one = 11', 'E1333: Cannot access private variable "_one" in class "Triple"')
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001091 assert_fails('trip.two = 22', 'E1335: Variable "two" in class "Triple" is not writable')
1092 trip.three = 33
1093 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001094
Ernie Raeld4802ec2023-10-20 11:59:00 +02001095 assert_fails('trip.four = 4', 'E1326: Variable "four" not found in object "Triple"')
Bram Moolenaard505d172022-12-18 21:42:55 +00001096 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001097 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001098
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001099 # Test for a public member variable name beginning with an underscore
1100 lines =<< trim END
1101 vim9script
1102 class A
1103 public this._val = 10
1104 endclass
1105 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001106 v9.CheckSourceFailure(lines, 'E1332: Public variable name cannot start with underscore: public this._val = 10', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001107
Bram Moolenaar590162c2022-12-24 21:24:06 +00001108 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001109 vim9script
Bram Moolenaar590162c2022-12-24 21:24:06 +00001110
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001111 class MyCar
1112 this.make: string
1113 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001114
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001115 def new(make_arg: string)
1116 this.make = make_arg
Bram Moolenaar574950d2023-01-03 19:08:50 +00001117 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001118
1119 def GetMake(): string
1120 return $"make = {this.make}"
1121 enddef
1122 def GetAge(): number
1123 return this.age
1124 enddef
1125 endclass
1126
1127 var c = MyCar.new("abc")
1128 assert_equal('make = abc', c.GetMake())
1129
1130 c = MyCar.new("def")
1131 assert_equal('make = def', c.GetMake())
1132
1133 var c2 = MyCar.new("123")
1134 assert_equal('make = 123', c2.GetMake())
1135
1136 def CheckCar()
1137 assert_equal("make = def", c.GetMake())
1138 assert_equal(5, c.GetAge())
1139 enddef
1140 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001141 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001142 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001143
1144 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001145 vim9script
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001146
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001147 class MyCar
1148 this.make: string
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001149
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001150 def new(make_arg: string)
1151 this.make = make_arg
1152 enddef
1153 endclass
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001154
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001155 var c = MyCar.new("abc")
1156 var c = MyCar.new("def")
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001157 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001158 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "c"', 12)
Bram Moolenaarb149d222023-01-24 13:03:37 +00001159
1160 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001161 vim9script
Bram Moolenaarb149d222023-01-24 13:03:37 +00001162
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001163 class Foo
1164 this.x: list<number> = []
Bram Moolenaarb149d222023-01-24 13:03:37 +00001165
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001166 def Add(n: number): any
1167 this.x->add(n)
1168 return this
1169 enddef
1170 endclass
Bram Moolenaarb149d222023-01-24 13:03:37 +00001171
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001172 echo Foo.new().Add(1).Add(2).x
1173 echo Foo.new().Add(1).Add(2)
1174 .x
1175 echo Foo.new().Add(1)
1176 .Add(2).x
1177 echo Foo.new()
1178 .Add(1).Add(2).x
1179 echo Foo.new()
1180 .Add(1)
1181 .Add(2)
1182 .x
Bram Moolenaarb149d222023-01-24 13:03:37 +00001183 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001184 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001185
1186 # Test for "public" cannot be abbreviated
1187 lines =<< trim END
1188 vim9script
1189 class Something
1190 pub this.val = 1
1191 endclass
1192 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001193 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: pub this.val = 1', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001194
1195 # Test for "public" keyword must be followed by "this" or "static".
1196 lines =<< trim END
1197 vim9script
1198 class Something
1199 public val = 1
1200 endclass
1201 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001202 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001203
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001204 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001205 lines =<< trim END
1206 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001207 class A
1208 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001209 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001210 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001211 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001212 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001213
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001214 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001215 lines =<< trim END
1216 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001217 class A
1218 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001219 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001220 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001221 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001222 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001223
1224 # Modify a instance variable using the class name in a def function
1225 lines =<< trim END
1226 vim9script
1227 class A
1228 public this.val = 1
1229 endclass
1230 def T()
1231 A.val = 1
1232 enddef
1233 T()
1234 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001235 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001236
1237 # Read a instance variable using the class name in a def function
1238 lines =<< trim END
1239 vim9script
1240 class A
1241 public this.val = 1
1242 endclass
1243 def T()
1244 var i = A.val
1245 enddef
1246 T()
1247 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001248 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Ernie Raelcf138d42023-09-06 20:45:03 +02001249
1250 # Access from child class extending a class:
1251 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001252 vim9script
1253 class A
1254 this.ro_obj_var = 10
1255 public this.rw_obj_var = 20
1256 this._priv_obj_var = 30
1257 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001258
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001259 class B extends A
1260 def Foo()
1261 var x: number
1262 x = this.ro_obj_var
1263 this.ro_obj_var = 0
1264 x = this.rw_obj_var
1265 this.rw_obj_var = 0
1266 x = this._priv_obj_var
1267 this._priv_obj_var = 0
1268 enddef
1269 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001270
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001271 var b = B.new()
1272 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001273 END
1274 v9.CheckSourceSuccess(lines)
1275enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001276
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001277" Test for class variable access
1278def Test_class_variable_access()
1279 # Test for "static" cannot be abbreviated
1280 var lines =<< trim END
1281 vim9script
1282 class Something
1283 stat this.val = 1
1284 endclass
1285 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001286 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: stat this.val = 1', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001287
1288 # Test for "static" cannot be followed by "this".
1289 lines =<< trim END
1290 vim9script
1291 class Something
1292 static this.val = 1
1293 endclass
1294 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001295 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a variable name', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001296
1297 # Test for "static" cannot be followed by "public".
1298 lines =<< trim END
1299 vim9script
1300 class Something
1301 static public val = 1
1302 endclass
1303 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001304 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001305
1306 # A readonly class variable cannot be modified from a child class
1307 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001308 vim9script
1309 class A
1310 static ro_class_var = 40
1311 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001312
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001313 class B extends A
1314 def Foo()
1315 A.ro_class_var = 50
1316 enddef
1317 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001318
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001319 var b = B.new()
1320 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001321 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001322 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001323
1324 # A private class variable cannot be accessed from a child class
1325 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001326 vim9script
1327 class A
1328 static _priv_class_var = 60
1329 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001330
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001331 class B extends A
1332 def Foo()
1333 var i = A._priv_class_var
1334 enddef
1335 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001336
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001337 var b = B.new()
1338 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001339 END
Ernie Rael64885642023-10-04 20:16:22 +02001340 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001341
1342 # A private class variable cannot be modified from a child class
1343 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001344 vim9script
1345 class A
1346 static _priv_class_var = 60
1347 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001348
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001349 class B extends A
1350 def Foo()
1351 A._priv_class_var = 0
1352 enddef
1353 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001354
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001355 var b = B.new()
1356 b.Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001357 END
Ernie Rael64885642023-10-04 20:16:22 +02001358 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001359
1360 # Access from child class extending a class and from script context
1361 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001362 vim9script
1363 class A
1364 static ro_class_var = 10
1365 public static rw_class_var = 20
1366 static _priv_class_var = 30
1367 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001368
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001369 class B extends A
1370 def Foo()
1371 var x: number
1372 x = A.ro_class_var
1373 assert_equal(10, x)
1374 x = A.rw_class_var
1375 assert_equal(25, x)
1376 A.rw_class_var = 20
1377 assert_equal(20, A.rw_class_var)
1378 enddef
1379 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001380
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001381 assert_equal(10, A.ro_class_var)
1382 assert_equal(20, A.rw_class_var)
1383 A.rw_class_var = 25
1384 assert_equal(25, A.rw_class_var)
1385 var b = B.new()
1386 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001387 END
1388 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001389enddef
1390
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001391def Test_class_object_compare()
1392 var class_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001393 vim9script
1394 class Item
1395 this.nr = 0
1396 this.name = 'xx'
1397 endclass
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001398 END
1399
1400 # used at the script level and in a compiled function
1401 var test_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001402 var i1 = Item.new()
1403 assert_equal(i1, i1)
1404 assert_true(i1 is i1)
1405 var i2 = Item.new()
1406 assert_equal(i1, i2)
1407 assert_false(i1 is i2)
1408 var i3 = Item.new(0, 'xx')
1409 assert_equal(i1, i3)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001410
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001411 var io1 = Item.new(1, 'xx')
1412 assert_notequal(i1, io1)
1413 var io2 = Item.new(0, 'yy')
1414 assert_notequal(i1, io2)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001415 END
1416
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001417 v9.CheckSourceSuccess(class_lines + test_lines)
1418 v9.CheckSourceSuccess(
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001419 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001420
1421 for op in ['>', '>=', '<', '<=', '=~', '!~']
1422 var op_lines = [
1423 'var i1 = Item.new()',
1424 'var i2 = Item.new()',
1425 'echo i1 ' .. op .. ' i2',
1426 ]
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001427 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object', 8)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001428 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001429 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001430 endfor
1431enddef
1432
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001433def Test_object_type()
1434 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001435 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001436
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001437 class One
1438 this.one = 1
1439 endclass
1440 class Two
1441 this.two = 2
1442 endclass
1443 class TwoMore extends Two
1444 this.more = 9
1445 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001446
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001447 var o: One = One.new()
1448 var t: Two = Two.new()
1449 var m: TwoMore = TwoMore.new()
1450 var tm: Two = TwoMore.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001451
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001452 t = m
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001453 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001454 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001455
1456 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001457 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001458
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001459 class One
1460 this.one = 1
1461 endclass
1462 class Two
1463 this.two = 2
1464 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001465
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001466 var o: One = Two.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001467 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001468 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>', 10)
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001469
1470 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001471 vim9script
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001472
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001473 interface One
1474 def GetMember(): number
1475 endinterface
1476 class Two implements One
1477 this.one = 1
1478 def GetMember(): number
1479 return this.one
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001480 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001481 endclass
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001482
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001483 var o: One = Two.new(5)
1484 assert_equal(5, o.GetMember())
1485 END
1486 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001487
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001488 lines =<< trim END
1489 vim9script
1490
1491 class Num
1492 this.n: number = 0
1493 endclass
1494
1495 def Ref(name: string): func(Num): Num
1496 return (arg: Num): Num => {
1497 return eval(name)(arg)
1498 }
1499 enddef
1500
1501 const Fn = Ref('Double')
1502 var Double = (m: Num): Num => Num.new(m.n * 2)
1503
1504 echo Fn(Num.new(4))
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001505 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001506 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001507enddef
1508
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001509def Test_class_member()
1510 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001511 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001512 vim9script
1513 class TextPos
1514 this.lnum = 1
1515 this.col = 1
1516 static counter = 0
1517 static _secret = 7
1518 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001519
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001520 static def AddToCounter(nr: number)
1521 counter += nr
1522 enddef
1523 endclass
Bram Moolenaard505d172022-12-18 21:42:55 +00001524
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001525 assert_equal(0, TextPos.counter)
1526 TextPos.AddToCounter(3)
1527 assert_equal(3, TextPos.counter)
1528 assert_fails('echo TextPos.noSuchMember', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001529
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001530 def GetCounter(): number
1531 return TextPos.counter
1532 enddef
1533 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001534
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001535 assert_fails('TextPos.noSuchMember = 2', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
1536 assert_fails('TextPos.counter = 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
1537 assert_fails('TextPos.counter += 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001538
Ernie Rael64885642023-10-04 20:16:22 +02001539 assert_fails('echo TextPos._secret', 'E1333: Cannot access private variable "_secret" in class "TextPos"')
1540 assert_fails('TextPos._secret = 8', 'E1333: Cannot access private variable "_secret" in class "TextPos"')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001541
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001542 assert_equal(42, TextPos.anybody)
1543 TextPos.anybody = 12
1544 assert_equal(12, TextPos.anybody)
1545 TextPos.anybody += 5
1546 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001547 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001548 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001549
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001550 # example in the help
1551 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001552 vim9script
1553 class OtherThing
1554 this.size: number
1555 static totalSize: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001556
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001557 def new(this.size)
1558 totalSize += this.size
1559 enddef
1560 endclass
1561 assert_equal(0, OtherThing.totalSize)
1562 var to3 = OtherThing.new(3)
1563 assert_equal(3, OtherThing.totalSize)
1564 var to7 = OtherThing.new(7)
1565 assert_equal(10, OtherThing.totalSize)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001566 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001567 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001568
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001569 # using static class member twice
1570 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001571 vim9script
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001572
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001573 class HTML
1574 static author: string = 'John Doe'
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001575
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001576 static def MacroSubstitute(s: string): string
1577 return substitute(s, '{{author}}', author, 'gi')
1578 enddef
1579 endclass
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001580
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001581 assert_equal('some text', HTML.MacroSubstitute('some text'))
1582 assert_equal('some text', HTML.MacroSubstitute('some text'))
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001583 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001584 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001585
Bram Moolenaar62a69232023-01-24 15:07:04 +00001586 # access private member in lambda
1587 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001588 vim9script
Bram Moolenaar62a69232023-01-24 15:07:04 +00001589
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001590 class Foo
1591 this._x: number = 0
Bram Moolenaar62a69232023-01-24 15:07:04 +00001592
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001593 def Add(n: number): number
1594 const F = (): number => this._x + n
1595 return F()
1596 enddef
1597 endclass
Bram Moolenaar62a69232023-01-24 15:07:04 +00001598
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001599 var foo = Foo.new()
1600 assert_equal(5, foo.Add(5))
Bram Moolenaar62a69232023-01-24 15:07:04 +00001601 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001602 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001603
h-east2bd6a092023-05-19 19:01:17 +01001604 # access private member in lambda body
1605 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001606 vim9script
h-east2bd6a092023-05-19 19:01:17 +01001607
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001608 class Foo
1609 this._x: number = 6
h-east2bd6a092023-05-19 19:01:17 +01001610
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001611 def Add(n: number): number
1612 var Lam = () => {
1613 this._x = this._x + n
1614 }
1615 Lam()
1616 return this._x
1617 enddef
1618 endclass
h-east2bd6a092023-05-19 19:01:17 +01001619
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001620 var foo = Foo.new()
1621 assert_equal(13, foo.Add(7))
h-east2bd6a092023-05-19 19:01:17 +01001622 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001623 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001624
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001625 # check shadowing
1626 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001627 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001628
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001629 class Some
1630 static count = 0
1631 def Method(count: number)
1632 echo count
1633 enddef
1634 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001635
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001636 var s = Some.new()
1637 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001638 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001639 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001640
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001641 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001642 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001643 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001644
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001645 class Some
1646 static count = 0
1647 def Method(arg: number)
1648 var count = 3
1649 echo arg count
1650 enddef
1651 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001652
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001653 var s = Some.new()
1654 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001655 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001656 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001657
1658 # Test for using an invalid type for a member variable
1659 lines =<< trim END
1660 vim9script
1661 class A
1662 this.val: xxx
1663 endclass
1664 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001665 v9.CheckSourceFailure(lines, 'E1010: Type not recognized: xxx', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001666
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001667 # Test for setting a member on a null object
1668 lines =<< trim END
1669 vim9script
1670 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001671 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001672 endclass
1673
1674 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001675 var obj: A
1676 obj.val = ""
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001677 enddef
1678 F()
1679 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001680 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001681
1682 # Test for accessing a member on a null object
1683 lines =<< trim END
1684 vim9script
1685 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001686 this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001687 endclass
1688
1689 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001690 var obj: A
1691 echo obj.val
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001692 enddef
1693 F()
1694 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001695 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001696
1697 # Test for setting a member on a null object, at script level
1698 lines =<< trim END
1699 vim9script
1700 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001701 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001702 endclass
1703
1704 var obj: A
1705 obj.val = ""
1706 END
Ernie Rael4c8da022023-10-11 21:35:11 +02001707 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001708
1709 # Test for accessing a member on a null object, at script level
1710 lines =<< trim END
1711 vim9script
1712 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001713 this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001714 endclass
1715
1716 var obj: A
1717 echo obj.val
1718 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001719 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001720
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001721 # Test for no space before or after the '=' when initializing a member
1722 # variable
1723 lines =<< trim END
1724 vim9script
1725 class A
1726 this.val: number= 10
1727 endclass
1728 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001729 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001730 lines =<< trim END
1731 vim9script
1732 class A
1733 this.val: number =10
1734 endclass
1735 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001736 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001737
1738 # Access a non-existing member
1739 lines =<< trim END
1740 vim9script
1741 class A
1742 endclass
1743 var a = A.new()
1744 var v = a.bar
1745 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02001746 v9.CheckSourceFailure(lines, 'E1326: Variable "bar" not found in object "A"', 5)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001747enddef
1748
Ernie Raele6c9aa52023-10-06 19:55:52 +02001749" These messages should show the defining class of the variable (base class),
1750" not the class that did the reference (super class)
1751def Test_defining_class_message()
1752 var lines =<< trim END
1753 vim9script
1754
1755 class Base
1756 this._v1: list<list<number>>
1757 endclass
1758
1759 class Child extends Base
1760 endclass
1761
1762 var o = Child.new()
1763 var x = o._v1
1764 END
1765 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Base"', 11)
1766 lines =<< trim END
1767 vim9script
1768
1769 class Base
1770 this._v1: list<list<number>>
1771 endclass
1772
1773 class Child extends Base
1774 endclass
1775
1776 def F()
1777 var o = Child.new()
1778 var x = o._v1
1779 enddef
1780 F()
1781 END
1782 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Base"', 2)
1783 lines =<< trim END
1784 vim9script
1785
1786 class Base
1787 this.v1: list<list<number>>
1788 endclass
1789
1790 class Child extends Base
1791 endclass
1792
1793 var o = Child.new()
1794 o.v1 = []
1795 END
1796 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 11)
1797 lines =<< trim END
1798 vim9script
1799
1800 class Base
1801 this.v1: list<list<number>>
1802 endclass
1803
1804 class Child extends Base
1805 endclass
1806
1807 def F()
1808 var o = Child.new()
1809 o.v1 = []
1810 enddef
1811 F()
1812 END
1813
1814 # Attempt to read a private variable that is in the middle
1815 # of the class hierarchy.
1816 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 2)
1817 lines =<< trim END
1818 vim9script
1819
1820 class Base0
1821 endclass
1822
1823 class Base extends Base0
1824 this._v1: list<list<number>>
1825 endclass
1826
1827 class Child extends Base
1828 endclass
1829
1830 def F()
1831 var o = Child.new()
1832 var x = o._v1
1833 enddef
1834 F()
1835 END
1836 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Base"', 2)
1837
1838 # Attempt to read a private variable that is at the start
1839 # of the class hierarchy.
1840 lines =<< trim END
1841 vim9script
1842
1843 class Base0
1844 endclass
1845
1846 class Base extends Base0
1847 endclass
1848
1849 class Child extends Base
1850 this._v1: list<list<number>>
1851 endclass
1852
1853 def F()
1854 var o = Child.new()
1855 var x = o._v1
1856 enddef
1857 F()
1858 END
1859 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Child"', 2)
1860enddef
1861
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001862func Test_class_garbagecollect()
1863 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001864 vim9script
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001865
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001866 class Point
1867 this.p = [2, 3]
1868 static pl = ['a', 'b']
1869 static pd = {a: 'a', b: 'b'}
1870 endclass
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001871
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001872 echo Point.pl Point.pd
1873 call test_garbagecollect_now()
1874 echo Point.pl Point.pd
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001875 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001876 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001877
1878 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001879 vim9script
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001880
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001881 interface View
1882 endinterface
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001883
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001884 class Widget
1885 this.view: View
1886 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001887
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001888 class MyView implements View
1889 this.widget: Widget
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001890
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001891 def new()
1892 # this will result in a circular reference to this object
1893 this.widget = Widget.new(this)
1894 enddef
1895 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001896
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001897 var view = MyView.new()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001898
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001899 # overwrite "view", will be garbage-collected next
1900 view = MyView.new()
1901 test_garbagecollect_now()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001902 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001903 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001904endfunc
1905
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001906" Test interface garbage collection
1907func Test_interface_garbagecollect()
1908 let lines =<< trim END
1909 vim9script
1910
1911 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001912 this.ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001913
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001914 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001915 endinterface
1916
1917 class A implements I
1918 static ro_class_var: number = 10
1919 public static rw_class_var: number = 20
1920 static _priv_class_var: number = 30
1921 this.ro_obj_var: number = 40
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001922 this._priv_obj_var: number = 60
1923
1924 static def _ClassBar(): number
1925 return _priv_class_var
1926 enddef
1927
1928 static def ClassFoo(): number
1929 return ro_class_var + rw_class_var + A._ClassBar()
1930 enddef
1931
1932 def _ObjBar(): number
1933 return this._priv_obj_var
1934 enddef
1935
1936 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001937 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001938 enddef
1939 endclass
1940
1941 assert_equal(60, A.ClassFoo())
1942 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001943 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001944 test_garbagecollect_now()
1945 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001946 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001947 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001948 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001949endfunc
1950
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001951def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001952 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001953 vim9script
1954 class Value
1955 this.value = 0
1956 static objects = 0
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001957
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001958 def new(v: number)
1959 this.value = v
1960 ++objects
1961 enddef
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001962
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001963 static def GetCount(): number
1964 return objects
1965 enddef
1966 endclass
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001967
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001968 assert_equal(0, Value.GetCount())
1969 var v1 = Value.new(2)
1970 assert_equal(1, Value.GetCount())
1971 var v2 = Value.new(7)
1972 assert_equal(2, Value.GetCount())
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001973 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001974 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001975
1976 # Test for cleaning up after a class definition failure when using class
1977 # functions.
1978 lines =<< trim END
1979 vim9script
1980 class A
1981 static def Foo()
1982 enddef
1983 aaa
1984 endclass
1985 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001986 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: aaa', 5)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001987
1988 # Test for calling a class method from another class method without the class
1989 # name prefix.
1990 lines =<< trim END
1991 vim9script
1992 class A
1993 static myList: list<number> = [1]
1994 static def Foo(n: number)
1995 myList->add(n)
1996 enddef
1997 static def Bar()
1998 Foo(2)
1999 enddef
2000 def Baz()
2001 Foo(3)
2002 enddef
2003 endclass
2004 A.Bar()
2005 var a = A.new()
2006 a.Baz()
2007 assert_equal([1, 2, 3], A.myList)
2008 END
2009 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002010enddef
2011
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002012def Test_class_defcompile()
2013 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002014 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002015
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002016 class C
2017 def Fo(i: number): string
2018 return i
2019 enddef
2020 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002021
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002022 defcompile C.Fo
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002023 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002024 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number', 1)
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002025
2026 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002027 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002028
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002029 class C
2030 static def Fc(): number
2031 return 'x'
2032 enddef
2033 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002034
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002035 defcompile C.Fc
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002036 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002037 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002038
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002039 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002040 vim9script
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002041
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002042 class C
2043 static def new()
2044 enddef
2045 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002046
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002047 defcompile C.new
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002048 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002049 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static', 5)
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002050
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002051 # Trying to compile a function using a non-existing class variable
2052 lines =<< trim END
2053 vim9script
2054 defcompile x.Foo()
2055 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002056 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002057
2058 # Trying to compile a function using a variable which is not a class
2059 lines =<< trim END
2060 vim9script
2061 var x: number
2062 defcompile x.Foo()
2063 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002064 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002065
2066 # Trying to compile a function without specifying the name
2067 lines =<< trim END
2068 vim9script
2069 class A
2070 endclass
2071 defcompile A.
2072 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002073 v9.CheckSourceFailure(lines, 'E475: Invalid argument: A.', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002074
2075 # Trying to compile a non-existing class object member function
2076 lines =<< trim END
2077 vim9script
2078 class A
2079 endclass
2080 var a = A.new()
2081 defcompile a.Foo()
2082 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02002083 v9.CheckSourceFailureList(lines, ['E1326: Variable "Foo" not found in object "A"', 'E475: Invalid argument: a.Foo()'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002084enddef
2085
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002086def Test_class_object_to_string()
2087 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002088 vim9script
2089 class TextPosition
2090 this.lnum = 1
2091 this.col = 22
2092 endclass
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002093
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002094 assert_equal("class TextPosition", string(TextPosition))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002095
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002096 var pos = TextPosition.new()
2097 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002098 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002099 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002100enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00002101
Bram Moolenaar554d0312023-01-05 19:59:18 +00002102def Test_interface_basics()
2103 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002104 vim9script
2105 interface Something
2106 this.ro_var: list<number>
2107 def GetCount(): number
2108 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002109 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002110 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002111
2112 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002113 interface SomethingWrong
2114 static count = 7
2115 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002116 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002117 v9.CheckSourceFailure(lines, 'E1342: Interface can only be defined in Vim9 script', 1)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002118
2119 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002120 vim9script
Bram Moolenaar554d0312023-01-05 19:59:18 +00002121
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002122 interface Some
2123 this.value: number
2124 def Method(value: number)
2125 endinterface
Bram Moolenaard40f00c2023-01-13 17:36:49 +00002126 END
h-east61378a12023-04-18 19:07:29 +01002127 # The argument name and the object member name are the same, but this is not a
2128 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002129 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002130
2131 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002132 vim9script
2133 interface somethingWrong
2134 static count = 7
2135 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002136 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002137 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong', 2)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002138
2139 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002140 vim9script
2141 interface SomethingWrong
2142 this.value: string
2143 this.count = 7
2144 def GetCount(): number
2145 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002146 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002147 v9.CheckSourceFailure(lines, 'E1344: Cannot initialize a variable in an interface', 4)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002148
2149 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002150 vim9script
2151 interface SomethingWrong
2152 this.value: string
2153 this.count: number
2154 def GetCount(): number
2155 return 5
2156 enddef
2157 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002158 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002159 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5', 6)
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002160
2161 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002162 vim9script
2163 export interface EnterExit
2164 def Enter(): void
2165 def Exit(): void
2166 endinterface
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002167 END
2168 writefile(lines, 'XdefIntf.vim', 'D')
2169
2170 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002171 vim9script
2172 import './XdefIntf.vim' as defIntf
2173 export def With(ee: defIntf.EnterExit, F: func)
2174 ee.Enter()
2175 try
2176 F()
2177 finally
2178 ee.Exit()
2179 endtry
2180 enddef
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002181 END
2182 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002183
2184 var imported =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002185 vim9script
2186 export abstract class EnterExit
2187 def Enter(): void
2188 enddef
2189 def Exit(): void
2190 enddef
2191 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +00002192 END
2193 writefile(imported, 'XdefIntf2.vim', 'D')
2194
2195 lines[1] = " import './XdefIntf2.vim' as defIntf"
2196 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002197enddef
2198
Bram Moolenaar94674f22023-01-06 18:42:20 +00002199def Test_class_implements_interface()
2200 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002201 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002202
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002203 interface Some
2204 this.count: number
2205 def Method(nr: number)
2206 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002207
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002208 class SomeImpl implements Some
2209 this.count: number
2210 def Method(nr: number)
2211 echo nr
2212 enddef
2213 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002214
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002215 interface Another
2216 this.member: string
2217 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002218
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002219 class AnotherImpl implements Some, Another
2220 this.member = 'abc'
2221 this.count = 20
2222 def Method(nr: number)
2223 echo nr
2224 enddef
2225 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002226 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002227 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002228
2229 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002230 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002231
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002232 interface Some
2233 this.count: number
2234 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002235
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002236 class SomeImpl implements Some implements Some
2237 this.count: number
2238 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002239 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002240 v9.CheckSourceFailure(lines, 'E1350: Duplicate "implements"', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002241
2242 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002243 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002244
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002245 interface Some
2246 this.count: number
2247 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002248
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002249 class SomeImpl implements Some, Some
2250 this.count: number
2251 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002252 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002253 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002254
2255 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002256 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002257
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002258 interface Some
2259 this.counter: number
2260 def Method(nr: number)
2261 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002262
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002263 class SomeImpl implements Some
2264 this.count: number
2265 def Method(nr: number)
2266 echo nr
2267 enddef
2268 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002269 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002270 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented', 13)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002271
2272 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002273 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002274
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002275 interface Some
2276 this.count: number
2277 def Methods(nr: number)
2278 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002279
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002280 class SomeImpl implements Some
2281 this.count: number
2282 def Method(nr: number)
2283 echo nr
2284 enddef
2285 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002286 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002287 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented', 13)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002288
2289 # Check different order of members in class and interface works.
2290 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002291 vim9script
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002292
2293 interface Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002294 this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002295 this.errpos: number
2296 endinterface
2297
2298 # order of members is opposite of interface
2299 class Failure implements Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002300 public this.lnum: number = 5
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002301 this.errpos: number = 42
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002302 this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002303 endclass
2304
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002305 def Test()
2306 var result: Result = Failure.new()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002307
2308 assert_equal('label', result.label)
2309 assert_equal(42, result.errpos)
2310 enddef
2311
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002312 Test()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002313 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002314 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002315
2316 # Interface name after "extends" doesn't end in a space or NUL character
2317 lines =<< trim END
2318 vim9script
2319 interface A
2320 endinterface
2321 class B extends A"
2322 endclass
2323 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002324 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002325
2326 # Trailing characters after a class name
2327 lines =<< trim END
2328 vim9script
2329 class A bbb
2330 endclass
2331 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002332 v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002333
2334 # using "implements" with a non-existing class
2335 lines =<< trim END
2336 vim9script
2337 class A implements B
2338 endclass
2339 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002340 v9.CheckSourceFailure(lines, 'E1346: Interface name not found: B', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002341
2342 # using "implements" with a regular class
2343 lines =<< trim END
2344 vim9script
2345 class A
2346 endclass
2347 class B implements A
2348 endclass
2349 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002350 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: A', 5)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002351
2352 # using "implements" with a variable
2353 lines =<< trim END
2354 vim9script
2355 var T: number = 10
2356 class A implements T
2357 endclass
2358 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002359 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: T', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002360
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002361 # implements should be followed by a white space
2362 lines =<< trim END
2363 vim9script
2364 interface A
2365 endinterface
2366 class B implements A;
2367 endclass
2368 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002369 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A;', 4)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002370
LemonBoyc5d27442023-08-19 13:02:35 +02002371 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002372 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002373
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002374 interface One
2375 def IsEven(nr: number): bool
2376 endinterface
2377 class Two implements One
2378 def IsEven(nr: number): string
2379 enddef
2380 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002381 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002382 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002383
2384 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002385 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002386
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002387 interface One
2388 def IsEven(nr: number): bool
2389 endinterface
2390 class Two implements One
2391 def IsEven(nr: bool): bool
2392 enddef
2393 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002394 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002395 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002396
2397 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002398 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002399
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002400 interface One
2401 def IsEven(nr: number): bool
2402 endinterface
2403 class Two implements One
2404 def IsEven(nr: number, ...extra: list<number>): bool
2405 enddef
2406 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002407 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002408 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool', 9)
Ernie Raelcf138d42023-09-06 20:45:03 +02002409
2410 # access superclass interface members from subclass, mix variable order
2411 lines =<< trim END
2412 vim9script
2413
2414 interface I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002415 this.mvar1: number
2416 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002417 endinterface
2418
2419 # NOTE: the order is swapped
2420 class A implements I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002421 this.mvar2: number
2422 this.mvar1: number
2423 public static svar2: number
2424 public static svar1: number
2425 def new()
2426 svar1 = 11
2427 svar2 = 12
2428 this.mvar1 = 111
2429 this.mvar2 = 112
2430 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002431 endclass
2432
2433 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002434 def new()
2435 this.mvar1 = 121
2436 this.mvar2 = 122
2437 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002438 endclass
2439
2440 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002441 def new()
2442 this.mvar1 = 131
2443 this.mvar2 = 132
2444 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002445 endclass
2446
Ernie Raelcf138d42023-09-06 20:45:03 +02002447 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002448 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002449 enddef
2450
2451 var oa = A.new()
2452 var ob = B.new()
2453 var oc = C.new()
2454
Ernie Raelcf138d42023-09-06 20:45:03 +02002455 assert_equal([111, 112], F2(oa))
2456 assert_equal([121, 122], F2(ob))
2457 assert_equal([131, 132], F2(oc))
2458 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002459 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002460
2461 # Access superclass interface members from subclass, mix variable order.
2462 # Two interfaces, one on A, one on B; each has both kinds of variables
2463 lines =<< trim END
2464 vim9script
2465
2466 interface I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002467 this.mvar1: number
2468 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002469 endinterface
2470
2471 interface I2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002472 this.mvar3: number
2473 this.mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002474 endinterface
2475
2476 class A implements I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002477 public static svar1: number
2478 public static svar2: number
2479 this.mvar1: number
2480 this.mvar2: number
2481 def new()
2482 svar1 = 11
2483 svar2 = 12
2484 this.mvar1 = 111
2485 this.mvar2 = 112
2486 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002487 endclass
2488
2489 class B extends A implements I2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002490 static svar3: number
2491 static svar4: number
2492 this.mvar3: number
2493 this.mvar4: number
2494 def new()
2495 svar3 = 23
2496 svar4 = 24
2497 this.mvar1 = 121
2498 this.mvar2 = 122
2499 this.mvar3 = 123
2500 this.mvar4 = 124
2501 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002502 endclass
2503
2504 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002505 public static svar5: number
2506 def new()
2507 svar5 = 1001
2508 this.mvar1 = 131
2509 this.mvar2 = 132
2510 this.mvar3 = 133
2511 this.mvar4 = 134
2512 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002513 endclass
2514
Ernie Raelcf138d42023-09-06 20:45:03 +02002515 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002516 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002517 enddef
2518
Ernie Raelcf138d42023-09-06 20:45:03 +02002519 def F4(i: I2): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002520 return [ i.mvar3, i.mvar4 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002521 enddef
2522
Ernie Raelcf138d42023-09-06 20:45:03 +02002523 var oa = A.new()
2524 var ob = B.new()
2525 var oc = C.new()
2526
Ernie Raelcf138d42023-09-06 20:45:03 +02002527 assert_equal([[111, 112]], [F2(oa)])
2528 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2529 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002530 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002531 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002532
2533 # Using two interface names without a space after the ","
2534 lines =<< trim END
2535 vim9script
2536 interface A
2537 endinterface
2538 interface B
2539 endinterface
2540 class C implements A,B
2541 endclass
2542 END
2543 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2544
2545 # No interface name after a comma
2546 lines =<< trim END
2547 vim9script
2548 interface A
2549 endinterface
2550 class B implements A,
2551 endclass
2552 END
2553 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2554
2555 # No interface name after implements
2556 lines =<< trim END
2557 vim9script
2558 class A implements
2559 endclass
2560 END
2561 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002562enddef
2563
Bram Moolenaard0200c82023-01-28 15:19:40 +00002564def Test_call_interface_method()
2565 var lines =<< trim END
2566 vim9script
2567 interface Base
2568 def Enter(): void
2569 endinterface
2570
2571 class Child implements Base
2572 def Enter(): void
2573 g:result ..= 'child'
2574 enddef
2575 endclass
2576
2577 def F(obj: Base)
2578 obj.Enter()
2579 enddef
2580
2581 g:result = ''
2582 F(Child.new())
2583 assert_equal('child', g:result)
2584 unlet g:result
2585 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002586 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002587
2588 lines =<< trim END
2589 vim9script
2590 class Base
2591 def Enter(): void
2592 g:result ..= 'base'
2593 enddef
2594 endclass
2595
2596 class Child extends Base
2597 def Enter(): void
2598 g:result ..= 'child'
2599 enddef
2600 endclass
2601
2602 def F(obj: Base)
2603 obj.Enter()
2604 enddef
2605
2606 g:result = ''
2607 F(Child.new())
2608 assert_equal('child', g:result)
2609 unlet g:result
2610 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002611 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002612
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002613 # method of interface returns a value
2614 lines =<< trim END
2615 vim9script
2616 interface Base
2617 def Enter(): string
2618 endinterface
2619
2620 class Child implements Base
2621 def Enter(): string
2622 g:result ..= 'child'
2623 return "/resource"
2624 enddef
2625 endclass
2626
2627 def F(obj: Base)
2628 var r = obj.Enter()
2629 g:result ..= r
2630 enddef
2631
2632 g:result = ''
2633 F(Child.new())
2634 assert_equal('child/resource', g:result)
2635 unlet g:result
2636 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002637 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002638
2639 lines =<< trim END
2640 vim9script
2641 class Base
2642 def Enter(): string
2643 return null_string
2644 enddef
2645 endclass
2646
2647 class Child extends Base
2648 def Enter(): string
2649 g:result ..= 'child'
2650 return "/resource"
2651 enddef
2652 endclass
2653
2654 def F(obj: Base)
2655 var r = obj.Enter()
2656 g:result ..= r
2657 enddef
2658
2659 g:result = ''
2660 F(Child.new())
2661 assert_equal('child/resource', g:result)
2662 unlet g:result
2663 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002664 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002665
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002666 # No class that implements the interface.
2667 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002668 vim9script
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002669
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002670 interface IWithEE
2671 def Enter(): any
2672 def Exit(): void
2673 endinterface
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002674
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002675 def With1(ee: IWithEE, F: func)
2676 var r = ee.Enter()
2677 enddef
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002678
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002679 defcompile
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002680 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002681 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002682enddef
2683
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002684def Test_class_used_as_type()
2685 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002686 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002687
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002688 class Point
2689 this.x = 0
2690 this.y = 0
2691 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002692
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002693 var p: Point
2694 p = Point.new(2, 33)
2695 assert_equal(2, p.x)
2696 assert_equal(33, p.y)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002697 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002698 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002699
2700 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002701 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002702
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002703 interface HasX
2704 this.x: number
2705 endinterface
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002706
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002707 class Point implements HasX
2708 this.x = 0
2709 this.y = 0
2710 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002711
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002712 var p: Point
2713 p = Point.new(2, 33)
2714 var hx = p
2715 assert_equal(2, hx.x)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002716 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002717 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002718
2719 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002720 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002721
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002722 class Point
2723 this.x = 0
2724 this.y = 0
2725 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002726
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002727 var p: Point
2728 p = 'text'
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002729 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002730 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string', 9)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002731enddef
2732
Bram Moolenaar83677162023-01-08 19:54:10 +00002733def Test_class_extends()
2734 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002735 vim9script
2736 class Base
2737 this.one = 1
2738 def GetOne(): number
2739 return this.one
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002740 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002741 endclass
2742 class Child extends Base
2743 this.two = 2
2744 def GetTotal(): number
2745 return this.one + this.two
2746 enddef
2747 endclass
2748 var o = Child.new()
2749 assert_equal(1, o.one)
2750 assert_equal(2, o.two)
2751 assert_equal(1, o.GetOne())
2752 assert_equal(3, o.GetTotal())
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002753 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002754 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002755
2756 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002757 vim9script
2758 class Base
2759 this.one = 1
2760 endclass
2761 class Child extends Base
2762 this.two = 2
2763 endclass
2764 var o = Child.new(3, 44)
2765 assert_equal(3, o.one)
2766 assert_equal(44, o.two)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002767 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002768 v9.CheckSourceSuccess(lines)
2769
2770 lines =<< trim END
2771 vim9script
2772 class Base
2773 this.one = 1
2774 endclass
2775 class Child extends Base extends Base
2776 this.two = 2
2777 endclass
2778 END
2779 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"', 5)
2780
2781 lines =<< trim END
2782 vim9script
2783 class Child extends BaseClass
2784 this.two = 2
2785 endclass
2786 END
2787 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass', 4)
2788
2789 lines =<< trim END
2790 vim9script
2791 var SomeVar = 99
2792 class Child extends SomeVar
2793 this.two = 2
2794 endclass
2795 END
2796 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar', 5)
2797
2798 lines =<< trim END
2799 vim9script
2800 class Base
2801 this.name: string
2802 def ToString(): string
2803 return this.name
2804 enddef
2805 endclass
2806
2807 class Child extends Base
2808 this.age: number
2809 def ToString(): string
2810 return super.ToString() .. ': ' .. this.age
2811 enddef
2812 endclass
2813
2814 var o = Child.new('John', 42)
2815 assert_equal('John: 42', o.ToString())
2816 END
2817 v9.CheckSourceSuccess(lines)
2818
2819 lines =<< trim END
2820 vim9script
2821 class Child
2822 this.age: number
2823 def ToString(): number
2824 return this.age
2825 enddef
2826 def ToString(): string
2827 return this.age
2828 enddef
2829 endclass
2830 END
2831 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
2832
2833 lines =<< trim END
2834 vim9script
2835 class Child
2836 this.age: number
2837 def ToString(): string
2838 return super .ToString() .. ': ' .. this.age
2839 enddef
2840 endclass
2841 var o = Child.new(42)
2842 echo o.ToString()
2843 END
2844 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
2845
2846 lines =<< trim END
2847 vim9script
2848 class Base
2849 this.name: string
2850 def ToString(): string
2851 return this.name
2852 enddef
2853 endclass
2854
2855 var age = 42
2856 def ToString(): string
2857 return super.ToString() .. ': ' .. age
2858 enddef
2859 echo ToString()
2860 END
2861 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
2862
2863 lines =<< trim END
2864 vim9script
2865 class Child
2866 this.age: number
2867 def ToString(): string
2868 return super.ToString() .. ': ' .. this.age
2869 enddef
2870 endclass
2871 var o = Child.new(42)
2872 echo o.ToString()
2873 END
2874 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
2875
2876 lines =<< trim END
2877 vim9script
2878 class Base
2879 this.name: string
2880 static def ToString(): string
2881 return 'Base class'
2882 enddef
2883 endclass
2884
2885 class Child extends Base
2886 this.age: number
2887 def ToString(): string
2888 return Base.ToString() .. ': ' .. this.age
2889 enddef
2890 endclass
2891
2892 var o = Child.new('John', 42)
2893 assert_equal('Base class: 42', o.ToString())
2894 END
2895 v9.CheckSourceSuccess(lines)
2896
2897 lines =<< trim END
2898 vim9script
2899 class Base
2900 this.value = 1
2901 def new(init: number)
2902 this.value = number + 1
2903 enddef
2904 endclass
2905 class Child extends Base
2906 def new()
2907 this.new(3)
2908 enddef
2909 endclass
2910 var c = Child.new()
2911 END
2912 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002913
2914 # base class with more than one object member
2915 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002916 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002917
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002918 class Result
2919 this.success: bool
2920 this.value: any = null
2921 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002922
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002923 class Success extends Result
2924 def new(this.value = v:none)
2925 this.success = true
2926 enddef
2927 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002928
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002929 var v = Success.new('asdf')
2930 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002931 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002932 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002933
2934 # class name after "extends" doesn't end in a space or NUL character
2935 lines =<< trim END
2936 vim9script
2937 class A
2938 endclass
2939 class B extends A"
2940 endclass
2941 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002942 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00002943enddef
2944
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002945def Test_using_base_class()
2946 var lines =<< trim END
2947 vim9script
2948
2949 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002950 def Enter(): any
2951 return null
2952 enddef
2953 def Exit(resource: any): void
2954 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002955 endclass
2956
2957 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002958 def Enter(): any
2959 return 42
2960 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002961
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002962 def Exit(resource: number): void
2963 g:result ..= '/exit'
2964 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002965 endclass
2966
2967 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002968 var r = ee.Enter()
2969 try
2970 g:result ..= r
2971 finally
2972 g:result ..= '/finally'
2973 ee.Exit(r)
2974 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002975 enddef
2976
2977 g:result = ''
2978 With(ChildEE.new())
2979 assert_equal('42/finally/exit', g:result)
2980 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002981 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002982 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002983
2984 # Using super, Child invokes Base method which has optional arg. #12471
2985 lines =<< trim END
2986 vim9script
2987
2988 class Base
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002989 this.success: bool = false
2990 def Method(arg = 0)
2991 this.success = true
2992 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01002993 endclass
2994
2995 class Child extends Base
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002996 def new()
2997 super.Method()
2998 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01002999 endclass
3000
3001 var obj = Child.new()
3002 assert_equal(true, obj.success)
3003 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003004 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003005enddef
3006
Bram Moolenaara86655a2023-01-12 17:06:27 +00003007def Test_class_import()
3008 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003009 vim9script
3010 export class Animal
3011 this.kind: string
3012 this.name: string
3013 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003014 END
3015 writefile(lines, 'Xanimal.vim', 'D')
3016
3017 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003018 vim9script
3019 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003020
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003021 var a: animal.Animal
3022 a = animal.Animal.new('fish', 'Eric')
3023 assert_equal('fish', a.kind)
3024 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003025
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003026 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3027 assert_equal('cat', b.kind)
3028 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003029 END
3030 v9.CheckScriptSuccess(lines)
3031enddef
3032
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003033def Test_abstract_class()
3034 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003035 vim9script
3036 abstract class Base
3037 this.name: string
3038 endclass
3039 class Person extends Base
3040 this.age: number
3041 endclass
3042 var p: Base = Person.new('Peter', 42)
3043 assert_equal('Peter', p.name)
3044 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003045 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003046 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003047
3048 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003049 vim9script
3050 abstract class Base
3051 this.name: string
3052 endclass
3053 class Person extends Base
3054 this.age: number
3055 endclass
3056 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003057 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003058 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003059
3060 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003061 abstract class Base
3062 this.name: string
3063 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003064 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003065 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003066
3067 # Abstract class cannot have a "new" function
3068 lines =<< trim END
3069 vim9script
3070 abstract class Base
3071 def new()
3072 enddef
3073 endclass
3074 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003075 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003076enddef
3077
Bram Moolenaar486fc252023-01-18 14:51:07 +00003078def Test_closure_in_class()
3079 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003080 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003081
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003082 class Foo
3083 this.y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003084
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003085 def new()
3086 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3087 enddef
3088 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003089
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003090 Foo.new()
3091 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003092 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003093 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003094enddef
3095
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003096def Test_call_constructor_from_legacy()
3097 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003098 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003099
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003100 var newCalled = 'false'
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003101
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003102 class A
3103 def new()
3104 newCalled = 'true'
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003105 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003106 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003107
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003108 export def F(options = {}): any
3109 return A
3110 enddef
3111
3112 g:p = F()
3113 legacy call p.new()
3114 assert_equal('true', newCalled)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003115 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003116 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003117enddef
3118
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003119def Test_defer_with_object()
3120 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003121 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003122
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003123 class CWithEE
3124 def Enter()
3125 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003126 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003127 def Exit()
3128 g:result ..= "exited"
3129 enddef
3130 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003131
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003132 def With(ee: CWithEE, F: func)
3133 ee.Enter()
3134 defer ee.Exit()
3135 F()
3136 enddef
3137
3138 g:result = ''
3139 var obj = CWithEE.new()
3140 obj->With(() => {
3141 g:result ..= "called/"
3142 })
3143 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003144 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003145 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003146 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003147
3148 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003149 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003150
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003151 class BaseWithEE
3152 def Enter()
3153 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003154 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003155 def Exit()
3156 g:result ..= "exited-base"
3157 enddef
3158 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003159
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003160 class CWithEE extends BaseWithEE
3161 def Enter()
3162 g:result ..= "entered-child/"
3163 enddef
3164 def Exit()
3165 g:result ..= "exited-child"
3166 enddef
3167 endclass
3168
3169 def With(ee: BaseWithEE, F: func)
3170 ee.Enter()
3171 defer ee.Exit()
3172 F()
3173 enddef
3174
3175 g:result = ''
3176 var obj = CWithEE.new()
3177 obj->With(() => {
3178 g:result ..= "called/"
3179 })
3180 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003181 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003182 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003183 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003184enddef
3185
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003186" The following test used to crash Vim (Github issue #12676)
3187def Test_extends_method_crashes_vim()
3188 var lines =<< trim END
3189 vim9script
3190
3191 class Observer
3192 endclass
3193
3194 class Property
3195 this.value: any
3196
3197 def Set(v: any)
3198 if v != this.value
3199 this.value = v
3200 endif
3201 enddef
3202
3203 def Register(observer: Observer)
3204 enddef
3205 endclass
3206
3207 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003208 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003209 endclass
3210
3211 def Observe(obj: Property, who: Observer)
3212 obj.Register(who)
3213 enddef
3214
3215 var p = Bool.new(false)
3216 var myObserver = Observer.new()
3217
3218 Observe(p, myObserver)
3219
3220 p.Set(true)
3221 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003222 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003223enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003224
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003225" Test for calling a method in a class that is extended
3226def Test_call_method_in_extended_class()
3227 var lines =<< trim END
3228 vim9script
3229
3230 var prop_init_called = false
3231 var prop_register_called = false
3232
3233 class Property
3234 def Init()
3235 prop_init_called = true
3236 enddef
3237
3238 def Register()
3239 prop_register_called = true
3240 enddef
3241 endclass
3242
3243 class Bool extends Property
3244 endclass
3245
3246 def Observe(obj: Property)
3247 obj.Register()
3248 enddef
3249
3250 var p = Property.new()
3251 Observe(p)
3252
3253 p.Init()
3254 assert_true(prop_init_called)
3255 assert_true(prop_register_called)
3256 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003257 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003258enddef
3259
LemonBoyafe04662023-08-23 21:08:11 +02003260def Test_instanceof()
3261 var lines =<< trim END
3262 vim9script
3263
3264 class Base1
3265 endclass
3266
3267 class Base2 extends Base1
3268 endclass
3269
3270 interface Intf1
3271 endinterface
3272
3273 class Mix1 implements Intf1
3274 endclass
3275
3276 class Base3 extends Mix1
3277 endclass
3278
3279 var b1 = Base1.new()
3280 var b2 = Base2.new()
3281 var b3 = Base3.new()
3282
3283 assert_true(instanceof(b1, Base1))
3284 assert_true(instanceof(b2, Base1))
3285 assert_false(instanceof(b1, Base2))
3286 assert_true(instanceof(b3, Mix1))
3287 assert_false(instanceof(b3, []))
3288 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003289
3290 def Foo()
3291 var a1 = Base1.new()
3292 var a2 = Base2.new()
3293 var a3 = Base3.new()
3294
3295 assert_true(instanceof(a1, Base1))
3296 assert_true(instanceof(a2, Base1))
3297 assert_false(instanceof(a1, Base2))
3298 assert_true(instanceof(a3, Mix1))
3299 assert_false(instanceof(a3, []))
3300 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
3301 enddef
3302 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003303
3304 var o_null: Base1
3305 assert_false(instanceof(o_null, Base1))
3306
LemonBoyafe04662023-08-23 21:08:11 +02003307 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003308 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02003309enddef
3310
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003311" Test for calling a method in the parent class that is extended partially.
3312" This used to fail with the 'E118: Too many arguments for function: Text' error
3313" message (Github issue #12524).
3314def Test_call_method_in_parent_class()
3315 var lines =<< trim END
3316 vim9script
3317
3318 class Widget
3319 this._lnum: number = 1
3320
3321 def SetY(lnum: number)
3322 this._lnum = lnum
3323 enddef
3324
3325 def Text(): string
3326 return ''
3327 enddef
3328 endclass
3329
3330 class Foo extends Widget
3331 def Text(): string
3332 return '<Foo>'
3333 enddef
3334 endclass
3335
3336 def Stack(w1: Widget, w2: Widget): list<Widget>
3337 w1.SetY(1)
3338 w2.SetY(2)
3339 return [w1, w2]
3340 enddef
3341
3342 var foo1 = Foo.new()
3343 var foo2 = Foo.new()
3344 var l = Stack(foo1, foo2)
3345 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003346 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003347enddef
3348
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003349" Test for calling methods from three levels of classes
3350def Test_multi_level_method_call()
3351 var lines =<< trim END
3352 vim9script
3353
3354 var A_func1: number = 0
3355 var A_func2: number = 0
3356 var A_func3: number = 0
3357 var B_func2: number = 0
3358 var B_func3: number = 0
3359 var C_func3: number = 0
3360
3361 class A
3362 def Func1()
3363 A_func1 += 1
3364 enddef
3365
3366 def Func2()
3367 A_func2 += 1
3368 enddef
3369
3370 def Func3()
3371 A_func3 += 1
3372 enddef
3373 endclass
3374
3375 class B extends A
3376 def Func2()
3377 B_func2 += 1
3378 enddef
3379
3380 def Func3()
3381 B_func3 += 1
3382 enddef
3383 endclass
3384
3385 class C extends B
3386 def Func3()
3387 C_func3 += 1
3388 enddef
3389 endclass
3390
3391 def A_CallFuncs(a: A)
3392 a.Func1()
3393 a.Func2()
3394 a.Func3()
3395 enddef
3396
3397 def B_CallFuncs(b: B)
3398 b.Func1()
3399 b.Func2()
3400 b.Func3()
3401 enddef
3402
3403 def C_CallFuncs(c: C)
3404 c.Func1()
3405 c.Func2()
3406 c.Func3()
3407 enddef
3408
3409 var cobj = C.new()
3410 A_CallFuncs(cobj)
3411 B_CallFuncs(cobj)
3412 C_CallFuncs(cobj)
3413 assert_equal(3, A_func1)
3414 assert_equal(0, A_func2)
3415 assert_equal(0, A_func3)
3416 assert_equal(3, B_func2)
3417 assert_equal(0, B_func3)
3418 assert_equal(3, C_func3)
3419 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003420 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003421enddef
3422
3423" Test for using members from three levels of classes
3424def Test_multi_level_member_access()
3425 var lines =<< trim END
3426 vim9script
3427
3428 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003429 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003430 endclass
3431
3432 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003433 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003434 endclass
3435
3436 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003437 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003438 endclass
3439
3440 def A_members(a: A)
3441 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003442 enddef
3443
3444 def B_members(b: B)
3445 b.val1 += 1
3446 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003447 enddef
3448
3449 def C_members(c: C)
3450 c.val1 += 1
3451 c.val2 += 1
3452 c.val3 += 1
3453 enddef
3454
3455 var cobj = C.new()
3456 A_members(cobj)
3457 B_members(cobj)
3458 C_members(cobj)
3459 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003460 assert_equal(2, cobj.val2)
3461 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003462 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003463 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003464enddef
3465
LemonBoy0ffc17a2023-08-20 18:09:11 +02003466" Test expansion of <stack> with class methods.
3467def Test_stack_expansion_with_methods()
3468 var lines =<< trim END
3469 vim9script
3470
3471 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003472 def M1()
3473 F0()
3474 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02003475 endclass
3476
3477 def F0()
3478 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3479 enddef
3480
3481 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003482 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02003483 enddef
3484
3485 F()
3486 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003487 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003488enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003489
3490" Test the return type of the new() constructor
3491def Test_new_return_type()
3492 # new() uses the default return type and there is no return statement
3493 var lines =<< trim END
3494 vim9script
3495
3496 class C
3497 this._bufnr: number
3498
3499 def new(this._bufnr)
3500 if !bufexists(this._bufnr)
3501 this._bufnr = -1
3502 endif
3503 enddef
3504 endclass
3505
3506 var c = C.new(12345)
3507 assert_equal('object<C>', typename(c))
3508
3509 var v1: C
3510 v1 = C.new(12345)
3511 assert_equal('object<C>', typename(v1))
3512
3513 def F()
3514 var v2: C
3515 v2 = C.new(12345)
3516 assert_equal('object<C>', typename(v2))
3517 enddef
3518 F()
3519 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003520 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003521
3522 # new() uses the default return type and an empty 'return' statement
3523 lines =<< trim END
3524 vim9script
3525
3526 class C
3527 this._bufnr: number
3528
3529 def new(this._bufnr)
3530 if !bufexists(this._bufnr)
3531 this._bufnr = -1
3532 return
3533 endif
3534 enddef
3535 endclass
3536
3537 var c = C.new(12345)
3538 assert_equal('object<C>', typename(c))
3539
3540 var v1: C
3541 v1 = C.new(12345)
3542 assert_equal('object<C>', typename(v1))
3543
3544 def F()
3545 var v2: C
3546 v2 = C.new(12345)
3547 assert_equal('object<C>', typename(v2))
3548 enddef
3549 F()
3550 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003551 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003552
3553 # new() uses "any" return type and returns "this"
3554 lines =<< trim END
3555 vim9script
3556
3557 class C
3558 this._bufnr: number
3559
3560 def new(this._bufnr): any
3561 if !bufexists(this._bufnr)
3562 this._bufnr = -1
3563 return this
3564 endif
3565 enddef
3566 endclass
3567 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003568 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003569
3570 # new() uses 'Dict' return type and returns a Dict
3571 lines =<< trim END
3572 vim9script
3573
3574 class C
3575 this._state: dict<any>
3576
3577 def new(): dict<any>
3578 this._state = {}
3579 return this._state
3580 enddef
3581 endclass
3582
3583 var c = C.new()
3584 assert_equal('object<C>', typename(c))
3585 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003586 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003587enddef
3588
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003589" Test for checking a member initialization type at run time.
3590def Test_runtime_type_check_for_member_init()
3591 var lines =<< trim END
3592 vim9script
3593
3594 var retnum: bool = false
3595
3596 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003597 retnum = !retnum
3598 if retnum
3599 return 1
3600 else
3601 return "hello"
3602 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003603 enddef
3604
3605 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003606 this._foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003607 endclass
3608
3609 var c1 = C.new()
3610 var c2 = C.new()
3611 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003612 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003613enddef
3614
3615" Test for locking a variable referring to an object and reassigning to another
3616" object.
Ernie Raelee865f32023-09-29 19:53:55 +02003617def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003618 var lines =<< trim END
3619 vim9script
3620
3621 class C
3622 this.val: number
3623 def new(this.val)
3624 enddef
3625 endclass
3626
3627 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3628 lockvar 2 some_dict
3629
3630 var current: C
3631 current = some_dict['c']
3632 assert_equal(3, current.val)
3633 current = some_dict['b']
3634 assert_equal(2, current.val)
3635
3636 def F()
3637 current = some_dict['c']
3638 enddef
3639
3640 def G()
3641 current = some_dict['b']
3642 enddef
3643
3644 F()
3645 assert_equal(3, current.val)
3646 G()
3647 assert_equal(2, current.val)
3648 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003649 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003650enddef
3651
Ernie Raelee865f32023-09-29 19:53:55 +02003652" Test trying to lock an object variable from various places
3653def Test_lockvar_object_variable()
3654 # An object variable lockvar has several cases:
3655 # object method, scriptlevel, scriplevel from :def, :def arg
3656 # method arg, static method arg.
3657 # Also different depths
3658
Ernie Raelee865f32023-09-29 19:53:55 +02003659 #
3660 # lockvar of read-only object variable
3661 #
3662
3663 # read-only lockvar from object method
3664 var lines =<< trim END
3665 vim9script
3666
3667 class C
3668 this.val1: number
3669 def Lock()
3670 lockvar this.val1
3671 enddef
3672 endclass
3673 var o = C.new(3)
3674 o.Lock()
3675 END
Ernie Rael64885642023-10-04 20:16:22 +02003676 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02003677
3678 # read-only lockvar from scriptlevel
3679 lines =<< trim END
3680 vim9script
3681
3682 class C
3683 this.val2: number
3684 endclass
3685 var o = C.new(3)
3686 lockvar o.val2
3687 END
3688 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
3689
3690 # read-only lockvar of scriptlevel variable from def
3691 lines =<< trim END
3692 vim9script
3693
3694 class C
3695 this.val3: number
3696 endclass
3697 var o = C.new(3)
3698 def Lock()
3699 lockvar o.val3
3700 enddef
3701 Lock()
3702 END
3703 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
3704
3705 # read-only lockvar of def argument variable
3706 lines =<< trim END
3707 vim9script
3708
3709 class C
3710 this.val4: number
3711 endclass
3712 def Lock(o: C)
3713 lockvar o.val4
3714 enddef
3715 Lock(C.new(3))
3716 END
3717 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
3718
3719 # TODO: the following tests use type "any" for argument. Need a run time
3720 # check for access. Probably OK as is for now.
3721
3722 # read-only lockvar from object method arg
3723 lines =<< trim END
3724 vim9script
3725
3726 class C
3727 this.val5: number
3728 def Lock(o_any: any)
3729 lockvar o_any.val5
3730 enddef
3731 endclass
3732 var o = C.new(3)
3733 o.Lock(C.new(5))
3734 END
Ernie Rael64885642023-10-04 20:16:22 +02003735 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02003736
3737 # read-only lockvar from class method arg
3738 lines =<< trim END
3739 vim9script
3740
3741 class C
3742 this.val6: number
3743 static def Lock(o_any: any)
3744 lockvar o_any.val6
3745 enddef
3746 endclass
3747 var o = C.new(3)
3748 C.Lock(o)
3749 END
Ernie Rael64885642023-10-04 20:16:22 +02003750 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02003751
3752 #
3753 # lockvar of public object variable
3754 #
3755
3756 # lockvar from object method
3757 lines =<< trim END
3758 vim9script
3759
3760 class C
3761 public this.val1: number
3762 def Lock()
3763 lockvar this.val1
3764 enddef
3765 endclass
3766 var o = C.new(3)
3767 o.Lock()
3768 END
3769 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
3770
3771 # lockvar from scriptlevel
3772 lines =<< trim END
3773 vim9script
3774
3775 class C
3776 public this.val2: number
3777 endclass
3778 var o = C.new(3)
3779 lockvar o.val2
3780 END
3781 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
3782
3783 # lockvar of scriptlevel variable from def
3784 lines =<< trim END
3785 vim9script
3786
3787 class C
3788 public this.val3: number
3789 endclass
3790 var o = C.new(3)
3791 def Lock()
3792 lockvar o.val3
3793 enddef
3794 Lock()
3795 END
3796 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
3797
3798 # lockvar of def argument variable
3799 lines =<< trim END
3800 vim9script
3801
3802 class C
3803 public this.val4: number
3804 endclass
3805 def Lock(o: C)
3806 lockvar o.val4
3807 enddef
3808 Lock(C.new(3))
3809 END
3810 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
3811
3812 # lockvar from object method arg
3813 lines =<< trim END
3814 vim9script
3815
3816 class C
3817 public this.val5: number
3818 def Lock(o_any: any)
3819 lockvar o_any.val5
3820 enddef
3821 endclass
3822 var o = C.new(3)
3823 o.Lock(C.new(5))
3824 END
3825 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val5" in class "C"', 1)
3826
3827 # lockvar from class method arg
3828 lines =<< trim END
3829 vim9script
3830
3831 class C
3832 public this.val6: number
3833 static def Lock(o_any: any)
3834 lockvar o_any.val6
3835 enddef
3836 endclass
3837 var o = C.new(3)
3838 C.Lock(o)
3839 END
3840 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val6" in class "C"', 1)
3841enddef
3842
3843" Test trying to lock a class variable from various places
3844def Test_lockvar_class_variable()
3845
3846 # lockvar bare static from object method
3847 var lines =<< trim END
3848 vim9script
3849
3850 class C
3851 public static sval1: number
3852 def Lock()
3853 lockvar sval1
3854 enddef
3855 endclass
3856 var o = C.new()
3857 o.Lock()
3858 END
3859 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
3860
3861 # lockvar C.static from object method
3862 lines =<< trim END
3863 vim9script
3864
3865 class C
3866 public static sval2: number
3867 def Lock()
3868 lockvar C.sval2
3869 enddef
3870 endclass
3871 var o = C.new()
3872 o.Lock()
3873 END
3874 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
3875
3876 # lockvar bare static from class method
3877 lines =<< trim END
3878 vim9script
3879
3880 class C
3881 public static sval3: number
3882 static def Lock()
3883 lockvar sval3
3884 enddef
3885 endclass
3886 C.Lock()
3887 END
3888 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
3889
3890 # lockvar C.static from class method
3891 lines =<< trim END
3892 vim9script
3893
3894 class C
3895 public static sval4: number
3896 static def Lock()
3897 lockvar C.sval4
3898 enddef
3899 endclass
3900 C.Lock()
3901 END
3902 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
3903
3904 # lockvar C.static from script level
3905 lines =<< trim END
3906 vim9script
3907
3908 class C
3909 public static sval5: number
3910 endclass
3911 lockvar C.sval5
3912 END
3913 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
3914
3915 # lockvar o.static from script level
3916 lines =<< trim END
3917 vim9script
3918
3919 class C
3920 public static sval6: number
3921 endclass
3922 var o = C.new()
3923 lockvar o.sval6
3924 END
3925 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
3926enddef
3927
3928" Test locking an argument to :def
3929def Test_lockvar_argument()
3930 # Lockvar a function arg
3931 var lines =<< trim END
3932 vim9script
3933
3934 def Lock(val: any)
3935 lockvar val
3936 enddef
3937
3938 var d = {a: 1, b: 2}
3939 Lock(d)
3940
3941 d->extend({c: 3})
3942 END
3943 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
3944
3945 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
3946 # class member in "C". This tests lval_root_is_arg.
3947 lines =<< trim END
3948 vim9script
3949
3950 class C
3951 public static sval: list<number>
3952 endclass
3953
3954 def Lock2(sval: any)
3955 lockvar sval
3956 enddef
3957
3958 var o = C.new()
3959 Lock2(o)
3960 END
3961 v9.CheckSourceSuccess(lines)
3962
3963 # Lock a class.
3964 lines =<< trim END
3965 vim9script
3966
3967 class C
3968 public static sval: list<number>
3969 endclass
3970
3971 def Lock2(sval: any)
3972 lockvar sval
3973 enddef
3974
3975 Lock2(C)
3976 END
3977 v9.CheckSourceSuccess(lines)
3978
3979 # Lock an object.
3980 lines =<< trim END
3981 vim9script
3982
3983 class C
3984 public static sval: list<number>
3985 endclass
3986
3987 def Lock2(sval: any)
3988 lockvar sval
3989 enddef
3990
3991 Lock2(C.new())
3992 END
3993 v9.CheckSourceSuccess(lines)
3994
3995 # In this case (unlike previous) "lockvar sval" is a class member.
3996 lines =<< trim END
3997 vim9script
3998
3999 class C
4000 public static sval: list<number>
4001 def Lock2()
4002 lockvar sval
4003 enddef
4004 endclass
4005
4006
4007 var o = C.new()
4008 o.Lock2()
4009 END
4010 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4011enddef
4012
4013" Test that this can be locked without error
4014def Test_lockvar_this()
4015 # lockvar this
4016 var lines =<< trim END
4017 vim9script
4018 class C
4019 def TLock()
4020 lockvar this
4021 enddef
4022 endclass
4023 var o = C.new()
4024 o.TLock()
4025 END
4026 v9.CheckSourceSuccess(lines)
4027
4028 # lockvar four (four letter word, but not this)
4029 lines =<< trim END
4030 vim9script
4031 class C
4032 def TLock4()
4033 var four: number
4034 lockvar four
4035 enddef
4036 endclass
4037 var o = C.new()
4038 o.TLock4()
4039 END
4040 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4041
4042 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4043 lines =<< trim END
4044 vim9script
4045 class C
4046 def TLock5()
4047 var this5: number
4048 lockvar this5
4049 enddef
4050 endclass
4051 var o = C.new()
4052 o.TLock5()
4053 END
4054 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4055enddef
4056
4057" Test some general lockvar cases
4058def Test_lockvar_general()
4059 # lockvar an object and a class. It does nothing
4060 var lines =<< trim END
4061 vim9script
4062 class C
4063 endclass
4064 var o = C.new()
4065 lockvar o
4066 lockvar C
4067 END
4068 v9.CheckSourceSuccess(lines)
4069
4070 # Lock a list element that's nested in an object variable from a :def
4071 lines =<< trim END
4072 vim9script
4073
4074 class C
4075 public this.val: list<list<number>> = [ [1], [2], [3] ]
4076 endclass
4077 def Lock2(obj: any)
4078 lockvar obj.val[1]
4079 enddef
4080
4081 var o = C.new()
4082 Lock2(o)
4083 o.val[0] = [9]
4084 assert_equal([ [9], [2], [3] ], o.val)
4085 try
4086 o.val[1] = [999]
4087 call assert_false(true, 'assign should have failed')
4088 catch
4089 assert_exception('E741:')
4090 endtry
4091 o.val[2] = [8]
4092 assert_equal([ [9], [2], [8] ], o.val)
4093 END
4094 v9.CheckSourceSuccess(lines)
4095
4096 # Lock a list element that's nested in an object variable from scriptlevel
4097 lines =<< trim END
4098 vim9script
4099
4100 class C
4101 public this.val: list<list<number>> = [ [1], [2], [3] ]
4102 endclass
4103
4104 var o = C.new()
4105 lockvar o.val[1]
4106 o.val[0] = [9]
4107 assert_equal([ [9], [2], [3] ], o.val)
4108 try
4109 o.val[1] = [999]
4110 call assert_false(true, 'assign should have failed')
4111 catch
4112 assert_exception('E741:')
4113 endtry
4114 o.val[2] = [8]
4115 assert_equal([ [9], [2], [8] ], o.val)
4116 END
4117 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004118
4119 # lock a script level variable from an object method
4120 lines =<< trim END
4121 vim9script
4122
4123 class C
4124 def Lock()
4125 lockvar l
4126 enddef
4127 endclass
4128
4129 var l = [1]
4130 C.new().Lock()
4131 l[0] = 11
4132 END
4133 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4134
4135 # lock a list element referenced by a private object variable
4136 # in an object fetched via a script level list
4137 lines =<< trim END
4138 vim9script
4139
4140 class C
4141 this._v1: list<list<number>>
4142 def Lock()
4143 lockvar lc[0]._v1[1]
4144 enddef
4145 endclass
4146
4147 var l = [[1], [2], [3]]
4148 var o = C.new(l)
4149 var lc: list<C> = [ o ]
4150
4151 o.Lock()
4152 l[0] = [22]
4153 l[1] = [33]
4154 END
4155 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4156
4157 # similar to the previous test, except the locking code is executing
4158 # in a class that does not own the private variable.
4159 # Note that the locking code is in a class has a private variable of
4160 # the same name.
4161 lines =<< trim END
4162 vim9script
4163
4164 class C2
4165 this._v1: list<list<number>>
4166 def Lock(obj: any)
4167 lockvar lc[0]._v1[1]
4168 enddef
4169 endclass
4170
4171 class C
4172 this._v1: list<list<number>>
4173 endclass
4174
4175 var l = [[1], [2], [3]]
4176 var o = C.new(l)
4177 var lc: list<C> = [ o ]
4178
4179 var o2 = C2.new()
4180 o2.Lock(o)
4181 END
4182 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004183enddef
4184
Ernie Rael9771b2a2023-10-07 22:05:40 +02004185" Test builtin islocked()
4186def Test_lockvar_islocked()
4187 # Can't lock class/object variable
4188 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01004189 # Lock item of variable's value (a list item)
4190 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02004191 var lines =<< trim END
4192 vim9script
4193
4194 class C
4195 this.o0: list<list<number>> = [ [0], [1], [2]]
4196 this.o1: list<list<number>> = [[10], [11], [12]]
4197 static c0: list<list<number>> = [[20], [21], [22]]
4198 static c1: list<list<number>> = [[30], [31], [32]]
4199 endclass
4200
4201 def LockIt(arg: any)
4202 lockvar arg
4203 enddef
4204
4205 def UnlockIt(arg: any)
4206 unlockvar arg
4207 enddef
4208
4209 var obj = C.new()
4210 #lockvar obj.o1 # can't lock something you can't write to
4211
4212 try
4213 lockvar obj.o1 # can't lock something you can't write to
4214 call assert_false(1, '"lockvar obj.o1" should have failed')
4215 catch
4216 call assert_exception('E1335:')
4217 endtry
4218
4219 LockIt(obj.o1) # but can lock it's value
4220 assert_equal(1, islocked("obj.o1"))
4221 assert_equal(1, islocked("obj.o1[0]"))
4222 assert_equal(1, islocked("obj.o1[1]"))
4223 UnlockIt(obj.o1)
4224 assert_equal(0, islocked("obj.o1"))
4225 assert_equal(0, islocked("obj.o1[0]"))
4226
4227 lockvar obj.o1[0]
4228 assert_equal(0, islocked("obj.o1"))
4229 assert_equal(1, islocked("obj.o1[0]"))
4230 assert_equal(0, islocked("obj.o1[1]"))
4231 unlockvar obj.o1[0]
4232 assert_equal(0, islocked("obj.o1"))
4233 assert_equal(0, islocked("obj.o1[0]"))
4234
4235 # Same thing, but with a static
4236
4237 try
4238 lockvar C.c1 # can't lock something you can't write to
4239 call assert_false(1, '"lockvar C.c1" should have failed')
4240 catch
4241 call assert_exception('E1335:')
4242 endtry
4243
4244 LockIt(C.c1) # but can lock it's value
4245 assert_equal(1, islocked("C.c1"))
4246 assert_equal(1, islocked("C.c1[0]"))
4247 assert_equal(1, islocked("C.c1[1]"))
4248 UnlockIt(C.c1)
4249 assert_equal(0, islocked("C.c1"))
4250 assert_equal(0, islocked("C.c1[0]"))
4251
4252 lockvar C.c1[0]
4253 assert_equal(0, islocked("C.c1"))
4254 assert_equal(1, islocked("C.c1[0]"))
4255 assert_equal(0, islocked("C.c1[1]"))
4256 unlockvar C.c1[0]
4257 assert_equal(0, islocked("C.c1"))
4258 assert_equal(0, islocked("C.c1[0]"))
4259 END
4260 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02004261
4262 # Do islocked() from an object method
4263 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02004264 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02004265 vim9script
4266
4267 var l0o0 = [ [0], [1], [2]]
4268 var l0o1 = [ [10], [11], [12]]
4269 var l0c0 = [[120], [121], [122]]
4270 var l0c1 = [[130], [131], [132]]
4271
4272 class C0
4273 this.o0: list<list<number>> = l0o0
4274 this.o1: list<list<number>> = l0o1
4275 static c0: list<list<number>> = l0c0
4276 static c1: list<list<number>> = l0c1
4277 def Islocked(arg: string): number
4278 return islocked(arg)
4279 enddef
4280 static def SIslocked(arg: string): number
4281 return islocked(arg)
4282 enddef
4283 endclass
4284
4285 var l2o0 = [[20000], [20001], [20002]]
4286 var l2o1 = [[20010], [20011], [20012]]
4287 var l2c0 = [[20120], [20121], [20122]]
4288 var l2c1 = [[20130], [20131], [20132]]
4289
4290 class C2
4291 this.o0: list<list<number>> = l2o0
4292 this.o1: list<list<number>> = l2o1
4293 static c0: list<list<number>> = l2c0
4294 static c1: list<list<number>> = l2c1
4295 def Islocked(arg: string): number
4296 return islocked(arg)
4297 enddef
4298 static def SIslocked(arg: string): number
4299 return islocked(arg)
4300 enddef
4301 endclass
4302
4303 var obj0 = C0.new()
4304 var obj2 = C2.new()
4305
4306 var l = [ obj0, null_object, obj2 ]
4307
4308 # lock list, object func access through script var expr
4309 assert_equal(0, obj0.Islocked("l[0].o0"))
4310 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
4311 lockvar l0o0
4312 assert_equal(1, obj0.Islocked("l[0].o0"))
4313 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
4314
4315 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
4316
4317 # lock list element, object func access through script var expr
4318 lockvar l0o1[1]
4319 assert_equal(0, obj0.Islocked("this.o1[0]"))
4320 assert_equal(1, obj0.Islocked("this.o1[1]"))
4321
4322 assert_equal(0, obj0.Islocked("this.o1"))
4323 lockvar l0o1
4324 assert_equal(1, obj0.Islocked("this.o1"))
4325 unlockvar l0o1
4326
4327 lockvar l0c1[1]
4328
4329 # static by class name member expr from same class
4330 assert_equal(0, obj0.Islocked("C0.c1[0]"))
4331 assert_equal(1, obj0.Islocked("C0.c1[1]"))
4332 # static by bare name member expr from same class
4333 assert_equal(0, obj0.Islocked("c1[0]"))
4334 assert_equal(1, obj0.Islocked("c1[1]"))
4335
4336 # static by class name member expr from other class
4337 assert_equal(0, obj2.Islocked("C0.c1[0]"))
4338 assert_equal(1, obj2.Islocked("C0.c1[1]"))
4339 # static by bare name member expr from other class
4340 assert_equal(0, obj2.Islocked("c1[0]"))
4341 assert_equal(0, obj2.Islocked("c1[1]"))
4342
4343
4344 # static by bare name in same class
4345 assert_equal(0, obj0.Islocked("c0"))
4346 lockvar l0c0
4347 assert_equal(1, obj0.Islocked("c0"))
4348
4349 #
4350 # similar stuff, but use static method
4351 #
4352
4353 unlockvar l0o0
4354
4355 # lock list, object func access through script var expr
4356 assert_equal(0, C0.SIslocked("l[0].o0"))
4357 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
4358 lockvar l0o0
4359 assert_equal(1, C0.SIslocked("l[0].o0"))
4360 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
4361
4362 unlockvar l0o1
4363
4364 # can't access "this" from class method
4365 try
4366 C0.SIslocked("this.o1[0]")
4367 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
4368 catch
4369 call assert_exception('E121: Undefined variable: this')
4370 endtry
4371
4372 lockvar l0c1[1]
4373
4374 # static by class name member expr from same class
4375 assert_equal(0, C0.SIslocked("C0.c1[0]"))
4376 assert_equal(1, C0.SIslocked("C0.c1[1]"))
4377 # static by bare name member expr from same class
4378 assert_equal(0, C0.SIslocked("c1[0]"))
4379 assert_equal(1, C0.SIslocked("c1[1]"))
4380
4381 # static by class name member expr from other class
4382 assert_equal(0, C2.SIslocked("C0.c1[0]"))
4383 assert_equal(1, C2.SIslocked("C0.c1[1]"))
4384 # static by bare name member expr from other class
4385 assert_equal(0, C2.SIslocked("c1[0]"))
4386 assert_equal(0, C2.SIslocked("c1[1]"))
4387
4388
4389 # static by bare name in same class
4390 unlockvar l0c0
4391 assert_equal(0, C0.SIslocked("c0"))
4392 lockvar l0c0
4393 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02004394 END
Ernie Rael4c8da022023-10-11 21:35:11 +02004395 v9.CheckSourceSuccess(lines)
4396
4397 # Check islocked class/object from various places.
4398 lines =<< trim END
4399 vim9script
4400
4401 class C
4402 def Islocked(arg: string): number
4403 return islocked(arg)
4404 enddef
4405 static def SIslocked(arg: string): number
4406 return islocked(arg)
4407 enddef
4408 endclass
4409 var obj = C.new()
4410
4411 # object method
4412 assert_equal(0, obj.Islocked("this"))
4413 assert_equal(0, obj.Islocked("C"))
4414
4415 # class method
4416 ### assert_equal(0, C.SIslocked("this"))
4417 assert_equal(0, C.SIslocked("C"))
4418
4419 #script level
4420 var v: number
4421 v = islocked("C")
4422 assert_equal(0, v)
4423 v = islocked("obj")
4424 assert_equal(0, v)
4425 END
4426 v9.CheckSourceSuccess(lines)
4427enddef
4428
4429def Test_lockvar_islocked_notfound()
4430 # Try non-existent things
4431 var lines =<< trim END
4432 vim9script
4433
4434 class C
4435 def Islocked(arg: string): number
4436 return islocked(arg)
4437 enddef
4438 static def SIslocked(arg: string): number
4439 return islocked(arg)
4440 enddef
4441 endclass
4442 var obj = C.new()
4443 assert_equal(-1, obj.Islocked("anywhere"))
4444 assert_equal(-1, C.SIslocked("notanywhere"))
4445 END
4446 v9.CheckSourceSuccess(lines)
4447
4448 # Something not found of the form "name1.name2" is an error
4449 lines =<< trim END
4450 vim9script
4451
4452 islocked("one.two")
4453 END
4454 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
4455
4456 lines =<< trim END
4457 vim9script
4458
4459 class C
4460 this.val = { key: "value" }
4461 def Islocked(arg: string): number
4462 return islocked(arg)
4463 enddef
4464 endclass
4465 var obj = C.new()
4466 obj.Islocked("this.val.not_there"))
4467 END
4468 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
4469
4470 lines =<< trim END
4471 vim9script
4472
4473 class C
4474 def Islocked(arg: string): number
4475 return islocked(arg)
4476 enddef
4477 endclass
4478 var obj = C.new()
4479 obj.Islocked("this.notobjmember")
4480 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02004481 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02004482
4483 # access a script variable through methods
4484 lines =<< trim END
4485 vim9script
4486
4487 var l = [1]
4488 class C
4489 def Islocked(arg: string): number
4490 return islocked(arg)
4491 enddef
4492 static def SIslocked(arg: string): number
4493 return islocked(arg)
4494 enddef
4495 endclass
4496 var obj = C.new()
4497 assert_equal(0, obj.Islocked("l"))
4498 assert_equal(0, C.SIslocked("l"))
4499 lockvar l
4500 assert_equal(1, obj.Islocked("l"))
4501 assert_equal(1, C.SIslocked("l"))
4502 END
4503 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02004504enddef
4505
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004506" Test for a private object method
4507def Test_private_object_method()
4508 # Try calling a private method using an object (at the script level)
4509 var lines =<< trim END
4510 vim9script
4511
4512 class A
4513 def _Foo(): number
4514 return 1234
4515 enddef
4516 endclass
4517 var a = A.new()
4518 a._Foo()
4519 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02004520 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004521
4522 # Try calling a private method using an object (from a def function)
4523 lines =<< trim END
4524 vim9script
4525
4526 class A
4527 def _Foo(): number
4528 return 1234
4529 enddef
4530 endclass
4531 def T()
4532 var a = A.new()
4533 a._Foo()
4534 enddef
4535 T()
4536 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004537 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004538
4539 # Use a private method from another object method (in script context)
4540 lines =<< trim END
4541 vim9script
4542
4543 class A
4544 def _Foo(): number
4545 return 1234
4546 enddef
4547 def Bar(): number
4548 return this._Foo()
4549 enddef
4550 endclass
4551 var a = A.new()
4552 assert_equal(1234, a.Bar())
4553 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004554 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004555
4556 # Use a private method from another object method (def function context)
4557 lines =<< trim END
4558 vim9script
4559
4560 class A
4561 def _Foo(): number
4562 return 1234
4563 enddef
4564 def Bar(): number
4565 return this._Foo()
4566 enddef
4567 endclass
4568 def T()
4569 var a = A.new()
4570 assert_equal(1234, a.Bar())
4571 enddef
4572 T()
4573 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004574 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004575
4576 # Try calling a private method without the "this" prefix
4577 lines =<< trim END
4578 vim9script
4579
4580 class A
4581 def _Foo(): number
4582 return 1234
4583 enddef
4584 def Bar(): number
4585 return _Foo()
4586 enddef
4587 endclass
4588 var a = A.new()
4589 a.Bar()
4590 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004591 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004592
4593 # Try calling a private method using the class name
4594 lines =<< trim END
4595 vim9script
4596
4597 class A
4598 def _Foo(): number
4599 return 1234
4600 enddef
4601 endclass
4602 A._Foo()
4603 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004604 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004605
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004606 # Define two private methods with the same name
4607 lines =<< trim END
4608 vim9script
4609
4610 class A
4611 def _Foo()
4612 enddef
4613 def _Foo()
4614 enddef
4615 endclass
4616 var a = A.new()
4617 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004618 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004619
4620 # Define a private method and a object method with the same name
4621 lines =<< trim END
4622 vim9script
4623
4624 class A
4625 def _Foo()
4626 enddef
4627 def Foo()
4628 enddef
4629 endclass
4630 var a = A.new()
4631 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004632 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004633
4634 # Define an object method and a private method with the same name
4635 lines =<< trim END
4636 vim9script
4637
4638 class A
4639 def Foo()
4640 enddef
4641 def _Foo()
4642 enddef
4643 endclass
4644 var a = A.new()
4645 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004646 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004647
4648 # Call a public method and a private method from a private method
4649 lines =<< trim END
4650 vim9script
4651
4652 class A
4653 def Foo(): number
4654 return 100
4655 enddef
4656 def _Bar(): number
4657 return 200
4658 enddef
4659 def _Baz()
4660 assert_equal(100, this.Foo())
4661 assert_equal(200, this._Bar())
4662 enddef
4663 def T()
4664 this._Baz()
4665 enddef
4666 endclass
4667 var a = A.new()
4668 a.T()
4669 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004670 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004671
4672 # Try calling a private method from another class
4673 lines =<< trim END
4674 vim9script
4675
4676 class A
4677 def _Foo(): number
4678 return 100
4679 enddef
4680 endclass
4681 class B
4682 def Foo(): number
4683 var a = A.new()
4684 a._Foo()
4685 enddef
4686 endclass
4687 var b = B.new()
4688 b.Foo()
4689 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004690 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004691
4692 # Call a private object method from a child class object method
4693 lines =<< trim END
4694 vim9script
4695 class A
4696 def _Foo(): number
4697 return 1234
4698 enddef
4699 endclass
4700 class B extends A
4701 def Bar()
4702 enddef
4703 endclass
4704 class C extends B
4705 def Baz(): number
4706 return this._Foo()
4707 enddef
4708 endclass
4709 var c = C.new()
4710 assert_equal(1234, c.Baz())
4711 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004712 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004713
4714 # Call a private object method from a child class object
4715 lines =<< trim END
4716 vim9script
4717 class A
4718 def _Foo(): number
4719 return 1234
4720 enddef
4721 endclass
4722 class B extends A
4723 def Bar()
4724 enddef
4725 endclass
4726 class C extends B
4727 def Baz(): number
4728 enddef
4729 endclass
4730 var c = C.new()
4731 assert_equal(1234, c._Foo())
4732 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02004733 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004734
4735 # Using "_" prefix in a method name should fail outside of a class
4736 lines =<< trim END
4737 vim9script
4738 def _Foo(): number
4739 return 1234
4740 enddef
4741 var a = _Foo()
4742 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004743 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004744enddef
4745
4746" Test for an private class method
4747def Test_private_class_method()
4748 # Try calling a class private method (at the script level)
4749 var lines =<< trim END
4750 vim9script
4751
4752 class A
4753 static def _Foo(): number
4754 return 1234
4755 enddef
4756 endclass
4757 A._Foo()
4758 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02004759 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004760
4761 # Try calling a class private method (from a def function)
4762 lines =<< trim END
4763 vim9script
4764
4765 class A
4766 static def _Foo(): number
4767 return 1234
4768 enddef
4769 endclass
4770 def T()
4771 A._Foo()
4772 enddef
4773 T()
4774 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004775 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004776
4777 # Try calling a class private method using an object (at the script level)
4778 lines =<< trim END
4779 vim9script
4780
4781 class A
4782 static def _Foo(): number
4783 return 1234
4784 enddef
4785 endclass
4786 var a = A.new()
4787 a._Foo()
4788 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004789 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004790
4791 # Try calling a class private method using an object (from a def function)
4792 lines =<< trim END
4793 vim9script
4794
4795 class A
4796 static def _Foo(): number
4797 return 1234
4798 enddef
4799 endclass
4800 def T()
4801 var a = A.new()
4802 a._Foo()
4803 enddef
4804 T()
4805 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004806 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004807
4808 # Use a class private method from an object method
4809 lines =<< trim END
4810 vim9script
4811
4812 class A
4813 static def _Foo(): number
4814 return 1234
4815 enddef
4816 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004817 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004818 enddef
4819 endclass
4820 var a = A.new()
4821 a.Bar()
4822 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004823 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004824
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004825 # Use a class private method from another class private method without the
4826 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004827 lines =<< trim END
4828 vim9script
4829
4830 class A
4831 static def _Foo1(): number
4832 return 1234
4833 enddef
4834 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004835 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004836 enddef
4837 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004838 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004839 enddef
4840 endclass
4841 var a = A.new()
4842 a.Bar()
4843 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004844 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004845
4846 # Declare a class method and a class private method with the same name
4847 lines =<< trim END
4848 vim9script
4849
4850 class A
4851 static def _Foo()
4852 enddef
4853 static def Foo()
4854 enddef
4855 endclass
4856 var a = A.new()
4857 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004858 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004859
4860 # Try calling a class private method from another class
4861 lines =<< trim END
4862 vim9script
4863
4864 class A
4865 static def _Foo(): number
4866 return 1234
4867 enddef
4868 endclass
4869 class B
4870 def Foo(): number
4871 return A._Foo()
4872 enddef
4873 endclass
4874 var b = B.new()
4875 assert_equal(1234, b.Foo())
4876 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004877 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004878
4879 # Call a private class method from a child class object method
4880 lines =<< trim END
4881 vim9script
4882 class A
4883 static def _Foo(): number
4884 return 1234
4885 enddef
4886 endclass
4887 class B extends A
4888 def Bar()
4889 enddef
4890 endclass
4891 class C extends B
4892 def Baz(): number
4893 return A._Foo()
4894 enddef
4895 endclass
4896 var c = C.new()
4897 assert_equal(1234, c.Baz())
4898 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004899 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004900
4901 # Call a private class method from a child class private class method
4902 lines =<< trim END
4903 vim9script
4904 class A
4905 static def _Foo(): number
4906 return 1234
4907 enddef
4908 endclass
4909 class B extends A
4910 def Bar()
4911 enddef
4912 endclass
4913 class C extends B
4914 static def Baz(): number
4915 return A._Foo()
4916 enddef
4917 endclass
4918 assert_equal(1234, C.Baz())
4919 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004920 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004921
4922 # Call a private class method from a child class object
4923 lines =<< trim END
4924 vim9script
4925 class A
4926 static def _Foo(): number
4927 return 1234
4928 enddef
4929 endclass
4930 class B extends A
4931 def Bar()
4932 enddef
4933 endclass
4934 class C extends B
4935 def Baz(): number
4936 enddef
4937 endclass
4938 var c = C.new()
4939 assert_equal(1234, C._Foo())
4940 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02004941 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004942enddef
4943
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004944" Test for using the return value of a class/object method as a function
4945" argument.
4946def Test_objmethod_funcarg()
4947 var lines =<< trim END
4948 vim9script
4949
4950 class C
4951 def Foo(): string
4952 return 'foo'
4953 enddef
4954 endclass
4955
4956 def Bar(a: number, s: string): string
4957 return s
4958 enddef
4959
4960 def Baz(c: C)
4961 assert_equal('foo', Bar(10, c.Foo()))
4962 enddef
4963
4964 var t = C.new()
4965 Baz(t)
4966 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004967 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004968
4969 lines =<< trim END
4970 vim9script
4971
4972 class C
4973 static def Foo(): string
4974 return 'foo'
4975 enddef
4976 endclass
4977
4978 def Bar(a: number, s: string): string
4979 return s
4980 enddef
4981
4982 def Baz()
4983 assert_equal('foo', Bar(10, C.Foo()))
4984 enddef
4985
4986 Baz()
4987 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004988 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004989enddef
4990
Ernie Raelcf138d42023-09-06 20:45:03 +02004991def Test_static_inheritence()
4992 # subclasses get their own static copy
4993 var lines =<< trim END
4994 vim9script
4995
4996 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004997 static _svar: number
4998 this._mvar: number
4999 def new()
5000 _svar = 1
5001 this._mvar = 101
5002 enddef
5003 def AccessObject(): number
5004 return this._mvar
5005 enddef
5006 def AccessStaticThroughObject(): number
5007 return _svar
5008 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005009 endclass
5010
5011 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005012 def new()
5013 this._mvar = 102
5014 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005015 endclass
5016
5017 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005018 def new()
5019 this._mvar = 103
5020 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005021
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005022 def AccessPrivateStaticThroughClassName(): number
5023 assert_equal(1, A._svar)
5024 return 444
5025 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005026 endclass
5027
5028 var oa = A.new()
5029 var ob = B.new()
5030 var oc = C.new()
5031 assert_equal(101, oa.AccessObject())
5032 assert_equal(102, ob.AccessObject())
5033 assert_equal(103, oc.AccessObject())
5034
Ernie Rael64885642023-10-04 20:16:22 +02005035 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005036
5037 # verify object properly resolves to correct static
5038 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005039 assert_equal(1, ob.AccessStaticThroughObject())
5040 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005041 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005042 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005043enddef
5044
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005045" Test for declaring duplicate object and class members
5046def Test_dup_member_variable()
5047 # Duplicate member variable
5048 var lines =<< trim END
5049 vim9script
5050 class C
5051 this.val = 10
5052 this.val = 20
5053 endclass
5054 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005055 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005056
5057 # Duplicate private member variable
5058 lines =<< trim END
5059 vim9script
5060 class C
5061 this._val = 10
5062 this._val = 20
5063 endclass
5064 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005065 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005066
5067 # Duplicate public member variable
5068 lines =<< trim END
5069 vim9script
5070 class C
5071 public this.val = 10
5072 public this.val = 20
5073 endclass
5074 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005075 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005076
5077 # Duplicate private member variable
5078 lines =<< trim END
5079 vim9script
5080 class C
5081 this.val = 10
5082 this._val = 20
5083 endclass
5084 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005085 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005086
5087 # Duplicate public and private member variable
5088 lines =<< trim END
5089 vim9script
5090 class C
5091 this._val = 20
5092 public this.val = 10
5093 endclass
5094 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005095 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005096
5097 # Duplicate class member variable
5098 lines =<< trim END
5099 vim9script
5100 class C
5101 static s: string = "abc"
5102 static _s: string = "def"
5103 endclass
5104 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005105 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005106
5107 # Duplicate public and private class member variable
5108 lines =<< trim END
5109 vim9script
5110 class C
5111 public static s: string = "abc"
5112 static _s: string = "def"
5113 endclass
5114 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005115 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005116
5117 # Duplicate class and object member variable
5118 lines =<< trim END
5119 vim9script
5120 class C
5121 static val = 10
5122 this.val = 20
5123 def new()
5124 enddef
5125 endclass
5126 var c = C.new()
5127 assert_equal(10, C.val)
5128 assert_equal(20, c.val)
5129 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005130 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005131
5132 # Duplicate object member variable in a derived class
5133 lines =<< trim END
5134 vim9script
5135 class A
5136 this.val = 10
5137 endclass
5138 class B extends A
5139 endclass
5140 class C extends B
5141 this.val = 20
5142 endclass
5143 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005144 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005145
5146 # Duplicate object private member variable in a derived class
5147 lines =<< trim END
5148 vim9script
5149 class A
5150 this._val = 10
5151 endclass
5152 class B extends A
5153 endclass
5154 class C extends B
5155 this._val = 20
5156 endclass
5157 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005158 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005159
5160 # Duplicate object private member variable in a derived class
5161 lines =<< trim END
5162 vim9script
5163 class A
5164 this.val = 10
5165 endclass
5166 class B extends A
5167 endclass
5168 class C extends B
5169 this._val = 20
5170 endclass
5171 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005172 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005173
5174 # Duplicate object member variable in a derived class
5175 lines =<< trim END
5176 vim9script
5177 class A
5178 this._val = 10
5179 endclass
5180 class B extends A
5181 endclass
5182 class C extends B
5183 this.val = 20
5184 endclass
5185 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005186 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005187
5188 # Two member variables with a common prefix
5189 lines =<< trim END
5190 vim9script
5191 class A
5192 public static svar2: number
5193 public static svar: number
5194 endclass
5195 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005196 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005197enddef
5198
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005199" Test for accessing a private member outside a class in a def function
5200def Test_private_member_access_outside_class()
5201 # private object member variable
5202 var lines =<< trim END
5203 vim9script
5204 class A
5205 this._val = 10
5206 def GetVal(): number
5207 return this._val
5208 enddef
5209 endclass
5210 def T()
5211 var a = A.new()
5212 a._val = 20
5213 enddef
5214 T()
5215 END
Ernie Rael64885642023-10-04 20:16:22 +02005216 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005217
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005218 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005219 lines =<< trim END
5220 vim9script
5221 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005222 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005223 endclass
5224 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005225 var a = A.new()
5226 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005227 enddef
5228 T()
5229 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005230 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005231
5232 # private static member variable
5233 lines =<< trim END
5234 vim9script
5235 class A
5236 static _val = 10
5237 endclass
5238 def T()
5239 var a = A.new()
5240 var x = a._val
5241 enddef
5242 T()
5243 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005244 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005245
5246 # private static member variable
5247 lines =<< trim END
5248 vim9script
5249 class A
5250 static _val = 10
5251 endclass
5252 def T()
5253 var a = A.new()
5254 a._val = 3
5255 enddef
5256 T()
5257 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005258 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005259
5260 # private static class variable
5261 lines =<< trim END
5262 vim9script
5263 class A
5264 static _val = 10
5265 endclass
5266 def T()
5267 var x = A._val
5268 enddef
5269 T()
5270 END
Ernie Rael64885642023-10-04 20:16:22 +02005271 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02005272
5273 # private static class variable
5274 lines =<< trim END
5275 vim9script
5276 class A
5277 static _val = 10
5278 endclass
5279 def T()
5280 A._val = 3
5281 enddef
5282 T()
5283 END
Ernie Rael64885642023-10-04 20:16:22 +02005284 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005285enddef
5286
5287" Test for changing the member access of an interface in a implementation class
5288def Test_change_interface_member_access()
5289 var lines =<< trim END
5290 vim9script
5291 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005292 this.val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005293 endinterface
5294 class B implements A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005295 public this.val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005296 endclass
5297 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005298 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005299
5300 lines =<< trim END
5301 vim9script
5302 interface A
5303 this.val: number
5304 endinterface
5305 class B implements A
5306 public this.val = 10
5307 endclass
5308 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005309 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005310enddef
5311
5312" Test for trying to change a readonly member from a def function
5313def Test_readonly_member_change_in_def_func()
5314 var lines =<< trim END
5315 vim9script
5316 class A
5317 this.val: number
5318 endclass
5319 def T()
5320 var a = A.new()
5321 a.val = 20
5322 enddef
5323 T()
5324 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005325 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005326enddef
5327
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005328" Test for reading and writing a class member from a def function
5329def Test_modify_class_member_from_def_function()
5330 var lines =<< trim END
5331 vim9script
5332 class A
5333 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02005334 public static var2: list<number> = [1, 2]
5335 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005336 static _priv_var4: number = 40
5337 endclass
5338 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02005339 assert_equal([1, 2], A.var2)
5340 assert_equal({a: 1, b: 2}, A.var3)
5341 A.var2 = [3, 4]
5342 A.var3 = {c: 3, d: 4}
5343 assert_equal([3, 4], A.var2)
5344 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael64885642023-10-04 20:16:22 +02005345 assert_fails('echo A._priv_var4', 'E1333: Cannot access private variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005346 enddef
5347 T()
5348 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005349 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005350enddef
5351
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005352" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005353def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005354 var lines =<< trim END
5355 vim9script
5356 class A
5357 public static svar1: list<number> = [1]
5358 public static svar2: list<number> = [2]
5359 endclass
5360
5361 A.svar1->add(3)
5362 A.svar2->add(4)
5363 assert_equal([1, 3], A.svar1)
5364 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005365
5366 def Foo()
5367 A.svar1->add(7)
5368 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005369 assert_equal([1, 3, 7], A.svar1)
5370 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005371 enddef
5372 Foo()
5373 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005374 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005375
5376 # Cannot read from a class variable using an object in script context
5377 lines =<< trim END
5378 vim9script
5379 class A
5380 public this.var1: number
5381 public static svar2: list<number> = [1]
5382 endclass
5383
5384 var a = A.new()
5385 echo a.svar2
5386 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02005387 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005388
5389 # Cannot write to a class variable using an object in script context
5390 lines =<< trim END
5391 vim9script
5392 class A
5393 public this.var1: number
5394 public static svar2: list<number> = [1]
5395 endclass
5396
5397 var a = A.new()
5398 a.svar2 = [2]
5399 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005400 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005401
5402 # Cannot read from a class variable using an object in def method context
5403 lines =<< trim END
5404 vim9script
5405 class A
5406 public this.var1: number
5407 public static svar2: list<number> = [1]
5408 endclass
5409
5410 def T()
5411 var a = A.new()
5412 echo a.svar2
5413 enddef
5414 T()
5415 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005416 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005417
5418 # Cannot write to a class variable using an object in def method context
5419 lines =<< trim END
5420 vim9script
5421 class A
5422 public this.var1: number
5423 public static svar2: list<number> = [1]
5424 endclass
5425
5426 def T()
5427 var a = A.new()
5428 a.svar2 = [2]
5429 enddef
5430 T()
5431 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005432 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005433enddef
5434
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02005435" Test for using a interface method using a child object
5436def Test_interface_method_from_child()
5437 var lines =<< trim END
5438 vim9script
5439
5440 interface A
5441 def Foo(): string
5442 endinterface
5443
5444 class B implements A
5445 def Foo(): string
5446 return 'foo'
5447 enddef
5448 endclass
5449
5450 class C extends B
5451 def Bar(): string
5452 return 'bar'
5453 enddef
5454 endclass
5455
5456 def T1(a: A)
5457 assert_equal('foo', a.Foo())
5458 enddef
5459
5460 def T2(b: B)
5461 assert_equal('foo', b.Foo())
5462 enddef
5463
5464 var c = C.new()
5465 T1(c)
5466 T2(c)
5467 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005468 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02005469enddef
5470
5471" Test for using an interface method using a child object when it is overridden
5472" by the child class.
5473" FIXME: This test fails.
5474" def Test_interface_overridden_method_from_child()
5475" var lines =<< trim END
5476" vim9script
5477"
5478" interface A
5479" def Foo(): string
5480" endinterface
5481"
5482" class B implements A
5483" def Foo(): string
5484" return 'b-foo'
5485" enddef
5486" endclass
5487"
5488" class C extends B
5489" def Bar(): string
5490" return 'bar'
5491" enddef
5492" def Foo(): string
5493" return 'c-foo'
5494" enddef
5495" endclass
5496"
5497" def T1(a: A)
5498" assert_equal('c-foo', a.Foo())
5499" enddef
5500"
5501" def T2(b: B)
5502" assert_equal('c-foo', b.Foo())
5503" enddef
5504"
5505" var c = C.new()
5506" T1(c)
5507" T2(c)
5508" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005509" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02005510" enddef
5511
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005512" Test for abstract methods
5513def Test_abstract_method()
5514 # Use two abstract methods
5515 var lines =<< trim END
5516 vim9script
5517 abstract class A
5518 def M1(): number
5519 return 10
5520 enddef
5521 abstract def M2(): number
5522 abstract def M3(): number
5523 endclass
5524 class B extends A
5525 def M2(): number
5526 return 20
5527 enddef
5528 def M3(): number
5529 return 30
5530 enddef
5531 endclass
5532 var b = B.new()
5533 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
5534 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005535 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005536
5537 # Don't define an abstract method
5538 lines =<< trim END
5539 vim9script
5540 abstract class A
5541 abstract def Foo()
5542 endclass
5543 class B extends A
5544 endclass
5545 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005546 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005547
5548 # Use abstract method in a concrete class
5549 lines =<< trim END
5550 vim9script
5551 class A
5552 abstract def Foo()
5553 endclass
5554 class B extends A
5555 endclass
5556 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005557 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005558
5559 # Use abstract method in an interface
5560 lines =<< trim END
5561 vim9script
5562 interface A
5563 abstract def Foo()
5564 endinterface
5565 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005566 def Foo()
5567 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005568 endclass
5569 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01005570 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
5571
5572 # Use abstract static method in an interface
5573 lines =<< trim END
5574 vim9script
5575 interface A
5576 abstract static def Foo()
5577 enddef
5578 endinterface
5579 END
5580 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
5581
5582 # Use abstract static variable in an interface
5583 lines =<< trim END
5584 vim9script
5585 interface A
5586 abstract static foo: number = 10
5587 endinterface
5588 END
5589 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005590
5591 # Abbreviate the "abstract" keyword
5592 lines =<< trim END
5593 vim9script
5594 class A
5595 abs def Foo()
5596 endclass
5597 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005598 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005599
5600 # Use "abstract" with a member variable
5601 lines =<< trim END
5602 vim9script
5603 abstract class A
5604 abstract this.val = 10
5605 endclass
5606 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01005607 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005608
5609 # Use a static abstract method
Christian Brabandt33c1da72023-11-02 22:45:12 +01005610 # TODO: this does not fail, so skip it for now
5611
5612 # lines =<< trim END
5613 # vim9script
5614 # abstract class A
5615 # abstract static def Foo(): number
5616 # endclass
5617 # END
5618 # v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005619
5620 # Type mismatch between abstract method and concrete method
5621 lines =<< trim END
5622 vim9script
5623 abstract class A
5624 abstract def Foo(a: string, b: number): list<number>
5625 endclass
5626 class B extends A
5627 def Foo(a: number, b: string): list<string>
5628 return []
5629 enddef
5630 endclass
5631 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005632 v9.CheckSourceFailure(lines, 'E1383: Method "Foo": type mismatch, expected func(string, number): list<number> but got func(number, string): list<string>', 9)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005633
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005634 # Invoke an abstract method from a def function
5635 lines =<< trim END
5636 vim9script
5637 abstract class A
5638 abstract def Foo(): list<number>
5639 endclass
5640 class B extends A
5641 def Foo(): list<number>
5642 return [3, 5]
5643 enddef
5644 endclass
5645 def Bar(c: B)
5646 assert_equal([3, 5], c.Foo())
5647 enddef
5648 var b = B.new()
5649 Bar(b)
5650 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005651 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01005652
5653 # Use a static method in an abstract class
5654 lines =<< trim END
5655 vim9script
5656 abstract class A
5657 static def Foo(): string
5658 return 'foo'
5659 enddef
5660 endclass
5661 assert_equal('foo', A.Foo())
5662 END
5663 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005664enddef
5665
5666" Test for calling a class method from a subclass
5667def Test_class_method_call_from_subclass()
5668 # class method call from a subclass
5669 var lines =<< trim END
5670 vim9script
5671
5672 class A
5673 static def Foo()
5674 echo "foo"
5675 enddef
5676 endclass
5677
5678 class B extends A
5679 def Bar()
5680 Foo()
5681 enddef
5682 endclass
5683
5684 var b = B.new()
5685 b.Bar()
5686 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005687 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005688enddef
5689
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005690" Test for calling a class method using an object in a def function context and
5691" script context.
5692def Test_class_method_call_using_object()
5693 # script context
5694 var lines =<< trim END
5695 vim9script
5696 class A
5697 static def Foo(): list<string>
5698 return ['a', 'b']
5699 enddef
5700 def Bar()
5701 assert_equal(['a', 'b'], A.Foo())
5702 assert_equal(['a', 'b'], Foo())
5703 enddef
5704 endclass
5705
5706 def T()
5707 assert_equal(['a', 'b'], A.Foo())
5708 var t_a = A.new()
5709 t_a.Bar()
5710 enddef
5711
5712 assert_equal(['a', 'b'], A.Foo())
5713 var a = A.new()
5714 a.Bar()
5715 T()
5716 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005717 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005718
5719 # script context
5720 lines =<< trim END
5721 vim9script
5722 class A
5723 static def Foo(): string
5724 return 'foo'
5725 enddef
5726 endclass
5727
5728 var a = A.new()
5729 assert_equal('foo', a.Foo())
5730 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005731 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005732
5733 # def function context
5734 lines =<< trim END
5735 vim9script
5736 class A
5737 static def Foo(): string
5738 return 'foo'
5739 enddef
5740 endclass
5741
5742 def T()
5743 var a = A.new()
5744 assert_equal('foo', a.Foo())
5745 enddef
5746 T()
5747 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005748 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005749enddef
5750
5751def Test_class_variable()
5752 var lines =<< trim END
5753 vim9script
5754
5755 class A
5756 public static val: number = 10
5757 static def ClassFunc()
5758 assert_equal(10, val)
5759 enddef
5760 def ObjFunc()
5761 assert_equal(10, val)
5762 enddef
5763 endclass
5764
5765 class B extends A
5766 endclass
5767
5768 assert_equal(10, A.val)
5769 A.ClassFunc()
5770 var a = A.new()
5771 a.ObjFunc()
5772 var b = B.new()
5773 b.ObjFunc()
5774
5775 def T1(a1: A)
5776 a1.ObjFunc()
5777 A.ClassFunc()
5778 enddef
5779 T1(b)
5780
5781 A.val = 20
5782 assert_equal(20, A.val)
5783 END
5784 v9.CheckSourceSuccess(lines)
5785
5786 # Modifying a parent class variable from a child class method
5787 lines =<< trim END
5788 vim9script
5789
5790 class A
5791 static val: number = 10
5792 endclass
5793
5794 class B extends A
5795 static def ClassFunc()
5796 val = 20
5797 enddef
5798 endclass
5799 B.ClassFunc()
5800 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005801 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005802
5803 # Reading a parent class variable from a child class method
5804 lines =<< trim END
5805 vim9script
5806
5807 class A
5808 static val: number = 10
5809 endclass
5810
5811 class B extends A
5812 static def ClassFunc()
5813 var i = val
5814 enddef
5815 endclass
5816 B.ClassFunc()
5817 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005818 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005819
5820 # Modifying a parent class variable from a child object method
5821 lines =<< trim END
5822 vim9script
5823
5824 class A
5825 static val: number = 10
5826 endclass
5827
5828 class B extends A
5829 def ObjFunc()
5830 val = 20
5831 enddef
5832 endclass
5833 var b = B.new()
5834 b.ObjFunc()
5835 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005836 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005837
5838 # Reading a parent class variable from a child object method
5839 lines =<< trim END
5840 vim9script
5841
5842 class A
5843 static val: number = 10
5844 endclass
5845
5846 class B extends A
5847 def ObjFunc()
5848 var i = val
5849 enddef
5850 endclass
5851 var b = B.new()
5852 b.ObjFunc()
5853 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005854 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005855
5856 # Modifying a class variable using an object at script level
5857 lines =<< trim END
5858 vim9script
5859
5860 class A
5861 static val: number = 10
5862 endclass
5863 var a = A.new()
5864 a.val = 20
5865 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005866 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005867
5868 # Reading a class variable using an object at script level
5869 lines =<< trim END
5870 vim9script
5871
5872 class A
5873 static val: number = 10
5874 endclass
5875 var a = A.new()
5876 var i = a.val
5877 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02005878 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005879
5880 # Modifying a class variable using an object at function level
5881 lines =<< trim END
5882 vim9script
5883
5884 class A
5885 static val: number = 10
5886 endclass
5887
5888 def T()
5889 var a = A.new()
5890 a.val = 20
5891 enddef
5892 T()
5893 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005894 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005895
5896 # Reading a class variable using an object at function level
5897 lines =<< trim END
5898 vim9script
5899
5900 class A
5901 static val: number = 10
5902 endclass
5903 def T()
5904 var a = A.new()
5905 var i = a.val
5906 enddef
5907 T()
5908 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005909 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005910enddef
5911
5912" Test for using a duplicate class method and class variable in a child class
5913def Test_dup_class_member()
5914 # duplicate class variable, class method and overridden object method
5915 var lines =<< trim END
5916 vim9script
5917 class A
5918 static sval = 100
5919 static def Check()
5920 assert_equal(100, sval)
5921 enddef
5922 def GetVal(): number
5923 return sval
5924 enddef
5925 endclass
5926
5927 class B extends A
5928 static sval = 200
5929 static def Check()
5930 assert_equal(200, sval)
5931 enddef
5932 def GetVal(): number
5933 return sval
5934 enddef
5935 endclass
5936
5937 def T1(aa: A): number
5938 return aa.GetVal()
5939 enddef
5940
5941 def T2(bb: B): number
5942 return bb.GetVal()
5943 enddef
5944
5945 assert_equal(100, A.sval)
5946 assert_equal(200, B.sval)
5947 var a = A.new()
5948 assert_equal(100, a.GetVal())
5949 var b = B.new()
5950 assert_equal(200, b.GetVal())
5951 assert_equal(200, T1(b))
5952 assert_equal(200, T2(b))
5953 END
5954 v9.CheckSourceSuccess(lines)
5955
5956 # duplicate class variable and class method
5957 lines =<< trim END
5958 vim9script
5959 class A
5960 static sval = 100
5961 static def Check()
5962 assert_equal(100, sval)
5963 enddef
5964 def GetVal(): number
5965 return sval
5966 enddef
5967 endclass
5968
5969 class B extends A
5970 static sval = 200
5971 static def Check()
5972 assert_equal(200, sval)
5973 enddef
5974 endclass
5975
5976 def T1(aa: A): number
5977 return aa.GetVal()
5978 enddef
5979
5980 def T2(bb: B): number
5981 return bb.GetVal()
5982 enddef
5983
5984 assert_equal(100, A.sval)
5985 assert_equal(200, B.sval)
5986 var a = A.new()
5987 assert_equal(100, a.GetVal())
5988 var b = B.new()
5989 assert_equal(100, b.GetVal())
5990 assert_equal(100, T1(b))
5991 assert_equal(100, T2(b))
5992 END
5993 v9.CheckSourceSuccess(lines)
5994enddef
5995
5996" Test for calling an instance method using the class
5997def Test_instance_method_call_using_class()
5998 # Invoke an object method using a class in script context
5999 var lines =<< trim END
6000 vim9script
6001 class A
6002 def Foo()
6003 echo "foo"
6004 enddef
6005 endclass
6006 A.Foo()
6007 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006008 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006009
6010 # Invoke an object method using a class in def function context
6011 lines =<< trim END
6012 vim9script
6013 class A
6014 def Foo()
6015 echo "foo"
6016 enddef
6017 endclass
6018 def T()
6019 A.Foo()
6020 enddef
6021 T()
6022 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006023 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006024enddef
6025
6026" Test for duplicate class method and instance method
6027def Test_dup_classmethod_objmethod()
6028 # Duplicate instance method
6029 var lines =<< trim END
6030 vim9script
6031 class A
6032 static def Foo()
6033 enddef
6034 def Foo()
6035 enddef
6036 endclass
6037 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006038 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006039
6040 # Duplicate private instance method
6041 lines =<< trim END
6042 vim9script
6043 class A
6044 static def Foo()
6045 enddef
6046 def _Foo()
6047 enddef
6048 endclass
6049 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006050 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006051
6052 # Duplicate class method
6053 lines =<< trim END
6054 vim9script
6055 class A
6056 def Foo()
6057 enddef
6058 static def Foo()
6059 enddef
6060 endclass
6061 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006062 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006063
6064 # Duplicate private class method
6065 lines =<< trim END
6066 vim9script
6067 class A
6068 def Foo()
6069 enddef
6070 static def _Foo()
6071 enddef
6072 endclass
6073 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006074 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006075
6076 # Duplicate private class and object method
6077 lines =<< trim END
6078 vim9script
6079 class A
6080 def _Foo()
6081 enddef
6082 static def _Foo()
6083 enddef
6084 endclass
6085 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006086 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006087enddef
6088
6089" Test for an instance method access level comparison with parent instance
6090" methods.
6091def Test_instance_method_access_level()
6092 # Private method in subclass
6093 var lines =<< trim END
6094 vim9script
6095 class A
6096 def Foo()
6097 enddef
6098 endclass
6099 class B extends A
6100 endclass
6101 class C extends B
6102 def _Foo()
6103 enddef
6104 endclass
6105 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006106 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006107
6108 # Public method in subclass
6109 lines =<< trim END
6110 vim9script
6111 class A
6112 def _Foo()
6113 enddef
6114 endclass
6115 class B extends A
6116 endclass
6117 class C extends B
6118 def Foo()
6119 enddef
6120 endclass
6121 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006122 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006123enddef
6124
6125def Test_extend_empty_class()
6126 var lines =<< trim END
6127 vim9script
6128 class A
6129 endclass
6130 class B extends A
6131 endclass
6132 class C extends B
6133 public static rw_class_var = 1
6134 public this.rw_obj_var = 2
6135 static def ClassMethod(): number
6136 return 3
6137 enddef
6138 def ObjMethod(): number
6139 return 4
6140 enddef
6141 endclass
6142 assert_equal(1, C.rw_class_var)
6143 assert_equal(3, C.ClassMethod())
6144 var c = C.new()
6145 assert_equal(2, c.rw_obj_var)
6146 assert_equal(4, c.ObjMethod())
6147 END
6148 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006149enddef
6150
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006151" A interface cannot have a static variable or a static method or a private
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006152" variable or a private method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006153def Test_interface_with_unsupported_members()
6154 var lines =<< trim END
6155 vim9script
6156 interface A
6157 static num: number
6158 endinterface
6159 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006160 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006161
6162 lines =<< trim END
6163 vim9script
6164 interface A
6165 static _num: number
6166 endinterface
6167 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006168 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006169
6170 lines =<< trim END
6171 vim9script
6172 interface A
6173 public static num: number
6174 endinterface
6175 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006176 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006177
6178 lines =<< trim END
6179 vim9script
6180 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006181 public static num: number
6182 endinterface
6183 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006184 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006185
6186 lines =<< trim END
6187 vim9script
6188 interface A
6189 static _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006190 endinterface
6191 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006192 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006193
6194 lines =<< trim END
6195 vim9script
6196 interface A
6197 static def Foo(d: dict<any>): list<string>
6198 endinterface
6199 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006200 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006201
6202 lines =<< trim END
6203 vim9script
6204 interface A
6205 static def _Foo(d: dict<any>): list<string>
6206 endinterface
6207 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006208 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006209
6210 lines =<< trim END
6211 vim9script
6212 interface A
6213 this._Foo: list<string>
6214 endinterface
6215 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006216 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006217
6218 lines =<< trim END
6219 vim9script
6220 interface A
6221 def _Foo(d: dict<any>): list<string>
6222 endinterface
6223 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006224 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006225enddef
6226
6227" Test for extending an interface
6228def Test_extend_interface()
6229 var lines =<< trim END
6230 vim9script
6231 interface A
6232 this.var1: list<string>
6233 def Foo()
6234 endinterface
6235 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006236 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006237 def Bar()
6238 endinterface
6239 class C implements A, B
6240 this.var1 = [1, 2]
6241 def Foo()
6242 enddef
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006243 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006244 def Bar()
6245 enddef
6246 endclass
6247 END
6248 v9.CheckSourceSuccess(lines)
6249
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02006250 # extending empty interface
6251 lines =<< trim END
6252 vim9script
6253 interface A
6254 endinterface
6255 interface B extends A
6256 endinterface
6257 class C implements B
6258 endclass
6259 END
6260 v9.CheckSourceSuccess(lines)
6261
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006262 lines =<< trim END
6263 vim9script
6264 interface A
6265 def Foo()
6266 endinterface
6267 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006268 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006269 endinterface
6270 class C implements A, B
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006271 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006272 endclass
6273 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006274 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006275
6276 lines =<< trim END
6277 vim9script
6278 interface A
6279 def Foo()
6280 endinterface
6281 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006282 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006283 endinterface
6284 class C implements A, B
6285 def Foo()
6286 enddef
6287 endclass
6288 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006289 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006290
6291 # interface cannot extend a class
6292 lines =<< trim END
6293 vim9script
6294 class A
6295 endclass
6296 interface B extends A
6297 endinterface
6298 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006299 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006300
6301 # class cannot extend an interface
6302 lines =<< trim END
6303 vim9script
6304 interface A
6305 endinterface
6306 class B extends A
6307 endclass
6308 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006309 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006310
6311 # interface cannot implement another interface
6312 lines =<< trim END
6313 vim9script
6314 interface A
6315 endinterface
6316 interface B implements A
6317 endinterface
6318 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006319 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006320
6321 # interface cannot extend multiple interfaces
6322 lines =<< trim END
6323 vim9script
6324 interface A
6325 endinterface
6326 interface B
6327 endinterface
6328 interface C extends A, B
6329 endinterface
6330 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006331 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006332
6333 # Variable type in an extended interface is of different type
6334 lines =<< trim END
6335 vim9script
6336 interface A
6337 this.val1: number
6338 endinterface
6339 interface B extends A
6340 this.val2: string
6341 endinterface
6342 interface C extends B
6343 this.val1: string
6344 this.val2: number
6345 endinterface
6346 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006347 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006348enddef
6349
6350" Test for a child class implementing an interface when some of the methods are
6351" defined in the parent class.
6352def Test_child_class_implements_interface()
6353 var lines =<< trim END
6354 vim9script
6355
6356 interface Intf
6357 def F1(): list<list<number>>
6358 def F2(): list<list<number>>
6359 def F3(): list<list<number>>
6360 this.var1: list<dict<number>>
6361 this.var2: list<dict<number>>
6362 this.var3: list<dict<number>>
6363 endinterface
6364
6365 class A
6366 def A1()
6367 enddef
6368 def F3(): list<list<number>>
6369 return [[3]]
6370 enddef
6371 this.v1: list<list<number>> = [[0]]
6372 this.var3 = [{c: 30}]
6373 endclass
6374
6375 class B extends A
6376 def B1()
6377 enddef
6378 def F2(): list<list<number>>
6379 return [[2]]
6380 enddef
6381 this.v2: list<list<number>> = [[0]]
6382 this.var2 = [{b: 20}]
6383 endclass
6384
6385 class C extends B implements Intf
6386 def C1()
6387 enddef
6388 def F1(): list<list<number>>
6389 return [[1]]
6390 enddef
6391 this.v3: list<list<number>> = [[0]]
6392 this.var1 = [{a: 10}]
6393 endclass
6394
6395 def T(if: Intf)
6396 assert_equal([[1]], if.F1())
6397 assert_equal([[2]], if.F2())
6398 assert_equal([[3]], if.F3())
6399 assert_equal([{a: 10}], if.var1)
6400 assert_equal([{b: 20}], if.var2)
6401 assert_equal([{c: 30}], if.var3)
6402 enddef
6403
6404 var c = C.new()
6405 T(c)
6406 assert_equal([[1]], c.F1())
6407 assert_equal([[2]], c.F2())
6408 assert_equal([[3]], c.F3())
6409 assert_equal([{a: 10}], c.var1)
6410 assert_equal([{b: 20}], c.var2)
6411 assert_equal([{c: 30}], c.var3)
6412 END
6413 v9.CheckSourceSuccess(lines)
6414
6415 # One of the interface methods is not found
6416 lines =<< trim END
6417 vim9script
6418
6419 interface Intf
6420 def F1()
6421 def F2()
6422 def F3()
6423 endinterface
6424
6425 class A
6426 def A1()
6427 enddef
6428 endclass
6429
6430 class B extends A
6431 def B1()
6432 enddef
6433 def F2()
6434 enddef
6435 endclass
6436
6437 class C extends B implements Intf
6438 def C1()
6439 enddef
6440 def F1()
6441 enddef
6442 endclass
6443 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006444 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006445
6446 # One of the interface methods is of different type
6447 lines =<< trim END
6448 vim9script
6449
6450 interface Intf
6451 def F1()
6452 def F2()
6453 def F3()
6454 endinterface
6455
6456 class A
6457 def F3(): number
6458 return 0
6459 enddef
6460 def A1()
6461 enddef
6462 endclass
6463
6464 class B extends A
6465 def B1()
6466 enddef
6467 def F2()
6468 enddef
6469 endclass
6470
6471 class C extends B implements Intf
6472 def C1()
6473 enddef
6474 def F1()
6475 enddef
6476 endclass
6477 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006478 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006479
6480 # One of the interface variables is not present
6481 lines =<< trim END
6482 vim9script
6483
6484 interface Intf
6485 this.var1: list<dict<number>>
6486 this.var2: list<dict<number>>
6487 this.var3: list<dict<number>>
6488 endinterface
6489
6490 class A
6491 this.v1: list<list<number>> = [[0]]
6492 endclass
6493
6494 class B extends A
6495 this.v2: list<list<number>> = [[0]]
6496 this.var2 = [{b: 20}]
6497 endclass
6498
6499 class C extends B implements Intf
6500 this.v3: list<list<number>> = [[0]]
6501 this.var1 = [{a: 10}]
6502 endclass
6503 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006504 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006505
6506 # One of the interface variables is of different type
6507 lines =<< trim END
6508 vim9script
6509
6510 interface Intf
6511 this.var1: list<dict<number>>
6512 this.var2: list<dict<number>>
6513 this.var3: list<dict<number>>
6514 endinterface
6515
6516 class A
6517 this.v1: list<list<number>> = [[0]]
6518 this.var3: list<dict<string>>
6519 endclass
6520
6521 class B extends A
6522 this.v2: list<list<number>> = [[0]]
6523 this.var2 = [{b: 20}]
6524 endclass
6525
6526 class C extends B implements Intf
6527 this.v3: list<list<number>> = [[0]]
6528 this.var1 = [{a: 10}]
6529 endclass
6530 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006531 v9.CheckSourceFailure(lines, 'E1382: Variable "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>', 22)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006532enddef
6533
6534" Test for extending an interface with duplicate variables and methods
6535def Test_interface_extends_with_dup_members()
6536 var lines =<< trim END
6537 vim9script
6538 interface A
6539 this.n1: number
6540 def Foo1(): number
6541 endinterface
6542 interface B extends A
6543 this.n2: number
6544 this.n1: number
6545 def Foo2(): number
6546 def Foo1(): number
6547 endinterface
6548 class C implements B
6549 this.n1 = 10
6550 this.n2 = 20
6551 def Foo1(): number
6552 return 30
6553 enddef
6554 def Foo2(): number
6555 return 40
6556 enddef
6557 endclass
6558 def T1(a: A)
6559 assert_equal(10, a.n1)
6560 assert_equal(30, a.Foo1())
6561 enddef
6562 def T2(b: B)
6563 assert_equal(10, b.n1)
6564 assert_equal(20, b.n2)
6565 assert_equal(30, b.Foo1())
6566 assert_equal(40, b.Foo2())
6567 enddef
6568 var c = C.new()
6569 T1(c)
6570 T2(c)
6571 END
6572 v9.CheckSourceSuccess(lines)
6573enddef
6574
6575" Test for using "any" type for a variable in a sub-class while it has a
6576" concrete type in the interface
6577def Test_implements_using_var_type_any()
6578 var lines =<< trim END
6579 vim9script
6580 interface A
6581 this.val: list<dict<string>>
6582 endinterface
6583 class B implements A
6584 this.val = [{a: '1'}, {b: '2'}]
6585 endclass
6586 var b = B.new()
6587 assert_equal([{a: '1'}, {b: '2'}], b.val)
6588 END
6589 v9.CheckSourceSuccess(lines)
6590
6591 # initialize instance variable using a different type
6592 lines =<< trim END
6593 vim9script
6594 interface A
6595 this.val: list<dict<string>>
6596 endinterface
6597 class B implements A
6598 this.val = {a: 1, b: 2}
6599 endclass
6600 var b = B.new()
6601 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006602 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006603enddef
6604
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006605" Test for assigning to a member variable in a nested class
6606def Test_nested_object_assignment()
6607 var lines =<< trim END
6608 vim9script
6609
6610 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006611 this.value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006612 endclass
6613
6614 class B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006615 this.a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006616 endclass
6617
6618 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006619 this.b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006620 endclass
6621
6622 class D
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006623 this.c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006624 endclass
6625
6626 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006627 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006628 enddef
6629
6630 var d = D.new()
6631 T(d)
6632 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006633 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006634enddef
6635
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02006636" Test for calling methods using a null object
6637def Test_null_object_method_call()
6638 # Calling a object method using a null object in script context
6639 var lines =<< trim END
6640 vim9script
6641
6642 class C
6643 def Foo()
6644 assert_report('This method should not be executed')
6645 enddef
6646 endclass
6647
6648 var o: C
6649 o.Foo()
6650 END
6651 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
6652
6653 # Calling a object method using a null object in def function context
6654 lines =<< trim END
6655 vim9script
6656
6657 class C
6658 def Foo()
6659 assert_report('This method should not be executed')
6660 enddef
6661 endclass
6662
6663 def T()
6664 var o: C
6665 o.Foo()
6666 enddef
6667 T()
6668 END
6669 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6670
6671 # Calling a object method through another class method using a null object in
6672 # script context
6673 lines =<< trim END
6674 vim9script
6675
6676 class C
6677 def Foo()
6678 assert_report('This method should not be executed')
6679 enddef
6680
6681 static def Bar(o_any: any)
6682 var o_typed: C = o_any
6683 o_typed.Foo()
6684 enddef
6685 endclass
6686
6687 var o: C
6688 C.Bar(o)
6689 END
6690 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6691
6692 # Calling a object method through another class method using a null object in
6693 # def function context
6694 lines =<< trim END
6695 vim9script
6696
6697 class C
6698 def Foo()
6699 assert_report('This method should not be executed')
6700 enddef
6701
6702 static def Bar(o_any: any)
6703 var o_typed: C = o_any
6704 o_typed.Foo()
6705 enddef
6706 endclass
6707
6708 def T()
6709 var o: C
6710 C.Bar(o)
6711 enddef
6712 T()
6713 END
6714 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6715enddef
6716
6717" Test for using a dict as an object member
6718def Test_dict_object_member()
6719 var lines =<< trim END
6720 vim9script
6721
6722 class Context
6723 public this.state: dict<number> = {}
6724 def GetState(): dict<number>
6725 return this.state
6726 enddef
6727 endclass
6728
6729 var ctx = Context.new()
6730 ctx.state->extend({a: 1})
6731 ctx.state['b'] = 2
6732 assert_equal({a: 1, b: 2}, ctx.GetState())
6733
6734 def F()
6735 ctx.state['c'] = 3
6736 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
6737 enddef
6738 F()
6739 assert_equal(3, ctx.state.c)
6740 ctx.state.c = 4
6741 assert_equal(4, ctx.state.c)
6742 END
6743 v9.CheckSourceSuccess(lines)
6744enddef
6745
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02006746" The following test was failing after 9.0.1914. This was caused by using a
6747" freed object from a previous method call.
6748def Test_freed_object_from_previous_method_call()
6749 var lines =<< trim END
6750 vim9script
6751
6752 class Context
6753 endclass
6754
6755 class Result
6756 endclass
6757
6758 def Failure(): Result
6759 return Result.new()
6760 enddef
6761
6762 def GetResult(ctx: Context): Result
6763 return Failure()
6764 enddef
6765
6766 def Test_GetResult()
6767 var ctx = Context.new()
6768 var result = GetResult(ctx)
6769 enddef
6770
6771 Test_GetResult()
6772 END
6773 v9.CheckSourceSuccess(lines)
6774enddef
6775
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02006776" Test for duplicate object and class variable
6777def Test_duplicate_variable()
6778 # Object variable name is same as the class variable name
6779 var lines =<< trim END
6780 vim9script
6781 class A
6782 public static sval: number
6783 public this.sval: number
6784 endclass
6785 var a = A.new()
6786 END
6787 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6788
6789 # Duplicate variable name and calling a class method
6790 lines =<< trim END
6791 vim9script
6792 class A
6793 public static sval: number
6794 public this.sval: number
6795 def F1()
6796 echo this.sval
6797 enddef
6798 static def F2()
6799 echo sval
6800 enddef
6801 endclass
6802 A.F2()
6803 END
6804 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6805
6806 # Duplicate variable with an empty constructor
6807 lines =<< trim END
6808 vim9script
6809 class A
6810 public static sval: number
6811 public this.sval: number
6812 def new()
6813 enddef
6814 endclass
6815 var a = A.new()
6816 END
6817 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6818enddef
6819
6820" Test for using a reserved keyword as a variable name
6821def Test_reserved_varname()
6822 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
6823 'null_function', 'null_list', 'null_partial', 'null_string',
6824 'null_channel', 'null_job', 'super', 'this']
6825
6826 var lines =<< trim eval END
6827 vim9script
6828 class C
6829 public this.{kword}: list<number> = [1, 2, 3]
6830 endclass
6831 var o = C.new()
6832 END
6833 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6834
6835 lines =<< trim eval END
6836 vim9script
6837 class C
6838 public this.{kword}: list<number> = [1, 2, 3]
6839 def new()
6840 enddef
6841 endclass
6842 var o = C.new()
6843 END
6844 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6845
6846 lines =<< trim eval END
6847 vim9script
6848 class C
6849 public this.{kword}: list<number> = [1, 2, 3]
6850 def new()
6851 enddef
6852 def F()
6853 echo this.{kword}
6854 enddef
6855 endclass
6856 var o = C.new()
6857 o.F()
6858 END
6859 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02006860
6861 # class variable name
6862 if kword != 'this'
6863 lines =<< trim eval END
6864 vim9script
6865 class C
6866 public static {kword}: list<number> = [1, 2, 3]
6867 endclass
6868 END
6869 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6870 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02006871 endfor
6872enddef
6873
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006874" Test for checking the type of the arguments and the return value of a object
6875" method in an extended class.
6876def Test_extended_obj_method_type_check()
6877 var lines =<< trim END
6878 vim9script
6879
6880 class A
6881 endclass
6882 class B extends A
6883 endclass
6884 class C extends B
6885 endclass
6886
6887 class Foo
6888 def Doit(p: B): B
6889 return B.new()
6890 enddef
6891 endclass
6892
6893 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006894 def Doit(p: C): B
6895 return B.new()
6896 enddef
6897 endclass
6898 END
6899 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
6900
6901 lines =<< trim END
6902 vim9script
6903
6904 class A
6905 endclass
6906 class B extends A
6907 endclass
6908 class C extends B
6909 endclass
6910
6911 class Foo
6912 def Doit(p: B): B
6913 return B.new()
6914 enddef
6915 endclass
6916
6917 class Bar extends Foo
6918 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006919 return C.new()
6920 enddef
6921 endclass
6922 END
6923 v9.CheckSourceSuccess(lines)
6924
6925 lines =<< trim END
6926 vim9script
6927
6928 class A
6929 endclass
6930 class B extends A
6931 endclass
6932 class C extends B
6933 endclass
6934
6935 class Foo
6936 def Doit(p: B): B
6937 return B.new()
6938 enddef
6939 endclass
6940
6941 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006942 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006943 return B.new()
6944 enddef
6945 endclass
6946 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006947 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<A>): object<B>', 20)
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006948
6949 lines =<< trim END
6950 vim9script
6951
6952 class A
6953 endclass
6954 class B extends A
6955 endclass
6956 class C extends B
6957 endclass
6958
6959 class Foo
6960 def Doit(p: B): B
6961 return B.new()
6962 enddef
6963 endclass
6964
6965 class Bar extends Foo
6966 def Doit(p: B): A
6967 return A.new()
6968 enddef
6969 endclass
6970 END
6971 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<B>): object<A>', 20)
Ernie Rael96952b22023-10-17 18:15:01 +02006972
6973 # check varargs type mismatch
6974 lines =<< trim END
6975 vim9script
6976
6977 class B
6978 def F(...xxx: list<any>)
6979 enddef
6980 endclass
6981 class C extends B
6982 def F(xxx: list<any>)
6983 enddef
6984 endclass
6985 END
6986 v9.CheckSourceFailure(lines, 'E1383: Method "F": type mismatch, expected func(...list<any>) but got func(list<any>)', 10)
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006987enddef
6988
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006989" Test type checking for class variable in assignments
6990func Test_class_variable_complex_type_check()
6991 " class variable with a specific type. Try assigning a different type at
6992 " script level.
6993 let lines =<< trim END
6994 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006995 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006996 return {}
6997 enddef
6998 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006999 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007000 endclass
7001 test_garbagecollect_now()
7002 A.Fn = "abc"
7003 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007004 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 9)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007005
7006 " class variable with a specific type. Try assigning a different type at
7007 " class def method level.
7008 let lines =<< trim END
7009 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007010 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007011 return {}
7012 enddef
7013 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007014 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007015 def Bar()
7016 Fn = "abc"
7017 enddef
7018 endclass
7019 var a = A.new()
7020 test_garbagecollect_now()
7021 a.Bar()
7022 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007023 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007024
7025 " class variable with a specific type. Try assigning a different type at
7026 " script def method level.
7027 let lines =<< trim END
7028 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007029 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007030 return {}
7031 enddef
7032 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007033 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007034 endclass
7035 def Bar()
7036 A.Fn = "abc"
7037 enddef
7038 test_garbagecollect_now()
7039 Bar()
7040 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007041 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007042
7043 " class variable without any type. Should be set to the initialization
7044 " expression type. Try assigning a different type from script level.
7045 let lines =<< trim END
7046 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007047 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007048 return {}
7049 enddef
7050 class A
7051 public static Fn = Foo
7052 endclass
7053 test_garbagecollect_now()
7054 A.Fn = "abc"
7055 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007056 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 9)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007057
7058 " class variable without any type. Should be set to the initialization
7059 " expression type. Try assigning a different type at class def level.
7060 let lines =<< trim END
7061 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007062 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007063 return {}
7064 enddef
7065 class A
7066 public static Fn = Foo
7067 def Bar()
7068 Fn = "abc"
7069 enddef
7070 endclass
7071 var a = A.new()
7072 test_garbagecollect_now()
7073 a.Bar()
7074 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007075 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007076
7077 " class variable without any type. Should be set to the initialization
7078 " expression type. Try assigning a different type at script def level.
7079 let lines =<< trim END
7080 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007081 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007082 return {}
7083 enddef
7084 class A
7085 public static Fn = Foo
7086 endclass
7087 def Bar()
7088 A.Fn = "abc"
7089 enddef
7090 test_garbagecollect_now()
7091 Bar()
7092 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007093 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007094
7095 " class variable with 'any" type. Can be assigned different types.
7096 let lines =<< trim END
7097 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007098 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007099 return {}
7100 enddef
7101 class A
7102 public static Fn: any = Foo
7103 public static Fn2: any
7104 endclass
7105 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007106 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007107 A.Fn = "abc"
7108 test_garbagecollect_now()
7109 assert_equal('string', typename(A.Fn))
7110 A.Fn2 = Foo
7111 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007112 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007113 A.Fn2 = "xyz"
7114 test_garbagecollect_now()
7115 assert_equal('string', typename(A.Fn2))
7116 END
7117 call v9.CheckSourceSuccess(lines)
7118
7119 " class variable with 'any" type. Can be assigned different types.
7120 let lines =<< trim END
7121 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007122 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007123 return {}
7124 enddef
7125 class A
7126 public static Fn: any = Foo
7127 public static Fn2: any
7128
7129 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007130 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007131 Fn = "abc"
7132 assert_equal('string', typename(Fn))
7133 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007134 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007135 Fn2 = "xyz"
7136 assert_equal('string', typename(Fn2))
7137 enddef
7138 endclass
7139 var a = A.new()
7140 test_garbagecollect_now()
7141 a.Bar()
7142 test_garbagecollect_now()
7143 A.Fn = Foo
7144 a.Bar()
7145 END
7146 call v9.CheckSourceSuccess(lines)
7147
7148 " class variable with 'any" type. Can be assigned different types.
7149 let lines =<< trim END
7150 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007151 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007152 return {}
7153 enddef
7154 class A
7155 public static Fn: any = Foo
7156 public static Fn2: any
7157 endclass
7158
7159 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007160 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007161 A.Fn = "abc"
7162 assert_equal('string', typename(A.Fn))
7163 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007164 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007165 A.Fn2 = "xyz"
7166 assert_equal('string', typename(A.Fn2))
7167 enddef
7168 Bar()
7169 test_garbagecollect_now()
7170 A.Fn = Foo
7171 Bar()
7172 END
7173 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007174
7175 let lines =<< trim END
7176 vim9script
7177 class A
7178 public static foo = [0z10, 0z20]
7179 endclass
7180 assert_equal([0z10, 0z20], A.foo)
7181 A.foo = [0z30]
7182 assert_equal([0z30], A.foo)
7183 var a = A.foo
7184 assert_equal([0z30], a)
7185 END
7186 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007187endfunc
7188
7189" Test type checking for object variable in assignments
7190func Test_object_variable_complex_type_check()
7191 " object variable with a specific type. Try assigning a different type at
7192 " script level.
7193 let lines =<< trim END
7194 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007195 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007196 return {}
7197 enddef
7198 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007199 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007200 endclass
7201 var a = A.new()
7202 test_garbagecollect_now()
7203 a.Fn = "abc"
7204 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007205 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 10)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007206
7207 " object variable with a specific type. Try assigning a different type at
7208 " object def method level.
7209 let lines =<< trim END
7210 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007211 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007212 return {}
7213 enddef
7214 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007215 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007216 def Bar()
7217 this.Fn = "abc"
7218 this.Fn = Foo
7219 enddef
7220 endclass
7221 var a = A.new()
7222 test_garbagecollect_now()
7223 a.Bar()
7224 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007225 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007226
7227 " object variable with a specific type. Try assigning a different type at
7228 " script def method level.
7229 let lines =<< trim END
7230 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007231 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007232 return {}
7233 enddef
7234 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007235 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007236 endclass
7237 def Bar()
7238 var a = A.new()
7239 a.Fn = "abc"
7240 a.Fn = Foo
7241 enddef
7242 test_garbagecollect_now()
7243 Bar()
7244 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007245 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 2)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007246
7247 " object variable without any type. Should be set to the initialization
7248 " expression type. Try assigning a different type from script level.
7249 let lines =<< trim END
7250 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007251 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007252 return {}
7253 enddef
7254 class A
7255 public this.Fn = Foo
7256 endclass
7257 var a = A.new()
7258 test_garbagecollect_now()
7259 a.Fn = "abc"
7260 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007261 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 10)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007262
7263 " object variable without any type. Should be set to the initialization
7264 " expression type. Try assigning a different type at object def level.
7265 let lines =<< trim END
7266 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007267 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007268 return {}
7269 enddef
7270 class A
7271 public this.Fn = Foo
7272 def Bar()
7273 this.Fn = "abc"
7274 this.Fn = Foo
7275 enddef
7276 endclass
7277 var a = A.new()
7278 test_garbagecollect_now()
7279 a.Bar()
7280 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007281 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007282
7283 " object variable without any type. Should be set to the initialization
7284 " expression type. Try assigning a different type at script def level.
7285 let lines =<< trim END
7286 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007287 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007288 return {}
7289 enddef
7290 class A
7291 public this.Fn = Foo
7292 endclass
7293 def Bar()
7294 var a = A.new()
7295 a.Fn = "abc"
7296 a.Fn = Foo
7297 enddef
7298 test_garbagecollect_now()
7299 Bar()
7300 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007301 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 2)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007302
7303 " object variable with 'any" type. Can be assigned different types.
7304 let lines =<< trim END
7305 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007306 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007307 return {}
7308 enddef
7309 class A
7310 public this.Fn: any = Foo
7311 public this.Fn2: any
7312 endclass
7313
7314 var a = A.new()
7315 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007316 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007317 a.Fn = "abc"
7318 test_garbagecollect_now()
7319 assert_equal('string', typename(a.Fn))
7320 a.Fn2 = Foo
7321 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007322 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007323 a.Fn2 = "xyz"
7324 test_garbagecollect_now()
7325 assert_equal('string', typename(a.Fn2))
7326 END
7327 call v9.CheckSourceSuccess(lines)
7328
7329 " object variable with 'any" type. Can be assigned different types.
7330 let lines =<< trim END
7331 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007332 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007333 return {}
7334 enddef
7335 class A
7336 public this.Fn: any = Foo
7337 public this.Fn2: any
7338
7339 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007340 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007341 this.Fn = "abc"
7342 assert_equal('string', typename(this.Fn))
7343 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007344 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007345 this.Fn2 = "xyz"
7346 assert_equal('string', typename(this.Fn2))
7347 enddef
7348 endclass
7349
7350 var a = A.new()
7351 test_garbagecollect_now()
7352 a.Bar()
7353 test_garbagecollect_now()
7354 a.Fn = Foo
7355 a.Bar()
7356 END
7357 call v9.CheckSourceSuccess(lines)
7358
7359 " object variable with 'any" type. Can be assigned different types.
7360 let lines =<< trim END
7361 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007362 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007363 return {}
7364 enddef
7365 class A
7366 public this.Fn: any = Foo
7367 public this.Fn2: any
7368 endclass
7369
7370 def Bar()
7371 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007372 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007373 a.Fn = "abc"
7374 assert_equal('string', typename(a.Fn))
7375 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007376 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007377 a.Fn2 = "xyz"
7378 assert_equal('string', typename(a.Fn2))
7379 enddef
7380 test_garbagecollect_now()
7381 Bar()
7382 test_garbagecollect_now()
7383 Bar()
7384 END
7385 call v9.CheckSourceSuccess(lines)
7386endfunc
7387
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02007388" Test for recursively calling an object method. This used to cause an
7389" use-after-free error.
7390def Test_recursive_object_method_call()
7391 var lines =<< trim END
7392 vim9script
7393 class A
7394 this.val: number = 0
7395 def Foo(): number
7396 if this.val >= 90
7397 return this.val
7398 endif
7399 this.val += 1
7400 return this.Foo()
7401 enddef
7402 endclass
7403 var a = A.new()
7404 assert_equal(90, a.Foo())
7405 END
7406 v9.CheckSourceSuccess(lines)
7407enddef
7408
7409" Test for recursively calling a class method.
7410def Test_recursive_class_method_call()
7411 var lines =<< trim END
7412 vim9script
7413 class A
7414 static val: number = 0
7415 static def Foo(): number
7416 if val >= 90
7417 return val
7418 endif
7419 val += 1
7420 return Foo()
7421 enddef
7422 endclass
7423 assert_equal(90, A.Foo())
7424 END
7425 v9.CheckSourceSuccess(lines)
7426enddef
7427
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02007428" Test for checking the argument types and the return type when assigning a
7429" funcref to make sure the invariant class type is used.
7430def Test_funcref_argtype_returntype_check()
7431 var lines =<< trim END
7432 vim9script
7433 class A
7434 endclass
7435 class B extends A
7436 endclass
7437
7438 def Foo(p: B): B
7439 return B.new()
7440 enddef
7441
7442 var Bar: func(A): A = Foo
7443 END
7444 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
7445
7446 lines =<< trim END
7447 vim9script
7448 class A
7449 endclass
7450 class B extends A
7451 endclass
7452
7453 def Foo(p: B): B
7454 return B.new()
7455 enddef
7456
7457 def Baz()
7458 var Bar: func(A): A = Foo
7459 enddef
7460 Baz()
7461 END
7462 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
7463enddef
7464
Ernie Rael96952b22023-10-17 18:15:01 +02007465def Test_funcref_argtype_invariance_check()
7466 var lines =<< trim END
7467 vim9script
7468
7469 class A
7470 endclass
7471 class B extends A
7472 endclass
7473 class C extends B
7474 endclass
7475
7476 var Func: func(B): number
7477 Func = (o: B): number => 3
7478 assert_equal(3, Func(B.new()))
7479 END
7480 v9.CheckSourceSuccess(lines)
7481
7482 lines =<< trim END
7483 vim9script
7484
7485 class A
7486 endclass
7487 class B extends A
7488 endclass
7489 class C extends B
7490 endclass
7491
7492 var Func: func(B): number
7493 Func = (o: A): number => 3
7494 END
7495 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
7496
7497 lines =<< trim END
7498 vim9script
7499
7500 class A
7501 endclass
7502 class B extends A
7503 endclass
7504 class C extends B
7505 endclass
7506
7507 var Func: func(B): number
7508 Func = (o: C): number => 3
7509 END
7510 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
7511enddef
7512
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02007513" Test for using an operator (e.g. +) with an assignment
7514def Test_op_and_assignment()
7515 # Using += with a class variable
7516 var lines =<< trim END
7517 vim9script
7518 class A
7519 public static val: list<number> = []
7520 static def Foo(): list<number>
7521 val += [1]
7522 return val
7523 enddef
7524 endclass
7525 def Bar(): list<number>
7526 A.val += [2]
7527 return A.val
7528 enddef
7529 assert_equal([1], A.Foo())
7530 assert_equal([1, 2], Bar())
7531 A.val += [3]
7532 assert_equal([1, 2, 3], A.val)
7533 END
7534 v9.CheckSourceSuccess(lines)
7535
7536 # Using += with an object variable
7537 lines =<< trim END
7538 vim9script
7539 class A
7540 public this.val: list<number> = []
7541 def Foo(): list<number>
7542 this.val += [1]
7543 return this.val
7544 enddef
7545 endclass
7546 def Bar(bar_a: A): list<number>
7547 bar_a.val += [2]
7548 return bar_a.val
7549 enddef
7550 var a = A.new()
7551 assert_equal([1], a.Foo())
7552 assert_equal([1, 2], Bar(a))
7553 a.val += [3]
7554 assert_equal([1, 2, 3], a.val)
7555 END
7556 v9.CheckSourceSuccess(lines)
7557enddef
7558
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007559" Test for using an object method as a funcref
7560def Test_object_funcref()
7561 # Using object method funcref from a def function
7562 var lines =<< trim END
7563 vim9script
7564 class A
7565 def Foo(): list<number>
7566 return [3, 2, 1]
7567 enddef
7568 endclass
7569 def Bar()
7570 var a = A.new()
7571 var Fn = a.Foo
7572 assert_equal([3, 2, 1], Fn())
7573 enddef
7574 Bar()
7575 END
7576 v9.CheckSourceSuccess(lines)
7577
7578 # Using object method funcref at the script level
7579 lines =<< trim END
7580 vim9script
7581 class A
7582 def Foo(): dict<number>
7583 return {a: 1, b: 2}
7584 enddef
7585 endclass
7586 var a = A.new()
7587 var Fn = a.Foo
7588 assert_equal({a: 1, b: 2}, Fn())
7589 END
7590 v9.CheckSourceSuccess(lines)
7591
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007592 # Using object method funcref at the script level
7593 lines =<< trim END
7594 vim9script
7595 class A
7596 this.val: number
7597 def Foo(): number
7598 return this.val
7599 enddef
7600 endclass
7601 var a = A.new(345)
7602 var Fn = a.Foo
7603 assert_equal(345, Fn())
7604 END
7605 v9.CheckSourceSuccess(lines)
7606
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007607 # Using object method funcref from another object method
7608 lines =<< trim END
7609 vim9script
7610 class A
7611 def Foo(): list<number>
7612 return [3, 2, 1]
7613 enddef
7614 def Bar()
7615 var Fn = this.Foo
7616 assert_equal([3, 2, 1], Fn())
7617 enddef
7618 endclass
7619 var a = A.new()
7620 a.Bar()
7621 END
7622 v9.CheckSourceSuccess(lines)
7623
7624 # Using function() to get a object method funcref
7625 lines =<< trim END
7626 vim9script
7627 class A
7628 def Foo(l: list<any>): list<any>
7629 return l
7630 enddef
7631 endclass
7632 var a = A.new()
7633 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
7634 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
7635 END
7636 v9.CheckSourceSuccess(lines)
7637
7638 # Use an object method with a function returning a funcref and then call the
7639 # funcref.
7640 lines =<< trim END
7641 vim9script
7642
7643 def Map(F: func(number): number): func(number): number
7644 return (n: number) => F(n)
7645 enddef
7646
7647 class Math
7648 def Double(n: number): number
7649 return 2 * n
7650 enddef
7651 endclass
7652
7653 const math = Math.new()
7654 assert_equal(48, Map(math.Double)(24))
7655 END
7656 v9.CheckSourceSuccess(lines)
7657
7658 # Try using a private object method funcref from a def function
7659 lines =<< trim END
7660 vim9script
7661 class A
7662 def _Foo()
7663 enddef
7664 endclass
7665 def Bar()
7666 var a = A.new()
7667 var Fn = a._Foo
7668 enddef
7669 Bar()
7670 END
7671 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 2)
7672
7673 # Try using a private object method funcref at the script level
7674 lines =<< trim END
7675 vim9script
7676 class A
7677 def _Foo()
7678 enddef
7679 endclass
7680 var a = A.new()
7681 var Fn = a._Foo
7682 END
7683 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 7)
7684
7685 # Using a private object method funcref from another object method
7686 lines =<< trim END
7687 vim9script
7688 class A
7689 def _Foo(): list<number>
7690 return [3, 2, 1]
7691 enddef
7692 def Bar()
7693 var Fn = this._Foo
7694 assert_equal([3, 2, 1], Fn())
7695 enddef
7696 endclass
7697 var a = A.new()
7698 a.Bar()
7699 END
7700 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007701
7702 # Using object method funcref using call()
7703 lines =<< trim END
7704 vim9script
7705 class A
7706 this.val: number
7707 def Foo(): number
7708 return this.val
7709 enddef
7710 endclass
7711
7712 def Bar(obj: A)
7713 assert_equal(123, call(obj.Foo, []))
7714 enddef
7715
7716 var a = A.new(123)
7717 Bar(a)
7718 assert_equal(123, call(a.Foo, []))
7719 END
7720 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007721enddef
7722
7723" Test for using a class method as a funcref
7724def Test_class_funcref()
7725 # Using class method funcref in a def function
7726 var lines =<< trim END
7727 vim9script
7728 class A
7729 static def Foo(): list<number>
7730 return [3, 2, 1]
7731 enddef
7732 endclass
7733 def Bar()
7734 var Fn = A.Foo
7735 assert_equal([3, 2, 1], Fn())
7736 enddef
7737 Bar()
7738 END
7739 v9.CheckSourceSuccess(lines)
7740
7741 # Using class method funcref at script level
7742 lines =<< trim END
7743 vim9script
7744 class A
7745 static def Foo(): dict<number>
7746 return {a: 1, b: 2}
7747 enddef
7748 endclass
7749 var Fn = A.Foo
7750 assert_equal({a: 1, b: 2}, Fn())
7751 END
7752 v9.CheckSourceSuccess(lines)
7753
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007754 # Using class method funcref at the script level
7755 lines =<< trim END
7756 vim9script
7757 class A
7758 public static val: number
7759 static def Foo(): number
7760 return val
7761 enddef
7762 endclass
7763 A.val = 567
7764 var Fn = A.Foo
7765 assert_equal(567, Fn())
7766 END
7767 v9.CheckSourceSuccess(lines)
7768
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007769 # Using function() to get a class method funcref
7770 lines =<< trim END
7771 vim9script
7772 class A
7773 static def Foo(l: list<any>): list<any>
7774 return l
7775 enddef
7776 endclass
7777 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
7778 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
7779 END
7780 v9.CheckSourceSuccess(lines)
7781
7782 # Using a class method funcref from another class method
7783 lines =<< trim END
7784 vim9script
7785 class A
7786 static def Foo(): list<number>
7787 return [3, 2, 1]
7788 enddef
7789 static def Bar()
7790 var Fn = Foo
7791 assert_equal([3, 2, 1], Fn())
7792 enddef
7793 endclass
7794 A.Bar()
7795 END
7796 v9.CheckSourceSuccess(lines)
7797
7798 # Use a class method with a function returning a funcref and then call the
7799 # funcref.
7800 lines =<< trim END
7801 vim9script
7802
7803 def Map(F: func(number): number): func(number): number
7804 return (n: number) => F(n)
7805 enddef
7806
7807 class Math
7808 static def StaticDouble(n: number): number
7809 return 2 * n
7810 enddef
7811 endclass
7812
7813 assert_equal(48, Map(Math.StaticDouble)(24))
7814 END
7815 v9.CheckSourceSuccess(lines)
7816
7817 # Try using a private class method funcref in a def function
7818 lines =<< trim END
7819 vim9script
7820 class A
7821 static def _Foo()
7822 enddef
7823 endclass
7824 def Bar()
7825 var Fn = A._Foo
7826 enddef
7827 Bar()
7828 END
7829 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 1)
7830
7831 # Try using a private class method funcref at script level
7832 lines =<< trim END
7833 vim9script
7834 class A
7835 static def _Foo()
7836 enddef
7837 endclass
7838 var Fn = A._Foo
7839 END
7840 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 6)
7841
7842 # Using a private class method funcref from another class method
7843 lines =<< trim END
7844 vim9script
7845 class A
7846 static def _Foo(): list<number>
7847 return [3, 2, 1]
7848 enddef
7849 static def Bar()
7850 var Fn = _Foo
7851 assert_equal([3, 2, 1], Fn())
7852 enddef
7853 endclass
7854 A.Bar()
7855 END
7856 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007857
7858 # Using class method funcref using call()
7859 lines =<< trim END
7860 vim9script
7861 class A
7862 public static val: number
7863 static def Foo(): number
7864 return val
7865 enddef
7866 endclass
7867
7868 def Bar()
7869 A.val = 468
7870 assert_equal(468, call(A.Foo, []))
7871 enddef
7872 Bar()
7873 assert_equal(468, call(A.Foo, []))
7874 END
7875 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007876enddef
7877
7878" Test for using an object member as a funcref
7879def Test_object_member_funcref()
7880 # Using a funcref object variable in an object method
7881 var lines =<< trim END
7882 vim9script
7883 def Foo(n: number): number
7884 return n * 10
7885 enddef
7886
7887 class A
7888 this.Cb: func(number): number = Foo
7889 def Bar()
7890 assert_equal(200, this.Cb(20))
7891 enddef
7892 endclass
7893
7894 var a = A.new()
7895 a.Bar()
7896 END
7897 v9.CheckSourceSuccess(lines)
7898
7899 # Using a funcref object variable in a def method
7900 lines =<< trim END
7901 vim9script
7902 def Foo(n: number): number
7903 return n * 10
7904 enddef
7905
7906 class A
7907 this.Cb: func(number): number = Foo
7908 endclass
7909
7910 def Bar()
7911 var a = A.new()
7912 assert_equal(200, a.Cb(20))
7913 enddef
7914 Bar()
7915 END
7916 v9.CheckSourceSuccess(lines)
7917
7918 # Using a funcref object variable at script level
7919 lines =<< trim END
7920 vim9script
7921 def Foo(n: number): number
7922 return n * 10
7923 enddef
7924
7925 class A
7926 this.Cb: func(number): number = Foo
7927 endclass
7928
7929 var a = A.new()
7930 assert_equal(200, a.Cb(20))
7931 END
7932 v9.CheckSourceSuccess(lines)
7933
7934 # Using a funcref object variable pointing to an object method in an object
7935 # method.
7936 lines =<< trim END
7937 vim9script
7938 class A
7939 this.Cb: func(number): number = this.Foo
7940 def Foo(n: number): number
7941 return n * 10
7942 enddef
7943 def Bar()
7944 assert_equal(200, this.Cb(20))
7945 enddef
7946 endclass
7947
7948 var a = A.new()
7949 a.Bar()
7950 END
7951 v9.CheckSourceSuccess(lines)
7952
7953 # Using a funcref object variable pointing to an object method in a def
7954 # method.
7955 lines =<< trim END
7956 vim9script
7957 class A
7958 this.Cb: func(number): number = this.Foo
7959 def Foo(n: number): number
7960 return n * 10
7961 enddef
7962 endclass
7963
7964 def Bar()
7965 var a = A.new()
7966 assert_equal(200, a.Cb(20))
7967 enddef
7968 Bar()
7969 END
7970 v9.CheckSourceSuccess(lines)
7971
7972 # Using a funcref object variable pointing to an object method at script
7973 # level.
7974 lines =<< trim END
7975 vim9script
7976 class A
7977 this.Cb = this.Foo
7978 def Foo(n: number): number
7979 return n * 10
7980 enddef
7981 endclass
7982
7983 var a = A.new()
7984 assert_equal(200, a.Cb(20))
7985 END
7986 v9.CheckSourceSuccess(lines)
7987enddef
7988
7989" Test for using a class member as a funcref
7990def Test_class_member_funcref()
7991 # Using a funcref class variable in a class method
7992 var lines =<< trim END
7993 vim9script
7994 def Foo(n: number): number
7995 return n * 10
7996 enddef
7997
7998 class A
7999 static Cb = Foo
8000 static def Bar()
8001 assert_equal(200, Cb(20))
8002 enddef
8003 endclass
8004
8005 A.Bar()
8006 END
8007 v9.CheckSourceSuccess(lines)
8008
8009 # Using a funcref class variable in a def method
8010 lines =<< trim END
8011 vim9script
8012 def Foo(n: number): number
8013 return n * 10
8014 enddef
8015
8016 class A
8017 public static Cb = Foo
8018 endclass
8019
8020 def Bar()
8021 assert_equal(200, A.Cb(20))
8022 enddef
8023 Bar()
8024 END
8025 v9.CheckSourceSuccess(lines)
8026
8027 # Using a funcref class variable at script level
8028 lines =<< trim END
8029 vim9script
8030 def Foo(n: number): number
8031 return n * 10
8032 enddef
8033
8034 class A
8035 public static Cb = Foo
8036 endclass
8037
8038 assert_equal(200, A.Cb(20))
8039 END
8040 v9.CheckSourceSuccess(lines)
8041
8042 # Using a funcref class variable pointing to a class method in a class
8043 # method.
8044 lines =<< trim END
8045 vim9script
8046 class A
8047 static Cb: func(number): number
8048 static def Foo(n: number): number
8049 return n * 10
8050 enddef
8051 static def Init()
8052 Cb = Foo
8053 enddef
8054 static def Bar()
8055 assert_equal(200, Cb(20))
8056 enddef
8057 endclass
8058
8059 A.Init()
8060 A.Bar()
8061 END
8062 v9.CheckSourceSuccess(lines)
8063
8064 # Using a funcref class variable pointing to a class method in a def method.
8065 lines =<< trim END
8066 vim9script
8067 class A
8068 static Cb: func(number): number
8069 static def Foo(n: number): number
8070 return n * 10
8071 enddef
8072 static def Init()
8073 Cb = Foo
8074 enddef
8075 endclass
8076
8077 def Bar()
8078 A.Init()
8079 assert_equal(200, A.Cb(20))
8080 enddef
8081 Bar()
8082 END
8083 v9.CheckSourceSuccess(lines)
8084
8085 # Using a funcref class variable pointing to a class method at script level.
8086 lines =<< trim END
8087 vim9script
8088 class A
8089 static Cb: func(number): number
8090 static def Foo(n: number): number
8091 return n * 10
8092 enddef
8093 static def Init()
8094 Cb = Foo
8095 enddef
8096 endclass
8097
8098 A.Init()
8099 assert_equal(200, A.Cb(20))
8100 END
8101 v9.CheckSourceSuccess(lines)
8102enddef
8103
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008104" Test for using object methods as popup callback functions
8105def Test_objmethod_popup_callback()
8106 # Use the popup from the script level
8107 var lines =<< trim END
8108 vim9script
8109
8110 class A
8111 this.selection: number = -1
8112 this.filterkeys: list<string> = []
8113
8114 def PopupFilter(id: number, key: string): bool
8115 add(this.filterkeys, key)
8116 return popup_filter_yesno(id, key)
8117 enddef
8118
8119 def PopupCb(id: number, result: number)
8120 this.selection = result ? 100 : 200
8121 enddef
8122 endclass
8123
8124 var a = A.new()
8125 feedkeys('', 'xt')
8126 var winid = popup_create('Y/N?',
8127 {filter: a.PopupFilter, callback: a.PopupCb})
8128 feedkeys('y', 'xt')
8129 popup_close(winid)
8130 assert_equal(100, a.selection)
8131 assert_equal(['y'], a.filterkeys)
8132 feedkeys('', 'xt')
8133 winid = popup_create('Y/N?',
8134 {filter: a.PopupFilter, callback: a.PopupCb})
8135 feedkeys('n', 'xt')
8136 popup_close(winid)
8137 assert_equal(200, a.selection)
8138 assert_equal(['y', 'n'], a.filterkeys)
8139 END
8140 v9.CheckSourceSuccess(lines)
8141
8142 # Use the popup from a def function
8143 lines =<< trim END
8144 vim9script
8145
8146 class A
8147 this.selection: number = -1
8148 this.filterkeys: list<string> = []
8149
8150 def PopupFilter(id: number, key: string): bool
8151 add(this.filterkeys, key)
8152 return popup_filter_yesno(id, key)
8153 enddef
8154
8155 def PopupCb(id: number, result: number)
8156 this.selection = result ? 100 : 200
8157 enddef
8158 endclass
8159
8160 def Foo()
8161 var a = A.new()
8162 feedkeys('', 'xt')
8163 var winid = popup_create('Y/N?',
8164 {filter: a.PopupFilter, callback: a.PopupCb})
8165 feedkeys('y', 'xt')
8166 popup_close(winid)
8167 assert_equal(100, a.selection)
8168 assert_equal(['y'], a.filterkeys)
8169 feedkeys('', 'xt')
8170 winid = popup_create('Y/N?',
8171 {filter: a.PopupFilter, callback: a.PopupCb})
8172 feedkeys('n', 'xt')
8173 popup_close(winid)
8174 assert_equal(200, a.selection)
8175 assert_equal(['y', 'n'], a.filterkeys)
8176 enddef
8177 Foo()
8178 END
8179 v9.CheckSourceSuccess(lines)
8180enddef
8181
8182" Test for using class methods as popup callback functions
8183def Test_classmethod_popup_callback()
8184 # Use the popup from the script level
8185 var lines =<< trim END
8186 vim9script
8187
8188 class A
8189 static selection: number = -1
8190 static filterkeys: list<string> = []
8191
8192 static def PopupFilter(id: number, key: string): bool
8193 add(filterkeys, key)
8194 return popup_filter_yesno(id, key)
8195 enddef
8196
8197 static def PopupCb(id: number, result: number)
8198 selection = result ? 100 : 200
8199 enddef
8200 endclass
8201
8202 feedkeys('', 'xt')
8203 var winid = popup_create('Y/N?',
8204 {filter: A.PopupFilter, callback: A.PopupCb})
8205 feedkeys('y', 'xt')
8206 popup_close(winid)
8207 assert_equal(100, A.selection)
8208 assert_equal(['y'], A.filterkeys)
8209 feedkeys('', 'xt')
8210 winid = popup_create('Y/N?',
8211 {filter: A.PopupFilter, callback: A.PopupCb})
8212 feedkeys('n', 'xt')
8213 popup_close(winid)
8214 assert_equal(200, A.selection)
8215 assert_equal(['y', 'n'], A.filterkeys)
8216 END
8217 v9.CheckSourceSuccess(lines)
8218
8219 # Use the popup from a def function
8220 lines =<< trim END
8221 vim9script
8222
8223 class A
8224 static selection: number = -1
8225 static filterkeys: list<string> = []
8226
8227 static def PopupFilter(id: number, key: string): bool
8228 add(filterkeys, key)
8229 return popup_filter_yesno(id, key)
8230 enddef
8231
8232 static def PopupCb(id: number, result: number)
8233 selection = result ? 100 : 200
8234 enddef
8235 endclass
8236
8237 def Foo()
8238 feedkeys('', 'xt')
8239 var winid = popup_create('Y/N?',
8240 {filter: A.PopupFilter, callback: A.PopupCb})
8241 feedkeys('y', 'xt')
8242 popup_close(winid)
8243 assert_equal(100, A.selection)
8244 assert_equal(['y'], A.filterkeys)
8245 feedkeys('', 'xt')
8246 winid = popup_create('Y/N?',
8247 {filter: A.PopupFilter, callback: A.PopupCb})
8248 feedkeys('n', 'xt')
8249 popup_close(winid)
8250 assert_equal(200, A.selection)
8251 assert_equal(['y', 'n'], A.filterkeys)
8252 enddef
8253 Foo()
8254 END
8255 v9.CheckSourceSuccess(lines)
8256enddef
8257
8258" Test for using an object method as a timer callback function
8259def Test_objmethod_timer_callback()
8260 # Use the timer callback from script level
8261 var lines =<< trim END
8262 vim9script
8263
8264 class A
8265 this.timerTick: number = -1
8266 def TimerCb(timerID: number)
8267 this.timerTick = 6
8268 enddef
8269 endclass
8270
8271 var a = A.new()
8272 timer_start(0, a.TimerCb)
8273 var maxWait = 5
8274 while maxWait > 0 && a.timerTick == -1
8275 :sleep 10m
8276 maxWait -= 1
8277 endwhile
8278 assert_equal(6, a.timerTick)
8279 END
8280 v9.CheckSourceSuccess(lines)
8281
8282 # Use the timer callback from a def function
8283 lines =<< trim END
8284 vim9script
8285
8286 class A
8287 this.timerTick: number = -1
8288 def TimerCb(timerID: number)
8289 this.timerTick = 6
8290 enddef
8291 endclass
8292
8293 def Foo()
8294 var a = A.new()
8295 timer_start(0, a.TimerCb)
8296 var maxWait = 5
8297 while maxWait > 0 && a.timerTick == -1
8298 :sleep 10m
8299 maxWait -= 1
8300 endwhile
8301 assert_equal(6, a.timerTick)
8302 enddef
8303 Foo()
8304 END
8305 v9.CheckSourceSuccess(lines)
8306enddef
8307
8308" Test for using a class method as a timer callback function
8309def Test_classmethod_timer_callback()
8310 # Use the timer callback from script level
8311 var lines =<< trim END
8312 vim9script
8313
8314 class A
8315 static timerTick: number = -1
8316 static def TimerCb(timerID: number)
8317 timerTick = 6
8318 enddef
8319 endclass
8320
8321 timer_start(0, A.TimerCb)
8322 var maxWait = 5
8323 while maxWait > 0 && A.timerTick == -1
8324 :sleep 10m
8325 maxWait -= 1
8326 endwhile
8327 assert_equal(6, A.timerTick)
8328 END
8329 v9.CheckSourceSuccess(lines)
8330
8331 # Use the timer callback from a def function
8332 lines =<< trim END
8333 vim9script
8334
8335 class A
8336 static timerTick: number = -1
8337 static def TimerCb(timerID: number)
8338 timerTick = 6
8339 enddef
8340 endclass
8341
8342 def Foo()
8343 timer_start(0, A.TimerCb)
8344 var maxWait = 5
8345 while maxWait > 0 && A.timerTick == -1
8346 :sleep 10m
8347 maxWait -= 1
8348 endwhile
8349 assert_equal(6, A.timerTick)
8350 enddef
8351 Foo()
8352 END
8353 v9.CheckSourceSuccess(lines)
8354enddef
8355
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008356" Test for using a class variable as the first and/or second operand of a binary
8357" operator.
8358def Test_class_variable_as_operands()
8359 var lines =<< trim END
8360 vim9script
8361 class Tests
8362 static truthy: bool = true
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008363 public static TruthyFn: func
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008364 static list: list<any> = []
8365 static four: number = 4
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008366 static str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008367
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008368 static def Str(): string
8369 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008370 enddef
8371
8372 static def Four(): number
8373 return four
8374 enddef
8375
8376 static def List(): list<any>
8377 return list
8378 enddef
8379
8380 static def Truthy(): bool
8381 return truthy
8382 enddef
8383
8384 def TestOps()
8385 assert_true(Tests.truthy == truthy)
8386 assert_true(truthy == Tests.truthy)
8387 assert_true(Tests.list isnot [])
8388 assert_true([] isnot Tests.list)
8389 assert_equal(2, Tests.four >> 1)
8390 assert_equal(16, 1 << Tests.four)
8391 assert_equal(8, Tests.four + four)
8392 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008393 assert_equal('hellohello', Tests.str .. str)
8394 assert_equal('hellohello', str .. Tests.str)
8395
8396 # Using class variable for list indexing
8397 var l = range(10)
8398 assert_equal(4, l[Tests.four])
8399 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
8400
8401 # Using class variable for Dict key
8402 var d = {hello: 'abc'}
8403 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008404 enddef
8405 endclass
8406
8407 def TestOps2()
8408 assert_true(Tests.truthy == Tests.Truthy())
8409 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008410 assert_true(Tests.truthy == Tests.TruthyFn())
8411 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008412 assert_true(Tests.list is Tests.List())
8413 assert_true(Tests.List() is Tests.list)
8414 assert_equal(2, Tests.four >> 1)
8415 assert_equal(16, 1 << Tests.four)
8416 assert_equal(8, Tests.four + Tests.Four())
8417 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008418 assert_equal('hellohello', Tests.str .. Tests.Str())
8419 assert_equal('hellohello', Tests.Str() .. Tests.str)
8420
8421 # Using class variable for list indexing
8422 var l = range(10)
8423 assert_equal(4, l[Tests.four])
8424 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
8425
8426 # Using class variable for Dict key
8427 var d = {hello: 'abc'}
8428 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008429 enddef
8430
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008431 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008432 var t = Tests.new()
8433 t.TestOps()
8434 TestOps2()
8435
8436 assert_true(Tests.truthy == Tests.Truthy())
8437 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008438 assert_true(Tests.truthy == Tests.TruthyFn())
8439 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008440 assert_true(Tests.list is Tests.List())
8441 assert_true(Tests.List() is Tests.list)
8442 assert_equal(2, Tests.four >> 1)
8443 assert_equal(16, 1 << Tests.four)
8444 assert_equal(8, Tests.four + Tests.Four())
8445 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008446 assert_equal('hellohello', Tests.str .. Tests.Str())
8447 assert_equal('hellohello', Tests.Str() .. Tests.str)
8448
8449 # Using class variable for list indexing
8450 var l = range(10)
8451 assert_equal(4, l[Tests.four])
8452 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
8453
8454 # Using class variable for Dict key
8455 var d = {hello: 'abc'}
8456 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008457 END
8458 v9.CheckSourceSuccess(lines)
8459enddef
8460
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02008461" Test for checking the type of the key used to access an object dict member.
8462def Test_dict_member_key_type_check()
8463 var lines =<< trim END
8464 vim9script
8465
8466 abstract class State
8467 this.numbers: dict<string> = {0: 'nil', 1: 'unity'}
8468 endclass
8469
8470 class Test extends State
8471 def ObjMethodTests()
8472 var cursor: number = 0
8473 var z: number = 0
8474 [this.numbers[cursor]] = ['zero.1']
8475 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
8476 [this.numbers[string(cursor)], z] = ['zero.2', 1]
8477 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
8478 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
8479 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
8480 [this.numbers[cursor], z] = ['zero.4', 1]
8481 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
8482 [z, this.numbers[cursor]] = [1, 'zero.5']
8483 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
8484 enddef
8485
8486 static def ClassMethodTests(that: State)
8487 var cursor: number = 0
8488 var z: number = 0
8489 [that.numbers[cursor]] = ['zero.1']
8490 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
8491 [that.numbers[string(cursor)], z] = ['zero.2', 1]
8492 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
8493 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
8494 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
8495 [that.numbers[cursor], z] = ['zero.4', 1]
8496 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
8497 [z, that.numbers[cursor]] = [1, 'zero.5']
8498 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
8499 enddef
8500
8501 def new()
8502 enddef
8503
8504 def newMethodTests()
8505 var cursor: number = 0
8506 var z: number
8507 [this.numbers[cursor]] = ['zero.1']
8508 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
8509 [this.numbers[string(cursor)], z] = ['zero.2', 1]
8510 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
8511 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
8512 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
8513 [this.numbers[cursor], z] = ['zero.4', 1]
8514 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
8515 [z, this.numbers[cursor]] = [1, 'zero.5']
8516 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
8517 enddef
8518 endclass
8519
8520 def DefFuncTests(that: Test)
8521 var cursor: number = 0
8522 var z: number
8523 [that.numbers[cursor]] = ['zero.1']
8524 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
8525 [that.numbers[string(cursor)], z] = ['zero.2', 1]
8526 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
8527 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
8528 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
8529 [that.numbers[cursor], z] = ['zero.4', 1]
8530 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
8531 [z, that.numbers[cursor]] = [1, 'zero.5']
8532 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
8533 enddef
8534
8535 Test.newMethodTests()
8536 Test.new().ObjMethodTests()
8537 Test.ClassMethodTests(Test.new())
8538 DefFuncTests(Test.new())
8539
8540 const test: Test = Test.new()
8541 var cursor: number = 0
8542 [test.numbers[cursor], cursor] = ['zero', 1]
8543 [cursor, test.numbers[cursor]] = [1, 'one']
8544 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
8545 END
8546 v9.CheckSourceSuccess(lines)
8547
8548 lines =<< trim END
8549 vim9script
8550
8551 class A
8552 this.numbers: dict<string> = {a: '1', b: '2'}
8553
8554 def new()
8555 enddef
8556
8557 def Foo()
8558 var z: number
8559 [this.numbers.a, z] = [{}, 10]
8560 enddef
8561 endclass
8562
8563 var a = A.new()
8564 a.Foo()
8565 END
8566 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<unknown>', 2)
8567
8568 lines =<< trim END
8569 vim9script
8570
8571 class A
8572 this.numbers: dict<number> = {a: 1, b: 2}
8573
8574 def new()
8575 enddef
8576
8577 def Foo()
8578 var x: string = 'a'
8579 var y: number
8580 [this.numbers[x], y] = [{}, 10]
8581 enddef
8582 endclass
8583
8584 var a = A.new()
8585 a.Foo()
8586 END
8587 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
8588enddef
8589
Bram Moolenaar00b28d62022-12-08 15:32:33 +00008590" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker