blob: 96d3ae58ab0a58031e4eae76cb700f9f56bc1cbe [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
Ernie Rael03042a22023-11-11 08:53:32 +0100327 # Using the "public" keyword when defining an object protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200328 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
Ernie Rael03042a22023-11-11 08:53:32 +0100337 # Using the "public" keyword when defining a class protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200338 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
Ernie Rael03042a22023-11-11 08:53:32 +0100609 # Try modifying a protected variable using an "any" object
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200610 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 Rael03042a22023-11-11 08:53:32 +0100629 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected 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 Rael03042a22023-11-11 08:53:32 +01001088 assert_fails('echo trip._one', 'E1333: Cannot access protected variable "_one" in class "Triple"')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001089
Ernie Rael03042a22023-11-11 08:53:32 +01001090 assert_fails('trip._one = 11', 'E1333: Cannot access protected 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
Ernie Rael03042a22023-11-11 08:53:32 +01001324 # A protected class variable cannot be accessed from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001325 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 Rael03042a22023-11-11 08:53:32 +01001340 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001341
Ernie Rael03042a22023-11-11 08:53:32 +01001342 # A protected class variable cannot be modified from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001343 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 Rael03042a22023-11-11 08:53:32 +01001358 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected 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 Rael03042a22023-11-11 08:53:32 +01001539 assert_fails('echo TextPos._secret', 'E1333: Cannot access protected variable "_secret" in class "TextPos"')
1540 assert_fails('TextPos._secret = 8', 'E1333: Cannot access protected 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
Ernie Rael03042a22023-11-11 08:53:32 +01001586 # access protected member in lambda
Bram Moolenaar62a69232023-01-24 15:07:04 +00001587 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
Ernie Rael03042a22023-11-11 08:53:32 +01001604 # access protected member in lambda body
h-east2bd6a092023-05-19 19:01:17 +01001605 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
Ernie Rael03042a22023-11-11 08:53:32 +01001765 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 11)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001766 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
Ernie Rael03042a22023-11-11 08:53:32 +01001782 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001783 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
Ernie Rael03042a22023-11-11 08:53:32 +01001814 # Attempt to read a protected variable that is in the middle
Ernie Raele6c9aa52023-10-06 19:55:52 +02001815 # 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
Ernie Rael03042a22023-11-11 08:53:32 +01001836 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001837
Ernie Rael03042a22023-11-11 08:53:32 +01001838 # Attempt to read a protected variable that is at the start
Ernie Raele6c9aa52023-10-06 19:55:52 +02001839 # 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
Ernie Rael03042a22023-11-11 08:53:32 +01001859 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Child"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001860enddef
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
Ernie Rael03042a22023-11-11 08:53:32 +01004135 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004136 # 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
Ernie Rael03042a22023-11-11 08:53:32 +01004158 # in a class that does not own the protected variable.
4159 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02004160 # 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
Ernie Rael03042a22023-11-11 08:53:32 +01004182 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected 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
Ernie Rael03042a22023-11-11 08:53:32 +01004506" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004507def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01004508 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004509 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
Ernie Rael03042a22023-11-11 08:53:32 +01004520 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004521
Ernie Rael03042a22023-11-11 08:53:32 +01004522 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004523 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
Ernie Rael03042a22023-11-11 08:53:32 +01004537 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004538
Ernie Rael03042a22023-11-11 08:53:32 +01004539 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004540 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
Ernie Rael03042a22023-11-11 08:53:32 +01004556 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004557 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
Ernie Rael03042a22023-11-11 08:53:32 +01004576 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004577 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
Ernie Rael03042a22023-11-11 08:53:32 +01004593 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004594 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
Ernie Rael03042a22023-11-11 08:53:32 +01004604 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004605
Ernie Rael03042a22023-11-11 08:53:32 +01004606 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004607 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
Ernie Rael03042a22023-11-11 08:53:32 +01004620 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004621 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
Ernie Rael03042a22023-11-11 08:53:32 +01004634 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004635 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
Ernie Rael03042a22023-11-11 08:53:32 +01004648 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004649 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
Ernie Rael03042a22023-11-11 08:53:32 +01004672 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004673 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
Ernie Rael03042a22023-11-11 08:53:32 +01004690 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004691
Ernie Rael03042a22023-11-11 08:53:32 +01004692 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004693 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
Ernie Rael03042a22023-11-11 08:53:32 +01004714 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004715 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
Ernie Rael03042a22023-11-11 08:53:32 +01004733 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected 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
Ernie Rael03042a22023-11-11 08:53:32 +01004746" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004747def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01004748 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004749 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
Ernie Rael03042a22023-11-11 08:53:32 +01004759 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004760
Ernie Rael03042a22023-11-11 08:53:32 +01004761 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004762 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
Ernie Rael03042a22023-11-11 08:53:32 +01004775 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004776
Ernie Rael03042a22023-11-11 08:53:32 +01004777 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004778 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
Ernie Rael03042a22023-11-11 08:53:32 +01004789 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004790
Ernie Rael03042a22023-11-11 08:53:32 +01004791 # Try calling a class protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004792 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
Ernie Rael03042a22023-11-11 08:53:32 +01004806 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004807
Ernie Rael03042a22023-11-11 08:53:32 +01004808 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004809 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
Ernie Rael03042a22023-11-11 08:53:32 +01004825 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004826 # 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
Ernie Rael03042a22023-11-11 08:53:32 +01004846 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004847 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
Ernie Rael03042a22023-11-11 08:53:32 +01004860 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004861 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
Ernie Rael03042a22023-11-11 08:53:32 +01004877 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004878
Ernie Rael03042a22023-11-11 08:53:32 +01004879 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004880 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
Ernie Rael03042a22023-11-11 08:53:32 +01004899 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004900
Ernie Rael03042a22023-11-11 08:53:32 +01004901 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004902 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
Ernie Rael03042a22023-11-11 08:53:32 +01004920 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004921
Ernie Rael03042a22023-11-11 08:53:32 +01004922 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004923 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 Rael03042a22023-11-11 08:53:32 +01005035 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected 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
Ernie Rael03042a22023-11-11 08:53:32 +01005057 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005058 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
Ernie Rael03042a22023-11-11 08:53:32 +01005077 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005078 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
Ernie Rael03042a22023-11-11 08:53:32 +01005087 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005088 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
Ernie Rael03042a22023-11-11 08:53:32 +01005107 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005108 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
Ernie Rael03042a22023-11-11 08:53:32 +01005146 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005147 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
Ernie Rael03042a22023-11-11 08:53:32 +01005160 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005161 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
Ernie Rael03042a22023-11-11 08:53:32 +01005199" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005200def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01005201 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005202 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 Rael03042a22023-11-11 08:53:32 +01005216 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005217
Ernie Rael03042a22023-11-11 08:53:32 +01005218 # access a non-existing protected 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
Ernie Rael03042a22023-11-11 08:53:32 +01005232 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005233 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
Ernie Rael03042a22023-11-11 08:53:32 +01005246 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005247 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
Ernie Rael03042a22023-11-11 08:53:32 +01005260 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005261 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 Rael03042a22023-11-11 08:53:32 +01005271 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02005272
Ernie Rael03042a22023-11-11 08:53:32 +01005273 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005274 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 Rael03042a22023-11-11 08:53:32 +01005284 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected 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 Rael03042a22023-11-11 08:53:32 +01005345 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected 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
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01005610 lines =<< trim END
5611 vim9script
5612 abstract class A
5613 abstract static def Foo(): number
5614 endclass
5615 END
5616 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005617
5618 # Type mismatch between abstract method and concrete method
5619 lines =<< trim END
5620 vim9script
5621 abstract class A
5622 abstract def Foo(a: string, b: number): list<number>
5623 endclass
5624 class B extends A
5625 def Foo(a: number, b: string): list<string>
5626 return []
5627 enddef
5628 endclass
5629 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005630 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 +02005631
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005632 # Invoke an abstract method from a def function
5633 lines =<< trim END
5634 vim9script
5635 abstract class A
5636 abstract def Foo(): list<number>
5637 endclass
5638 class B extends A
5639 def Foo(): list<number>
5640 return [3, 5]
5641 enddef
5642 endclass
5643 def Bar(c: B)
5644 assert_equal([3, 5], c.Foo())
5645 enddef
5646 var b = B.new()
5647 Bar(b)
5648 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005649 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01005650
5651 # Use a static method in an abstract class
5652 lines =<< trim END
5653 vim9script
5654 abstract class A
5655 static def Foo(): string
5656 return 'foo'
5657 enddef
5658 endclass
5659 assert_equal('foo', A.Foo())
5660 END
5661 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005662enddef
5663
5664" Test for calling a class method from a subclass
5665def Test_class_method_call_from_subclass()
5666 # class method call from a subclass
5667 var lines =<< trim END
5668 vim9script
5669
5670 class A
5671 static def Foo()
5672 echo "foo"
5673 enddef
5674 endclass
5675
5676 class B extends A
5677 def Bar()
5678 Foo()
5679 enddef
5680 endclass
5681
5682 var b = B.new()
5683 b.Bar()
5684 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005685 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005686enddef
5687
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005688" Test for calling a class method using an object in a def function context and
5689" script context.
5690def Test_class_method_call_using_object()
5691 # script context
5692 var lines =<< trim END
5693 vim9script
5694 class A
5695 static def Foo(): list<string>
5696 return ['a', 'b']
5697 enddef
5698 def Bar()
5699 assert_equal(['a', 'b'], A.Foo())
5700 assert_equal(['a', 'b'], Foo())
5701 enddef
5702 endclass
5703
5704 def T()
5705 assert_equal(['a', 'b'], A.Foo())
5706 var t_a = A.new()
5707 t_a.Bar()
5708 enddef
5709
5710 assert_equal(['a', 'b'], A.Foo())
5711 var a = A.new()
5712 a.Bar()
5713 T()
5714 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005715 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005716
5717 # script context
5718 lines =<< trim END
5719 vim9script
5720 class A
5721 static def Foo(): string
5722 return 'foo'
5723 enddef
5724 endclass
5725
5726 var a = A.new()
5727 assert_equal('foo', a.Foo())
5728 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005729 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005730
5731 # def function context
5732 lines =<< trim END
5733 vim9script
5734 class A
5735 static def Foo(): string
5736 return 'foo'
5737 enddef
5738 endclass
5739
5740 def T()
5741 var a = A.new()
5742 assert_equal('foo', a.Foo())
5743 enddef
5744 T()
5745 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005746 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005747enddef
5748
5749def Test_class_variable()
5750 var lines =<< trim END
5751 vim9script
5752
5753 class A
5754 public static val: number = 10
5755 static def ClassFunc()
5756 assert_equal(10, val)
5757 enddef
5758 def ObjFunc()
5759 assert_equal(10, val)
5760 enddef
5761 endclass
5762
5763 class B extends A
5764 endclass
5765
5766 assert_equal(10, A.val)
5767 A.ClassFunc()
5768 var a = A.new()
5769 a.ObjFunc()
5770 var b = B.new()
5771 b.ObjFunc()
5772
5773 def T1(a1: A)
5774 a1.ObjFunc()
5775 A.ClassFunc()
5776 enddef
5777 T1(b)
5778
5779 A.val = 20
5780 assert_equal(20, A.val)
5781 END
5782 v9.CheckSourceSuccess(lines)
5783
5784 # Modifying a parent class variable from a child class method
5785 lines =<< trim END
5786 vim9script
5787
5788 class A
5789 static val: number = 10
5790 endclass
5791
5792 class B extends A
5793 static def ClassFunc()
5794 val = 20
5795 enddef
5796 endclass
5797 B.ClassFunc()
5798 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005799 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005800
5801 # Reading a parent class variable from a child class method
5802 lines =<< trim END
5803 vim9script
5804
5805 class A
5806 static val: number = 10
5807 endclass
5808
5809 class B extends A
5810 static def ClassFunc()
5811 var i = val
5812 enddef
5813 endclass
5814 B.ClassFunc()
5815 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005816 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005817
5818 # Modifying a parent class variable from a child object method
5819 lines =<< trim END
5820 vim9script
5821
5822 class A
5823 static val: number = 10
5824 endclass
5825
5826 class B extends A
5827 def ObjFunc()
5828 val = 20
5829 enddef
5830 endclass
5831 var b = B.new()
5832 b.ObjFunc()
5833 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005834 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005835
5836 # Reading a parent class variable from a child object method
5837 lines =<< trim END
5838 vim9script
5839
5840 class A
5841 static val: number = 10
5842 endclass
5843
5844 class B extends A
5845 def ObjFunc()
5846 var i = val
5847 enddef
5848 endclass
5849 var b = B.new()
5850 b.ObjFunc()
5851 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005852 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005853
5854 # Modifying a class variable using an object at script level
5855 lines =<< trim END
5856 vim9script
5857
5858 class A
5859 static val: number = 10
5860 endclass
5861 var a = A.new()
5862 a.val = 20
5863 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005864 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005865
5866 # Reading a class variable using an object at script level
5867 lines =<< trim END
5868 vim9script
5869
5870 class A
5871 static val: number = 10
5872 endclass
5873 var a = A.new()
5874 var i = a.val
5875 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02005876 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005877
5878 # Modifying a class variable using an object at function level
5879 lines =<< trim END
5880 vim9script
5881
5882 class A
5883 static val: number = 10
5884 endclass
5885
5886 def T()
5887 var a = A.new()
5888 a.val = 20
5889 enddef
5890 T()
5891 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005892 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005893
5894 # Reading a class variable using an object at function level
5895 lines =<< trim END
5896 vim9script
5897
5898 class A
5899 static val: number = 10
5900 endclass
5901 def T()
5902 var a = A.new()
5903 var i = a.val
5904 enddef
5905 T()
5906 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005907 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005908enddef
5909
5910" Test for using a duplicate class method and class variable in a child class
5911def Test_dup_class_member()
5912 # duplicate class variable, class method and overridden object method
5913 var lines =<< trim END
5914 vim9script
5915 class A
5916 static sval = 100
5917 static def Check()
5918 assert_equal(100, sval)
5919 enddef
5920 def GetVal(): number
5921 return sval
5922 enddef
5923 endclass
5924
5925 class B extends A
5926 static sval = 200
5927 static def Check()
5928 assert_equal(200, sval)
5929 enddef
5930 def GetVal(): number
5931 return sval
5932 enddef
5933 endclass
5934
5935 def T1(aa: A): number
5936 return aa.GetVal()
5937 enddef
5938
5939 def T2(bb: B): number
5940 return bb.GetVal()
5941 enddef
5942
5943 assert_equal(100, A.sval)
5944 assert_equal(200, B.sval)
5945 var a = A.new()
5946 assert_equal(100, a.GetVal())
5947 var b = B.new()
5948 assert_equal(200, b.GetVal())
5949 assert_equal(200, T1(b))
5950 assert_equal(200, T2(b))
5951 END
5952 v9.CheckSourceSuccess(lines)
5953
5954 # duplicate class variable and class method
5955 lines =<< trim END
5956 vim9script
5957 class A
5958 static sval = 100
5959 static def Check()
5960 assert_equal(100, sval)
5961 enddef
5962 def GetVal(): number
5963 return sval
5964 enddef
5965 endclass
5966
5967 class B extends A
5968 static sval = 200
5969 static def Check()
5970 assert_equal(200, sval)
5971 enddef
5972 endclass
5973
5974 def T1(aa: A): number
5975 return aa.GetVal()
5976 enddef
5977
5978 def T2(bb: B): number
5979 return bb.GetVal()
5980 enddef
5981
5982 assert_equal(100, A.sval)
5983 assert_equal(200, B.sval)
5984 var a = A.new()
5985 assert_equal(100, a.GetVal())
5986 var b = B.new()
5987 assert_equal(100, b.GetVal())
5988 assert_equal(100, T1(b))
5989 assert_equal(100, T2(b))
5990 END
5991 v9.CheckSourceSuccess(lines)
5992enddef
5993
5994" Test for calling an instance method using the class
5995def Test_instance_method_call_using_class()
5996 # Invoke an object method using a class in script context
5997 var lines =<< trim END
5998 vim9script
5999 class A
6000 def Foo()
6001 echo "foo"
6002 enddef
6003 endclass
6004 A.Foo()
6005 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006006 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006007
6008 # Invoke an object method using a class in def function context
6009 lines =<< trim END
6010 vim9script
6011 class A
6012 def Foo()
6013 echo "foo"
6014 enddef
6015 endclass
6016 def T()
6017 A.Foo()
6018 enddef
6019 T()
6020 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006021 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006022enddef
6023
6024" Test for duplicate class method and instance method
6025def Test_dup_classmethod_objmethod()
6026 # Duplicate instance method
6027 var lines =<< trim END
6028 vim9script
6029 class A
6030 static def Foo()
6031 enddef
6032 def Foo()
6033 enddef
6034 endclass
6035 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006036 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006037
Ernie Rael03042a22023-11-11 08:53:32 +01006038 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006039 lines =<< trim END
6040 vim9script
6041 class A
6042 static def Foo()
6043 enddef
6044 def _Foo()
6045 enddef
6046 endclass
6047 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006048 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006049
6050 # Duplicate class method
6051 lines =<< trim END
6052 vim9script
6053 class A
6054 def Foo()
6055 enddef
6056 static def Foo()
6057 enddef
6058 endclass
6059 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006060 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006061
Ernie Rael03042a22023-11-11 08:53:32 +01006062 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006063 lines =<< trim END
6064 vim9script
6065 class A
6066 def Foo()
6067 enddef
6068 static def _Foo()
6069 enddef
6070 endclass
6071 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006072 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006073
Ernie Rael03042a22023-11-11 08:53:32 +01006074 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006075 lines =<< trim END
6076 vim9script
6077 class A
6078 def _Foo()
6079 enddef
6080 static def _Foo()
6081 enddef
6082 endclass
6083 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006084 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006085enddef
6086
6087" Test for an instance method access level comparison with parent instance
6088" methods.
6089def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01006090 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006091 var lines =<< trim END
6092 vim9script
6093 class A
6094 def Foo()
6095 enddef
6096 endclass
6097 class B extends A
6098 endclass
6099 class C extends B
6100 def _Foo()
6101 enddef
6102 endclass
6103 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006104 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006105
6106 # Public method in subclass
6107 lines =<< trim END
6108 vim9script
6109 class A
6110 def _Foo()
6111 enddef
6112 endclass
6113 class B extends A
6114 endclass
6115 class C extends B
6116 def Foo()
6117 enddef
6118 endclass
6119 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006120 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006121enddef
6122
6123def Test_extend_empty_class()
6124 var lines =<< trim END
6125 vim9script
6126 class A
6127 endclass
6128 class B extends A
6129 endclass
6130 class C extends B
6131 public static rw_class_var = 1
6132 public this.rw_obj_var = 2
6133 static def ClassMethod(): number
6134 return 3
6135 enddef
6136 def ObjMethod(): number
6137 return 4
6138 enddef
6139 endclass
6140 assert_equal(1, C.rw_class_var)
6141 assert_equal(3, C.ClassMethod())
6142 var c = C.new()
6143 assert_equal(2, c.rw_obj_var)
6144 assert_equal(4, c.ObjMethod())
6145 END
6146 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006147enddef
6148
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006149" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01006150" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006151def Test_interface_with_unsupported_members()
6152 var lines =<< trim END
6153 vim9script
6154 interface A
6155 static num: number
6156 endinterface
6157 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006158 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006159
6160 lines =<< trim END
6161 vim9script
6162 interface A
6163 static _num: number
6164 endinterface
6165 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006166 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006167
6168 lines =<< trim END
6169 vim9script
6170 interface A
6171 public static num: number
6172 endinterface
6173 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006174 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006175
6176 lines =<< trim END
6177 vim9script
6178 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006179 public static num: number
6180 endinterface
6181 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006182 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006183
6184 lines =<< trim END
6185 vim9script
6186 interface A
6187 static _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006188 endinterface
6189 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006190 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006191
6192 lines =<< trim END
6193 vim9script
6194 interface A
6195 static def Foo(d: dict<any>): list<string>
6196 endinterface
6197 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006198 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006199
6200 lines =<< trim END
6201 vim9script
6202 interface A
6203 static def _Foo(d: dict<any>): list<string>
6204 endinterface
6205 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006206 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006207
6208 lines =<< trim END
6209 vim9script
6210 interface A
6211 this._Foo: list<string>
6212 endinterface
6213 END
Ernie Rael03042a22023-11-11 08:53:32 +01006214 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006215
6216 lines =<< trim END
6217 vim9script
6218 interface A
6219 def _Foo(d: dict<any>): list<string>
6220 endinterface
6221 END
Ernie Rael03042a22023-11-11 08:53:32 +01006222 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006223enddef
6224
6225" Test for extending an interface
6226def Test_extend_interface()
6227 var lines =<< trim END
6228 vim9script
6229 interface A
6230 this.var1: list<string>
6231 def Foo()
6232 endinterface
6233 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006234 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006235 def Bar()
6236 endinterface
6237 class C implements A, B
6238 this.var1 = [1, 2]
6239 def Foo()
6240 enddef
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006241 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006242 def Bar()
6243 enddef
6244 endclass
6245 END
6246 v9.CheckSourceSuccess(lines)
6247
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02006248 # extending empty interface
6249 lines =<< trim END
6250 vim9script
6251 interface A
6252 endinterface
6253 interface B extends A
6254 endinterface
6255 class C implements B
6256 endclass
6257 END
6258 v9.CheckSourceSuccess(lines)
6259
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006260 lines =<< trim END
6261 vim9script
6262 interface A
6263 def Foo()
6264 endinterface
6265 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006266 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006267 endinterface
6268 class C implements A, B
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006269 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006270 endclass
6271 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006272 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006273
6274 lines =<< trim END
6275 vim9script
6276 interface A
6277 def Foo()
6278 endinterface
6279 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006280 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006281 endinterface
6282 class C implements A, B
6283 def Foo()
6284 enddef
6285 endclass
6286 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006287 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006288
6289 # interface cannot extend a class
6290 lines =<< trim END
6291 vim9script
6292 class A
6293 endclass
6294 interface B extends A
6295 endinterface
6296 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006297 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006298
6299 # class cannot extend an interface
6300 lines =<< trim END
6301 vim9script
6302 interface A
6303 endinterface
6304 class B extends A
6305 endclass
6306 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006307 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006308
6309 # interface cannot implement another interface
6310 lines =<< trim END
6311 vim9script
6312 interface A
6313 endinterface
6314 interface B implements A
6315 endinterface
6316 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006317 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006318
6319 # interface cannot extend multiple interfaces
6320 lines =<< trim END
6321 vim9script
6322 interface A
6323 endinterface
6324 interface B
6325 endinterface
6326 interface C extends A, B
6327 endinterface
6328 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006329 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006330
6331 # Variable type in an extended interface is of different type
6332 lines =<< trim END
6333 vim9script
6334 interface A
6335 this.val1: number
6336 endinterface
6337 interface B extends A
6338 this.val2: string
6339 endinterface
6340 interface C extends B
6341 this.val1: string
6342 this.val2: number
6343 endinterface
6344 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006345 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006346enddef
6347
6348" Test for a child class implementing an interface when some of the methods are
6349" defined in the parent class.
6350def Test_child_class_implements_interface()
6351 var lines =<< trim END
6352 vim9script
6353
6354 interface Intf
6355 def F1(): list<list<number>>
6356 def F2(): list<list<number>>
6357 def F3(): list<list<number>>
6358 this.var1: list<dict<number>>
6359 this.var2: list<dict<number>>
6360 this.var3: list<dict<number>>
6361 endinterface
6362
6363 class A
6364 def A1()
6365 enddef
6366 def F3(): list<list<number>>
6367 return [[3]]
6368 enddef
6369 this.v1: list<list<number>> = [[0]]
6370 this.var3 = [{c: 30}]
6371 endclass
6372
6373 class B extends A
6374 def B1()
6375 enddef
6376 def F2(): list<list<number>>
6377 return [[2]]
6378 enddef
6379 this.v2: list<list<number>> = [[0]]
6380 this.var2 = [{b: 20}]
6381 endclass
6382
6383 class C extends B implements Intf
6384 def C1()
6385 enddef
6386 def F1(): list<list<number>>
6387 return [[1]]
6388 enddef
6389 this.v3: list<list<number>> = [[0]]
6390 this.var1 = [{a: 10}]
6391 endclass
6392
6393 def T(if: Intf)
6394 assert_equal([[1]], if.F1())
6395 assert_equal([[2]], if.F2())
6396 assert_equal([[3]], if.F3())
6397 assert_equal([{a: 10}], if.var1)
6398 assert_equal([{b: 20}], if.var2)
6399 assert_equal([{c: 30}], if.var3)
6400 enddef
6401
6402 var c = C.new()
6403 T(c)
6404 assert_equal([[1]], c.F1())
6405 assert_equal([[2]], c.F2())
6406 assert_equal([[3]], c.F3())
6407 assert_equal([{a: 10}], c.var1)
6408 assert_equal([{b: 20}], c.var2)
6409 assert_equal([{c: 30}], c.var3)
6410 END
6411 v9.CheckSourceSuccess(lines)
6412
6413 # One of the interface methods is not found
6414 lines =<< trim END
6415 vim9script
6416
6417 interface Intf
6418 def F1()
6419 def F2()
6420 def F3()
6421 endinterface
6422
6423 class A
6424 def A1()
6425 enddef
6426 endclass
6427
6428 class B extends A
6429 def B1()
6430 enddef
6431 def F2()
6432 enddef
6433 endclass
6434
6435 class C extends B implements Intf
6436 def C1()
6437 enddef
6438 def F1()
6439 enddef
6440 endclass
6441 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006442 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006443
6444 # One of the interface methods is of different type
6445 lines =<< trim END
6446 vim9script
6447
6448 interface Intf
6449 def F1()
6450 def F2()
6451 def F3()
6452 endinterface
6453
6454 class A
6455 def F3(): number
6456 return 0
6457 enddef
6458 def A1()
6459 enddef
6460 endclass
6461
6462 class B extends A
6463 def B1()
6464 enddef
6465 def F2()
6466 enddef
6467 endclass
6468
6469 class C extends B implements Intf
6470 def C1()
6471 enddef
6472 def F1()
6473 enddef
6474 endclass
6475 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006476 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006477
6478 # One of the interface variables is not present
6479 lines =<< trim END
6480 vim9script
6481
6482 interface Intf
6483 this.var1: list<dict<number>>
6484 this.var2: list<dict<number>>
6485 this.var3: list<dict<number>>
6486 endinterface
6487
6488 class A
6489 this.v1: list<list<number>> = [[0]]
6490 endclass
6491
6492 class B extends A
6493 this.v2: list<list<number>> = [[0]]
6494 this.var2 = [{b: 20}]
6495 endclass
6496
6497 class C extends B implements Intf
6498 this.v3: list<list<number>> = [[0]]
6499 this.var1 = [{a: 10}]
6500 endclass
6501 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006502 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006503
6504 # One of the interface variables is of different type
6505 lines =<< trim END
6506 vim9script
6507
6508 interface Intf
6509 this.var1: list<dict<number>>
6510 this.var2: list<dict<number>>
6511 this.var3: list<dict<number>>
6512 endinterface
6513
6514 class A
6515 this.v1: list<list<number>> = [[0]]
6516 this.var3: list<dict<string>>
6517 endclass
6518
6519 class B extends A
6520 this.v2: list<list<number>> = [[0]]
6521 this.var2 = [{b: 20}]
6522 endclass
6523
6524 class C extends B implements Intf
6525 this.v3: list<list<number>> = [[0]]
6526 this.var1 = [{a: 10}]
6527 endclass
6528 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006529 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 +02006530enddef
6531
6532" Test for extending an interface with duplicate variables and methods
6533def Test_interface_extends_with_dup_members()
6534 var lines =<< trim END
6535 vim9script
6536 interface A
6537 this.n1: number
6538 def Foo1(): number
6539 endinterface
6540 interface B extends A
6541 this.n2: number
6542 this.n1: number
6543 def Foo2(): number
6544 def Foo1(): number
6545 endinterface
6546 class C implements B
6547 this.n1 = 10
6548 this.n2 = 20
6549 def Foo1(): number
6550 return 30
6551 enddef
6552 def Foo2(): number
6553 return 40
6554 enddef
6555 endclass
6556 def T1(a: A)
6557 assert_equal(10, a.n1)
6558 assert_equal(30, a.Foo1())
6559 enddef
6560 def T2(b: B)
6561 assert_equal(10, b.n1)
6562 assert_equal(20, b.n2)
6563 assert_equal(30, b.Foo1())
6564 assert_equal(40, b.Foo2())
6565 enddef
6566 var c = C.new()
6567 T1(c)
6568 T2(c)
6569 END
6570 v9.CheckSourceSuccess(lines)
6571enddef
6572
6573" Test for using "any" type for a variable in a sub-class while it has a
6574" concrete type in the interface
6575def Test_implements_using_var_type_any()
6576 var lines =<< trim END
6577 vim9script
6578 interface A
6579 this.val: list<dict<string>>
6580 endinterface
6581 class B implements A
6582 this.val = [{a: '1'}, {b: '2'}]
6583 endclass
6584 var b = B.new()
6585 assert_equal([{a: '1'}, {b: '2'}], b.val)
6586 END
6587 v9.CheckSourceSuccess(lines)
6588
6589 # initialize instance variable using a different type
6590 lines =<< trim END
6591 vim9script
6592 interface A
6593 this.val: list<dict<string>>
6594 endinterface
6595 class B implements A
6596 this.val = {a: 1, b: 2}
6597 endclass
6598 var b = B.new()
6599 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006600 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006601enddef
6602
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006603" Test for assigning to a member variable in a nested class
6604def Test_nested_object_assignment()
6605 var lines =<< trim END
6606 vim9script
6607
6608 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006609 this.value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006610 endclass
6611
6612 class B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006613 this.a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006614 endclass
6615
6616 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006617 this.b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006618 endclass
6619
6620 class D
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006621 this.c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006622 endclass
6623
6624 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006625 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006626 enddef
6627
6628 var d = D.new()
6629 T(d)
6630 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006631 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006632enddef
6633
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02006634" Test for calling methods using a null object
6635def Test_null_object_method_call()
6636 # Calling a object method using a null object in script context
6637 var lines =<< trim END
6638 vim9script
6639
6640 class C
6641 def Foo()
6642 assert_report('This method should not be executed')
6643 enddef
6644 endclass
6645
6646 var o: C
6647 o.Foo()
6648 END
6649 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
6650
6651 # Calling a object method using a null object in def function context
6652 lines =<< trim END
6653 vim9script
6654
6655 class C
6656 def Foo()
6657 assert_report('This method should not be executed')
6658 enddef
6659 endclass
6660
6661 def T()
6662 var o: C
6663 o.Foo()
6664 enddef
6665 T()
6666 END
6667 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6668
6669 # Calling a object method through another class method using a null object in
6670 # script context
6671 lines =<< trim END
6672 vim9script
6673
6674 class C
6675 def Foo()
6676 assert_report('This method should not be executed')
6677 enddef
6678
6679 static def Bar(o_any: any)
6680 var o_typed: C = o_any
6681 o_typed.Foo()
6682 enddef
6683 endclass
6684
6685 var o: C
6686 C.Bar(o)
6687 END
6688 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6689
6690 # Calling a object method through another class method using a null object in
6691 # def function context
6692 lines =<< trim END
6693 vim9script
6694
6695 class C
6696 def Foo()
6697 assert_report('This method should not be executed')
6698 enddef
6699
6700 static def Bar(o_any: any)
6701 var o_typed: C = o_any
6702 o_typed.Foo()
6703 enddef
6704 endclass
6705
6706 def T()
6707 var o: C
6708 C.Bar(o)
6709 enddef
6710 T()
6711 END
6712 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6713enddef
6714
6715" Test for using a dict as an object member
6716def Test_dict_object_member()
6717 var lines =<< trim END
6718 vim9script
6719
6720 class Context
6721 public this.state: dict<number> = {}
6722 def GetState(): dict<number>
6723 return this.state
6724 enddef
6725 endclass
6726
6727 var ctx = Context.new()
6728 ctx.state->extend({a: 1})
6729 ctx.state['b'] = 2
6730 assert_equal({a: 1, b: 2}, ctx.GetState())
6731
6732 def F()
6733 ctx.state['c'] = 3
6734 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
6735 enddef
6736 F()
6737 assert_equal(3, ctx.state.c)
6738 ctx.state.c = 4
6739 assert_equal(4, ctx.state.c)
6740 END
6741 v9.CheckSourceSuccess(lines)
6742enddef
6743
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02006744" The following test was failing after 9.0.1914. This was caused by using a
6745" freed object from a previous method call.
6746def Test_freed_object_from_previous_method_call()
6747 var lines =<< trim END
6748 vim9script
6749
6750 class Context
6751 endclass
6752
6753 class Result
6754 endclass
6755
6756 def Failure(): Result
6757 return Result.new()
6758 enddef
6759
6760 def GetResult(ctx: Context): Result
6761 return Failure()
6762 enddef
6763
6764 def Test_GetResult()
6765 var ctx = Context.new()
6766 var result = GetResult(ctx)
6767 enddef
6768
6769 Test_GetResult()
6770 END
6771 v9.CheckSourceSuccess(lines)
6772enddef
6773
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02006774" Test for duplicate object and class variable
6775def Test_duplicate_variable()
6776 # Object variable name is same as the class variable name
6777 var lines =<< trim END
6778 vim9script
6779 class A
6780 public static sval: number
6781 public this.sval: number
6782 endclass
6783 var a = A.new()
6784 END
6785 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6786
6787 # Duplicate variable name and calling a class method
6788 lines =<< trim END
6789 vim9script
6790 class A
6791 public static sval: number
6792 public this.sval: number
6793 def F1()
6794 echo this.sval
6795 enddef
6796 static def F2()
6797 echo sval
6798 enddef
6799 endclass
6800 A.F2()
6801 END
6802 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6803
6804 # Duplicate variable with an empty constructor
6805 lines =<< trim END
6806 vim9script
6807 class A
6808 public static sval: number
6809 public this.sval: number
6810 def new()
6811 enddef
6812 endclass
6813 var a = A.new()
6814 END
6815 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6816enddef
6817
6818" Test for using a reserved keyword as a variable name
6819def Test_reserved_varname()
6820 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
6821 'null_function', 'null_list', 'null_partial', 'null_string',
6822 'null_channel', 'null_job', 'super', 'this']
6823
6824 var lines =<< trim eval END
6825 vim9script
6826 class C
6827 public this.{kword}: list<number> = [1, 2, 3]
6828 endclass
6829 var o = C.new()
6830 END
6831 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6832
6833 lines =<< trim eval END
6834 vim9script
6835 class C
6836 public this.{kword}: list<number> = [1, 2, 3]
6837 def new()
6838 enddef
6839 endclass
6840 var o = C.new()
6841 END
6842 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6843
6844 lines =<< trim eval END
6845 vim9script
6846 class C
6847 public this.{kword}: list<number> = [1, 2, 3]
6848 def new()
6849 enddef
6850 def F()
6851 echo this.{kword}
6852 enddef
6853 endclass
6854 var o = C.new()
6855 o.F()
6856 END
6857 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02006858
6859 # class variable name
6860 if kword != 'this'
6861 lines =<< trim eval END
6862 vim9script
6863 class C
6864 public static {kword}: list<number> = [1, 2, 3]
6865 endclass
6866 END
6867 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6868 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02006869 endfor
6870enddef
6871
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006872" Test for checking the type of the arguments and the return value of a object
6873" method in an extended class.
6874def Test_extended_obj_method_type_check()
6875 var lines =<< trim END
6876 vim9script
6877
6878 class A
6879 endclass
6880 class B extends A
6881 endclass
6882 class C extends B
6883 endclass
6884
6885 class Foo
6886 def Doit(p: B): B
6887 return B.new()
6888 enddef
6889 endclass
6890
6891 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006892 def Doit(p: C): B
6893 return B.new()
6894 enddef
6895 endclass
6896 END
6897 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
6898
6899 lines =<< trim END
6900 vim9script
6901
6902 class A
6903 endclass
6904 class B extends A
6905 endclass
6906 class C extends B
6907 endclass
6908
6909 class Foo
6910 def Doit(p: B): B
6911 return B.new()
6912 enddef
6913 endclass
6914
6915 class Bar extends Foo
6916 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006917 return C.new()
6918 enddef
6919 endclass
6920 END
6921 v9.CheckSourceSuccess(lines)
6922
6923 lines =<< trim END
6924 vim9script
6925
6926 class A
6927 endclass
6928 class B extends A
6929 endclass
6930 class C extends B
6931 endclass
6932
6933 class Foo
6934 def Doit(p: B): B
6935 return B.new()
6936 enddef
6937 endclass
6938
6939 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006940 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006941 return B.new()
6942 enddef
6943 endclass
6944 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006945 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 +02006946
6947 lines =<< trim END
6948 vim9script
6949
6950 class A
6951 endclass
6952 class B extends A
6953 endclass
6954 class C extends B
6955 endclass
6956
6957 class Foo
6958 def Doit(p: B): B
6959 return B.new()
6960 enddef
6961 endclass
6962
6963 class Bar extends Foo
6964 def Doit(p: B): A
6965 return A.new()
6966 enddef
6967 endclass
6968 END
6969 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 +02006970
6971 # check varargs type mismatch
6972 lines =<< trim END
6973 vim9script
6974
6975 class B
6976 def F(...xxx: list<any>)
6977 enddef
6978 endclass
6979 class C extends B
6980 def F(xxx: list<any>)
6981 enddef
6982 endclass
6983 END
6984 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 +02006985enddef
6986
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006987" Test type checking for class variable in assignments
6988func Test_class_variable_complex_type_check()
6989 " class variable with a specific type. Try assigning a different type at
6990 " script level.
6991 let lines =<< trim END
6992 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006993 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006994 return {}
6995 enddef
6996 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006997 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006998 endclass
6999 test_garbagecollect_now()
7000 A.Fn = "abc"
7001 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007002 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 +02007003
7004 " class variable with a specific type. Try assigning a different type at
7005 " class def method level.
7006 let lines =<< trim END
7007 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007008 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007009 return {}
7010 enddef
7011 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007012 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007013 def Bar()
7014 Fn = "abc"
7015 enddef
7016 endclass
7017 var a = A.new()
7018 test_garbagecollect_now()
7019 a.Bar()
7020 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007021 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 +02007022
7023 " class variable with a specific type. Try assigning a different type at
7024 " script def method level.
7025 let lines =<< trim END
7026 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007027 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007028 return {}
7029 enddef
7030 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007031 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007032 endclass
7033 def Bar()
7034 A.Fn = "abc"
7035 enddef
7036 test_garbagecollect_now()
7037 Bar()
7038 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007039 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 +02007040
7041 " class variable without any type. Should be set to the initialization
7042 " expression type. Try assigning a different type from script level.
7043 let lines =<< trim END
7044 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007045 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007046 return {}
7047 enddef
7048 class A
7049 public static Fn = Foo
7050 endclass
7051 test_garbagecollect_now()
7052 A.Fn = "abc"
7053 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007054 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 +02007055
7056 " class variable without any type. Should be set to the initialization
7057 " expression type. Try assigning a different type at class def level.
7058 let lines =<< trim END
7059 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007060 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007061 return {}
7062 enddef
7063 class A
7064 public static Fn = Foo
7065 def Bar()
7066 Fn = "abc"
7067 enddef
7068 endclass
7069 var a = A.new()
7070 test_garbagecollect_now()
7071 a.Bar()
7072 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007073 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 +02007074
7075 " class variable without any type. Should be set to the initialization
7076 " expression type. Try assigning a different type at script def level.
7077 let lines =<< trim END
7078 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007079 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007080 return {}
7081 enddef
7082 class A
7083 public static Fn = Foo
7084 endclass
7085 def Bar()
7086 A.Fn = "abc"
7087 enddef
7088 test_garbagecollect_now()
7089 Bar()
7090 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007091 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 +02007092
7093 " class variable with 'any" type. Can be assigned different types.
7094 let lines =<< trim END
7095 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007096 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007097 return {}
7098 enddef
7099 class A
7100 public static Fn: any = Foo
7101 public static Fn2: any
7102 endclass
7103 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007104 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007105 A.Fn = "abc"
7106 test_garbagecollect_now()
7107 assert_equal('string', typename(A.Fn))
7108 A.Fn2 = Foo
7109 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007110 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007111 A.Fn2 = "xyz"
7112 test_garbagecollect_now()
7113 assert_equal('string', typename(A.Fn2))
7114 END
7115 call v9.CheckSourceSuccess(lines)
7116
7117 " class variable with 'any" type. Can be assigned different types.
7118 let lines =<< trim END
7119 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007120 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007121 return {}
7122 enddef
7123 class A
7124 public static Fn: any = Foo
7125 public static Fn2: any
7126
7127 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007128 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007129 Fn = "abc"
7130 assert_equal('string', typename(Fn))
7131 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007132 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007133 Fn2 = "xyz"
7134 assert_equal('string', typename(Fn2))
7135 enddef
7136 endclass
7137 var a = A.new()
7138 test_garbagecollect_now()
7139 a.Bar()
7140 test_garbagecollect_now()
7141 A.Fn = Foo
7142 a.Bar()
7143 END
7144 call v9.CheckSourceSuccess(lines)
7145
7146 " class variable with 'any" type. Can be assigned different types.
7147 let lines =<< trim END
7148 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007149 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007150 return {}
7151 enddef
7152 class A
7153 public static Fn: any = Foo
7154 public static Fn2: any
7155 endclass
7156
7157 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007158 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007159 A.Fn = "abc"
7160 assert_equal('string', typename(A.Fn))
7161 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007162 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007163 A.Fn2 = "xyz"
7164 assert_equal('string', typename(A.Fn2))
7165 enddef
7166 Bar()
7167 test_garbagecollect_now()
7168 A.Fn = Foo
7169 Bar()
7170 END
7171 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007172
7173 let lines =<< trim END
7174 vim9script
7175 class A
7176 public static foo = [0z10, 0z20]
7177 endclass
7178 assert_equal([0z10, 0z20], A.foo)
7179 A.foo = [0z30]
7180 assert_equal([0z30], A.foo)
7181 var a = A.foo
7182 assert_equal([0z30], a)
7183 END
7184 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007185endfunc
7186
7187" Test type checking for object variable in assignments
7188func Test_object_variable_complex_type_check()
7189 " object variable with a specific type. Try assigning a different type at
7190 " script level.
7191 let lines =<< trim END
7192 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007193 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007194 return {}
7195 enddef
7196 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007197 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007198 endclass
7199 var a = A.new()
7200 test_garbagecollect_now()
7201 a.Fn = "abc"
7202 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007203 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 +02007204
7205 " object variable with a specific type. Try assigning a different type at
7206 " object def method level.
7207 let lines =<< trim END
7208 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007209 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007210 return {}
7211 enddef
7212 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007213 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007214 def Bar()
7215 this.Fn = "abc"
7216 this.Fn = Foo
7217 enddef
7218 endclass
7219 var a = A.new()
7220 test_garbagecollect_now()
7221 a.Bar()
7222 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007223 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 +02007224
7225 " object variable with a specific type. Try assigning a different type at
7226 " script def method level.
7227 let lines =<< trim END
7228 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007229 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007230 return {}
7231 enddef
7232 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007233 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007234 endclass
7235 def Bar()
7236 var a = A.new()
7237 a.Fn = "abc"
7238 a.Fn = Foo
7239 enddef
7240 test_garbagecollect_now()
7241 Bar()
7242 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007243 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 +02007244
7245 " object variable without any type. Should be set to the initialization
7246 " expression type. Try assigning a different type from script level.
7247 let lines =<< trim END
7248 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007249 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007250 return {}
7251 enddef
7252 class A
7253 public this.Fn = Foo
7254 endclass
7255 var a = A.new()
7256 test_garbagecollect_now()
7257 a.Fn = "abc"
7258 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007259 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 +02007260
7261 " object variable without any type. Should be set to the initialization
7262 " expression type. Try assigning a different type at object def level.
7263 let lines =<< trim END
7264 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007265 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007266 return {}
7267 enddef
7268 class A
7269 public this.Fn = Foo
7270 def Bar()
7271 this.Fn = "abc"
7272 this.Fn = Foo
7273 enddef
7274 endclass
7275 var a = A.new()
7276 test_garbagecollect_now()
7277 a.Bar()
7278 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007279 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 +02007280
7281 " object variable without any type. Should be set to the initialization
7282 " expression type. Try assigning a different type at script def level.
7283 let lines =<< trim END
7284 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007285 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007286 return {}
7287 enddef
7288 class A
7289 public this.Fn = Foo
7290 endclass
7291 def Bar()
7292 var a = A.new()
7293 a.Fn = "abc"
7294 a.Fn = Foo
7295 enddef
7296 test_garbagecollect_now()
7297 Bar()
7298 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007299 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 +02007300
7301 " object variable with 'any" type. Can be assigned different types.
7302 let lines =<< trim END
7303 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007304 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007305 return {}
7306 enddef
7307 class A
7308 public this.Fn: any = Foo
7309 public this.Fn2: any
7310 endclass
7311
7312 var a = A.new()
7313 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007314 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007315 a.Fn = "abc"
7316 test_garbagecollect_now()
7317 assert_equal('string', typename(a.Fn))
7318 a.Fn2 = Foo
7319 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007320 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007321 a.Fn2 = "xyz"
7322 test_garbagecollect_now()
7323 assert_equal('string', typename(a.Fn2))
7324 END
7325 call v9.CheckSourceSuccess(lines)
7326
7327 " object variable with 'any" type. Can be assigned different types.
7328 let lines =<< trim END
7329 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007330 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007331 return {}
7332 enddef
7333 class A
7334 public this.Fn: any = Foo
7335 public this.Fn2: any
7336
7337 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007338 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007339 this.Fn = "abc"
7340 assert_equal('string', typename(this.Fn))
7341 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007342 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007343 this.Fn2 = "xyz"
7344 assert_equal('string', typename(this.Fn2))
7345 enddef
7346 endclass
7347
7348 var a = A.new()
7349 test_garbagecollect_now()
7350 a.Bar()
7351 test_garbagecollect_now()
7352 a.Fn = Foo
7353 a.Bar()
7354 END
7355 call v9.CheckSourceSuccess(lines)
7356
7357 " object variable with 'any" type. Can be assigned different types.
7358 let lines =<< trim END
7359 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007360 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007361 return {}
7362 enddef
7363 class A
7364 public this.Fn: any = Foo
7365 public this.Fn2: any
7366 endclass
7367
7368 def Bar()
7369 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007370 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007371 a.Fn = "abc"
7372 assert_equal('string', typename(a.Fn))
7373 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007374 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007375 a.Fn2 = "xyz"
7376 assert_equal('string', typename(a.Fn2))
7377 enddef
7378 test_garbagecollect_now()
7379 Bar()
7380 test_garbagecollect_now()
7381 Bar()
7382 END
7383 call v9.CheckSourceSuccess(lines)
7384endfunc
7385
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02007386" Test for recursively calling an object method. This used to cause an
7387" use-after-free error.
7388def Test_recursive_object_method_call()
7389 var lines =<< trim END
7390 vim9script
7391 class A
7392 this.val: number = 0
7393 def Foo(): number
7394 if this.val >= 90
7395 return this.val
7396 endif
7397 this.val += 1
7398 return this.Foo()
7399 enddef
7400 endclass
7401 var a = A.new()
7402 assert_equal(90, a.Foo())
7403 END
7404 v9.CheckSourceSuccess(lines)
7405enddef
7406
7407" Test for recursively calling a class method.
7408def Test_recursive_class_method_call()
7409 var lines =<< trim END
7410 vim9script
7411 class A
7412 static val: number = 0
7413 static def Foo(): number
7414 if val >= 90
7415 return val
7416 endif
7417 val += 1
7418 return Foo()
7419 enddef
7420 endclass
7421 assert_equal(90, A.Foo())
7422 END
7423 v9.CheckSourceSuccess(lines)
7424enddef
7425
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02007426" Test for checking the argument types and the return type when assigning a
7427" funcref to make sure the invariant class type is used.
7428def Test_funcref_argtype_returntype_check()
7429 var lines =<< trim END
7430 vim9script
7431 class A
7432 endclass
7433 class B extends A
7434 endclass
7435
7436 def Foo(p: B): B
7437 return B.new()
7438 enddef
7439
7440 var Bar: func(A): A = Foo
7441 END
7442 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
7443
7444 lines =<< trim END
7445 vim9script
7446 class A
7447 endclass
7448 class B extends A
7449 endclass
7450
7451 def Foo(p: B): B
7452 return B.new()
7453 enddef
7454
7455 def Baz()
7456 var Bar: func(A): A = Foo
7457 enddef
7458 Baz()
7459 END
7460 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
7461enddef
7462
Ernie Rael96952b22023-10-17 18:15:01 +02007463def Test_funcref_argtype_invariance_check()
7464 var lines =<< trim END
7465 vim9script
7466
7467 class A
7468 endclass
7469 class B extends A
7470 endclass
7471 class C extends B
7472 endclass
7473
7474 var Func: func(B): number
7475 Func = (o: B): number => 3
7476 assert_equal(3, Func(B.new()))
7477 END
7478 v9.CheckSourceSuccess(lines)
7479
7480 lines =<< trim END
7481 vim9script
7482
7483 class A
7484 endclass
7485 class B extends A
7486 endclass
7487 class C extends B
7488 endclass
7489
7490 var Func: func(B): number
7491 Func = (o: A): number => 3
7492 END
7493 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
7494
7495 lines =<< trim END
7496 vim9script
7497
7498 class A
7499 endclass
7500 class B extends A
7501 endclass
7502 class C extends B
7503 endclass
7504
7505 var Func: func(B): number
7506 Func = (o: C): number => 3
7507 END
7508 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
7509enddef
7510
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02007511" Test for using an operator (e.g. +) with an assignment
7512def Test_op_and_assignment()
7513 # Using += with a class variable
7514 var lines =<< trim END
7515 vim9script
7516 class A
7517 public static val: list<number> = []
7518 static def Foo(): list<number>
7519 val += [1]
7520 return val
7521 enddef
7522 endclass
7523 def Bar(): list<number>
7524 A.val += [2]
7525 return A.val
7526 enddef
7527 assert_equal([1], A.Foo())
7528 assert_equal([1, 2], Bar())
7529 A.val += [3]
7530 assert_equal([1, 2, 3], A.val)
7531 END
7532 v9.CheckSourceSuccess(lines)
7533
7534 # Using += with an object variable
7535 lines =<< trim END
7536 vim9script
7537 class A
7538 public this.val: list<number> = []
7539 def Foo(): list<number>
7540 this.val += [1]
7541 return this.val
7542 enddef
7543 endclass
7544 def Bar(bar_a: A): list<number>
7545 bar_a.val += [2]
7546 return bar_a.val
7547 enddef
7548 var a = A.new()
7549 assert_equal([1], a.Foo())
7550 assert_equal([1, 2], Bar(a))
7551 a.val += [3]
7552 assert_equal([1, 2, 3], a.val)
7553 END
7554 v9.CheckSourceSuccess(lines)
7555enddef
7556
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007557" Test for using an object method as a funcref
7558def Test_object_funcref()
7559 # Using object method funcref from a def function
7560 var lines =<< trim END
7561 vim9script
7562 class A
7563 def Foo(): list<number>
7564 return [3, 2, 1]
7565 enddef
7566 endclass
7567 def Bar()
7568 var a = A.new()
7569 var Fn = a.Foo
7570 assert_equal([3, 2, 1], Fn())
7571 enddef
7572 Bar()
7573 END
7574 v9.CheckSourceSuccess(lines)
7575
7576 # Using object method funcref at the script level
7577 lines =<< trim END
7578 vim9script
7579 class A
7580 def Foo(): dict<number>
7581 return {a: 1, b: 2}
7582 enddef
7583 endclass
7584 var a = A.new()
7585 var Fn = a.Foo
7586 assert_equal({a: 1, b: 2}, Fn())
7587 END
7588 v9.CheckSourceSuccess(lines)
7589
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007590 # Using object method funcref at the script level
7591 lines =<< trim END
7592 vim9script
7593 class A
7594 this.val: number
7595 def Foo(): number
7596 return this.val
7597 enddef
7598 endclass
7599 var a = A.new(345)
7600 var Fn = a.Foo
7601 assert_equal(345, Fn())
7602 END
7603 v9.CheckSourceSuccess(lines)
7604
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007605 # Using object method funcref from another object method
7606 lines =<< trim END
7607 vim9script
7608 class A
7609 def Foo(): list<number>
7610 return [3, 2, 1]
7611 enddef
7612 def Bar()
7613 var Fn = this.Foo
7614 assert_equal([3, 2, 1], Fn())
7615 enddef
7616 endclass
7617 var a = A.new()
7618 a.Bar()
7619 END
7620 v9.CheckSourceSuccess(lines)
7621
7622 # Using function() to get a object method funcref
7623 lines =<< trim END
7624 vim9script
7625 class A
7626 def Foo(l: list<any>): list<any>
7627 return l
7628 enddef
7629 endclass
7630 var a = A.new()
7631 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
7632 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
7633 END
7634 v9.CheckSourceSuccess(lines)
7635
7636 # Use an object method with a function returning a funcref and then call the
7637 # funcref.
7638 lines =<< trim END
7639 vim9script
7640
7641 def Map(F: func(number): number): func(number): number
7642 return (n: number) => F(n)
7643 enddef
7644
7645 class Math
7646 def Double(n: number): number
7647 return 2 * n
7648 enddef
7649 endclass
7650
7651 const math = Math.new()
7652 assert_equal(48, Map(math.Double)(24))
7653 END
7654 v9.CheckSourceSuccess(lines)
7655
Ernie Rael03042a22023-11-11 08:53:32 +01007656 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007657 lines =<< trim END
7658 vim9script
7659 class A
7660 def _Foo()
7661 enddef
7662 endclass
7663 def Bar()
7664 var a = A.new()
7665 var Fn = a._Foo
7666 enddef
7667 Bar()
7668 END
Ernie Rael03042a22023-11-11 08:53:32 +01007669 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007670
Ernie Rael03042a22023-11-11 08:53:32 +01007671 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007672 lines =<< trim END
7673 vim9script
7674 class A
7675 def _Foo()
7676 enddef
7677 endclass
7678 var a = A.new()
7679 var Fn = a._Foo
7680 END
Ernie Rael03042a22023-11-11 08:53:32 +01007681 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007682
Ernie Rael03042a22023-11-11 08:53:32 +01007683 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007684 lines =<< trim END
7685 vim9script
7686 class A
7687 def _Foo(): list<number>
7688 return [3, 2, 1]
7689 enddef
7690 def Bar()
7691 var Fn = this._Foo
7692 assert_equal([3, 2, 1], Fn())
7693 enddef
7694 endclass
7695 var a = A.new()
7696 a.Bar()
7697 END
7698 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007699
7700 # Using object method funcref using call()
7701 lines =<< trim END
7702 vim9script
7703 class A
7704 this.val: number
7705 def Foo(): number
7706 return this.val
7707 enddef
7708 endclass
7709
7710 def Bar(obj: A)
7711 assert_equal(123, call(obj.Foo, []))
7712 enddef
7713
7714 var a = A.new(123)
7715 Bar(a)
7716 assert_equal(123, call(a.Foo, []))
7717 END
7718 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007719enddef
7720
7721" Test for using a class method as a funcref
7722def Test_class_funcref()
7723 # Using class method funcref in a def function
7724 var lines =<< trim END
7725 vim9script
7726 class A
7727 static def Foo(): list<number>
7728 return [3, 2, 1]
7729 enddef
7730 endclass
7731 def Bar()
7732 var Fn = A.Foo
7733 assert_equal([3, 2, 1], Fn())
7734 enddef
7735 Bar()
7736 END
7737 v9.CheckSourceSuccess(lines)
7738
7739 # Using class method funcref at script level
7740 lines =<< trim END
7741 vim9script
7742 class A
7743 static def Foo(): dict<number>
7744 return {a: 1, b: 2}
7745 enddef
7746 endclass
7747 var Fn = A.Foo
7748 assert_equal({a: 1, b: 2}, Fn())
7749 END
7750 v9.CheckSourceSuccess(lines)
7751
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007752 # Using class method funcref at the script level
7753 lines =<< trim END
7754 vim9script
7755 class A
7756 public static val: number
7757 static def Foo(): number
7758 return val
7759 enddef
7760 endclass
7761 A.val = 567
7762 var Fn = A.Foo
7763 assert_equal(567, Fn())
7764 END
7765 v9.CheckSourceSuccess(lines)
7766
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007767 # Using function() to get a class method funcref
7768 lines =<< trim END
7769 vim9script
7770 class A
7771 static def Foo(l: list<any>): list<any>
7772 return l
7773 enddef
7774 endclass
7775 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
7776 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
7777 END
7778 v9.CheckSourceSuccess(lines)
7779
7780 # Using a class method funcref from another class method
7781 lines =<< trim END
7782 vim9script
7783 class A
7784 static def Foo(): list<number>
7785 return [3, 2, 1]
7786 enddef
7787 static def Bar()
7788 var Fn = Foo
7789 assert_equal([3, 2, 1], Fn())
7790 enddef
7791 endclass
7792 A.Bar()
7793 END
7794 v9.CheckSourceSuccess(lines)
7795
7796 # Use a class method with a function returning a funcref and then call the
7797 # funcref.
7798 lines =<< trim END
7799 vim9script
7800
7801 def Map(F: func(number): number): func(number): number
7802 return (n: number) => F(n)
7803 enddef
7804
7805 class Math
7806 static def StaticDouble(n: number): number
7807 return 2 * n
7808 enddef
7809 endclass
7810
7811 assert_equal(48, Map(Math.StaticDouble)(24))
7812 END
7813 v9.CheckSourceSuccess(lines)
7814
Ernie Rael03042a22023-11-11 08:53:32 +01007815 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007816 lines =<< trim END
7817 vim9script
7818 class A
7819 static def _Foo()
7820 enddef
7821 endclass
7822 def Bar()
7823 var Fn = A._Foo
7824 enddef
7825 Bar()
7826 END
Ernie Rael03042a22023-11-11 08:53:32 +01007827 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007828
Ernie Rael03042a22023-11-11 08:53:32 +01007829 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007830 lines =<< trim END
7831 vim9script
7832 class A
7833 static def _Foo()
7834 enddef
7835 endclass
7836 var Fn = A._Foo
7837 END
Ernie Rael03042a22023-11-11 08:53:32 +01007838 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007839
Ernie Rael03042a22023-11-11 08:53:32 +01007840 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007841 lines =<< trim END
7842 vim9script
7843 class A
7844 static def _Foo(): list<number>
7845 return [3, 2, 1]
7846 enddef
7847 static def Bar()
7848 var Fn = _Foo
7849 assert_equal([3, 2, 1], Fn())
7850 enddef
7851 endclass
7852 A.Bar()
7853 END
7854 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02007855
7856 # Using class method funcref using call()
7857 lines =<< trim END
7858 vim9script
7859 class A
7860 public static val: number
7861 static def Foo(): number
7862 return val
7863 enddef
7864 endclass
7865
7866 def Bar()
7867 A.val = 468
7868 assert_equal(468, call(A.Foo, []))
7869 enddef
7870 Bar()
7871 assert_equal(468, call(A.Foo, []))
7872 END
7873 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02007874enddef
7875
7876" Test for using an object member as a funcref
7877def Test_object_member_funcref()
7878 # Using a funcref object variable in an object method
7879 var lines =<< trim END
7880 vim9script
7881 def Foo(n: number): number
7882 return n * 10
7883 enddef
7884
7885 class A
7886 this.Cb: func(number): number = Foo
7887 def Bar()
7888 assert_equal(200, this.Cb(20))
7889 enddef
7890 endclass
7891
7892 var a = A.new()
7893 a.Bar()
7894 END
7895 v9.CheckSourceSuccess(lines)
7896
7897 # Using a funcref object variable in a def method
7898 lines =<< trim END
7899 vim9script
7900 def Foo(n: number): number
7901 return n * 10
7902 enddef
7903
7904 class A
7905 this.Cb: func(number): number = Foo
7906 endclass
7907
7908 def Bar()
7909 var a = A.new()
7910 assert_equal(200, a.Cb(20))
7911 enddef
7912 Bar()
7913 END
7914 v9.CheckSourceSuccess(lines)
7915
7916 # Using a funcref object variable at script level
7917 lines =<< trim END
7918 vim9script
7919 def Foo(n: number): number
7920 return n * 10
7921 enddef
7922
7923 class A
7924 this.Cb: func(number): number = Foo
7925 endclass
7926
7927 var a = A.new()
7928 assert_equal(200, a.Cb(20))
7929 END
7930 v9.CheckSourceSuccess(lines)
7931
7932 # Using a funcref object variable pointing to an object method in an object
7933 # method.
7934 lines =<< trim END
7935 vim9script
7936 class A
7937 this.Cb: func(number): number = this.Foo
7938 def Foo(n: number): number
7939 return n * 10
7940 enddef
7941 def Bar()
7942 assert_equal(200, this.Cb(20))
7943 enddef
7944 endclass
7945
7946 var a = A.new()
7947 a.Bar()
7948 END
7949 v9.CheckSourceSuccess(lines)
7950
7951 # Using a funcref object variable pointing to an object method in a def
7952 # method.
7953 lines =<< trim END
7954 vim9script
7955 class A
7956 this.Cb: func(number): number = this.Foo
7957 def Foo(n: number): number
7958 return n * 10
7959 enddef
7960 endclass
7961
7962 def Bar()
7963 var a = A.new()
7964 assert_equal(200, a.Cb(20))
7965 enddef
7966 Bar()
7967 END
7968 v9.CheckSourceSuccess(lines)
7969
7970 # Using a funcref object variable pointing to an object method at script
7971 # level.
7972 lines =<< trim END
7973 vim9script
7974 class A
7975 this.Cb = this.Foo
7976 def Foo(n: number): number
7977 return n * 10
7978 enddef
7979 endclass
7980
7981 var a = A.new()
7982 assert_equal(200, a.Cb(20))
7983 END
7984 v9.CheckSourceSuccess(lines)
7985enddef
7986
7987" Test for using a class member as a funcref
7988def Test_class_member_funcref()
7989 # Using a funcref class variable in a class method
7990 var lines =<< trim END
7991 vim9script
7992 def Foo(n: number): number
7993 return n * 10
7994 enddef
7995
7996 class A
7997 static Cb = Foo
7998 static def Bar()
7999 assert_equal(200, Cb(20))
8000 enddef
8001 endclass
8002
8003 A.Bar()
8004 END
8005 v9.CheckSourceSuccess(lines)
8006
8007 # Using a funcref class variable in a def method
8008 lines =<< trim END
8009 vim9script
8010 def Foo(n: number): number
8011 return n * 10
8012 enddef
8013
8014 class A
8015 public static Cb = Foo
8016 endclass
8017
8018 def Bar()
8019 assert_equal(200, A.Cb(20))
8020 enddef
8021 Bar()
8022 END
8023 v9.CheckSourceSuccess(lines)
8024
8025 # Using a funcref class variable at script level
8026 lines =<< trim END
8027 vim9script
8028 def Foo(n: number): number
8029 return n * 10
8030 enddef
8031
8032 class A
8033 public static Cb = Foo
8034 endclass
8035
8036 assert_equal(200, A.Cb(20))
8037 END
8038 v9.CheckSourceSuccess(lines)
8039
8040 # Using a funcref class variable pointing to a class method in a class
8041 # method.
8042 lines =<< trim END
8043 vim9script
8044 class A
8045 static Cb: func(number): number
8046 static def Foo(n: number): number
8047 return n * 10
8048 enddef
8049 static def Init()
8050 Cb = Foo
8051 enddef
8052 static def Bar()
8053 assert_equal(200, Cb(20))
8054 enddef
8055 endclass
8056
8057 A.Init()
8058 A.Bar()
8059 END
8060 v9.CheckSourceSuccess(lines)
8061
8062 # Using a funcref class variable pointing to a class method in a def method.
8063 lines =<< trim END
8064 vim9script
8065 class A
8066 static Cb: func(number): number
8067 static def Foo(n: number): number
8068 return n * 10
8069 enddef
8070 static def Init()
8071 Cb = Foo
8072 enddef
8073 endclass
8074
8075 def Bar()
8076 A.Init()
8077 assert_equal(200, A.Cb(20))
8078 enddef
8079 Bar()
8080 END
8081 v9.CheckSourceSuccess(lines)
8082
8083 # Using a funcref class variable pointing to a class method at script level.
8084 lines =<< trim END
8085 vim9script
8086 class A
8087 static Cb: func(number): number
8088 static def Foo(n: number): number
8089 return n * 10
8090 enddef
8091 static def Init()
8092 Cb = Foo
8093 enddef
8094 endclass
8095
8096 A.Init()
8097 assert_equal(200, A.Cb(20))
8098 END
8099 v9.CheckSourceSuccess(lines)
8100enddef
8101
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008102" Test for using object methods as popup callback functions
8103def Test_objmethod_popup_callback()
8104 # Use the popup from the script level
8105 var lines =<< trim END
8106 vim9script
8107
8108 class A
8109 this.selection: number = -1
8110 this.filterkeys: list<string> = []
8111
8112 def PopupFilter(id: number, key: string): bool
8113 add(this.filterkeys, key)
8114 return popup_filter_yesno(id, key)
8115 enddef
8116
8117 def PopupCb(id: number, result: number)
8118 this.selection = result ? 100 : 200
8119 enddef
8120 endclass
8121
8122 var a = A.new()
8123 feedkeys('', 'xt')
8124 var winid = popup_create('Y/N?',
8125 {filter: a.PopupFilter, callback: a.PopupCb})
8126 feedkeys('y', 'xt')
8127 popup_close(winid)
8128 assert_equal(100, a.selection)
8129 assert_equal(['y'], a.filterkeys)
8130 feedkeys('', 'xt')
8131 winid = popup_create('Y/N?',
8132 {filter: a.PopupFilter, callback: a.PopupCb})
8133 feedkeys('n', 'xt')
8134 popup_close(winid)
8135 assert_equal(200, a.selection)
8136 assert_equal(['y', 'n'], a.filterkeys)
8137 END
8138 v9.CheckSourceSuccess(lines)
8139
8140 # Use the popup from a def function
8141 lines =<< trim END
8142 vim9script
8143
8144 class A
8145 this.selection: number = -1
8146 this.filterkeys: list<string> = []
8147
8148 def PopupFilter(id: number, key: string): bool
8149 add(this.filterkeys, key)
8150 return popup_filter_yesno(id, key)
8151 enddef
8152
8153 def PopupCb(id: number, result: number)
8154 this.selection = result ? 100 : 200
8155 enddef
8156 endclass
8157
8158 def Foo()
8159 var a = A.new()
8160 feedkeys('', 'xt')
8161 var winid = popup_create('Y/N?',
8162 {filter: a.PopupFilter, callback: a.PopupCb})
8163 feedkeys('y', 'xt')
8164 popup_close(winid)
8165 assert_equal(100, a.selection)
8166 assert_equal(['y'], a.filterkeys)
8167 feedkeys('', 'xt')
8168 winid = popup_create('Y/N?',
8169 {filter: a.PopupFilter, callback: a.PopupCb})
8170 feedkeys('n', 'xt')
8171 popup_close(winid)
8172 assert_equal(200, a.selection)
8173 assert_equal(['y', 'n'], a.filterkeys)
8174 enddef
8175 Foo()
8176 END
8177 v9.CheckSourceSuccess(lines)
8178enddef
8179
8180" Test for using class methods as popup callback functions
8181def Test_classmethod_popup_callback()
8182 # Use the popup from the script level
8183 var lines =<< trim END
8184 vim9script
8185
8186 class A
8187 static selection: number = -1
8188 static filterkeys: list<string> = []
8189
8190 static def PopupFilter(id: number, key: string): bool
8191 add(filterkeys, key)
8192 return popup_filter_yesno(id, key)
8193 enddef
8194
8195 static def PopupCb(id: number, result: number)
8196 selection = result ? 100 : 200
8197 enddef
8198 endclass
8199
8200 feedkeys('', 'xt')
8201 var winid = popup_create('Y/N?',
8202 {filter: A.PopupFilter, callback: A.PopupCb})
8203 feedkeys('y', 'xt')
8204 popup_close(winid)
8205 assert_equal(100, A.selection)
8206 assert_equal(['y'], A.filterkeys)
8207 feedkeys('', 'xt')
8208 winid = popup_create('Y/N?',
8209 {filter: A.PopupFilter, callback: A.PopupCb})
8210 feedkeys('n', 'xt')
8211 popup_close(winid)
8212 assert_equal(200, A.selection)
8213 assert_equal(['y', 'n'], A.filterkeys)
8214 END
8215 v9.CheckSourceSuccess(lines)
8216
8217 # Use the popup from a def function
8218 lines =<< trim END
8219 vim9script
8220
8221 class A
8222 static selection: number = -1
8223 static filterkeys: list<string> = []
8224
8225 static def PopupFilter(id: number, key: string): bool
8226 add(filterkeys, key)
8227 return popup_filter_yesno(id, key)
8228 enddef
8229
8230 static def PopupCb(id: number, result: number)
8231 selection = result ? 100 : 200
8232 enddef
8233 endclass
8234
8235 def Foo()
8236 feedkeys('', 'xt')
8237 var winid = popup_create('Y/N?',
8238 {filter: A.PopupFilter, callback: A.PopupCb})
8239 feedkeys('y', 'xt')
8240 popup_close(winid)
8241 assert_equal(100, A.selection)
8242 assert_equal(['y'], A.filterkeys)
8243 feedkeys('', 'xt')
8244 winid = popup_create('Y/N?',
8245 {filter: A.PopupFilter, callback: A.PopupCb})
8246 feedkeys('n', 'xt')
8247 popup_close(winid)
8248 assert_equal(200, A.selection)
8249 assert_equal(['y', 'n'], A.filterkeys)
8250 enddef
8251 Foo()
8252 END
8253 v9.CheckSourceSuccess(lines)
8254enddef
8255
8256" Test for using an object method as a timer callback function
8257def Test_objmethod_timer_callback()
8258 # Use the timer callback from script level
8259 var lines =<< trim END
8260 vim9script
8261
8262 class A
8263 this.timerTick: number = -1
8264 def TimerCb(timerID: number)
8265 this.timerTick = 6
8266 enddef
8267 endclass
8268
8269 var a = A.new()
8270 timer_start(0, a.TimerCb)
8271 var maxWait = 5
8272 while maxWait > 0 && a.timerTick == -1
8273 :sleep 10m
8274 maxWait -= 1
8275 endwhile
8276 assert_equal(6, a.timerTick)
8277 END
8278 v9.CheckSourceSuccess(lines)
8279
8280 # Use the timer callback from a def function
8281 lines =<< trim END
8282 vim9script
8283
8284 class A
8285 this.timerTick: number = -1
8286 def TimerCb(timerID: number)
8287 this.timerTick = 6
8288 enddef
8289 endclass
8290
8291 def Foo()
8292 var a = A.new()
8293 timer_start(0, a.TimerCb)
8294 var maxWait = 5
8295 while maxWait > 0 && a.timerTick == -1
8296 :sleep 10m
8297 maxWait -= 1
8298 endwhile
8299 assert_equal(6, a.timerTick)
8300 enddef
8301 Foo()
8302 END
8303 v9.CheckSourceSuccess(lines)
8304enddef
8305
8306" Test for using a class method as a timer callback function
8307def Test_classmethod_timer_callback()
8308 # Use the timer callback from script level
8309 var lines =<< trim END
8310 vim9script
8311
8312 class A
8313 static timerTick: number = -1
8314 static def TimerCb(timerID: number)
8315 timerTick = 6
8316 enddef
8317 endclass
8318
8319 timer_start(0, A.TimerCb)
8320 var maxWait = 5
8321 while maxWait > 0 && A.timerTick == -1
8322 :sleep 10m
8323 maxWait -= 1
8324 endwhile
8325 assert_equal(6, A.timerTick)
8326 END
8327 v9.CheckSourceSuccess(lines)
8328
8329 # Use the timer callback from a def function
8330 lines =<< trim END
8331 vim9script
8332
8333 class A
8334 static timerTick: number = -1
8335 static def TimerCb(timerID: number)
8336 timerTick = 6
8337 enddef
8338 endclass
8339
8340 def Foo()
8341 timer_start(0, A.TimerCb)
8342 var maxWait = 5
8343 while maxWait > 0 && A.timerTick == -1
8344 :sleep 10m
8345 maxWait -= 1
8346 endwhile
8347 assert_equal(6, A.timerTick)
8348 enddef
8349 Foo()
8350 END
8351 v9.CheckSourceSuccess(lines)
8352enddef
8353
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008354" Test for using a class variable as the first and/or second operand of a binary
8355" operator.
8356def Test_class_variable_as_operands()
8357 var lines =<< trim END
8358 vim9script
8359 class Tests
8360 static truthy: bool = true
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008361 public static TruthyFn: func
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008362 static list: list<any> = []
8363 static four: number = 4
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008364 static str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008365
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008366 static def Str(): string
8367 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008368 enddef
8369
8370 static def Four(): number
8371 return four
8372 enddef
8373
8374 static def List(): list<any>
8375 return list
8376 enddef
8377
8378 static def Truthy(): bool
8379 return truthy
8380 enddef
8381
8382 def TestOps()
8383 assert_true(Tests.truthy == truthy)
8384 assert_true(truthy == Tests.truthy)
8385 assert_true(Tests.list isnot [])
8386 assert_true([] isnot Tests.list)
8387 assert_equal(2, Tests.four >> 1)
8388 assert_equal(16, 1 << Tests.four)
8389 assert_equal(8, Tests.four + four)
8390 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008391 assert_equal('hellohello', Tests.str .. str)
8392 assert_equal('hellohello', str .. Tests.str)
8393
8394 # Using class variable for list indexing
8395 var l = range(10)
8396 assert_equal(4, l[Tests.four])
8397 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
8398
8399 # Using class variable for Dict key
8400 var d = {hello: 'abc'}
8401 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008402 enddef
8403 endclass
8404
8405 def TestOps2()
8406 assert_true(Tests.truthy == Tests.Truthy())
8407 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008408 assert_true(Tests.truthy == Tests.TruthyFn())
8409 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008410 assert_true(Tests.list is Tests.List())
8411 assert_true(Tests.List() is Tests.list)
8412 assert_equal(2, Tests.four >> 1)
8413 assert_equal(16, 1 << Tests.four)
8414 assert_equal(8, Tests.four + Tests.Four())
8415 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008416 assert_equal('hellohello', Tests.str .. Tests.Str())
8417 assert_equal('hellohello', Tests.Str() .. Tests.str)
8418
8419 # Using class variable for list indexing
8420 var l = range(10)
8421 assert_equal(4, l[Tests.four])
8422 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
8423
8424 # Using class variable for Dict key
8425 var d = {hello: 'abc'}
8426 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008427 enddef
8428
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008429 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008430 var t = Tests.new()
8431 t.TestOps()
8432 TestOps2()
8433
8434 assert_true(Tests.truthy == Tests.Truthy())
8435 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02008436 assert_true(Tests.truthy == Tests.TruthyFn())
8437 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008438 assert_true(Tests.list is Tests.List())
8439 assert_true(Tests.List() is Tests.list)
8440 assert_equal(2, Tests.four >> 1)
8441 assert_equal(16, 1 << Tests.four)
8442 assert_equal(8, Tests.four + Tests.Four())
8443 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02008444 assert_equal('hellohello', Tests.str .. Tests.Str())
8445 assert_equal('hellohello', Tests.Str() .. Tests.str)
8446
8447 # Using class variable for list indexing
8448 var l = range(10)
8449 assert_equal(4, l[Tests.four])
8450 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
8451
8452 # Using class variable for Dict key
8453 var d = {hello: 'abc'}
8454 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02008455 END
8456 v9.CheckSourceSuccess(lines)
8457enddef
8458
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02008459" Test for checking the type of the key used to access an object dict member.
8460def Test_dict_member_key_type_check()
8461 var lines =<< trim END
8462 vim9script
8463
8464 abstract class State
8465 this.numbers: dict<string> = {0: 'nil', 1: 'unity'}
8466 endclass
8467
8468 class Test extends State
8469 def ObjMethodTests()
8470 var cursor: number = 0
8471 var z: number = 0
8472 [this.numbers[cursor]] = ['zero.1']
8473 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
8474 [this.numbers[string(cursor)], z] = ['zero.2', 1]
8475 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
8476 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
8477 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
8478 [this.numbers[cursor], z] = ['zero.4', 1]
8479 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
8480 [z, this.numbers[cursor]] = [1, 'zero.5']
8481 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
8482 enddef
8483
8484 static def ClassMethodTests(that: State)
8485 var cursor: number = 0
8486 var z: number = 0
8487 [that.numbers[cursor]] = ['zero.1']
8488 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
8489 [that.numbers[string(cursor)], z] = ['zero.2', 1]
8490 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
8491 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
8492 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
8493 [that.numbers[cursor], z] = ['zero.4', 1]
8494 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
8495 [z, that.numbers[cursor]] = [1, 'zero.5']
8496 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
8497 enddef
8498
8499 def new()
8500 enddef
8501
8502 def newMethodTests()
8503 var cursor: number = 0
8504 var z: number
8505 [this.numbers[cursor]] = ['zero.1']
8506 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
8507 [this.numbers[string(cursor)], z] = ['zero.2', 1]
8508 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
8509 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
8510 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
8511 [this.numbers[cursor], z] = ['zero.4', 1]
8512 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
8513 [z, this.numbers[cursor]] = [1, 'zero.5']
8514 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
8515 enddef
8516 endclass
8517
8518 def DefFuncTests(that: Test)
8519 var cursor: number = 0
8520 var z: number
8521 [that.numbers[cursor]] = ['zero.1']
8522 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
8523 [that.numbers[string(cursor)], z] = ['zero.2', 1]
8524 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
8525 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
8526 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
8527 [that.numbers[cursor], z] = ['zero.4', 1]
8528 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
8529 [z, that.numbers[cursor]] = [1, 'zero.5']
8530 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
8531 enddef
8532
8533 Test.newMethodTests()
8534 Test.new().ObjMethodTests()
8535 Test.ClassMethodTests(Test.new())
8536 DefFuncTests(Test.new())
8537
8538 const test: Test = Test.new()
8539 var cursor: number = 0
8540 [test.numbers[cursor], cursor] = ['zero', 1]
8541 [cursor, test.numbers[cursor]] = [1, 'one']
8542 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
8543 END
8544 v9.CheckSourceSuccess(lines)
8545
8546 lines =<< trim END
8547 vim9script
8548
8549 class A
8550 this.numbers: dict<string> = {a: '1', b: '2'}
8551
8552 def new()
8553 enddef
8554
8555 def Foo()
8556 var z: number
8557 [this.numbers.a, z] = [{}, 10]
8558 enddef
8559 endclass
8560
8561 var a = A.new()
8562 a.Foo()
8563 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01008564 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02008565
8566 lines =<< trim END
8567 vim9script
8568
8569 class A
8570 this.numbers: dict<number> = {a: 1, b: 2}
8571
8572 def new()
8573 enddef
8574
8575 def Foo()
8576 var x: string = 'a'
8577 var y: number
8578 [this.numbers[x], y] = [{}, 10]
8579 enddef
8580 endclass
8581
8582 var a = A.new()
8583 a.Foo()
8584 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01008585 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02008586enddef
8587
mityua5550692023-11-25 15:41:20 +01008588def Test_compile_many_def_functions_in_funcref_instr()
8589 # This used to crash Vim. This is reproducible only when run on new instance
8590 # of Vim.
8591 var lines =<< trim END
8592 vim9script
8593
8594 class A
8595 def new()
8596 this.TakeFunc(this.F00)
8597 enddef
8598
8599 def TakeFunc(F: func)
8600 enddef
8601
8602 def F00()
8603 this.F01()
8604 this.F02()
8605 this.F03()
8606 this.F04()
8607 this.F05()
8608 this.F06()
8609 this.F07()
8610 this.F08()
8611 this.F09()
8612 this.F10()
8613 this.F11()
8614 this.F12()
8615 this.F13()
8616 this.F14()
8617 this.F15()
8618 this.F16()
8619 this.F17()
8620 this.F18()
8621 this.F19()
8622 this.F20()
8623 this.F21()
8624 this.F22()
8625 this.F23()
8626 this.F24()
8627 this.F25()
8628 this.F26()
8629 this.F27()
8630 this.F28()
8631 this.F29()
8632 this.F30()
8633 this.F31()
8634 this.F32()
8635 this.F33()
8636 this.F34()
8637 this.F35()
8638 this.F36()
8639 this.F37()
8640 this.F38()
8641 this.F39()
8642 this.F40()
8643 this.F41()
8644 this.F42()
8645 this.F43()
8646 this.F44()
8647 this.F45()
8648 this.F46()
8649 this.F47()
8650 enddef
8651
8652 def F01()
8653 enddef
8654 def F02()
8655 enddef
8656 def F03()
8657 enddef
8658 def F04()
8659 enddef
8660 def F05()
8661 enddef
8662 def F06()
8663 enddef
8664 def F07()
8665 enddef
8666 def F08()
8667 enddef
8668 def F09()
8669 enddef
8670 def F10()
8671 enddef
8672 def F11()
8673 enddef
8674 def F12()
8675 enddef
8676 def F13()
8677 enddef
8678 def F14()
8679 enddef
8680 def F15()
8681 enddef
8682 def F16()
8683 enddef
8684 def F17()
8685 enddef
8686 def F18()
8687 enddef
8688 def F19()
8689 enddef
8690 def F20()
8691 enddef
8692 def F21()
8693 enddef
8694 def F22()
8695 enddef
8696 def F23()
8697 enddef
8698 def F24()
8699 enddef
8700 def F25()
8701 enddef
8702 def F26()
8703 enddef
8704 def F27()
8705 enddef
8706 def F28()
8707 enddef
8708 def F29()
8709 enddef
8710 def F30()
8711 enddef
8712 def F31()
8713 enddef
8714 def F32()
8715 enddef
8716 def F33()
8717 enddef
8718 def F34()
8719 enddef
8720 def F35()
8721 enddef
8722 def F36()
8723 enddef
8724 def F37()
8725 enddef
8726 def F38()
8727 enddef
8728 def F39()
8729 enddef
8730 def F40()
8731 enddef
8732 def F41()
8733 enddef
8734 def F42()
8735 enddef
8736 def F43()
8737 enddef
8738 def F44()
8739 enddef
8740 def F45()
8741 enddef
8742 def F46()
8743 enddef
8744 def F47()
8745 enddef
8746 endclass
8747
8748 A.new()
8749 END
8750 writefile(lines, 'Xscript', 'D')
8751 g:RunVim([], [], '-u NONE -S Xscript -c qa')
8752 assert_equal(0, v:shell_error)
8753enddef
8754
Bram Moolenaar00b28d62022-12-08 15:32:33 +00008755" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker