blob: ce7d5f7faaf1a9305f46ab264c662f51b911bfcc [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 Lakshmanan00cd1822023-09-18 19:56:49 +020038 # Only the completed word "class" should be recognized
Bram Moolenaar00b28d62022-12-08 15:32:33 +000039 lines =<< trim END
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200135 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "Something": state', 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 Lakshmananb90e3bc2023-09-28 23:06:48 +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 Lakshmananb90e3bc2023-09-28 23:06:48 +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 Lakshmananb90e3bc2023-09-28 23:06:48 +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 Lakshmananb90e3bc2023-09-28 23:06:48 +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 Lakshmananb90e3bc2023-09-28 23:06:48 +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 Lakshmananb90e3bc2023-09-28 23:06:48 +0200222 v9.CheckSourceFailure(lines, 'E1324: Using an object as a String', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200223
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200224 # Test creating a class with member variables and methods, calling a object
225 # method. Check for using type() and typename() with a class and an object.
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000226 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200227 vim9script
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000228
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200229 class TextPosition
230 this.lnum: number
231 this.col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000232
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200233 # make a nicely formatted string
234 def ToString(): string
235 return $'({this.lnum}, {this.col})'
236 enddef
237 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000238
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200239 # use the automatically generated new() method
240 var pos = TextPosition.new(2, 12)
241 assert_equal(2, pos.lnum)
242 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000243
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200244 # call an object method
245 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000246
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200247 assert_equal(v:t_class, type(TextPosition))
248 assert_equal(v:t_object, type(pos))
249 assert_equal('class<TextPosition>', typename(TextPosition))
250 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000251 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200252 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200253
254 # When referencing object methods, space cannot be used after a "."
255 lines =<< trim END
256 vim9script
257 class A
258 def Foo(): number
259 return 10
260 enddef
261 endclass
262 var a = A.new()
263 var v = a. Foo()
264 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200265 v9.CheckSourceFailure(lines, "E1202: No white space allowed after '.'", 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200266
267 # Using an object without specifying a method or a member variable
268 lines =<< trim END
269 vim9script
270 class A
271 def Foo(): number
272 return 10
273 enddef
274 endclass
275 var a = A.new()
276 var v = a.
277 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200278 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a."', 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200279
280 # Error when parsing the arguments of an object method.
281 lines =<< trim END
282 vim9script
283 class A
284 def Foo()
285 enddef
286 endclass
287 var a = A.new()
288 var v = a.Foo(,)
289 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200290 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a.Foo(,)"', 7)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200291
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200292 # Use a multi-line initialization for a member variable
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200293 lines =<< trim END
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200294 vim9script
295 class A
296 this.y = {
297 X: 1
298 }
299 endclass
300 var a = A.new()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200301 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200302 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000303enddef
304
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200305" Tests for object/class methods in a class
306def Test_class_def_method()
307 # Using the "public" keyword when defining an object method
308 var lines =<< trim END
309 vim9script
310 class A
311 public def Foo()
312 enddef
313 endclass
314 END
315 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"', 3)
316
317 # Using the "public" keyword when defining a class method
318 lines =<< trim END
319 vim9script
320 class A
321 public static def Foo()
322 enddef
323 endclass
324 END
325 v9.CheckSourceFailure(lines, 'E1388: Public keyword not supported for a method', 3)
326
327 # Using the "public" keyword when defining an object private method
328 lines =<< trim END
329 vim9script
330 class A
331 public def _Foo()
332 enddef
333 endclass
334 END
335 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"', 3)
336
337 # Using the "public" keyword when defining a class private method
338 lines =<< trim END
339 vim9script
340 class A
341 public static def _Foo()
342 enddef
343 endclass
344 END
345 v9.CheckSourceFailure(lines, 'E1388: Public keyword not supported for a method', 3)
346
347 # Using a "def" keyword without an object method name
348 lines =<< trim END
349 vim9script
350 class A
351 def
352 enddef
353 endclass
354 END
355 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: def', 3)
356
357 # Using a "def" keyword without a class method name
358 lines =<< trim END
359 vim9script
360 class A
361 static def
362 enddef
363 endclass
364 END
365 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: static def', 3)
366enddef
367
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000368def Test_class_defined_twice()
369 # class defined twice should fail
370 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200371 vim9script
372 class There
373 endclass
374 class There
375 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000376 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200377 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"', 4)
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000378
379 # one class, reload same script twice is OK
380 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200381 vim9script
382 class There
383 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000384 END
385 writefile(lines, 'XclassTwice.vim', 'D')
386 source XclassTwice.vim
387 source XclassTwice.vim
388enddef
389
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000390def Test_returning_null_object()
391 # this was causing an internal error
392 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200393 vim9script
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000394
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200395 class BufferList
396 def Current(): any
397 return null_object
398 enddef
399 endclass
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000400
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200401 var buffers = BufferList.new()
402 echo buffers.Current()
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000403 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200404 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000405enddef
406
Bram Moolenaard13dd302023-03-11 20:56:35 +0000407def Test_using_null_class()
408 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200409 @_ = null_class.member
Bram Moolenaard13dd302023-03-11 20:56:35 +0000410 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200411 v9.CheckDefExecAndScriptFailure(lines, ['E715: Dictionary required', 'E1363: Incomplete type'])
Bram Moolenaard13dd302023-03-11 20:56:35 +0000412enddef
413
Bram Moolenaar657aea72023-01-27 13:16:19 +0000414def Test_class_interface_wrong_end()
415 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200416 vim9script
417 abstract class SomeName
418 this.member = 'text'
419 endinterface
Bram Moolenaar657aea72023-01-27 13:16:19 +0000420 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200421 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass', 4)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000422
423 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200424 vim9script
425 export interface AnotherName
426 this.member: string
427 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +0000428 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200429 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface', 4)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000430enddef
431
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000432def Test_object_not_set()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200433 # Use an uninitialized object in script context
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000434 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200435 vim9script
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000436
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200437 class State
438 this.value = 'xyz'
439 endclass
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000440
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200441 var state: State
442 var db = {'xyz': 789}
443 echo db[state.value]
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000444 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200445 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 9)
Bram Moolenaar0917e862023-02-18 14:42:44 +0000446
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200447 # Use an uninitialized object from a def function
Bram Moolenaar0917e862023-02-18 14:42:44 +0000448 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200449 vim9script
Bram Moolenaar0917e862023-02-18 14:42:44 +0000450
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200451 class Class
452 this.id: string
453 def Method1()
454 echo 'Method1' .. this.id
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000455 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200456 endclass
457
458 var obj: Class
459 def Func()
460 obj.Method1()
461 enddef
462 Func()
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000463 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200464 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000465
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200466 # Pass an uninitialized object variable to a "new" function and try to call an
467 # object method.
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000468 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200469 vim9script
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000470
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200471 class Background
472 this.background = 'dark'
473 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000474
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200475 class Colorscheme
476 this._bg: Background
Bram Moolenaar0917e862023-02-18 14:42:44 +0000477
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200478 def GetBackground(): string
479 return this._bg.background
480 enddef
481 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000482
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200483 var bg: Background # UNINITIALIZED
484 echo Colorscheme.new(bg).GetBackground()
Bram Moolenaar0917e862023-02-18 14:42:44 +0000485 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200486 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
Ernie Raelf77a7f72023-03-03 15:05:30 +0000487
488 # TODO: this should not give an error but be handled at runtime
489 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200490 vim9script
Ernie Raelf77a7f72023-03-03 15:05:30 +0000491
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200492 class Class
493 this.id: string
494 def Method1()
495 echo 'Method1' .. this.id
Ernie Raelf77a7f72023-03-03 15:05:30 +0000496 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200497 endclass
498
499 var obj = null_object
500 def Func()
501 obj.Method1()
502 enddef
503 Func()
Ernie Raelf77a7f72023-03-03 15:05:30 +0000504 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200505 v9.CheckSourceFailure(lines, 'E1363: Incomplete type', 1)
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000506enddef
507
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200508" Null object assignment and comparison
Ernie Rael5c018be2023-08-27 18:40:26 +0200509def Test_null_object_assign_compare()
510 var lines =<< trim END
511 vim9script
512
513 var nullo = null_object
514 def F(): any
515 return nullo
516 enddef
517 assert_equal('object<Unknown>', typename(F()))
518
519 var o0 = F()
520 assert_true(o0 == null_object)
521 assert_true(o0 == null)
522
523 var o1: any = nullo
524 assert_true(o1 == null_object)
525 assert_true(o1 == null)
526
527 def G()
528 var x = null_object
529 enddef
530
531 class C
532 endclass
533 var o2: C
534 assert_true(o2 == null_object)
535 assert_true(o2 == null)
536
537 o2 = null_object
538 assert_true(o2 == null)
539
540 o2 = C.new()
541 assert_true(o2 != null)
542
543 o2 = null_object
544 assert_true(o2 == null)
545 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200546 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200547enddef
548
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200549" Test for object member initialization and disassembly
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000550def Test_class_member_initializer()
551 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200552 vim9script
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000553
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200554 class TextPosition
555 this.lnum: number = 1
556 this.col: number = 1
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000557
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200558 # constructor with only the line number
559 def new(lnum: number)
560 this.lnum = lnum
561 enddef
562 endclass
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000563
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200564 var pos = TextPosition.new(3)
565 assert_equal(3, pos.lnum)
566 assert_equal(1, pos.col)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000567
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200568 var instr = execute('disassemble TextPosition.new')
569 assert_match('new\_s*' ..
570 '0 NEW TextPosition size \d\+\_s*' ..
571 '\d PUSHNR 1\_s*' ..
572 '\d STORE_THIS 0\_s*' ..
573 '\d PUSHNR 1\_s*' ..
574 '\d STORE_THIS 1\_s*' ..
575 'this.lnum = lnum\_s*' ..
576 '\d LOAD arg\[-1]\_s*' ..
577 '\d PUSHNR 0\_s*' ..
578 '\d LOAD $0\_s*' ..
579 '\d\+ STOREINDEX object\_s*' ..
580 '\d\+ RETURN object.*',
581 instr)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000582 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200583 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000584enddef
585
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000586def Test_member_any_used_as_object()
587 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200588 vim9script
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000589
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200590 class Inner
591 this.value: number = 0
592 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000593
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200594 class Outer
595 this.inner: any
596 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000597
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200598 def F(outer: Outer)
599 outer.inner.value = 1
600 enddef
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000601
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200602 var inner_obj = Inner.new(0)
603 var outer_obj = Outer.new(inner_obj)
604 F(outer_obj)
605 assert_equal(1, inner_obj.value)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000606 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200607 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000608
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200609 # Try modifying a private variable using an "any" object
610 lines =<< trim END
611 vim9script
612
613 class Inner
614 this._value: string = ''
615 endclass
616
617 class Outer
618 this.inner: any
619 endclass
620
621 def F(outer: Outer)
622 outer.inner._value = 'b'
623 enddef
624
625 var inner_obj = Inner.new('a')
626 var outer_obj = Outer.new(inner_obj)
627 F(outer_obj)
628 END
Ernie Rael64885642023-10-04 20:16:22 +0200629 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_value" in class "Inner"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200630
631 # Try modifying a non-existing variable using an "any" object
632 lines =<< trim END
633 vim9script
634
635 class Inner
636 this.value: string = ''
637 endclass
638
639 class Outer
640 this.inner: any
641 endclass
642
643 def F(outer: Outer)
644 outer.inner.someval = 'b'
645 enddef
646
647 var inner_obj = Inner.new('a')
648 var outer_obj = Outer.new(inner_obj)
649 F(outer_obj)
650 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200651 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "Inner": someval', 1)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000652enddef
653
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200654" Nested assignment to a object variable which is of another class type
655def Test_assignment_nested_type()
656 var lines =<< trim END
657 vim9script
658
659 class Inner
660 public this.value: number = 0
661 endclass
662
663 class Outer
664 this.inner: Inner
665 endclass
666
667 def F(outer: Outer)
668 outer.inner.value = 1
669 enddef
670
671 def Test_assign_to_nested_typed_member()
672 var inner = Inner.new(0)
673 var outer = Outer.new(inner)
674 F(outer)
675 assert_equal(1, inner.value)
676 enddef
677
678 Test_assign_to_nested_typed_member()
Ernie Rael98e68c02023-09-20 20:13:06 +0200679
680 var script_inner = Inner.new(0)
681 var script_outer = Outer.new(script_inner)
682 script_outer.inner.value = 1
683 assert_equal(1, script_inner.value)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200684 END
685 v9.CheckSourceSuccess(lines)
Ernie Rael98e68c02023-09-20 20:13:06 +0200686
687 # Assignment where target item is read only in :def
688 lines =<< trim END
689 vim9script
690
691 class Inner
692 this.value: number = 0
693 endclass
694
695 class Outer
696 this.inner: Inner
697 endclass
698
699 def F(outer: Outer)
700 outer.inner.value = 1
701 enddef
702
703 def Test_assign_to_nested_typed_member()
704 var inner = Inner.new(0)
705 var outer = Outer.new(inner)
706 F(outer)
707 assert_equal(1, inner.value)
708 enddef
709
710 Test_assign_to_nested_typed_member()
711 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200712 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 1)
Ernie Rael98e68c02023-09-20 20:13:06 +0200713
714 # Assignment where target item is read only script level
715 lines =<< trim END
716 vim9script
717
718 class Inner
719 this.value: number = 0
720 endclass
721
722 class Outer
723 this.inner: Inner
724 endclass
725
726 def F(outer: Outer)
727 outer.inner.value = 1
728 enddef
729
730 var script_inner = Inner.new(0)
731 var script_outer = Outer.new(script_inner)
732 script_outer.inner.value = 1
733 assert_equal(1, script_inner.value)
734 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200735 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 17)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200736enddef
737
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000738def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200739 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000740 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200741 vim9script
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000742
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200743 class Foo
744 public this.x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000745
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200746 def Add(n: number)
747 this.x += n
Bram Moolenaar22363c62023-04-24 17:15:25 +0100748 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200749 endclass
Bram Moolenaar22363c62023-04-24 17:15:25 +0100750
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200751 var f = Foo.new(3)
752 f.Add(17)
753 assert_equal(20, f.x)
754
755 def AddToFoo(obj: Foo)
756 obj.x += 3
757 enddef
758
759 AddToFoo(f)
760 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000761 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200762 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000763enddef
764
Bram Moolenaarf4508042023-01-15 16:54:57 +0000765def Test_list_of_objects()
766 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200767 vim9script
Bram Moolenaarf4508042023-01-15 16:54:57 +0000768
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200769 class Foo
770 def Add()
Bram Moolenaarf4508042023-01-15 16:54:57 +0000771 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200772 endclass
Bram Moolenaarf4508042023-01-15 16:54:57 +0000773
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200774 def ProcessList(fooList: list<Foo>)
775 for foo in fooList
776 foo.Add()
777 endfor
778 enddef
779
780 var l: list<Foo> = [Foo.new()]
781 ProcessList(l)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000782 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200783 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000784enddef
785
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000786def Test_expr_after_using_object()
787 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200788 vim9script
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000789
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200790 class Something
791 this.label: string = ''
792 endclass
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000793
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200794 def Foo(): Something
795 var v = Something.new()
796 echo 'in Foo(): ' .. typename(v)
797 return v
798 enddef
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000799
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200800 Foo()
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000801 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200802 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000803enddef
804
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000805def Test_class_default_new()
806 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200807 vim9script
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000808
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200809 class TextPosition
810 this.lnum: number = 1
811 this.col: number = 1
812 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000813
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200814 var pos = TextPosition.new()
815 assert_equal(1, pos.lnum)
816 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000817
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200818 pos = TextPosition.new(v:none, v:none)
819 assert_equal(1, pos.lnum)
820 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000821
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200822 pos = TextPosition.new(3, 22)
823 assert_equal(3, pos.lnum)
824 assert_equal(22, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000825
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200826 pos = TextPosition.new(v:none, 33)
827 assert_equal(1, pos.lnum)
828 assert_equal(33, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000829 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200830 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000831
832 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200833 vim9script
834 class Person
835 this.name: string
836 this.age: number = 42
837 this.education: string = "unknown"
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000838
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200839 def new(this.name, this.age = v:none, this.education = v:none)
840 enddef
841 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000842
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200843 var piet = Person.new("Piet")
844 assert_equal("Piet", piet.name)
845 assert_equal(42, piet.age)
846 assert_equal("unknown", piet.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000847
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200848 var chris = Person.new("Chris", 4, "none")
849 assert_equal("Chris", chris.name)
850 assert_equal(4, chris.age)
851 assert_equal("none", chris.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000852 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200853 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +0000854
855 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200856 vim9script
857 class Person
858 this.name: string
859 this.age: number = 42
860 this.education: string = "unknown"
Bram Moolenaar74e12742022-12-13 21:14:28 +0000861
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200862 def new(this.name, this.age = v:none, this.education = v:none)
863 enddef
864 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +0000865
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200866 var missing = Person.new()
Bram Moolenaar74e12742022-12-13 21:14:28 +0000867 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200868 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200869
870 # Using a specific value to initialize an instance variable in the new()
871 # method.
872 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200873 vim9script
874 class A
875 this.val: string
876 def new(this.val = 'a')
877 enddef
878 endclass
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200879 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200880 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'", 4)
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000881enddef
882
h-east2261c892023-08-16 21:49:54 +0900883def Test_class_new_with_object_member()
884 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200885 vim9script
h-east2261c892023-08-16 21:49:54 +0900886
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200887 class C
888 this.str: string
889 this.num: number
890 def new(this.str, this.num)
h-east2261c892023-08-16 21:49:54 +0900891 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200892 def newVals(this.str, this.num)
893 enddef
894 endclass
h-east2261c892023-08-16 21:49:54 +0900895
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200896 def Check()
897 try
898 var c = C.new('cats', 2)
899 assert_equal('cats', c.str)
900 assert_equal(2, c.num)
901
902 c = C.newVals('dogs', 4)
903 assert_equal('dogs', c.str)
904 assert_equal(4, c.num)
905 catch
906 assert_report($'Unexpected exception was caught: {v:exception}')
907 endtry
908 enddef
909
910 Check()
h-east2261c892023-08-16 21:49:54 +0900911 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200912 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +0900913
914 lines =<< trim END
h-eastdb385522023-09-28 22:18:19 +0200915 vim9script
916
917 class C
918 this.str: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200919 this.num: number
920 def new(this.str, this.num)
h-eastdb385522023-09-28 22:18:19 +0200921 enddef
922 endclass
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200923
924 def Check()
925 try
926 var c = C.new(1, 2)
927 catch
928 assert_report($'Unexpected exception was caught: {v:exception}')
929 endtry
930 enddef
931
932 Check()
h-eastdb385522023-09-28 22:18:19 +0200933 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200934 v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 2)
h-eastdb385522023-09-28 22:18:19 +0200935
936 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200937 vim9script
h-eastb895b0f2023-09-24 15:46:31 +0200938
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200939 class C
940 this.str: string
941 this.num: number
942 def newVals(this.str, this.num)
h-eastb895b0f2023-09-24 15:46:31 +0200943 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200944 endclass
h-eastb895b0f2023-09-24 15:46:31 +0200945
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200946 def Check()
947 try
948 var c = C.newVals('dogs', 'apes')
949 catch
950 assert_report($'Unexpected exception was caught: {v:exception}')
951 endtry
952 enddef
953
954 Check()
955 END
956 v9.CheckSourceFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string', 2)
957
958 lines =<< trim END
959 vim9script
960
961 class C
962 this.str: string
963 def new(str: any)
964 enddef
965 endclass
966
967 def Check()
968 try
969 var c = C.new(1)
970 catch
971 assert_report($'Unexpected exception was caught: {v:exception}')
972 endtry
973 enddef
974
975 Check()
h-eastb895b0f2023-09-24 15:46:31 +0200976 END
977 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +0200978
979 # Try using "this." argument in a class method
980 lines =<< trim END
981 vim9script
982 class A
983 this.val = 10
984 static def Foo(this.val: number)
985 enddef
986 endclass
987 END
988 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
989
990 # Try using "this." argument in an object method
991 lines =<< trim END
992 vim9script
993 class A
994 this.val = 10
995 def Foo(this.val: number)
996 enddef
997 endclass
998 END
999 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
h-east2261c892023-08-16 21:49:54 +09001000enddef
1001
Bram Moolenaar74e12742022-12-13 21:14:28 +00001002def Test_class_object_member_inits()
1003 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001004 vim9script
1005 class TextPosition
1006 this.lnum: number
1007 this.col = 1
1008 this.addcol: number = 2
1009 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001010
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001011 var pos = TextPosition.new()
1012 assert_equal(0, pos.lnum)
1013 assert_equal(1, pos.col)
1014 assert_equal(2, pos.addcol)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001015 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001016 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001017
1018 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001019 vim9script
1020 class TextPosition
1021 this.lnum
1022 this.col = 1
1023 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001024 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001025 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001026
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001027 # If the type is not specified for a member, then it should be set during
1028 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +00001029 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001030 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001031
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001032 var init_count = 0
1033 def Init(): string
1034 init_count += 1
1035 return 'foo'
1036 enddef
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001037
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001038 class A
1039 this.str1 = Init()
1040 this.str2: string = Init()
1041 this.col = 1
1042 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001043
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001044 assert_equal(init_count, 0)
1045 var a = A.new()
1046 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001047 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001048 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001049
1050 # Test for initializing an object member with an unknown variable/type
1051 lines =<< trim END
1052 vim9script
1053 class A
1054 this.value = init_val
1055 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001056 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001057 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001058 v9.CheckSourceFailure(lines, 'E1001: Variable not found: init_val', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001059
1060 # Test for initializing an object member with an special type
1061 lines =<< trim END
1062 vim9script
1063 class A
1064 this.value: void
1065 endclass
1066 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001067 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001068enddef
1069
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001070" Test for instance variable access
1071def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001072 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001073 vim9script
1074 class Triple
1075 this._one = 1
1076 this.two = 2
1077 public this.three = 3
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001078
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001079 def GetOne(): number
1080 return this._one
1081 enddef
1082 endclass
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001083
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001084 var trip = Triple.new()
1085 assert_equal(1, trip.GetOne())
1086 assert_equal(2, trip.two)
1087 assert_equal(3, trip.three)
Ernie Rael64885642023-10-04 20:16:22 +02001088 assert_fails('echo trip._one', 'E1333: Cannot access private variable "_one" in class "Triple"')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001089
Ernie Rael64885642023-10-04 20:16:22 +02001090 assert_fails('trip._one = 11', 'E1333: Cannot access private variable "_one" in class "Triple"')
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001091 assert_fails('trip.two = 22', 'E1335: Variable "two" in class "Triple" is not writable')
1092 trip.three = 33
1093 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001094
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001095 assert_fails('trip.four = 4', 'E1326: Variable not found on object "Triple": four')
Bram Moolenaard505d172022-12-18 21:42:55 +00001096 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001097 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001098
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001099 # Test for a public member variable name beginning with an underscore
1100 lines =<< trim END
1101 vim9script
1102 class A
1103 public this._val = 10
1104 endclass
1105 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001106 v9.CheckSourceFailure(lines, 'E1332: Public variable name cannot start with underscore: public this._val = 10', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001107
Bram Moolenaar590162c2022-12-24 21:24:06 +00001108 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001109 vim9script
Bram Moolenaar590162c2022-12-24 21:24:06 +00001110
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001111 class MyCar
1112 this.make: string
1113 this.age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001114
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001115 def new(make_arg: string)
1116 this.make = make_arg
Bram Moolenaar574950d2023-01-03 19:08:50 +00001117 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001118
1119 def GetMake(): string
1120 return $"make = {this.make}"
1121 enddef
1122 def GetAge(): number
1123 return this.age
1124 enddef
1125 endclass
1126
1127 var c = MyCar.new("abc")
1128 assert_equal('make = abc', c.GetMake())
1129
1130 c = MyCar.new("def")
1131 assert_equal('make = def', c.GetMake())
1132
1133 var c2 = MyCar.new("123")
1134 assert_equal('make = 123', c2.GetMake())
1135
1136 def CheckCar()
1137 assert_equal("make = def", c.GetMake())
1138 assert_equal(5, c.GetAge())
1139 enddef
1140 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001141 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001142 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001143
1144 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001145 vim9script
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001146
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001147 class MyCar
1148 this.make: string
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001149
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001150 def new(make_arg: string)
1151 this.make = make_arg
1152 enddef
1153 endclass
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001154
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001155 var c = MyCar.new("abc")
1156 var c = MyCar.new("def")
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001157 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001158 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "c"', 12)
Bram Moolenaarb149d222023-01-24 13:03:37 +00001159
1160 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001161 vim9script
Bram Moolenaarb149d222023-01-24 13:03:37 +00001162
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001163 class Foo
1164 this.x: list<number> = []
Bram Moolenaarb149d222023-01-24 13:03:37 +00001165
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001166 def Add(n: number): any
1167 this.x->add(n)
1168 return this
1169 enddef
1170 endclass
Bram Moolenaarb149d222023-01-24 13:03:37 +00001171
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001172 echo Foo.new().Add(1).Add(2).x
1173 echo Foo.new().Add(1).Add(2)
1174 .x
1175 echo Foo.new().Add(1)
1176 .Add(2).x
1177 echo Foo.new()
1178 .Add(1).Add(2).x
1179 echo Foo.new()
1180 .Add(1)
1181 .Add(2)
1182 .x
Bram Moolenaarb149d222023-01-24 13:03:37 +00001183 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001184 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001185
1186 # Test for "public" cannot be abbreviated
1187 lines =<< trim END
1188 vim9script
1189 class Something
1190 pub this.val = 1
1191 endclass
1192 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001193 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: pub this.val = 1', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001194
1195 # Test for "public" keyword must be followed by "this" or "static".
1196 lines =<< trim END
1197 vim9script
1198 class Something
1199 public val = 1
1200 endclass
1201 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001202 v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001203
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001204 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001205 lines =<< trim END
1206 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001207 class A
1208 public this.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001209 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001210 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001211 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001212 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001213
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001214 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001215 lines =<< trim END
1216 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001217 class A
1218 public this.val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001219 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001220 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001221 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001222 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001223
1224 # Modify a instance variable using the class name in a def function
1225 lines =<< trim END
1226 vim9script
1227 class A
1228 public this.val = 1
1229 endclass
1230 def T()
1231 A.val = 1
1232 enddef
1233 T()
1234 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001235 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001236
1237 # Read a instance variable using the class name in a def function
1238 lines =<< trim END
1239 vim9script
1240 class A
1241 public this.val = 1
1242 endclass
1243 def T()
1244 var i = A.val
1245 enddef
1246 T()
1247 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001248 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Ernie Raelcf138d42023-09-06 20:45:03 +02001249
1250 # Access from child class extending a class:
1251 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001252 vim9script
1253 class A
1254 this.ro_obj_var = 10
1255 public this.rw_obj_var = 20
1256 this._priv_obj_var = 30
1257 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001258
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001259 class B extends A
1260 def Foo()
1261 var x: number
1262 x = this.ro_obj_var
1263 this.ro_obj_var = 0
1264 x = this.rw_obj_var
1265 this.rw_obj_var = 0
1266 x = this._priv_obj_var
1267 this._priv_obj_var = 0
1268 enddef
1269 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001270
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001271 var b = B.new()
1272 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001273 END
1274 v9.CheckSourceSuccess(lines)
1275enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001276
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001277" Test for class variable access
1278def Test_class_variable_access()
1279 # Test for "static" cannot be abbreviated
1280 var lines =<< trim END
1281 vim9script
1282 class Something
1283 stat this.val = 1
1284 endclass
1285 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001286 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: stat this.val = 1', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001287
1288 # Test for "static" cannot be followed by "this".
1289 lines =<< trim END
1290 vim9script
1291 class Something
1292 static this.val = 1
1293 endclass
1294 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001295 v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a variable name', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001296
1297 # Test for "static" cannot be followed by "public".
1298 lines =<< trim END
1299 vim9script
1300 class Something
1301 static public val = 1
1302 endclass
1303 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001304 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001305
1306 # A readonly class variable cannot be modified from a child class
1307 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001308 vim9script
1309 class A
1310 static ro_class_var = 40
1311 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001312
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001313 class B extends A
1314 def Foo()
1315 A.ro_class_var = 50
1316 enddef
1317 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001318
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001319 var b = B.new()
1320 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001321 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001322 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001323
1324 # A private class variable cannot be accessed from a child class
1325 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001326 vim9script
1327 class A
1328 static _priv_class_var = 60
1329 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001330
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001331 class B extends A
1332 def Foo()
1333 var i = A._priv_class_var
1334 enddef
1335 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001336
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001337 var b = B.new()
1338 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001339 END
Ernie Rael64885642023-10-04 20:16:22 +02001340 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001341
1342 # A private class variable cannot be modified from a child class
1343 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001344 vim9script
1345 class A
1346 static _priv_class_var = 60
1347 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001348
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001349 class B extends A
1350 def Foo()
1351 A._priv_class_var = 0
1352 enddef
1353 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001354
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001355 var b = B.new()
1356 b.Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001357 END
Ernie Rael64885642023-10-04 20:16:22 +02001358 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001359
1360 # Access from child class extending a class and from script context
1361 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001362 vim9script
1363 class A
1364 static ro_class_var = 10
1365 public static rw_class_var = 20
1366 static _priv_class_var = 30
1367 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001368
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001369 class B extends A
1370 def Foo()
1371 var x: number
1372 x = A.ro_class_var
1373 assert_equal(10, x)
1374 x = A.rw_class_var
1375 assert_equal(25, x)
1376 A.rw_class_var = 20
1377 assert_equal(20, A.rw_class_var)
1378 enddef
1379 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001380
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001381 assert_equal(10, A.ro_class_var)
1382 assert_equal(20, A.rw_class_var)
1383 A.rw_class_var = 25
1384 assert_equal(25, A.rw_class_var)
1385 var b = B.new()
1386 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001387 END
1388 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001389enddef
1390
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001391def Test_class_object_compare()
1392 var class_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001393 vim9script
1394 class Item
1395 this.nr = 0
1396 this.name = 'xx'
1397 endclass
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001398 END
1399
1400 # used at the script level and in a compiled function
1401 var test_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001402 var i1 = Item.new()
1403 assert_equal(i1, i1)
1404 assert_true(i1 is i1)
1405 var i2 = Item.new()
1406 assert_equal(i1, i2)
1407 assert_false(i1 is i2)
1408 var i3 = Item.new(0, 'xx')
1409 assert_equal(i1, i3)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001410
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001411 var io1 = Item.new(1, 'xx')
1412 assert_notequal(i1, io1)
1413 var io2 = Item.new(0, 'yy')
1414 assert_notequal(i1, io2)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001415 END
1416
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001417 v9.CheckSourceSuccess(class_lines + test_lines)
1418 v9.CheckSourceSuccess(
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001419 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001420
1421 for op in ['>', '>=', '<', '<=', '=~', '!~']
1422 var op_lines = [
1423 'var i1 = Item.new()',
1424 'var i2 = Item.new()',
1425 'echo i1 ' .. op .. ' i2',
1426 ]
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001427 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object', 8)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001428 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001429 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001430 endfor
1431enddef
1432
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001433def Test_object_type()
1434 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001435 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001436
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001437 class One
1438 this.one = 1
1439 endclass
1440 class Two
1441 this.two = 2
1442 endclass
1443 class TwoMore extends Two
1444 this.more = 9
1445 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001446
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001447 var o: One = One.new()
1448 var t: Two = Two.new()
1449 var m: TwoMore = TwoMore.new()
1450 var tm: Two = TwoMore.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001451
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001452 t = m
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001453 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001454 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001455
1456 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001457 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001458
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001459 class One
1460 this.one = 1
1461 endclass
1462 class Two
1463 this.two = 2
1464 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001465
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001466 var o: One = Two.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001467 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001468 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>', 10)
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001469
1470 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001471 vim9script
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001472
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001473 interface One
1474 def GetMember(): number
1475 endinterface
1476 class Two implements One
1477 this.one = 1
1478 def GetMember(): number
1479 return this.one
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001480 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001481 endclass
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001482
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001483 var o: One = Two.new(5)
1484 assert_equal(5, o.GetMember())
1485 END
1486 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001487
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001488 lines =<< trim END
1489 vim9script
1490
1491 class Num
1492 this.n: number = 0
1493 endclass
1494
1495 def Ref(name: string): func(Num): Num
1496 return (arg: Num): Num => {
1497 return eval(name)(arg)
1498 }
1499 enddef
1500
1501 const Fn = Ref('Double')
1502 var Double = (m: Num): Num => Num.new(m.n * 2)
1503
1504 echo Fn(Num.new(4))
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001505 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001506 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001507enddef
1508
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001509def Test_class_member()
1510 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001511 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001512 vim9script
1513 class TextPos
1514 this.lnum = 1
1515 this.col = 1
1516 static counter = 0
1517 static _secret = 7
1518 public static anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001519
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001520 static def AddToCounter(nr: number)
1521 counter += nr
1522 enddef
1523 endclass
Bram Moolenaard505d172022-12-18 21:42:55 +00001524
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001525 assert_equal(0, TextPos.counter)
1526 TextPos.AddToCounter(3)
1527 assert_equal(3, TextPos.counter)
1528 assert_fails('echo TextPos.noSuchMember', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001529
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001530 def GetCounter(): number
1531 return TextPos.counter
1532 enddef
1533 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001534
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001535 assert_fails('TextPos.noSuchMember = 2', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
1536 assert_fails('TextPos.counter = 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
1537 assert_fails('TextPos.counter += 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001538
Ernie Rael64885642023-10-04 20:16:22 +02001539 assert_fails('echo TextPos._secret', 'E1333: Cannot access private variable "_secret" in class "TextPos"')
1540 assert_fails('TextPos._secret = 8', 'E1333: Cannot access private variable "_secret" in class "TextPos"')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001541
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001542 assert_equal(42, TextPos.anybody)
1543 TextPos.anybody = 12
1544 assert_equal(12, TextPos.anybody)
1545 TextPos.anybody += 5
1546 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001547 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001548 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001549
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001550 # example in the help
1551 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001552 vim9script
1553 class OtherThing
1554 this.size: number
1555 static totalSize: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001556
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001557 def new(this.size)
1558 totalSize += this.size
1559 enddef
1560 endclass
1561 assert_equal(0, OtherThing.totalSize)
1562 var to3 = OtherThing.new(3)
1563 assert_equal(3, OtherThing.totalSize)
1564 var to7 = OtherThing.new(7)
1565 assert_equal(10, OtherThing.totalSize)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001566 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001567 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001568
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001569 # using static class member twice
1570 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001571 vim9script
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001572
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001573 class HTML
1574 static author: string = 'John Doe'
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001575
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001576 static def MacroSubstitute(s: string): string
1577 return substitute(s, '{{author}}', author, 'gi')
1578 enddef
1579 endclass
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001580
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001581 assert_equal('some text', HTML.MacroSubstitute('some text'))
1582 assert_equal('some text', HTML.MacroSubstitute('some text'))
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001583 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001584 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001585
Bram Moolenaar62a69232023-01-24 15:07:04 +00001586 # access private member in lambda
1587 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001588 vim9script
Bram Moolenaar62a69232023-01-24 15:07:04 +00001589
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001590 class Foo
1591 this._x: number = 0
Bram Moolenaar62a69232023-01-24 15:07:04 +00001592
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001593 def Add(n: number): number
1594 const F = (): number => this._x + n
1595 return F()
1596 enddef
1597 endclass
Bram Moolenaar62a69232023-01-24 15:07:04 +00001598
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001599 var foo = Foo.new()
1600 assert_equal(5, foo.Add(5))
Bram Moolenaar62a69232023-01-24 15:07:04 +00001601 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001602 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001603
h-east2bd6a092023-05-19 19:01:17 +01001604 # access private member in lambda body
1605 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001606 vim9script
h-east2bd6a092023-05-19 19:01:17 +01001607
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001608 class Foo
1609 this._x: number = 6
h-east2bd6a092023-05-19 19:01:17 +01001610
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001611 def Add(n: number): number
1612 var Lam = () => {
1613 this._x = this._x + n
1614 }
1615 Lam()
1616 return this._x
1617 enddef
1618 endclass
h-east2bd6a092023-05-19 19:01:17 +01001619
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001620 var foo = Foo.new()
1621 assert_equal(13, foo.Add(7))
h-east2bd6a092023-05-19 19:01:17 +01001622 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001623 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001624
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001625 # check shadowing
1626 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001627 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001628
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001629 class Some
1630 static count = 0
1631 def Method(count: number)
1632 echo count
1633 enddef
1634 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001635
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001636 var s = Some.new()
1637 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001638 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001639 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001640
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001641 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001642 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001643 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001644
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001645 class Some
1646 static count = 0
1647 def Method(arg: number)
1648 var count = 3
1649 echo arg count
1650 enddef
1651 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001652
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001653 var s = Some.new()
1654 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001655 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001656 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001657
1658 # Test for using an invalid type for a member variable
1659 lines =<< trim END
1660 vim9script
1661 class A
1662 this.val: xxx
1663 endclass
1664 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001665 v9.CheckSourceFailure(lines, 'E1010: Type not recognized: xxx', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001666
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001667 # Test for setting a member on a null object
1668 lines =<< trim END
1669 vim9script
1670 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001671 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001672 endclass
1673
1674 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001675 var obj: A
1676 obj.val = ""
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001677 enddef
1678 F()
1679 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001680 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001681
1682 # Test for accessing a member on a null object
1683 lines =<< trim END
1684 vim9script
1685 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001686 this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001687 endclass
1688
1689 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001690 var obj: A
1691 echo obj.val
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001692 enddef
1693 F()
1694 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001695 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001696
1697 # Test for setting a member on a null object, at script level
1698 lines =<< trim END
1699 vim9script
1700 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001701 public this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001702 endclass
1703
1704 var obj: A
1705 obj.val = ""
1706 END
1707 # FIXME(in source): this should give E1360 as well!
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001708 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001709
1710 # Test for accessing a member on a null object, at script level
1711 lines =<< trim END
1712 vim9script
1713 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001714 this.val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001715 endclass
1716
1717 var obj: A
1718 echo obj.val
1719 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001720 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001721
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001722 # Test for no space before or after the '=' when initializing a member
1723 # variable
1724 lines =<< trim END
1725 vim9script
1726 class A
1727 this.val: number= 10
1728 endclass
1729 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001730 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001731 lines =<< trim END
1732 vim9script
1733 class A
1734 this.val: number =10
1735 endclass
1736 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001737 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001738
1739 # Access a non-existing member
1740 lines =<< trim END
1741 vim9script
1742 class A
1743 endclass
1744 var a = A.new()
1745 var v = a.bar
1746 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001747 v9.CheckSourceFailure(lines, 'E1337: Class variable "bar" not found in class "A"', 5)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001748enddef
1749
Ernie Raele6c9aa52023-10-06 19:55:52 +02001750" These messages should show the defining class of the variable (base class),
1751" not the class that did the reference (super class)
1752def Test_defining_class_message()
1753 var lines =<< trim END
1754 vim9script
1755
1756 class Base
1757 this._v1: list<list<number>>
1758 endclass
1759
1760 class Child extends Base
1761 endclass
1762
1763 var o = Child.new()
1764 var x = o._v1
1765 END
1766 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Base"', 11)
1767 lines =<< trim END
1768 vim9script
1769
1770 class Base
1771 this._v1: list<list<number>>
1772 endclass
1773
1774 class Child extends Base
1775 endclass
1776
1777 def F()
1778 var o = Child.new()
1779 var x = o._v1
1780 enddef
1781 F()
1782 END
1783 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Base"', 2)
1784 lines =<< trim END
1785 vim9script
1786
1787 class Base
1788 this.v1: list<list<number>>
1789 endclass
1790
1791 class Child extends Base
1792 endclass
1793
1794 var o = Child.new()
1795 o.v1 = []
1796 END
1797 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 11)
1798 lines =<< trim END
1799 vim9script
1800
1801 class Base
1802 this.v1: list<list<number>>
1803 endclass
1804
1805 class Child extends Base
1806 endclass
1807
1808 def F()
1809 var o = Child.new()
1810 o.v1 = []
1811 enddef
1812 F()
1813 END
1814
1815 # Attempt to read a private variable that is in the middle
1816 # of the class hierarchy.
1817 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 2)
1818 lines =<< trim END
1819 vim9script
1820
1821 class Base0
1822 endclass
1823
1824 class Base extends Base0
1825 this._v1: list<list<number>>
1826 endclass
1827
1828 class Child extends Base
1829 endclass
1830
1831 def F()
1832 var o = Child.new()
1833 var x = o._v1
1834 enddef
1835 F()
1836 END
1837 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Base"', 2)
1838
1839 # Attempt to read a private variable that is at the start
1840 # of the class hierarchy.
1841 lines =<< trim END
1842 vim9script
1843
1844 class Base0
1845 endclass
1846
1847 class Base extends Base0
1848 endclass
1849
1850 class Child extends Base
1851 this._v1: list<list<number>>
1852 endclass
1853
1854 def F()
1855 var o = Child.new()
1856 var x = o._v1
1857 enddef
1858 F()
1859 END
1860 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "Child"', 2)
1861enddef
1862
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001863func Test_class_garbagecollect()
1864 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001865 vim9script
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001866
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001867 class Point
1868 this.p = [2, 3]
1869 static pl = ['a', 'b']
1870 static pd = {a: 'a', b: 'b'}
1871 endclass
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001872
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001873 echo Point.pl Point.pd
1874 call test_garbagecollect_now()
1875 echo Point.pl Point.pd
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001876 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001877 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001878
1879 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001880 vim9script
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001881
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001882 interface View
1883 endinterface
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001884
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001885 class Widget
1886 this.view: View
1887 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001888
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001889 class MyView implements View
1890 this.widget: Widget
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001891
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001892 def new()
1893 # this will result in a circular reference to this object
1894 this.widget = Widget.new(this)
1895 enddef
1896 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001897
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001898 var view = MyView.new()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001899
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001900 # overwrite "view", will be garbage-collected next
1901 view = MyView.new()
1902 test_garbagecollect_now()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01001903 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001904 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00001905endfunc
1906
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001907" Test interface garbage collection
1908func Test_interface_garbagecollect()
1909 let lines =<< trim END
1910 vim9script
1911
1912 interface I
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001913 this.ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001914
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001915 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001916 endinterface
1917
1918 class A implements I
1919 static ro_class_var: number = 10
1920 public static rw_class_var: number = 20
1921 static _priv_class_var: number = 30
1922 this.ro_obj_var: number = 40
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001923 this._priv_obj_var: number = 60
1924
1925 static def _ClassBar(): number
1926 return _priv_class_var
1927 enddef
1928
1929 static def ClassFoo(): number
1930 return ro_class_var + rw_class_var + A._ClassBar()
1931 enddef
1932
1933 def _ObjBar(): number
1934 return this._priv_obj_var
1935 enddef
1936
1937 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001938 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001939 enddef
1940 endclass
1941
1942 assert_equal(60, A.ClassFoo())
1943 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001944 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001945 test_garbagecollect_now()
1946 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02001947 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001948 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001949 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02001950endfunc
1951
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001952def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001953 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001954 vim9script
1955 class Value
1956 this.value = 0
1957 static objects = 0
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001958
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001959 def new(v: number)
1960 this.value = v
1961 ++objects
1962 enddef
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001963
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001964 static def GetCount(): number
1965 return objects
1966 enddef
1967 endclass
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001968
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001969 assert_equal(0, Value.GetCount())
1970 var v1 = Value.new(2)
1971 assert_equal(1, Value.GetCount())
1972 var v2 = Value.new(7)
1973 assert_equal(2, Value.GetCount())
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00001974 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001975 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001976
1977 # Test for cleaning up after a class definition failure when using class
1978 # functions.
1979 lines =<< trim END
1980 vim9script
1981 class A
1982 static def Foo()
1983 enddef
1984 aaa
1985 endclass
1986 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001987 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: aaa', 5)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02001988
1989 # Test for calling a class method from another class method without the class
1990 # name prefix.
1991 lines =<< trim END
1992 vim9script
1993 class A
1994 static myList: list<number> = [1]
1995 static def Foo(n: number)
1996 myList->add(n)
1997 enddef
1998 static def Bar()
1999 Foo(2)
2000 enddef
2001 def Baz()
2002 Foo(3)
2003 enddef
2004 endclass
2005 A.Bar()
2006 var a = A.new()
2007 a.Baz()
2008 assert_equal([1, 2, 3], A.myList)
2009 END
2010 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002011enddef
2012
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002013def Test_class_defcompile()
2014 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002015 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002016
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002017 class C
2018 def Fo(i: number): string
2019 return i
2020 enddef
2021 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002022
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002023 defcompile C.Fo
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002024 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002025 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number', 1)
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002026
2027 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002028 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002029
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002030 class C
2031 static def Fc(): number
2032 return 'x'
2033 enddef
2034 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002035
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002036 defcompile C.Fc
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002037 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002038 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002039
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002040 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002041 vim9script
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002042
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002043 class C
2044 static def new()
2045 enddef
2046 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002047
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002048 defcompile C.new
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002049 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002050 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static', 5)
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002051
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002052 # Trying to compile a function using a non-existing class variable
2053 lines =<< trim END
2054 vim9script
2055 defcompile x.Foo()
2056 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002057 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002058
2059 # Trying to compile a function using a variable which is not a class
2060 lines =<< trim END
2061 vim9script
2062 var x: number
2063 defcompile x.Foo()
2064 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002065 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002066
2067 # Trying to compile a function without specifying the name
2068 lines =<< trim END
2069 vim9script
2070 class A
2071 endclass
2072 defcompile A.
2073 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002074 v9.CheckSourceFailure(lines, 'E475: Invalid argument: A.', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002075
2076 # Trying to compile a non-existing class object member function
2077 lines =<< trim END
2078 vim9script
2079 class A
2080 endclass
2081 var a = A.new()
2082 defcompile a.Foo()
2083 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002084 v9.CheckSourceFailureList(lines, ['E1326: Variable not found on object "A": Foo', 'E475: Invalid argument: a.Foo()'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002085enddef
2086
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002087def Test_class_object_to_string()
2088 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002089 vim9script
2090 class TextPosition
2091 this.lnum = 1
2092 this.col = 22
2093 endclass
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002094
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002095 assert_equal("class TextPosition", string(TextPosition))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002096
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002097 var pos = TextPosition.new()
2098 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002099 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002100 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002101enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00002102
Bram Moolenaar554d0312023-01-05 19:59:18 +00002103def Test_interface_basics()
2104 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002105 vim9script
2106 interface Something
2107 this.ro_var: list<number>
2108 def GetCount(): number
2109 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002110 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002111 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002112
2113 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002114 interface SomethingWrong
2115 static count = 7
2116 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002117 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002118 v9.CheckSourceFailure(lines, 'E1342: Interface can only be defined in Vim9 script', 1)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002119
2120 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002121 vim9script
Bram Moolenaar554d0312023-01-05 19:59:18 +00002122
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002123 interface Some
2124 this.value: number
2125 def Method(value: number)
2126 endinterface
Bram Moolenaard40f00c2023-01-13 17:36:49 +00002127 END
h-east61378a12023-04-18 19:07:29 +01002128 # The argument name and the object member name are the same, but this is not a
2129 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002130 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002131
2132 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002133 vim9script
2134 interface somethingWrong
2135 static count = 7
2136 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002137 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002138 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong', 2)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002139
2140 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002141 vim9script
2142 interface SomethingWrong
2143 this.value: string
2144 this.count = 7
2145 def GetCount(): number
2146 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002147 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002148 v9.CheckSourceFailure(lines, 'E1344: Cannot initialize a variable in an interface', 4)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002149
2150 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002151 vim9script
2152 interface SomethingWrong
2153 this.value: string
2154 this.count: number
2155 def GetCount(): number
2156 return 5
2157 enddef
2158 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002159 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002160 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5', 6)
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002161
2162 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002163 vim9script
2164 export interface EnterExit
2165 def Enter(): void
2166 def Exit(): void
2167 endinterface
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002168 END
2169 writefile(lines, 'XdefIntf.vim', 'D')
2170
2171 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002172 vim9script
2173 import './XdefIntf.vim' as defIntf
2174 export def With(ee: defIntf.EnterExit, F: func)
2175 ee.Enter()
2176 try
2177 F()
2178 finally
2179 ee.Exit()
2180 endtry
2181 enddef
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002182 END
2183 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002184
2185 var imported =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002186 vim9script
2187 export abstract class EnterExit
2188 def Enter(): void
2189 enddef
2190 def Exit(): void
2191 enddef
2192 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +00002193 END
2194 writefile(imported, 'XdefIntf2.vim', 'D')
2195
2196 lines[1] = " import './XdefIntf2.vim' as defIntf"
2197 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002198enddef
2199
Bram Moolenaar94674f22023-01-06 18:42:20 +00002200def Test_class_implements_interface()
2201 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002202 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002203
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002204 interface Some
2205 this.count: number
2206 def Method(nr: number)
2207 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002208
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002209 class SomeImpl implements Some
2210 this.count: number
2211 def Method(nr: number)
2212 echo nr
2213 enddef
2214 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002215
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002216 interface Another
2217 this.member: string
2218 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002219
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002220 class AnotherImpl implements Some, Another
2221 this.member = 'abc'
2222 this.count = 20
2223 def Method(nr: number)
2224 echo nr
2225 enddef
2226 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002227 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002228 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002229
2230 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002231 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002232
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002233 interface Some
2234 this.count: number
2235 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002236
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002237 class SomeImpl implements Some implements Some
2238 this.count: number
2239 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002240 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002241 v9.CheckSourceFailure(lines, 'E1350: Duplicate "implements"', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002242
2243 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002244 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002245
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002246 interface Some
2247 this.count: number
2248 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002249
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002250 class SomeImpl implements Some, Some
2251 this.count: number
2252 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002253 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002254 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002255
2256 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002257 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002258
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002259 interface Some
2260 this.counter: number
2261 def Method(nr: number)
2262 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002263
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002264 class SomeImpl implements Some
2265 this.count: number
2266 def Method(nr: number)
2267 echo nr
2268 enddef
2269 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002270 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002271 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented', 13)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002272
2273 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002274 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002275
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002276 interface Some
2277 this.count: number
2278 def Methods(nr: number)
2279 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002280
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002281 class SomeImpl implements Some
2282 this.count: number
2283 def Method(nr: number)
2284 echo nr
2285 enddef
2286 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002287 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002288 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented', 13)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002289
2290 # Check different order of members in class and interface works.
2291 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002292 vim9script
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002293
2294 interface Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002295 this.label: string
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002296 this.errpos: number
2297 endinterface
2298
2299 # order of members is opposite of interface
2300 class Failure implements Result
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002301 public this.lnum: number = 5
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002302 this.errpos: number = 42
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002303 this.label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002304 endclass
2305
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002306 def Test()
2307 var result: Result = Failure.new()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002308
2309 assert_equal('label', result.label)
2310 assert_equal(42, result.errpos)
2311 enddef
2312
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002313 Test()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002314 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002315 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002316
2317 # Interface name after "extends" doesn't end in a space or NUL character
2318 lines =<< trim END
2319 vim9script
2320 interface A
2321 endinterface
2322 class B extends A"
2323 endclass
2324 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002325 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002326
2327 # Trailing characters after a class name
2328 lines =<< trim END
2329 vim9script
2330 class A bbb
2331 endclass
2332 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002333 v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002334
2335 # using "implements" with a non-existing class
2336 lines =<< trim END
2337 vim9script
2338 class A implements B
2339 endclass
2340 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002341 v9.CheckSourceFailure(lines, 'E1346: Interface name not found: B', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002342
2343 # using "implements" with a regular class
2344 lines =<< trim END
2345 vim9script
2346 class A
2347 endclass
2348 class B implements A
2349 endclass
2350 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002351 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: A', 5)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002352
2353 # using "implements" with a variable
2354 lines =<< trim END
2355 vim9script
2356 var T: number = 10
2357 class A implements T
2358 endclass
2359 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002360 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: T', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002361
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002362 # implements should be followed by a white space
2363 lines =<< trim END
2364 vim9script
2365 interface A
2366 endinterface
2367 class B implements A;
2368 endclass
2369 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002370 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A;', 4)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002371
LemonBoyc5d27442023-08-19 13:02:35 +02002372 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002373 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002374
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002375 interface One
2376 def IsEven(nr: number): bool
2377 endinterface
2378 class Two implements One
2379 def IsEven(nr: number): string
2380 enddef
2381 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002382 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002383 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002384
2385 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002386 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002387
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002388 interface One
2389 def IsEven(nr: number): bool
2390 endinterface
2391 class Two implements One
2392 def IsEven(nr: bool): bool
2393 enddef
2394 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002395 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002396 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002397
2398 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002399 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002400
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002401 interface One
2402 def IsEven(nr: number): bool
2403 endinterface
2404 class Two implements One
2405 def IsEven(nr: number, ...extra: list<number>): bool
2406 enddef
2407 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002408 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002409 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 +02002410
2411 # access superclass interface members from subclass, mix variable order
2412 lines =<< trim END
2413 vim9script
2414
2415 interface I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002416 this.mvar1: number
2417 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002418 endinterface
2419
2420 # NOTE: the order is swapped
2421 class A implements I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002422 this.mvar2: number
2423 this.mvar1: number
2424 public static svar2: number
2425 public static svar1: number
2426 def new()
2427 svar1 = 11
2428 svar2 = 12
2429 this.mvar1 = 111
2430 this.mvar2 = 112
2431 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002432 endclass
2433
2434 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002435 def new()
2436 this.mvar1 = 121
2437 this.mvar2 = 122
2438 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002439 endclass
2440
2441 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002442 def new()
2443 this.mvar1 = 131
2444 this.mvar2 = 132
2445 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002446 endclass
2447
Ernie Raelcf138d42023-09-06 20:45:03 +02002448 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002449 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002450 enddef
2451
2452 var oa = A.new()
2453 var ob = B.new()
2454 var oc = C.new()
2455
Ernie Raelcf138d42023-09-06 20:45:03 +02002456 assert_equal([111, 112], F2(oa))
2457 assert_equal([121, 122], F2(ob))
2458 assert_equal([131, 132], F2(oc))
2459 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002460 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002461
2462 # Access superclass interface members from subclass, mix variable order.
2463 # Two interfaces, one on A, one on B; each has both kinds of variables
2464 lines =<< trim END
2465 vim9script
2466
2467 interface I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002468 this.mvar1: number
2469 this.mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002470 endinterface
2471
2472 interface I2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002473 this.mvar3: number
2474 this.mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002475 endinterface
2476
2477 class A implements I1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002478 public static svar1: number
2479 public static svar2: number
2480 this.mvar1: number
2481 this.mvar2: number
2482 def new()
2483 svar1 = 11
2484 svar2 = 12
2485 this.mvar1 = 111
2486 this.mvar2 = 112
2487 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002488 endclass
2489
2490 class B extends A implements I2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002491 static svar3: number
2492 static svar4: number
2493 this.mvar3: number
2494 this.mvar4: number
2495 def new()
2496 svar3 = 23
2497 svar4 = 24
2498 this.mvar1 = 121
2499 this.mvar2 = 122
2500 this.mvar3 = 123
2501 this.mvar4 = 124
2502 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002503 endclass
2504
2505 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002506 public static svar5: number
2507 def new()
2508 svar5 = 1001
2509 this.mvar1 = 131
2510 this.mvar2 = 132
2511 this.mvar3 = 133
2512 this.mvar4 = 134
2513 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002514 endclass
2515
Ernie Raelcf138d42023-09-06 20:45:03 +02002516 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002517 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002518 enddef
2519
Ernie Raelcf138d42023-09-06 20:45:03 +02002520 def F4(i: I2): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002521 return [ i.mvar3, i.mvar4 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002522 enddef
2523
Ernie Raelcf138d42023-09-06 20:45:03 +02002524 var oa = A.new()
2525 var ob = B.new()
2526 var oc = C.new()
2527
Ernie Raelcf138d42023-09-06 20:45:03 +02002528 assert_equal([[111, 112]], [F2(oa)])
2529 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2530 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002531 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002532 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002533
2534 # Using two interface names without a space after the ","
2535 lines =<< trim END
2536 vim9script
2537 interface A
2538 endinterface
2539 interface B
2540 endinterface
2541 class C implements A,B
2542 endclass
2543 END
2544 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2545
2546 # No interface name after a comma
2547 lines =<< trim END
2548 vim9script
2549 interface A
2550 endinterface
2551 class B implements A,
2552 endclass
2553 END
2554 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2555
2556 # No interface name after implements
2557 lines =<< trim END
2558 vim9script
2559 class A implements
2560 endclass
2561 END
2562 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002563enddef
2564
Bram Moolenaard0200c82023-01-28 15:19:40 +00002565def Test_call_interface_method()
2566 var lines =<< trim END
2567 vim9script
2568 interface Base
2569 def Enter(): void
2570 endinterface
2571
2572 class Child implements Base
2573 def Enter(): void
2574 g:result ..= 'child'
2575 enddef
2576 endclass
2577
2578 def F(obj: Base)
2579 obj.Enter()
2580 enddef
2581
2582 g:result = ''
2583 F(Child.new())
2584 assert_equal('child', g:result)
2585 unlet g:result
2586 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002587 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002588
2589 lines =<< trim END
2590 vim9script
2591 class Base
2592 def Enter(): void
2593 g:result ..= 'base'
2594 enddef
2595 endclass
2596
2597 class Child extends Base
2598 def Enter(): void
2599 g:result ..= 'child'
2600 enddef
2601 endclass
2602
2603 def F(obj: Base)
2604 obj.Enter()
2605 enddef
2606
2607 g:result = ''
2608 F(Child.new())
2609 assert_equal('child', g:result)
2610 unlet g:result
2611 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002612 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002613
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002614 # method of interface returns a value
2615 lines =<< trim END
2616 vim9script
2617 interface Base
2618 def Enter(): string
2619 endinterface
2620
2621 class Child implements Base
2622 def Enter(): string
2623 g:result ..= 'child'
2624 return "/resource"
2625 enddef
2626 endclass
2627
2628 def F(obj: Base)
2629 var r = obj.Enter()
2630 g:result ..= r
2631 enddef
2632
2633 g:result = ''
2634 F(Child.new())
2635 assert_equal('child/resource', g:result)
2636 unlet g:result
2637 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002638 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002639
2640 lines =<< trim END
2641 vim9script
2642 class Base
2643 def Enter(): string
2644 return null_string
2645 enddef
2646 endclass
2647
2648 class Child extends Base
2649 def Enter(): string
2650 g:result ..= 'child'
2651 return "/resource"
2652 enddef
2653 endclass
2654
2655 def F(obj: Base)
2656 var r = obj.Enter()
2657 g:result ..= r
2658 enddef
2659
2660 g:result = ''
2661 F(Child.new())
2662 assert_equal('child/resource', g:result)
2663 unlet g:result
2664 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002665 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002666
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002667 # No class that implements the interface.
2668 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002669 vim9script
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002670
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002671 interface IWithEE
2672 def Enter(): any
2673 def Exit(): void
2674 endinterface
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002675
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002676 def With1(ee: IWithEE, F: func)
2677 var r = ee.Enter()
2678 enddef
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002679
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002680 defcompile
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002681 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002682 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002683enddef
2684
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002685def Test_class_used_as_type()
2686 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002687 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002688
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002689 class Point
2690 this.x = 0
2691 this.y = 0
2692 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002693
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002694 var p: Point
2695 p = Point.new(2, 33)
2696 assert_equal(2, p.x)
2697 assert_equal(33, p.y)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002698 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002699 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002700
2701 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002702 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002703
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002704 interface HasX
2705 this.x: number
2706 endinterface
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002707
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002708 class Point implements HasX
2709 this.x = 0
2710 this.y = 0
2711 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002712
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002713 var p: Point
2714 p = Point.new(2, 33)
2715 var hx = p
2716 assert_equal(2, hx.x)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002717 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002718 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002719
2720 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002721 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002722
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002723 class Point
2724 this.x = 0
2725 this.y = 0
2726 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002727
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002728 var p: Point
2729 p = 'text'
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002730 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002731 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string', 9)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002732enddef
2733
Bram Moolenaar83677162023-01-08 19:54:10 +00002734def Test_class_extends()
2735 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002736 vim9script
2737 class Base
2738 this.one = 1
2739 def GetOne(): number
2740 return this.one
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002741 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002742 endclass
2743 class Child extends Base
2744 this.two = 2
2745 def GetTotal(): number
2746 return this.one + this.two
2747 enddef
2748 endclass
2749 var o = Child.new()
2750 assert_equal(1, o.one)
2751 assert_equal(2, o.two)
2752 assert_equal(1, o.GetOne())
2753 assert_equal(3, o.GetTotal())
Bram Moolenaar6481acc2023-01-11 21:14:17 +00002754 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002755 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002756
2757 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002758 vim9script
2759 class Base
2760 this.one = 1
2761 endclass
2762 class Child extends Base
2763 this.two = 2
2764 endclass
2765 var o = Child.new(3, 44)
2766 assert_equal(3, o.one)
2767 assert_equal(44, o.two)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00002768 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002769 v9.CheckSourceSuccess(lines)
2770
2771 lines =<< trim END
2772 vim9script
2773 class Base
2774 this.one = 1
2775 endclass
2776 class Child extends Base extends Base
2777 this.two = 2
2778 endclass
2779 END
2780 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"', 5)
2781
2782 lines =<< trim END
2783 vim9script
2784 class Child extends BaseClass
2785 this.two = 2
2786 endclass
2787 END
2788 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass', 4)
2789
2790 lines =<< trim END
2791 vim9script
2792 var SomeVar = 99
2793 class Child extends SomeVar
2794 this.two = 2
2795 endclass
2796 END
2797 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar', 5)
2798
2799 lines =<< trim END
2800 vim9script
2801 class Base
2802 this.name: string
2803 def ToString(): string
2804 return this.name
2805 enddef
2806 endclass
2807
2808 class Child extends Base
2809 this.age: number
2810 def ToString(): string
2811 return super.ToString() .. ': ' .. this.age
2812 enddef
2813 endclass
2814
2815 var o = Child.new('John', 42)
2816 assert_equal('John: 42', o.ToString())
2817 END
2818 v9.CheckSourceSuccess(lines)
2819
2820 lines =<< trim END
2821 vim9script
2822 class Child
2823 this.age: number
2824 def ToString(): number
2825 return this.age
2826 enddef
2827 def ToString(): string
2828 return this.age
2829 enddef
2830 endclass
2831 END
2832 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
2833
2834 lines =<< trim END
2835 vim9script
2836 class Child
2837 this.age: number
2838 def ToString(): string
2839 return super .ToString() .. ': ' .. this.age
2840 enddef
2841 endclass
2842 var o = Child.new(42)
2843 echo o.ToString()
2844 END
2845 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
2846
2847 lines =<< trim END
2848 vim9script
2849 class Base
2850 this.name: string
2851 def ToString(): string
2852 return this.name
2853 enddef
2854 endclass
2855
2856 var age = 42
2857 def ToString(): string
2858 return super.ToString() .. ': ' .. age
2859 enddef
2860 echo ToString()
2861 END
2862 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
2863
2864 lines =<< trim END
2865 vim9script
2866 class Child
2867 this.age: number
2868 def ToString(): string
2869 return super.ToString() .. ': ' .. this.age
2870 enddef
2871 endclass
2872 var o = Child.new(42)
2873 echo o.ToString()
2874 END
2875 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
2876
2877 lines =<< trim END
2878 vim9script
2879 class Base
2880 this.name: string
2881 static def ToString(): string
2882 return 'Base class'
2883 enddef
2884 endclass
2885
2886 class Child extends Base
2887 this.age: number
2888 def ToString(): string
2889 return Base.ToString() .. ': ' .. this.age
2890 enddef
2891 endclass
2892
2893 var o = Child.new('John', 42)
2894 assert_equal('Base class: 42', o.ToString())
2895 END
2896 v9.CheckSourceSuccess(lines)
2897
2898 lines =<< trim END
2899 vim9script
2900 class Base
2901 this.value = 1
2902 def new(init: number)
2903 this.value = number + 1
2904 enddef
2905 endclass
2906 class Child extends Base
2907 def new()
2908 this.new(3)
2909 enddef
2910 endclass
2911 var c = Child.new()
2912 END
2913 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002914
2915 # base class with more than one object member
2916 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002917 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002918
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002919 class Result
2920 this.success: bool
2921 this.value: any = null
2922 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002923
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002924 class Success extends Result
2925 def new(this.value = v:none)
2926 this.success = true
2927 enddef
2928 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002929
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002930 var v = Success.new('asdf')
2931 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00002932 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002933 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002934
2935 # class name after "extends" doesn't end in a space or NUL character
2936 lines =<< trim END
2937 vim9script
2938 class A
2939 endclass
2940 class B extends A"
2941 endclass
2942 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002943 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00002944enddef
2945
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002946def Test_using_base_class()
2947 var lines =<< trim END
2948 vim9script
2949
2950 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002951 def Enter(): any
2952 return null
2953 enddef
2954 def Exit(resource: any): void
2955 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002956 endclass
2957
2958 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002959 def Enter(): any
2960 return 42
2961 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002962
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002963 def Exit(resource: number): void
2964 g:result ..= '/exit'
2965 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002966 endclass
2967
2968 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002969 var r = ee.Enter()
2970 try
2971 g:result ..= r
2972 finally
2973 g:result ..= '/finally'
2974 ee.Exit(r)
2975 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002976 enddef
2977
2978 g:result = ''
2979 With(ChildEE.new())
2980 assert_equal('42/finally/exit', g:result)
2981 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002982 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00002983 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01002984
2985 # Using super, Child invokes Base method which has optional arg. #12471
2986 lines =<< trim END
2987 vim9script
2988
2989 class Base
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002990 this.success: bool = false
2991 def Method(arg = 0)
2992 this.success = true
2993 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01002994 endclass
2995
2996 class Child extends Base
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002997 def new()
2998 super.Method()
2999 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01003000 endclass
3001
3002 var obj = Child.new()
3003 assert_equal(true, obj.success)
3004 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003005 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003006enddef
3007
Bram Moolenaara86655a2023-01-12 17:06:27 +00003008def Test_class_import()
3009 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003010 vim9script
3011 export class Animal
3012 this.kind: string
3013 this.name: string
3014 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003015 END
3016 writefile(lines, 'Xanimal.vim', 'D')
3017
3018 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003019 vim9script
3020 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003021
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003022 var a: animal.Animal
3023 a = animal.Animal.new('fish', 'Eric')
3024 assert_equal('fish', a.kind)
3025 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003026
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003027 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3028 assert_equal('cat', b.kind)
3029 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003030 END
3031 v9.CheckScriptSuccess(lines)
3032enddef
3033
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003034def Test_abstract_class()
3035 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003036 vim9script
3037 abstract class Base
3038 this.name: string
3039 endclass
3040 class Person extends Base
3041 this.age: number
3042 endclass
3043 var p: Base = Person.new('Peter', 42)
3044 assert_equal('Peter', p.name)
3045 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003046 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003047 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003048
3049 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003050 vim9script
3051 abstract class Base
3052 this.name: string
3053 endclass
3054 class Person extends Base
3055 this.age: number
3056 endclass
3057 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003058 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003059 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003060
3061 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003062 abstract class Base
3063 this.name: string
3064 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003065 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003066 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003067
3068 # Abstract class cannot have a "new" function
3069 lines =<< trim END
3070 vim9script
3071 abstract class Base
3072 def new()
3073 enddef
3074 endclass
3075 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003076 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003077enddef
3078
Bram Moolenaar486fc252023-01-18 14:51:07 +00003079def Test_closure_in_class()
3080 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003081 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003082
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003083 class Foo
3084 this.y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003085
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003086 def new()
3087 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3088 enddef
3089 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003090
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003091 Foo.new()
3092 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003093 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003094 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003095enddef
3096
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003097def Test_call_constructor_from_legacy()
3098 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003099 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003100
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003101 var newCalled = 'false'
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003102
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003103 class A
3104 def new()
3105 newCalled = 'true'
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003106 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003107 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003108
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003109 export def F(options = {}): any
3110 return A
3111 enddef
3112
3113 g:p = F()
3114 legacy call p.new()
3115 assert_equal('true', newCalled)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003116 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003117 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003118enddef
3119
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003120def Test_defer_with_object()
3121 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003122 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003123
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003124 class CWithEE
3125 def Enter()
3126 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003127 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003128 def Exit()
3129 g:result ..= "exited"
3130 enddef
3131 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003132
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003133 def With(ee: CWithEE, F: func)
3134 ee.Enter()
3135 defer ee.Exit()
3136 F()
3137 enddef
3138
3139 g:result = ''
3140 var obj = CWithEE.new()
3141 obj->With(() => {
3142 g:result ..= "called/"
3143 })
3144 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003145 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003146 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003147 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003148
3149 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003150 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003151
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003152 class BaseWithEE
3153 def Enter()
3154 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003155 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003156 def Exit()
3157 g:result ..= "exited-base"
3158 enddef
3159 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003160
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003161 class CWithEE extends BaseWithEE
3162 def Enter()
3163 g:result ..= "entered-child/"
3164 enddef
3165 def Exit()
3166 g:result ..= "exited-child"
3167 enddef
3168 endclass
3169
3170 def With(ee: BaseWithEE, F: func)
3171 ee.Enter()
3172 defer ee.Exit()
3173 F()
3174 enddef
3175
3176 g:result = ''
3177 var obj = CWithEE.new()
3178 obj->With(() => {
3179 g:result ..= "called/"
3180 })
3181 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003182 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003183 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003184 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003185enddef
3186
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003187" The following test used to crash Vim (Github issue #12676)
3188def Test_extends_method_crashes_vim()
3189 var lines =<< trim END
3190 vim9script
3191
3192 class Observer
3193 endclass
3194
3195 class Property
3196 this.value: any
3197
3198 def Set(v: any)
3199 if v != this.value
3200 this.value = v
3201 endif
3202 enddef
3203
3204 def Register(observer: Observer)
3205 enddef
3206 endclass
3207
3208 class Bool extends Property
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003209 this.value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003210 endclass
3211
3212 def Observe(obj: Property, who: Observer)
3213 obj.Register(who)
3214 enddef
3215
3216 var p = Bool.new(false)
3217 var myObserver = Observer.new()
3218
3219 Observe(p, myObserver)
3220
3221 p.Set(true)
3222 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003223 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003224enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003225
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003226" Test for calling a method in a class that is extended
3227def Test_call_method_in_extended_class()
3228 var lines =<< trim END
3229 vim9script
3230
3231 var prop_init_called = false
3232 var prop_register_called = false
3233
3234 class Property
3235 def Init()
3236 prop_init_called = true
3237 enddef
3238
3239 def Register()
3240 prop_register_called = true
3241 enddef
3242 endclass
3243
3244 class Bool extends Property
3245 endclass
3246
3247 def Observe(obj: Property)
3248 obj.Register()
3249 enddef
3250
3251 var p = Property.new()
3252 Observe(p)
3253
3254 p.Init()
3255 assert_true(prop_init_called)
3256 assert_true(prop_register_called)
3257 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003258 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003259enddef
3260
LemonBoyafe04662023-08-23 21:08:11 +02003261def Test_instanceof()
3262 var lines =<< trim END
3263 vim9script
3264
3265 class Base1
3266 endclass
3267
3268 class Base2 extends Base1
3269 endclass
3270
3271 interface Intf1
3272 endinterface
3273
3274 class Mix1 implements Intf1
3275 endclass
3276
3277 class Base3 extends Mix1
3278 endclass
3279
3280 var b1 = Base1.new()
3281 var b2 = Base2.new()
3282 var b3 = Base3.new()
3283
3284 assert_true(instanceof(b1, Base1))
3285 assert_true(instanceof(b2, Base1))
3286 assert_false(instanceof(b1, Base2))
3287 assert_true(instanceof(b3, Mix1))
3288 assert_false(instanceof(b3, []))
3289 assert_true(instanceof(b3, [Base1, Base2, Intf1]))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003290
3291 def Foo()
3292 var a1 = Base1.new()
3293 var a2 = Base2.new()
3294 var a3 = Base3.new()
3295
3296 assert_true(instanceof(a1, Base1))
3297 assert_true(instanceof(a2, Base1))
3298 assert_false(instanceof(a1, Base2))
3299 assert_true(instanceof(a3, Mix1))
3300 assert_false(instanceof(a3, []))
3301 assert_true(instanceof(a3, [Base1, Base2, Intf1]))
3302 enddef
3303 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003304
3305 var o_null: Base1
3306 assert_false(instanceof(o_null, Base1))
3307
LemonBoyafe04662023-08-23 21:08:11 +02003308 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003309 v9.CheckSourceSuccess(lines)
LemonBoyafe04662023-08-23 21:08:11 +02003310enddef
3311
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003312" Test for calling a method in the parent class that is extended partially.
3313" This used to fail with the 'E118: Too many arguments for function: Text' error
3314" message (Github issue #12524).
3315def Test_call_method_in_parent_class()
3316 var lines =<< trim END
3317 vim9script
3318
3319 class Widget
3320 this._lnum: number = 1
3321
3322 def SetY(lnum: number)
3323 this._lnum = lnum
3324 enddef
3325
3326 def Text(): string
3327 return ''
3328 enddef
3329 endclass
3330
3331 class Foo extends Widget
3332 def Text(): string
3333 return '<Foo>'
3334 enddef
3335 endclass
3336
3337 def Stack(w1: Widget, w2: Widget): list<Widget>
3338 w1.SetY(1)
3339 w2.SetY(2)
3340 return [w1, w2]
3341 enddef
3342
3343 var foo1 = Foo.new()
3344 var foo2 = Foo.new()
3345 var l = Stack(foo1, foo2)
3346 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003347 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003348enddef
3349
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003350" Test for calling methods from three levels of classes
3351def Test_multi_level_method_call()
3352 var lines =<< trim END
3353 vim9script
3354
3355 var A_func1: number = 0
3356 var A_func2: number = 0
3357 var A_func3: number = 0
3358 var B_func2: number = 0
3359 var B_func3: number = 0
3360 var C_func3: number = 0
3361
3362 class A
3363 def Func1()
3364 A_func1 += 1
3365 enddef
3366
3367 def Func2()
3368 A_func2 += 1
3369 enddef
3370
3371 def Func3()
3372 A_func3 += 1
3373 enddef
3374 endclass
3375
3376 class B extends A
3377 def Func2()
3378 B_func2 += 1
3379 enddef
3380
3381 def Func3()
3382 B_func3 += 1
3383 enddef
3384 endclass
3385
3386 class C extends B
3387 def Func3()
3388 C_func3 += 1
3389 enddef
3390 endclass
3391
3392 def A_CallFuncs(a: A)
3393 a.Func1()
3394 a.Func2()
3395 a.Func3()
3396 enddef
3397
3398 def B_CallFuncs(b: B)
3399 b.Func1()
3400 b.Func2()
3401 b.Func3()
3402 enddef
3403
3404 def C_CallFuncs(c: C)
3405 c.Func1()
3406 c.Func2()
3407 c.Func3()
3408 enddef
3409
3410 var cobj = C.new()
3411 A_CallFuncs(cobj)
3412 B_CallFuncs(cobj)
3413 C_CallFuncs(cobj)
3414 assert_equal(3, A_func1)
3415 assert_equal(0, A_func2)
3416 assert_equal(0, A_func3)
3417 assert_equal(3, B_func2)
3418 assert_equal(0, B_func3)
3419 assert_equal(3, C_func3)
3420 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003421 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003422enddef
3423
3424" Test for using members from three levels of classes
3425def Test_multi_level_member_access()
3426 var lines =<< trim END
3427 vim9script
3428
3429 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003430 public this.val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003431 endclass
3432
3433 class B extends A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003434 public this.val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003435 endclass
3436
3437 class C extends B
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02003438 public this.val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003439 endclass
3440
3441 def A_members(a: A)
3442 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003443 enddef
3444
3445 def B_members(b: B)
3446 b.val1 += 1
3447 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003448 enddef
3449
3450 def C_members(c: C)
3451 c.val1 += 1
3452 c.val2 += 1
3453 c.val3 += 1
3454 enddef
3455
3456 var cobj = C.new()
3457 A_members(cobj)
3458 B_members(cobj)
3459 C_members(cobj)
3460 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02003461 assert_equal(2, cobj.val2)
3462 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003463 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003464 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003465enddef
3466
LemonBoy0ffc17a2023-08-20 18:09:11 +02003467" Test expansion of <stack> with class methods.
3468def Test_stack_expansion_with_methods()
3469 var lines =<< trim END
3470 vim9script
3471
3472 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003473 def M1()
3474 F0()
3475 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02003476 endclass
3477
3478 def F0()
3479 assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
3480 enddef
3481
3482 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003483 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02003484 enddef
3485
3486 F()
3487 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003488 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02003489enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003490
3491" Test the return type of the new() constructor
3492def Test_new_return_type()
3493 # new() uses the default return type and there is no return statement
3494 var lines =<< trim END
3495 vim9script
3496
3497 class C
3498 this._bufnr: number
3499
3500 def new(this._bufnr)
3501 if !bufexists(this._bufnr)
3502 this._bufnr = -1
3503 endif
3504 enddef
3505 endclass
3506
3507 var c = C.new(12345)
3508 assert_equal('object<C>', typename(c))
3509
3510 var v1: C
3511 v1 = C.new(12345)
3512 assert_equal('object<C>', typename(v1))
3513
3514 def F()
3515 var v2: C
3516 v2 = C.new(12345)
3517 assert_equal('object<C>', typename(v2))
3518 enddef
3519 F()
3520 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003521 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003522
3523 # new() uses the default return type and an empty 'return' statement
3524 lines =<< trim END
3525 vim9script
3526
3527 class C
3528 this._bufnr: number
3529
3530 def new(this._bufnr)
3531 if !bufexists(this._bufnr)
3532 this._bufnr = -1
3533 return
3534 endif
3535 enddef
3536 endclass
3537
3538 var c = C.new(12345)
3539 assert_equal('object<C>', typename(c))
3540
3541 var v1: C
3542 v1 = C.new(12345)
3543 assert_equal('object<C>', typename(v1))
3544
3545 def F()
3546 var v2: C
3547 v2 = C.new(12345)
3548 assert_equal('object<C>', typename(v2))
3549 enddef
3550 F()
3551 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003552 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003553
3554 # new() uses "any" return type and returns "this"
3555 lines =<< trim END
3556 vim9script
3557
3558 class C
3559 this._bufnr: number
3560
3561 def new(this._bufnr): any
3562 if !bufexists(this._bufnr)
3563 this._bufnr = -1
3564 return this
3565 endif
3566 enddef
3567 endclass
3568 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003569 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003570
3571 # new() uses 'Dict' return type and returns a Dict
3572 lines =<< trim END
3573 vim9script
3574
3575 class C
3576 this._state: dict<any>
3577
3578 def new(): dict<any>
3579 this._state = {}
3580 return this._state
3581 enddef
3582 endclass
3583
3584 var c = C.new()
3585 assert_equal('object<C>', typename(c))
3586 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003587 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02003588enddef
3589
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003590" Test for checking a member initialization type at run time.
3591def Test_runtime_type_check_for_member_init()
3592 var lines =<< trim END
3593 vim9script
3594
3595 var retnum: bool = false
3596
3597 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003598 retnum = !retnum
3599 if retnum
3600 return 1
3601 else
3602 return "hello"
3603 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003604 enddef
3605
3606 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003607 this._foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003608 endclass
3609
3610 var c1 = C.new()
3611 var c2 = C.new()
3612 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003613 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003614enddef
3615
3616" Test for locking a variable referring to an object and reassigning to another
3617" object.
Ernie Raelee865f32023-09-29 19:53:55 +02003618def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003619 var lines =<< trim END
3620 vim9script
3621
3622 class C
3623 this.val: number
3624 def new(this.val)
3625 enddef
3626 endclass
3627
3628 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
3629 lockvar 2 some_dict
3630
3631 var current: C
3632 current = some_dict['c']
3633 assert_equal(3, current.val)
3634 current = some_dict['b']
3635 assert_equal(2, current.val)
3636
3637 def F()
3638 current = some_dict['c']
3639 enddef
3640
3641 def G()
3642 current = some_dict['b']
3643 enddef
3644
3645 F()
3646 assert_equal(3, current.val)
3647 G()
3648 assert_equal(2, current.val)
3649 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003650 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02003651enddef
3652
Ernie Raelee865f32023-09-29 19:53:55 +02003653" Test trying to lock an object variable from various places
3654def Test_lockvar_object_variable()
3655 # An object variable lockvar has several cases:
3656 # object method, scriptlevel, scriplevel from :def, :def arg
3657 # method arg, static method arg.
3658 # Also different depths
3659
Ernie Raelee865f32023-09-29 19:53:55 +02003660 #
3661 # lockvar of read-only object variable
3662 #
3663
3664 # read-only lockvar from object method
3665 var lines =<< trim END
3666 vim9script
3667
3668 class C
3669 this.val1: number
3670 def Lock()
3671 lockvar this.val1
3672 enddef
3673 endclass
3674 var o = C.new(3)
3675 o.Lock()
3676 END
Ernie Rael64885642023-10-04 20:16:22 +02003677 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02003678
3679 # read-only lockvar from scriptlevel
3680 lines =<< trim END
3681 vim9script
3682
3683 class C
3684 this.val2: number
3685 endclass
3686 var o = C.new(3)
3687 lockvar o.val2
3688 END
3689 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
3690
3691 # read-only lockvar of scriptlevel variable from def
3692 lines =<< trim END
3693 vim9script
3694
3695 class C
3696 this.val3: number
3697 endclass
3698 var o = C.new(3)
3699 def Lock()
3700 lockvar o.val3
3701 enddef
3702 Lock()
3703 END
3704 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
3705
3706 # read-only lockvar of def argument variable
3707 lines =<< trim END
3708 vim9script
3709
3710 class C
3711 this.val4: number
3712 endclass
3713 def Lock(o: C)
3714 lockvar o.val4
3715 enddef
3716 Lock(C.new(3))
3717 END
3718 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
3719
3720 # TODO: the following tests use type "any" for argument. Need a run time
3721 # check for access. Probably OK as is for now.
3722
3723 # read-only lockvar from object method arg
3724 lines =<< trim END
3725 vim9script
3726
3727 class C
3728 this.val5: number
3729 def Lock(o_any: any)
3730 lockvar o_any.val5
3731 enddef
3732 endclass
3733 var o = C.new(3)
3734 o.Lock(C.new(5))
3735 END
Ernie Rael64885642023-10-04 20:16:22 +02003736 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02003737
3738 # read-only lockvar from class method arg
3739 lines =<< trim END
3740 vim9script
3741
3742 class C
3743 this.val6: number
3744 static def Lock(o_any: any)
3745 lockvar o_any.val6
3746 enddef
3747 endclass
3748 var o = C.new(3)
3749 C.Lock(o)
3750 END
Ernie Rael64885642023-10-04 20:16:22 +02003751 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02003752
3753 #
3754 # lockvar of public object variable
3755 #
3756
3757 # lockvar from object method
3758 lines =<< trim END
3759 vim9script
3760
3761 class C
3762 public this.val1: number
3763 def Lock()
3764 lockvar this.val1
3765 enddef
3766 endclass
3767 var o = C.new(3)
3768 o.Lock()
3769 END
3770 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
3771
3772 # lockvar from scriptlevel
3773 lines =<< trim END
3774 vim9script
3775
3776 class C
3777 public this.val2: number
3778 endclass
3779 var o = C.new(3)
3780 lockvar o.val2
3781 END
3782 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
3783
3784 # lockvar of scriptlevel variable from def
3785 lines =<< trim END
3786 vim9script
3787
3788 class C
3789 public this.val3: number
3790 endclass
3791 var o = C.new(3)
3792 def Lock()
3793 lockvar o.val3
3794 enddef
3795 Lock()
3796 END
3797 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
3798
3799 # lockvar of def argument variable
3800 lines =<< trim END
3801 vim9script
3802
3803 class C
3804 public this.val4: number
3805 endclass
3806 def Lock(o: C)
3807 lockvar o.val4
3808 enddef
3809 Lock(C.new(3))
3810 END
3811 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
3812
3813 # lockvar from object method arg
3814 lines =<< trim END
3815 vim9script
3816
3817 class C
3818 public this.val5: number
3819 def Lock(o_any: any)
3820 lockvar o_any.val5
3821 enddef
3822 endclass
3823 var o = C.new(3)
3824 o.Lock(C.new(5))
3825 END
3826 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val5" in class "C"', 1)
3827
3828 # lockvar from class method arg
3829 lines =<< trim END
3830 vim9script
3831
3832 class C
3833 public this.val6: number
3834 static def Lock(o_any: any)
3835 lockvar o_any.val6
3836 enddef
3837 endclass
3838 var o = C.new(3)
3839 C.Lock(o)
3840 END
3841 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val6" in class "C"', 1)
3842enddef
3843
3844" Test trying to lock a class variable from various places
3845def Test_lockvar_class_variable()
3846
3847 # lockvar bare static from object method
3848 var lines =<< trim END
3849 vim9script
3850
3851 class C
3852 public static sval1: number
3853 def Lock()
3854 lockvar sval1
3855 enddef
3856 endclass
3857 var o = C.new()
3858 o.Lock()
3859 END
3860 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
3861
3862 # lockvar C.static from object method
3863 lines =<< trim END
3864 vim9script
3865
3866 class C
3867 public static sval2: number
3868 def Lock()
3869 lockvar C.sval2
3870 enddef
3871 endclass
3872 var o = C.new()
3873 o.Lock()
3874 END
3875 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
3876
3877 # lockvar bare static from class method
3878 lines =<< trim END
3879 vim9script
3880
3881 class C
3882 public static sval3: number
3883 static def Lock()
3884 lockvar sval3
3885 enddef
3886 endclass
3887 C.Lock()
3888 END
3889 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
3890
3891 # lockvar C.static from class method
3892 lines =<< trim END
3893 vim9script
3894
3895 class C
3896 public static sval4: number
3897 static def Lock()
3898 lockvar C.sval4
3899 enddef
3900 endclass
3901 C.Lock()
3902 END
3903 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
3904
3905 # lockvar C.static from script level
3906 lines =<< trim END
3907 vim9script
3908
3909 class C
3910 public static sval5: number
3911 endclass
3912 lockvar C.sval5
3913 END
3914 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
3915
3916 # lockvar o.static from script level
3917 lines =<< trim END
3918 vim9script
3919
3920 class C
3921 public static sval6: number
3922 endclass
3923 var o = C.new()
3924 lockvar o.sval6
3925 END
3926 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
3927enddef
3928
3929" Test locking an argument to :def
3930def Test_lockvar_argument()
3931 # Lockvar a function arg
3932 var lines =<< trim END
3933 vim9script
3934
3935 def Lock(val: any)
3936 lockvar val
3937 enddef
3938
3939 var d = {a: 1, b: 2}
3940 Lock(d)
3941
3942 d->extend({c: 3})
3943 END
3944 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
3945
3946 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
3947 # class member in "C". This tests lval_root_is_arg.
3948 lines =<< trim END
3949 vim9script
3950
3951 class C
3952 public static sval: list<number>
3953 endclass
3954
3955 def Lock2(sval: any)
3956 lockvar sval
3957 enddef
3958
3959 var o = C.new()
3960 Lock2(o)
3961 END
3962 v9.CheckSourceSuccess(lines)
3963
3964 # Lock a class.
3965 lines =<< trim END
3966 vim9script
3967
3968 class C
3969 public static sval: list<number>
3970 endclass
3971
3972 def Lock2(sval: any)
3973 lockvar sval
3974 enddef
3975
3976 Lock2(C)
3977 END
3978 v9.CheckSourceSuccess(lines)
3979
3980 # Lock an object.
3981 lines =<< trim END
3982 vim9script
3983
3984 class C
3985 public static sval: list<number>
3986 endclass
3987
3988 def Lock2(sval: any)
3989 lockvar sval
3990 enddef
3991
3992 Lock2(C.new())
3993 END
3994 v9.CheckSourceSuccess(lines)
3995
3996 # In this case (unlike previous) "lockvar sval" is a class member.
3997 lines =<< trim END
3998 vim9script
3999
4000 class C
4001 public static sval: list<number>
4002 def Lock2()
4003 lockvar sval
4004 enddef
4005 endclass
4006
4007
4008 var o = C.new()
4009 o.Lock2()
4010 END
4011 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4012enddef
4013
4014" Test that this can be locked without error
4015def Test_lockvar_this()
4016 # lockvar this
4017 var lines =<< trim END
4018 vim9script
4019 class C
4020 def TLock()
4021 lockvar this
4022 enddef
4023 endclass
4024 var o = C.new()
4025 o.TLock()
4026 END
4027 v9.CheckSourceSuccess(lines)
4028
4029 # lockvar four (four letter word, but not this)
4030 lines =<< trim END
4031 vim9script
4032 class C
4033 def TLock4()
4034 var four: number
4035 lockvar four
4036 enddef
4037 endclass
4038 var o = C.new()
4039 o.TLock4()
4040 END
4041 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4042
4043 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4044 lines =<< trim END
4045 vim9script
4046 class C
4047 def TLock5()
4048 var this5: number
4049 lockvar this5
4050 enddef
4051 endclass
4052 var o = C.new()
4053 o.TLock5()
4054 END
4055 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4056enddef
4057
4058" Test some general lockvar cases
4059def Test_lockvar_general()
4060 # lockvar an object and a class. It does nothing
4061 var lines =<< trim END
4062 vim9script
4063 class C
4064 endclass
4065 var o = C.new()
4066 lockvar o
4067 lockvar C
4068 END
4069 v9.CheckSourceSuccess(lines)
4070
4071 # Lock a list element that's nested in an object variable from a :def
4072 lines =<< trim END
4073 vim9script
4074
4075 class C
4076 public this.val: list<list<number>> = [ [1], [2], [3] ]
4077 endclass
4078 def Lock2(obj: any)
4079 lockvar obj.val[1]
4080 enddef
4081
4082 var o = C.new()
4083 Lock2(o)
4084 o.val[0] = [9]
4085 assert_equal([ [9], [2], [3] ], o.val)
4086 try
4087 o.val[1] = [999]
4088 call assert_false(true, 'assign should have failed')
4089 catch
4090 assert_exception('E741:')
4091 endtry
4092 o.val[2] = [8]
4093 assert_equal([ [9], [2], [8] ], o.val)
4094 END
4095 v9.CheckSourceSuccess(lines)
4096
4097 # Lock a list element that's nested in an object variable from scriptlevel
4098 lines =<< trim END
4099 vim9script
4100
4101 class C
4102 public this.val: list<list<number>> = [ [1], [2], [3] ]
4103 endclass
4104
4105 var o = C.new()
4106 lockvar o.val[1]
4107 o.val[0] = [9]
4108 assert_equal([ [9], [2], [3] ], o.val)
4109 try
4110 o.val[1] = [999]
4111 call assert_false(true, 'assign should have failed')
4112 catch
4113 assert_exception('E741:')
4114 endtry
4115 o.val[2] = [8]
4116 assert_equal([ [9], [2], [8] ], o.val)
4117 END
4118 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004119
4120 # lock a script level variable from an object method
4121 lines =<< trim END
4122 vim9script
4123
4124 class C
4125 def Lock()
4126 lockvar l
4127 enddef
4128 endclass
4129
4130 var l = [1]
4131 C.new().Lock()
4132 l[0] = 11
4133 END
4134 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4135
4136 # lock a list element referenced by a private object variable
4137 # in an object fetched via a script level list
4138 lines =<< trim END
4139 vim9script
4140
4141 class C
4142 this._v1: list<list<number>>
4143 def Lock()
4144 lockvar lc[0]._v1[1]
4145 enddef
4146 endclass
4147
4148 var l = [[1], [2], [3]]
4149 var o = C.new(l)
4150 var lc: list<C> = [ o ]
4151
4152 o.Lock()
4153 l[0] = [22]
4154 l[1] = [33]
4155 END
4156 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4157
4158 # similar to the previous test, except the locking code is executing
4159 # in a class that does not own the private variable.
4160 # Note that the locking code is in a class has a private variable of
4161 # the same name.
4162 lines =<< trim END
4163 vim9script
4164
4165 class C2
4166 this._v1: list<list<number>>
4167 def Lock(obj: any)
4168 lockvar lc[0]._v1[1]
4169 enddef
4170 endclass
4171
4172 class C
4173 this._v1: list<list<number>>
4174 endclass
4175
4176 var l = [[1], [2], [3]]
4177 var o = C.new(l)
4178 var lc: list<C> = [ o ]
4179
4180 var o2 = C2.new()
4181 o2.Lock(o)
4182 END
4183 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004184enddef
4185
Ernie Rael9771b2a2023-10-07 22:05:40 +02004186" Test builtin islocked()
4187def Test_lockvar_islocked()
4188 # Can't lock class/object variable
4189 # Lock class/object variable's value
4190 # Lock item of variabl's value (a list item)
4191 # varible is at index 1 within class/object
4192 var lines =<< trim END
4193 vim9script
4194
4195 class C
4196 this.o0: list<list<number>> = [ [0], [1], [2]]
4197 this.o1: list<list<number>> = [[10], [11], [12]]
4198 static c0: list<list<number>> = [[20], [21], [22]]
4199 static c1: list<list<number>> = [[30], [31], [32]]
4200 endclass
4201
4202 def LockIt(arg: any)
4203 lockvar arg
4204 enddef
4205
4206 def UnlockIt(arg: any)
4207 unlockvar arg
4208 enddef
4209
4210 var obj = C.new()
4211 #lockvar obj.o1 # can't lock something you can't write to
4212
4213 try
4214 lockvar obj.o1 # can't lock something you can't write to
4215 call assert_false(1, '"lockvar obj.o1" should have failed')
4216 catch
4217 call assert_exception('E1335:')
4218 endtry
4219
4220 LockIt(obj.o1) # but can lock it's value
4221 assert_equal(1, islocked("obj.o1"))
4222 assert_equal(1, islocked("obj.o1[0]"))
4223 assert_equal(1, islocked("obj.o1[1]"))
4224 UnlockIt(obj.o1)
4225 assert_equal(0, islocked("obj.o1"))
4226 assert_equal(0, islocked("obj.o1[0]"))
4227
4228 lockvar obj.o1[0]
4229 assert_equal(0, islocked("obj.o1"))
4230 assert_equal(1, islocked("obj.o1[0]"))
4231 assert_equal(0, islocked("obj.o1[1]"))
4232 unlockvar obj.o1[0]
4233 assert_equal(0, islocked("obj.o1"))
4234 assert_equal(0, islocked("obj.o1[0]"))
4235
4236 # Same thing, but with a static
4237
4238 try
4239 lockvar C.c1 # can't lock something you can't write to
4240 call assert_false(1, '"lockvar C.c1" should have failed')
4241 catch
4242 call assert_exception('E1335:')
4243 endtry
4244
4245 LockIt(C.c1) # but can lock it's value
4246 assert_equal(1, islocked("C.c1"))
4247 assert_equal(1, islocked("C.c1[0]"))
4248 assert_equal(1, islocked("C.c1[1]"))
4249 UnlockIt(C.c1)
4250 assert_equal(0, islocked("C.c1"))
4251 assert_equal(0, islocked("C.c1[0]"))
4252
4253 lockvar C.c1[0]
4254 assert_equal(0, islocked("C.c1"))
4255 assert_equal(1, islocked("C.c1[0]"))
4256 assert_equal(0, islocked("C.c1[1]"))
4257 unlockvar C.c1[0]
4258 assert_equal(0, islocked("C.c1"))
4259 assert_equal(0, islocked("C.c1[0]"))
4260 END
4261 v9.CheckSourceSuccess(lines)
4262 lines =<< trim END
4263 END
4264enddef
4265
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004266" Test for a private object method
4267def Test_private_object_method()
4268 # Try calling a private method using an object (at the script level)
4269 var lines =<< trim END
4270 vim9script
4271
4272 class A
4273 def _Foo(): number
4274 return 1234
4275 enddef
4276 endclass
4277 var a = A.new()
4278 a._Foo()
4279 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02004280 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004281
4282 # Try calling a private method using an object (from a def function)
4283 lines =<< trim END
4284 vim9script
4285
4286 class A
4287 def _Foo(): number
4288 return 1234
4289 enddef
4290 endclass
4291 def T()
4292 var a = A.new()
4293 a._Foo()
4294 enddef
4295 T()
4296 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004297 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004298
4299 # Use a private method from another object method (in script context)
4300 lines =<< trim END
4301 vim9script
4302
4303 class A
4304 def _Foo(): number
4305 return 1234
4306 enddef
4307 def Bar(): number
4308 return this._Foo()
4309 enddef
4310 endclass
4311 var a = A.new()
4312 assert_equal(1234, a.Bar())
4313 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004314 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004315
4316 # Use a private method from another object method (def function context)
4317 lines =<< trim END
4318 vim9script
4319
4320 class A
4321 def _Foo(): number
4322 return 1234
4323 enddef
4324 def Bar(): number
4325 return this._Foo()
4326 enddef
4327 endclass
4328 def T()
4329 var a = A.new()
4330 assert_equal(1234, a.Bar())
4331 enddef
4332 T()
4333 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004334 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004335
4336 # Try calling a private method without the "this" prefix
4337 lines =<< trim END
4338 vim9script
4339
4340 class A
4341 def _Foo(): number
4342 return 1234
4343 enddef
4344 def Bar(): number
4345 return _Foo()
4346 enddef
4347 endclass
4348 var a = A.new()
4349 a.Bar()
4350 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004351 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004352
4353 # Try calling a private method using the class name
4354 lines =<< trim END
4355 vim9script
4356
4357 class A
4358 def _Foo(): number
4359 return 1234
4360 enddef
4361 endclass
4362 A._Foo()
4363 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004364 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004365
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004366 # Define two private methods with the same name
4367 lines =<< trim END
4368 vim9script
4369
4370 class A
4371 def _Foo()
4372 enddef
4373 def _Foo()
4374 enddef
4375 endclass
4376 var a = A.new()
4377 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004378 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004379
4380 # Define a private method and a object method with the same name
4381 lines =<< trim END
4382 vim9script
4383
4384 class A
4385 def _Foo()
4386 enddef
4387 def Foo()
4388 enddef
4389 endclass
4390 var a = A.new()
4391 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004392 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004393
4394 # Define an object method and a private method with the same name
4395 lines =<< trim END
4396 vim9script
4397
4398 class A
4399 def Foo()
4400 enddef
4401 def _Foo()
4402 enddef
4403 endclass
4404 var a = A.new()
4405 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004406 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004407
4408 # Call a public method and a private method from a private method
4409 lines =<< trim END
4410 vim9script
4411
4412 class A
4413 def Foo(): number
4414 return 100
4415 enddef
4416 def _Bar(): number
4417 return 200
4418 enddef
4419 def _Baz()
4420 assert_equal(100, this.Foo())
4421 assert_equal(200, this._Bar())
4422 enddef
4423 def T()
4424 this._Baz()
4425 enddef
4426 endclass
4427 var a = A.new()
4428 a.T()
4429 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004430 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004431
4432 # Try calling a private method from another class
4433 lines =<< trim END
4434 vim9script
4435
4436 class A
4437 def _Foo(): number
4438 return 100
4439 enddef
4440 endclass
4441 class B
4442 def Foo(): number
4443 var a = A.new()
4444 a._Foo()
4445 enddef
4446 endclass
4447 var b = B.new()
4448 b.Foo()
4449 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004450 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004451
4452 # Call a private object method from a child class object method
4453 lines =<< trim END
4454 vim9script
4455 class A
4456 def _Foo(): number
4457 return 1234
4458 enddef
4459 endclass
4460 class B extends A
4461 def Bar()
4462 enddef
4463 endclass
4464 class C extends B
4465 def Baz(): number
4466 return this._Foo()
4467 enddef
4468 endclass
4469 var c = C.new()
4470 assert_equal(1234, c.Baz())
4471 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004472 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004473
4474 # Call a private object method from a child class object
4475 lines =<< trim END
4476 vim9script
4477 class A
4478 def _Foo(): number
4479 return 1234
4480 enddef
4481 endclass
4482 class B extends A
4483 def Bar()
4484 enddef
4485 endclass
4486 class C extends B
4487 def Baz(): number
4488 enddef
4489 endclass
4490 var c = C.new()
4491 assert_equal(1234, c._Foo())
4492 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02004493 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004494
4495 # Using "_" prefix in a method name should fail outside of a class
4496 lines =<< trim END
4497 vim9script
4498 def _Foo(): number
4499 return 1234
4500 enddef
4501 var a = _Foo()
4502 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004503 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004504enddef
4505
4506" Test for an private class method
4507def Test_private_class_method()
4508 # Try calling a class private method (at the script level)
4509 var lines =<< trim END
4510 vim9script
4511
4512 class A
4513 static def _Foo(): number
4514 return 1234
4515 enddef
4516 endclass
4517 A._Foo()
4518 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02004519 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004520
4521 # Try calling a class private method (from a def function)
4522 lines =<< trim END
4523 vim9script
4524
4525 class A
4526 static def _Foo(): number
4527 return 1234
4528 enddef
4529 endclass
4530 def T()
4531 A._Foo()
4532 enddef
4533 T()
4534 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004535 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004536
4537 # Try calling a class private method using an object (at the script level)
4538 lines =<< trim END
4539 vim9script
4540
4541 class A
4542 static def _Foo(): number
4543 return 1234
4544 enddef
4545 endclass
4546 var a = A.new()
4547 a._Foo()
4548 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004549 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004550
4551 # Try calling a class private method using an object (from a def function)
4552 lines =<< trim END
4553 vim9script
4554
4555 class A
4556 static def _Foo(): number
4557 return 1234
4558 enddef
4559 endclass
4560 def T()
4561 var a = A.new()
4562 a._Foo()
4563 enddef
4564 T()
4565 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004566 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004567
4568 # Use a class private method from an object method
4569 lines =<< trim END
4570 vim9script
4571
4572 class A
4573 static def _Foo(): number
4574 return 1234
4575 enddef
4576 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004577 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004578 enddef
4579 endclass
4580 var a = A.new()
4581 a.Bar()
4582 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004583 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004584
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004585 # Use a class private method from another class private method without the
4586 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004587 lines =<< trim END
4588 vim9script
4589
4590 class A
4591 static def _Foo1(): number
4592 return 1234
4593 enddef
4594 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004595 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004596 enddef
4597 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02004598 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004599 enddef
4600 endclass
4601 var a = A.new()
4602 a.Bar()
4603 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004604 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004605
4606 # Declare a class method and a class private method with the same name
4607 lines =<< trim END
4608 vim9script
4609
4610 class A
4611 static def _Foo()
4612 enddef
4613 static def Foo()
4614 enddef
4615 endclass
4616 var a = A.new()
4617 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004618 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004619
4620 # Try calling a class private method from another class
4621 lines =<< trim END
4622 vim9script
4623
4624 class A
4625 static def _Foo(): number
4626 return 1234
4627 enddef
4628 endclass
4629 class B
4630 def Foo(): number
4631 return A._Foo()
4632 enddef
4633 endclass
4634 var b = B.new()
4635 assert_equal(1234, b.Foo())
4636 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004637 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004638
4639 # Call a private class method from a child class object method
4640 lines =<< trim END
4641 vim9script
4642 class A
4643 static def _Foo(): number
4644 return 1234
4645 enddef
4646 endclass
4647 class B extends A
4648 def Bar()
4649 enddef
4650 endclass
4651 class C extends B
4652 def Baz(): number
4653 return A._Foo()
4654 enddef
4655 endclass
4656 var c = C.new()
4657 assert_equal(1234, c.Baz())
4658 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004659 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004660
4661 # Call a private class method from a child class private class method
4662 lines =<< trim END
4663 vim9script
4664 class A
4665 static def _Foo(): number
4666 return 1234
4667 enddef
4668 endclass
4669 class B extends A
4670 def Bar()
4671 enddef
4672 endclass
4673 class C extends B
4674 static def Baz(): number
4675 return A._Foo()
4676 enddef
4677 endclass
4678 assert_equal(1234, C.Baz())
4679 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004680 v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004681
4682 # Call a private class method from a child class object
4683 lines =<< trim END
4684 vim9script
4685 class A
4686 static def _Foo(): number
4687 return 1234
4688 enddef
4689 endclass
4690 class B extends A
4691 def Bar()
4692 enddef
4693 endclass
4694 class C extends B
4695 def Baz(): number
4696 enddef
4697 endclass
4698 var c = C.new()
4699 assert_equal(1234, C._Foo())
4700 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004701 v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02004702enddef
4703
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004704" Test for using the return value of a class/object method as a function
4705" argument.
4706def Test_objmethod_funcarg()
4707 var lines =<< trim END
4708 vim9script
4709
4710 class C
4711 def Foo(): string
4712 return 'foo'
4713 enddef
4714 endclass
4715
4716 def Bar(a: number, s: string): string
4717 return s
4718 enddef
4719
4720 def Baz(c: C)
4721 assert_equal('foo', Bar(10, c.Foo()))
4722 enddef
4723
4724 var t = C.new()
4725 Baz(t)
4726 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004727 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004728
4729 lines =<< trim END
4730 vim9script
4731
4732 class C
4733 static def Foo(): string
4734 return 'foo'
4735 enddef
4736 endclass
4737
4738 def Bar(a: number, s: string): string
4739 return s
4740 enddef
4741
4742 def Baz()
4743 assert_equal('foo', Bar(10, C.Foo()))
4744 enddef
4745
4746 Baz()
4747 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004748 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02004749enddef
4750
Ernie Raelcf138d42023-09-06 20:45:03 +02004751def Test_static_inheritence()
4752 # subclasses get their own static copy
4753 var lines =<< trim END
4754 vim9script
4755
4756 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004757 static _svar: number
4758 this._mvar: number
4759 def new()
4760 _svar = 1
4761 this._mvar = 101
4762 enddef
4763 def AccessObject(): number
4764 return this._mvar
4765 enddef
4766 def AccessStaticThroughObject(): number
4767 return _svar
4768 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02004769 endclass
4770
4771 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004772 def new()
4773 this._mvar = 102
4774 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02004775 endclass
4776
4777 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004778 def new()
4779 this._mvar = 103
4780 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02004781
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004782 def AccessPrivateStaticThroughClassName(): number
4783 assert_equal(1, A._svar)
4784 return 444
4785 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02004786 endclass
4787
4788 var oa = A.new()
4789 var ob = B.new()
4790 var oc = C.new()
4791 assert_equal(101, oa.AccessObject())
4792 assert_equal(102, ob.AccessObject())
4793 assert_equal(103, oc.AccessObject())
4794
Ernie Rael64885642023-10-04 20:16:22 +02004795 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02004796
4797 # verify object properly resolves to correct static
4798 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004799 assert_equal(1, ob.AccessStaticThroughObject())
4800 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02004801 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004802 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02004803enddef
4804
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004805" Test for declaring duplicate object and class members
4806def Test_dup_member_variable()
4807 # Duplicate member variable
4808 var lines =<< trim END
4809 vim9script
4810 class C
4811 this.val = 10
4812 this.val = 20
4813 endclass
4814 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004815 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004816
4817 # Duplicate private member variable
4818 lines =<< trim END
4819 vim9script
4820 class C
4821 this._val = 10
4822 this._val = 20
4823 endclass
4824 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004825 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004826
4827 # Duplicate public member variable
4828 lines =<< trim END
4829 vim9script
4830 class C
4831 public this.val = 10
4832 public this.val = 20
4833 endclass
4834 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004835 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004836
4837 # Duplicate private member variable
4838 lines =<< trim END
4839 vim9script
4840 class C
4841 this.val = 10
4842 this._val = 20
4843 endclass
4844 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004845 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004846
4847 # Duplicate public and private member variable
4848 lines =<< trim END
4849 vim9script
4850 class C
4851 this._val = 20
4852 public this.val = 10
4853 endclass
4854 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004855 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004856
4857 # Duplicate class member variable
4858 lines =<< trim END
4859 vim9script
4860 class C
4861 static s: string = "abc"
4862 static _s: string = "def"
4863 endclass
4864 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004865 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004866
4867 # Duplicate public and private class member variable
4868 lines =<< trim END
4869 vim9script
4870 class C
4871 public static s: string = "abc"
4872 static _s: string = "def"
4873 endclass
4874 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004875 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004876
4877 # Duplicate class and object member variable
4878 lines =<< trim END
4879 vim9script
4880 class C
4881 static val = 10
4882 this.val = 20
4883 def new()
4884 enddef
4885 endclass
4886 var c = C.new()
4887 assert_equal(10, C.val)
4888 assert_equal(20, c.val)
4889 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02004890 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004891
4892 # Duplicate object member variable in a derived class
4893 lines =<< trim END
4894 vim9script
4895 class A
4896 this.val = 10
4897 endclass
4898 class B extends A
4899 endclass
4900 class C extends B
4901 this.val = 20
4902 endclass
4903 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004904 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004905
4906 # Duplicate object private member variable in a derived class
4907 lines =<< trim END
4908 vim9script
4909 class A
4910 this._val = 10
4911 endclass
4912 class B extends A
4913 endclass
4914 class C extends B
4915 this._val = 20
4916 endclass
4917 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004918 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004919
4920 # Duplicate object private member variable in a derived class
4921 lines =<< trim END
4922 vim9script
4923 class A
4924 this.val = 10
4925 endclass
4926 class B extends A
4927 endclass
4928 class C extends B
4929 this._val = 20
4930 endclass
4931 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004932 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004933
4934 # Duplicate object member variable in a derived class
4935 lines =<< trim END
4936 vim9script
4937 class A
4938 this._val = 10
4939 endclass
4940 class B extends A
4941 endclass
4942 class C extends B
4943 this.val = 20
4944 endclass
4945 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004946 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02004947
4948 # Two member variables with a common prefix
4949 lines =<< trim END
4950 vim9script
4951 class A
4952 public static svar2: number
4953 public static svar: number
4954 endclass
4955 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004956 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02004957enddef
4958
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004959" Test for accessing a private member outside a class in a def function
4960def Test_private_member_access_outside_class()
4961 # private object member variable
4962 var lines =<< trim END
4963 vim9script
4964 class A
4965 this._val = 10
4966 def GetVal(): number
4967 return this._val
4968 enddef
4969 endclass
4970 def T()
4971 var a = A.new()
4972 a._val = 20
4973 enddef
4974 T()
4975 END
Ernie Rael64885642023-10-04 20:16:22 +02004976 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004977
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004978 # access a non-existing private object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004979 lines =<< trim END
4980 vim9script
4981 class A
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004982 this._val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004983 endclass
4984 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02004985 var a = A.new()
4986 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02004987 enddef
4988 T()
4989 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004990 v9.CheckSourceFailure(lines, 'E1326: Variable not found on object "A": _a', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02004991
4992 # private static member variable
4993 lines =<< trim END
4994 vim9script
4995 class A
4996 static _val = 10
4997 endclass
4998 def T()
4999 var a = A.new()
5000 var x = a._val
5001 enddef
5002 T()
5003 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005004 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005005
5006 # private static member variable
5007 lines =<< trim END
5008 vim9script
5009 class A
5010 static _val = 10
5011 endclass
5012 def T()
5013 var a = A.new()
5014 a._val = 3
5015 enddef
5016 T()
5017 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005018 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005019
5020 # private static class variable
5021 lines =<< trim END
5022 vim9script
5023 class A
5024 static _val = 10
5025 endclass
5026 def T()
5027 var x = A._val
5028 enddef
5029 T()
5030 END
Ernie Rael64885642023-10-04 20:16:22 +02005031 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02005032
5033 # private static class variable
5034 lines =<< trim END
5035 vim9script
5036 class A
5037 static _val = 10
5038 endclass
5039 def T()
5040 A._val = 3
5041 enddef
5042 T()
5043 END
Ernie Rael64885642023-10-04 20:16:22 +02005044 v9.CheckSourceFailure(lines, 'E1333: Cannot access private variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005045enddef
5046
5047" Test for changing the member access of an interface in a implementation class
5048def Test_change_interface_member_access()
5049 var lines =<< trim END
5050 vim9script
5051 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005052 this.val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005053 endinterface
5054 class B implements A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005055 public this.val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005056 endclass
5057 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005058 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005059
5060 lines =<< trim END
5061 vim9script
5062 interface A
5063 this.val: number
5064 endinterface
5065 class B implements A
5066 public this.val = 10
5067 endclass
5068 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005069 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005070enddef
5071
5072" Test for trying to change a readonly member from a def function
5073def Test_readonly_member_change_in_def_func()
5074 var lines =<< trim END
5075 vim9script
5076 class A
5077 this.val: number
5078 endclass
5079 def T()
5080 var a = A.new()
5081 a.val = 20
5082 enddef
5083 T()
5084 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005085 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005086enddef
5087
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005088" Test for reading and writing a class member from a def function
5089def Test_modify_class_member_from_def_function()
5090 var lines =<< trim END
5091 vim9script
5092 class A
5093 this.var1: number = 10
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02005094 public static var2: list<number> = [1, 2]
5095 public static var3: dict<number> = {a: 1, b: 2}
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005096 static _priv_var4: number = 40
5097 endclass
5098 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02005099 assert_equal([1, 2], A.var2)
5100 assert_equal({a: 1, b: 2}, A.var3)
5101 A.var2 = [3, 4]
5102 A.var3 = {c: 3, d: 4}
5103 assert_equal([3, 4], A.var2)
5104 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael64885642023-10-04 20:16:22 +02005105 assert_fails('echo A._priv_var4', 'E1333: Cannot access private variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005106 enddef
5107 T()
5108 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005109 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005110enddef
5111
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005112" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005113def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005114 var lines =<< trim END
5115 vim9script
5116 class A
5117 public static svar1: list<number> = [1]
5118 public static svar2: list<number> = [2]
5119 endclass
5120
5121 A.svar1->add(3)
5122 A.svar2->add(4)
5123 assert_equal([1, 3], A.svar1)
5124 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005125
5126 def Foo()
5127 A.svar1->add(7)
5128 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005129 assert_equal([1, 3, 7], A.svar1)
5130 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005131 enddef
5132 Foo()
5133 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005134 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005135
5136 # Cannot read from a class variable using an object in script context
5137 lines =<< trim END
5138 vim9script
5139 class A
5140 public this.var1: number
5141 public static svar2: list<number> = [1]
5142 endclass
5143
5144 var a = A.new()
5145 echo a.svar2
5146 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02005147 v9.CheckSourceFailure(lines, 'E1337: Class variable "svar2" not found in class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005148
5149 # Cannot write to a class variable using an object in script context
5150 lines =<< trim END
5151 vim9script
5152 class A
5153 public this.var1: number
5154 public static svar2: list<number> = [1]
5155 endclass
5156
5157 var a = A.new()
5158 a.svar2 = [2]
5159 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005160 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005161
5162 # Cannot read from a class variable using an object in def method context
5163 lines =<< trim END
5164 vim9script
5165 class A
5166 public this.var1: number
5167 public static svar2: list<number> = [1]
5168 endclass
5169
5170 def T()
5171 var a = A.new()
5172 echo a.svar2
5173 enddef
5174 T()
5175 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005176 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005177
5178 # Cannot write to a class variable using an object in def method context
5179 lines =<< trim END
5180 vim9script
5181 class A
5182 public this.var1: number
5183 public static svar2: list<number> = [1]
5184 endclass
5185
5186 def T()
5187 var a = A.new()
5188 a.svar2 = [2]
5189 enddef
5190 T()
5191 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005192 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005193enddef
5194
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02005195" Test for using a interface method using a child object
5196def Test_interface_method_from_child()
5197 var lines =<< trim END
5198 vim9script
5199
5200 interface A
5201 def Foo(): string
5202 endinterface
5203
5204 class B implements A
5205 def Foo(): string
5206 return 'foo'
5207 enddef
5208 endclass
5209
5210 class C extends B
5211 def Bar(): string
5212 return 'bar'
5213 enddef
5214 endclass
5215
5216 def T1(a: A)
5217 assert_equal('foo', a.Foo())
5218 enddef
5219
5220 def T2(b: B)
5221 assert_equal('foo', b.Foo())
5222 enddef
5223
5224 var c = C.new()
5225 T1(c)
5226 T2(c)
5227 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005228 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02005229enddef
5230
5231" Test for using an interface method using a child object when it is overridden
5232" by the child class.
5233" FIXME: This test fails.
5234" def Test_interface_overridden_method_from_child()
5235" var lines =<< trim END
5236" vim9script
5237"
5238" interface A
5239" def Foo(): string
5240" endinterface
5241"
5242" class B implements A
5243" def Foo(): string
5244" return 'b-foo'
5245" enddef
5246" endclass
5247"
5248" class C extends B
5249" def Bar(): string
5250" return 'bar'
5251" enddef
5252" def Foo(): string
5253" return 'c-foo'
5254" enddef
5255" endclass
5256"
5257" def T1(a: A)
5258" assert_equal('c-foo', a.Foo())
5259" enddef
5260"
5261" def T2(b: B)
5262" assert_equal('c-foo', b.Foo())
5263" enddef
5264"
5265" var c = C.new()
5266" T1(c)
5267" T2(c)
5268" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005269" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02005270" enddef
5271
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005272" Test for abstract methods
5273def Test_abstract_method()
5274 # Use two abstract methods
5275 var lines =<< trim END
5276 vim9script
5277 abstract class A
5278 def M1(): number
5279 return 10
5280 enddef
5281 abstract def M2(): number
5282 abstract def M3(): number
5283 endclass
5284 class B extends A
5285 def M2(): number
5286 return 20
5287 enddef
5288 def M3(): number
5289 return 30
5290 enddef
5291 endclass
5292 var b = B.new()
5293 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
5294 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005295 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005296
5297 # Don't define an abstract method
5298 lines =<< trim END
5299 vim9script
5300 abstract class A
5301 abstract def Foo()
5302 endclass
5303 class B extends A
5304 endclass
5305 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005306 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005307
5308 # Use abstract method in a concrete class
5309 lines =<< trim END
5310 vim9script
5311 class A
5312 abstract def Foo()
5313 endclass
5314 class B extends A
5315 endclass
5316 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005317 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005318
5319 # Use abstract method in an interface
5320 lines =<< trim END
5321 vim9script
5322 interface A
5323 abstract def Foo()
5324 endinterface
5325 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005326 def Foo()
5327 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005328 endclass
5329 END
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005330 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005331
5332 # Abbreviate the "abstract" keyword
5333 lines =<< trim END
5334 vim9script
5335 class A
5336 abs def Foo()
5337 endclass
5338 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005339 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005340
5341 # Use "abstract" with a member variable
5342 lines =<< trim END
5343 vim9script
5344 abstract class A
5345 abstract this.val = 10
5346 endclass
5347 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005348 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005349
5350 # Use a static abstract method
5351 lines =<< trim END
5352 vim9script
5353 abstract class A
5354 abstract static def Foo(): number
5355 endclass
5356 class B extends A
5357 static def Foo(): number
5358 return 4
5359 enddef
5360 endclass
5361 assert_equal(4, B.Foo())
5362 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005363 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005364
5365 # Type mismatch between abstract method and concrete method
5366 lines =<< trim END
5367 vim9script
5368 abstract class A
5369 abstract def Foo(a: string, b: number): list<number>
5370 endclass
5371 class B extends A
5372 def Foo(a: number, b: string): list<string>
5373 return []
5374 enddef
5375 endclass
5376 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005377 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 +02005378
5379 # Use an abstract class to invoke an abstract method
5380 # FIXME: This should fail
5381 lines =<< trim END
5382 vim9script
5383 abstract class A
5384 abstract static def Foo()
5385 endclass
5386 A.Foo()
5387 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005388 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005389
5390 # Invoke an abstract method from a def function
5391 lines =<< trim END
5392 vim9script
5393 abstract class A
5394 abstract def Foo(): list<number>
5395 endclass
5396 class B extends A
5397 def Foo(): list<number>
5398 return [3, 5]
5399 enddef
5400 endclass
5401 def Bar(c: B)
5402 assert_equal([3, 5], c.Foo())
5403 enddef
5404 var b = B.new()
5405 Bar(b)
5406 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005407 v9.CheckSourceSuccess(lines)
5408enddef
5409
5410" Test for calling a class method from a subclass
5411def Test_class_method_call_from_subclass()
5412 # class method call from a subclass
5413 var lines =<< trim END
5414 vim9script
5415
5416 class A
5417 static def Foo()
5418 echo "foo"
5419 enddef
5420 endclass
5421
5422 class B extends A
5423 def Bar()
5424 Foo()
5425 enddef
5426 endclass
5427
5428 var b = B.new()
5429 b.Bar()
5430 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005431 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02005432enddef
5433
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005434" Test for calling a class method using an object in a def function context and
5435" script context.
5436def Test_class_method_call_using_object()
5437 # script context
5438 var lines =<< trim END
5439 vim9script
5440 class A
5441 static def Foo(): list<string>
5442 return ['a', 'b']
5443 enddef
5444 def Bar()
5445 assert_equal(['a', 'b'], A.Foo())
5446 assert_equal(['a', 'b'], Foo())
5447 enddef
5448 endclass
5449
5450 def T()
5451 assert_equal(['a', 'b'], A.Foo())
5452 var t_a = A.new()
5453 t_a.Bar()
5454 enddef
5455
5456 assert_equal(['a', 'b'], A.Foo())
5457 var a = A.new()
5458 a.Bar()
5459 T()
5460 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005461 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005462
5463 # script context
5464 lines =<< trim END
5465 vim9script
5466 class A
5467 static def Foo(): string
5468 return 'foo'
5469 enddef
5470 endclass
5471
5472 var a = A.new()
5473 assert_equal('foo', a.Foo())
5474 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005475 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005476
5477 # def function context
5478 lines =<< trim END
5479 vim9script
5480 class A
5481 static def Foo(): string
5482 return 'foo'
5483 enddef
5484 endclass
5485
5486 def T()
5487 var a = A.new()
5488 assert_equal('foo', a.Foo())
5489 enddef
5490 T()
5491 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005492 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005493enddef
5494
5495def Test_class_variable()
5496 var lines =<< trim END
5497 vim9script
5498
5499 class A
5500 public static val: number = 10
5501 static def ClassFunc()
5502 assert_equal(10, val)
5503 enddef
5504 def ObjFunc()
5505 assert_equal(10, val)
5506 enddef
5507 endclass
5508
5509 class B extends A
5510 endclass
5511
5512 assert_equal(10, A.val)
5513 A.ClassFunc()
5514 var a = A.new()
5515 a.ObjFunc()
5516 var b = B.new()
5517 b.ObjFunc()
5518
5519 def T1(a1: A)
5520 a1.ObjFunc()
5521 A.ClassFunc()
5522 enddef
5523 T1(b)
5524
5525 A.val = 20
5526 assert_equal(20, A.val)
5527 END
5528 v9.CheckSourceSuccess(lines)
5529
5530 # Modifying a parent class variable from a child class method
5531 lines =<< trim END
5532 vim9script
5533
5534 class A
5535 static val: number = 10
5536 endclass
5537
5538 class B extends A
5539 static def ClassFunc()
5540 val = 20
5541 enddef
5542 endclass
5543 B.ClassFunc()
5544 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005545 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005546
5547 # Reading a parent class variable from a child class method
5548 lines =<< trim END
5549 vim9script
5550
5551 class A
5552 static val: number = 10
5553 endclass
5554
5555 class B extends A
5556 static def ClassFunc()
5557 var i = val
5558 enddef
5559 endclass
5560 B.ClassFunc()
5561 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005562 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005563
5564 # Modifying a parent class variable from a child object method
5565 lines =<< trim END
5566 vim9script
5567
5568 class A
5569 static val: number = 10
5570 endclass
5571
5572 class B extends A
5573 def ObjFunc()
5574 val = 20
5575 enddef
5576 endclass
5577 var b = B.new()
5578 b.ObjFunc()
5579 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005580 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005581
5582 # Reading a parent class variable from a child object method
5583 lines =<< trim END
5584 vim9script
5585
5586 class A
5587 static val: number = 10
5588 endclass
5589
5590 class B extends A
5591 def ObjFunc()
5592 var i = val
5593 enddef
5594 endclass
5595 var b = B.new()
5596 b.ObjFunc()
5597 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005598 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005599
5600 # Modifying a class variable using an object at script level
5601 lines =<< trim END
5602 vim9script
5603
5604 class A
5605 static val: number = 10
5606 endclass
5607 var a = A.new()
5608 a.val = 20
5609 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005610 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005611
5612 # Reading a class variable using an object at script level
5613 lines =<< trim END
5614 vim9script
5615
5616 class A
5617 static val: number = 10
5618 endclass
5619 var a = A.new()
5620 var i = a.val
5621 END
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02005622 v9.CheckSourceFailure(lines, 'E1337: Class variable "val" not found in class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005623
5624 # Modifying a class variable using an object at function level
5625 lines =<< trim END
5626 vim9script
5627
5628 class A
5629 static val: number = 10
5630 endclass
5631
5632 def T()
5633 var a = A.new()
5634 a.val = 20
5635 enddef
5636 T()
5637 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005638 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005639
5640 # Reading a class variable using an object at function level
5641 lines =<< trim END
5642 vim9script
5643
5644 class A
5645 static val: number = 10
5646 endclass
5647 def T()
5648 var a = A.new()
5649 var i = a.val
5650 enddef
5651 T()
5652 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005653 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005654enddef
5655
5656" Test for using a duplicate class method and class variable in a child class
5657def Test_dup_class_member()
5658 # duplicate class variable, class method and overridden object method
5659 var lines =<< trim END
5660 vim9script
5661 class A
5662 static sval = 100
5663 static def Check()
5664 assert_equal(100, sval)
5665 enddef
5666 def GetVal(): number
5667 return sval
5668 enddef
5669 endclass
5670
5671 class B extends A
5672 static sval = 200
5673 static def Check()
5674 assert_equal(200, sval)
5675 enddef
5676 def GetVal(): number
5677 return sval
5678 enddef
5679 endclass
5680
5681 def T1(aa: A): number
5682 return aa.GetVal()
5683 enddef
5684
5685 def T2(bb: B): number
5686 return bb.GetVal()
5687 enddef
5688
5689 assert_equal(100, A.sval)
5690 assert_equal(200, B.sval)
5691 var a = A.new()
5692 assert_equal(100, a.GetVal())
5693 var b = B.new()
5694 assert_equal(200, b.GetVal())
5695 assert_equal(200, T1(b))
5696 assert_equal(200, T2(b))
5697 END
5698 v9.CheckSourceSuccess(lines)
5699
5700 # duplicate class variable and class method
5701 lines =<< trim END
5702 vim9script
5703 class A
5704 static sval = 100
5705 static def Check()
5706 assert_equal(100, sval)
5707 enddef
5708 def GetVal(): number
5709 return sval
5710 enddef
5711 endclass
5712
5713 class B extends A
5714 static sval = 200
5715 static def Check()
5716 assert_equal(200, sval)
5717 enddef
5718 endclass
5719
5720 def T1(aa: A): number
5721 return aa.GetVal()
5722 enddef
5723
5724 def T2(bb: B): number
5725 return bb.GetVal()
5726 enddef
5727
5728 assert_equal(100, A.sval)
5729 assert_equal(200, B.sval)
5730 var a = A.new()
5731 assert_equal(100, a.GetVal())
5732 var b = B.new()
5733 assert_equal(100, b.GetVal())
5734 assert_equal(100, T1(b))
5735 assert_equal(100, T2(b))
5736 END
5737 v9.CheckSourceSuccess(lines)
5738enddef
5739
5740" Test for calling an instance method using the class
5741def Test_instance_method_call_using_class()
5742 # Invoke an object method using a class in script context
5743 var lines =<< trim END
5744 vim9script
5745 class A
5746 def Foo()
5747 echo "foo"
5748 enddef
5749 endclass
5750 A.Foo()
5751 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005752 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005753
5754 # Invoke an object method using a class in def function context
5755 lines =<< trim END
5756 vim9script
5757 class A
5758 def Foo()
5759 echo "foo"
5760 enddef
5761 endclass
5762 def T()
5763 A.Foo()
5764 enddef
5765 T()
5766 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005767 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005768enddef
5769
5770" Test for duplicate class method and instance method
5771def Test_dup_classmethod_objmethod()
5772 # Duplicate instance method
5773 var lines =<< trim END
5774 vim9script
5775 class A
5776 static def Foo()
5777 enddef
5778 def Foo()
5779 enddef
5780 endclass
5781 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005782 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005783
5784 # Duplicate private instance method
5785 lines =<< trim END
5786 vim9script
5787 class A
5788 static def Foo()
5789 enddef
5790 def _Foo()
5791 enddef
5792 endclass
5793 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005794 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005795
5796 # Duplicate class method
5797 lines =<< trim END
5798 vim9script
5799 class A
5800 def Foo()
5801 enddef
5802 static def Foo()
5803 enddef
5804 endclass
5805 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005806 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005807
5808 # Duplicate private class method
5809 lines =<< trim END
5810 vim9script
5811 class A
5812 def Foo()
5813 enddef
5814 static def _Foo()
5815 enddef
5816 endclass
5817 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005818 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005819
5820 # Duplicate private class and object method
5821 lines =<< trim END
5822 vim9script
5823 class A
5824 def _Foo()
5825 enddef
5826 static def _Foo()
5827 enddef
5828 endclass
5829 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005830 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005831enddef
5832
5833" Test for an instance method access level comparison with parent instance
5834" methods.
5835def Test_instance_method_access_level()
5836 # Private method in subclass
5837 var lines =<< trim END
5838 vim9script
5839 class A
5840 def Foo()
5841 enddef
5842 endclass
5843 class B extends A
5844 endclass
5845 class C extends B
5846 def _Foo()
5847 enddef
5848 endclass
5849 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005850 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005851
5852 # Public method in subclass
5853 lines =<< trim END
5854 vim9script
5855 class A
5856 def _Foo()
5857 enddef
5858 endclass
5859 class B extends A
5860 endclass
5861 class C extends B
5862 def Foo()
5863 enddef
5864 endclass
5865 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005866 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005867enddef
5868
5869def Test_extend_empty_class()
5870 var lines =<< trim END
5871 vim9script
5872 class A
5873 endclass
5874 class B extends A
5875 endclass
5876 class C extends B
5877 public static rw_class_var = 1
5878 public this.rw_obj_var = 2
5879 static def ClassMethod(): number
5880 return 3
5881 enddef
5882 def ObjMethod(): number
5883 return 4
5884 enddef
5885 endclass
5886 assert_equal(1, C.rw_class_var)
5887 assert_equal(3, C.ClassMethod())
5888 var c = C.new()
5889 assert_equal(2, c.rw_obj_var)
5890 assert_equal(4, c.ObjMethod())
5891 END
5892 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02005893enddef
5894
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005895" A interface cannot have a static variable or a static method or a private
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005896" variable or a private method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005897def Test_interface_with_unsupported_members()
5898 var lines =<< trim END
5899 vim9script
5900 interface A
5901 static num: number
5902 endinterface
5903 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005904 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005905
5906 lines =<< trim END
5907 vim9script
5908 interface A
5909 static _num: number
5910 endinterface
5911 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005912 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005913
5914 lines =<< trim END
5915 vim9script
5916 interface A
5917 public static num: number
5918 endinterface
5919 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005920 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005921
5922 lines =<< trim END
5923 vim9script
5924 interface A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005925 public static num: number
5926 endinterface
5927 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005928 v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005929
5930 lines =<< trim END
5931 vim9script
5932 interface A
5933 static _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005934 endinterface
5935 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005936 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005937
5938 lines =<< trim END
5939 vim9script
5940 interface A
5941 static def Foo(d: dict<any>): list<string>
5942 endinterface
5943 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005944 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005945
5946 lines =<< trim END
5947 vim9script
5948 interface A
5949 static def _Foo(d: dict<any>): list<string>
5950 endinterface
5951 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005952 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005953
5954 lines =<< trim END
5955 vim9script
5956 interface A
5957 this._Foo: list<string>
5958 endinterface
5959 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005960 v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005961
5962 lines =<< trim END
5963 vim9script
5964 interface A
5965 def _Foo(d: dict<any>): list<string>
5966 endinterface
5967 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005968 v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005969enddef
5970
5971" Test for extending an interface
5972def Test_extend_interface()
5973 var lines =<< trim END
5974 vim9script
5975 interface A
5976 this.var1: list<string>
5977 def Foo()
5978 endinterface
5979 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005980 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005981 def Bar()
5982 endinterface
5983 class C implements A, B
5984 this.var1 = [1, 2]
5985 def Foo()
5986 enddef
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02005987 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02005988 def Bar()
5989 enddef
5990 endclass
5991 END
5992 v9.CheckSourceSuccess(lines)
5993
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02005994 # extending empty interface
5995 lines =<< trim END
5996 vim9script
5997 interface A
5998 endinterface
5999 interface B extends A
6000 endinterface
6001 class C implements B
6002 endclass
6003 END
6004 v9.CheckSourceSuccess(lines)
6005
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006006 lines =<< trim END
6007 vim9script
6008 interface A
6009 def Foo()
6010 endinterface
6011 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006012 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006013 endinterface
6014 class C implements A, B
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006015 this.var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006016 endclass
6017 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006018 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006019
6020 lines =<< trim END
6021 vim9script
6022 interface A
6023 def Foo()
6024 endinterface
6025 interface B extends A
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006026 this.var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006027 endinterface
6028 class C implements A, B
6029 def Foo()
6030 enddef
6031 endclass
6032 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006033 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006034
6035 # interface cannot extend a class
6036 lines =<< trim END
6037 vim9script
6038 class A
6039 endclass
6040 interface B extends A
6041 endinterface
6042 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006043 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006044
6045 # class cannot extend an interface
6046 lines =<< trim END
6047 vim9script
6048 interface A
6049 endinterface
6050 class B extends A
6051 endclass
6052 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006053 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006054
6055 # interface cannot implement another interface
6056 lines =<< trim END
6057 vim9script
6058 interface A
6059 endinterface
6060 interface B implements A
6061 endinterface
6062 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006063 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006064
6065 # interface cannot extend multiple interfaces
6066 lines =<< trim END
6067 vim9script
6068 interface A
6069 endinterface
6070 interface B
6071 endinterface
6072 interface C extends A, B
6073 endinterface
6074 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006075 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006076
6077 # Variable type in an extended interface is of different type
6078 lines =<< trim END
6079 vim9script
6080 interface A
6081 this.val1: number
6082 endinterface
6083 interface B extends A
6084 this.val2: string
6085 endinterface
6086 interface C extends B
6087 this.val1: string
6088 this.val2: number
6089 endinterface
6090 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006091 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006092enddef
6093
6094" Test for a child class implementing an interface when some of the methods are
6095" defined in the parent class.
6096def Test_child_class_implements_interface()
6097 var lines =<< trim END
6098 vim9script
6099
6100 interface Intf
6101 def F1(): list<list<number>>
6102 def F2(): list<list<number>>
6103 def F3(): list<list<number>>
6104 this.var1: list<dict<number>>
6105 this.var2: list<dict<number>>
6106 this.var3: list<dict<number>>
6107 endinterface
6108
6109 class A
6110 def A1()
6111 enddef
6112 def F3(): list<list<number>>
6113 return [[3]]
6114 enddef
6115 this.v1: list<list<number>> = [[0]]
6116 this.var3 = [{c: 30}]
6117 endclass
6118
6119 class B extends A
6120 def B1()
6121 enddef
6122 def F2(): list<list<number>>
6123 return [[2]]
6124 enddef
6125 this.v2: list<list<number>> = [[0]]
6126 this.var2 = [{b: 20}]
6127 endclass
6128
6129 class C extends B implements Intf
6130 def C1()
6131 enddef
6132 def F1(): list<list<number>>
6133 return [[1]]
6134 enddef
6135 this.v3: list<list<number>> = [[0]]
6136 this.var1 = [{a: 10}]
6137 endclass
6138
6139 def T(if: Intf)
6140 assert_equal([[1]], if.F1())
6141 assert_equal([[2]], if.F2())
6142 assert_equal([[3]], if.F3())
6143 assert_equal([{a: 10}], if.var1)
6144 assert_equal([{b: 20}], if.var2)
6145 assert_equal([{c: 30}], if.var3)
6146 enddef
6147
6148 var c = C.new()
6149 T(c)
6150 assert_equal([[1]], c.F1())
6151 assert_equal([[2]], c.F2())
6152 assert_equal([[3]], c.F3())
6153 assert_equal([{a: 10}], c.var1)
6154 assert_equal([{b: 20}], c.var2)
6155 assert_equal([{c: 30}], c.var3)
6156 END
6157 v9.CheckSourceSuccess(lines)
6158
6159 # One of the interface methods is not found
6160 lines =<< trim END
6161 vim9script
6162
6163 interface Intf
6164 def F1()
6165 def F2()
6166 def F3()
6167 endinterface
6168
6169 class A
6170 def A1()
6171 enddef
6172 endclass
6173
6174 class B extends A
6175 def B1()
6176 enddef
6177 def F2()
6178 enddef
6179 endclass
6180
6181 class C extends B implements Intf
6182 def C1()
6183 enddef
6184 def F1()
6185 enddef
6186 endclass
6187 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006188 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006189
6190 # One of the interface methods is of different type
6191 lines =<< trim END
6192 vim9script
6193
6194 interface Intf
6195 def F1()
6196 def F2()
6197 def F3()
6198 endinterface
6199
6200 class A
6201 def F3(): number
6202 return 0
6203 enddef
6204 def A1()
6205 enddef
6206 endclass
6207
6208 class B extends A
6209 def B1()
6210 enddef
6211 def F2()
6212 enddef
6213 endclass
6214
6215 class C extends B implements Intf
6216 def C1()
6217 enddef
6218 def F1()
6219 enddef
6220 endclass
6221 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006222 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006223
6224 # One of the interface variables is not present
6225 lines =<< trim END
6226 vim9script
6227
6228 interface Intf
6229 this.var1: list<dict<number>>
6230 this.var2: list<dict<number>>
6231 this.var3: list<dict<number>>
6232 endinterface
6233
6234 class A
6235 this.v1: list<list<number>> = [[0]]
6236 endclass
6237
6238 class B extends A
6239 this.v2: list<list<number>> = [[0]]
6240 this.var2 = [{b: 20}]
6241 endclass
6242
6243 class C extends B implements Intf
6244 this.v3: list<list<number>> = [[0]]
6245 this.var1 = [{a: 10}]
6246 endclass
6247 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006248 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006249
6250 # One of the interface variables is of different type
6251 lines =<< trim END
6252 vim9script
6253
6254 interface Intf
6255 this.var1: list<dict<number>>
6256 this.var2: list<dict<number>>
6257 this.var3: list<dict<number>>
6258 endinterface
6259
6260 class A
6261 this.v1: list<list<number>> = [[0]]
6262 this.var3: list<dict<string>>
6263 endclass
6264
6265 class B extends A
6266 this.v2: list<list<number>> = [[0]]
6267 this.var2 = [{b: 20}]
6268 endclass
6269
6270 class C extends B implements Intf
6271 this.v3: list<list<number>> = [[0]]
6272 this.var1 = [{a: 10}]
6273 endclass
6274 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006275 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 +02006276enddef
6277
6278" Test for extending an interface with duplicate variables and methods
6279def Test_interface_extends_with_dup_members()
6280 var lines =<< trim END
6281 vim9script
6282 interface A
6283 this.n1: number
6284 def Foo1(): number
6285 endinterface
6286 interface B extends A
6287 this.n2: number
6288 this.n1: number
6289 def Foo2(): number
6290 def Foo1(): number
6291 endinterface
6292 class C implements B
6293 this.n1 = 10
6294 this.n2 = 20
6295 def Foo1(): number
6296 return 30
6297 enddef
6298 def Foo2(): number
6299 return 40
6300 enddef
6301 endclass
6302 def T1(a: A)
6303 assert_equal(10, a.n1)
6304 assert_equal(30, a.Foo1())
6305 enddef
6306 def T2(b: B)
6307 assert_equal(10, b.n1)
6308 assert_equal(20, b.n2)
6309 assert_equal(30, b.Foo1())
6310 assert_equal(40, b.Foo2())
6311 enddef
6312 var c = C.new()
6313 T1(c)
6314 T2(c)
6315 END
6316 v9.CheckSourceSuccess(lines)
6317enddef
6318
6319" Test for using "any" type for a variable in a sub-class while it has a
6320" concrete type in the interface
6321def Test_implements_using_var_type_any()
6322 var lines =<< trim END
6323 vim9script
6324 interface A
6325 this.val: list<dict<string>>
6326 endinterface
6327 class B implements A
6328 this.val = [{a: '1'}, {b: '2'}]
6329 endclass
6330 var b = B.new()
6331 assert_equal([{a: '1'}, {b: '2'}], b.val)
6332 END
6333 v9.CheckSourceSuccess(lines)
6334
6335 # initialize instance variable using a different type
6336 lines =<< trim END
6337 vim9script
6338 interface A
6339 this.val: list<dict<string>>
6340 endinterface
6341 class B implements A
6342 this.val = {a: 1, b: 2}
6343 endclass
6344 var b = B.new()
6345 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006346 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006347enddef
6348
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006349" Test for assigning to a member variable in a nested class
6350def Test_nested_object_assignment()
6351 var lines =<< trim END
6352 vim9script
6353
6354 class A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006355 this.value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006356 endclass
6357
6358 class B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006359 this.a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006360 endclass
6361
6362 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006363 this.b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006364 endclass
6365
6366 class D
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006367 this.c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006368 endclass
6369
6370 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006371 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006372 enddef
6373
6374 var d = D.new()
6375 T(d)
6376 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006377 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02006378enddef
6379
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02006380" Test for calling methods using a null object
6381def Test_null_object_method_call()
6382 # Calling a object method using a null object in script context
6383 var lines =<< trim END
6384 vim9script
6385
6386 class C
6387 def Foo()
6388 assert_report('This method should not be executed')
6389 enddef
6390 endclass
6391
6392 var o: C
6393 o.Foo()
6394 END
6395 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
6396
6397 # Calling a object method using a null object in def function context
6398 lines =<< trim END
6399 vim9script
6400
6401 class C
6402 def Foo()
6403 assert_report('This method should not be executed')
6404 enddef
6405 endclass
6406
6407 def T()
6408 var o: C
6409 o.Foo()
6410 enddef
6411 T()
6412 END
6413 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6414
6415 # Calling a object method through another class method using a null object in
6416 # script context
6417 lines =<< trim END
6418 vim9script
6419
6420 class C
6421 def Foo()
6422 assert_report('This method should not be executed')
6423 enddef
6424
6425 static def Bar(o_any: any)
6426 var o_typed: C = o_any
6427 o_typed.Foo()
6428 enddef
6429 endclass
6430
6431 var o: C
6432 C.Bar(o)
6433 END
6434 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6435
6436 # Calling a object method through another class method using a null object in
6437 # def function context
6438 lines =<< trim END
6439 vim9script
6440
6441 class C
6442 def Foo()
6443 assert_report('This method should not be executed')
6444 enddef
6445
6446 static def Bar(o_any: any)
6447 var o_typed: C = o_any
6448 o_typed.Foo()
6449 enddef
6450 endclass
6451
6452 def T()
6453 var o: C
6454 C.Bar(o)
6455 enddef
6456 T()
6457 END
6458 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
6459enddef
6460
6461" Test for using a dict as an object member
6462def Test_dict_object_member()
6463 var lines =<< trim END
6464 vim9script
6465
6466 class Context
6467 public this.state: dict<number> = {}
6468 def GetState(): dict<number>
6469 return this.state
6470 enddef
6471 endclass
6472
6473 var ctx = Context.new()
6474 ctx.state->extend({a: 1})
6475 ctx.state['b'] = 2
6476 assert_equal({a: 1, b: 2}, ctx.GetState())
6477
6478 def F()
6479 ctx.state['c'] = 3
6480 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
6481 enddef
6482 F()
6483 assert_equal(3, ctx.state.c)
6484 ctx.state.c = 4
6485 assert_equal(4, ctx.state.c)
6486 END
6487 v9.CheckSourceSuccess(lines)
6488enddef
6489
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02006490" The following test was failing after 9.0.1914. This was caused by using a
6491" freed object from a previous method call.
6492def Test_freed_object_from_previous_method_call()
6493 var lines =<< trim END
6494 vim9script
6495
6496 class Context
6497 endclass
6498
6499 class Result
6500 endclass
6501
6502 def Failure(): Result
6503 return Result.new()
6504 enddef
6505
6506 def GetResult(ctx: Context): Result
6507 return Failure()
6508 enddef
6509
6510 def Test_GetResult()
6511 var ctx = Context.new()
6512 var result = GetResult(ctx)
6513 enddef
6514
6515 Test_GetResult()
6516 END
6517 v9.CheckSourceSuccess(lines)
6518enddef
6519
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02006520" Test for duplicate object and class variable
6521def Test_duplicate_variable()
6522 # Object variable name is same as the class variable name
6523 var lines =<< trim END
6524 vim9script
6525 class A
6526 public static sval: number
6527 public this.sval: number
6528 endclass
6529 var a = A.new()
6530 END
6531 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6532
6533 # Duplicate variable name and calling a class method
6534 lines =<< trim END
6535 vim9script
6536 class A
6537 public static sval: number
6538 public this.sval: number
6539 def F1()
6540 echo this.sval
6541 enddef
6542 static def F2()
6543 echo sval
6544 enddef
6545 endclass
6546 A.F2()
6547 END
6548 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6549
6550 # Duplicate variable with an empty constructor
6551 lines =<< trim END
6552 vim9script
6553 class A
6554 public static sval: number
6555 public this.sval: number
6556 def new()
6557 enddef
6558 endclass
6559 var a = A.new()
6560 END
6561 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
6562enddef
6563
6564" Test for using a reserved keyword as a variable name
6565def Test_reserved_varname()
6566 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
6567 'null_function', 'null_list', 'null_partial', 'null_string',
6568 'null_channel', 'null_job', 'super', 'this']
6569
6570 var lines =<< trim eval END
6571 vim9script
6572 class C
6573 public this.{kword}: list<number> = [1, 2, 3]
6574 endclass
6575 var o = C.new()
6576 END
6577 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6578
6579 lines =<< trim eval END
6580 vim9script
6581 class C
6582 public this.{kword}: list<number> = [1, 2, 3]
6583 def new()
6584 enddef
6585 endclass
6586 var o = C.new()
6587 END
6588 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6589
6590 lines =<< trim eval END
6591 vim9script
6592 class C
6593 public this.{kword}: list<number> = [1, 2, 3]
6594 def new()
6595 enddef
6596 def F()
6597 echo this.{kword}
6598 enddef
6599 endclass
6600 var o = C.new()
6601 o.F()
6602 END
6603 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02006604
6605 # class variable name
6606 if kword != 'this'
6607 lines =<< trim eval END
6608 vim9script
6609 class C
6610 public static {kword}: list<number> = [1, 2, 3]
6611 endclass
6612 END
6613 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
6614 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02006615 endfor
6616enddef
6617
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006618" Test for checking the type of the arguments and the return value of a object
6619" method in an extended class.
6620def Test_extended_obj_method_type_check()
6621 var lines =<< trim END
6622 vim9script
6623
6624 class A
6625 endclass
6626 class B extends A
6627 endclass
6628 class C extends B
6629 endclass
6630
6631 class Foo
6632 def Doit(p: B): B
6633 return B.new()
6634 enddef
6635 endclass
6636
6637 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006638 def Doit(p: C): B
6639 return B.new()
6640 enddef
6641 endclass
6642 END
6643 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
6644
6645 lines =<< trim END
6646 vim9script
6647
6648 class A
6649 endclass
6650 class B extends A
6651 endclass
6652 class C extends B
6653 endclass
6654
6655 class Foo
6656 def Doit(p: B): B
6657 return B.new()
6658 enddef
6659 endclass
6660
6661 class Bar extends Foo
6662 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006663 return C.new()
6664 enddef
6665 endclass
6666 END
6667 v9.CheckSourceSuccess(lines)
6668
6669 lines =<< trim END
6670 vim9script
6671
6672 class A
6673 endclass
6674 class B extends A
6675 endclass
6676 class C extends B
6677 endclass
6678
6679 class Foo
6680 def Doit(p: B): B
6681 return B.new()
6682 enddef
6683 endclass
6684
6685 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006686 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02006687 return B.new()
6688 enddef
6689 endclass
6690 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02006691 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 +02006692
6693 lines =<< trim END
6694 vim9script
6695
6696 class A
6697 endclass
6698 class B extends A
6699 endclass
6700 class C extends B
6701 endclass
6702
6703 class Foo
6704 def Doit(p: B): B
6705 return B.new()
6706 enddef
6707 endclass
6708
6709 class Bar extends Foo
6710 def Doit(p: B): A
6711 return A.new()
6712 enddef
6713 endclass
6714 END
6715 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<B>): object<A>', 20)
6716enddef
6717
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006718" Test type checking for class variable in assignments
6719func Test_class_variable_complex_type_check()
6720 " class variable with a specific type. Try assigning a different type at
6721 " script level.
6722 let lines =<< trim END
6723 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006724 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006725 return {}
6726 enddef
6727 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006728 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006729 endclass
6730 test_garbagecollect_now()
6731 A.Fn = "abc"
6732 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006733 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 +02006734
6735 " class variable with a specific type. Try assigning a different type at
6736 " class def method level.
6737 let lines =<< trim END
6738 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006739 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006740 return {}
6741 enddef
6742 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006743 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006744 def Bar()
6745 Fn = "abc"
6746 enddef
6747 endclass
6748 var a = A.new()
6749 test_garbagecollect_now()
6750 a.Bar()
6751 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006752 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 +02006753
6754 " class variable with a specific type. Try assigning a different type at
6755 " script def method level.
6756 let lines =<< trim END
6757 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006758 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006759 return {}
6760 enddef
6761 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006762 public static Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006763 endclass
6764 def Bar()
6765 A.Fn = "abc"
6766 enddef
6767 test_garbagecollect_now()
6768 Bar()
6769 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006770 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 +02006771
6772 " class variable without any type. Should be set to the initialization
6773 " expression type. Try assigning a different type from script level.
6774 let lines =<< trim END
6775 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006776 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006777 return {}
6778 enddef
6779 class A
6780 public static Fn = Foo
6781 endclass
6782 test_garbagecollect_now()
6783 A.Fn = "abc"
6784 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006785 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 +02006786
6787 " class variable without any type. Should be set to the initialization
6788 " expression type. Try assigning a different type at class def level.
6789 let lines =<< trim END
6790 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006791 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006792 return {}
6793 enddef
6794 class A
6795 public static Fn = Foo
6796 def Bar()
6797 Fn = "abc"
6798 enddef
6799 endclass
6800 var a = A.new()
6801 test_garbagecollect_now()
6802 a.Bar()
6803 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006804 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 +02006805
6806 " class variable without any type. Should be set to the initialization
6807 " expression type. Try assigning a different type at script def level.
6808 let lines =<< trim END
6809 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006810 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006811 return {}
6812 enddef
6813 class A
6814 public static Fn = Foo
6815 endclass
6816 def Bar()
6817 A.Fn = "abc"
6818 enddef
6819 test_garbagecollect_now()
6820 Bar()
6821 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006822 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 +02006823
6824 " class variable with 'any" type. Can be assigned different types.
6825 let lines =<< trim END
6826 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006827 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006828 return {}
6829 enddef
6830 class A
6831 public static Fn: any = Foo
6832 public static Fn2: any
6833 endclass
6834 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006835 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006836 A.Fn = "abc"
6837 test_garbagecollect_now()
6838 assert_equal('string', typename(A.Fn))
6839 A.Fn2 = Foo
6840 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006841 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006842 A.Fn2 = "xyz"
6843 test_garbagecollect_now()
6844 assert_equal('string', typename(A.Fn2))
6845 END
6846 call v9.CheckSourceSuccess(lines)
6847
6848 " class variable with 'any" type. Can be assigned different types.
6849 let lines =<< trim END
6850 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006851 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006852 return {}
6853 enddef
6854 class A
6855 public static Fn: any = Foo
6856 public static Fn2: any
6857
6858 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006859 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006860 Fn = "abc"
6861 assert_equal('string', typename(Fn))
6862 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006863 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006864 Fn2 = "xyz"
6865 assert_equal('string', typename(Fn2))
6866 enddef
6867 endclass
6868 var a = A.new()
6869 test_garbagecollect_now()
6870 a.Bar()
6871 test_garbagecollect_now()
6872 A.Fn = Foo
6873 a.Bar()
6874 END
6875 call v9.CheckSourceSuccess(lines)
6876
6877 " class variable with 'any" type. Can be assigned different types.
6878 let lines =<< trim END
6879 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006880 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006881 return {}
6882 enddef
6883 class A
6884 public static Fn: any = Foo
6885 public static Fn2: any
6886 endclass
6887
6888 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006889 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006890 A.Fn = "abc"
6891 assert_equal('string', typename(A.Fn))
6892 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006893 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006894 A.Fn2 = "xyz"
6895 assert_equal('string', typename(A.Fn2))
6896 enddef
6897 Bar()
6898 test_garbagecollect_now()
6899 A.Fn = Foo
6900 Bar()
6901 END
6902 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006903
6904 let lines =<< trim END
6905 vim9script
6906 class A
6907 public static foo = [0z10, 0z20]
6908 endclass
6909 assert_equal([0z10, 0z20], A.foo)
6910 A.foo = [0z30]
6911 assert_equal([0z30], A.foo)
6912 var a = A.foo
6913 assert_equal([0z30], a)
6914 END
6915 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006916endfunc
6917
6918" Test type checking for object variable in assignments
6919func Test_object_variable_complex_type_check()
6920 " object variable with a specific type. Try assigning a different type at
6921 " script level.
6922 let lines =<< trim END
6923 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006924 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006925 return {}
6926 enddef
6927 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006928 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006929 endclass
6930 var a = A.new()
6931 test_garbagecollect_now()
6932 a.Fn = "abc"
6933 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006934 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 +02006935
6936 " object variable with a specific type. Try assigning a different type at
6937 " object def method level.
6938 let lines =<< trim END
6939 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006940 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006941 return {}
6942 enddef
6943 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006944 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006945 def Bar()
6946 this.Fn = "abc"
6947 this.Fn = Foo
6948 enddef
6949 endclass
6950 var a = A.new()
6951 test_garbagecollect_now()
6952 a.Bar()
6953 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006954 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 +02006955
6956 " object variable with a specific type. Try assigning a different type at
6957 " script def method level.
6958 let lines =<< trim END
6959 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006960 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006961 return {}
6962 enddef
6963 class A
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006964 public this.Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006965 endclass
6966 def Bar()
6967 var a = A.new()
6968 a.Fn = "abc"
6969 a.Fn = Foo
6970 enddef
6971 test_garbagecollect_now()
6972 Bar()
6973 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006974 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 +02006975
6976 " object variable without any type. Should be set to the initialization
6977 " expression type. Try assigning a different type from script level.
6978 let lines =<< trim END
6979 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006980 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006981 return {}
6982 enddef
6983 class A
6984 public this.Fn = Foo
6985 endclass
6986 var a = A.new()
6987 test_garbagecollect_now()
6988 a.Fn = "abc"
6989 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006990 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 +02006991
6992 " object variable without any type. Should be set to the initialization
6993 " expression type. Try assigning a different type at object def level.
6994 let lines =<< trim END
6995 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02006996 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02006997 return {}
6998 enddef
6999 class A
7000 public this.Fn = Foo
7001 def Bar()
7002 this.Fn = "abc"
7003 this.Fn = Foo
7004 enddef
7005 endclass
7006 var a = A.new()
7007 test_garbagecollect_now()
7008 a.Bar()
7009 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007010 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 +02007011
7012 " object variable without any type. Should be set to the initialization
7013 " expression type. Try assigning a different type at script def level.
7014 let lines =<< trim END
7015 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007016 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007017 return {}
7018 enddef
7019 class A
7020 public this.Fn = Foo
7021 endclass
7022 def Bar()
7023 var a = A.new()
7024 a.Fn = "abc"
7025 a.Fn = Foo
7026 enddef
7027 test_garbagecollect_now()
7028 Bar()
7029 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007030 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 +02007031
7032 " object variable with 'any" type. Can be assigned different types.
7033 let lines =<< trim END
7034 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007035 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007036 return {}
7037 enddef
7038 class A
7039 public this.Fn: any = Foo
7040 public this.Fn2: any
7041 endclass
7042
7043 var a = A.new()
7044 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007045 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007046 a.Fn = "abc"
7047 test_garbagecollect_now()
7048 assert_equal('string', typename(a.Fn))
7049 a.Fn2 = Foo
7050 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007051 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007052 a.Fn2 = "xyz"
7053 test_garbagecollect_now()
7054 assert_equal('string', typename(a.Fn2))
7055 END
7056 call v9.CheckSourceSuccess(lines)
7057
7058 " object variable with 'any" type. Can be assigned different types.
7059 let lines =<< trim END
7060 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007061 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007062 return {}
7063 enddef
7064 class A
7065 public this.Fn: any = Foo
7066 public this.Fn2: any
7067
7068 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007069 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007070 this.Fn = "abc"
7071 assert_equal('string', typename(this.Fn))
7072 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007073 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007074 this.Fn2 = "xyz"
7075 assert_equal('string', typename(this.Fn2))
7076 enddef
7077 endclass
7078
7079 var a = A.new()
7080 test_garbagecollect_now()
7081 a.Bar()
7082 test_garbagecollect_now()
7083 a.Fn = Foo
7084 a.Bar()
7085 END
7086 call v9.CheckSourceSuccess(lines)
7087
7088 " object variable with 'any" type. Can be assigned different types.
7089 let lines =<< trim END
7090 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007091 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007092 return {}
7093 enddef
7094 class A
7095 public this.Fn: any = Foo
7096 public this.Fn2: any
7097 endclass
7098
7099 def Bar()
7100 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007101 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007102 a.Fn = "abc"
7103 assert_equal('string', typename(a.Fn))
7104 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007105 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007106 a.Fn2 = "xyz"
7107 assert_equal('string', typename(a.Fn2))
7108 enddef
7109 test_garbagecollect_now()
7110 Bar()
7111 test_garbagecollect_now()
7112 Bar()
7113 END
7114 call v9.CheckSourceSuccess(lines)
7115endfunc
7116
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02007117" Test for recursively calling an object method. This used to cause an
7118" use-after-free error.
7119def Test_recursive_object_method_call()
7120 var lines =<< trim END
7121 vim9script
7122 class A
7123 this.val: number = 0
7124 def Foo(): number
7125 if this.val >= 90
7126 return this.val
7127 endif
7128 this.val += 1
7129 return this.Foo()
7130 enddef
7131 endclass
7132 var a = A.new()
7133 assert_equal(90, a.Foo())
7134 END
7135 v9.CheckSourceSuccess(lines)
7136enddef
7137
7138" Test for recursively calling a class method.
7139def Test_recursive_class_method_call()
7140 var lines =<< trim END
7141 vim9script
7142 class A
7143 static val: number = 0
7144 static def Foo(): number
7145 if val >= 90
7146 return val
7147 endif
7148 val += 1
7149 return Foo()
7150 enddef
7151 endclass
7152 assert_equal(90, A.Foo())
7153 END
7154 v9.CheckSourceSuccess(lines)
7155enddef
7156
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02007157" Test for checking the argument types and the return type when assigning a
7158" funcref to make sure the invariant class type is used.
7159def Test_funcref_argtype_returntype_check()
7160 var lines =<< trim END
7161 vim9script
7162 class A
7163 endclass
7164 class B extends A
7165 endclass
7166
7167 def Foo(p: B): B
7168 return B.new()
7169 enddef
7170
7171 var Bar: func(A): A = Foo
7172 END
7173 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
7174
7175 lines =<< trim END
7176 vim9script
7177 class A
7178 endclass
7179 class B extends A
7180 endclass
7181
7182 def Foo(p: B): B
7183 return B.new()
7184 enddef
7185
7186 def Baz()
7187 var Bar: func(A): A = Foo
7188 enddef
7189 Baz()
7190 END
7191 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
7192enddef
7193
Bram Moolenaar00b28d62022-12-08 15:32:33 +00007194" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker