blob: c6d93b2b70d4876dfc7875b4a9e7188871a2d639 [file] [log] [blame]
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001" Test Vim9 classes
2
3source check.vim
4import './vim9.vim' as v9
5
6def Test_class_basic()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007 # Class supported only in "vim9script"
Bram Moolenaar00b28d62022-12-08 15:32:33 +00008 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02009 class NotWorking
10 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000011 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020012 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000013
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020014 # First character in a class name should be capitalized.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000015 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020016 vim9script
17 class notWorking
18 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000019 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020020 v9.CheckSourceFailure(lines, 'E1314: Class name must start with an uppercase letter: notWorking', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000021
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020022 # Only alphanumeric characters are supported in a class name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000023 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020024 vim9script
25 class Not@working
26 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000027 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020028 v9.CheckSourceFailure(lines, 'E1315: White space required after name: Not@working', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000029
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020030 # Unsupported keyword (instead of class)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000031 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020032 vim9script
33 abstract noclass Something
34 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000035 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020036 v9.CheckSourceFailure(lines, 'E475: Invalid argument: noclass Something', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000037
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +010038 # Only the complete word "class" should be recognized
Bram Moolenaar00b28d62022-12-08 15:32:33 +000039 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020040 vim9script
41 abstract classy Something
42 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000043 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020044 v9.CheckSourceFailure(lines, 'E475: Invalid argument: classy Something', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000045
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020046 # The complete "endclass" should be specified.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000047 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020048 vim9script
49 class Something
50 endcl
Bram Moolenaar00b28d62022-12-08 15:32:33 +000051 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020052 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endcl', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000053
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020054 # Additional words after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000055 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020056 vim9script
57 class Something
58 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000059 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020060 v9.CheckSourceFailure(lines, "E488: Trailing characters: school's out", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000061
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020062 # Additional commands after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000063 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020064 vim9script
65 class Something
66 endclass | echo 'done'
Bram Moolenaar00b28d62022-12-08 15:32:33 +000067 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020068 v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000069
Yegappan Lakshmananac773182024-04-27 11:36:12 +020070 # Additional command after "class name"
71 lines =<< trim END
72 vim9script
73 class Something | var x = 10
74 endclass
75 END
76 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
77
78 # Additional command after "object variable"
79 lines =<< trim END
80 vim9script
81 class Something
82 var l: list<number> = [] | var y = 10
83 endclass
84 END
85 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
86
87 # Additional command after "class variable"
88 lines =<< trim END
89 vim9script
90 class Something
91 static var d = {a: 10} | var y = 10
92 endclass
93 END
94 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
95
96 # Additional command after "object method"
97 lines =<< trim END
98 vim9script
99 class Something
100 def Foo() | var y = 10
101 enddef
102 endclass
103 END
104 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
105
Yegappan Lakshmananfe55c312024-04-28 09:54:09 +0200106 # Comments are allowed after an inline block
107 lines =<< trim END
108 vim9script
109 class Foo
110 static const bar = { # {{{
111 baz: 'qux'
112 } # }}}
113 endclass
114 assert_equal({baz: 'qux'}, Foo.bar)
115 END
116 v9.CheckSourceSuccess(lines)
117
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +0100118 # Try to define a class with the same name as an existing variable
119 lines =<< trim END
120 vim9script
121 var Something: list<number> = [1]
122 class Thing
123 endclass
124 interface Api
125 endinterface
126 class Something extends Thing implements Api
127 var v1: string = ''
128 def Foo()
129 enddef
130 endclass
131 END
132 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 7)
133
zeertzjqe7102202024-02-13 20:32:04 +0100134 # Use old "this." prefixed member variable declaration syntax (without initialization)
Doug Kearns74da0ee2023-12-14 20:26:26 +0100135 lines =<< trim END
136 vim9script
137 class Something
138 this.count: number
139 endclass
140 END
141 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number', 3)
142
zeertzjqe7102202024-02-13 20:32:04 +0100143 # Use old "this." prefixed member variable declaration syntax (with initialization)
Doug Kearns74da0ee2023-12-14 20:26:26 +0100144 lines =<< trim END
145 vim9script
146 class Something
147 this.count: number = 42
148 endclass
149 END
150 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number = 42', 3)
151
152 # Use old "this." prefixed member variable declaration syntax (type inferred)
153 lines =<< trim END
154 vim9script
155 class Something
156 this.count = 42
157 endclass
158 END
159 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count = 42', 3)
160
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200161 # Use "this" without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000162 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200163 vim9script
164 class Something
165 this
166 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000167 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100168 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000169
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200170 # Use "this." without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000171 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200172 vim9script
173 class Something
174 this.
175 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000176 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100177 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000178
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200179 # Space between "this" and ".<variable>"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000180 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200181 vim9script
182 class Something
183 this .count
184 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000185 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100186 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this .count', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000187
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200188 # Space between "this." and the member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000189 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200190 vim9script
191 class Something
192 this. count
193 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000194 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100195 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this. count', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000196
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200197 # Use "that" instead of "this"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000198 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200199 vim9script
200 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100201 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200202 that.count
203 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000204 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200205 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count', 4)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000206
Doug Kearns74da0ee2023-12-14 20:26:26 +0100207 # Use "variable" instead of "var" for member variable declaration (without initialization)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000208 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200209 vim9script
210 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100211 variable count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200212 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000213 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100214 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count: number', 3)
215
216 # Use "variable" instead of "var" for member variable declaration (with initialization)
217 lines =<< trim END
218 vim9script
219 class Something
220 variable count: number = 42
221 endclass
222 END
223 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count: number = 42', 3)
224
225 # Use "variable" instead of "var" for member variable declaration (type inferred)
226 lines =<< trim END
227 vim9script
228 class Something
229 variable count = 42
230 endclass
231 END
232 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count = 42', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000233
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200234 # Use a non-existing member variable in new()
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000235 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200236 vim9script
237 class Something
238 def new()
239 this.state = 0
240 enddef
241 endclass
242 var obj = Something.new()
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000243 END
Ernie Raeld4802ec2023-10-20 11:59:00 +0200244 v9.CheckSourceFailure(lines, 'E1326: Variable "state" not found in object "Something"', 1)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000245
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200246 # Space before ":" in a member variable declaration
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000247 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200248 vim9script
249 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100250 var count : number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200251 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000252 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200253 v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: count : number', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000254
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200255 # No space after ":" in a member variable declaration
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000256 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200257 vim9script
258 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100259 var count:number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200260 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000261 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200262 v9.CheckSourceFailure(lines, "E1069: White space required after ':'", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000263
Doug Kearns74da0ee2023-12-14 20:26:26 +0100264 # Missing ":var" in a "var" member variable declaration (without initialization)
265 lines =<< trim END
266 vim9script
267 class Something
268 var: number
269 endclass
270 END
271 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var: number', 3)
272
273 # Missing ":var" in a "var" member variable declaration (with initialization)
274 lines =<< trim END
275 vim9script
276 class Something
277 var: number = 42
278 endclass
279 END
280 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var: number = 42', 3)
281
282 # Missing ":var" in a "var" member variable declaration (type inferred)
283 lines =<< trim END
284 vim9script
285 class Something
286 var = 42
287 endclass
288 END
289 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var = 42', 3)
290
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200291 # Test for unsupported comment specifier
292 lines =<< trim END
293 vim9script
294 class Something
295 # comment
296 #{
297 endclass
298 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200299 v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200300
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200301 # Test for using class as a bool
302 lines =<< trim END
303 vim9script
304 class A
305 endclass
306 if A
307 endif
308 END
Ernie Raele75fde62023-12-21 17:18:54 +0100309 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200310
311 # Test for using object as a bool
312 lines =<< trim END
313 vim9script
314 class A
315 endclass
316 var a = A.new()
317 if a
318 endif
319 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200320 v9.CheckSourceFailure(lines, 'E1320: Using an Object as a Number', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200321
322 # Test for using class as a float
323 lines =<< trim END
324 vim9script
325 class A
326 endclass
327 sort([1.1, A], 'f')
328 END
Ernie Raelfa831102023-12-14 20:06:39 +0100329 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200330
331 # Test for using object as a float
332 lines =<< trim END
333 vim9script
334 class A
335 endclass
336 var a = A.new()
337 sort([1.1, a], 'f')
338 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200339 v9.CheckSourceFailure(lines, 'E1322: Using an Object as a Float', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200340
341 # Test for using class as a string
342 lines =<< trim END
343 vim9script
344 class A
345 endclass
346 :exe 'call ' .. A
347 END
Ernie Raele75fde62023-12-21 17:18:54 +0100348 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200349
350 # Test for using object as a string
351 lines =<< trim END
352 vim9script
353 class A
354 endclass
355 var a = A.new()
356 :exe 'call ' .. a
357 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200358 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200359
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200360 # Test creating a class with member variables and methods, calling a object
361 # method. Check for using type() and typename() with a class and an object.
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000362 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200363 vim9script
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000364
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200365 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100366 var lnum: number
367 var col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000368
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200369 # make a nicely formatted string
370 def ToString(): string
371 return $'({this.lnum}, {this.col})'
372 enddef
373 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000374
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200375 # use the automatically generated new() method
376 var pos = TextPosition.new(2, 12)
377 assert_equal(2, pos.lnum)
378 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000379
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200380 # call an object method
381 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000382
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200383 assert_equal(v:t_class, type(TextPosition))
384 assert_equal(v:t_object, type(pos))
385 assert_equal('class<TextPosition>', typename(TextPosition))
386 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000387 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200388 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200389
390 # When referencing object methods, space cannot be used after a "."
391 lines =<< trim END
392 vim9script
393 class A
394 def Foo(): number
395 return 10
396 enddef
397 endclass
398 var a = A.new()
399 var v = a. Foo()
400 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200401 v9.CheckSourceFailure(lines, "E1202: No white space allowed after '.'", 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200402
403 # Using an object without specifying a method or a member variable
404 lines =<< trim END
405 vim9script
406 class A
407 def Foo(): number
408 return 10
409 enddef
410 endclass
411 var a = A.new()
412 var v = a.
413 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200414 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a."', 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200415
416 # Error when parsing the arguments of an object method.
417 lines =<< trim END
418 vim9script
419 class A
420 def Foo()
421 enddef
422 endclass
423 var a = A.new()
424 var v = a.Foo(,)
425 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200426 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a.Foo(,)"', 7)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200427
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200428 # Use a multi-line initialization for a member variable
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200429 lines =<< trim END
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200430 vim9script
431 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +0100432 var y = {
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200433 X: 1
434 }
435 endclass
436 var a = A.new()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200437 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200438 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000439enddef
440
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200441" Tests for object/class methods in a class
442def Test_class_def_method()
443 # Using the "public" keyword when defining an object method
444 var lines =<< trim END
445 vim9script
446 class A
447 public def Foo()
448 enddef
449 endclass
450 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200451 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200452
453 # Using the "public" keyword when defining a class method
454 lines =<< trim END
455 vim9script
456 class A
457 public static def Foo()
458 enddef
459 endclass
460 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200461 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200462
Ernie Rael03042a22023-11-11 08:53:32 +0100463 # Using the "public" keyword when defining an object protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200464 lines =<< trim END
465 vim9script
466 class A
467 public def _Foo()
468 enddef
469 endclass
470 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200471 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200472
Ernie Rael03042a22023-11-11 08:53:32 +0100473 # Using the "public" keyword when defining a class protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200474 lines =<< trim END
475 vim9script
476 class A
477 public static def _Foo()
478 enddef
479 endclass
480 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200481 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200482
483 # Using a "def" keyword without an object method name
484 lines =<< trim END
485 vim9script
486 class A
487 def
488 enddef
489 endclass
490 END
491 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: def', 3)
492
493 # Using a "def" keyword without a class method name
494 lines =<< trim END
495 vim9script
496 class A
497 static def
498 enddef
499 endclass
500 END
501 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: static def', 3)
502enddef
503
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000504def Test_class_defined_twice()
505 # class defined twice should fail
506 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200507 vim9script
508 class There
509 endclass
510 class There
511 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000512 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200513 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"', 4)
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000514
515 # one class, reload same script twice is OK
516 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200517 vim9script
518 class There
519 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000520 END
521 writefile(lines, 'XclassTwice.vim', 'D')
522 source XclassTwice.vim
523 source XclassTwice.vim
524enddef
525
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000526def Test_returning_null_object()
527 # this was causing an internal error
528 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200529 vim9script
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000530
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200531 class BufferList
532 def Current(): any
533 return null_object
534 enddef
535 endclass
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000536
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200537 var buffers = BufferList.new()
538 echo buffers.Current()
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000539 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200540 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000541enddef
542
Bram Moolenaard13dd302023-03-11 20:56:35 +0000543def Test_using_null_class()
544 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200545 @_ = null_class.member
Bram Moolenaard13dd302023-03-11 20:56:35 +0000546 END
Yegappan Lakshmanan778ada42025-02-17 20:21:23 +0100547 v9.CheckDefExecAndScriptFailure(lines, ['E1395: Using a null class', 'E1363: Incomplete type'])
Yegappan Lakshmananb2e42b92024-05-01 11:44:17 +0200548
549 # Test for using a null class as a value
550 lines =<< trim END
551 vim9script
552 echo empty(null_class)
553 END
554 v9.CheckSourceFailure(lines, 'E1405: Class "" cannot be used as a value', 2)
555
556 # Test for using a null class with string()
557 lines =<< trim END
558 vim9script
559 assert_equal('class [unknown]', string(null_class))
560 END
561 v9.CheckSourceSuccess(lines)
562
Yegappan Lakshmananda9d3452024-05-02 13:02:36 +0200563 # Test for using a null class with type() and typename()
Yegappan Lakshmananb2e42b92024-05-01 11:44:17 +0200564 lines =<< trim END
565 vim9script
566 assert_equal(12, type(null_class))
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +0200567 assert_equal('class<any>', typename(null_class))
Yegappan Lakshmananb2e42b92024-05-01 11:44:17 +0200568 END
569 v9.CheckSourceSuccess(lines)
570enddef
571
Bram Moolenaar657aea72023-01-27 13:16:19 +0000572def Test_class_interface_wrong_end()
573 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200574 vim9script
575 abstract class SomeName
Doug Kearns74da0ee2023-12-14 20:26:26 +0100576 var member = 'text'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200577 endinterface
Bram Moolenaar657aea72023-01-27 13:16:19 +0000578 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200579 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass', 4)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000580
581 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200582 vim9script
583 export interface AnotherName
Doug Kearns74da0ee2023-12-14 20:26:26 +0100584 var member: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200585 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +0000586 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200587 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface', 4)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000588enddef
589
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000590def Test_object_not_set()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200591 # Use an uninitialized object in script context
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000592 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200593 vim9script
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000594
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200595 class State
Doug Kearns74da0ee2023-12-14 20:26:26 +0100596 var value = 'xyz'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200597 endclass
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000598
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200599 var state: State
600 var db = {'xyz': 789}
601 echo db[state.value]
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000602 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200603 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 9)
Bram Moolenaar0917e862023-02-18 14:42:44 +0000604
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200605 # Use an uninitialized object from a def function
Bram Moolenaar0917e862023-02-18 14:42:44 +0000606 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200607 vim9script
Bram Moolenaar0917e862023-02-18 14:42:44 +0000608
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200609 class Class
Doug Kearns74da0ee2023-12-14 20:26:26 +0100610 var id: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200611 def Method1()
612 echo 'Method1' .. this.id
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000613 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200614 endclass
615
616 var obj: Class
617 def Func()
618 obj.Method1()
619 enddef
620 Func()
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000621 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200622 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000623
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200624 # Pass an uninitialized object variable to a "new" function and try to call an
625 # object method.
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000626 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200627 vim9script
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000628
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200629 class Background
Doug Kearns74da0ee2023-12-14 20:26:26 +0100630 var background = 'dark'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200631 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000632
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200633 class Colorscheme
Doug Kearns74da0ee2023-12-14 20:26:26 +0100634 var _bg: Background
Bram Moolenaar0917e862023-02-18 14:42:44 +0000635
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200636 def GetBackground(): string
637 return this._bg.background
638 enddef
639 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000640
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200641 var bg: Background # UNINITIALIZED
642 echo Colorscheme.new(bg).GetBackground()
Bram Moolenaar0917e862023-02-18 14:42:44 +0000643 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200644 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
Ernie Raelf77a7f72023-03-03 15:05:30 +0000645
Ernie Raelf77a7f72023-03-03 15:05:30 +0000646 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200647 vim9script
Ernie Raelf77a7f72023-03-03 15:05:30 +0000648
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200649 class Class
Doug Kearns74da0ee2023-12-14 20:26:26 +0100650 var id: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200651 def Method1()
652 echo 'Method1' .. this.id
Ernie Raelf77a7f72023-03-03 15:05:30 +0000653 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200654 endclass
655
656 var obj = null_object
657 def Func()
658 obj.Method1()
659 enddef
660 Func()
Ernie Raelf77a7f72023-03-03 15:05:30 +0000661 END
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +0200662 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
Ernie Raelbe828252024-07-26 18:37:02 +0200663
664 # Reference a object variable through a null class object which is stored in a
665 # variable of type "any".
666 lines =<< trim END
667 vim9script
668
669 def Z()
670 var o: any = null_object
671 o.v = 4
672 enddef
673 Z()
674 END
675 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
676
677 # Do "echom" of a null object variable.
678 lines =<< trim END
679 vim9script
680
681 def X()
682 var x = null_object
683 echom x
684 enddef
685 X()
686 END
687 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 2)
Ernie Rael94082b62024-07-26 19:40:29 +0200688
689 # Use a null object variable that vim wants to force to number.
690 lines =<< trim END
691 vim9script
692
693 def X()
694 var o = null_object
695 var l = [ 1, o]
696 sort(l, 'N')
697 enddef
698 X()
699 END
700 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 3)
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000701enddef
702
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200703" Null object assignment and comparison
Ernie Rael5c018be2023-08-27 18:40:26 +0200704def Test_null_object_assign_compare()
705 var lines =<< trim END
706 vim9script
707
708 var nullo = null_object
709 def F(): any
710 return nullo
711 enddef
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +0200712 assert_equal('object<any>', typename(F()))
Ernie Rael5c018be2023-08-27 18:40:26 +0200713
714 var o0 = F()
715 assert_true(o0 == null_object)
716 assert_true(o0 == null)
717
718 var o1: any = nullo
719 assert_true(o1 == null_object)
720 assert_true(o1 == null)
721
722 def G()
723 var x = null_object
724 enddef
725
726 class C
727 endclass
728 var o2: C
729 assert_true(o2 == null_object)
730 assert_true(o2 == null)
731
732 o2 = null_object
733 assert_true(o2 == null)
734
735 o2 = C.new()
736 assert_true(o2 != null)
737
738 o2 = null_object
739 assert_true(o2 == null)
740 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200741 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200742enddef
743
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200744" Test for object member initialization and disassembly
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000745def Test_class_member_initializer()
746 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200747 vim9script
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000748
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200749 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100750 var lnum: number = 1
751 var col: number = 1
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000752
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200753 # constructor with only the line number
754 def new(lnum: number)
755 this.lnum = lnum
756 enddef
757 endclass
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000758
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200759 var pos = TextPosition.new(3)
760 assert_equal(3, pos.lnum)
761 assert_equal(1, pos.col)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000762
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200763 var instr = execute('disassemble TextPosition.new')
764 assert_match('new\_s*' ..
765 '0 NEW TextPosition size \d\+\_s*' ..
766 '\d PUSHNR 1\_s*' ..
767 '\d STORE_THIS 0\_s*' ..
768 '\d PUSHNR 1\_s*' ..
769 '\d STORE_THIS 1\_s*' ..
770 'this.lnum = lnum\_s*' ..
771 '\d LOAD arg\[-1]\_s*' ..
772 '\d PUSHNR 0\_s*' ..
773 '\d LOAD $0\_s*' ..
774 '\d\+ STOREINDEX object\_s*' ..
775 '\d\+ RETURN object.*',
776 instr)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000777 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200778 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000779enddef
780
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000781def Test_member_any_used_as_object()
782 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200783 vim9script
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000784
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200785 class Inner
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +0100786 public var value: number = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200787 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000788
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200789 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100790 var inner: any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200791 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000792
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200793 def F(outer: Outer)
794 outer.inner.value = 1
795 enddef
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000796
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200797 var inner_obj = Inner.new(0)
798 var outer_obj = Outer.new(inner_obj)
799 F(outer_obj)
800 assert_equal(1, inner_obj.value)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000801 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200802 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000803
Ernie Rael03042a22023-11-11 08:53:32 +0100804 # Try modifying a protected variable using an "any" object
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200805 lines =<< trim END
806 vim9script
807
808 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100809 var _value: string = ''
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200810 endclass
811
812 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100813 var inner: any
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200814 endclass
815
816 def F(outer: Outer)
817 outer.inner._value = 'b'
818 enddef
819
820 var inner_obj = Inner.new('a')
821 var outer_obj = Outer.new(inner_obj)
822 F(outer_obj)
823 END
Ernie Rael03042a22023-11-11 08:53:32 +0100824 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_value" in class "Inner"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200825
826 # Try modifying a non-existing variable using an "any" object
827 lines =<< trim END
828 vim9script
829
830 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100831 var value: string = ''
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200832 endclass
833
834 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100835 var inner: any
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200836 endclass
837
838 def F(outer: Outer)
839 outer.inner.someval = 'b'
840 enddef
841
842 var inner_obj = Inner.new('a')
843 var outer_obj = Outer.new(inner_obj)
844 F(outer_obj)
845 END
Ernie Raeld4802ec2023-10-20 11:59:00 +0200846 v9.CheckSourceFailure(lines, 'E1326: Variable "someval" not found in object "Inner"', 1)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000847enddef
848
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200849" Nested assignment to a object variable which is of another class type
850def Test_assignment_nested_type()
851 var lines =<< trim END
852 vim9script
853
854 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100855 public var value: number = 0
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200856 endclass
857
858 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100859 var inner: Inner
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200860 endclass
861
862 def F(outer: Outer)
863 outer.inner.value = 1
864 enddef
865
866 def Test_assign_to_nested_typed_member()
867 var inner = Inner.new(0)
868 var outer = Outer.new(inner)
869 F(outer)
870 assert_equal(1, inner.value)
871 enddef
872
873 Test_assign_to_nested_typed_member()
Ernie Rael98e68c02023-09-20 20:13:06 +0200874
875 var script_inner = Inner.new(0)
876 var script_outer = Outer.new(script_inner)
877 script_outer.inner.value = 1
878 assert_equal(1, script_inner.value)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200879 END
880 v9.CheckSourceSuccess(lines)
Ernie Rael98e68c02023-09-20 20:13:06 +0200881
882 # Assignment where target item is read only in :def
883 lines =<< trim END
884 vim9script
885
886 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100887 var value: number = 0
Ernie Rael98e68c02023-09-20 20:13:06 +0200888 endclass
889
890 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100891 var inner: Inner
Ernie Rael98e68c02023-09-20 20:13:06 +0200892 endclass
893
894 def F(outer: Outer)
895 outer.inner.value = 1
896 enddef
897
898 def Test_assign_to_nested_typed_member()
899 var inner = Inner.new(0)
900 var outer = Outer.new(inner)
901 F(outer)
902 assert_equal(1, inner.value)
903 enddef
904
905 Test_assign_to_nested_typed_member()
906 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200907 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 1)
Ernie Rael98e68c02023-09-20 20:13:06 +0200908
909 # Assignment where target item is read only script level
910 lines =<< trim END
911 vim9script
912
913 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100914 var value: number = 0
Ernie Rael98e68c02023-09-20 20:13:06 +0200915 endclass
916
917 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100918 var inner: Inner
Ernie Rael98e68c02023-09-20 20:13:06 +0200919 endclass
920
921 def F(outer: Outer)
922 outer.inner.value = 1
923 enddef
924
925 var script_inner = Inner.new(0)
926 var script_outer = Outer.new(script_inner)
927 script_outer.inner.value = 1
928 assert_equal(1, script_inner.value)
929 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200930 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 17)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200931enddef
932
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000933def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200934 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000935 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200936 vim9script
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000937
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200938 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +0100939 public var x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000940
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200941 def Add(n: number)
942 this.x += n
Bram Moolenaar22363c62023-04-24 17:15:25 +0100943 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200944 endclass
Bram Moolenaar22363c62023-04-24 17:15:25 +0100945
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200946 var f = Foo.new(3)
947 f.Add(17)
948 assert_equal(20, f.x)
949
950 def AddToFoo(obj: Foo)
951 obj.x += 3
952 enddef
953
954 AddToFoo(f)
955 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000956 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200957 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000958enddef
959
Bram Moolenaarf4508042023-01-15 16:54:57 +0000960def Test_list_of_objects()
961 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200962 vim9script
Bram Moolenaarf4508042023-01-15 16:54:57 +0000963
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200964 class Foo
965 def Add()
Bram Moolenaarf4508042023-01-15 16:54:57 +0000966 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200967 endclass
Bram Moolenaarf4508042023-01-15 16:54:57 +0000968
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200969 def ProcessList(fooList: list<Foo>)
970 for foo in fooList
971 foo.Add()
972 endfor
973 enddef
974
975 var l: list<Foo> = [Foo.new()]
976 ProcessList(l)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000977 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200978 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000979enddef
980
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000981def Test_expr_after_using_object()
982 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200983 vim9script
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000984
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200985 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100986 var label: string = ''
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200987 endclass
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000988
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200989 def Foo(): Something
990 var v = Something.new()
991 echo 'in Foo(): ' .. typename(v)
992 return v
993 enddef
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000994
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200995 Foo()
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000996 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200997 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000998enddef
999
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001000def Test_class_default_new()
1001 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001002 vim9script
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001003
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001004 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001005 var lnum: number = 1
1006 var col: number = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001007 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001008
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001009 var pos = TextPosition.new()
1010 assert_equal(1, pos.lnum)
1011 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001012
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001013 pos = TextPosition.new(v:none, v:none)
1014 assert_equal(1, pos.lnum)
1015 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001016
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001017 pos = TextPosition.new(3, 22)
1018 assert_equal(3, pos.lnum)
1019 assert_equal(22, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001020
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001021 pos = TextPosition.new(v:none, 33)
1022 assert_equal(1, pos.lnum)
1023 assert_equal(33, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001024 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001025 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001026
1027 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001028 vim9script
1029 class Person
Doug Kearns74da0ee2023-12-14 20:26:26 +01001030 var name: string
1031 var age: number = 42
1032 var education: string = "unknown"
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001033
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001034 def new(this.name, this.age = v:none, this.education = v:none)
1035 enddef
1036 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001037
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001038 var piet = Person.new("Piet")
1039 assert_equal("Piet", piet.name)
1040 assert_equal(42, piet.age)
1041 assert_equal("unknown", piet.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001042
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001043 var chris = Person.new("Chris", 4, "none")
1044 assert_equal("Chris", chris.name)
1045 assert_equal(4, chris.age)
1046 assert_equal("none", chris.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001047 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001048 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001049
1050 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001051 vim9script
1052 class Person
Doug Kearns74da0ee2023-12-14 20:26:26 +01001053 var name: string
1054 var age: number = 42
1055 var education: string = "unknown"
Bram Moolenaar74e12742022-12-13 21:14:28 +00001056
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001057 def new(this.name, this.age = v:none, this.education = v:none)
1058 enddef
1059 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001060
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001061 var missing = Person.new()
Bram Moolenaar74e12742022-12-13 21:14:28 +00001062 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001063 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001064
1065 # Using a specific value to initialize an instance variable in the new()
1066 # method.
1067 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001068 vim9script
1069 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001070 var val: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001071 def new(this.val = 'a')
1072 enddef
1073 endclass
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001074 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001075 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'", 4)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001076enddef
1077
h-east2261c892023-08-16 21:49:54 +09001078def Test_class_new_with_object_member()
1079 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001080 vim9script
h-east2261c892023-08-16 21:49:54 +09001081
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001082 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001083 var str: string
1084 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001085 def new(this.str, this.num)
h-east2261c892023-08-16 21:49:54 +09001086 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001087 def newVals(this.str, this.num)
1088 enddef
1089 endclass
h-east2261c892023-08-16 21:49:54 +09001090
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001091 def Check()
1092 try
1093 var c = C.new('cats', 2)
1094 assert_equal('cats', c.str)
1095 assert_equal(2, c.num)
1096
1097 c = C.newVals('dogs', 4)
1098 assert_equal('dogs', c.str)
1099 assert_equal(4, c.num)
1100 catch
1101 assert_report($'Unexpected exception was caught: {v:exception}')
1102 endtry
1103 enddef
1104
1105 Check()
h-east2261c892023-08-16 21:49:54 +09001106 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001107 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +09001108
1109 lines =<< trim END
h-eastdb385522023-09-28 22:18:19 +02001110 vim9script
1111
1112 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001113 var str: string
1114 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001115 def new(this.str, this.num)
h-eastdb385522023-09-28 22:18:19 +02001116 enddef
1117 endclass
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001118
1119 def Check()
1120 try
1121 var c = C.new(1, 2)
1122 catch
1123 assert_report($'Unexpected exception was caught: {v:exception}')
1124 endtry
1125 enddef
1126
1127 Check()
h-eastdb385522023-09-28 22:18:19 +02001128 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001129 v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 2)
h-eastdb385522023-09-28 22:18:19 +02001130
1131 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001132 vim9script
h-eastb895b0f2023-09-24 15:46:31 +02001133
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001134 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001135 var str: string
1136 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001137 def newVals(this.str, this.num)
h-eastb895b0f2023-09-24 15:46:31 +02001138 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001139 endclass
h-eastb895b0f2023-09-24 15:46:31 +02001140
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001141 def Check()
1142 try
1143 var c = C.newVals('dogs', 'apes')
1144 catch
1145 assert_report($'Unexpected exception was caught: {v:exception}')
1146 endtry
1147 enddef
1148
1149 Check()
1150 END
1151 v9.CheckSourceFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string', 2)
1152
1153 lines =<< trim END
1154 vim9script
1155
1156 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001157 var str: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001158 def new(str: any)
1159 enddef
1160 endclass
1161
1162 def Check()
1163 try
1164 var c = C.new(1)
1165 catch
1166 assert_report($'Unexpected exception was caught: {v:exception}')
1167 endtry
1168 enddef
1169
1170 Check()
h-eastb895b0f2023-09-24 15:46:31 +02001171 END
1172 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001173
1174 # Try using "this." argument in a class method
1175 lines =<< trim END
1176 vim9script
1177 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001178 var val = 10
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001179 static def Foo(this.val: number)
1180 enddef
1181 endclass
1182 END
1183 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
1184
1185 # Try using "this." argument in an object method
1186 lines =<< trim END
1187 vim9script
1188 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001189 var val = 10
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001190 def Foo(this.val: number)
1191 enddef
1192 endclass
1193 END
1194 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
h-east2261c892023-08-16 21:49:54 +09001195enddef
1196
Bram Moolenaar74e12742022-12-13 21:14:28 +00001197def Test_class_object_member_inits()
1198 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001199 vim9script
1200 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001201 var lnum: number
1202 var col = 1
1203 var addcol: number = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001204 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001205
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001206 var pos = TextPosition.new()
1207 assert_equal(0, pos.lnum)
1208 assert_equal(1, pos.col)
1209 assert_equal(2, pos.addcol)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001210 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001211 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001212
1213 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001214 vim9script
1215 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001216 var lnum
1217 var col = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001218 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001219 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001220 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001221
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001222 # If the type is not specified for a member, then it should be set during
1223 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +00001224 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001225 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001226
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001227 var init_count = 0
1228 def Init(): string
1229 init_count += 1
1230 return 'foo'
1231 enddef
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001232
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001233 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001234 var str1 = Init()
1235 var str2: string = Init()
1236 var col = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001237 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001238
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001239 assert_equal(init_count, 0)
1240 var a = A.new()
1241 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001242 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001243 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001244
1245 # Test for initializing an object member with an unknown variable/type
1246 lines =<< trim END
1247 vim9script
1248 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001249 var value = init_val
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001250 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001251 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001252 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001253 v9.CheckSourceFailure(lines, 'E1001: Variable not found: init_val', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001254
1255 # Test for initializing an object member with an special type
1256 lines =<< trim END
1257 vim9script
1258 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001259 var value: void
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001260 endclass
1261 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001262 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001263enddef
1264
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001265" Test for instance variable access
1266def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001267 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001268 vim9script
1269 class Triple
Doug Kearns74da0ee2023-12-14 20:26:26 +01001270 var _one = 1
1271 var two = 2
1272 public var three = 3
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001273
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001274 def GetOne(): number
1275 return this._one
1276 enddef
1277 endclass
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001278
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001279 var trip = Triple.new()
1280 assert_equal(1, trip.GetOne())
1281 assert_equal(2, trip.two)
1282 assert_equal(3, trip.three)
Ernie Rael03042a22023-11-11 08:53:32 +01001283 assert_fails('echo trip._one', 'E1333: Cannot access protected variable "_one" in class "Triple"')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001284
Ernie Rael03042a22023-11-11 08:53:32 +01001285 assert_fails('trip._one = 11', 'E1333: Cannot access protected variable "_one" in class "Triple"')
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001286 assert_fails('trip.two = 22', 'E1335: Variable "two" in class "Triple" is not writable')
1287 trip.three = 33
1288 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001289
Ernie Raeld4802ec2023-10-20 11:59:00 +02001290 assert_fails('trip.four = 4', 'E1326: Variable "four" not found in object "Triple"')
Bram Moolenaard505d172022-12-18 21:42:55 +00001291 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001292 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001293
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001294 # Test for a public member variable name beginning with an underscore
1295 lines =<< trim END
1296 vim9script
1297 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001298 public var _val = 10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001299 endclass
1300 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02001301 v9.CheckSourceFailure(lines, 'E1332: public variable name cannot start with underscore: public var _val = 10', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001302
Bram Moolenaar590162c2022-12-24 21:24:06 +00001303 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001304 vim9script
Bram Moolenaar590162c2022-12-24 21:24:06 +00001305
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001306 class MyCar
Doug Kearns74da0ee2023-12-14 20:26:26 +01001307 var make: string
1308 var age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001309
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001310 def new(make_arg: string)
1311 this.make = make_arg
Bram Moolenaar574950d2023-01-03 19:08:50 +00001312 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001313
1314 def GetMake(): string
1315 return $"make = {this.make}"
1316 enddef
1317 def GetAge(): number
1318 return this.age
1319 enddef
1320 endclass
1321
1322 var c = MyCar.new("abc")
1323 assert_equal('make = abc', c.GetMake())
1324
1325 c = MyCar.new("def")
1326 assert_equal('make = def', c.GetMake())
1327
1328 var c2 = MyCar.new("123")
1329 assert_equal('make = 123', c2.GetMake())
1330
1331 def CheckCar()
1332 assert_equal("make = def", c.GetMake())
1333 assert_equal(5, c.GetAge())
1334 enddef
1335 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001336 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001337 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001338
1339 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001340 vim9script
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001341
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001342 class MyCar
Doug Kearns74da0ee2023-12-14 20:26:26 +01001343 var make: string
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001344
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001345 def new(make_arg: string)
1346 this.make = make_arg
1347 enddef
1348 endclass
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001349
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001350 var c = MyCar.new("abc")
1351 var c = MyCar.new("def")
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001352 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001353 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "c"', 12)
Bram Moolenaarb149d222023-01-24 13:03:37 +00001354
1355 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001356 vim9script
Bram Moolenaarb149d222023-01-24 13:03:37 +00001357
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001358 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001359 var x: list<number> = []
Bram Moolenaarb149d222023-01-24 13:03:37 +00001360
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001361 def Add(n: number): any
1362 this.x->add(n)
1363 return this
1364 enddef
1365 endclass
Bram Moolenaarb149d222023-01-24 13:03:37 +00001366
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001367 echo Foo.new().Add(1).Add(2).x
1368 echo Foo.new().Add(1).Add(2)
1369 .x
1370 echo Foo.new().Add(1)
1371 .Add(2).x
1372 echo Foo.new()
1373 .Add(1).Add(2).x
1374 echo Foo.new()
1375 .Add(1)
1376 .Add(2)
1377 .x
Bram Moolenaarb149d222023-01-24 13:03:37 +00001378 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001379 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001380
1381 # Test for "public" cannot be abbreviated
1382 lines =<< trim END
1383 vim9script
1384 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001385 pub var val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001386 endclass
1387 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001388 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: pub var val = 1', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001389
Doug Kearns74da0ee2023-12-14 20:26:26 +01001390 # Test for "public" keyword must be followed by "var" or "static".
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001391 lines =<< trim END
1392 vim9script
1393 class Something
1394 public val = 1
1395 endclass
1396 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02001397 v9.CheckSourceFailure(lines, 'E1331: public must be followed by "var" or "static"', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001398
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001399 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001400 lines =<< trim END
1401 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001402 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001403 public var val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001404 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001405 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001406 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001407 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001408
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001409 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001410 lines =<< trim END
1411 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001412 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001413 public var val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001414 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001415 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001416 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001417 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001418
1419 # Modify a instance variable using the class name in a def function
1420 lines =<< trim END
1421 vim9script
1422 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001423 public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001424 endclass
1425 def T()
1426 A.val = 1
1427 enddef
1428 T()
1429 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001430 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001431
1432 # Read a instance variable using the class name in a def function
1433 lines =<< trim END
1434 vim9script
1435 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001436 public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001437 endclass
1438 def T()
1439 var i = A.val
1440 enddef
1441 T()
1442 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001443 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Ernie Raelcf138d42023-09-06 20:45:03 +02001444
1445 # Access from child class extending a class:
1446 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001447 vim9script
1448 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001449 var ro_obj_var = 10
1450 public var rw_obj_var = 20
1451 var _priv_obj_var = 30
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001452 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001453
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001454 class B extends A
1455 def Foo()
1456 var x: number
1457 x = this.ro_obj_var
1458 this.ro_obj_var = 0
1459 x = this.rw_obj_var
1460 this.rw_obj_var = 0
1461 x = this._priv_obj_var
1462 this._priv_obj_var = 0
1463 enddef
1464 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001465
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001466 var b = B.new()
1467 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001468 END
1469 v9.CheckSourceSuccess(lines)
1470enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001471
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001472" Test for class variable access
1473def Test_class_variable_access()
1474 # Test for "static" cannot be abbreviated
1475 var lines =<< trim END
1476 vim9script
1477 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001478 stat var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001479 endclass
1480 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001481 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: stat var val = 1', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001482
1483 # Test for "static" cannot be followed by "public".
1484 lines =<< trim END
1485 vim9script
1486 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001487 static public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001488 endclass
1489 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001490 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001491
1492 # A readonly class variable cannot be modified from a child class
1493 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001494 vim9script
1495 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001496 static var ro_class_var = 40
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001497 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001498
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001499 class B extends A
1500 def Foo()
1501 A.ro_class_var = 50
1502 enddef
1503 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001504
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001505 var b = B.new()
1506 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001507 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001508 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001509
Ernie Rael03042a22023-11-11 08:53:32 +01001510 # A protected class variable cannot be accessed from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001511 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001512 vim9script
1513 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001514 static var _priv_class_var = 60
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001515 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001516
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001517 class B extends A
1518 def Foo()
1519 var i = A._priv_class_var
1520 enddef
1521 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001522
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001523 var b = B.new()
1524 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001525 END
Ernie Rael03042a22023-11-11 08:53:32 +01001526 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001527
Ernie Rael03042a22023-11-11 08:53:32 +01001528 # A protected class variable cannot be modified from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001529 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001530 vim9script
1531 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001532 static var _priv_class_var = 60
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001533 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001534
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001535 class B extends A
1536 def Foo()
1537 A._priv_class_var = 0
1538 enddef
1539 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001540
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001541 var b = B.new()
1542 b.Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001543 END
Ernie Rael03042a22023-11-11 08:53:32 +01001544 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001545
1546 # Access from child class extending a class and from script context
1547 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001548 vim9script
1549 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001550 static var ro_class_var = 10
1551 public static var rw_class_var = 20
1552 static var _priv_class_var = 30
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001553 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001554
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001555 class B extends A
1556 def Foo()
1557 var x: number
1558 x = A.ro_class_var
1559 assert_equal(10, x)
1560 x = A.rw_class_var
1561 assert_equal(25, x)
1562 A.rw_class_var = 20
1563 assert_equal(20, A.rw_class_var)
1564 enddef
1565 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001566
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001567 assert_equal(10, A.ro_class_var)
1568 assert_equal(20, A.rw_class_var)
1569 A.rw_class_var = 25
1570 assert_equal(25, A.rw_class_var)
1571 var b = B.new()
1572 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001573 END
1574 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001575enddef
1576
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001577def Test_class_object_compare()
1578 var class_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001579 vim9script
1580 class Item
Doug Kearns74da0ee2023-12-14 20:26:26 +01001581 var nr = 0
1582 var name = 'xx'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001583 endclass
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001584 END
1585
1586 # used at the script level and in a compiled function
1587 var test_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001588 var i1 = Item.new()
1589 assert_equal(i1, i1)
1590 assert_true(i1 is i1)
1591 var i2 = Item.new()
1592 assert_equal(i1, i2)
1593 assert_false(i1 is i2)
1594 var i3 = Item.new(0, 'xx')
1595 assert_equal(i1, i3)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001596
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001597 var io1 = Item.new(1, 'xx')
1598 assert_notequal(i1, io1)
1599 var io2 = Item.new(0, 'yy')
1600 assert_notequal(i1, io2)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001601 END
1602
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001603 v9.CheckSourceSuccess(class_lines + test_lines)
1604 v9.CheckSourceSuccess(
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001605 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001606
1607 for op in ['>', '>=', '<', '<=', '=~', '!~']
1608 var op_lines = [
1609 'var i1 = Item.new()',
1610 'var i2 = Item.new()',
1611 'echo i1 ' .. op .. ' i2',
1612 ]
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001613 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object', 8)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001614 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001615 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001616 endfor
1617enddef
1618
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001619def Test_object_type()
1620 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001621 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001622
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001623 class One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001624 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001625 endclass
1626 class Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001627 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001628 endclass
1629 class TwoMore extends Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001630 var more = 9
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001631 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001632
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001633 var o: One = One.new()
1634 var t: Two = Two.new()
1635 var m: TwoMore = TwoMore.new()
1636 var tm: Two = TwoMore.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001637
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001638 t = m
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001639 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001640 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001641
1642 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001643 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001644
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001645 class One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001646 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001647 endclass
1648 class Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001649 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001650 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001651
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001652 var o: One = Two.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001653 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001654 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>', 10)
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001655
1656 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001657 vim9script
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001658
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001659 interface One
1660 def GetMember(): number
1661 endinterface
1662 class Two implements One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001663 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001664 def GetMember(): number
1665 return this.one
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001666 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001667 endclass
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001668
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001669 var o: One = Two.new(5)
1670 assert_equal(5, o.GetMember())
1671 END
1672 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001673
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001674 lines =<< trim END
1675 vim9script
1676
1677 class Num
Doug Kearns74da0ee2023-12-14 20:26:26 +01001678 var n: number = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001679 endclass
1680
1681 def Ref(name: string): func(Num): Num
1682 return (arg: Num): Num => {
1683 return eval(name)(arg)
1684 }
1685 enddef
1686
1687 const Fn = Ref('Double')
1688 var Double = (m: Num): Num => Num.new(m.n * 2)
1689
1690 echo Fn(Num.new(4))
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001691 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001692 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001693enddef
1694
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001695def Test_class_member()
1696 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001697 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001698 vim9script
1699 class TextPos
Doug Kearns74da0ee2023-12-14 20:26:26 +01001700 var lnum = 1
1701 var col = 1
1702 static var counter = 0
1703 static var _secret = 7
1704 public static var anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001705
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001706 static def AddToCounter(nr: number)
1707 counter += nr
1708 enddef
1709 endclass
Bram Moolenaard505d172022-12-18 21:42:55 +00001710
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001711 assert_equal(0, TextPos.counter)
1712 TextPos.AddToCounter(3)
1713 assert_equal(3, TextPos.counter)
1714 assert_fails('echo TextPos.noSuchMember', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001715
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001716 def GetCounter(): number
1717 return TextPos.counter
1718 enddef
1719 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001720
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001721 assert_fails('TextPos.noSuchMember = 2', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
1722 assert_fails('TextPos.counter = 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
1723 assert_fails('TextPos.counter += 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001724
Ernie Rael03042a22023-11-11 08:53:32 +01001725 assert_fails('echo TextPos._secret', 'E1333: Cannot access protected variable "_secret" in class "TextPos"')
1726 assert_fails('TextPos._secret = 8', 'E1333: Cannot access protected variable "_secret" in class "TextPos"')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001727
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001728 assert_equal(42, TextPos.anybody)
1729 TextPos.anybody = 12
1730 assert_equal(12, TextPos.anybody)
1731 TextPos.anybody += 5
1732 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001733 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001734 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001735
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001736 # example in the help
1737 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001738 vim9script
1739 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +01001740 var size: number
1741 static var totalSize: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001742
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001743 def new(this.size)
1744 totalSize += this.size
1745 enddef
1746 endclass
1747 assert_equal(0, OtherThing.totalSize)
1748 var to3 = OtherThing.new(3)
1749 assert_equal(3, OtherThing.totalSize)
1750 var to7 = OtherThing.new(7)
1751 assert_equal(10, OtherThing.totalSize)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001752 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001753 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001754
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001755 # using static class member twice
1756 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001757 vim9script
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001758
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001759 class HTML
Doug Kearns74da0ee2023-12-14 20:26:26 +01001760 static var author: string = 'John Doe'
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001761
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001762 static def MacroSubstitute(s: string): string
1763 return substitute(s, '{{author}}', author, 'gi')
1764 enddef
1765 endclass
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001766
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001767 assert_equal('some text', HTML.MacroSubstitute('some text'))
1768 assert_equal('some text', HTML.MacroSubstitute('some text'))
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001769 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001770 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001771
Ernie Rael03042a22023-11-11 08:53:32 +01001772 # access protected member in lambda
Bram Moolenaar62a69232023-01-24 15:07:04 +00001773 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001774 vim9script
Bram Moolenaar62a69232023-01-24 15:07:04 +00001775
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001776 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001777 var _x: number = 0
Bram Moolenaar62a69232023-01-24 15:07:04 +00001778
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001779 def Add(n: number): number
1780 const F = (): number => this._x + n
1781 return F()
1782 enddef
1783 endclass
Bram Moolenaar62a69232023-01-24 15:07:04 +00001784
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001785 var foo = Foo.new()
1786 assert_equal(5, foo.Add(5))
Bram Moolenaar62a69232023-01-24 15:07:04 +00001787 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001788 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001789
Ernie Rael03042a22023-11-11 08:53:32 +01001790 # access protected member in lambda body
h-east2bd6a092023-05-19 19:01:17 +01001791 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001792 vim9script
h-east2bd6a092023-05-19 19:01:17 +01001793
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001794 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001795 var _x: number = 6
h-east2bd6a092023-05-19 19:01:17 +01001796
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001797 def Add(n: number): number
1798 var Lam = () => {
1799 this._x = this._x + n
1800 }
1801 Lam()
1802 return this._x
1803 enddef
1804 endclass
h-east2bd6a092023-05-19 19:01:17 +01001805
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001806 var foo = Foo.new()
1807 assert_equal(13, foo.Add(7))
h-east2bd6a092023-05-19 19:01:17 +01001808 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001809 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001810
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001811 # check shadowing
1812 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001813 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001814
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001815 class Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01001816 static var count = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001817 def Method(count: number)
1818 echo count
1819 enddef
1820 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001821
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001822 var s = Some.new()
1823 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001824 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001825 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001826
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001827 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001828 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001829 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001830
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001831 class Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01001832 static var count = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001833 def Method(arg: number)
1834 var count = 3
1835 echo arg count
1836 enddef
1837 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001838
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001839 var s = Some.new()
1840 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001841 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001842 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001843
1844 # Test for using an invalid type for a member variable
1845 lines =<< trim END
1846 vim9script
1847 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001848 var val: xxx
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001849 endclass
1850 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001851 v9.CheckSourceFailure(lines, 'E1010: Type not recognized: xxx', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001852
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001853 # Test for setting a member on a null object
1854 lines =<< trim END
1855 vim9script
1856 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001857 public var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001858 endclass
1859
1860 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001861 var obj: A
1862 obj.val = ""
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001863 enddef
1864 F()
1865 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001866 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001867
1868 # Test for accessing a member on a null object
1869 lines =<< trim END
1870 vim9script
1871 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001872 var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001873 endclass
1874
1875 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001876 var obj: A
1877 echo obj.val
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001878 enddef
1879 F()
1880 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001881 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001882
1883 # Test for setting a member on a null object, at script level
1884 lines =<< trim END
1885 vim9script
1886 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001887 public var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001888 endclass
1889
1890 var obj: A
1891 obj.val = ""
1892 END
Ernie Rael4c8da022023-10-11 21:35:11 +02001893 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001894
1895 # Test for accessing a member on a null object, at script level
1896 lines =<< trim END
1897 vim9script
1898 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001899 var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001900 endclass
1901
1902 var obj: A
1903 echo obj.val
1904 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001905 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001906
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001907 # Test for no space before or after the '=' when initializing a member
1908 # variable
1909 lines =<< trim END
1910 vim9script
1911 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001912 var val: number= 10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001913 endclass
1914 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001915 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001916 lines =<< trim END
1917 vim9script
1918 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001919 var val: number =10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001920 endclass
1921 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001922 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001923
1924 # Access a non-existing member
1925 lines =<< trim END
1926 vim9script
1927 class A
1928 endclass
1929 var a = A.new()
1930 var v = a.bar
1931 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02001932 v9.CheckSourceFailure(lines, 'E1326: Variable "bar" not found in object "A"', 5)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001933enddef
1934
Ernie Raele6c9aa52023-10-06 19:55:52 +02001935" These messages should show the defining class of the variable (base class),
1936" not the class that did the reference (super class)
1937def Test_defining_class_message()
1938 var lines =<< trim END
1939 vim9script
1940
1941 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001942 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001943 endclass
1944
1945 class Child extends Base
1946 endclass
1947
1948 var o = Child.new()
1949 var x = o._v1
1950 END
Ernie Rael03042a22023-11-11 08:53:32 +01001951 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 11)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001952 lines =<< trim END
1953 vim9script
1954
1955 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001956 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001957 endclass
1958
1959 class Child extends Base
1960 endclass
1961
1962 def F()
1963 var o = Child.new()
1964 var x = o._v1
1965 enddef
1966 F()
1967 END
Ernie Rael03042a22023-11-11 08:53:32 +01001968 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001969 lines =<< trim END
1970 vim9script
1971
1972 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001973 var v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001974 endclass
1975
1976 class Child extends Base
1977 endclass
1978
1979 var o = Child.new()
1980 o.v1 = []
1981 END
1982 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 11)
1983 lines =<< trim END
1984 vim9script
1985
1986 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001987 var v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001988 endclass
1989
1990 class Child extends Base
1991 endclass
1992
1993 def F()
1994 var o = Child.new()
1995 o.v1 = []
1996 enddef
1997 F()
1998 END
1999
Ernie Rael03042a22023-11-11 08:53:32 +01002000 # Attempt to read a protected variable that is in the middle
Ernie Raele6c9aa52023-10-06 19:55:52 +02002001 # of the class hierarchy.
2002 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 2)
2003 lines =<< trim END
2004 vim9script
2005
2006 class Base0
2007 endclass
2008
2009 class Base extends Base0
Doug Kearns74da0ee2023-12-14 20:26:26 +01002010 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002011 endclass
2012
2013 class Child extends Base
2014 endclass
2015
2016 def F()
2017 var o = Child.new()
2018 var x = o._v1
2019 enddef
2020 F()
2021 END
Ernie Rael03042a22023-11-11 08:53:32 +01002022 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002023
Ernie Rael03042a22023-11-11 08:53:32 +01002024 # Attempt to read a protected variable that is at the start
Ernie Raele6c9aa52023-10-06 19:55:52 +02002025 # of the class hierarchy.
2026 lines =<< trim END
2027 vim9script
2028
2029 class Base0
2030 endclass
2031
2032 class Base extends Base0
2033 endclass
2034
2035 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01002036 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002037 endclass
2038
2039 def F()
2040 var o = Child.new()
2041 var x = o._v1
2042 enddef
2043 F()
2044 END
Ernie Rael03042a22023-11-11 08:53:32 +01002045 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Child"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002046enddef
2047
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002048func Test_class_garbagecollect()
2049 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002050 vim9script
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002051
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002052 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002053 var p = [2, 3]
2054 static var pl = ['a', 'b']
2055 static var pd = {a: 'a', b: 'b'}
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002056 endclass
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002057
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002058 echo Point.pl Point.pd
2059 call test_garbagecollect_now()
2060 echo Point.pl Point.pd
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002061 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002062 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002063
2064 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002065 vim9script
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002066
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002067 interface View
2068 endinterface
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002069
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002070 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01002071 var view: View
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002072 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002073
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002074 class MyView implements View
Doug Kearns74da0ee2023-12-14 20:26:26 +01002075 var widget: Widget
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002076
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002077 def new()
2078 # this will result in a circular reference to this object
Doug Kearns74da0ee2023-12-14 20:26:26 +01002079 var widget = Widget.new(this)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002080 enddef
2081 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002082
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002083 var view = MyView.new()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002084
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002085 # overwrite "view", will be garbage-collected next
2086 view = MyView.new()
2087 test_garbagecollect_now()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002088 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002089 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002090endfunc
2091
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002092" Test interface garbage collection
2093func Test_interface_garbagecollect()
2094 let lines =<< trim END
2095 vim9script
2096
2097 interface I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002098 var ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002099
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002100 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002101 endinterface
2102
2103 class A implements I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002104 static var ro_class_var: number = 10
2105 public static var rw_class_var: number = 20
2106 static var _priv_class_var: number = 30
2107 var ro_obj_var: number = 40
2108 var _priv_obj_var: number = 60
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002109
2110 static def _ClassBar(): number
2111 return _priv_class_var
2112 enddef
2113
2114 static def ClassFoo(): number
2115 return ro_class_var + rw_class_var + A._ClassBar()
2116 enddef
2117
2118 def _ObjBar(): number
2119 return this._priv_obj_var
2120 enddef
2121
2122 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002123 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002124 enddef
2125 endclass
2126
2127 assert_equal(60, A.ClassFoo())
2128 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002129 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002130 test_garbagecollect_now()
2131 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002132 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002133 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002134 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002135endfunc
2136
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002137def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002138 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002139 vim9script
2140 class Value
Doug Kearns74da0ee2023-12-14 20:26:26 +01002141 var value = 0
2142 static var objects = 0
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002143
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002144 def new(v: number)
2145 this.value = v
2146 ++objects
2147 enddef
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002148
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002149 static def GetCount(): number
2150 return objects
2151 enddef
2152 endclass
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002153
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002154 assert_equal(0, Value.GetCount())
2155 var v1 = Value.new(2)
2156 assert_equal(1, Value.GetCount())
2157 var v2 = Value.new(7)
2158 assert_equal(2, Value.GetCount())
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002159 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002160 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002161
2162 # Test for cleaning up after a class definition failure when using class
2163 # functions.
2164 lines =<< trim END
2165 vim9script
2166 class A
2167 static def Foo()
2168 enddef
2169 aaa
2170 endclass
2171 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002172 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: aaa', 5)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002173
2174 # Test for calling a class method from another class method without the class
2175 # name prefix.
2176 lines =<< trim END
2177 vim9script
2178 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01002179 static var myList: list<number> = [1]
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002180 static def Foo(n: number)
2181 myList->add(n)
2182 enddef
2183 static def Bar()
2184 Foo(2)
2185 enddef
2186 def Baz()
2187 Foo(3)
2188 enddef
2189 endclass
2190 A.Bar()
2191 var a = A.new()
2192 a.Baz()
2193 assert_equal([1, 2, 3], A.myList)
2194 END
2195 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002196enddef
2197
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002198def Test_class_defcompile()
2199 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002200 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002201
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002202 class C
2203 def Fo(i: number): string
2204 return i
2205 enddef
2206 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002207
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002208 defcompile C.Fo
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002209 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002210 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number', 1)
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002211
2212 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002213 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002214
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002215 class C
2216 static def Fc(): number
2217 return 'x'
2218 enddef
2219 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002220
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002221 defcompile C.Fc
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002222 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002223 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002224
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002225 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002226 vim9script
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002227
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002228 class C
2229 static def new()
2230 enddef
2231 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002232
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002233 defcompile C.new
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002234 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002235 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static', 5)
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002236
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002237 # Trying to compile a function using a non-existing class variable
2238 lines =<< trim END
2239 vim9script
2240 defcompile x.Foo()
2241 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002242 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002243
2244 # Trying to compile a function using a variable which is not a class
2245 lines =<< trim END
2246 vim9script
2247 var x: number
2248 defcompile x.Foo()
2249 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002250 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002251
2252 # Trying to compile a function without specifying the name
2253 lines =<< trim END
2254 vim9script
2255 class A
2256 endclass
2257 defcompile A.
2258 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002259 v9.CheckSourceFailure(lines, 'E475: Invalid argument: A.', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002260
2261 # Trying to compile a non-existing class object member function
2262 lines =<< trim END
2263 vim9script
2264 class A
2265 endclass
2266 var a = A.new()
2267 defcompile a.Foo()
2268 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02002269 v9.CheckSourceFailureList(lines, ['E1326: Variable "Foo" not found in object "A"', 'E475: Invalid argument: a.Foo()'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002270enddef
2271
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002272def Test_class_object_to_string()
2273 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002274 vim9script
2275 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01002276 var lnum = 1
2277 var col = 22
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002278 endclass
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002279
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002280 assert_equal("class TextPosition", string(TextPosition))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002281
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002282 var pos = TextPosition.new()
2283 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002284 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002285 v9.CheckSourceSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +02002286
2287 # check string() with object nesting
2288 lines =<< trim END
2289 vim9script
2290 class C
2291 var nest1: C
2292 var nest2: C
2293 def Init(n1: C, n2: C)
2294 this.nest1 = n1
2295 this.nest2 = n2
2296 enddef
2297 endclass
2298
2299 var o1 = C.new()
2300 var o2 = C.new()
2301 o1.Init(o1, o2)
2302 o2.Init(o2, o1)
2303
2304 # The following previously put's vim into an infinite loop.
2305
2306 var expect = "object of C {nest1: object of C {...}, nest2: object of C {nest1: object of C {...}, nest2: object of C {...}}}"
2307 assert_equal(expect, string(o1))
2308 END
2309 v9.CheckSourceSuccess(lines)
2310
2311 lines =<< trim END
2312 vim9script
2313
2314 class B
2315 endclass
2316
2317 class C
2318 var b: B
2319 var c: C
2320 endclass
2321
2322 var o1 = C.new(B.new(), C.new(B.new()))
2323 var expect = "object of C {b: object of B {}, c: object of C {b: object of B {}, c: object of [unknown]}}"
2324 assert_equal(expect, string(o1))
2325 END
2326 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002327enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00002328
Bram Moolenaar554d0312023-01-05 19:59:18 +00002329def Test_interface_basics()
2330 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002331 vim9script
2332 interface Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01002333 var ro_var: list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002334 def GetCount(): number
2335 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002336 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002337 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002338
2339 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002340 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002341 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002342 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002343 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002344 v9.CheckSourceFailure(lines, 'E1342: Interface can only be defined in Vim9 script', 1)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002345
2346 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002347 vim9script
Bram Moolenaar554d0312023-01-05 19:59:18 +00002348
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002349 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002350 var value: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002351 def Method(value: number)
2352 endinterface
Bram Moolenaard40f00c2023-01-13 17:36:49 +00002353 END
h-east61378a12023-04-18 19:07:29 +01002354 # The argument name and the object member name are the same, but this is not a
2355 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002356 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002357
2358 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002359 vim9script
2360 interface somethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002361 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002362 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002363 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002364 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong', 2)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002365
2366 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002367 vim9script
2368 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002369 var value: string
2370 var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002371 def GetCount(): number
2372 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002373 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002374 v9.CheckSourceFailure(lines, 'E1344: Cannot initialize a variable in an interface', 4)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002375
2376 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002377 vim9script
2378 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002379 var value: string
2380 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002381 def GetCount(): number
2382 return 5
2383 enddef
2384 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002385 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002386 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5', 6)
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002387
h-eastaa979c72025-01-03 10:19:45 +01002388 # Test for "interface" cannot be abbreviated
2389 lines =<< trim END
2390 vim9script
2391 inte Something
2392 endinterface
2393 END
2394 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: inte Something', 2)
2395
2396 # Test for "endinterface" cannot be abbreviated
2397 lines =<< trim END
2398 vim9script
2399 interface Something
2400 endin
2401 END
2402 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endin', 3)
2403
Yegappan Lakshmananac773182024-04-27 11:36:12 +02002404 # Additional commands after "interface name"
2405 lines =<< trim END
2406 vim9script
2407 interface Something | var x = 10 | var y = 20
2408 endinterface
2409 END
2410 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
2411
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002412 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002413 vim9script
2414 export interface EnterExit
2415 def Enter(): void
2416 def Exit(): void
2417 endinterface
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002418 END
2419 writefile(lines, 'XdefIntf.vim', 'D')
2420
2421 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002422 vim9script
2423 import './XdefIntf.vim' as defIntf
2424 export def With(ee: defIntf.EnterExit, F: func)
2425 ee.Enter()
2426 try
2427 F()
2428 finally
2429 ee.Exit()
2430 endtry
2431 enddef
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002432 END
2433 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002434
2435 var imported =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002436 vim9script
2437 export abstract class EnterExit
2438 def Enter(): void
2439 enddef
2440 def Exit(): void
2441 enddef
2442 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +00002443 END
2444 writefile(imported, 'XdefIntf2.vim', 'D')
2445
2446 lines[1] = " import './XdefIntf2.vim' as defIntf"
2447 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002448enddef
2449
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01002450" Test for using string() with an interface
2451def Test_interface_to_string()
2452 var lines =<< trim END
2453 vim9script
2454 interface Intf
2455 def Method(nr: number)
2456 endinterface
2457 assert_equal("interface Intf", string(Intf))
2458 END
2459 v9.CheckSourceSuccess(lines)
2460enddef
2461
Bram Moolenaar94674f22023-01-06 18:42:20 +00002462def Test_class_implements_interface()
2463 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002464 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002465
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002466 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002467 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002468 def Method(nr: number)
2469 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002470
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002471 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002472 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002473 def Method(nr: number)
2474 echo nr
2475 enddef
2476 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002477
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002478 interface Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002479 var member: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002480 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002481
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002482 class AnotherImpl implements Some, Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002483 var member = 'abc'
2484 var count = 20
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002485 def Method(nr: number)
2486 echo nr
2487 enddef
2488 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002489 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002490 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002491
2492 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002493 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002494
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002495 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002496 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002497 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002498
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002499 class SomeImpl implements Some implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002500 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002501 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002502 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002503 v9.CheckSourceFailure(lines, 'E1350: Duplicate "implements"', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002504
2505 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002506 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002507
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002508 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002509 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002510 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002511
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002512 class SomeImpl implements Some, Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002513 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002514 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002515 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002516 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002517
2518 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002519 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002520
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002521 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002522 var counter: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002523 def Method(nr: number)
2524 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002525
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002526 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002527 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002528 def Method(nr: number)
2529 echo nr
2530 enddef
2531 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002532 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002533 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented', 13)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002534
2535 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002536 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002537
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002538 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002539 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002540 def Methods(nr: number)
2541 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002542
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002543 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002544 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002545 def Method(nr: number)
2546 echo nr
2547 enddef
2548 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002549 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002550 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented', 13)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002551
2552 # Check different order of members in class and interface works.
2553 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002554 vim9script
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002555
2556 interface Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002557 var label: string
2558 var errpos: number
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002559 endinterface
2560
2561 # order of members is opposite of interface
2562 class Failure implements Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002563 public var lnum: number = 5
2564 var errpos: number = 42
2565 var label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002566 endclass
2567
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002568 def Test()
2569 var result: Result = Failure.new()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002570
2571 assert_equal('label', result.label)
2572 assert_equal(42, result.errpos)
2573 enddef
2574
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002575 Test()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002576 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002577 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002578
2579 # Interface name after "extends" doesn't end in a space or NUL character
2580 lines =<< trim END
2581 vim9script
2582 interface A
2583 endinterface
2584 class B extends A"
2585 endclass
2586 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002587 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002588
2589 # Trailing characters after a class name
2590 lines =<< trim END
2591 vim9script
2592 class A bbb
2593 endclass
2594 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002595 v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002596
2597 # using "implements" with a non-existing class
2598 lines =<< trim END
2599 vim9script
2600 class A implements B
2601 endclass
2602 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002603 v9.CheckSourceFailure(lines, 'E1346: Interface name not found: B', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002604
2605 # using "implements" with a regular class
2606 lines =<< trim END
2607 vim9script
2608 class A
2609 endclass
2610 class B implements A
2611 endclass
2612 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002613 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: A', 5)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002614
2615 # using "implements" with a variable
2616 lines =<< trim END
2617 vim9script
2618 var T: number = 10
2619 class A implements T
2620 endclass
2621 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002622 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: T', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002623
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002624 # implements should be followed by a white space
2625 lines =<< trim END
2626 vim9script
2627 interface A
2628 endinterface
2629 class B implements A;
2630 endclass
2631 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002632 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A;', 4)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002633
LemonBoyc5d27442023-08-19 13:02:35 +02002634 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002635 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002636
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002637 interface One
2638 def IsEven(nr: number): bool
2639 endinterface
2640 class Two implements One
2641 def IsEven(nr: number): string
2642 enddef
2643 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002644 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002645 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002646
2647 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002648 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002649
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002650 interface One
2651 def IsEven(nr: number): bool
2652 endinterface
2653 class Two implements One
2654 def IsEven(nr: bool): bool
2655 enddef
2656 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002657 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002658 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002659
2660 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002661 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002662
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002663 interface One
2664 def IsEven(nr: number): bool
2665 endinterface
2666 class Two implements One
2667 def IsEven(nr: number, ...extra: list<number>): bool
2668 enddef
2669 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002670 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002671 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 +02002672
2673 # access superclass interface members from subclass, mix variable order
2674 lines =<< trim END
2675 vim9script
2676
2677 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002678 var mvar1: number
2679 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002680 endinterface
2681
2682 # NOTE: the order is swapped
2683 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002684 var mvar2: number
2685 var mvar1: number
2686 public static var svar2: number
2687 public static var svar1: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002688 def new()
2689 svar1 = 11
2690 svar2 = 12
2691 this.mvar1 = 111
2692 this.mvar2 = 112
2693 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002694 endclass
2695
2696 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002697 def new()
2698 this.mvar1 = 121
2699 this.mvar2 = 122
2700 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002701 endclass
2702
2703 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002704 def new()
2705 this.mvar1 = 131
2706 this.mvar2 = 132
2707 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002708 endclass
2709
Ernie Raelcf138d42023-09-06 20:45:03 +02002710 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002711 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002712 enddef
2713
2714 var oa = A.new()
2715 var ob = B.new()
2716 var oc = C.new()
2717
Ernie Raelcf138d42023-09-06 20:45:03 +02002718 assert_equal([111, 112], F2(oa))
2719 assert_equal([121, 122], F2(ob))
2720 assert_equal([131, 132], F2(oc))
2721 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002722 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002723
2724 # Access superclass interface members from subclass, mix variable order.
2725 # Two interfaces, one on A, one on B; each has both kinds of variables
2726 lines =<< trim END
2727 vim9script
2728
2729 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002730 var mvar1: number
2731 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002732 endinterface
2733
2734 interface I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002735 var mvar3: number
2736 var mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002737 endinterface
2738
2739 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002740 public static var svar1: number
2741 public static var svar2: number
2742 var mvar1: number
2743 var mvar2: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002744 def new()
2745 svar1 = 11
2746 svar2 = 12
2747 this.mvar1 = 111
2748 this.mvar2 = 112
2749 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002750 endclass
2751
2752 class B extends A implements I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002753 static var svar3: number
2754 static var svar4: number
2755 var mvar3: number
2756 var mvar4: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002757 def new()
2758 svar3 = 23
2759 svar4 = 24
2760 this.mvar1 = 121
2761 this.mvar2 = 122
2762 this.mvar3 = 123
2763 this.mvar4 = 124
2764 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002765 endclass
2766
2767 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01002768 public static var svar5: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002769 def new()
2770 svar5 = 1001
2771 this.mvar1 = 131
2772 this.mvar2 = 132
2773 this.mvar3 = 133
2774 this.mvar4 = 134
2775 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002776 endclass
2777
Ernie Raelcf138d42023-09-06 20:45:03 +02002778 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002779 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002780 enddef
2781
Ernie Raelcf138d42023-09-06 20:45:03 +02002782 def F4(i: I2): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002783 return [ i.mvar3, i.mvar4 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002784 enddef
2785
Ernie Raelcf138d42023-09-06 20:45:03 +02002786 var oa = A.new()
2787 var ob = B.new()
2788 var oc = C.new()
2789
Ernie Raelcf138d42023-09-06 20:45:03 +02002790 assert_equal([[111, 112]], [F2(oa)])
2791 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2792 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002793 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002794 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002795
2796 # Using two interface names without a space after the ","
2797 lines =<< trim END
2798 vim9script
2799 interface A
2800 endinterface
2801 interface B
2802 endinterface
2803 class C implements A,B
2804 endclass
2805 END
2806 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2807
2808 # No interface name after a comma
2809 lines =<< trim END
2810 vim9script
2811 interface A
2812 endinterface
2813 class B implements A,
2814 endclass
2815 END
2816 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2817
2818 # No interface name after implements
2819 lines =<< trim END
2820 vim9script
2821 class A implements
2822 endclass
2823 END
2824 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002825enddef
2826
Bram Moolenaard0200c82023-01-28 15:19:40 +00002827def Test_call_interface_method()
2828 var lines =<< trim END
2829 vim9script
2830 interface Base
2831 def Enter(): void
2832 endinterface
2833
2834 class Child implements Base
2835 def Enter(): void
2836 g:result ..= 'child'
2837 enddef
2838 endclass
2839
2840 def F(obj: Base)
2841 obj.Enter()
2842 enddef
2843
2844 g:result = ''
2845 F(Child.new())
2846 assert_equal('child', g:result)
2847 unlet g:result
2848 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002849 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002850
2851 lines =<< trim END
2852 vim9script
2853 class Base
2854 def Enter(): void
2855 g:result ..= 'base'
2856 enddef
2857 endclass
2858
2859 class Child extends Base
2860 def Enter(): void
2861 g:result ..= 'child'
2862 enddef
2863 endclass
2864
2865 def F(obj: Base)
2866 obj.Enter()
2867 enddef
2868
2869 g:result = ''
2870 F(Child.new())
2871 assert_equal('child', g:result)
2872 unlet g:result
2873 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002874 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002875
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002876 # method of interface returns a value
2877 lines =<< trim END
2878 vim9script
2879 interface Base
2880 def Enter(): string
2881 endinterface
2882
2883 class Child implements Base
2884 def Enter(): string
2885 g:result ..= 'child'
2886 return "/resource"
2887 enddef
2888 endclass
2889
2890 def F(obj: Base)
2891 var r = obj.Enter()
2892 g:result ..= r
2893 enddef
2894
2895 g:result = ''
2896 F(Child.new())
2897 assert_equal('child/resource', g:result)
2898 unlet g:result
2899 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002900 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002901
2902 lines =<< trim END
2903 vim9script
2904 class Base
2905 def Enter(): string
2906 return null_string
2907 enddef
2908 endclass
2909
2910 class Child extends Base
2911 def Enter(): string
2912 g:result ..= 'child'
2913 return "/resource"
2914 enddef
2915 endclass
2916
2917 def F(obj: Base)
2918 var r = obj.Enter()
2919 g:result ..= r
2920 enddef
2921
2922 g:result = ''
2923 F(Child.new())
2924 assert_equal('child/resource', g:result)
2925 unlet g:result
2926 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002927 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002928
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002929 # No class that implements the interface.
2930 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002931 vim9script
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002932
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002933 interface IWithEE
2934 def Enter(): any
2935 def Exit(): void
2936 endinterface
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002937
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002938 def With1(ee: IWithEE, F: func)
2939 var r = ee.Enter()
2940 enddef
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002941
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002942 defcompile
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002943 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002944 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002945enddef
2946
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002947def Test_class_used_as_type()
2948 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002949 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002950
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002951 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002952 var x = 0
2953 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002954 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002955
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002956 var p: Point
2957 p = Point.new(2, 33)
2958 assert_equal(2, p.x)
2959 assert_equal(33, p.y)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002960 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002961 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002962
2963 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002964 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002965
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002966 interface HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002967 var x: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002968 endinterface
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002969
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002970 class Point implements HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002971 var x = 0
2972 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002973 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002974
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002975 var p: Point
2976 p = Point.new(2, 33)
2977 var hx = p
2978 assert_equal(2, hx.x)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002979 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002980 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002981
2982 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002983 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002984
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002985 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002986 var x = 0
2987 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002988 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002989
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002990 var p: Point
2991 p = 'text'
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002992 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002993 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string', 9)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002994enddef
2995
Bram Moolenaar83677162023-01-08 19:54:10 +00002996def Test_class_extends()
2997 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002998 vim9script
2999 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003000 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003001 def GetOne(): number
3002 return this.one
Bram Moolenaar6aa09372023-01-11 17:59:38 +00003003 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003004 endclass
3005 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003006 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003007 def GetTotal(): number
3008 return this.one + this.two
3009 enddef
3010 endclass
3011 var o = Child.new()
3012 assert_equal(1, o.one)
3013 assert_equal(2, o.two)
3014 assert_equal(1, o.GetOne())
3015 assert_equal(3, o.GetTotal())
Bram Moolenaar6481acc2023-01-11 21:14:17 +00003016 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003017 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003018
3019 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003020 vim9script
3021 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003022 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003023 endclass
3024 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003025 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003026 endclass
3027 var o = Child.new(3, 44)
3028 assert_equal(3, o.one)
3029 assert_equal(44, o.two)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003030 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003031 v9.CheckSourceSuccess(lines)
3032
3033 lines =<< trim END
3034 vim9script
3035 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003036 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003037 endclass
3038 class Child extends Base extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003039 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003040 endclass
3041 END
3042 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"', 5)
3043
3044 lines =<< trim END
3045 vim9script
3046 class Child extends BaseClass
Doug Kearns74da0ee2023-12-14 20:26:26 +01003047 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003048 endclass
3049 END
3050 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass', 4)
3051
3052 lines =<< trim END
3053 vim9script
3054 var SomeVar = 99
3055 class Child extends SomeVar
Doug Kearns74da0ee2023-12-14 20:26:26 +01003056 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003057 endclass
3058 END
3059 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar', 5)
3060
3061 lines =<< trim END
3062 vim9script
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003063 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003064 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003065 def ToString(): number
3066 return this.age
3067 enddef
3068 def ToString(): string
3069 return this.age
3070 enddef
3071 endclass
3072 END
3073 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
3074
3075 lines =<< trim END
3076 vim9script
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003077 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003078 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003079 static def ToString(): string
3080 return 'Base class'
3081 enddef
3082 endclass
3083
3084 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003085 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003086 def ToString(): string
3087 return Base.ToString() .. ': ' .. this.age
3088 enddef
3089 endclass
3090
3091 var o = Child.new('John', 42)
3092 assert_equal('Base class: 42', o.ToString())
3093 END
3094 v9.CheckSourceSuccess(lines)
3095
3096 lines =<< trim END
3097 vim9script
3098 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003099 var value = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003100 def new(init: number)
3101 this.value = number + 1
3102 enddef
3103 endclass
3104 class Child extends Base
3105 def new()
3106 this.new(3)
3107 enddef
3108 endclass
3109 var c = Child.new()
3110 END
3111 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003112
3113 # base class with more than one object member
3114 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003115 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003116
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003117 class Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01003118 var success: bool
3119 var value: any = null
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003120 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003121
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003122 class Success extends Result
3123 def new(this.value = v:none)
3124 this.success = true
3125 enddef
3126 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003127
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003128 var v = Success.new('asdf')
3129 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003130 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003131 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003132
3133 # class name after "extends" doesn't end in a space or NUL character
3134 lines =<< trim END
3135 vim9script
3136 class A
3137 endclass
3138 class B extends A"
3139 endclass
3140 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003141 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00003142enddef
3143
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003144def Test_using_base_class()
3145 var lines =<< trim END
3146 vim9script
3147
3148 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003149 def Enter(): any
3150 return null
3151 enddef
3152 def Exit(resource: any): void
3153 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003154 endclass
3155
3156 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003157 def Enter(): any
3158 return 42
3159 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003160
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003161 def Exit(resource: number): void
3162 g:result ..= '/exit'
3163 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003164 endclass
3165
3166 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003167 var r = ee.Enter()
3168 try
3169 g:result ..= r
3170 finally
3171 g:result ..= '/finally'
3172 ee.Exit(r)
3173 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003174 enddef
3175
3176 g:result = ''
3177 With(ChildEE.new())
3178 assert_equal('42/finally/exit', g:result)
3179 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003180 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003181 unlet g:result
3182enddef
3183
Ernie Raelbce60c42025-01-19 10:03:00 +01003184" Test for using a method from the super class
Ernie Rael58c95792024-08-13 23:27:22 +02003185def Test_super_dispatch()
3186 # See #15448 and #15463
3187 var lines =<< trim END
3188 vim9script
3189
3190 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003191 def String(): string
3192 return 'A'
3193 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003194 endclass
3195
3196 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003197 def String(): string
3198 return super.String()
3199 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003200 endclass
3201
3202 class C extends B
3203 endclass
3204
3205 assert_equal('A', C.new().String())
3206 END
3207 v9.CheckSourceSuccess(lines)
3208
3209 lines =<< trim END
3210 vim9script
3211
3212 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003213 def F(): string
3214 return 'AA'
3215 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003216 endclass
3217
3218 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003219 def F(): string
3220 return 'BB'
3221 enddef
3222 def S(): string
3223 return super.F()
3224 enddef
3225 def S0(): string
3226 return this.S()
3227 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003228 endclass
3229
3230 class C extends B
Ernie Raelbce60c42025-01-19 10:03:00 +01003231 def F(): string
3232 return 'CC'
3233 enddef
3234 def ToB(): string
3235 return super.F()
3236 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003237 endclass
3238
3239 assert_equal('AA', B.new().S())
3240 assert_equal('AA', C.new().S())
3241 assert_equal('AA', B.new().S0())
3242 assert_equal('AA', C.new().S0())
3243
3244 assert_equal('BB', C.new().ToB())
3245
3246 assert_equal('CC', C.new().F())
3247 assert_equal('BB', B.new().F())
3248 assert_equal('AA', A.new().F())
3249 END
3250 v9.CheckSourceSuccess(lines)
3251
3252 lines =<< trim END
3253 vim9script
3254
3255 var call_chain: list<string>
3256
3257 abstract class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003258 abstract def _G(): string
Ernie Rael58c95792024-08-13 23:27:22 +02003259
Ernie Raelbce60c42025-01-19 10:03:00 +01003260 def F(): string
3261 call_chain->add('A.F()')
3262 return this._G()
3263 enddef
3264 def _H(): string
3265 call_chain->add('A._H()')
3266 return this.F()
3267 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003268 endclass
3269
3270 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003271 def _G(): string
3272 call_chain->add('B.G()')
3273 return 'BBB'
3274 enddef
3275 def SF(): string
3276 call_chain->add('B.SF()')
3277 return super._H()
3278 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003279 endclass
3280
3281 class C extends B
3282 endclass
3283
3284 class D extends C
Ernie Raelbce60c42025-01-19 10:03:00 +01003285 def SF(): string
3286 call_chain->add('D.SF()')
3287 return super.SF()
3288 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003289 endclass
3290
3291 class E extends D
Ernie Raelbce60c42025-01-19 10:03:00 +01003292 def SF(): string
3293 call_chain->add('E.SF()')
3294 return super.SF()
3295 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003296 endclass
3297
3298 class F extends E
Ernie Raelbce60c42025-01-19 10:03:00 +01003299 def _G(): string
3300 call_chain->add('F._G()')
3301 return 'FFF'
3302 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003303 endclass
3304
3305 # E.new() -> A.F() -> B._G()
3306 call_chain = []
3307 var o1 = E.new()
3308 assert_equal('BBB', o1.F())
3309 assert_equal(['A.F()', 'B.G()'], call_chain)
3310
3311 # F.new() -> E.SF() -> D.SF() -> B.SF() -> A._H() -> A.F() -> F._G()
3312 call_chain = []
3313 var o2 = F.new()
3314 assert_equal('FFF', o2.SF())
3315 assert_equal(['E.SF()', 'D.SF()', 'B.SF()', 'A._H()', 'A.F()', 'F._G()'], call_chain)
3316 END
3317 v9.CheckSourceSuccess(lines)
Ernie Raelbce60c42025-01-19 10:03:00 +01003318
3319 # problems with method dispatch: super -> abstract
3320 # https://github.com/vim/vim/issues/15514
3321 lines =<< trim END
3322 vim9script
3323 abstract class B
3324 abstract def ToString(): string
3325 endclass
3326
3327 class C extends B
3328 def ToString(): string
3329 return super.ToString()
3330 enddef
3331 endclass
3332
3333 try
3334 defcompile C.ToString
3335 call assert_false(1, 'command should have failed')
3336 catch
3337 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3338 endtry
3339 END
3340 v9.CheckSourceSuccess(lines)
3341
3342 # problems with method dispatch: super -> abstract -> concrete
3343 lines =<< trim END
3344 vim9script
3345
3346 class A
3347 def ToString()
3348 echo 'A'
3349 enddef
3350 endclass
3351
3352 abstract class B extends A
3353 abstract def ToString()
3354 endclass
3355
3356 class C extends B
3357 def ToString()
3358 super.ToString()
3359 enddef
3360 endclass
3361
3362 try
3363 defcompile C.ToString
3364 call assert_false(1, 'command should have failed')
3365 catch
3366 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3367 endtry
3368 END
3369 v9.CheckSourceSuccess(lines)
3370
3371 # Invoking a super method and an interface method which have the same name.
3372 lines =<< trim END
3373 vim9script
3374
3375 interface I
3376 def ToString(): string
3377 endinterface
3378
3379 # Note that A does not implement I.
3380 class A
3381 def ToString(): string
3382 return 'A'
3383 enddef
3384 endclass
3385
3386 class B extends A implements I
3387 def ToString(): string
3388 return super.ToString()
3389 enddef
3390 endclass
3391
3392 def TestI(i: I): string
3393 return i.ToString()
3394 enddef
3395
3396 assert_equal('A', B.new().ToString())
3397 assert_equal('A', TestI(B.new()))
3398 END
3399 v9.CheckSourceSuccess(lines)
3400
3401 # super and an abstract class with no abstract methods
3402 lines =<< trim END
3403 vim9script
3404
3405 class A
3406 def ToString(): string
3407 return 'A'
3408 enddef
3409 endclass
3410
3411 # An abstract class with no abstract methods.
3412 abstract class B extends A
3413 endclass
3414
3415 class C extends B
3416 def ToString(): string
3417 return super.ToString()
3418 enddef
3419 endclass
3420
3421 def TestA(a: A): string
3422 return a.ToString()
3423 enddef
3424
3425 def TestB(b: B): string
3426 return b.ToString()
3427 enddef
3428
3429 assert_equal('A', C.new().ToString())
3430 assert_equal('A', TestA(A.new()))
3431 assert_equal('A', TestA(C.new()))
3432 assert_equal('A', TestB(C.new()))
3433 END
3434 v9.CheckSourceSuccess(lines)
3435
3436 # super and an abstract class with no abstract methods and the initial
3437 # implements clause
3438 lines =<< trim END
3439 vim9script
3440
3441 interface I
3442 def ToString(): string
3443 endinterface
3444
3445 # Note that A does not implement I.
3446 class A
3447 def ToString(): string
3448 return 'A'
3449 enddef
3450 endclass
3451
3452 # An abstract class with no abstract methods.
3453 abstract class B extends A implements I
3454 endclass
3455
3456 class C extends B implements I
3457 def ToString(): string
3458 return super.ToString()
3459 enddef
3460 endclass
3461
3462 # Note that A.ToString() is different from I.ToString().
3463 def TestA(a: A): string
3464 return a.ToString()
3465 enddef
3466
3467 assert_equal('A', C.new().ToString())
3468 assert_equal('A', TestA(A.new()))
3469 assert_equal('A', TestA(C.new()))
3470 END
3471 v9.CheckSourceSuccess(lines)
Ernie Rael58c95792024-08-13 23:27:22 +02003472enddef
3473
Bram Moolenaara86655a2023-01-12 17:06:27 +00003474def Test_class_import()
3475 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003476 vim9script
3477 export class Animal
Doug Kearns74da0ee2023-12-14 20:26:26 +01003478 var kind: string
3479 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003480 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003481 END
3482 writefile(lines, 'Xanimal.vim', 'D')
3483
3484 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003485 vim9script
3486 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003487
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003488 var a: animal.Animal
3489 a = animal.Animal.new('fish', 'Eric')
3490 assert_equal('fish', a.kind)
3491 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003492
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003493 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3494 assert_equal('cat', b.kind)
3495 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003496 END
3497 v9.CheckScriptSuccess(lines)
3498enddef
3499
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003500" Test for importing a class into a legacy script and calling the class method
3501def Test_class_method_from_legacy_script()
3502 var lines =<< trim END
3503 vim9script
3504 export class A
3505 static var name: string = 'a'
3506 static def SetName(n: string)
3507 name = n
3508 enddef
3509 endclass
3510 END
3511 writefile(lines, 'Xvim9export.vim', 'D')
3512
3513 lines =<< trim END
3514 import './Xvim9export.vim' as vim9
3515
3516 call s:vim9.A.SetName('b')
3517 call assert_equal('b', s:vim9.A.name)
3518 END
3519 v9.CheckScriptSuccess(lines)
3520enddef
3521
Yegappan Lakshmanand2e1c832023-12-14 19:59:45 +01003522" Test for implementing an imported interface
3523def Test_implement_imported_interface()
3524 var lines =<< trim END
3525 vim9script
3526 export interface Imp_Intf1
3527 def Fn1(): number
3528 endinterface
3529 export interface Imp_Intf2
3530 def Fn2(): number
3531 endinterface
3532 END
3533 writefile(lines, 'Ximportinterface.vim', 'D')
3534
3535 lines =<< trim END
3536 vim9script
3537 import './Ximportinterface.vim' as Xintf
3538
3539 class A implements Xintf.Imp_Intf1, Xintf.Imp_Intf2
3540 def Fn1(): number
3541 return 10
3542 enddef
3543 def Fn2(): number
3544 return 20
3545 enddef
3546 endclass
3547 var a = A.new()
3548 assert_equal(10, a.Fn1())
3549 assert_equal(20, a.Fn2())
3550 END
3551 v9.CheckScriptSuccess(lines)
3552enddef
3553
3554" Test for extending an imported class
3555def Test_extend_imported_class()
3556 var lines =<< trim END
3557 vim9script
3558 export class Imp_C1
3559 def Fn1(): number
3560 return 5
3561 enddef
3562 endclass
3563 END
3564 writefile(lines, 'Xextendimportclass.vim', 'D')
3565
3566 lines =<< trim END
3567 vim9script
3568 import './Xextendimportclass.vim' as XClass
3569
3570 class A extends XClass.Imp_C1
3571 endclass
3572 var a = A.new()
3573 assert_equal(5, a.Fn1())
3574 END
3575 v9.CheckScriptSuccess(lines)
3576enddef
3577
Christian Brabandtd9a1f262025-01-21 22:17:50 +01003578def Test_abstract_class()
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003579 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003580 vim9script
3581 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003582 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003583 endclass
3584 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003585 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003586 endclass
3587 var p: Base = Person.new('Peter', 42)
3588 assert_equal('Peter', p.name)
3589 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003590 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003591 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003592
3593 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003594 vim9script
3595 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003596 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003597 endclass
3598 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003599 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003600 endclass
3601 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003602 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003603 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003604
3605 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003606 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003607 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003608 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003609 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003610 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003611
h-eastaa979c72025-01-03 10:19:45 +01003612 # Test for "abstract" cannot be abbreviated
3613 lines =<< trim END
3614 vim9script
3615 abs class A
3616 endclass
3617 END
3618 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs class A', 2)
3619
Yegappan Lakshmananac773182024-04-27 11:36:12 +02003620 # Additional commands after "abstract class"
3621 lines =<< trim END
3622 vim9script
3623 abstract class Something | var x = []
3624 endclass
3625 END
3626 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = []", 2)
3627
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003628 # Abstract class cannot have a "new" function
3629 lines =<< trim END
3630 vim9script
3631 abstract class Base
3632 def new()
3633 enddef
3634 endclass
3635 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003636 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003637
3638 # extending an abstract class with class methods and variables
3639 lines =<< trim END
3640 vim9script
3641 abstract class A
3642 static var s: string = 'vim'
3643 static def Fn(): list<number>
3644 return [10]
3645 enddef
3646 endclass
3647 class B extends A
3648 endclass
3649 var b = B.new()
3650 assert_equal('vim', A.s)
3651 assert_equal([10], A.Fn())
3652 END
3653 v9.CheckScriptSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003654enddef
3655
Bram Moolenaar486fc252023-01-18 14:51:07 +00003656def Test_closure_in_class()
3657 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003658 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003659
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003660 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01003661 var y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003662
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003663 def new()
3664 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3665 enddef
3666 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003667
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003668 Foo.new()
3669 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003670 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003671 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003672enddef
3673
Ernie Rael9ed53752023-12-11 17:40:46 +01003674def Test_construct_object_from_legacy()
3675 # Cannot directly invoke constructor from legacy
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003676 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003677 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003678
Ernie Rael9ed53752023-12-11 17:40:46 +01003679 var newCalled = false
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003680
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003681 class A
Ernie Rael9ed53752023-12-11 17:40:46 +01003682 def new(arg: string)
3683 newCalled = true
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003684 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003685 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003686
Ernie Rael9ed53752023-12-11 17:40:46 +01003687 export def CreateA(...args: list<any>): A
3688 return call(A.new, args)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003689 enddef
3690
Ernie Rael9ed53752023-12-11 17:40:46 +01003691 g:P = CreateA
3692 legacy call g:P('some_arg')
3693 assert_equal(true, newCalled)
3694 unlet g:P
3695 END
3696 v9.CheckSourceSuccess(lines)
3697
3698 lines =<< trim END
3699 vim9script
3700
3701 var newCalled = false
3702
3703 class A
3704 static def CreateA(options = {}): any
3705 return A.new()
3706 enddef
3707 def new()
3708 newCalled = true
3709 enddef
3710 endclass
3711
3712 g:P = A.CreateA
3713 legacy call g:P()
3714 assert_equal(true, newCalled)
3715 unlet g:P
3716 END
3717 v9.CheckSourceSuccess(lines)
3718
3719 # This also tests invoking "new()" with "call"
3720 lines =<< trim END
3721 vim9script
3722
3723 var createdObject: any
3724
3725 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01003726 var val1: number
3727 var val2: number
Ernie Rael9ed53752023-12-11 17:40:46 +01003728 static def CreateA(...args: list<any>): any
3729 createdObject = call(A.new, args)
3730 return createdObject
3731 enddef
3732 endclass
3733
3734 g:P = A.CreateA
3735 legacy call g:P(3, 5)
3736 assert_equal(3, createdObject.val1)
3737 assert_equal(5, createdObject.val2)
3738 legacy call g:P()
3739 assert_equal(0, createdObject.val1)
3740 assert_equal(0, createdObject.val2)
3741 legacy call g:P(7)
3742 assert_equal(7, createdObject.val1)
3743 assert_equal(0, createdObject.val2)
3744 unlet g:P
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003745 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003746 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003747enddef
3748
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003749def Test_defer_with_object()
3750 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003751 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003752
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003753 class CWithEE
3754 def Enter()
3755 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003756 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003757 def Exit()
3758 g:result ..= "exited"
3759 enddef
3760 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003761
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003762 def With(ee: CWithEE, F: func)
3763 ee.Enter()
3764 defer ee.Exit()
3765 F()
3766 enddef
3767
3768 g:result = ''
3769 var obj = CWithEE.new()
3770 obj->With(() => {
3771 g:result ..= "called/"
3772 })
3773 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003774 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003775 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003776 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003777
3778 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003779 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003780
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003781 class BaseWithEE
3782 def Enter()
3783 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003784 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003785 def Exit()
3786 g:result ..= "exited-base"
3787 enddef
3788 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003789
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003790 class CWithEE extends BaseWithEE
3791 def Enter()
3792 g:result ..= "entered-child/"
3793 enddef
3794 def Exit()
3795 g:result ..= "exited-child"
3796 enddef
3797 endclass
3798
3799 def With(ee: BaseWithEE, F: func)
3800 ee.Enter()
3801 defer ee.Exit()
3802 F()
3803 enddef
3804
3805 g:result = ''
3806 var obj = CWithEE.new()
3807 obj->With(() => {
3808 g:result ..= "called/"
3809 })
3810 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003811 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003812 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003813 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003814enddef
3815
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003816" The following test used to crash Vim (Github issue #12676)
3817def Test_extends_method_crashes_vim()
3818 var lines =<< trim END
3819 vim9script
3820
3821 class Observer
3822 endclass
3823
3824 class Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003825 var value: any
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003826
3827 def Set(v: any)
3828 if v != this.value
3829 this.value = v
3830 endif
3831 enddef
3832
3833 def Register(observer: Observer)
3834 enddef
3835 endclass
3836
3837 class Bool extends Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003838 var value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003839 endclass
3840
3841 def Observe(obj: Property, who: Observer)
3842 obj.Register(who)
3843 enddef
3844
3845 var p = Bool.new(false)
3846 var myObserver = Observer.new()
3847
3848 Observe(p, myObserver)
3849
3850 p.Set(true)
3851 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003852 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003853enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003854
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003855" Test for calling a method in a class that is extended
3856def Test_call_method_in_extended_class()
3857 var lines =<< trim END
3858 vim9script
3859
3860 var prop_init_called = false
3861 var prop_register_called = false
3862
3863 class Property
3864 def Init()
3865 prop_init_called = true
3866 enddef
3867
3868 def Register()
3869 prop_register_called = true
3870 enddef
3871 endclass
3872
3873 class Bool extends Property
3874 endclass
3875
3876 def Observe(obj: Property)
3877 obj.Register()
3878 enddef
3879
3880 var p = Property.new()
3881 Observe(p)
3882
3883 p.Init()
3884 assert_true(prop_init_called)
3885 assert_true(prop_register_called)
3886 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003887 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003888enddef
3889
LemonBoyafe04662023-08-23 21:08:11 +02003890def Test_instanceof()
3891 var lines =<< trim END
3892 vim9script
3893
3894 class Base1
3895 endclass
3896
3897 class Base2 extends Base1
3898 endclass
3899
3900 interface Intf1
3901 endinterface
3902
3903 class Mix1 implements Intf1
3904 endclass
3905
3906 class Base3 extends Mix1
3907 endclass
3908
Ernie Rael2025af12023-12-12 16:58:00 +01003909 type AliasBase1 = Base1
3910 type AliasBase2 = Base2
3911 type AliasIntf1 = Intf1
3912 type AliasMix1 = Mix1
3913
LemonBoyafe04662023-08-23 21:08:11 +02003914 var b1 = Base1.new()
3915 var b2 = Base2.new()
3916 var b3 = Base3.new()
3917
3918 assert_true(instanceof(b1, Base1))
3919 assert_true(instanceof(b2, Base1))
3920 assert_false(instanceof(b1, Base2))
3921 assert_true(instanceof(b3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003922 assert_true(instanceof(b3, Base1, Base2, Intf1))
3923
3924 assert_true(instanceof(b1, AliasBase1))
3925 assert_true(instanceof(b2, AliasBase1))
3926 assert_false(instanceof(b1, AliasBase2))
3927 assert_true(instanceof(b3, AliasMix1))
3928 assert_true(instanceof(b3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003929
3930 def Foo()
3931 var a1 = Base1.new()
3932 var a2 = Base2.new()
3933 var a3 = Base3.new()
3934
3935 assert_true(instanceof(a1, Base1))
3936 assert_true(instanceof(a2, Base1))
3937 assert_false(instanceof(a1, Base2))
3938 assert_true(instanceof(a3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003939 assert_true(instanceof(a3, Base1, Base2, Intf1))
3940
3941 assert_true(instanceof(a1, AliasBase1))
3942 assert_true(instanceof(a2, AliasBase1))
3943 assert_false(instanceof(a1, AliasBase2))
3944 assert_true(instanceof(a3, AliasMix1))
3945 assert_true(instanceof(a3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003946 enddef
3947 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003948
3949 var o_null: Base1
3950 assert_false(instanceof(o_null, Base1))
3951
LemonBoyafe04662023-08-23 21:08:11 +02003952 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003953 v9.CheckSourceSuccess(lines)
Ernie Rael2025af12023-12-12 16:58:00 +01003954
3955 lines =<< trim END
3956 vim9script
3957
3958 class Base1
3959 endclass
3960 instanceof(Base1.new())
3961 END
3962 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3963
3964 lines =<< trim END
3965 vim9script
3966
3967 class Base1
3968 endclass
3969 def F()
3970 instanceof(Base1.new())
3971 enddef
3972 F()
3973 END
3974 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3975
3976 lines =<< trim END
3977 vim9script
3978
3979 class Base1
3980 endclass
3981
3982 class Base2
3983 endclass
3984
3985 var o = Base2.new()
3986 instanceof(o, Base1, Base2, 3)
3987 END
3988 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4', 10)
3989
3990 lines =<< trim END
3991 vim9script
3992
3993 class Base1
3994 endclass
3995
3996 class Base2
3997 endclass
3998
3999 def F()
4000 var o = Base2.new()
4001 instanceof(o, Base1, Base2, 3)
4002 enddef
4003 F()
4004 END
4005 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4')
LemonBoyafe04662023-08-23 21:08:11 +02004006enddef
4007
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004008" Test for calling a method in the parent class that is extended partially.
4009" This used to fail with the 'E118: Too many arguments for function: Text' error
4010" message (Github issue #12524).
4011def Test_call_method_in_parent_class()
4012 var lines =<< trim END
4013 vim9script
4014
4015 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01004016 var _lnum: number = 1
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004017
4018 def SetY(lnum: number)
4019 this._lnum = lnum
4020 enddef
4021
4022 def Text(): string
4023 return ''
4024 enddef
4025 endclass
4026
4027 class Foo extends Widget
4028 def Text(): string
4029 return '<Foo>'
4030 enddef
4031 endclass
4032
4033 def Stack(w1: Widget, w2: Widget): list<Widget>
4034 w1.SetY(1)
4035 w2.SetY(2)
4036 return [w1, w2]
4037 enddef
4038
4039 var foo1 = Foo.new()
4040 var foo2 = Foo.new()
4041 var l = Stack(foo1, foo2)
4042 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004043 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004044enddef
4045
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004046" Test for calling methods from three levels of classes
4047def Test_multi_level_method_call()
4048 var lines =<< trim END
4049 vim9script
4050
4051 var A_func1: number = 0
4052 var A_func2: number = 0
4053 var A_func3: number = 0
4054 var B_func2: number = 0
4055 var B_func3: number = 0
4056 var C_func3: number = 0
4057
4058 class A
4059 def Func1()
4060 A_func1 += 1
4061 enddef
4062
4063 def Func2()
4064 A_func2 += 1
4065 enddef
4066
4067 def Func3()
4068 A_func3 += 1
4069 enddef
4070 endclass
4071
4072 class B extends A
4073 def Func2()
4074 B_func2 += 1
4075 enddef
4076
4077 def Func3()
4078 B_func3 += 1
4079 enddef
4080 endclass
4081
4082 class C extends B
4083 def Func3()
4084 C_func3 += 1
4085 enddef
4086 endclass
4087
4088 def A_CallFuncs(a: A)
4089 a.Func1()
4090 a.Func2()
4091 a.Func3()
4092 enddef
4093
4094 def B_CallFuncs(b: B)
4095 b.Func1()
4096 b.Func2()
4097 b.Func3()
4098 enddef
4099
4100 def C_CallFuncs(c: C)
4101 c.Func1()
4102 c.Func2()
4103 c.Func3()
4104 enddef
4105
4106 var cobj = C.new()
4107 A_CallFuncs(cobj)
4108 B_CallFuncs(cobj)
4109 C_CallFuncs(cobj)
4110 assert_equal(3, A_func1)
4111 assert_equal(0, A_func2)
4112 assert_equal(0, A_func3)
4113 assert_equal(3, B_func2)
4114 assert_equal(0, B_func3)
4115 assert_equal(3, C_func3)
4116 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004117 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004118enddef
4119
4120" Test for using members from three levels of classes
4121def Test_multi_level_member_access()
4122 var lines =<< trim END
4123 vim9script
4124
4125 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004126 public var val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004127 endclass
4128
4129 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004130 public var val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004131 endclass
4132
4133 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01004134 public var val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004135 endclass
4136
4137 def A_members(a: A)
4138 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004139 enddef
4140
4141 def B_members(b: B)
4142 b.val1 += 1
4143 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004144 enddef
4145
4146 def C_members(c: C)
4147 c.val1 += 1
4148 c.val2 += 1
4149 c.val3 += 1
4150 enddef
4151
4152 var cobj = C.new()
4153 A_members(cobj)
4154 B_members(cobj)
4155 C_members(cobj)
4156 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004157 assert_equal(2, cobj.val2)
4158 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004159 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004160 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004161enddef
4162
LemonBoy0ffc17a2023-08-20 18:09:11 +02004163" Test expansion of <stack> with class methods.
4164def Test_stack_expansion_with_methods()
4165 var lines =<< trim END
4166 vim9script
4167
4168 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004169 def M1()
4170 F0()
4171 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02004172 endclass
4173
4174 def F0()
Ernie Rael16cdfa62024-04-02 19:05:39 +02004175 assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
LemonBoy0ffc17a2023-08-20 18:09:11 +02004176 enddef
4177
4178 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004179 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02004180 enddef
4181
4182 F()
4183 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004184 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02004185enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004186
4187" Test the return type of the new() constructor
4188def Test_new_return_type()
4189 # new() uses the default return type and there is no return statement
4190 var lines =<< trim END
4191 vim9script
4192
4193 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004194 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004195
4196 def new(this._bufnr)
4197 if !bufexists(this._bufnr)
4198 this._bufnr = -1
4199 endif
4200 enddef
4201 endclass
4202
4203 var c = C.new(12345)
4204 assert_equal('object<C>', typename(c))
4205
4206 var v1: C
4207 v1 = C.new(12345)
4208 assert_equal('object<C>', typename(v1))
4209
4210 def F()
4211 var v2: C
4212 v2 = C.new(12345)
4213 assert_equal('object<C>', typename(v2))
4214 enddef
4215 F()
4216 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004217 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004218
4219 # new() uses the default return type and an empty 'return' statement
4220 lines =<< trim END
4221 vim9script
4222
4223 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004224 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004225
4226 def new(this._bufnr)
4227 if !bufexists(this._bufnr)
4228 this._bufnr = -1
4229 return
4230 endif
4231 enddef
4232 endclass
4233
4234 var c = C.new(12345)
4235 assert_equal('object<C>', typename(c))
4236
4237 var v1: C
4238 v1 = C.new(12345)
4239 assert_equal('object<C>', typename(v1))
4240
4241 def F()
4242 var v2: C
4243 v2 = C.new(12345)
4244 assert_equal('object<C>', typename(v2))
4245 enddef
4246 F()
4247 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004248 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004249
4250 # new() uses "any" return type and returns "this"
4251 lines =<< trim END
4252 vim9script
4253
4254 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004255 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004256
4257 def new(this._bufnr): any
4258 if !bufexists(this._bufnr)
4259 this._bufnr = -1
4260 return this
4261 endif
4262 enddef
4263 endclass
4264 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004265 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004266
4267 # new() uses 'Dict' return type and returns a Dict
4268 lines =<< trim END
4269 vim9script
4270
4271 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004272 var _state: dict<any>
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004273
4274 def new(): dict<any>
4275 this._state = {}
4276 return this._state
4277 enddef
4278 endclass
4279
4280 var c = C.new()
4281 assert_equal('object<C>', typename(c))
4282 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004283 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004284enddef
4285
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004286" Test for checking a member initialization type at run time.
4287def Test_runtime_type_check_for_member_init()
4288 var lines =<< trim END
4289 vim9script
4290
4291 var retnum: bool = false
4292
4293 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004294 retnum = !retnum
4295 if retnum
4296 return 1
4297 else
4298 return "hello"
4299 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004300 enddef
4301
4302 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004303 var _foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004304 endclass
4305
4306 var c1 = C.new()
4307 var c2 = C.new()
4308 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004309 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004310enddef
4311
4312" Test for locking a variable referring to an object and reassigning to another
4313" object.
Ernie Raelee865f32023-09-29 19:53:55 +02004314def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004315 var lines =<< trim END
4316 vim9script
4317
4318 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004319 var val: number
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004320 def new(this.val)
4321 enddef
4322 endclass
4323
4324 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
4325 lockvar 2 some_dict
4326
4327 var current: C
4328 current = some_dict['c']
4329 assert_equal(3, current.val)
4330 current = some_dict['b']
4331 assert_equal(2, current.val)
4332
4333 def F()
4334 current = some_dict['c']
4335 enddef
4336
4337 def G()
4338 current = some_dict['b']
4339 enddef
4340
4341 F()
4342 assert_equal(3, current.val)
4343 G()
4344 assert_equal(2, current.val)
4345 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004346 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004347enddef
4348
Ernie Raelee865f32023-09-29 19:53:55 +02004349" Test trying to lock an object variable from various places
4350def Test_lockvar_object_variable()
4351 # An object variable lockvar has several cases:
4352 # object method, scriptlevel, scriplevel from :def, :def arg
4353 # method arg, static method arg.
4354 # Also different depths
4355
Ernie Raelee865f32023-09-29 19:53:55 +02004356 #
4357 # lockvar of read-only object variable
4358 #
4359
4360 # read-only lockvar from object method
4361 var lines =<< trim END
4362 vim9script
4363
4364 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004365 var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004366 def Lock()
4367 lockvar this.val1
4368 enddef
4369 endclass
4370 var o = C.new(3)
4371 o.Lock()
4372 END
Ernie Rael64885642023-10-04 20:16:22 +02004373 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004374
4375 # read-only lockvar from scriptlevel
4376 lines =<< trim END
4377 vim9script
4378
4379 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004380 var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004381 endclass
4382 var o = C.new(3)
4383 lockvar o.val2
4384 END
4385 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
4386
4387 # read-only lockvar of scriptlevel variable from def
4388 lines =<< trim END
4389 vim9script
4390
4391 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004392 var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004393 endclass
4394 var o = C.new(3)
4395 def Lock()
4396 lockvar o.val3
4397 enddef
4398 Lock()
4399 END
4400 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
4401
4402 # read-only lockvar of def argument variable
4403 lines =<< trim END
4404 vim9script
4405
4406 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004407 var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004408 endclass
4409 def Lock(o: C)
4410 lockvar o.val4
4411 enddef
4412 Lock(C.new(3))
4413 END
4414 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
4415
Ernie Raelee865f32023-09-29 19:53:55 +02004416 # read-only lockvar from object method arg
4417 lines =<< trim END
4418 vim9script
4419
4420 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004421 var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004422 def Lock(c: C)
4423 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004424 enddef
4425 endclass
4426 var o = C.new(3)
4427 o.Lock(C.new(5))
4428 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004429 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004430
4431 # read-only lockvar from class method arg
4432 lines =<< trim END
4433 vim9script
4434
4435 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004436 var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004437 static def Lock(c: C)
4438 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004439 enddef
4440 endclass
4441 var o = C.new(3)
4442 C.Lock(o)
4443 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004444 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004445
4446 #
4447 # lockvar of public object variable
4448 #
4449
4450 # lockvar from object method
4451 lines =<< trim END
4452 vim9script
4453
4454 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004455 public var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004456 def Lock()
4457 lockvar this.val1
4458 enddef
4459 endclass
4460 var o = C.new(3)
4461 o.Lock()
4462 END
4463 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
4464
4465 # lockvar from scriptlevel
4466 lines =<< trim END
4467 vim9script
4468
4469 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004470 public var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004471 endclass
4472 var o = C.new(3)
4473 lockvar o.val2
4474 END
4475 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
4476
4477 # lockvar of scriptlevel variable from def
4478 lines =<< trim END
4479 vim9script
4480
4481 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004482 public var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004483 endclass
4484 var o = C.new(3)
4485 def Lock()
4486 lockvar o.val3
4487 enddef
4488 Lock()
4489 END
4490 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
4491
4492 # lockvar of def argument variable
4493 lines =<< trim END
4494 vim9script
4495
4496 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004497 public var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004498 endclass
4499 def Lock(o: C)
4500 lockvar o.val4
4501 enddef
4502 Lock(C.new(3))
4503 END
4504 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
4505
4506 # lockvar from object method arg
4507 lines =<< trim END
4508 vim9script
4509
4510 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004511 public var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004512 def Lock(c: C)
4513 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004514 enddef
4515 endclass
4516 var o = C.new(3)
4517 o.Lock(C.new(5))
4518 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004519 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004520
4521 # lockvar from class method arg
4522 lines =<< trim END
4523 vim9script
4524
4525 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004526 public var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004527 static def Lock(c: C)
4528 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004529 enddef
4530 endclass
4531 var o = C.new(3)
4532 C.Lock(o)
4533 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004534 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004535enddef
4536
4537" Test trying to lock a class variable from various places
4538def Test_lockvar_class_variable()
4539
4540 # lockvar bare static from object method
4541 var lines =<< trim END
4542 vim9script
4543
4544 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004545 public static var sval1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004546 def Lock()
4547 lockvar sval1
4548 enddef
4549 endclass
4550 var o = C.new()
4551 o.Lock()
4552 END
4553 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
4554
4555 # lockvar C.static from object method
4556 lines =<< trim END
4557 vim9script
4558
4559 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004560 public static var sval2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004561 def Lock()
4562 lockvar C.sval2
4563 enddef
4564 endclass
4565 var o = C.new()
4566 o.Lock()
4567 END
4568 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
4569
4570 # lockvar bare static from class method
4571 lines =<< trim END
4572 vim9script
4573
4574 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004575 public static var sval3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004576 static def Lock()
4577 lockvar sval3
4578 enddef
4579 endclass
4580 C.Lock()
4581 END
4582 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
4583
4584 # lockvar C.static from class method
4585 lines =<< trim END
4586 vim9script
4587
4588 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004589 public static var sval4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004590 static def Lock()
4591 lockvar C.sval4
4592 enddef
4593 endclass
4594 C.Lock()
4595 END
4596 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
4597
4598 # lockvar C.static from script level
4599 lines =<< trim END
4600 vim9script
4601
4602 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004603 public static var sval5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004604 endclass
4605 lockvar C.sval5
4606 END
4607 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
4608
4609 # lockvar o.static from script level
4610 lines =<< trim END
4611 vim9script
4612
4613 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004614 public static var sval6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004615 endclass
4616 var o = C.new()
4617 lockvar o.sval6
4618 END
4619 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
4620enddef
4621
4622" Test locking an argument to :def
4623def Test_lockvar_argument()
4624 # Lockvar a function arg
4625 var lines =<< trim END
4626 vim9script
4627
4628 def Lock(val: any)
4629 lockvar val
4630 enddef
4631
4632 var d = {a: 1, b: 2}
4633 Lock(d)
4634
4635 d->extend({c: 3})
4636 END
4637 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
4638
4639 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
4640 # class member in "C". This tests lval_root_is_arg.
4641 lines =<< trim END
4642 vim9script
4643
4644 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004645 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004646 endclass
4647
4648 def Lock2(sval: any)
4649 lockvar sval
4650 enddef
4651
4652 var o = C.new()
4653 Lock2(o)
4654 END
4655 v9.CheckSourceSuccess(lines)
4656
4657 # Lock a class.
4658 lines =<< trim END
4659 vim9script
4660
4661 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004662 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004663 endclass
4664
4665 def Lock2(sval: any)
4666 lockvar sval
4667 enddef
4668
4669 Lock2(C)
4670 END
Ernie Raelb077b582023-12-14 20:11:44 +01004671 v9.CheckSourceFailure(lines, 'E1405: Class "C" cannot be used as a value')
Ernie Raelee865f32023-09-29 19:53:55 +02004672
4673 # Lock an object.
4674 lines =<< trim END
4675 vim9script
4676
4677 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004678 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004679 endclass
4680
4681 def Lock2(sval: any)
4682 lockvar sval
4683 enddef
4684
4685 Lock2(C.new())
4686 END
4687 v9.CheckSourceSuccess(lines)
4688
4689 # In this case (unlike previous) "lockvar sval" is a class member.
4690 lines =<< trim END
4691 vim9script
4692
4693 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004694 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004695 def Lock2()
4696 lockvar sval
4697 enddef
4698 endclass
4699
4700
4701 var o = C.new()
4702 o.Lock2()
4703 END
4704 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4705enddef
4706
4707" Test that this can be locked without error
4708def Test_lockvar_this()
4709 # lockvar this
4710 var lines =<< trim END
4711 vim9script
4712 class C
4713 def TLock()
4714 lockvar this
4715 enddef
4716 endclass
4717 var o = C.new()
4718 o.TLock()
4719 END
4720 v9.CheckSourceSuccess(lines)
4721
4722 # lockvar four (four letter word, but not this)
4723 lines =<< trim END
4724 vim9script
4725 class C
4726 def TLock4()
4727 var four: number
4728 lockvar four
4729 enddef
4730 endclass
4731 var o = C.new()
4732 o.TLock4()
4733 END
4734 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4735
4736 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4737 lines =<< trim END
4738 vim9script
4739 class C
4740 def TLock5()
4741 var this5: number
4742 lockvar this5
4743 enddef
4744 endclass
4745 var o = C.new()
4746 o.TLock5()
4747 END
4748 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4749enddef
4750
4751" Test some general lockvar cases
4752def Test_lockvar_general()
4753 # lockvar an object and a class. It does nothing
4754 var lines =<< trim END
4755 vim9script
4756 class C
4757 endclass
4758 var o = C.new()
4759 lockvar o
4760 lockvar C
4761 END
4762 v9.CheckSourceSuccess(lines)
4763
4764 # Lock a list element that's nested in an object variable from a :def
4765 lines =<< trim END
4766 vim9script
4767
4768 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004769 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004770 endclass
4771 def Lock2(obj: any)
4772 lockvar obj.val[1]
4773 enddef
4774
4775 var o = C.new()
4776 Lock2(o)
4777 o.val[0] = [9]
4778 assert_equal([ [9], [2], [3] ], o.val)
4779 try
4780 o.val[1] = [999]
4781 call assert_false(true, 'assign should have failed')
4782 catch
4783 assert_exception('E741:')
4784 endtry
4785 o.val[2] = [8]
4786 assert_equal([ [9], [2], [8] ], o.val)
4787 END
4788 v9.CheckSourceSuccess(lines)
4789
4790 # Lock a list element that's nested in an object variable from scriptlevel
4791 lines =<< trim END
4792 vim9script
4793
4794 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004795 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004796 endclass
4797
4798 var o = C.new()
4799 lockvar o.val[1]
4800 o.val[0] = [9]
4801 assert_equal([ [9], [2], [3] ], o.val)
4802 try
4803 o.val[1] = [999]
4804 call assert_false(true, 'assign should have failed')
4805 catch
4806 assert_exception('E741:')
4807 endtry
4808 o.val[2] = [8]
4809 assert_equal([ [9], [2], [8] ], o.val)
4810 END
4811 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004812
4813 # lock a script level variable from an object method
4814 lines =<< trim END
4815 vim9script
4816
4817 class C
4818 def Lock()
4819 lockvar l
4820 enddef
4821 endclass
4822
4823 var l = [1]
4824 C.new().Lock()
4825 l[0] = 11
4826 END
4827 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4828
Ernie Rael03042a22023-11-11 08:53:32 +01004829 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004830 # in an object fetched via a script level list
4831 lines =<< trim END
4832 vim9script
4833
4834 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004835 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004836 def Lock()
4837 lockvar lc[0]._v1[1]
4838 enddef
4839 endclass
4840
4841 var l = [[1], [2], [3]]
4842 var o = C.new(l)
4843 var lc: list<C> = [ o ]
4844
4845 o.Lock()
4846 l[0] = [22]
4847 l[1] = [33]
4848 END
4849 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4850
4851 # similar to the previous test, except the locking code is executing
Ernie Rael03042a22023-11-11 08:53:32 +01004852 # in a class that does not own the protected variable.
4853 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02004854 # the same name.
4855 lines =<< trim END
4856 vim9script
4857
4858 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004859 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004860 def Lock(obj: any)
4861 lockvar lc[0]._v1[1]
4862 enddef
4863 endclass
4864
4865 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004866 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004867 endclass
4868
4869 var l = [[1], [2], [3]]
4870 var o = C.new(l)
4871 var lc: list<C> = [ o ]
4872
4873 var o2 = C2.new()
4874 o2.Lock(o)
4875 END
Ernie Rael03042a22023-11-11 08:53:32 +01004876 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004877enddef
4878
Ernie Rael9771b2a2023-10-07 22:05:40 +02004879" Test builtin islocked()
4880def Test_lockvar_islocked()
4881 # Can't lock class/object variable
4882 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01004883 # Lock item of variable's value (a list item)
4884 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02004885 var lines =<< trim END
4886 vim9script
4887
4888 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004889 var o0: list<list<number>> = [ [0], [1], [2]]
4890 var o1: list<list<number>> = [[10], [11], [12]]
4891 static var c0: list<list<number>> = [[20], [21], [22]]
4892 static var c1: list<list<number>> = [[30], [31], [32]]
Ernie Rael9771b2a2023-10-07 22:05:40 +02004893 endclass
4894
4895 def LockIt(arg: any)
4896 lockvar arg
4897 enddef
4898
4899 def UnlockIt(arg: any)
4900 unlockvar arg
4901 enddef
4902
4903 var obj = C.new()
4904 #lockvar obj.o1 # can't lock something you can't write to
4905
4906 try
4907 lockvar obj.o1 # can't lock something you can't write to
4908 call assert_false(1, '"lockvar obj.o1" should have failed')
4909 catch
4910 call assert_exception('E1335:')
4911 endtry
4912
4913 LockIt(obj.o1) # but can lock it's value
4914 assert_equal(1, islocked("obj.o1"))
4915 assert_equal(1, islocked("obj.o1[0]"))
4916 assert_equal(1, islocked("obj.o1[1]"))
4917 UnlockIt(obj.o1)
4918 assert_equal(0, islocked("obj.o1"))
4919 assert_equal(0, islocked("obj.o1[0]"))
4920
4921 lockvar obj.o1[0]
4922 assert_equal(0, islocked("obj.o1"))
4923 assert_equal(1, islocked("obj.o1[0]"))
4924 assert_equal(0, islocked("obj.o1[1]"))
4925 unlockvar obj.o1[0]
4926 assert_equal(0, islocked("obj.o1"))
4927 assert_equal(0, islocked("obj.o1[0]"))
4928
4929 # Same thing, but with a static
4930
4931 try
4932 lockvar C.c1 # can't lock something you can't write to
4933 call assert_false(1, '"lockvar C.c1" should have failed')
4934 catch
4935 call assert_exception('E1335:')
4936 endtry
4937
4938 LockIt(C.c1) # but can lock it's value
4939 assert_equal(1, islocked("C.c1"))
4940 assert_equal(1, islocked("C.c1[0]"))
4941 assert_equal(1, islocked("C.c1[1]"))
4942 UnlockIt(C.c1)
4943 assert_equal(0, islocked("C.c1"))
4944 assert_equal(0, islocked("C.c1[0]"))
4945
4946 lockvar C.c1[0]
4947 assert_equal(0, islocked("C.c1"))
4948 assert_equal(1, islocked("C.c1[0]"))
4949 assert_equal(0, islocked("C.c1[1]"))
4950 unlockvar C.c1[0]
4951 assert_equal(0, islocked("C.c1"))
4952 assert_equal(0, islocked("C.c1[0]"))
4953 END
4954 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02004955
4956 # Do islocked() from an object method
4957 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02004958 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02004959 vim9script
4960
4961 var l0o0 = [ [0], [1], [2]]
4962 var l0o1 = [ [10], [11], [12]]
4963 var l0c0 = [[120], [121], [122]]
4964 var l0c1 = [[130], [131], [132]]
4965
4966 class C0
Doug Kearns74da0ee2023-12-14 20:26:26 +01004967 var o0: list<list<number>> = l0o0
4968 var o1: list<list<number>> = l0o1
4969 static var c0: list<list<number>> = l0c0
4970 static var c1: list<list<number>> = l0c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004971 def Islocked(arg: string): number
4972 return islocked(arg)
4973 enddef
4974 static def SIslocked(arg: string): number
4975 return islocked(arg)
4976 enddef
4977 endclass
4978
4979 var l2o0 = [[20000], [20001], [20002]]
4980 var l2o1 = [[20010], [20011], [20012]]
4981 var l2c0 = [[20120], [20121], [20122]]
4982 var l2c1 = [[20130], [20131], [20132]]
4983
4984 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004985 var o0: list<list<number>> = l2o0
4986 var o1: list<list<number>> = l2o1
4987 static var c0: list<list<number>> = l2c0
4988 static var c1: list<list<number>> = l2c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004989 def Islocked(arg: string): number
4990 return islocked(arg)
4991 enddef
4992 static def SIslocked(arg: string): number
4993 return islocked(arg)
4994 enddef
4995 endclass
4996
4997 var obj0 = C0.new()
4998 var obj2 = C2.new()
4999
5000 var l = [ obj0, null_object, obj2 ]
5001
5002 # lock list, object func access through script var expr
5003 assert_equal(0, obj0.Islocked("l[0].o0"))
5004 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
5005 lockvar l0o0
5006 assert_equal(1, obj0.Islocked("l[0].o0"))
5007 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
5008
5009 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
5010
5011 # lock list element, object func access through script var expr
5012 lockvar l0o1[1]
5013 assert_equal(0, obj0.Islocked("this.o1[0]"))
5014 assert_equal(1, obj0.Islocked("this.o1[1]"))
5015
5016 assert_equal(0, obj0.Islocked("this.o1"))
5017 lockvar l0o1
5018 assert_equal(1, obj0.Islocked("this.o1"))
5019 unlockvar l0o1
5020
5021 lockvar l0c1[1]
5022
5023 # static by class name member expr from same class
5024 assert_equal(0, obj0.Islocked("C0.c1[0]"))
5025 assert_equal(1, obj0.Islocked("C0.c1[1]"))
5026 # static by bare name member expr from same class
5027 assert_equal(0, obj0.Islocked("c1[0]"))
5028 assert_equal(1, obj0.Islocked("c1[1]"))
5029
5030 # static by class name member expr from other class
5031 assert_equal(0, obj2.Islocked("C0.c1[0]"))
5032 assert_equal(1, obj2.Islocked("C0.c1[1]"))
5033 # static by bare name member expr from other class
5034 assert_equal(0, obj2.Islocked("c1[0]"))
5035 assert_equal(0, obj2.Islocked("c1[1]"))
5036
5037
5038 # static by bare name in same class
5039 assert_equal(0, obj0.Islocked("c0"))
5040 lockvar l0c0
5041 assert_equal(1, obj0.Islocked("c0"))
5042
5043 #
5044 # similar stuff, but use static method
5045 #
5046
5047 unlockvar l0o0
5048
5049 # lock list, object func access through script var expr
5050 assert_equal(0, C0.SIslocked("l[0].o0"))
5051 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
5052 lockvar l0o0
5053 assert_equal(1, C0.SIslocked("l[0].o0"))
5054 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
5055
5056 unlockvar l0o1
5057
5058 # can't access "this" from class method
5059 try
5060 C0.SIslocked("this.o1[0]")
5061 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
5062 catch
5063 call assert_exception('E121: Undefined variable: this')
5064 endtry
5065
5066 lockvar l0c1[1]
5067
5068 # static by class name member expr from same class
5069 assert_equal(0, C0.SIslocked("C0.c1[0]"))
5070 assert_equal(1, C0.SIslocked("C0.c1[1]"))
5071 # static by bare name member expr from same class
5072 assert_equal(0, C0.SIslocked("c1[0]"))
5073 assert_equal(1, C0.SIslocked("c1[1]"))
5074
5075 # static by class name member expr from other class
5076 assert_equal(0, C2.SIslocked("C0.c1[0]"))
5077 assert_equal(1, C2.SIslocked("C0.c1[1]"))
5078 # static by bare name member expr from other class
5079 assert_equal(0, C2.SIslocked("c1[0]"))
5080 assert_equal(0, C2.SIslocked("c1[1]"))
5081
5082
5083 # static by bare name in same class
5084 unlockvar l0c0
5085 assert_equal(0, C0.SIslocked("c0"))
5086 lockvar l0c0
5087 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02005088 END
Ernie Rael4c8da022023-10-11 21:35:11 +02005089 v9.CheckSourceSuccess(lines)
5090
5091 # Check islocked class/object from various places.
5092 lines =<< trim END
5093 vim9script
5094
5095 class C
5096 def Islocked(arg: string): number
5097 return islocked(arg)
5098 enddef
5099 static def SIslocked(arg: string): number
5100 return islocked(arg)
5101 enddef
5102 endclass
5103 var obj = C.new()
5104
5105 # object method
5106 assert_equal(0, obj.Islocked("this"))
5107 assert_equal(0, obj.Islocked("C"))
5108
5109 # class method
5110 ### assert_equal(0, C.SIslocked("this"))
5111 assert_equal(0, C.SIslocked("C"))
5112
5113 #script level
5114 var v: number
5115 v = islocked("C")
5116 assert_equal(0, v)
5117 v = islocked("obj")
5118 assert_equal(0, v)
5119 END
5120 v9.CheckSourceSuccess(lines)
5121enddef
5122
5123def Test_lockvar_islocked_notfound()
5124 # Try non-existent things
5125 var lines =<< trim END
5126 vim9script
5127
5128 class C
5129 def Islocked(arg: string): number
5130 return islocked(arg)
5131 enddef
5132 static def SIslocked(arg: string): number
5133 return islocked(arg)
5134 enddef
5135 endclass
5136 var obj = C.new()
5137 assert_equal(-1, obj.Islocked("anywhere"))
5138 assert_equal(-1, C.SIslocked("notanywhere"))
5139 END
5140 v9.CheckSourceSuccess(lines)
5141
5142 # Something not found of the form "name1.name2" is an error
5143 lines =<< trim END
5144 vim9script
5145
5146 islocked("one.two")
5147 END
5148 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
5149
5150 lines =<< trim END
5151 vim9script
5152
5153 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005154 var val = { key: "value" }
Ernie Rael4c8da022023-10-11 21:35:11 +02005155 def Islocked(arg: string): number
5156 return islocked(arg)
5157 enddef
5158 endclass
5159 var obj = C.new()
5160 obj.Islocked("this.val.not_there"))
5161 END
5162 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
5163
5164 lines =<< trim END
5165 vim9script
5166
5167 class C
5168 def Islocked(arg: string): number
5169 return islocked(arg)
5170 enddef
5171 endclass
5172 var obj = C.new()
5173 obj.Islocked("this.notobjmember")
5174 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005175 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02005176
5177 # access a script variable through methods
5178 lines =<< trim END
5179 vim9script
5180
5181 var l = [1]
5182 class C
5183 def Islocked(arg: string): number
5184 return islocked(arg)
5185 enddef
5186 static def SIslocked(arg: string): number
5187 return islocked(arg)
5188 enddef
5189 endclass
5190 var obj = C.new()
5191 assert_equal(0, obj.Islocked("l"))
5192 assert_equal(0, C.SIslocked("l"))
5193 lockvar l
5194 assert_equal(1, obj.Islocked("l"))
5195 assert_equal(1, C.SIslocked("l"))
5196 END
5197 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02005198enddef
5199
Ernie Rael03042a22023-11-11 08:53:32 +01005200" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005201def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005202 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005203 var lines =<< trim END
5204 vim9script
5205
5206 class A
5207 def _Foo(): number
5208 return 1234
5209 enddef
5210 endclass
5211 var a = A.new()
5212 a._Foo()
5213 END
Ernie Rael03042a22023-11-11 08:53:32 +01005214 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005215
Ernie Rael03042a22023-11-11 08:53:32 +01005216 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005217 lines =<< trim END
5218 vim9script
5219
5220 class A
5221 def _Foo(): number
5222 return 1234
5223 enddef
5224 endclass
5225 def T()
5226 var a = A.new()
5227 a._Foo()
5228 enddef
5229 T()
5230 END
Ernie Rael03042a22023-11-11 08:53:32 +01005231 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005232
Ernie Rael03042a22023-11-11 08:53:32 +01005233 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005234 lines =<< trim END
5235 vim9script
5236
5237 class A
5238 def _Foo(): number
5239 return 1234
5240 enddef
5241 def Bar(): number
5242 return this._Foo()
5243 enddef
5244 endclass
5245 var a = A.new()
5246 assert_equal(1234, a.Bar())
5247 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005248 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005249
Ernie Rael03042a22023-11-11 08:53:32 +01005250 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005251 lines =<< trim END
5252 vim9script
5253
5254 class A
5255 def _Foo(): number
5256 return 1234
5257 enddef
5258 def Bar(): number
5259 return this._Foo()
5260 enddef
5261 endclass
5262 def T()
5263 var a = A.new()
5264 assert_equal(1234, a.Bar())
5265 enddef
5266 T()
5267 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005268 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005269
Ernie Rael03042a22023-11-11 08:53:32 +01005270 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005271 lines =<< trim END
5272 vim9script
5273
5274 class A
5275 def _Foo(): number
5276 return 1234
5277 enddef
5278 def Bar(): number
5279 return _Foo()
5280 enddef
5281 endclass
5282 var a = A.new()
5283 a.Bar()
5284 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005285 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005286
Ernie Rael03042a22023-11-11 08:53:32 +01005287 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005288 lines =<< trim END
5289 vim9script
5290
5291 class A
5292 def _Foo(): number
5293 return 1234
5294 enddef
5295 endclass
5296 A._Foo()
5297 END
Ernie Rael03042a22023-11-11 08:53:32 +01005298 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005299
Ernie Rael03042a22023-11-11 08:53:32 +01005300 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005301 lines =<< trim END
5302 vim9script
5303
5304 class A
5305 def _Foo()
5306 enddef
5307 def _Foo()
5308 enddef
5309 endclass
5310 var a = A.new()
5311 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005312 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005313
Ernie Rael03042a22023-11-11 08:53:32 +01005314 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005315 lines =<< trim END
5316 vim9script
5317
5318 class A
5319 def _Foo()
5320 enddef
5321 def Foo()
5322 enddef
5323 endclass
5324 var a = A.new()
5325 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005326 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005327
Ernie Rael03042a22023-11-11 08:53:32 +01005328 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005329 lines =<< trim END
5330 vim9script
5331
5332 class A
5333 def Foo()
5334 enddef
5335 def _Foo()
5336 enddef
5337 endclass
5338 var a = A.new()
5339 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005340 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005341
Ernie Rael03042a22023-11-11 08:53:32 +01005342 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005343 lines =<< trim END
5344 vim9script
5345
5346 class A
5347 def Foo(): number
5348 return 100
5349 enddef
5350 def _Bar(): number
5351 return 200
5352 enddef
5353 def _Baz()
5354 assert_equal(100, this.Foo())
5355 assert_equal(200, this._Bar())
5356 enddef
5357 def T()
5358 this._Baz()
5359 enddef
5360 endclass
5361 var a = A.new()
5362 a.T()
5363 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005364 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005365
Ernie Rael03042a22023-11-11 08:53:32 +01005366 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005367 lines =<< trim END
5368 vim9script
5369
5370 class A
5371 def _Foo(): number
5372 return 100
5373 enddef
5374 endclass
5375 class B
5376 def Foo(): number
5377 var a = A.new()
5378 a._Foo()
5379 enddef
5380 endclass
5381 var b = B.new()
5382 b.Foo()
5383 END
Ernie Rael03042a22023-11-11 08:53:32 +01005384 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005385
Ernie Rael03042a22023-11-11 08:53:32 +01005386 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005387 lines =<< trim END
5388 vim9script
5389 class A
5390 def _Foo(): number
5391 return 1234
5392 enddef
5393 endclass
5394 class B extends A
5395 def Bar()
5396 enddef
5397 endclass
5398 class C extends B
5399 def Baz(): number
5400 return this._Foo()
5401 enddef
5402 endclass
5403 var c = C.new()
5404 assert_equal(1234, c.Baz())
5405 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005406 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005407
Ernie Rael03042a22023-11-11 08:53:32 +01005408 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005409 lines =<< trim END
5410 vim9script
5411 class A
5412 def _Foo(): number
5413 return 1234
5414 enddef
5415 endclass
5416 class B extends A
5417 def Bar()
5418 enddef
5419 endclass
5420 class C extends B
5421 def Baz(): number
5422 enddef
5423 endclass
5424 var c = C.new()
5425 assert_equal(1234, c._Foo())
5426 END
Ernie Rael03042a22023-11-11 08:53:32 +01005427 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005428
5429 # Using "_" prefix in a method name should fail outside of a class
5430 lines =<< trim END
5431 vim9script
5432 def _Foo(): number
5433 return 1234
5434 enddef
5435 var a = _Foo()
5436 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005437 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005438enddef
5439
Ernie Rael03042a22023-11-11 08:53:32 +01005440" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005441def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005442 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005443 var lines =<< trim END
5444 vim9script
5445
5446 class A
5447 static def _Foo(): number
5448 return 1234
5449 enddef
5450 endclass
5451 A._Foo()
5452 END
Ernie Rael03042a22023-11-11 08:53:32 +01005453 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005454
Ernie Rael03042a22023-11-11 08:53:32 +01005455 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005456 lines =<< trim END
5457 vim9script
5458
5459 class A
5460 static def _Foo(): number
5461 return 1234
5462 enddef
5463 endclass
5464 def T()
5465 A._Foo()
5466 enddef
5467 T()
5468 END
Ernie Rael03042a22023-11-11 08:53:32 +01005469 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005470
Ernie Rael03042a22023-11-11 08:53:32 +01005471 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005472 lines =<< trim END
5473 vim9script
5474
5475 class A
5476 static def _Foo(): number
5477 return 1234
5478 enddef
5479 endclass
5480 var a = A.new()
5481 a._Foo()
5482 END
Ernie Rael03042a22023-11-11 08:53:32 +01005483 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005484
Ernie Rael03042a22023-11-11 08:53:32 +01005485 # Try calling a class protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005486 lines =<< trim END
5487 vim9script
5488
5489 class A
5490 static def _Foo(): number
5491 return 1234
5492 enddef
5493 endclass
5494 def T()
5495 var a = A.new()
5496 a._Foo()
5497 enddef
5498 T()
5499 END
Ernie Rael03042a22023-11-11 08:53:32 +01005500 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005501
Ernie Rael03042a22023-11-11 08:53:32 +01005502 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005503 lines =<< trim END
5504 vim9script
5505
5506 class A
5507 static def _Foo(): number
5508 return 1234
5509 enddef
5510 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005511 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005512 enddef
5513 endclass
5514 var a = A.new()
5515 a.Bar()
5516 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005517 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005518
Ernie Rael03042a22023-11-11 08:53:32 +01005519 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005520 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005521 lines =<< trim END
5522 vim9script
5523
5524 class A
5525 static def _Foo1(): number
5526 return 1234
5527 enddef
5528 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005529 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005530 enddef
5531 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005532 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005533 enddef
5534 endclass
5535 var a = A.new()
5536 a.Bar()
5537 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005538 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005539
Ernie Rael03042a22023-11-11 08:53:32 +01005540 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005541 lines =<< trim END
5542 vim9script
5543
5544 class A
5545 static def _Foo()
5546 enddef
5547 static def Foo()
5548 enddef
5549 endclass
5550 var a = A.new()
5551 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005552 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005553
Ernie Rael03042a22023-11-11 08:53:32 +01005554 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005555 lines =<< trim END
5556 vim9script
5557
5558 class A
5559 static def _Foo(): number
5560 return 1234
5561 enddef
5562 endclass
5563 class B
5564 def Foo(): number
5565 return A._Foo()
5566 enddef
5567 endclass
5568 var b = B.new()
5569 assert_equal(1234, b.Foo())
5570 END
Ernie Rael03042a22023-11-11 08:53:32 +01005571 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005572
Ernie Rael03042a22023-11-11 08:53:32 +01005573 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005574 lines =<< trim END
5575 vim9script
5576 class A
5577 static def _Foo(): number
5578 return 1234
5579 enddef
5580 endclass
5581 class B extends A
5582 def Bar()
5583 enddef
5584 endclass
5585 class C extends B
5586 def Baz(): number
5587 return A._Foo()
5588 enddef
5589 endclass
5590 var c = C.new()
5591 assert_equal(1234, c.Baz())
5592 END
Ernie Rael03042a22023-11-11 08:53:32 +01005593 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005594
Ernie Rael03042a22023-11-11 08:53:32 +01005595 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005596 lines =<< trim END
5597 vim9script
5598 class A
5599 static def _Foo(): number
5600 return 1234
5601 enddef
5602 endclass
5603 class B extends A
5604 def Bar()
5605 enddef
5606 endclass
5607 class C extends B
5608 static def Baz(): number
5609 return A._Foo()
5610 enddef
5611 endclass
5612 assert_equal(1234, C.Baz())
5613 END
Ernie Rael03042a22023-11-11 08:53:32 +01005614 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005615
Ernie Rael03042a22023-11-11 08:53:32 +01005616 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005617 lines =<< trim END
5618 vim9script
5619 class A
5620 static def _Foo(): number
5621 return 1234
5622 enddef
5623 endclass
5624 class B extends A
5625 def Bar()
5626 enddef
5627 endclass
5628 class C extends B
5629 def Baz(): number
5630 enddef
5631 endclass
5632 var c = C.new()
5633 assert_equal(1234, C._Foo())
5634 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005635 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005636enddef
5637
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005638" Test for using the return value of a class/object method as a function
5639" argument.
5640def Test_objmethod_funcarg()
5641 var lines =<< trim END
5642 vim9script
5643
5644 class C
5645 def Foo(): string
5646 return 'foo'
5647 enddef
5648 endclass
5649
5650 def Bar(a: number, s: string): string
5651 return s
5652 enddef
5653
5654 def Baz(c: C)
5655 assert_equal('foo', Bar(10, c.Foo()))
5656 enddef
5657
5658 var t = C.new()
5659 Baz(t)
5660 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005661 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005662
5663 lines =<< trim END
5664 vim9script
5665
5666 class C
5667 static def Foo(): string
5668 return 'foo'
5669 enddef
5670 endclass
5671
5672 def Bar(a: number, s: string): string
5673 return s
5674 enddef
5675
5676 def Baz()
5677 assert_equal('foo', Bar(10, C.Foo()))
5678 enddef
5679
5680 Baz()
5681 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005682 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005683enddef
5684
Ernie Raelcf138d42023-09-06 20:45:03 +02005685def Test_static_inheritence()
5686 # subclasses get their own static copy
5687 var lines =<< trim END
5688 vim9script
5689
5690 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005691 static var _svar: number
5692 var _mvar: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005693 def new()
5694 _svar = 1
5695 this._mvar = 101
5696 enddef
5697 def AccessObject(): number
5698 return this._mvar
5699 enddef
5700 def AccessStaticThroughObject(): number
5701 return _svar
5702 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005703 endclass
5704
5705 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005706 def new()
5707 this._mvar = 102
5708 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005709 endclass
5710
5711 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005712 def new()
5713 this._mvar = 103
5714 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005715
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005716 def AccessPrivateStaticThroughClassName(): number
5717 assert_equal(1, A._svar)
5718 return 444
5719 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005720 endclass
5721
5722 var oa = A.new()
5723 var ob = B.new()
5724 var oc = C.new()
5725 assert_equal(101, oa.AccessObject())
5726 assert_equal(102, ob.AccessObject())
5727 assert_equal(103, oc.AccessObject())
5728
Ernie Rael03042a22023-11-11 08:53:32 +01005729 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005730
5731 # verify object properly resolves to correct static
5732 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005733 assert_equal(1, ob.AccessStaticThroughObject())
5734 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005735 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005736 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005737enddef
5738
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005739" Test for declaring duplicate object and class members
5740def Test_dup_member_variable()
5741 # Duplicate member variable
5742 var lines =<< trim END
5743 vim9script
5744 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005745 var val = 10
5746 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005747 endclass
5748 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005749 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005750
Ernie Rael03042a22023-11-11 08:53:32 +01005751 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005752 lines =<< trim END
5753 vim9script
5754 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005755 var _val = 10
5756 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005757 endclass
5758 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005759 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005760
5761 # Duplicate public member variable
5762 lines =<< trim END
5763 vim9script
5764 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005765 public var val = 10
5766 public var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005767 endclass
5768 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005769 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005770
Ernie Rael03042a22023-11-11 08:53:32 +01005771 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005772 lines =<< trim END
5773 vim9script
5774 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005775 var val = 10
5776 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005777 endclass
5778 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005779 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005780
Ernie Rael03042a22023-11-11 08:53:32 +01005781 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005782 lines =<< trim END
5783 vim9script
5784 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005785 var _val = 20
5786 public var val = 10
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005787 endclass
5788 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005789 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005790
5791 # Duplicate class member variable
5792 lines =<< trim END
5793 vim9script
5794 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005795 static var s: string = "abc"
5796 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005797 endclass
5798 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005799 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005800
Ernie Rael03042a22023-11-11 08:53:32 +01005801 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005802 lines =<< trim END
5803 vim9script
5804 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005805 public static var s: string = "abc"
5806 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005807 endclass
5808 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005809 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005810
5811 # Duplicate class and object member variable
5812 lines =<< trim END
5813 vim9script
5814 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005815 static var val = 10
5816 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005817 def new()
5818 enddef
5819 endclass
5820 var c = C.new()
5821 assert_equal(10, C.val)
5822 assert_equal(20, c.val)
5823 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005824 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005825
5826 # Duplicate object member variable in a derived class
5827 lines =<< trim END
5828 vim9script
5829 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005830 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005831 endclass
5832 class B extends A
5833 endclass
5834 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005835 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005836 endclass
5837 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005838 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005839
Ernie Rael03042a22023-11-11 08:53:32 +01005840 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005841 lines =<< trim END
5842 vim9script
5843 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005844 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005845 endclass
5846 class B extends A
5847 endclass
5848 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005849 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005850 endclass
5851 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005852 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005853
Ernie Rael03042a22023-11-11 08:53:32 +01005854 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005855 lines =<< trim END
5856 vim9script
5857 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005858 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005859 endclass
5860 class B extends A
5861 endclass
5862 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005863 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005864 endclass
5865 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005866 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005867
5868 # Duplicate object member variable in a derived class
5869 lines =<< trim END
5870 vim9script
5871 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005872 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005873 endclass
5874 class B extends A
5875 endclass
5876 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005877 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005878 endclass
5879 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005880 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005881
5882 # Two member variables with a common prefix
5883 lines =<< trim END
5884 vim9script
5885 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005886 public static var svar2: number
5887 public static var svar: number
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005888 endclass
5889 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005890 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005891enddef
5892
Ernie Rael03042a22023-11-11 08:53:32 +01005893" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005894def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01005895 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005896 var lines =<< trim END
5897 vim9script
5898 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005899 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005900 def GetVal(): number
5901 return this._val
5902 enddef
5903 endclass
5904 def T()
5905 var a = A.new()
5906 a._val = 20
5907 enddef
5908 T()
5909 END
Ernie Rael03042a22023-11-11 08:53:32 +01005910 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005911
Ernie Rael03042a22023-11-11 08:53:32 +01005912 # access a non-existing protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005913 lines =<< trim END
5914 vim9script
5915 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005916 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005917 endclass
5918 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005919 var a = A.new()
5920 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005921 enddef
5922 T()
5923 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005924 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005925
Ernie Rael03042a22023-11-11 08:53:32 +01005926 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005927 lines =<< trim END
5928 vim9script
5929 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005930 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005931 endclass
5932 def T()
5933 var a = A.new()
5934 var x = a._val
5935 enddef
5936 T()
5937 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005938 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005939
Ernie Rael03042a22023-11-11 08:53:32 +01005940 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005941 lines =<< trim END
5942 vim9script
5943 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005944 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005945 endclass
5946 def T()
5947 var a = A.new()
5948 a._val = 3
5949 enddef
5950 T()
5951 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005952 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005953
Ernie Rael03042a22023-11-11 08:53:32 +01005954 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005955 lines =<< trim END
5956 vim9script
5957 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005958 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005959 endclass
5960 def T()
5961 var x = A._val
5962 enddef
5963 T()
5964 END
Ernie Rael03042a22023-11-11 08:53:32 +01005965 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02005966
Ernie Rael03042a22023-11-11 08:53:32 +01005967 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005968 lines =<< trim END
5969 vim9script
5970 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005971 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005972 endclass
5973 def T()
5974 A._val = 3
5975 enddef
5976 T()
5977 END
Ernie Rael03042a22023-11-11 08:53:32 +01005978 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005979enddef
5980
5981" Test for changing the member access of an interface in a implementation class
5982def Test_change_interface_member_access()
5983 var lines =<< trim END
5984 vim9script
5985 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005986 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005987 endinterface
5988 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005989 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005990 endclass
5991 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005992 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005993
5994 lines =<< trim END
5995 vim9script
5996 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005997 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005998 endinterface
5999 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006000 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006001 endclass
6002 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006003 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006004enddef
6005
6006" Test for trying to change a readonly member from a def function
6007def Test_readonly_member_change_in_def_func()
6008 var lines =<< trim END
6009 vim9script
6010 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006011 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006012 endclass
6013 def T()
6014 var a = A.new()
6015 a.val = 20
6016 enddef
6017 T()
6018 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006019 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006020enddef
6021
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006022" Test for reading and writing a class member from a def function
6023def Test_modify_class_member_from_def_function()
6024 var lines =<< trim END
6025 vim9script
6026 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006027 var var1: number = 10
6028 public static var var2: list<number> = [1, 2]
6029 public static var var3: dict<number> = {a: 1, b: 2}
6030 static var _priv_var4: number = 40
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006031 endclass
6032 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02006033 assert_equal([1, 2], A.var2)
6034 assert_equal({a: 1, b: 2}, A.var3)
6035 A.var2 = [3, 4]
6036 A.var3 = {c: 3, d: 4}
6037 assert_equal([3, 4], A.var2)
6038 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael03042a22023-11-11 08:53:32 +01006039 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006040 enddef
6041 T()
6042 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006043 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006044enddef
6045
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006046" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006047def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006048 var lines =<< trim END
6049 vim9script
6050 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006051 public static var svar1: list<number> = [1]
6052 public static var svar2: list<number> = [2]
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006053 endclass
6054
6055 A.svar1->add(3)
6056 A.svar2->add(4)
6057 assert_equal([1, 3], A.svar1)
6058 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006059
6060 def Foo()
6061 A.svar1->add(7)
6062 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006063 assert_equal([1, 3, 7], A.svar1)
6064 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006065 enddef
6066 Foo()
6067 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006068 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006069
6070 # Cannot read from a class variable using an object in script context
6071 lines =<< trim END
6072 vim9script
6073 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006074 public var var1: number
6075 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006076 endclass
6077
6078 var a = A.new()
6079 echo a.svar2
6080 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006081 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006082
6083 # Cannot write to a class variable using an object in script context
6084 lines =<< trim END
6085 vim9script
6086 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006087 public var var1: number
6088 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006089 endclass
6090
6091 var a = A.new()
6092 a.svar2 = [2]
6093 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006094 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006095
6096 # Cannot read from a class variable using an object in def method context
6097 lines =<< trim END
6098 vim9script
6099 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006100 public var var1: number
6101 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006102 endclass
6103
6104 def T()
6105 var a = A.new()
6106 echo a.svar2
6107 enddef
6108 T()
6109 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006110 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006111
6112 # Cannot write to a class variable using an object in def method context
6113 lines =<< trim END
6114 vim9script
6115 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006116 public var var1: number
6117 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006118 endclass
6119
6120 def T()
6121 var a = A.new()
6122 a.svar2 = [2]
6123 enddef
6124 T()
6125 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006126 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006127enddef
6128
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006129" Test for using a interface method using a child object
6130def Test_interface_method_from_child()
6131 var lines =<< trim END
6132 vim9script
6133
6134 interface A
6135 def Foo(): string
6136 endinterface
6137
6138 class B implements A
6139 def Foo(): string
6140 return 'foo'
6141 enddef
6142 endclass
6143
6144 class C extends B
6145 def Bar(): string
6146 return 'bar'
6147 enddef
6148 endclass
6149
6150 def T1(a: A)
6151 assert_equal('foo', a.Foo())
6152 enddef
6153
6154 def T2(b: B)
6155 assert_equal('foo', b.Foo())
6156 enddef
6157
6158 var c = C.new()
6159 T1(c)
6160 T2(c)
6161 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006162 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006163enddef
6164
6165" Test for using an interface method using a child object when it is overridden
6166" by the child class.
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01006167def Test_interface_overridden_method_from_child()
6168 var lines =<< trim END
6169 vim9script
6170
6171 interface A
6172 def Foo(): string
6173 endinterface
6174
6175 class B implements A
6176 def Foo(): string
6177 return 'b-foo'
6178 enddef
6179 endclass
6180
6181 class C extends B
6182 def Bar(): string
6183 return 'bar'
6184 enddef
6185 def Foo(): string
6186 return 'c-foo'
6187 enddef
6188 endclass
6189
6190 def T1(a: A)
6191 assert_equal('c-foo', a.Foo())
6192 enddef
6193
6194 def T2(b: B)
6195 assert_equal('c-foo', b.Foo())
6196 enddef
6197
6198 var c = C.new()
6199 T1(c)
6200 T2(c)
6201 END
6202 v9.CheckSourceSuccess(lines)
6203enddef
6204
6205" Test for interface inheritance
6206def Test_interface_inheritance()
6207 var lines =<< trim END
6208 vim9script
6209
6210 interface A
6211 def A_Fn(): string
6212 endinterface
6213
6214 interface B
6215 def B_Fn(): string
6216 endinterface
6217
6218 interface C
6219 def C_Fn(): string
6220 endinterface
6221
6222 class C1 implements A
6223 def A_Fn(): string
6224 return 'c1-a'
6225 enddef
6226 endclass
6227
6228 class C2 extends C1 implements B
6229 def B_Fn(): string
6230 return 'c2-b'
6231 enddef
6232 def A_Fn(): string
6233 return 'c2-a'
6234 enddef
6235 endclass
6236
6237 class C3 extends C2 implements C
6238 def C_Fn(): string
6239 return 'c3-c'
6240 enddef
6241 def A_Fn(): string
6242 return 'c3-a'
6243 enddef
6244 def B_Fn(): string
6245 return 'c3-b'
6246 enddef
6247 endclass
6248
6249 def T1(a: A, s: string)
6250 assert_equal(s, a.A_Fn())
6251 enddef
6252
6253 def T2(b: B, s: string)
6254 assert_equal(s, b.B_Fn())
6255 enddef
6256
6257 def T3(c: C, s: string)
6258 assert_equal(s, c.C_Fn())
6259 enddef
6260
6261 def T4(c1: C1)
6262 T1(c1, 'c3-a')
6263 enddef
6264
6265 def T5(c2: C2)
6266 T1(c2, 'c3-a')
6267 T2(c2, 'c3-b')
6268 enddef
6269
6270 def T6(c3: C3)
6271 T1(c3, 'c3-a')
6272 T2(c3, 'c3-b')
6273 T3(c3, 'c3-c')
6274 enddef
6275
6276 var o3 = C3.new()
6277 T4(o3)
6278 T5(o3)
6279 T6(o3)
6280 END
6281 v9.CheckSourceSuccess(lines)
6282
6283 # Both the parent and child classes implement the same interface
6284 lines =<< trim END
6285 vim9script
6286
6287 interface I
6288 def Foo(): string
6289 endinterface
6290
6291 class A implements I
6292 def Foo(): string
6293 return 'A-foo'
6294 enddef
6295 endclass
6296
6297 class B implements I
6298 def Foo(): string
6299 return 'B-foo'
6300 enddef
6301 endclass
6302
6303 def Bar(i1: I): string
6304 return i1.Foo()
6305 enddef
6306
6307 var b = B.new()
6308 assert_equal('B-foo', Bar(b))
6309 END
6310 v9.CheckSourceSuccess(lines)
6311enddef
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006312
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006313" Test for abstract methods
6314def Test_abstract_method()
6315 # Use two abstract methods
6316 var lines =<< trim END
6317 vim9script
6318 abstract class A
6319 def M1(): number
6320 return 10
6321 enddef
6322 abstract def M2(): number
6323 abstract def M3(): number
6324 endclass
6325 class B extends A
6326 def M2(): number
6327 return 20
6328 enddef
6329 def M3(): number
6330 return 30
6331 enddef
6332 endclass
6333 var b = B.new()
6334 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6335 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006336 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006337
6338 # Don't define an abstract method
6339 lines =<< trim END
6340 vim9script
6341 abstract class A
6342 abstract def Foo()
6343 endclass
6344 class B extends A
6345 endclass
6346 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006347 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006348
6349 # Use abstract method in a concrete class
6350 lines =<< trim END
6351 vim9script
6352 class A
6353 abstract def Foo()
6354 endclass
6355 class B extends A
6356 endclass
6357 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006358 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006359
6360 # Use abstract method in an interface
6361 lines =<< trim END
6362 vim9script
6363 interface A
6364 abstract def Foo()
6365 endinterface
6366 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006367 def Foo()
6368 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006369 endclass
6370 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006371 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6372
6373 # Use abstract static method in an interface
6374 lines =<< trim END
6375 vim9script
6376 interface A
6377 abstract static def Foo()
6378 enddef
6379 endinterface
6380 END
6381 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6382
6383 # Use abstract static variable in an interface
6384 lines =<< trim END
6385 vim9script
6386 interface A
6387 abstract static foo: number = 10
6388 endinterface
6389 END
6390 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006391
6392 # Abbreviate the "abstract" keyword
6393 lines =<< trim END
6394 vim9script
6395 class A
6396 abs def Foo()
6397 endclass
6398 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006399 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006400
6401 # Use "abstract" with a member variable
6402 lines =<< trim END
6403 vim9script
6404 abstract class A
6405 abstract this.val = 10
6406 endclass
6407 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006408 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006409
6410 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006411 lines =<< trim END
6412 vim9script
6413 abstract class A
6414 abstract static def Foo(): number
6415 endclass
6416 END
6417 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006418
6419 # Type mismatch between abstract method and concrete method
6420 lines =<< trim END
6421 vim9script
6422 abstract class A
6423 abstract def Foo(a: string, b: number): list<number>
6424 endclass
6425 class B extends A
6426 def Foo(a: number, b: string): list<string>
6427 return []
6428 enddef
6429 endclass
6430 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006431 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 +02006432
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006433 # Invoke an abstract method from a def function
6434 lines =<< trim END
6435 vim9script
6436 abstract class A
6437 abstract def Foo(): list<number>
6438 endclass
6439 class B extends A
6440 def Foo(): list<number>
6441 return [3, 5]
6442 enddef
6443 endclass
6444 def Bar(c: B)
6445 assert_equal([3, 5], c.Foo())
6446 enddef
6447 var b = B.new()
6448 Bar(b)
6449 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006450 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006451
6452 # Use a static method in an abstract class
6453 lines =<< trim END
6454 vim9script
6455 abstract class A
6456 static def Foo(): string
6457 return 'foo'
6458 enddef
6459 endclass
6460 assert_equal('foo', A.Foo())
6461 END
6462 v9.CheckSourceSuccess(lines)
Ernie Rael7c92e882025-01-18 17:26:39 +01006463
6464 # Invoke method returning a value through the abstract class. See #15432.
6465 lines =<< trim END
6466 vim9script
6467
6468 abstract class A
6469 abstract def String(): string
6470 endclass
6471
6472 class B extends A
6473 def String(): string
6474 return 'B'
6475 enddef
6476 endclass
6477
6478 def F(o: A)
6479 assert_equal('B', o.String())
6480 enddef
6481 F(B.new())
6482 END
6483 v9.CheckSourceSuccess(lines)
6484
6485 # Invoke abstract method returning a value does not compile
6486 lines =<< trim END
6487 vim9script
6488
6489 abstract class A
6490 abstract def String(): string
6491 return 'X'
6492 enddef
6493 endclass
6494 END
6495 v9.CheckScriptFailure(lines, "E1318: Not a valid command in a class: return 'X'")
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006496enddef
6497
6498" Test for calling a class method from a subclass
6499def Test_class_method_call_from_subclass()
6500 # class method call from a subclass
6501 var lines =<< trim END
6502 vim9script
6503
6504 class A
6505 static def Foo()
6506 echo "foo"
6507 enddef
6508 endclass
6509
6510 class B extends A
6511 def Bar()
6512 Foo()
6513 enddef
6514 endclass
6515
6516 var b = B.new()
6517 b.Bar()
6518 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006519 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006520enddef
6521
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006522" Test for calling a class method using an object in a def function context and
6523" script context.
6524def Test_class_method_call_using_object()
6525 # script context
6526 var lines =<< trim END
6527 vim9script
6528 class A
6529 static def Foo(): list<string>
6530 return ['a', 'b']
6531 enddef
6532 def Bar()
6533 assert_equal(['a', 'b'], A.Foo())
6534 assert_equal(['a', 'b'], Foo())
6535 enddef
6536 endclass
6537
6538 def T()
6539 assert_equal(['a', 'b'], A.Foo())
6540 var t_a = A.new()
6541 t_a.Bar()
6542 enddef
6543
6544 assert_equal(['a', 'b'], A.Foo())
6545 var a = A.new()
6546 a.Bar()
6547 T()
6548 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006549 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006550
6551 # script context
6552 lines =<< trim END
6553 vim9script
6554 class A
6555 static def Foo(): string
6556 return 'foo'
6557 enddef
6558 endclass
6559
6560 var a = A.new()
6561 assert_equal('foo', a.Foo())
6562 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006563 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006564
6565 # def function context
6566 lines =<< trim END
6567 vim9script
6568 class A
6569 static def Foo(): string
6570 return 'foo'
6571 enddef
6572 endclass
6573
6574 def T()
6575 var a = A.new()
6576 assert_equal('foo', a.Foo())
6577 enddef
6578 T()
6579 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006580 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006581enddef
6582
6583def Test_class_variable()
6584 var lines =<< trim END
6585 vim9script
6586
6587 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006588 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006589 static def ClassFunc()
6590 assert_equal(10, val)
6591 enddef
6592 def ObjFunc()
6593 assert_equal(10, val)
6594 enddef
6595 endclass
6596
6597 class B extends A
6598 endclass
6599
6600 assert_equal(10, A.val)
6601 A.ClassFunc()
6602 var a = A.new()
6603 a.ObjFunc()
6604 var b = B.new()
6605 b.ObjFunc()
6606
6607 def T1(a1: A)
6608 a1.ObjFunc()
6609 A.ClassFunc()
6610 enddef
6611 T1(b)
6612
6613 A.val = 20
6614 assert_equal(20, A.val)
6615 END
6616 v9.CheckSourceSuccess(lines)
6617
6618 # Modifying a parent class variable from a child class method
6619 lines =<< trim END
6620 vim9script
6621
6622 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006623 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006624 endclass
6625
6626 class B extends A
6627 static def ClassFunc()
6628 val = 20
6629 enddef
6630 endclass
6631 B.ClassFunc()
6632 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006633 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006634
6635 # Reading a parent class variable from a child class method
6636 lines =<< trim END
6637 vim9script
6638
6639 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006640 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006641 endclass
6642
6643 class B extends A
6644 static def ClassFunc()
6645 var i = val
6646 enddef
6647 endclass
6648 B.ClassFunc()
6649 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006650 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006651
6652 # Modifying a parent class variable from a child object method
6653 lines =<< trim END
6654 vim9script
6655
6656 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006657 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006658 endclass
6659
6660 class B extends A
6661 def ObjFunc()
6662 val = 20
6663 enddef
6664 endclass
6665 var b = B.new()
6666 b.ObjFunc()
6667 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006668 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006669
6670 # Reading a parent class variable from a child object method
6671 lines =<< trim END
6672 vim9script
6673
6674 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006675 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006676 endclass
6677
6678 class B extends A
6679 def ObjFunc()
6680 var i = val
6681 enddef
6682 endclass
6683 var b = B.new()
6684 b.ObjFunc()
6685 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006686 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006687
6688 # Modifying a class variable using an object at script level
6689 lines =<< trim END
6690 vim9script
6691
6692 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006693 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006694 endclass
6695 var a = A.new()
6696 a.val = 20
6697 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006698 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006699
6700 # Reading a class variable using an object at script level
6701 lines =<< trim END
6702 vim9script
6703
6704 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006705 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006706 endclass
6707 var a = A.new()
6708 var i = a.val
6709 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006710 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006711
6712 # Modifying a class variable using an object at function level
6713 lines =<< trim END
6714 vim9script
6715
6716 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006717 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006718 endclass
6719
6720 def T()
6721 var a = A.new()
6722 a.val = 20
6723 enddef
6724 T()
6725 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006726 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006727
6728 # Reading a class variable using an object at function level
6729 lines =<< trim END
6730 vim9script
6731
6732 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006733 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006734 endclass
6735 def T()
6736 var a = A.new()
6737 var i = a.val
6738 enddef
6739 T()
6740 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006741 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006742
6743 # Use old implicit var declaration syntax (without initialization)
6744 lines =<< trim END
6745 vim9script
6746
6747 class A
6748 static val: number
6749 endclass
6750 END
6751 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6752
6753 # Use old implicit var declaration syntax (with initialization)
6754 lines =<< trim END
6755 vim9script
6756
6757 class A
6758 static val: number = 10
6759 endclass
6760 END
6761 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6762
6763 # Use old implicit var declaration syntax (type inferred)
6764 lines =<< trim END
6765 vim9script
6766
6767 class A
6768 static val = 10
6769 endclass
6770 END
6771 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6772
6773 # Missing ":var" in "var" class variable declaration (without initialization)
6774 lines =<< trim END
6775 vim9script
6776
6777 class A
6778 static var: number
6779 endclass
6780 END
6781 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6782
6783 # Missing ":var" in "var" class variable declaration (with initialization)
6784 lines =<< trim END
6785 vim9script
6786
6787 class A
6788 static var: number = 10
6789 endclass
6790 END
6791 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6792
6793 # Missing ":var" in "var" class variable declaration (type inferred)
6794 lines =<< trim END
6795 vim9script
6796
6797 class A
6798 static var = 10
6799 endclass
6800 END
6801 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6802
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006803enddef
6804
6805" Test for using a duplicate class method and class variable in a child class
6806def Test_dup_class_member()
6807 # duplicate class variable, class method and overridden object method
6808 var lines =<< trim END
6809 vim9script
6810 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006811 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006812 static def Check()
6813 assert_equal(100, sval)
6814 enddef
6815 def GetVal(): number
6816 return sval
6817 enddef
6818 endclass
6819
6820 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006821 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006822 static def Check()
6823 assert_equal(200, sval)
6824 enddef
6825 def GetVal(): number
6826 return sval
6827 enddef
6828 endclass
6829
6830 def T1(aa: A): number
6831 return aa.GetVal()
6832 enddef
6833
6834 def T2(bb: B): number
6835 return bb.GetVal()
6836 enddef
6837
6838 assert_equal(100, A.sval)
6839 assert_equal(200, B.sval)
6840 var a = A.new()
6841 assert_equal(100, a.GetVal())
6842 var b = B.new()
6843 assert_equal(200, b.GetVal())
6844 assert_equal(200, T1(b))
6845 assert_equal(200, T2(b))
6846 END
6847 v9.CheckSourceSuccess(lines)
6848
6849 # duplicate class variable and class method
6850 lines =<< trim END
6851 vim9script
6852 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006853 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006854 static def Check()
6855 assert_equal(100, sval)
6856 enddef
6857 def GetVal(): number
6858 return sval
6859 enddef
6860 endclass
6861
6862 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006863 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006864 static def Check()
6865 assert_equal(200, sval)
6866 enddef
6867 endclass
6868
6869 def T1(aa: A): number
6870 return aa.GetVal()
6871 enddef
6872
6873 def T2(bb: B): number
6874 return bb.GetVal()
6875 enddef
6876
6877 assert_equal(100, A.sval)
6878 assert_equal(200, B.sval)
6879 var a = A.new()
6880 assert_equal(100, a.GetVal())
6881 var b = B.new()
6882 assert_equal(100, b.GetVal())
6883 assert_equal(100, T1(b))
6884 assert_equal(100, T2(b))
6885 END
6886 v9.CheckSourceSuccess(lines)
6887enddef
6888
6889" Test for calling an instance method using the class
6890def Test_instance_method_call_using_class()
6891 # Invoke an object method using a class in script context
6892 var lines =<< trim END
6893 vim9script
6894 class A
6895 def Foo()
6896 echo "foo"
6897 enddef
6898 endclass
6899 A.Foo()
6900 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006901 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006902
6903 # Invoke an object method using a class in def function context
6904 lines =<< trim END
6905 vim9script
6906 class A
6907 def Foo()
6908 echo "foo"
6909 enddef
6910 endclass
6911 def T()
6912 A.Foo()
6913 enddef
6914 T()
6915 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006916 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006917enddef
6918
6919" Test for duplicate class method and instance method
6920def Test_dup_classmethod_objmethod()
6921 # Duplicate instance method
6922 var lines =<< trim END
6923 vim9script
6924 class A
6925 static def Foo()
6926 enddef
6927 def Foo()
6928 enddef
6929 endclass
6930 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006931 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006932
Ernie Rael03042a22023-11-11 08:53:32 +01006933 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006934 lines =<< trim END
6935 vim9script
6936 class A
6937 static def Foo()
6938 enddef
6939 def _Foo()
6940 enddef
6941 endclass
6942 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006943 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006944
6945 # Duplicate class method
6946 lines =<< trim END
6947 vim9script
6948 class A
6949 def Foo()
6950 enddef
6951 static def Foo()
6952 enddef
6953 endclass
6954 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006955 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006956
Ernie Rael03042a22023-11-11 08:53:32 +01006957 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006958 lines =<< trim END
6959 vim9script
6960 class A
6961 def Foo()
6962 enddef
6963 static def _Foo()
6964 enddef
6965 endclass
6966 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006967 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006968
Ernie Rael03042a22023-11-11 08:53:32 +01006969 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006970 lines =<< trim END
6971 vim9script
6972 class A
6973 def _Foo()
6974 enddef
6975 static def _Foo()
6976 enddef
6977 endclass
6978 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006979 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006980enddef
6981
6982" Test for an instance method access level comparison with parent instance
6983" methods.
6984def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01006985 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006986 var lines =<< trim END
6987 vim9script
6988 class A
6989 def Foo()
6990 enddef
6991 endclass
6992 class B extends A
6993 endclass
6994 class C extends B
6995 def _Foo()
6996 enddef
6997 endclass
6998 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006999 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007000
7001 # Public method in subclass
7002 lines =<< trim END
7003 vim9script
7004 class A
7005 def _Foo()
7006 enddef
7007 endclass
7008 class B extends A
7009 endclass
7010 class C extends B
7011 def Foo()
7012 enddef
7013 endclass
7014 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007015 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007016enddef
7017
7018def Test_extend_empty_class()
7019 var lines =<< trim END
7020 vim9script
7021 class A
7022 endclass
7023 class B extends A
7024 endclass
7025 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007026 public static var rw_class_var = 1
7027 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007028 static def ClassMethod(): number
7029 return 3
7030 enddef
7031 def ObjMethod(): number
7032 return 4
7033 enddef
7034 endclass
7035 assert_equal(1, C.rw_class_var)
7036 assert_equal(3, C.ClassMethod())
7037 var c = C.new()
7038 assert_equal(2, c.rw_obj_var)
7039 assert_equal(4, c.ObjMethod())
7040 END
7041 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02007042enddef
7043
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007044" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01007045" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007046def Test_interface_with_unsupported_members()
7047 var lines =<< trim END
7048 vim9script
7049 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007050 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007051 endinterface
7052 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007053 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007054
7055 lines =<< trim END
7056 vim9script
7057 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007058 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007059 endinterface
7060 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007061 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007062
7063 lines =<< trim END
7064 vim9script
7065 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007066 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007067 endinterface
7068 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007069 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007070
7071 lines =<< trim END
7072 vim9script
7073 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007074 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007075 endinterface
7076 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007077 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007078
7079 lines =<< trim END
7080 vim9script
7081 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007082 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007083 endinterface
7084 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007085 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007086
7087 lines =<< trim END
7088 vim9script
7089 interface A
7090 static def Foo(d: dict<any>): list<string>
7091 endinterface
7092 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007093 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007094
7095 lines =<< trim END
7096 vim9script
7097 interface A
7098 static def _Foo(d: dict<any>): list<string>
7099 endinterface
7100 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007101 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007102
7103 lines =<< trim END
7104 vim9script
7105 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007106 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007107 endinterface
7108 END
Ernie Rael03042a22023-11-11 08:53:32 +01007109 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007110
7111 lines =<< trim END
7112 vim9script
7113 interface A
7114 def _Foo(d: dict<any>): list<string>
7115 endinterface
7116 END
Ernie Rael03042a22023-11-11 08:53:32 +01007117 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007118enddef
7119
7120" Test for extending an interface
7121def Test_extend_interface()
7122 var lines =<< trim END
7123 vim9script
7124 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007125 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007126 def Foo()
7127 endinterface
7128 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007129 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007130 def Bar()
7131 endinterface
7132 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007133 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007134 def Foo()
7135 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007136 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007137 def Bar()
7138 enddef
7139 endclass
7140 END
7141 v9.CheckSourceSuccess(lines)
7142
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007143 # extending empty interface
7144 lines =<< trim END
7145 vim9script
7146 interface A
7147 endinterface
7148 interface B extends A
7149 endinterface
7150 class C implements B
7151 endclass
7152 END
7153 v9.CheckSourceSuccess(lines)
7154
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007155 lines =<< trim END
7156 vim9script
7157 interface A
7158 def Foo()
7159 endinterface
7160 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007161 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007162 endinterface
7163 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007164 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007165 endclass
7166 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007167 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007168
7169 lines =<< trim END
7170 vim9script
7171 interface A
7172 def Foo()
7173 endinterface
7174 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007175 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007176 endinterface
7177 class C implements A, B
7178 def Foo()
7179 enddef
7180 endclass
7181 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007182 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007183
7184 # interface cannot extend a class
7185 lines =<< trim END
7186 vim9script
7187 class A
7188 endclass
7189 interface B extends A
7190 endinterface
7191 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007192 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007193
7194 # class cannot extend an interface
7195 lines =<< trim END
7196 vim9script
7197 interface A
7198 endinterface
7199 class B extends A
7200 endclass
7201 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007202 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007203
7204 # interface cannot implement another interface
7205 lines =<< trim END
7206 vim9script
7207 interface A
7208 endinterface
7209 interface B implements A
7210 endinterface
7211 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007212 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007213
7214 # interface cannot extend multiple interfaces
7215 lines =<< trim END
7216 vim9script
7217 interface A
7218 endinterface
7219 interface B
7220 endinterface
7221 interface C extends A, B
7222 endinterface
7223 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007224 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007225
7226 # Variable type in an extended interface is of different type
7227 lines =<< trim END
7228 vim9script
7229 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007230 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007231 endinterface
7232 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007233 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007234 endinterface
7235 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007236 var val1: string
7237 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007238 endinterface
7239 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007240 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007241enddef
7242
7243" Test for a child class implementing an interface when some of the methods are
7244" defined in the parent class.
7245def Test_child_class_implements_interface()
7246 var lines =<< trim END
7247 vim9script
7248
7249 interface Intf
7250 def F1(): list<list<number>>
7251 def F2(): list<list<number>>
7252 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007253 var var1: list<dict<number>>
7254 var var2: list<dict<number>>
7255 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007256 endinterface
7257
7258 class A
7259 def A1()
7260 enddef
7261 def F3(): list<list<number>>
7262 return [[3]]
7263 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007264 var v1: list<list<number>> = [[0]]
7265 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007266 endclass
7267
7268 class B extends A
7269 def B1()
7270 enddef
7271 def F2(): list<list<number>>
7272 return [[2]]
7273 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007274 var v2: list<list<number>> = [[0]]
7275 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007276 endclass
7277
7278 class C extends B implements Intf
7279 def C1()
7280 enddef
7281 def F1(): list<list<number>>
7282 return [[1]]
7283 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007284 var v3: list<list<number>> = [[0]]
7285 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007286 endclass
7287
7288 def T(if: Intf)
7289 assert_equal([[1]], if.F1())
7290 assert_equal([[2]], if.F2())
7291 assert_equal([[3]], if.F3())
7292 assert_equal([{a: 10}], if.var1)
7293 assert_equal([{b: 20}], if.var2)
7294 assert_equal([{c: 30}], if.var3)
7295 enddef
7296
7297 var c = C.new()
7298 T(c)
7299 assert_equal([[1]], c.F1())
7300 assert_equal([[2]], c.F2())
7301 assert_equal([[3]], c.F3())
7302 assert_equal([{a: 10}], c.var1)
7303 assert_equal([{b: 20}], c.var2)
7304 assert_equal([{c: 30}], c.var3)
7305 END
7306 v9.CheckSourceSuccess(lines)
7307
7308 # One of the interface methods is not found
7309 lines =<< trim END
7310 vim9script
7311
7312 interface Intf
7313 def F1()
7314 def F2()
7315 def F3()
7316 endinterface
7317
7318 class A
7319 def A1()
7320 enddef
7321 endclass
7322
7323 class B extends A
7324 def B1()
7325 enddef
7326 def F2()
7327 enddef
7328 endclass
7329
7330 class C extends B implements Intf
7331 def C1()
7332 enddef
7333 def F1()
7334 enddef
7335 endclass
7336 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007337 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007338
7339 # One of the interface methods is of different type
7340 lines =<< trim END
7341 vim9script
7342
7343 interface Intf
7344 def F1()
7345 def F2()
7346 def F3()
7347 endinterface
7348
7349 class A
7350 def F3(): number
7351 return 0
7352 enddef
7353 def A1()
7354 enddef
7355 endclass
7356
7357 class B extends A
7358 def B1()
7359 enddef
7360 def F2()
7361 enddef
7362 endclass
7363
7364 class C extends B implements Intf
7365 def C1()
7366 enddef
7367 def F1()
7368 enddef
7369 endclass
7370 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007371 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007372
7373 # One of the interface variables is not present
7374 lines =<< trim END
7375 vim9script
7376
7377 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007378 var var1: list<dict<number>>
7379 var var2: list<dict<number>>
7380 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007381 endinterface
7382
7383 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007384 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007385 endclass
7386
7387 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007388 var v2: list<list<number>> = [[0]]
7389 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007390 endclass
7391
7392 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007393 var v3: list<list<number>> = [[0]]
7394 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007395 endclass
7396 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007397 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007398
7399 # One of the interface variables is of different type
7400 lines =<< trim END
7401 vim9script
7402
7403 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007404 var var1: list<dict<number>>
7405 var var2: list<dict<number>>
7406 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007407 endinterface
7408
7409 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007410 var v1: list<list<number>> = [[0]]
7411 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007412 endclass
7413
7414 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007415 var v2: list<list<number>> = [[0]]
7416 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007417 endclass
7418
7419 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007420 var v3: list<list<number>> = [[0]]
7421 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007422 endclass
7423 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007424 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 +02007425enddef
7426
7427" Test for extending an interface with duplicate variables and methods
7428def Test_interface_extends_with_dup_members()
7429 var lines =<< trim END
7430 vim9script
7431 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007432 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007433 def Foo1(): number
7434 endinterface
7435 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007436 var n2: number
7437 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007438 def Foo2(): number
7439 def Foo1(): number
7440 endinterface
7441 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007442 var n1 = 10
7443 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007444 def Foo1(): number
7445 return 30
7446 enddef
7447 def Foo2(): number
7448 return 40
7449 enddef
7450 endclass
7451 def T1(a: A)
7452 assert_equal(10, a.n1)
7453 assert_equal(30, a.Foo1())
7454 enddef
7455 def T2(b: B)
7456 assert_equal(10, b.n1)
7457 assert_equal(20, b.n2)
7458 assert_equal(30, b.Foo1())
7459 assert_equal(40, b.Foo2())
7460 enddef
7461 var c = C.new()
7462 T1(c)
7463 T2(c)
7464 END
7465 v9.CheckSourceSuccess(lines)
7466enddef
7467
Yegappan Lakshmananc10342d2025-01-11 09:39:01 +01007468" Test for implementing an interface with different ordering for the interface
7469" member variables.
7470def Test_implement_interface_with_different_variable_order()
7471 var lines =<< trim END
7472 vim9script
7473
7474 interface IX
7475 var F: func(): string
7476 endinterface
7477
7478 class X implements IX
7479 var x: number
7480 var F: func(): string = () => 'ok'
7481 endclass
7482
7483 def Foo(ix: IX): string
7484 return ix.F()
7485 enddef
7486
7487 var x0 = X.new(0)
7488 assert_equal('ok', Foo(x0))
7489 END
7490 v9.CheckSourceSuccess(lines)
7491enddef
7492
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01007493" Test for inheriting interfaces from an imported super class
7494def Test_interface_inheritance_with_imported_super()
7495 var lines =<< trim END
7496 vim9script
7497
7498 export interface I
7499 def F(): string
7500 endinterface
7501
7502 export class A implements I
7503 def F(): string
7504 return 'A'
7505 enddef
7506 endclass
7507 END
7508 writefile(lines, 'Xinheritintfimportclass.vim', 'D')
7509
7510 lines =<< trim END
7511 vim9script
7512
7513 import './Xinheritintfimportclass.vim' as i_imp
7514
7515 # class C extends i_imp.A
7516 class C extends i_imp.A implements i_imp.I
7517 def F(): string
7518 return 'C'
7519 enddef
7520 endclass
7521
7522 def TestI(i: i_imp.I): string
7523 return i.F()
7524 enddef
7525
7526 assert_equal('C', TestI(C.new()))
7527 END
7528 v9.CheckSourceSuccess(lines)
7529enddef
7530
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007531" Test for using "any" type for a variable in a sub-class while it has a
7532" concrete type in the interface
7533def Test_implements_using_var_type_any()
7534 var lines =<< trim END
7535 vim9script
7536 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007537 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007538 endinterface
7539 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007540 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007541 endclass
7542 var b = B.new()
7543 assert_equal([{a: '1'}, {b: '2'}], b.val)
7544 END
7545 v9.CheckSourceSuccess(lines)
7546
7547 # initialize instance variable using a different type
7548 lines =<< trim END
7549 vim9script
7550 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007551 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007552 endinterface
7553 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007554 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007555 endclass
7556 var b = B.new()
7557 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007558 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007559enddef
7560
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007561" Test for assigning to a member variable in a nested class
7562def Test_nested_object_assignment()
7563 var lines =<< trim END
7564 vim9script
7565
7566 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007567 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007568 endclass
7569
7570 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007571 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007572 endclass
7573
7574 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007575 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007576 endclass
7577
7578 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007579 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007580 endclass
7581
7582 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007583 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007584 enddef
7585
7586 var d = D.new()
7587 T(d)
7588 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007589 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007590enddef
7591
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007592" Test for calling methods using a null object
7593def Test_null_object_method_call()
7594 # Calling a object method using a null object in script context
7595 var lines =<< trim END
7596 vim9script
7597
7598 class C
7599 def Foo()
7600 assert_report('This method should not be executed')
7601 enddef
7602 endclass
7603
7604 var o: C
7605 o.Foo()
7606 END
7607 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7608
7609 # Calling a object method using a null object in def function context
7610 lines =<< trim END
7611 vim9script
7612
7613 class C
7614 def Foo()
7615 assert_report('This method should not be executed')
7616 enddef
7617 endclass
7618
7619 def T()
7620 var o: C
7621 o.Foo()
7622 enddef
7623 T()
7624 END
7625 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7626
7627 # Calling a object method through another class method using a null object in
7628 # script context
7629 lines =<< trim END
7630 vim9script
7631
7632 class C
7633 def Foo()
7634 assert_report('This method should not be executed')
7635 enddef
7636
7637 static def Bar(o_any: any)
7638 var o_typed: C = o_any
7639 o_typed.Foo()
7640 enddef
7641 endclass
7642
7643 var o: C
7644 C.Bar(o)
7645 END
7646 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7647
7648 # Calling a object method through another class method using a null object in
7649 # def function context
7650 lines =<< trim END
7651 vim9script
7652
7653 class C
7654 def Foo()
7655 assert_report('This method should not be executed')
7656 enddef
7657
7658 static def Bar(o_any: any)
7659 var o_typed: C = o_any
7660 o_typed.Foo()
7661 enddef
7662 endclass
7663
7664 def T()
7665 var o: C
7666 C.Bar(o)
7667 enddef
7668 T()
7669 END
7670 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007671
7672 # Calling an object method defined in a class that is extended. This differs
7673 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7674 lines =<< trim END
7675 vim9script
7676
7677 class C0
7678 def F()
7679 enddef
7680 endclass
7681
7682 class C extends C0
7683 endclass
7684
7685 def X()
7686 var o: C0 = null_object
7687 o.F()
7688 enddef
7689 X()
7690 END
7691 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7692
7693 # Getting a function ref an object method.
7694 lines =<< trim END
7695 vim9script
7696
7697 class C0
7698 def F()
7699 enddef
7700 endclass
7701
7702 class C extends C0
7703 endclass
7704
7705 def X()
7706 var o: C0 = null_object
7707 var XXX = o.F
7708 enddef
7709 X()
7710 END
7711 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007712enddef
7713
7714" Test for using a dict as an object member
7715def Test_dict_object_member()
7716 var lines =<< trim END
7717 vim9script
7718
7719 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007720 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007721 def GetState(): dict<number>
7722 return this.state
7723 enddef
7724 endclass
7725
7726 var ctx = Context.new()
7727 ctx.state->extend({a: 1})
7728 ctx.state['b'] = 2
7729 assert_equal({a: 1, b: 2}, ctx.GetState())
7730
7731 def F()
7732 ctx.state['c'] = 3
7733 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7734 enddef
7735 F()
7736 assert_equal(3, ctx.state.c)
7737 ctx.state.c = 4
7738 assert_equal(4, ctx.state.c)
7739 END
7740 v9.CheckSourceSuccess(lines)
7741enddef
7742
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007743" The following test was failing after 9.0.1914. This was caused by using a
7744" freed object from a previous method call.
7745def Test_freed_object_from_previous_method_call()
7746 var lines =<< trim END
7747 vim9script
7748
7749 class Context
7750 endclass
7751
7752 class Result
7753 endclass
7754
7755 def Failure(): Result
7756 return Result.new()
7757 enddef
7758
7759 def GetResult(ctx: Context): Result
7760 return Failure()
7761 enddef
7762
7763 def Test_GetResult()
7764 var ctx = Context.new()
7765 var result = GetResult(ctx)
7766 enddef
7767
7768 Test_GetResult()
7769 END
7770 v9.CheckSourceSuccess(lines)
7771enddef
7772
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007773" Test for duplicate object and class variable
7774def Test_duplicate_variable()
7775 # Object variable name is same as the class variable name
7776 var lines =<< trim END
7777 vim9script
7778 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007779 public static var sval: number
7780 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007781 endclass
7782 var a = A.new()
7783 END
7784 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7785
7786 # Duplicate variable name and calling a class method
7787 lines =<< trim END
7788 vim9script
7789 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007790 public static var sval: number
7791 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007792 def F1()
7793 echo this.sval
7794 enddef
7795 static def F2()
7796 echo sval
7797 enddef
7798 endclass
7799 A.F2()
7800 END
7801 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7802
7803 # Duplicate variable with an empty constructor
7804 lines =<< trim END
7805 vim9script
7806 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007807 public static var sval: number
7808 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007809 def new()
7810 enddef
7811 endclass
7812 var a = A.new()
7813 END
7814 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7815enddef
7816
7817" Test for using a reserved keyword as a variable name
7818def Test_reserved_varname()
7819 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7820 'null_function', 'null_list', 'null_partial', 'null_string',
7821 'null_channel', 'null_job', 'super', 'this']
7822
7823 var lines =<< trim eval END
7824 vim9script
7825 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007826 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007827 endclass
7828 var o = C.new()
7829 END
7830 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7831
7832 lines =<< trim eval END
7833 vim9script
7834 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007835 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007836 def new()
7837 enddef
7838 endclass
7839 var o = C.new()
7840 END
7841 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7842
7843 lines =<< trim eval END
7844 vim9script
7845 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007846 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007847 def new()
7848 enddef
7849 def F()
7850 echo this.{kword}
7851 enddef
7852 endclass
7853 var o = C.new()
7854 o.F()
7855 END
7856 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007857
7858 # class variable name
7859 if kword != 'this'
7860 lines =<< trim eval END
7861 vim9script
7862 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007863 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007864 endclass
7865 END
7866 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7867 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007868 endfor
7869enddef
7870
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007871" Test for checking the type of the arguments and the return value of a object
7872" method in an extended class.
7873def Test_extended_obj_method_type_check()
7874 var lines =<< trim END
7875 vim9script
7876
7877 class A
7878 endclass
7879 class B extends A
7880 endclass
7881 class C extends B
7882 endclass
7883
7884 class Foo
7885 def Doit(p: B): B
7886 return B.new()
7887 enddef
7888 endclass
7889
7890 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007891 def Doit(p: C): B
7892 return B.new()
7893 enddef
7894 endclass
7895 END
7896 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
7897
7898 lines =<< trim END
7899 vim9script
7900
7901 class A
7902 endclass
7903 class B extends A
7904 endclass
7905 class C extends B
7906 endclass
7907
7908 class Foo
7909 def Doit(p: B): B
7910 return B.new()
7911 enddef
7912 endclass
7913
7914 class Bar extends Foo
7915 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007916 return C.new()
7917 enddef
7918 endclass
7919 END
7920 v9.CheckSourceSuccess(lines)
7921
7922 lines =<< trim END
7923 vim9script
7924
7925 class A
7926 endclass
7927 class B extends A
7928 endclass
7929 class C extends B
7930 endclass
7931
7932 class Foo
7933 def Doit(p: B): B
7934 return B.new()
7935 enddef
7936 endclass
7937
7938 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007939 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007940 return B.new()
7941 enddef
7942 endclass
7943 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007944 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 +02007945
7946 lines =<< trim END
7947 vim9script
7948
7949 class A
7950 endclass
7951 class B extends A
7952 endclass
7953 class C extends B
7954 endclass
7955
7956 class Foo
7957 def Doit(p: B): B
7958 return B.new()
7959 enddef
7960 endclass
7961
7962 class Bar extends Foo
7963 def Doit(p: B): A
7964 return A.new()
7965 enddef
7966 endclass
7967 END
7968 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<B>): object<A>', 20)
Ernie Rael96952b22023-10-17 18:15:01 +02007969
7970 # check varargs type mismatch
7971 lines =<< trim END
7972 vim9script
7973
7974 class B
7975 def F(...xxx: list<any>)
7976 enddef
7977 endclass
7978 class C extends B
7979 def F(xxx: list<any>)
7980 enddef
7981 endclass
7982 END
7983 v9.CheckSourceFailure(lines, 'E1383: Method "F": type mismatch, expected func(...list<any>) but got func(list<any>)', 10)
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007984enddef
7985
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007986" Test type checking for class variable in assignments
7987func Test_class_variable_complex_type_check()
7988 " class variable with a specific type. Try assigning a different type at
7989 " script level.
7990 let lines =<< trim END
7991 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007992 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007993 return {}
7994 enddef
7995 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007996 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007997 endclass
7998 test_garbagecollect_now()
7999 A.Fn = "abc"
8000 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008001 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 +02008002
8003 " class variable with a specific type. Try assigning a different type at
8004 " class def method level.
8005 let lines =<< trim END
8006 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008007 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008008 return {}
8009 enddef
8010 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008011 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008012 def Bar()
8013 Fn = "abc"
8014 enddef
8015 endclass
8016 var a = A.new()
8017 test_garbagecollect_now()
8018 a.Bar()
8019 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008020 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 +02008021
8022 " class variable with a specific type. Try assigning a different type at
8023 " script def method level.
8024 let lines =<< trim END
8025 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008026 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008027 return {}
8028 enddef
8029 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008030 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008031 endclass
8032 def Bar()
8033 A.Fn = "abc"
8034 enddef
8035 test_garbagecollect_now()
8036 Bar()
8037 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008038 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 +02008039
8040 " class variable without any type. Should be set to the initialization
8041 " expression type. Try assigning a different type from script level.
8042 let lines =<< trim END
8043 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008044 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008045 return {}
8046 enddef
8047 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008048 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008049 endclass
8050 test_garbagecollect_now()
8051 A.Fn = "abc"
8052 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008053 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 +02008054
8055 " class variable without any type. Should be set to the initialization
8056 " expression type. Try assigning a different type at class def level.
8057 let lines =<< trim END
8058 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008059 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008060 return {}
8061 enddef
8062 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008063 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008064 def Bar()
8065 Fn = "abc"
8066 enddef
8067 endclass
8068 var a = A.new()
8069 test_garbagecollect_now()
8070 a.Bar()
8071 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008072 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 +02008073
8074 " class variable without any type. Should be set to the initialization
8075 " expression type. Try assigning a different type at script def level.
8076 let lines =<< trim END
8077 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008078 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008079 return {}
8080 enddef
8081 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008082 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008083 endclass
8084 def Bar()
8085 A.Fn = "abc"
8086 enddef
8087 test_garbagecollect_now()
8088 Bar()
8089 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008090 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 +02008091
8092 " class variable with 'any" type. Can be assigned different types.
8093 let lines =<< trim END
8094 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008095 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008096 return {}
8097 enddef
8098 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008099 public static var Fn: any = Foo
8100 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008101 endclass
8102 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008103 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008104 A.Fn = "abc"
8105 test_garbagecollect_now()
8106 assert_equal('string', typename(A.Fn))
8107 A.Fn2 = Foo
8108 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008109 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008110 A.Fn2 = "xyz"
8111 test_garbagecollect_now()
8112 assert_equal('string', typename(A.Fn2))
8113 END
8114 call v9.CheckSourceSuccess(lines)
8115
8116 " class variable with 'any" type. Can be assigned different types.
8117 let lines =<< trim END
8118 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008119 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008120 return {}
8121 enddef
8122 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008123 public static var Fn: any = Foo
8124 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008125
8126 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008127 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008128 Fn = "abc"
8129 assert_equal('string', typename(Fn))
8130 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008131 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008132 Fn2 = "xyz"
8133 assert_equal('string', typename(Fn2))
8134 enddef
8135 endclass
8136 var a = A.new()
8137 test_garbagecollect_now()
8138 a.Bar()
8139 test_garbagecollect_now()
8140 A.Fn = Foo
8141 a.Bar()
8142 END
8143 call v9.CheckSourceSuccess(lines)
8144
8145 " class variable with 'any" type. Can be assigned different types.
8146 let lines =<< trim END
8147 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008148 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008149 return {}
8150 enddef
8151 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008152 public static var Fn: any = Foo
8153 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008154 endclass
8155
8156 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008157 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008158 A.Fn = "abc"
8159 assert_equal('string', typename(A.Fn))
8160 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008161 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008162 A.Fn2 = "xyz"
8163 assert_equal('string', typename(A.Fn2))
8164 enddef
8165 Bar()
8166 test_garbagecollect_now()
8167 A.Fn = Foo
8168 Bar()
8169 END
8170 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008171
8172 let lines =<< trim END
8173 vim9script
8174 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008175 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008176 endclass
8177 assert_equal([0z10, 0z20], A.foo)
8178 A.foo = [0z30]
8179 assert_equal([0z30], A.foo)
8180 var a = A.foo
8181 assert_equal([0z30], a)
8182 END
8183 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008184endfunc
8185
8186" Test type checking for object variable in assignments
8187func Test_object_variable_complex_type_check()
8188 " object variable with a specific type. Try assigning a different type at
8189 " script level.
8190 let lines =<< trim END
8191 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008192 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008193 return {}
8194 enddef
8195 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008196 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008197 endclass
8198 var a = A.new()
8199 test_garbagecollect_now()
8200 a.Fn = "abc"
8201 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008202 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 +02008203
8204 " object variable with a specific type. Try assigning a different type at
8205 " object def method level.
8206 let lines =<< trim END
8207 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008208 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008209 return {}
8210 enddef
8211 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008212 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008213 def Bar()
8214 this.Fn = "abc"
8215 this.Fn = Foo
8216 enddef
8217 endclass
8218 var a = A.new()
8219 test_garbagecollect_now()
8220 a.Bar()
8221 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008222 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 +02008223
8224 " object variable with a specific type. Try assigning a different type at
8225 " script def method level.
8226 let lines =<< trim END
8227 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008228 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008229 return {}
8230 enddef
8231 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008232 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008233 endclass
8234 def Bar()
8235 var a = A.new()
8236 a.Fn = "abc"
8237 a.Fn = Foo
8238 enddef
8239 test_garbagecollect_now()
8240 Bar()
8241 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008242 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 +02008243
8244 " object variable without any type. Should be set to the initialization
8245 " expression type. Try assigning a different type from script level.
8246 let lines =<< trim END
8247 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008248 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008249 return {}
8250 enddef
8251 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008252 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008253 endclass
8254 var a = A.new()
8255 test_garbagecollect_now()
8256 a.Fn = "abc"
8257 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008258 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 +02008259
8260 " object variable without any type. Should be set to the initialization
8261 " expression type. Try assigning a different type at object def level.
8262 let lines =<< trim END
8263 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008264 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008265 return {}
8266 enddef
8267 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008268 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008269 def Bar()
8270 this.Fn = "abc"
8271 this.Fn = Foo
8272 enddef
8273 endclass
8274 var a = A.new()
8275 test_garbagecollect_now()
8276 a.Bar()
8277 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008278 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 +02008279
8280 " object variable without any type. Should be set to the initialization
8281 " expression type. Try assigning a different type at script def level.
8282 let lines =<< trim END
8283 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008284 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008285 return {}
8286 enddef
8287 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008288 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008289 endclass
8290 def Bar()
8291 var a = A.new()
8292 a.Fn = "abc"
8293 a.Fn = Foo
8294 enddef
8295 test_garbagecollect_now()
8296 Bar()
8297 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008298 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 +02008299
8300 " object variable with 'any" type. Can be assigned different types.
8301 let lines =<< trim END
8302 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008303 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008304 return {}
8305 enddef
8306 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008307 public var Fn: any = Foo
8308 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008309 endclass
8310
8311 var a = A.new()
8312 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008313 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008314 a.Fn = "abc"
8315 test_garbagecollect_now()
8316 assert_equal('string', typename(a.Fn))
8317 a.Fn2 = Foo
8318 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008319 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008320 a.Fn2 = "xyz"
8321 test_garbagecollect_now()
8322 assert_equal('string', typename(a.Fn2))
8323 END
8324 call v9.CheckSourceSuccess(lines)
8325
8326 " object variable with 'any" type. Can be assigned different types.
8327 let lines =<< trim END
8328 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008329 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008330 return {}
8331 enddef
8332 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008333 public var Fn: any = Foo
8334 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008335
8336 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008337 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008338 this.Fn = "abc"
8339 assert_equal('string', typename(this.Fn))
8340 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008341 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008342 this.Fn2 = "xyz"
8343 assert_equal('string', typename(this.Fn2))
8344 enddef
8345 endclass
8346
8347 var a = A.new()
8348 test_garbagecollect_now()
8349 a.Bar()
8350 test_garbagecollect_now()
8351 a.Fn = Foo
8352 a.Bar()
8353 END
8354 call v9.CheckSourceSuccess(lines)
8355
8356 " object variable with 'any" type. Can be assigned different types.
8357 let lines =<< trim END
8358 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008359 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008360 return {}
8361 enddef
8362 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008363 public var Fn: any = Foo
8364 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008365 endclass
8366
8367 def Bar()
8368 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008369 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008370 a.Fn = "abc"
8371 assert_equal('string', typename(a.Fn))
8372 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008373 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008374 a.Fn2 = "xyz"
8375 assert_equal('string', typename(a.Fn2))
8376 enddef
8377 test_garbagecollect_now()
8378 Bar()
8379 test_garbagecollect_now()
8380 Bar()
8381 END
8382 call v9.CheckSourceSuccess(lines)
8383endfunc
8384
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008385" Test for recursively calling an object method. This used to cause an
8386" use-after-free error.
8387def Test_recursive_object_method_call()
8388 var lines =<< trim END
8389 vim9script
8390 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008391 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008392 def Foo(): number
8393 if this.val >= 90
8394 return this.val
8395 endif
8396 this.val += 1
8397 return this.Foo()
8398 enddef
8399 endclass
8400 var a = A.new()
8401 assert_equal(90, a.Foo())
8402 END
8403 v9.CheckSourceSuccess(lines)
8404enddef
8405
8406" Test for recursively calling a class method.
8407def Test_recursive_class_method_call()
8408 var lines =<< trim END
8409 vim9script
8410 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008411 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008412 static def Foo(): number
8413 if val >= 90
8414 return val
8415 endif
8416 val += 1
8417 return Foo()
8418 enddef
8419 endclass
8420 assert_equal(90, A.Foo())
8421 END
8422 v9.CheckSourceSuccess(lines)
8423enddef
8424
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008425" Test for checking the argument types and the return type when assigning a
8426" funcref to make sure the invariant class type is used.
8427def Test_funcref_argtype_returntype_check()
8428 var lines =<< trim END
8429 vim9script
8430 class A
8431 endclass
8432 class B extends A
8433 endclass
8434
8435 def Foo(p: B): B
8436 return B.new()
8437 enddef
8438
8439 var Bar: func(A): A = Foo
8440 END
8441 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8442
8443 lines =<< trim END
8444 vim9script
8445 class A
8446 endclass
8447 class B extends A
8448 endclass
8449
8450 def Foo(p: B): B
8451 return B.new()
8452 enddef
8453
8454 def Baz()
8455 var Bar: func(A): A = Foo
8456 enddef
8457 Baz()
8458 END
8459 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8460enddef
8461
Ernie Rael96952b22023-10-17 18:15:01 +02008462def Test_funcref_argtype_invariance_check()
8463 var lines =<< trim END
8464 vim9script
8465
8466 class A
8467 endclass
8468 class B extends A
8469 endclass
8470 class C extends B
8471 endclass
8472
8473 var Func: func(B): number
8474 Func = (o: B): number => 3
8475 assert_equal(3, Func(B.new()))
8476 END
8477 v9.CheckSourceSuccess(lines)
8478
8479 lines =<< trim END
8480 vim9script
8481
8482 class A
8483 endclass
8484 class B extends A
8485 endclass
8486 class C extends B
8487 endclass
8488
8489 var Func: func(B): number
8490 Func = (o: A): number => 3
8491 END
8492 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8493
8494 lines =<< trim END
8495 vim9script
8496
8497 class A
8498 endclass
8499 class B extends A
8500 endclass
8501 class C extends B
8502 endclass
8503
8504 var Func: func(B): number
8505 Func = (o: C): number => 3
8506 END
8507 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8508enddef
8509
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008510" Test for using an operator (e.g. +) with an assignment
8511def Test_op_and_assignment()
8512 # Using += with a class variable
8513 var lines =<< trim END
8514 vim9script
8515 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008516 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008517 static def Foo(): list<number>
8518 val += [1]
8519 return val
8520 enddef
8521 endclass
8522 def Bar(): list<number>
8523 A.val += [2]
8524 return A.val
8525 enddef
8526 assert_equal([1], A.Foo())
8527 assert_equal([1, 2], Bar())
8528 A.val += [3]
8529 assert_equal([1, 2, 3], A.val)
8530 END
8531 v9.CheckSourceSuccess(lines)
8532
8533 # Using += with an object variable
8534 lines =<< trim END
8535 vim9script
8536 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008537 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008538 def Foo(): list<number>
8539 this.val += [1]
8540 return this.val
8541 enddef
8542 endclass
8543 def Bar(bar_a: A): list<number>
8544 bar_a.val += [2]
8545 return bar_a.val
8546 enddef
8547 var a = A.new()
8548 assert_equal([1], a.Foo())
8549 assert_equal([1, 2], Bar(a))
8550 a.val += [3]
8551 assert_equal([1, 2, 3], a.val)
8552 END
8553 v9.CheckSourceSuccess(lines)
8554enddef
8555
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008556" Test for using an object method as a funcref
8557def Test_object_funcref()
8558 # Using object method funcref from a def function
8559 var lines =<< trim END
8560 vim9script
8561 class A
8562 def Foo(): list<number>
8563 return [3, 2, 1]
8564 enddef
8565 endclass
8566 def Bar()
8567 var a = A.new()
8568 var Fn = a.Foo
8569 assert_equal([3, 2, 1], Fn())
8570 enddef
8571 Bar()
8572 END
8573 v9.CheckSourceSuccess(lines)
8574
8575 # Using object method funcref at the script level
8576 lines =<< trim END
8577 vim9script
8578 class A
8579 def Foo(): dict<number>
8580 return {a: 1, b: 2}
8581 enddef
8582 endclass
8583 var a = A.new()
8584 var Fn = a.Foo
8585 assert_equal({a: 1, b: 2}, Fn())
8586 END
8587 v9.CheckSourceSuccess(lines)
8588
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008589 # Using object method funcref at the script level
8590 lines =<< trim END
8591 vim9script
8592 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008593 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008594 def Foo(): number
8595 return this.val
8596 enddef
8597 endclass
8598 var a = A.new(345)
8599 var Fn = a.Foo
8600 assert_equal(345, Fn())
8601 END
8602 v9.CheckSourceSuccess(lines)
8603
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008604 # Using object method funcref from another object method
8605 lines =<< trim END
8606 vim9script
8607 class A
8608 def Foo(): list<number>
8609 return [3, 2, 1]
8610 enddef
8611 def Bar()
8612 var Fn = this.Foo
8613 assert_equal([3, 2, 1], Fn())
8614 enddef
8615 endclass
8616 var a = A.new()
8617 a.Bar()
8618 END
8619 v9.CheckSourceSuccess(lines)
8620
8621 # Using function() to get a object method funcref
8622 lines =<< trim END
8623 vim9script
8624 class A
8625 def Foo(l: list<any>): list<any>
8626 return l
8627 enddef
8628 endclass
8629 var a = A.new()
8630 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8631 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8632 END
8633 v9.CheckSourceSuccess(lines)
8634
8635 # Use an object method with a function returning a funcref and then call the
8636 # funcref.
8637 lines =<< trim END
8638 vim9script
8639
8640 def Map(F: func(number): number): func(number): number
8641 return (n: number) => F(n)
8642 enddef
8643
8644 class Math
8645 def Double(n: number): number
8646 return 2 * n
8647 enddef
8648 endclass
8649
8650 const math = Math.new()
8651 assert_equal(48, Map(math.Double)(24))
8652 END
8653 v9.CheckSourceSuccess(lines)
8654
Ernie Rael03042a22023-11-11 08:53:32 +01008655 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008656 lines =<< trim END
8657 vim9script
8658 class A
8659 def _Foo()
8660 enddef
8661 endclass
8662 def Bar()
8663 var a = A.new()
8664 var Fn = a._Foo
8665 enddef
8666 Bar()
8667 END
Ernie Rael03042a22023-11-11 08:53:32 +01008668 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008669
Ernie Rael03042a22023-11-11 08:53:32 +01008670 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008671 lines =<< trim END
8672 vim9script
8673 class A
8674 def _Foo()
8675 enddef
8676 endclass
8677 var a = A.new()
8678 var Fn = a._Foo
8679 END
Ernie Rael03042a22023-11-11 08:53:32 +01008680 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008681
Ernie Rael03042a22023-11-11 08:53:32 +01008682 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008683 lines =<< trim END
8684 vim9script
8685 class A
8686 def _Foo(): list<number>
8687 return [3, 2, 1]
8688 enddef
8689 def Bar()
8690 var Fn = this._Foo
8691 assert_equal([3, 2, 1], Fn())
8692 enddef
8693 endclass
8694 var a = A.new()
8695 a.Bar()
8696 END
8697 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008698
8699 # Using object method funcref using call()
8700 lines =<< trim END
8701 vim9script
8702 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008703 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008704 def Foo(): number
8705 return this.val
8706 enddef
8707 endclass
8708
8709 def Bar(obj: A)
8710 assert_equal(123, call(obj.Foo, []))
8711 enddef
8712
8713 var a = A.new(123)
8714 Bar(a)
8715 assert_equal(123, call(a.Foo, []))
8716 END
8717 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008718enddef
8719
8720" Test for using a class method as a funcref
8721def Test_class_funcref()
8722 # Using class method funcref in a def function
8723 var lines =<< trim END
8724 vim9script
8725 class A
8726 static def Foo(): list<number>
8727 return [3, 2, 1]
8728 enddef
8729 endclass
8730 def Bar()
8731 var Fn = A.Foo
8732 assert_equal([3, 2, 1], Fn())
8733 enddef
8734 Bar()
8735 END
8736 v9.CheckSourceSuccess(lines)
8737
8738 # Using class method funcref at script level
8739 lines =<< trim END
8740 vim9script
8741 class A
8742 static def Foo(): dict<number>
8743 return {a: 1, b: 2}
8744 enddef
8745 endclass
8746 var Fn = A.Foo
8747 assert_equal({a: 1, b: 2}, Fn())
8748 END
8749 v9.CheckSourceSuccess(lines)
8750
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008751 # Using class method funcref at the script level
8752 lines =<< trim END
8753 vim9script
8754 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008755 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008756 static def Foo(): number
8757 return val
8758 enddef
8759 endclass
8760 A.val = 567
8761 var Fn = A.Foo
8762 assert_equal(567, Fn())
8763 END
8764 v9.CheckSourceSuccess(lines)
8765
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008766 # Using function() to get a class method funcref
8767 lines =<< trim END
8768 vim9script
8769 class A
8770 static def Foo(l: list<any>): list<any>
8771 return l
8772 enddef
8773 endclass
8774 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8775 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8776 END
8777 v9.CheckSourceSuccess(lines)
8778
8779 # Using a class method funcref from another class method
8780 lines =<< trim END
8781 vim9script
8782 class A
8783 static def Foo(): list<number>
8784 return [3, 2, 1]
8785 enddef
8786 static def Bar()
8787 var Fn = Foo
8788 assert_equal([3, 2, 1], Fn())
8789 enddef
8790 endclass
8791 A.Bar()
8792 END
8793 v9.CheckSourceSuccess(lines)
8794
8795 # Use a class method with a function returning a funcref and then call the
8796 # funcref.
8797 lines =<< trim END
8798 vim9script
8799
8800 def Map(F: func(number): number): func(number): number
8801 return (n: number) => F(n)
8802 enddef
8803
8804 class Math
8805 static def StaticDouble(n: number): number
8806 return 2 * n
8807 enddef
8808 endclass
8809
8810 assert_equal(48, Map(Math.StaticDouble)(24))
8811 END
8812 v9.CheckSourceSuccess(lines)
8813
Ernie Rael03042a22023-11-11 08:53:32 +01008814 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008815 lines =<< trim END
8816 vim9script
8817 class A
8818 static def _Foo()
8819 enddef
8820 endclass
8821 def Bar()
8822 var Fn = A._Foo
8823 enddef
8824 Bar()
8825 END
Ernie Rael03042a22023-11-11 08:53:32 +01008826 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008827
Ernie Rael03042a22023-11-11 08:53:32 +01008828 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008829 lines =<< trim END
8830 vim9script
8831 class A
8832 static def _Foo()
8833 enddef
8834 endclass
8835 var Fn = A._Foo
8836 END
Ernie Rael03042a22023-11-11 08:53:32 +01008837 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008838
Ernie Rael03042a22023-11-11 08:53:32 +01008839 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008840 lines =<< trim END
8841 vim9script
8842 class A
8843 static def _Foo(): list<number>
8844 return [3, 2, 1]
8845 enddef
8846 static def Bar()
8847 var Fn = _Foo
8848 assert_equal([3, 2, 1], Fn())
8849 enddef
8850 endclass
8851 A.Bar()
8852 END
8853 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008854
8855 # Using class method funcref using call()
8856 lines =<< trim END
8857 vim9script
8858 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008859 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008860 static def Foo(): number
8861 return val
8862 enddef
8863 endclass
8864
8865 def Bar()
8866 A.val = 468
8867 assert_equal(468, call(A.Foo, []))
8868 enddef
8869 Bar()
8870 assert_equal(468, call(A.Foo, []))
8871 END
8872 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008873enddef
8874
8875" Test for using an object member as a funcref
8876def Test_object_member_funcref()
8877 # Using a funcref object variable in an object method
8878 var lines =<< trim END
8879 vim9script
8880 def Foo(n: number): number
8881 return n * 10
8882 enddef
8883
8884 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008885 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008886 def Bar()
8887 assert_equal(200, this.Cb(20))
8888 enddef
8889 endclass
8890
8891 var a = A.new()
8892 a.Bar()
8893 END
8894 v9.CheckSourceSuccess(lines)
8895
8896 # Using a funcref object variable in a def method
8897 lines =<< trim END
8898 vim9script
8899 def Foo(n: number): number
8900 return n * 10
8901 enddef
8902
8903 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008904 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008905 endclass
8906
8907 def Bar()
8908 var a = A.new()
8909 assert_equal(200, a.Cb(20))
8910 enddef
8911 Bar()
8912 END
8913 v9.CheckSourceSuccess(lines)
8914
8915 # Using a funcref object variable at script level
8916 lines =<< trim END
8917 vim9script
8918 def Foo(n: number): number
8919 return n * 10
8920 enddef
8921
8922 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008923 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008924 endclass
8925
8926 var a = A.new()
8927 assert_equal(200, a.Cb(20))
8928 END
8929 v9.CheckSourceSuccess(lines)
8930
8931 # Using a funcref object variable pointing to an object method in an object
8932 # method.
8933 lines =<< trim END
8934 vim9script
8935 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008936 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008937 def Foo(n: number): number
8938 return n * 10
8939 enddef
8940 def Bar()
8941 assert_equal(200, this.Cb(20))
8942 enddef
8943 endclass
8944
8945 var a = A.new()
8946 a.Bar()
8947 END
8948 v9.CheckSourceSuccess(lines)
8949
8950 # Using a funcref object variable pointing to an object method in a def
8951 # method.
8952 lines =<< trim END
8953 vim9script
8954 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008955 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008956 def Foo(n: number): number
8957 return n * 10
8958 enddef
8959 endclass
8960
8961 def Bar()
8962 var a = A.new()
8963 assert_equal(200, a.Cb(20))
8964 enddef
8965 Bar()
8966 END
8967 v9.CheckSourceSuccess(lines)
8968
8969 # Using a funcref object variable pointing to an object method at script
8970 # level.
8971 lines =<< trim END
8972 vim9script
8973 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008974 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008975 def Foo(n: number): number
8976 return n * 10
8977 enddef
8978 endclass
8979
8980 var a = A.new()
8981 assert_equal(200, a.Cb(20))
8982 END
8983 v9.CheckSourceSuccess(lines)
8984enddef
8985
8986" Test for using a class member as a funcref
8987def Test_class_member_funcref()
8988 # Using a funcref class variable in a class method
8989 var lines =<< trim END
8990 vim9script
8991 def Foo(n: number): number
8992 return n * 10
8993 enddef
8994
8995 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008996 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008997 static def Bar()
8998 assert_equal(200, Cb(20))
8999 enddef
9000 endclass
9001
9002 A.Bar()
9003 END
9004 v9.CheckSourceSuccess(lines)
9005
9006 # Using a funcref class variable in a def method
9007 lines =<< trim END
9008 vim9script
9009 def Foo(n: number): number
9010 return n * 10
9011 enddef
9012
9013 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009014 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009015 endclass
9016
9017 def Bar()
9018 assert_equal(200, A.Cb(20))
9019 enddef
9020 Bar()
9021 END
9022 v9.CheckSourceSuccess(lines)
9023
9024 # Using a funcref class variable at script level
9025 lines =<< trim END
9026 vim9script
9027 def Foo(n: number): number
9028 return n * 10
9029 enddef
9030
9031 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009032 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009033 endclass
9034
9035 assert_equal(200, A.Cb(20))
9036 END
9037 v9.CheckSourceSuccess(lines)
9038
9039 # Using a funcref class variable pointing to a class method in a class
9040 # method.
9041 lines =<< trim END
9042 vim9script
9043 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009044 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009045 static def Foo(n: number): number
9046 return n * 10
9047 enddef
9048 static def Init()
9049 Cb = Foo
9050 enddef
9051 static def Bar()
9052 assert_equal(200, Cb(20))
9053 enddef
9054 endclass
9055
9056 A.Init()
9057 A.Bar()
9058 END
9059 v9.CheckSourceSuccess(lines)
9060
9061 # Using a funcref class variable pointing to a class method in a def method.
9062 lines =<< trim END
9063 vim9script
9064 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009065 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009066 static def Foo(n: number): number
9067 return n * 10
9068 enddef
9069 static def Init()
9070 Cb = Foo
9071 enddef
9072 endclass
9073
9074 def Bar()
9075 A.Init()
9076 assert_equal(200, A.Cb(20))
9077 enddef
9078 Bar()
9079 END
9080 v9.CheckSourceSuccess(lines)
9081
9082 # Using a funcref class variable pointing to a class method at script level.
9083 lines =<< trim END
9084 vim9script
9085 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009086 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009087 static def Foo(n: number): number
9088 return n * 10
9089 enddef
9090 static def Init()
9091 Cb = Foo
9092 enddef
9093 endclass
9094
9095 A.Init()
9096 assert_equal(200, A.Cb(20))
9097 END
9098 v9.CheckSourceSuccess(lines)
9099enddef
9100
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009101" Test for using object methods as popup callback functions
9102def Test_objmethod_popup_callback()
9103 # Use the popup from the script level
9104 var lines =<< trim END
9105 vim9script
9106
9107 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009108 var selection: number = -1
9109 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009110
9111 def PopupFilter(id: number, key: string): bool
9112 add(this.filterkeys, key)
9113 return popup_filter_yesno(id, key)
9114 enddef
9115
9116 def PopupCb(id: number, result: number)
9117 this.selection = result ? 100 : 200
9118 enddef
9119 endclass
9120
9121 var a = A.new()
9122 feedkeys('', 'xt')
9123 var winid = popup_create('Y/N?',
9124 {filter: a.PopupFilter, callback: a.PopupCb})
9125 feedkeys('y', 'xt')
9126 popup_close(winid)
9127 assert_equal(100, a.selection)
9128 assert_equal(['y'], a.filterkeys)
9129 feedkeys('', 'xt')
9130 winid = popup_create('Y/N?',
9131 {filter: a.PopupFilter, callback: a.PopupCb})
9132 feedkeys('n', 'xt')
9133 popup_close(winid)
9134 assert_equal(200, a.selection)
9135 assert_equal(['y', 'n'], a.filterkeys)
9136 END
9137 v9.CheckSourceSuccess(lines)
9138
9139 # Use the popup from a def function
9140 lines =<< trim END
9141 vim9script
9142
9143 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009144 var selection: number = -1
9145 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009146
9147 def PopupFilter(id: number, key: string): bool
9148 add(this.filterkeys, key)
9149 return popup_filter_yesno(id, key)
9150 enddef
9151
9152 def PopupCb(id: number, result: number)
9153 this.selection = result ? 100 : 200
9154 enddef
9155 endclass
9156
9157 def Foo()
9158 var a = A.new()
9159 feedkeys('', 'xt')
9160 var winid = popup_create('Y/N?',
9161 {filter: a.PopupFilter, callback: a.PopupCb})
9162 feedkeys('y', 'xt')
9163 popup_close(winid)
9164 assert_equal(100, a.selection)
9165 assert_equal(['y'], a.filterkeys)
9166 feedkeys('', 'xt')
9167 winid = popup_create('Y/N?',
9168 {filter: a.PopupFilter, callback: a.PopupCb})
9169 feedkeys('n', 'xt')
9170 popup_close(winid)
9171 assert_equal(200, a.selection)
9172 assert_equal(['y', 'n'], a.filterkeys)
9173 enddef
9174 Foo()
9175 END
9176 v9.CheckSourceSuccess(lines)
9177enddef
9178
9179" Test for using class methods as popup callback functions
9180def Test_classmethod_popup_callback()
9181 # Use the popup from the script level
9182 var lines =<< trim END
9183 vim9script
9184
9185 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009186 static var selection: number = -1
9187 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009188
9189 static def PopupFilter(id: number, key: string): bool
9190 add(filterkeys, key)
9191 return popup_filter_yesno(id, key)
9192 enddef
9193
9194 static def PopupCb(id: number, result: number)
9195 selection = result ? 100 : 200
9196 enddef
9197 endclass
9198
9199 feedkeys('', 'xt')
9200 var winid = popup_create('Y/N?',
9201 {filter: A.PopupFilter, callback: A.PopupCb})
9202 feedkeys('y', 'xt')
9203 popup_close(winid)
9204 assert_equal(100, A.selection)
9205 assert_equal(['y'], A.filterkeys)
9206 feedkeys('', 'xt')
9207 winid = popup_create('Y/N?',
9208 {filter: A.PopupFilter, callback: A.PopupCb})
9209 feedkeys('n', 'xt')
9210 popup_close(winid)
9211 assert_equal(200, A.selection)
9212 assert_equal(['y', 'n'], A.filterkeys)
9213 END
9214 v9.CheckSourceSuccess(lines)
9215
9216 # Use the popup from a def function
9217 lines =<< trim END
9218 vim9script
9219
9220 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009221 static var selection: number = -1
9222 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009223
9224 static def PopupFilter(id: number, key: string): bool
9225 add(filterkeys, key)
9226 return popup_filter_yesno(id, key)
9227 enddef
9228
9229 static def PopupCb(id: number, result: number)
9230 selection = result ? 100 : 200
9231 enddef
9232 endclass
9233
9234 def Foo()
9235 feedkeys('', 'xt')
9236 var winid = popup_create('Y/N?',
9237 {filter: A.PopupFilter, callback: A.PopupCb})
9238 feedkeys('y', 'xt')
9239 popup_close(winid)
9240 assert_equal(100, A.selection)
9241 assert_equal(['y'], A.filterkeys)
9242 feedkeys('', 'xt')
9243 winid = popup_create('Y/N?',
9244 {filter: A.PopupFilter, callback: A.PopupCb})
9245 feedkeys('n', 'xt')
9246 popup_close(winid)
9247 assert_equal(200, A.selection)
9248 assert_equal(['y', 'n'], A.filterkeys)
9249 enddef
9250 Foo()
9251 END
9252 v9.CheckSourceSuccess(lines)
9253enddef
9254
9255" Test for using an object method as a timer callback function
9256def Test_objmethod_timer_callback()
9257 # Use the timer callback from script level
9258 var lines =<< trim END
9259 vim9script
9260
9261 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009262 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009263 def TimerCb(timerID: number)
9264 this.timerTick = 6
9265 enddef
9266 endclass
9267
9268 var a = A.new()
9269 timer_start(0, a.TimerCb)
9270 var maxWait = 5
9271 while maxWait > 0 && a.timerTick == -1
9272 :sleep 10m
9273 maxWait -= 1
9274 endwhile
9275 assert_equal(6, a.timerTick)
9276 END
9277 v9.CheckSourceSuccess(lines)
9278
9279 # Use the timer callback from a def function
9280 lines =<< trim END
9281 vim9script
9282
9283 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009284 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009285 def TimerCb(timerID: number)
9286 this.timerTick = 6
9287 enddef
9288 endclass
9289
9290 def Foo()
9291 var a = A.new()
9292 timer_start(0, a.TimerCb)
9293 var maxWait = 5
9294 while maxWait > 0 && a.timerTick == -1
9295 :sleep 10m
9296 maxWait -= 1
9297 endwhile
9298 assert_equal(6, a.timerTick)
9299 enddef
9300 Foo()
9301 END
9302 v9.CheckSourceSuccess(lines)
9303enddef
9304
9305" Test for using a class method as a timer callback function
9306def Test_classmethod_timer_callback()
9307 # Use the timer callback from script level
9308 var lines =<< trim END
9309 vim9script
9310
9311 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009312 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009313 static def TimerCb(timerID: number)
9314 timerTick = 6
9315 enddef
9316 endclass
9317
9318 timer_start(0, A.TimerCb)
9319 var maxWait = 5
9320 while maxWait > 0 && A.timerTick == -1
9321 :sleep 10m
9322 maxWait -= 1
9323 endwhile
9324 assert_equal(6, A.timerTick)
9325 END
9326 v9.CheckSourceSuccess(lines)
9327
9328 # Use the timer callback from a def function
9329 lines =<< trim END
9330 vim9script
9331
9332 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009333 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009334 static def TimerCb(timerID: number)
9335 timerTick = 6
9336 enddef
9337 endclass
9338
9339 def Foo()
9340 timer_start(0, A.TimerCb)
9341 var maxWait = 5
9342 while maxWait > 0 && A.timerTick == -1
9343 :sleep 10m
9344 maxWait -= 1
9345 endwhile
9346 assert_equal(6, A.timerTick)
9347 enddef
9348 Foo()
9349 END
9350 v9.CheckSourceSuccess(lines)
9351enddef
9352
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009353" Test for using a class variable as the first and/or second operand of a binary
9354" operator.
9355def Test_class_variable_as_operands()
9356 var lines =<< trim END
9357 vim9script
9358 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009359 static var truthy: bool = true
9360 public static var TruthyFn: func
9361 static var list: list<any> = []
9362 static var four: number = 4
9363 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009364
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009365 static def Str(): string
9366 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009367 enddef
9368
9369 static def Four(): number
9370 return four
9371 enddef
9372
9373 static def List(): list<any>
9374 return list
9375 enddef
9376
9377 static def Truthy(): bool
9378 return truthy
9379 enddef
9380
9381 def TestOps()
9382 assert_true(Tests.truthy == truthy)
9383 assert_true(truthy == Tests.truthy)
9384 assert_true(Tests.list isnot [])
9385 assert_true([] isnot Tests.list)
9386 assert_equal(2, Tests.four >> 1)
9387 assert_equal(16, 1 << Tests.four)
9388 assert_equal(8, Tests.four + four)
9389 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009390 assert_equal('hellohello', Tests.str .. str)
9391 assert_equal('hellohello', str .. Tests.str)
9392
9393 # Using class variable for list indexing
9394 var l = range(10)
9395 assert_equal(4, l[Tests.four])
9396 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9397
9398 # Using class variable for Dict key
9399 var d = {hello: 'abc'}
9400 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009401 enddef
9402 endclass
9403
9404 def TestOps2()
9405 assert_true(Tests.truthy == Tests.Truthy())
9406 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009407 assert_true(Tests.truthy == Tests.TruthyFn())
9408 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009409 assert_true(Tests.list is Tests.List())
9410 assert_true(Tests.List() is Tests.list)
9411 assert_equal(2, Tests.four >> 1)
9412 assert_equal(16, 1 << Tests.four)
9413 assert_equal(8, Tests.four + Tests.Four())
9414 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009415 assert_equal('hellohello', Tests.str .. Tests.Str())
9416 assert_equal('hellohello', Tests.Str() .. Tests.str)
9417
9418 # Using class variable for list indexing
9419 var l = range(10)
9420 assert_equal(4, l[Tests.four])
9421 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9422
9423 # Using class variable for Dict key
9424 var d = {hello: 'abc'}
9425 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009426 enddef
9427
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009428 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009429 var t = Tests.new()
9430 t.TestOps()
9431 TestOps2()
9432
9433 assert_true(Tests.truthy == Tests.Truthy())
9434 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009435 assert_true(Tests.truthy == Tests.TruthyFn())
9436 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009437 assert_true(Tests.list is Tests.List())
9438 assert_true(Tests.List() is Tests.list)
9439 assert_equal(2, Tests.four >> 1)
9440 assert_equal(16, 1 << Tests.four)
9441 assert_equal(8, Tests.four + Tests.Four())
9442 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009443 assert_equal('hellohello', Tests.str .. Tests.Str())
9444 assert_equal('hellohello', Tests.Str() .. Tests.str)
9445
9446 # Using class variable for list indexing
9447 var l = range(10)
9448 assert_equal(4, l[Tests.four])
9449 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9450
9451 # Using class variable for Dict key
9452 var d = {hello: 'abc'}
9453 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009454 END
9455 v9.CheckSourceSuccess(lines)
9456enddef
9457
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009458" Test for checking the type of the key used to access an object dict member.
9459def Test_dict_member_key_type_check()
9460 var lines =<< trim END
9461 vim9script
9462
9463 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009464 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009465 endclass
9466
9467 class Test extends State
9468 def ObjMethodTests()
9469 var cursor: number = 0
9470 var z: number = 0
9471 [this.numbers[cursor]] = ['zero.1']
9472 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9473 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9474 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9475 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9476 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9477 [this.numbers[cursor], z] = ['zero.4', 1]
9478 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9479 [z, this.numbers[cursor]] = [1, 'zero.5']
9480 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9481 enddef
9482
9483 static def ClassMethodTests(that: State)
9484 var cursor: number = 0
9485 var z: number = 0
9486 [that.numbers[cursor]] = ['zero.1']
9487 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9488 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9489 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9490 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9491 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9492 [that.numbers[cursor], z] = ['zero.4', 1]
9493 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9494 [z, that.numbers[cursor]] = [1, 'zero.5']
9495 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9496 enddef
9497
9498 def new()
9499 enddef
9500
9501 def newMethodTests()
9502 var cursor: number = 0
9503 var z: number
9504 [this.numbers[cursor]] = ['zero.1']
9505 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9506 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9507 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9508 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9509 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9510 [this.numbers[cursor], z] = ['zero.4', 1]
9511 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9512 [z, this.numbers[cursor]] = [1, 'zero.5']
9513 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9514 enddef
9515 endclass
9516
9517 def DefFuncTests(that: Test)
9518 var cursor: number = 0
9519 var z: number
9520 [that.numbers[cursor]] = ['zero.1']
9521 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9522 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9523 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9524 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9525 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9526 [that.numbers[cursor], z] = ['zero.4', 1]
9527 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9528 [z, that.numbers[cursor]] = [1, 'zero.5']
9529 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9530 enddef
9531
9532 Test.newMethodTests()
9533 Test.new().ObjMethodTests()
9534 Test.ClassMethodTests(Test.new())
9535 DefFuncTests(Test.new())
9536
9537 const test: Test = Test.new()
9538 var cursor: number = 0
9539 [test.numbers[cursor], cursor] = ['zero', 1]
9540 [cursor, test.numbers[cursor]] = [1, 'one']
9541 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9542 END
9543 v9.CheckSourceSuccess(lines)
9544
9545 lines =<< trim END
9546 vim9script
9547
9548 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009549 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009550
9551 def new()
9552 enddef
9553
9554 def Foo()
9555 var z: number
9556 [this.numbers.a, z] = [{}, 10]
9557 enddef
9558 endclass
9559
9560 var a = A.new()
9561 a.Foo()
9562 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009563 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009564
9565 lines =<< trim END
9566 vim9script
9567
9568 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009569 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009570
9571 def new()
9572 enddef
9573
9574 def Foo()
9575 var x: string = 'a'
9576 var y: number
9577 [this.numbers[x], y] = [{}, 10]
9578 enddef
9579 endclass
9580
9581 var a = A.new()
9582 a.Foo()
9583 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009584 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009585enddef
9586
mityua5550692023-11-25 15:41:20 +01009587def Test_compile_many_def_functions_in_funcref_instr()
9588 # This used to crash Vim. This is reproducible only when run on new instance
9589 # of Vim.
9590 var lines =<< trim END
9591 vim9script
9592
9593 class A
9594 def new()
9595 this.TakeFunc(this.F00)
9596 enddef
9597
9598 def TakeFunc(F: func)
9599 enddef
9600
9601 def F00()
9602 this.F01()
9603 this.F02()
9604 this.F03()
9605 this.F04()
9606 this.F05()
9607 this.F06()
9608 this.F07()
9609 this.F08()
9610 this.F09()
9611 this.F10()
9612 this.F11()
9613 this.F12()
9614 this.F13()
9615 this.F14()
9616 this.F15()
9617 this.F16()
9618 this.F17()
9619 this.F18()
9620 this.F19()
9621 this.F20()
9622 this.F21()
9623 this.F22()
9624 this.F23()
9625 this.F24()
9626 this.F25()
9627 this.F26()
9628 this.F27()
9629 this.F28()
9630 this.F29()
9631 this.F30()
9632 this.F31()
9633 this.F32()
9634 this.F33()
9635 this.F34()
9636 this.F35()
9637 this.F36()
9638 this.F37()
9639 this.F38()
9640 this.F39()
9641 this.F40()
9642 this.F41()
9643 this.F42()
9644 this.F43()
9645 this.F44()
9646 this.F45()
9647 this.F46()
9648 this.F47()
9649 enddef
9650
9651 def F01()
9652 enddef
9653 def F02()
9654 enddef
9655 def F03()
9656 enddef
9657 def F04()
9658 enddef
9659 def F05()
9660 enddef
9661 def F06()
9662 enddef
9663 def F07()
9664 enddef
9665 def F08()
9666 enddef
9667 def F09()
9668 enddef
9669 def F10()
9670 enddef
9671 def F11()
9672 enddef
9673 def F12()
9674 enddef
9675 def F13()
9676 enddef
9677 def F14()
9678 enddef
9679 def F15()
9680 enddef
9681 def F16()
9682 enddef
9683 def F17()
9684 enddef
9685 def F18()
9686 enddef
9687 def F19()
9688 enddef
9689 def F20()
9690 enddef
9691 def F21()
9692 enddef
9693 def F22()
9694 enddef
9695 def F23()
9696 enddef
9697 def F24()
9698 enddef
9699 def F25()
9700 enddef
9701 def F26()
9702 enddef
9703 def F27()
9704 enddef
9705 def F28()
9706 enddef
9707 def F29()
9708 enddef
9709 def F30()
9710 enddef
9711 def F31()
9712 enddef
9713 def F32()
9714 enddef
9715 def F33()
9716 enddef
9717 def F34()
9718 enddef
9719 def F35()
9720 enddef
9721 def F36()
9722 enddef
9723 def F37()
9724 enddef
9725 def F38()
9726 enddef
9727 def F39()
9728 enddef
9729 def F40()
9730 enddef
9731 def F41()
9732 enddef
9733 def F42()
9734 enddef
9735 def F43()
9736 enddef
9737 def F44()
9738 enddef
9739 def F45()
9740 enddef
9741 def F46()
9742 enddef
9743 def F47()
9744 enddef
9745 endclass
9746
9747 A.new()
9748 END
9749 writefile(lines, 'Xscript', 'D')
9750 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9751 assert_equal(0, v:shell_error)
9752enddef
9753
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009754" Test for 'final' class and object variables
9755def Test_final_class_object_variable()
9756 # Test for changing a final object variable from an object function
9757 var lines =<< trim END
9758 vim9script
9759 class A
9760 final foo: string = "abc"
9761 def Foo()
9762 this.foo = "def"
9763 enddef
9764 endclass
9765 defcompile A.Foo
9766 END
9767 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9768
9769 # Test for changing a final object variable from the 'new' function
9770 lines =<< trim END
9771 vim9script
9772 class A
9773 final s1: string
9774 final s2: string
9775 def new(this.s1)
9776 this.s2 = 'def'
9777 enddef
9778 endclass
9779 var a = A.new('abc')
9780 assert_equal('abc', a.s1)
9781 assert_equal('def', a.s2)
9782 END
9783 v9.CheckSourceSuccess(lines)
9784
9785 # Test for a final class variable
9786 lines =<< trim END
9787 vim9script
9788 class A
9789 static final s1: string = "abc"
9790 endclass
9791 assert_equal('abc', A.s1)
9792 END
9793 v9.CheckSourceSuccess(lines)
9794
9795 # Test for changing a final class variable from a class function
9796 lines =<< trim END
9797 vim9script
9798 class A
9799 static final s1: string = "abc"
9800 static def Foo()
9801 s1 = "def"
9802 enddef
9803 endclass
9804 A.Foo()
9805 END
9806 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9807
9808 # Test for changing a public final class variable at script level
9809 lines =<< trim END
9810 vim9script
9811 class A
9812 public static final s1: string = "abc"
9813 endclass
9814 assert_equal('abc', A.s1)
9815 A.s1 = 'def'
9816 END
9817 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9818
9819 # Test for changing a public final class variable from a class function
9820 lines =<< trim END
9821 vim9script
9822 class A
9823 public static final s1: string = "abc"
9824 static def Foo()
9825 s1 = "def"
9826 enddef
9827 endclass
9828 A.Foo()
9829 END
9830 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9831
9832 # Test for changing a public final class variable from a function
9833 lines =<< trim END
9834 vim9script
9835 class A
9836 public static final s1: string = "abc"
9837 endclass
9838 def Foo()
9839 A.s1 = 'def'
9840 enddef
9841 defcompile
9842 END
9843 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9844
9845 # Test for using a final variable of composite type
9846 lines =<< trim END
9847 vim9script
9848 class A
9849 public final l: list<number>
9850 def new()
9851 this.l = [1, 2]
9852 enddef
9853 def Foo()
9854 this.l[0] = 3
9855 this.l->add(4)
9856 enddef
9857 endclass
9858 var a = A.new()
9859 assert_equal([1, 2], a.l)
9860 a.Foo()
9861 assert_equal([3, 2, 4], a.l)
9862 END
9863 v9.CheckSourceSuccess(lines)
9864
9865 # Test for changing a final variable of composite type from another object
9866 # function
9867 lines =<< trim END
9868 vim9script
9869 class A
9870 public final l: list<number> = [1, 2]
9871 def Foo()
9872 this.l = [3, 4]
9873 enddef
9874 endclass
9875 var a = A.new()
9876 a.Foo()
9877 END
9878 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9879
9880 # Test for modifying a final variable of composite type at script level
9881 lines =<< trim END
9882 vim9script
9883 class A
9884 public final l: list<number> = [1, 2]
9885 endclass
9886 var a = A.new()
9887 a.l[0] = 3
9888 a.l->add(4)
9889 assert_equal([3, 2, 4], a.l)
9890 END
9891 v9.CheckSourceSuccess(lines)
9892
9893 # Test for modifying a final variable of composite type from a function
9894 lines =<< trim END
9895 vim9script
9896 class A
9897 public final l: list<number> = [1, 2]
9898 endclass
9899 def Foo()
9900 var a = A.new()
9901 a.l[0] = 3
9902 a.l->add(4)
9903 assert_equal([3, 2, 4], a.l)
9904 enddef
9905 Foo()
9906 END
9907 v9.CheckSourceSuccess(lines)
9908
9909 # Test for modifying a final variable of composite type from another object
9910 # function
9911 lines =<< trim END
9912 vim9script
9913 class A
9914 public final l: list<number> = [1, 2]
9915 def Foo()
9916 this.l[0] = 3
9917 this.l->add(4)
9918 enddef
9919 endclass
9920 var a = A.new()
9921 a.Foo()
9922 assert_equal([3, 2, 4], a.l)
9923 END
9924 v9.CheckSourceSuccess(lines)
9925
9926 # Test for assigning a new value to a final variable of composite type at
9927 # script level
9928 lines =<< trim END
9929 vim9script
9930 class A
9931 public final l: list<number> = [1, 2]
9932 endclass
9933 var a = A.new()
9934 a.l = [3, 4]
9935 END
9936 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
9937
9938 # Test for assigning a new value to a final variable of composite type from
9939 # another object function
9940 lines =<< trim END
9941 vim9script
9942 class A
9943 public final l: list<number> = [1, 2]
9944 def Foo()
9945 this.l = [3, 4]
9946 enddef
9947 endclass
9948 var a = A.new()
9949 a.Foo()
9950 END
9951 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9952
9953 # Test for assigning a new value to a final variable of composite type from
9954 # another function
9955 lines =<< trim END
9956 vim9script
9957 class A
9958 public final l: list<number> = [1, 2]
9959 endclass
9960 def Foo()
9961 var a = A.new()
9962 a.l = [3, 4]
9963 enddef
9964 Foo()
9965 END
9966 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
9967
9968 # Error case: Use 'final' with just a variable name
9969 lines =<< trim END
9970 vim9script
9971 class A
9972 final foo
9973 endclass
9974 var a = A.new()
9975 END
9976 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9977
9978 # Error case: Use 'final' followed by 'public'
9979 lines =<< trim END
9980 vim9script
9981 class A
9982 final public foo: number
9983 endclass
9984 var a = A.new()
9985 END
9986 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9987
9988 # Error case: Use 'final' followed by 'static'
9989 lines =<< trim END
9990 vim9script
9991 class A
9992 final static foo: number
9993 endclass
9994 var a = A.new()
9995 END
9996 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9997
9998 # Error case: 'final' cannot be used in an interface
9999 lines =<< trim END
10000 vim9script
10001 interface A
10002 final foo: number = 10
10003 endinterface
10004 END
10005 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
10006
10007 # Error case: 'final' not supported for an object method
10008 lines =<< trim END
10009 vim9script
10010 class A
10011 final def Foo()
10012 enddef
10013 endclass
10014 END
10015 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10016
10017 # Error case: 'final' not supported for a class method
10018 lines =<< trim END
10019 vim9script
10020 class A
10021 static final def Foo()
10022 enddef
10023 endclass
10024 END
10025 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10026enddef
10027
10028" Test for 'const' class and object variables
10029def Test_const_class_object_variable()
10030 # Test for changing a const object variable from an object function
10031 var lines =<< trim END
10032 vim9script
10033 class A
10034 const foo: string = "abc"
10035 def Foo()
10036 this.foo = "def"
10037 enddef
10038 endclass
10039 defcompile A.Foo
10040 END
10041 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
10042
10043 # Test for changing a const object variable from the 'new' function
10044 lines =<< trim END
10045 vim9script
10046 class A
10047 const s1: string
10048 const s2: string
10049 def new(this.s1)
10050 this.s2 = 'def'
10051 enddef
10052 endclass
10053 var a = A.new('abc')
10054 assert_equal('abc', a.s1)
10055 assert_equal('def', a.s2)
10056 END
10057 v9.CheckSourceSuccess(lines)
10058
10059 # Test for changing a const object variable from an object method called from
10060 # the 'new' function
10061 lines =<< trim END
10062 vim9script
10063 class A
10064 const s1: string = 'abc'
10065 def new()
10066 this.ChangeStr()
10067 enddef
10068 def ChangeStr()
10069 this.s1 = 'def'
10070 enddef
10071 endclass
10072 var a = A.new()
10073 END
10074 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10075
10076 # Test for a const class variable
10077 lines =<< trim END
10078 vim9script
10079 class A
10080 static const s1: string = "abc"
10081 endclass
10082 assert_equal('abc', A.s1)
10083 END
10084 v9.CheckSourceSuccess(lines)
10085
10086 # Test for changing a const class variable from a class function
10087 lines =<< trim END
10088 vim9script
10089 class A
10090 static const s1: string = "abc"
10091 static def Foo()
10092 s1 = "def"
10093 enddef
10094 endclass
10095 A.Foo()
10096 END
10097 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10098
10099 # Test for changing a public const class variable at script level
10100 lines =<< trim END
10101 vim9script
10102 class A
10103 public static const s1: string = "abc"
10104 endclass
10105 assert_equal('abc', A.s1)
10106 A.s1 = 'def'
10107 END
10108 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
10109
10110 # Test for changing a public const class variable from a class function
10111 lines =<< trim END
10112 vim9script
10113 class A
10114 public static const s1: string = "abc"
10115 static def Foo()
10116 s1 = "def"
10117 enddef
10118 endclass
10119 A.Foo()
10120 END
10121 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10122
10123 # Test for changing a public const class variable from a function
10124 lines =<< trim END
10125 vim9script
10126 class A
10127 public static const s1: string = "abc"
10128 endclass
10129 def Foo()
10130 A.s1 = 'def'
10131 enddef
10132 defcompile
10133 END
10134 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10135
10136 # Test for changing a const List item from an object function
10137 lines =<< trim END
10138 vim9script
10139 class A
10140 public const l: list<number>
10141 def new()
10142 this.l = [1, 2]
10143 enddef
10144 def Foo()
10145 this.l[0] = 3
10146 enddef
10147 endclass
10148 var a = A.new()
10149 assert_equal([1, 2], a.l)
10150 a.Foo()
10151 END
10152 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10153
10154 # Test for adding a value to a const List from an object function
10155 lines =<< trim END
10156 vim9script
10157 class A
10158 public const l: list<number>
10159 def new()
10160 this.l = [1, 2]
10161 enddef
10162 def Foo()
10163 this.l->add(3)
10164 enddef
10165 endclass
10166 var a = A.new()
10167 a.Foo()
10168 END
10169 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10170
10171 # Test for reassigning a const List from an object function
10172 lines =<< trim END
10173 vim9script
10174 class A
10175 public const l: list<number> = [1, 2]
10176 def Foo()
10177 this.l = [3, 4]
10178 enddef
10179 endclass
10180 var a = A.new()
10181 a.Foo()
10182 END
10183 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10184
10185 # Test for changing a const List item at script level
10186 lines =<< trim END
10187 vim9script
10188 class A
10189 public const l: list<number> = [1, 2]
10190 endclass
10191 var a = A.new()
10192 a.l[0] = 3
10193 END
10194 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10195
10196 # Test for adding a value to a const List item at script level
10197 lines =<< trim END
10198 vim9script
10199 class A
10200 public const l: list<number> = [1, 2]
10201 endclass
10202 var a = A.new()
10203 a.l->add(4)
10204 END
10205 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10206
10207 # Test for changing a const List item from a function
10208 lines =<< trim END
10209 vim9script
10210 class A
10211 public const l: list<number> = [1, 2]
10212 endclass
10213 def Foo()
10214 var a = A.new()
10215 a.l[0] = 3
10216 enddef
10217 Foo()
10218 END
10219 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
10220
10221 # Test for adding a value to a const List item from a function
10222 lines =<< trim END
10223 vim9script
10224 class A
10225 public const l: list<number> = [1, 2]
10226 endclass
10227 def Foo()
10228 var a = A.new()
10229 a.l->add(4)
10230 enddef
10231 Foo()
10232 END
10233 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
10234
10235 # Test for changing a const List item from an object method
10236 lines =<< trim END
10237 vim9script
10238 class A
10239 public const l: list<number> = [1, 2]
10240 def Foo()
10241 this.l[0] = 3
10242 enddef
10243 endclass
10244 var a = A.new()
10245 a.Foo()
10246 END
10247 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10248
10249 # Test for adding a value to a const List item from an object method
10250 lines =<< trim END
10251 vim9script
10252 class A
10253 public const l: list<number> = [1, 2]
10254 def Foo()
10255 this.l->add(4)
10256 enddef
10257 endclass
10258 var a = A.new()
10259 a.Foo()
10260 END
10261 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10262
10263 # Test for reassigning a const List object variable at script level
10264 lines =<< trim END
10265 vim9script
10266 class A
10267 public const l: list<number> = [1, 2]
10268 endclass
10269 var a = A.new()
10270 a.l = [3, 4]
10271 END
10272 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10273
10274 # Test for reassigning a const List object variable from an object method
10275 lines =<< trim END
10276 vim9script
10277 class A
10278 public const l: list<number> = [1, 2]
10279 def Foo()
10280 this.l = [3, 4]
10281 enddef
10282 endclass
10283 var a = A.new()
10284 a.Foo()
10285 END
10286 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10287
10288 # Test for reassigning a const List object variable from another function
10289 lines =<< trim END
10290 vim9script
10291 class A
10292 public const l: list<number> = [1, 2]
10293 endclass
10294 def Foo()
10295 var a = A.new()
10296 a.l = [3, 4]
10297 enddef
10298 Foo()
10299 END
10300 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10301
10302 # Error case: Use 'const' with just a variable name
10303 lines =<< trim END
10304 vim9script
10305 class A
10306 const foo
10307 endclass
10308 var a = A.new()
10309 END
10310 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10311
10312 # Error case: Use 'const' followed by 'public'
10313 lines =<< trim END
10314 vim9script
10315 class A
10316 const public foo: number
10317 endclass
10318 var a = A.new()
10319 END
10320 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10321
10322 # Error case: Use 'const' followed by 'static'
10323 lines =<< trim END
10324 vim9script
10325 class A
10326 const static foo: number
10327 endclass
10328 var a = A.new()
10329 END
10330 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10331
10332 # Error case: 'const' cannot be used in an interface
10333 lines =<< trim END
10334 vim9script
10335 interface A
10336 const foo: number = 10
10337 endinterface
10338 END
10339 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10340
10341 # Error case: 'const' not supported for an object method
10342 lines =<< trim END
10343 vim9script
10344 class A
10345 const def Foo()
10346 enddef
10347 endclass
10348 END
10349 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10350
10351 # Error case: 'const' not supported for a class method
10352 lines =<< trim END
10353 vim9script
10354 class A
10355 static const def Foo()
10356 enddef
10357 endclass
10358 END
10359 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10360enddef
10361
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010362" Test for compiling class/object methods using :defcompile
10363def Test_defcompile_class()
10364 # defcompile all the classes in the current script
10365 var lines =<< trim END
10366 vim9script
10367 class A
10368 def Foo()
10369 var i = 10
10370 enddef
10371 endclass
10372 class B
10373 def Bar()
10374 var i = 20
10375 xxx
10376 enddef
10377 endclass
10378 defcompile
10379 END
10380 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10381
10382 # defcompile a specific class
10383 lines =<< trim END
10384 vim9script
10385 class A
10386 def Foo()
10387 xxx
10388 enddef
10389 endclass
10390 class B
10391 def Bar()
10392 yyy
10393 enddef
10394 endclass
10395 defcompile B
10396 END
10397 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10398
10399 # defcompile a non-class
10400 lines =<< trim END
10401 vim9script
10402 class A
10403 def Foo()
10404 enddef
10405 endclass
10406 var X: list<number> = []
10407 defcompile X
10408 END
10409 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10410
10411 # defcompile a class twice
10412 lines =<< trim END
10413 vim9script
10414 class A
10415 def new()
10416 enddef
10417 endclass
10418 defcompile A
10419 defcompile A
10420 assert_equal('Function A.new does not need compiling', v:statusmsg)
10421 END
10422 v9.CheckSourceSuccess(lines)
10423
10424 # defcompile should not compile an imported class
10425 lines =<< trim END
10426 vim9script
10427 export class A
10428 def Foo()
10429 xxx
10430 enddef
10431 endclass
10432 END
10433 writefile(lines, 'Xdefcompileimport.vim', 'D')
10434 lines =<< trim END
10435 vim9script
10436
10437 import './Xdefcompileimport.vim'
10438 class B
10439 endclass
10440 defcompile
10441 END
10442 v9.CheckScriptSuccess(lines)
10443enddef
10444
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010445" Test for cases common to all the object builtin methods
10446def Test_object_builtin_method()
10447 var lines =<< trim END
10448 vim9script
10449 class A
10450 def abc()
10451 enddef
10452 endclass
10453 END
10454 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10455
10456 for funcname in ["len", "string", "empty"]
10457 lines =<< trim eval END
10458 vim9script
10459 class A
10460 static def {funcname}(): number
10461 enddef
10462 endclass
10463 END
10464 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10465 endfor
10466enddef
10467
10468" Test for using the empty() builtin method with an object
10469" This is a legacy function to use the test_garbagecollect_now() function.
10470func Test_object_empty()
10471 let lines =<< trim END
10472 vim9script
10473 class A
10474 def empty(): bool
10475 return true
10476 enddef
10477 endclass
10478
10479 def Foo()
10480 var afoo = A.new()
10481 assert_equal(true, empty(afoo))
10482 assert_equal(true, afoo->empty())
10483 enddef
10484
10485 var a = A.new()
10486 assert_equal(1, empty(a))
10487 assert_equal(1, a->empty())
10488 test_garbagecollect_now()
10489 assert_equal(1, empty(a))
10490 Foo()
10491 test_garbagecollect_now()
10492 Foo()
10493 END
10494 call v9.CheckSourceSuccess(lines)
10495
10496 " empty() should return 1 without a builtin method
10497 let lines =<< trim END
10498 vim9script
10499 class A
10500 endclass
10501
10502 def Foo()
10503 var afoo = A.new()
10504 assert_equal(1, empty(afoo))
10505 enddef
10506
10507 var a = A.new()
10508 assert_equal(1, empty(a))
10509 Foo()
10510 END
10511 call v9.CheckSourceSuccess(lines)
10512
10513 " Unsupported signature for the empty() method
10514 let lines =<< trim END
10515 vim9script
10516 class A
10517 def empty()
10518 enddef
10519 endclass
10520 END
10521 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10522
10523 " Error when calling the empty() method
10524 let lines =<< trim END
10525 vim9script
10526 class A
10527 def empty(): bool
10528 throw "Failed to check emptiness"
10529 enddef
10530 endclass
10531
10532 def Foo()
10533 var afoo = A.new()
10534 var i = empty(afoo)
10535 enddef
10536
10537 var a = A.new()
10538 assert_fails('empty(a)', 'Failed to check emptiness')
10539 assert_fails('Foo()', 'Failed to check emptiness')
10540 END
10541 call v9.CheckSourceSuccess(lines)
10542
10543 " call empty() using an object from a script
10544 let lines =<< trim END
10545 vim9script
10546 class A
10547 def empty(): bool
10548 return true
10549 enddef
10550 endclass
10551 var afoo = A.new()
10552 assert_equal(true, afoo.empty())
10553 END
10554 call v9.CheckSourceSuccess(lines)
10555
10556 " call empty() using an object from a method
10557 let lines =<< trim END
10558 vim9script
10559 class A
10560 def empty(): bool
10561 return true
10562 enddef
10563 endclass
10564 def Foo()
10565 var afoo = A.new()
10566 assert_equal(true, afoo.empty())
10567 enddef
10568 Foo()
10569 END
10570 call v9.CheckSourceSuccess(lines)
10571
10572 " call empty() using "this" from an object method
10573 let lines =<< trim END
10574 vim9script
10575 class A
10576 def empty(): bool
10577 return true
10578 enddef
10579 def Foo(): bool
10580 return this.empty()
10581 enddef
10582 endclass
10583 def Bar()
10584 var abar = A.new()
10585 assert_equal(true, abar.Foo())
10586 enddef
10587 Bar()
10588 END
10589 call v9.CheckSourceSuccess(lines)
10590
10591 " Call empty() from a derived object
10592 let lines =<< trim END
10593 vim9script
10594 class A
10595 def empty(): bool
10596 return false
10597 enddef
10598 endclass
10599 class B extends A
10600 def empty(): bool
10601 return true
10602 enddef
10603 endclass
10604 def Foo(afoo: A)
10605 assert_equal(true, empty(afoo))
10606 var bfoo = B.new()
10607 assert_equal(true, empty(bfoo))
10608 enddef
10609 var b = B.new()
10610 assert_equal(1, empty(b))
10611 Foo(b)
10612 END
10613 call v9.CheckSourceSuccess(lines)
10614
10615 " Invoking empty method using an interface
10616 let lines =<< trim END
10617 vim9script
10618 interface A
10619 def empty(): bool
10620 endinterface
10621 class B implements A
10622 def empty(): bool
10623 return false
10624 enddef
10625 endclass
10626 def Foo(a: A)
10627 assert_equal(false, empty(a))
10628 enddef
10629 var b = B.new()
10630 Foo(b)
10631 END
10632 call v9.CheckSourceSuccess(lines)
10633endfunc
10634
10635" Test for using the len() builtin method with an object
10636" This is a legacy function to use the test_garbagecollect_now() function.
10637func Test_object_length()
10638 let lines =<< trim END
10639 vim9script
10640 class A
10641 var mylen: number = 0
10642 def new(n: number)
10643 this.mylen = n
10644 enddef
10645 def len(): number
10646 return this.mylen
10647 enddef
10648 endclass
10649
10650 def Foo()
10651 var afoo = A.new(12)
10652 assert_equal(12, len(afoo))
10653 assert_equal(12, afoo->len())
10654 enddef
10655
10656 var a = A.new(22)
10657 assert_equal(22, len(a))
10658 assert_equal(22, a->len())
10659 test_garbagecollect_now()
10660 assert_equal(22, len(a))
10661 Foo()
10662 test_garbagecollect_now()
10663 Foo()
10664 END
10665 call v9.CheckSourceSuccess(lines)
10666
10667 " len() should return 0 without a builtin method
10668 let lines =<< trim END
10669 vim9script
10670 class A
10671 endclass
10672
10673 def Foo()
10674 var afoo = A.new()
10675 assert_equal(0, len(afoo))
10676 enddef
10677
10678 var a = A.new()
10679 assert_equal(0, len(a))
10680 Foo()
10681 END
10682 call v9.CheckSourceSuccess(lines)
10683
10684 " Unsupported signature for the len() method
10685 let lines =<< trim END
10686 vim9script
10687 class A
10688 def len()
10689 enddef
10690 endclass
10691 END
10692 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10693
10694 " Error when calling the len() method
10695 let lines =<< trim END
10696 vim9script
10697 class A
10698 def len(): number
10699 throw "Failed to compute length"
10700 enddef
10701 endclass
10702
10703 def Foo()
10704 var afoo = A.new()
10705 var i = len(afoo)
10706 enddef
10707
10708 var a = A.new()
10709 assert_fails('len(a)', 'Failed to compute length')
10710 assert_fails('Foo()', 'Failed to compute length')
10711 END
10712 call v9.CheckSourceSuccess(lines)
10713
10714 " call len() using an object from a script
10715 let lines =<< trim END
10716 vim9script
10717 class A
10718 def len(): number
10719 return 5
10720 enddef
10721 endclass
10722 var afoo = A.new()
10723 assert_equal(5, afoo.len())
10724 END
10725 call v9.CheckSourceSuccess(lines)
10726
10727 " call len() using an object from a method
10728 let lines =<< trim END
10729 vim9script
10730 class A
10731 def len(): number
10732 return 5
10733 enddef
10734 endclass
10735 def Foo()
10736 var afoo = A.new()
10737 assert_equal(5, afoo.len())
10738 enddef
10739 Foo()
10740 END
10741 call v9.CheckSourceSuccess(lines)
10742
10743 " call len() using "this" from an object method
10744 let lines =<< trim END
10745 vim9script
10746 class A
10747 def len(): number
10748 return 8
10749 enddef
10750 def Foo(): number
10751 return this.len()
10752 enddef
10753 endclass
10754 def Bar()
10755 var abar = A.new()
10756 assert_equal(8, abar.Foo())
10757 enddef
10758 Bar()
10759 END
10760 call v9.CheckSourceSuccess(lines)
10761
10762 " Call len() from a derived object
10763 let lines =<< trim END
10764 vim9script
10765 class A
10766 def len(): number
10767 return 10
10768 enddef
10769 endclass
10770 class B extends A
10771 def len(): number
10772 return 20
10773 enddef
10774 endclass
10775 def Foo(afoo: A)
10776 assert_equal(20, len(afoo))
10777 var bfoo = B.new()
10778 assert_equal(20, len(bfoo))
10779 enddef
10780 var b = B.new()
10781 assert_equal(20, len(b))
10782 Foo(b)
10783 END
10784 call v9.CheckSourceSuccess(lines)
10785
10786 " Invoking len method using an interface
10787 let lines =<< trim END
10788 vim9script
10789 interface A
10790 def len(): number
10791 endinterface
10792 class B implements A
10793 def len(): number
10794 return 123
10795 enddef
10796 endclass
10797 def Foo(a: A)
10798 assert_equal(123, len(a))
10799 enddef
10800 var b = B.new()
10801 Foo(b)
10802 END
10803 call v9.CheckSourceSuccess(lines)
10804endfunc
10805
10806" Test for using the string() builtin method with an object
10807" This is a legacy function to use the test_garbagecollect_now() function.
10808func Test_object_string()
10809 let lines =<< trim END
10810 vim9script
10811 class A
10812 var name: string
10813 def string(): string
10814 return this.name
10815 enddef
10816 endclass
10817
10818 def Foo()
10819 var afoo = A.new("foo-A")
10820 assert_equal('foo-A', string(afoo))
10821 assert_equal('foo-A', afoo->string())
10822 enddef
10823
10824 var a = A.new("script-A")
10825 assert_equal('script-A', string(a))
10826 assert_equal('script-A', a->string())
10827 assert_equal(['script-A'], execute('echo a')->split("\n"))
10828 test_garbagecollect_now()
10829 assert_equal('script-A', string(a))
10830 Foo()
10831 test_garbagecollect_now()
10832 Foo()
10833 END
10834 call v9.CheckSourceSuccess(lines)
10835
10836 " string() should return "object of A {}" without a builtin method
10837 let lines =<< trim END
10838 vim9script
10839 class A
10840 endclass
10841
10842 def Foo()
10843 var afoo = A.new()
10844 assert_equal('object of A {}', string(afoo))
10845 enddef
10846
10847 var a = A.new()
10848 assert_equal('object of A {}', string(a))
10849 Foo()
10850 END
10851 call v9.CheckSourceSuccess(lines)
10852
10853 " Unsupported signature for the string() method
10854 let lines =<< trim END
10855 vim9script
10856 class A
10857 def string()
10858 enddef
10859 endclass
10860 END
10861 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
10862
10863 " Error when calling the string() method
10864 let lines =<< trim END
10865 vim9script
10866 class A
10867 def string(): string
10868 throw "Failed to get text"
10869 enddef
10870 endclass
10871
10872 def Foo()
10873 var afoo = A.new()
10874 var i = string(afoo)
10875 enddef
10876
10877 var a = A.new()
10878 assert_fails('string(a)', 'Failed to get text')
10879 assert_fails('Foo()', 'Failed to get text')
10880 END
10881 call v9.CheckSourceSuccess(lines)
10882
10883 " call string() using an object from a script
10884 let lines =<< trim END
10885 vim9script
10886 class A
10887 def string(): string
10888 return 'A'
10889 enddef
10890 endclass
10891 var afoo = A.new()
10892 assert_equal('A', afoo.string())
10893 END
10894 call v9.CheckSourceSuccess(lines)
10895
10896 " call string() using an object from a method
10897 let lines =<< trim END
10898 vim9script
10899 class A
10900 def string(): string
10901 return 'A'
10902 enddef
10903 endclass
10904 def Foo()
10905 var afoo = A.new()
10906 assert_equal('A', afoo.string())
10907 enddef
10908 Foo()
10909 END
10910 call v9.CheckSourceSuccess(lines)
10911
10912 " call string() using "this" from an object method
10913 let lines =<< trim END
10914 vim9script
10915 class A
10916 def string(): string
10917 return 'A'
10918 enddef
10919 def Foo(): string
10920 return this.string()
10921 enddef
10922 endclass
10923 def Bar()
10924 var abar = A.new()
10925 assert_equal('A', abar.string())
10926 enddef
10927 Bar()
10928 END
10929 call v9.CheckSourceSuccess(lines)
10930
10931 " Call string() from a derived object
10932 let lines =<< trim END
10933 vim9script
10934 class A
10935 def string(): string
10936 return 'A'
10937 enddef
10938 endclass
10939 class B extends A
10940 def string(): string
10941 return 'B'
10942 enddef
10943 endclass
10944 def Foo(afoo: A)
10945 assert_equal('B', string(afoo))
10946 var bfoo = B.new()
10947 assert_equal('B', string(bfoo))
10948 enddef
10949 var b = B.new()
10950 assert_equal('B', string(b))
10951 Foo(b)
10952 END
10953 call v9.CheckSourceSuccess(lines)
10954
10955 " Invoking string method using an interface
10956 let lines =<< trim END
10957 vim9script
10958 interface A
10959 def string(): string
10960 endinterface
10961 class B implements A
10962 def string(): string
10963 return 'B'
10964 enddef
10965 endclass
10966 def Foo(a: A)
10967 assert_equal('B', string(a))
10968 enddef
10969 var b = B.new()
10970 Foo(b)
10971 END
10972 call v9.CheckSourceSuccess(lines)
10973endfunc
10974
Ernie Rael9d779c52024-07-07 20:41:44 +020010975" Test for using the string() builtin method with an object's method
10976def Test_method_string()
10977 var lines =<< trim END
10978 vim9script
10979 class A
10980 def F()
10981 enddef
10982 endclass
10983 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
10984 END
10985 v9.CheckScriptSuccess(lines)
10986enddef
10987
10988
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010010989" Test for using a class in the class definition
10990def Test_Ref_Class_Within_Same_Class()
10991 var lines =<< trim END
10992 vim9script
10993 class A
10994 var n: number = 0
10995 def Equals(other: A): bool
10996 return this.n == other.n
10997 enddef
10998 endclass
10999
11000 var a1 = A.new(10)
11001 var a2 = A.new(10)
11002 var a3 = A.new(20)
11003 assert_equal(true, a1.Equals(a2))
11004 assert_equal(false, a2.Equals(a3))
11005 END
11006 v9.CheckScriptSuccess(lines)
11007
11008 lines =<< trim END
11009 vim9script
11010
11011 class Foo
11012 var num: number
11013 def Clone(): Foo
11014 return Foo.new(this.num)
11015 enddef
11016 endclass
11017
11018 var f1 = Foo.new(1)
11019
11020 def F()
11021 var f2: Foo = f1.Clone()
11022 assert_equal(false, f2 is f1)
11023 assert_equal(true, f2.num == f1.num)
11024 enddef
11025 F()
11026
11027 var f3: Foo = f1.Clone()
11028 assert_equal(false, f3 is f1)
11029 assert_equal(true, f3.num == f1.num)
11030 END
11031 v9.CheckScriptSuccess(lines)
11032
11033 # Test for trying to use a class to extend when defining the same class
11034 lines =<< trim END
11035 vim9script
11036 class A extends A
11037 endclass
11038 END
11039 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
11040
11041 # Test for trying to use a class to implement when defining the same class
11042 lines =<< trim END
11043 vim9script
11044 class A implements A
11045 endclass
11046 END
11047 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
11048enddef
11049
Ernie Raelf0e69142024-06-22 11:12:00 +020011050" Test for comparing a class referencing itself
11051def Test_Object_Compare_With_Recursive_Class_Ref()
11052 var lines =<< trim END
11053 vim9script
11054
11055 class C
11056 public var nest: C
11057 endclass
11058
11059 var o1 = C.new()
11060 o1.nest = o1
11061
11062 var result = o1 == o1
11063 assert_equal(true, result)
11064 END
11065 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020011066
11067 lines =<< trim END
11068 vim9script
11069
11070 class C
11071 public var nest: C
11072 endclass
11073 var o1 = C.new()
11074 var o2 = C.new(C.new())
11075
11076 var result = o1 == o2
11077 assert_equal(false, result)
11078 END
11079 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020011080
11081 lines =<< trim END
11082 vim9script
11083 class C
11084 var nest1: C
11085 var nest2: C
11086 def Init(n1: C, n2: C)
11087 this.nest1 = n1
11088 this.nest2 = n2
11089 enddef
11090 endclass
11091
11092 var o1 = C.new()
11093 var o2 = C.new()
11094 o1.Init(o1, o2)
11095 o2.Init(o2, o1)
11096
11097 var result = o1 == o2
11098 assert_equal(true, result)
11099 END
11100 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020011101enddef
11102
Ernie Raelf3975492024-07-06 11:44:37 +020011103" Test for comparing a class with nesting objects
11104def Test_Object_Compare_With_Nesting_Objects()
11105 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
11106 # return the compare is equal.
11107 # Test that limit
11108
11109 var lines =<< trim END
11110 vim9script
11111 class C
11112 public var n: number
11113 public var nest: C
11114
11115 # Create a "C" that chains/nests to indicated depth.
11116 # return {head: firstC, tail: lastC}
11117 static def CreateNested(depth: number): dict<C>
11118 var first = C.new(1, null_object)
11119 var last = first
11120 for i in range(2, depth)
11121 last.nest = C.new(i, null_object)
11122 last = last.nest
11123 endfor
11124 return {head: first, tail: last}
11125 enddef
11126
11127 # Return pointer to nth item in chain.
11128 def GetLink(depth: number): C
11129 var count = 1
11130 var p: C = this
11131 while count < depth
11132 p = p.nest
11133 if p == null
11134 throw "too deep"
11135 endif
11136 count += 1
11137 endwhile
11138 return p
11139 enddef
11140
11141 # Return the length of the chain
11142 def len(): number
11143 var count = 1
11144 var p: C = this
11145 while p.nest != null
11146 p = p.nest
11147 count += 1
11148 endwhile
11149 return count
11150 enddef
11151 endclass
11152
11153 var chain = C.CreateNested(3)
11154 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
11155 assert_equal(s, string(chain.head))
11156 assert_equal(3, chain.head->len())
11157
11158 var chain1 = C.CreateNested(100)
11159 var chain2 = C.CreateNested(100)
11160 assert_true(chain1.head == chain2.head)
11161
11162 # modify the tail of chain2, compare not equal
11163 chain2.tail.n = 123456
11164 assert_true(chain1.head != chain2.head)
11165
11166 # a tail of a different length compares not equal
11167 chain2 = C.CreateNested(101)
11168 assert_true(chain1.head != chain2.head)
11169
11170 chain1 = C.CreateNested(1000)
11171 chain2 = C.CreateNested(1000)
11172 assert_true(chain1.head == chain2.head)
11173
11174 # modify the tail of chain2, compare not equal
11175 chain2.tail.n = 123456
11176 assert_true(chain1.head != chain2.head)
11177
11178 # try a chain longer that the limit
11179 chain1 = C.CreateNested(1001)
11180 chain2 = C.CreateNested(1001)
11181 assert_true(chain1.head == chain2.head)
11182
11183 # modify the tail, but still equal
11184 chain2.tail.n = 123456
11185 assert_true(chain1.head == chain2.head)
11186
11187 # remove 2 items from front, shorten the chain by two.
11188 chain1.head = chain1.head.GetLink(3)
11189 chain2.head = chain2.head.GetLink(3)
11190 assert_equal(3, chain1.head.n)
11191 assert_equal(3, chain2.head.n)
11192 assert_equal(999, chain1.head->len())
11193 assert_equal(999, chain2.head->len())
11194 # Now less than the limit, compare not equal
11195 assert_true(chain1.head != chain2.head)
11196 END
11197 v9.CheckScriptSuccess(lines)
11198enddef
11199
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011200" Test for using a compound operator from a lambda function in an object method
11201def Test_compound_op_in_objmethod_lambda()
11202 # Test using the "+=" operator
11203 var lines =<< trim END
11204 vim9script
11205 class A
11206 var n: number = 10
11207 def Foo()
11208 var Fn = () => {
11209 this.n += 1
11210 }
11211 Fn()
11212 enddef
11213 endclass
11214
11215 var a = A.new()
11216 a.Foo()
11217 assert_equal(11, a.n)
11218 END
11219 v9.CheckScriptSuccess(lines)
11220
11221 # Test using the "..=" operator
11222 lines =<< trim END
11223 vim9script
11224 class A
11225 var s: string = "a"
11226 def Foo()
11227 var Fn = () => {
11228 this.s ..= "a"
11229 }
11230 Fn()
11231 enddef
11232 endclass
11233
11234 var a = A.new()
11235 a.Foo()
11236 a.Foo()
11237 assert_equal("aaa", a.s)
11238 END
11239 v9.CheckScriptSuccess(lines)
11240enddef
11241
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011242" Test for using test_refcount() with a class and an object
11243def Test_class_object_refcount()
11244 var lines =<< trim END
11245 vim9script
11246 class A
11247 endclass
11248 var a: A = A.new()
11249 assert_equal(2, test_refcount(A))
11250 assert_equal(1, test_refcount(a))
11251 var b = a
11252 assert_equal(2, test_refcount(A))
11253 assert_equal(2, test_refcount(a))
11254 assert_equal(2, test_refcount(b))
11255 END
11256 v9.CheckScriptSuccess(lines)
11257enddef
11258
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011259" call a lambda function in one object from another object
11260def Test_lambda_invocation_across_classes()
11261 var lines =<< trim END
11262 vim9script
11263 class A
11264 var s: string = "foo"
11265 def GetFn(): func
11266 var Fn = (): string => {
11267 return this.s
11268 }
11269 return Fn
11270 enddef
11271 endclass
11272
11273 class B
11274 var s: string = "bar"
11275 def GetFn(): func
11276 var a = A.new()
11277 return a.GetFn()
11278 enddef
11279 endclass
11280
11281 var b = B.new()
11282 var Fn = b.GetFn()
11283 assert_equal("foo", Fn())
11284 END
11285 v9.CheckScriptSuccess(lines)
11286enddef
11287
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011288" Test for using a class member which is an object of the current class
11289def Test_current_class_object_class_member()
11290 var lines =<< trim END
11291 vim9script
11292 class A
11293 public static var obj1: A = A.new(10)
11294 var n: number
11295 endclass
11296 defcompile
11297 assert_equal(10, A.obj1.n)
11298 END
11299 v9.CheckScriptSuccess(lines)
11300enddef
11301
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011302" Test for updating a base class variable from a base class method without the
11303" class name. This used to crash Vim (Github issue #14352).
11304def Test_use_base_class_variable_from_base_class_method()
11305 var lines =<< trim END
11306 vim9script
11307
11308 class DictKeyClass
11309 static var _obj_id_count = 1
11310 def _GenerateKey()
11311 _obj_id_count += 1
11312 enddef
11313 static def GetIdCount(): number
11314 return _obj_id_count
11315 enddef
11316 endclass
11317
11318 class C extends DictKeyClass
11319 def F()
11320 this._GenerateKey()
11321 enddef
11322 endclass
11323
11324 C.new().F()
11325 assert_equal(2, DictKeyClass.GetIdCount())
11326 END
11327 v9.CheckScriptSuccess(lines)
11328enddef
11329
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011330" Test for accessing protected funcref object and class variables
11331def Test_protected_funcref()
11332 # protected funcref object variable
11333 var lines =<< trim END
11334 vim9script
11335 class Test1
11336 const _Id: func(any): any = (v) => v
11337 endclass
11338 var n = Test1.new()._Id(1)
11339 END
11340 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11341
11342 # protected funcref class variable
11343 lines =<< trim END
11344 vim9script
11345 class Test2
11346 static const _Id: func(any): any = (v) => v
11347 endclass
11348 var n = Test2._Id(2)
11349 END
11350 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11351enddef
11352
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011353" Test for using lambda block in classes
11354def Test_lambda_block_in_class()
11355 # This used to crash Vim
11356 var lines =<< trim END
11357 vim9script
11358 class IdClass1
11359 const Id: func(number): number = (num: number): number => {
11360 # Return a ID
11361 return num * 10
11362 }
11363 endclass
11364 var id = IdClass1.new()
11365 assert_equal(20, id.Id(2))
11366 END
11367 v9.CheckScriptSuccess(lines)
11368
11369 # This used to crash Vim
11370 lines =<< trim END
11371 vim9script
11372 class IdClass2
11373 static const Id: func(number): number = (num: number): number => {
11374 # Return a ID
11375 return num * 2
11376 }
11377 endclass
11378 assert_equal(16, IdClass2.Id(8))
11379 END
11380 v9.CheckScriptSuccess(lines)
11381enddef
11382
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011383" Test for defcompiling an abstract method
11384def Test_abstract_method_defcompile()
11385 # Compile an abstract class with abstract object methods
11386 var lines =<< trim END
11387 vim9script
11388 abstract class A
11389 abstract def Foo(): string
11390 abstract def Bar(): list<string>
11391 endclass
11392 defcompile
11393 END
11394 v9.CheckScriptSuccess(lines)
11395
11396 # Compile a concrete object method in an abstract class
11397 lines =<< trim END
11398 vim9script
11399 abstract class A
11400 abstract def Foo(): string
11401 abstract def Bar(): list<string>
11402 def Baz(): string
11403 pass
11404 enddef
11405 endclass
11406 defcompile
11407 END
11408 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11409
11410 # Compile a concrete class method in an abstract class
11411 lines =<< trim END
11412 vim9script
11413 abstract class A
11414 abstract def Foo(): string
11415 abstract def Bar(): list<string>
11416 static def Baz(): string
11417 pass
11418 enddef
11419 endclass
11420 defcompile
11421 END
11422 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11423enddef
11424
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011425" Test for defining a class in a function
11426def Test_class_definition_in_a_function()
11427 var lines =<< trim END
11428 vim9script
11429 def Foo()
11430 class A
11431 endclass
11432 enddef
11433 defcompile
11434 END
11435 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11436enddef
11437
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011438" Test for using [] with a class and an object
11439def Test_class_object_index()
11440 var lines =<< trim END
11441 vim9script
11442 class A
11443 endclass
11444 A[10] = 1
11445 END
11446 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11447
11448 lines =<< trim END
11449 vim9script
11450 class A
11451 endclass
11452 var a = A.new()
11453 a[10] = 1
11454 END
11455 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11456enddef
11457
LemonBoyf4af3312024-07-04 13:43:12 +020011458def Test_class_member_init_typecheck()
11459 # Ensure the class member is assigned its declared type.
11460 var lines =<< trim END
11461 vim9script
11462 class S
11463 static var l: list<string> = []
11464 endclass
11465 S.l->add(123)
11466 END
11467 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11468
11469 # Ensure the initializer value and the declared type match.
11470 lines =<< trim END
11471 vim9script
11472 class S
11473 var l: list<string> = [1, 2, 3]
11474 endclass
11475 var o = S.new()
11476 END
11477 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11478
11479 # Ensure the class member is assigned its declared type.
11480 lines =<< trim END
11481 vim9script
11482 class S
11483 var l: list<string> = []
11484 endclass
11485 var o = S.new()
11486 o.l->add(123)
11487 END
11488 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11489enddef
11490
LemonBoy50d48542024-07-04 17:03:17 +020011491def Test_class_cast()
11492 var lines =<< trim END
11493 vim9script
11494 class A
11495 endclass
11496 class B extends A
11497 var mylen: number
11498 endclass
11499 def F(o: A): number
11500 return (<B>o).mylen
11501 enddef
11502
11503 defcompile F
11504 END
11505 v9.CheckScriptSuccess(lines)
11506enddef
11507
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011508" Test for using a variable of type "any" with an object
11509def Test_any_obj_var_type()
11510 var lines =<< trim END
11511 vim9script
11512 class A
11513 var name: string = "foobar"
11514 def Foo(): string
11515 return "func foo"
11516 enddef
11517 endclass
11518
11519 def CheckVals(x: any)
11520 assert_equal("foobar", x.name)
11521 assert_equal("func foo", x.Foo())
11522 enddef
11523
11524 var a = A.new()
11525 CheckVals(a)
11526 END
11527 v9.CheckScriptSuccess(lines)
11528
11529 # Try to set a non-existing variable
11530 lines =<< trim END
11531 vim9script
11532 class A
11533 var name: string = "foobar"
11534 endclass
11535
11536 def SetNonExistingVar(x: any)
11537 x.bar = [1, 2, 3]
11538 enddef
11539
11540 var a = A.new()
11541 SetNonExistingVar(a)
11542 END
11543 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11544
11545 # Try to read a non-existing variable
11546 lines =<< trim END
11547 vim9script
11548 class A
11549 var name: string = "foobar"
11550 endclass
11551
11552 def GetNonExistingVar(x: any)
11553 var i: dict<any> = x.bar
11554 enddef
11555
11556 var a = A.new()
11557 GetNonExistingVar(a)
11558 END
11559 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11560
11561 # Try to invoke a non-existing method
11562 lines =<< trim END
11563 vim9script
11564 class A
11565 def Foo(): number
11566 return 10
11567 enddef
11568 endclass
11569
11570 def CallNonExistingMethod(x: any)
11571 var i: number = x.Bar()
11572 enddef
11573
11574 var a = A.new()
11575 CallNonExistingMethod(a)
11576 END
11577 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11578
11579 # Use an object which is a Dict value
11580 lines =<< trim END
11581 vim9script
11582 class Foo
11583 def Bar(): number
11584 return 369
11585 enddef
11586 endclass
11587
11588 def GetValue(FooDict: dict<any>): number
11589 var n: number = 0
11590 for foo in values(FooDict)
11591 n += foo.Bar()
11592 endfor
11593 return n
11594 enddef
11595
11596 var d = {'x': Foo.new()}
11597 assert_equal(369, GetValue(d))
11598 END
11599 v9.CheckScriptSuccess(lines)
11600
zeertzjqd32bf0a2024-12-17 20:55:13 +010011601 # Nested data. Object containing a Dict containing another Object.
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011602 lines =<< trim END
11603 vim9script
11604 class Context
11605 public var state: dict<any> = {}
11606 endclass
11607
11608 class Metadata
11609 public var value = 0
11610 endclass
11611
11612 var ctx = Context.new()
11613 ctx.state["meta"] = Metadata.new(2468)
11614
11615 const foo = ctx.state.meta.value
11616
11617 def F(): number
11618 const bar = ctx.state.meta.value
11619 return bar
11620 enddef
11621
11622 assert_equal(2468, F())
11623 END
11624 v9.CheckScriptSuccess(lines)
11625
11626 # Accessing an object from a method inside the class using any type
11627 lines =<< trim END
11628 vim9script
11629 class C
11630 def _G(): string
11631 return '_G'
11632 enddef
11633 static def S(o_any: any): string
11634 return o_any._G()
11635 enddef
11636 endclass
11637
11638 var o1 = C.new()
11639 assert_equal('_G', C.S(o1))
11640 END
11641 v9.CheckScriptSuccess(lines)
11642
11643 # Modifying an object private variable from a method in another class using
11644 # any type
11645 lines =<< trim END
11646 vim9script
11647
11648 class A
11649 var num = 10
11650 endclass
11651
11652 class B
11653 def SetVal(x: any)
11654 x.num = 20
11655 enddef
11656 endclass
11657
11658 var a = A.new()
11659 var b = B.new()
11660 b.SetVal(a)
11661 END
11662 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11663
11664 # Accessing a object protected variable from a method in another class using
11665 # any type
11666 lines =<< trim END
11667 vim9script
11668
11669 class A
11670 var _num = 10
11671 endclass
11672
11673 class B
11674 def GetVal(x: any): number
11675 return x._num
11676 enddef
11677 endclass
11678
11679 var a = A.new()
11680 var b = B.new()
11681 var i = b.GetVal(a)
11682 END
11683 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11684
11685 # Accessing an object returned from an imported function and class
11686 lines =<< trim END
11687 vim9script
11688 export class Foo
11689 public var name: string
11690 endclass
11691
11692 export def ReturnFooObject(): Foo
11693 var r = Foo.new('star')
11694 return r
11695 enddef
11696 END
11697 writefile(lines, 'Xanyvar1.vim', 'D')
11698
11699 lines =<< trim END
11700 vim9script
11701
11702 import './Xanyvar1.vim'
11703
11704 def GetName(): string
11705 var whatever = Xanyvar1.ReturnFooObject()
11706 return whatever.name
11707 enddef
11708
11709 assert_equal('star', GetName())
11710 END
11711 v9.CheckScriptSuccess(lines)
11712
11713 # Try to modify a private object variable using a variable of type "any"
11714 lines =<< trim END
11715 vim9script
11716
11717 class Foo
11718 var n: number = 10
11719 endclass
11720 def Fn(x: any)
11721 x.n = 20
11722 enddef
11723 var a = Foo.new()
11724 Fn(a)
11725 END
11726 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11727
11728 # Try to read a protected object variable using a variable of type "any"
11729 lines =<< trim END
11730 vim9script
11731
11732 class Foo
11733 var _n: number = 10
11734 endclass
11735 def Fn(x: any): number
11736 return x._n
11737 enddef
11738
11739 var a = Foo.new()
11740 Fn(a)
11741 END
11742 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11743
11744 # Read a protected object variable using a variable of type "any" in an object
11745 # method
11746 lines =<< trim END
11747 vim9script
11748
11749 class Foo
11750 var _n: number = 10
11751 def Fn(x: any): number
11752 return x._n
11753 enddef
11754 endclass
11755
11756 var a = Foo.new()
11757 assert_equal(10, a.Fn(a))
11758 END
11759 v9.CheckScriptSuccess(lines)
11760
11761 # Try to call a protected object method using a "any" type variable
11762 lines =<< trim END
11763 vim9script
11764
11765 class Foo
11766 def _GetVal(): number
11767 return 234
11768 enddef
11769 endclass
11770 def Fn(x: any): number
11771 return x._GetVal()
11772 enddef
11773
11774 var a = Foo.new()
11775 Fn(a)
11776 END
11777 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11778
11779 # Call a protected object method using a "any" type variable from another
11780 # object method
11781 lines =<< trim END
11782 vim9script
11783
11784 class Foo
11785 def _GetVal(): number
11786 return 234
11787 enddef
11788 def FooVal(x: any): number
11789 return x._GetVal()
11790 enddef
11791 endclass
11792
11793 var a = Foo.new()
11794 assert_equal(234, a.FooVal(a))
11795 END
11796 v9.CheckScriptSuccess(lines)
11797
11798 # Method chaining
11799 lines =<< trim END
11800 vim9script
11801
11802 export class T
11803 var id: number = 268
11804 def F(): any
11805 return this
11806 enddef
11807 endclass
11808
11809 def H()
11810 var a = T.new().F().F()
11811 assert_equal(268, a.id)
11812 enddef
11813 H()
11814
11815 var b: T = T.new().F().F()
11816 assert_equal(268, b.id)
11817 END
11818 v9.CheckScriptSuccess(lines)
11819
11820 # Using a null object to access a member variable
11821 lines =<< trim END
11822 vim9script
11823 def Fn(x: any): number
11824 return x.num
11825 enddef
11826
11827 Fn(null_object)
11828 END
11829 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11830
11831 # Using a null object to invoke a method
11832 lines =<< trim END
11833 vim9script
11834 def Fn(x: any)
11835 x.Foo()
11836 enddef
11837
11838 Fn(null_object)
11839 END
11840 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
Yegappan Lakshmanane7984462024-11-12 21:03:00 +010011841
11842 # Try to change a const object variable using a "any" variable
11843 lines =<< trim END
11844 vim9script
11845 class A
11846 public const v1: number = 123
11847 endclass
11848
11849 def Fn(o: any)
11850 o.v1 = 321
11851 enddef
11852
11853 var a = A.new()
11854 Fn(a)
11855 END
11856 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11857
11858 # Try to change a final object variable using a "any" variable
11859 lines =<< trim END
11860 vim9script
11861 class A
11862 public final v1: number = 123
11863 endclass
11864
11865 def Fn(o: any)
11866 o.v1 = 321
11867 enddef
11868
11869 var a = A.new()
11870 Fn(a)
11871 END
11872 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11873
11874 # Assign a different type of value to an "any" type object variable
11875 lines =<< trim END
11876 vim9script
11877 class A
11878 public var v1: list<any> = [1, 2]
11879 endclass
11880
11881 def Fn(o: A)
11882 o.v1 = 'abc'
11883 enddef
11884
11885 var a = A.new()
11886 Fn(a)
11887 END
11888 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 1)
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011889enddef
11890
Yegappan Lakshmanan481992c2024-12-06 18:35:12 +010011891" Test for using an object method with mapnew()
11892def Test_mapnew_with_instance_method()
11893 var lines =<< trim END
11894 vim9script
11895
11896 class Foo
11897 var str: string
11898 var nums: list<number> = [1, 2, 3]
11899
11900 def InstanceMethod(n: number): string
11901 return this.str .. n
11902 enddef
11903
11904 def MapperMethod(idx: number, elem: number): string
11905 return elem->this.InstanceMethod()
11906 enddef
11907
11908 def MapTest()
11909 this.str = "foo"
11910 var l = ['foo1', 'foo2', 'foo3']
11911 assert_equal(l, this.nums->mapnew(this.MapperMethod))
11912 enddef
11913 endclass
11914
11915 Foo.new().MapTest()
11916 END
11917 v9.CheckSourceSuccess(lines)
11918
11919 # Error in the mapnew() function
11920 lines =<< trim END
11921 vim9script
11922
11923 class Foo
11924 var str: string
11925 var nums: list<number> = [1, 2, 3]
11926
11927 def InstanceMethod(n: number): string
11928 throw "InstanceMethod failed"
11929 enddef
11930
11931 def MapperMethod(idx: number, elem: number): string
11932 return elem->this.InstanceMethod()
11933 enddef
11934
11935 def MapTest()
11936 this.str = "foo"
11937 var caught_exception: bool = false
11938 try
11939 this.nums->mapnew(this.MapperMethod)
11940 catch /InstanceMethod failed/
11941 caught_exception = true
11942 endtry
11943 assert_true(caught_exception)
11944 enddef
11945 endclass
11946
11947 Foo.new().MapTest()
11948 END
11949 v9.CheckSourceSuccess(lines)
11950enddef
11951
Yegappan Lakshmananb0206e92024-12-30 09:52:16 +010011952" Test for using an object method in a method call.
11953def Test_use_object_method_in_a_method_call()
11954 var lines =<< trim END
11955 vim9script
11956
11957 class Foo
11958 def Cost(nums: list<number>): number
11959 return nums[0] * nums[1]
11960 enddef
11961
11962 def ShowCost(): string
11963 var g = [4, 5]
11964 return $"Cost is: {g->this.Cost()}"
11965 enddef
11966 endclass
11967
11968 var d = Foo.new()
11969 assert_equal('Cost is: 20', d.ShowCost())
11970 END
11971 v9.CheckSourceSuccess(lines)
11972
11973 # Test for using a non-existing object method in string interpolation
11974 lines =<< trim END
11975 vim9script
11976
11977 class Foo
11978 def Cost(nums: list<number>): number
11979 return nums[0] * nums[1]
11980 enddef
11981
11982 def ShowCost(): string
11983 var g = [4, 5]
11984 echo $"Cost is: {g->this.NewCost()}"
11985 enddef
11986 endclass
11987
11988 var d = Foo.new()
11989 d.ShowCost()
11990 END
11991 v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
11992enddef
11993
Yegappan Lakshmananb04af4c2025-01-03 10:50:08 +010011994" Test for referencing an object variable which is not yet initialized
11995def Test_uninitialized_object_var()
11996 var lines =<< trim END
11997 vim9script
11998 class Foo
11999 const two: number = Foo.Two(this)
12000 const one: number = 1
12001
12002 static def Two(that: Foo): number
12003 return that.one + 2
12004 enddef
12005 endclass
12006
12007 echo Foo.Two(Foo.new())
12008 END
12009 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
12010
12011 lines =<< trim END
12012 vim9script
12013 class Foo
12014 const one: number = Foo.One(this)
12015
12016 static def One(that: Foo): number
12017 return 1
12018 enddef
12019 endclass
12020
12021 assert_equal(1, Foo.One(Foo.new()))
12022 END
12023 v9.CheckSourceSuccess(lines)
12024
12025 lines =<< trim END
12026 vim9script
12027 class Foo
12028 const one: number = 1
12029 const two: number = Foo.Two(this)
12030
12031 static def Two(that: Foo): number
12032 return that.one + 1
12033 enddef
12034 endclass
12035
12036 assert_equal(2, Foo.Two(Foo.new()))
12037 END
12038 v9.CheckSourceSuccess(lines)
12039
12040 lines =<< trim END
12041 vim9script
12042 class Foo
12043 const Id: func(any): any = ((_) => (v) => v)(this)
12044
12045 static def Id(that: Foo): func(any): any
12046 return that.Id
12047 enddef
12048 endclass
12049
12050 assert_equal(5, Foo.Id(Foo.new())(5))
12051 assert_equal(7, Foo.new().Id(7))
12052 END
12053 v9.CheckSourceSuccess(lines)
12054
12055 lines =<< trim END
12056 vim9script
12057 class Foo
12058 const Id: func(any): any = ((that) => (_) => that)(this)
12059
12060 static def Id(that: Foo): func(any): any
12061 return that.Id
12062 enddef
12063 endclass
12064
12065 const Id0: func(any): any = Foo.Id(Foo.new())
12066 const Id1: func(any): any = Foo.new().Id
12067 END
12068 v9.CheckSourceSuccess(lines)
12069
12070 lines =<< trim END
12071 vim9script
12072 class Foo
12073 const Id: any = Foo.Id(this)
12074
12075 static def Id(that: Foo): any
12076 return that.Id
12077 enddef
12078 endclass
12079
12080 const Id2: any = Foo.Id(Foo.new())
12081 const Id3: any = Foo.new().Id
12082 END
12083 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
12084
12085 lines =<< trim END
12086 vim9script
12087
12088 class Foo
12089 var x: string = ''
12090 var Y: func(): string = () => this.x
12091 endclass
12092
12093 var foo = Foo.new('ok')
12094 assert_equal('ok', foo.Y())
12095 END
12096 v9.CheckSourceSuccess(lines)
12097
12098 lines =<< trim END
12099 vim9script
12100
12101 class Foo
12102 var x: string = this.x
12103 endclass
12104
12105 var foo = Foo.new('ok')
12106 END
12107 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
12108enddef
12109
Yegappan Lakshmanan2050dcc2025-01-06 18:34:49 +010012110" Test for initializing member variables of compound type in the constructor
12111def Test_constructor_init_compound_member_var()
12112 var lines =<< trim END
12113 vim9script
12114
12115 class Foo
12116 var v1: string = "aaa"
12117 var v2: list<number> = [1, 2]
12118 var v3: dict<string> = {a: 'a', b: 'b'}
12119 endclass
12120
12121 class Bar
12122 var v4: string = "bbb"
12123 var v5: Foo = Foo.new()
12124 var v6: list<number> = [1, 2]
12125 endclass
12126
12127 var b: Bar = Bar.new()
12128 assert_equal("aaa", b.v5.v1)
12129 assert_equal([1, 2], b.v5.v2)
12130 assert_equal({a: 'a', b: 'b'}, b.v5.v3)
12131 assert_equal("bbb", b.v4)
12132 assert_equal([1, 2], b.v6)
12133 END
12134 v9.CheckSourceSuccess(lines)
12135enddef
12136
Yegappan Lakshmanan68d08582025-02-09 19:39:52 +010012137" Test for using a concrete method in an abstract extended class which is
12138" further extended
12139def Test_abstract_method_across_hierarchy()
12140 var lines =<< trim END
12141 vim9script
12142
12143 abstract class A
12144 abstract def Foo(): string
12145 endclass
12146
12147 abstract class B extends A
12148 abstract def Bar(): string
12149 endclass
12150
12151 class C extends B
12152 def Foo(): string
12153 return 'foo'
12154 enddef
12155
12156 def Bar(): string
12157 return 'bar'
12158 enddef
12159 endclass
12160
12161 def Fn1(a: A): string
12162 return a.Foo()
12163 enddef
12164
12165 def Fn2(b: B): string
12166 return b.Bar()
12167 enddef
12168
12169 var c = C.new()
12170 assert_equal('foo', Fn1(c))
12171 assert_equal('bar', Fn2(c))
12172 END
12173 v9.CheckSourceSuccess(lines)
12174
12175 lines =<< trim END
12176 vim9script
12177
12178 abstract class A
12179 abstract def Foo(): string
12180 endclass
12181
12182 abstract class B extends A
12183 abstract def Bar(): string
12184 endclass
12185
12186 class C extends B
12187 def Bar(): string
12188 return 'bar'
12189 enddef
12190 endclass
12191
12192 defcompile
12193 END
12194 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
12195
12196 lines =<< trim END
12197 vim9script
12198
12199 abstract class A
12200 abstract def M1(): string
12201 abstract def M2(): string
12202 endclass
12203
12204 abstract class B extends A
12205 def M1(): string
12206 return 'B: M1'
12207 enddef
12208
12209 def M2(): string
12210 return 'B: M2'
12211 enddef
12212 endclass
12213
12214 class C1 extends B
12215 def M1(): string
12216 return 'C1: M1'
12217 enddef
12218 endclass
12219
12220 class C2 extends B
12221 def M2(): string
12222 return 'C2: M2'
12223 enddef
12224 endclass
12225
12226 class D1 extends C1
12227 endclass
12228
12229 class D2 extends C2
12230 endclass
12231
12232 var l: list<string> = []
12233 for Type in ['C1', 'C2', 'D1', 'D2']
12234 l->add(eval($'{Type}.new().M1()'))
12235 l->add(eval($'{Type}.new().M2()'))
12236 endfor
12237 assert_equal(['C1: M1', 'B: M2', 'B: M1', 'C2: M2', 'C1: M1', 'B: M2', 'B: M1', 'C2: M2'], l)
12238 END
12239 v9.CheckSourceSuccess(lines)
12240
12241 lines =<< trim END
12242 vim9script
12243
12244 abstract class A
12245 abstract def M1(): string
12246 abstract def M2(): string
12247 endclass
12248
12249 class B extends A
12250 def M1(): string
12251 return 'B: M1'
12252 enddef
12253
12254 def M2(): string
12255 return 'B: M2'
12256 enddef
12257 endclass
12258
12259 abstract class C extends B
12260 endclass
12261
12262 class D1 extends C
12263 def M1(): string
12264 return 'D1: M1'
12265 enddef
12266 endclass
12267
12268 class D2 extends C
12269 def M2(): string
12270 return 'D2: M2'
12271 enddef
12272 endclass
12273
12274 class E1 extends D1
12275 endclass
12276
12277 class E2 extends D2
12278 endclass
12279
12280 var l: list<string> = []
12281 for Type in ['B', 'D1', 'D2', 'E1', 'E2']
12282 l->add(eval($'{Type}.new().M1()'))
12283 l->add( eval($'{Type}.new().M2()'))
12284 endfor
12285 assert_equal(['B: M1', 'B: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2'], l)
12286 END
12287 v9.CheckSourceSuccess(lines)
12288enddef
12289
Yegappan Lakshmanan7e898002025-02-11 22:07:05 +010012290" Test for using a protected new() method (singleton design pattern)
12291def Test_protected_new_method()
12292 var lines =<< trim END
12293 vim9script
12294 class A
12295 def _new()
12296 enddef
12297 endclass
12298 var a = A.new()
12299 END
12300 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "A"', 6)
12301
12302 lines =<< trim END
12303 vim9script
12304 class A
12305 static var _instance: A
12306 var str: string
12307 def _new(str: string)
12308 this.str = str
12309 enddef
12310 static def GetInstance(str: string): A
12311 if _instance == null
12312 _instance = A._new(str)
12313 endif
12314 return _instance
12315 enddef
12316 endclass
12317 var a: A = A.GetInstance('foo')
12318 var b: A = A.GetInstance('bar')
12319 assert_equal('foo', a.str)
12320 assert_equal('foo', b.str)
12321 END
12322 v9.CheckSourceSuccess(lines)
12323enddef
12324
Yegappan Lakshmananb5f463c2025-02-16 16:25:24 +010012325" Test for using 'super' in a closure function inside an object method
12326def Test_super_in_closure()
12327 var lines =<< trim END
12328 vim9script
12329
12330 class A
12331 const _value: number
12332
12333 def Fn(): func(any): number
12334 return (_: any) => this._value
12335 enddef
12336 endclass
12337
12338 class B extends A
12339 def Fn(): func(any): number
12340 return (_: any) => super._value
12341 enddef
12342 endclass
12343
12344 assert_equal(100, A.new(100).Fn()(null))
12345 assert_equal(200, B.new(200).Fn()(null))
12346 END
12347 v9.CheckSourceSuccess(lines)
12348enddef
12349
12350" Test for using 'super' to access methods and variables
12351def Test_super_keyword()
12352 var lines =<< trim END
12353 vim9script
12354 class Base
12355 var name: string
12356 def ToString(): string
12357 return this.name
12358 enddef
12359 endclass
12360
12361 class Child extends Base
12362 var age: number
12363 def ToString(): string
12364 return super.ToString() .. ': ' .. this.age
12365 enddef
12366 endclass
12367
12368 var o = Child.new('John', 42)
12369 assert_equal('John: 42', o.ToString())
12370 END
12371 v9.CheckSourceSuccess(lines)
12372
12373 lines =<< trim END
12374 vim9script
12375 class Child
12376 var age: number
12377 def ToString(): string
12378 return super .ToString() .. ': ' .. this.age
12379 enddef
12380 endclass
12381 var o = Child.new(42)
12382 echo o.ToString()
12383 END
12384 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
12385
12386 lines =<< trim END
12387 vim9script
12388 class Base
12389 var name: string
12390 def ToString(): string
12391 return this.name
12392 enddef
12393 endclass
12394
12395 var age = 42
12396 def ToString(): string
12397 return super.ToString() .. ': ' .. age
12398 enddef
12399 echo ToString()
12400 END
12401 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
12402
12403 lines =<< trim END
12404 vim9script
12405 class Child
12406 var age: number
12407 def ToString(): string
12408 return super.ToString() .. ': ' .. this.age
12409 enddef
12410 endclass
12411 var o = Child.new(42)
12412 echo o.ToString()
12413 END
12414 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
12415
12416 # Using super, Child invokes Base method which has optional arg. #12471
12417 lines =<< trim END
12418 vim9script
12419
12420 class Base
12421 var success: bool = false
12422 def Method(arg = 0)
12423 this.success = true
12424 enddef
12425 endclass
12426
12427 class Child extends Base
12428 def new()
12429 super.Method()
12430 enddef
12431 endclass
12432
12433 var obj = Child.new()
12434 assert_equal(true, obj.success)
12435 END
12436 v9.CheckSourceSuccess(lines)
12437
12438 # Using 'super' to access an object variable in the parent
12439 lines =<< trim END
12440 vim9script
12441
12442 class A
12443 var foo: string = 'xxx'
12444 endclass
12445
12446 class B extends A
12447 def GetString(): string
12448 return super.foo
12449 enddef
12450 endclass
12451
12452 var b: B = B.new()
12453 echo b.GetString()
12454 END
12455 v9.CheckSourceSuccess(lines)
12456
12457 # Using super to access an overriden method in the parent class
12458 lines =<< trim END
12459 vim9script
12460
12461 class A
12462 def Foo(): string
12463 return 'A.Foo'
12464 enddef
12465 endclass
12466
12467 class B extends A
12468 def Foo(): string
12469 return 'B.Foo'
12470 enddef
12471
12472 def Bar(): string
12473 return $'{super.Foo()} {this.Foo()}'
12474 enddef
12475 endclass
12476
12477 var b = B.new()
12478 assert_equal('A.Foo B.Foo', b.Bar())
12479 END
12480 v9.CheckSourceSuccess(lines)
12481enddef
12482
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012483" Test for using a list of objects
12484def Test_method_call_from_list_of_objects()
12485 var lines =<< trim END
12486 vim9script
12487
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012488 class A
12489 var n: list<number> = [100, 101]
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012490 def F(): string
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012491 return 'A.F'
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012492 enddef
12493 endclass
12494
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012495 class B
12496 var name: string
12497 var n: list<number> = [200, 201]
12498 def new(this.name)
12499 enddef
12500 def F(): string
12501 return 'B.F'
12502 enddef
12503 endclass
12504
12505 var obj1 = A.new()
12506 var obj2 = B.new('b1')
12507
12508 def CheckObjectList()
12509 var objlist = [obj1, obj2]
12510 assert_equal('list<object<any>>', typename(objlist))
12511
12512 # Use a member function
12513 assert_equal('A.F', objlist[0].F())
12514 assert_equal('B.F', objlist[1].F())
12515
12516 # Use a member variable on the RHS
12517 assert_equal([100, 101], objlist[0].n)
12518 assert_equal([200, 201], objlist[1].n)
12519
12520 # Use a member variable on the LHS
12521 objlist[0].n[1] = 110
12522 objlist[1].n[1] = 210
12523 assert_equal([100, 110], objlist[0].n)
12524 assert_equal([200, 210], objlist[1].n)
12525
12526 # Iterate using a for loop
12527 var s1 = []
12528 for o in objlist
12529 add(s1, o.F())
12530 endfor
12531 assert_equal(['A.F', 'B.F'], s1)
12532
12533 # Iterate using foreach()
12534 var s2 = []
12535 foreach(objlist, (k, v) => add(s2, v.F()))
12536 assert_equal(['A.F', 'B.F'], s2)
12537
12538 # Add a new list item
12539 objlist->add(B.new('b2'))
12540 assert_equal('b2', objlist[2].name)
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012541 enddef
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012542
12543 CheckObjectList()
12544
12545 var objlist = [A.new(), B.new('b2')]
12546 assert_equal('list<object<any>>', typename(objlist))
12547
12548 # Use a member function
12549 assert_equal('A.F', objlist[0].F())
12550 assert_equal('B.F', objlist[1].F())
12551
12552 # Use a member variable on the RHS
12553 assert_equal([100, 101], objlist[0].n)
12554 assert_equal([200, 201], objlist[1].n)
12555
12556 # Use a member variable on the LHS
12557 objlist[0].n[1] = 110
12558 objlist[1].n[1] = 210
12559 assert_equal([100, 110], objlist[0].n)
12560 assert_equal([200, 210], objlist[1].n)
12561
12562 # Iterate using a for loop
12563 var s1 = []
12564 for o in objlist
12565 add(s1, o.F())
12566 endfor
12567 assert_equal(['A.F', 'B.F'], s1)
12568
12569 # Iterate using foreach()
12570 var s2 = []
12571 foreach(objlist, (k, v) => add(s2, v.F()))
12572 assert_equal(['A.F', 'B.F'], s2)
12573
12574 # Add a new list item
12575 objlist->add(B.new('b2'))
12576 assert_equal('b2', objlist[2].name)
12577 END
12578 v9.CheckSourceSuccess(lines)
12579
12580 lines =<< trim END
12581 vim9script
12582
12583 class A
12584 endclass
12585
12586 class B
12587 endclass
12588
12589 var objlist = [A.new(), B.new()]
12590 def Fn()
12591 objlist->add(10)
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012592 enddef
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012593
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012594 try
12595 Fn()
12596 catch
12597 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12598 endtry
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012599
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012600 try
12601 objlist->add(10)
12602 catch
12603 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12604 endtry
12605 END
12606 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012607
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012608 # Adding an enum to a List of objects should fail
12609 lines =<< trim END
12610 vim9script
12611 class A
12612 endclass
12613 class B
12614 endclass
12615 enum C
12616 Red,
12617 Green,
12618 endenum
12619 var items = [A.new(), B.new()]
12620 def Fn()
12621 items->add(C.Red)
12622 enddef
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012623
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012624 try
12625 Fn()
12626 catch
12627 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
12628 endtry
12629
12630 try
12631 items->add(C.Green)
12632 catch
12633 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
12634 endtry
12635
12636 var items2 = [C.Red, C.Green]
12637 def Fn2()
12638 items2->add(A.new())
12639 enddef
12640 try
12641 Fn2()
12642 catch
12643 assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<A>')
12644 endtry
12645
12646 try
12647 items2->add(B.new())
12648 catch
12649 assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<B>')
12650 endtry
12651 END
12652 v9.CheckSourceSuccess(lines)
12653enddef
12654
12655" Test for using a dict of objects
12656def Test_dict_of_objects()
12657 var lines =<< trim END
12658 vim9script
12659
12660 class A
12661 var n: list<number> = [100, 101]
12662 def F(): string
12663 return 'A.F'
12664 enddef
12665 endclass
12666
12667 class B
12668 var name: string
12669 var n: list<number> = [200, 201]
12670 def new(this.name)
12671 enddef
12672 def F(): string
12673 return 'B.F'
12674 enddef
12675 endclass
12676
12677 var obj1 = A.new()
12678 var obj2 = B.new('b1')
12679
12680 def CheckObjectDict()
12681 var objdict = {o_a: obj1, o_b: obj2}
12682 assert_equal('dict<object<any>>', typename(objdict))
12683
12684 # Use a member function
12685 assert_equal('A.F', objdict.o_a.F())
12686 assert_equal('B.F', objdict.o_b.F())
12687
12688 # Use a member variable on the RHS
12689 assert_equal([100, 101], objdict.o_a.n)
12690 assert_equal([200, 201], objdict.o_b.n)
12691
12692 # Use a member variable on the LHS
12693 objdict.o_a.n[1] = 110
12694 objdict.o_b.n[1] = 210
12695 assert_equal([100, 110], objdict.o_a.n)
12696 assert_equal([200, 210], objdict.o_b.n)
12697
12698 # Iterate using a for loop
12699 var l = []
12700 for v in values(objdict)
12701 add(l, v.F())
12702 endfor
12703 assert_equal(['A.F', 'B.F'], l)
12704
12705 # Iterate using foreach()
12706 l = []
12707 foreach(objdict, (k, v) => add(l, v.F()))
12708 assert_equal(['A.F', 'B.F'], l)
12709
12710 # Add a new dict item
12711 objdict['o_b2'] = B.new('b2')
12712 assert_equal('b2', objdict.o_b2.name)
12713 enddef
12714
12715 CheckObjectDict()
12716
12717 var objdict = {o_a: A.new(), o_b: B.new('b2')}
12718 assert_equal('dict<object<any>>', typename(objdict))
12719 assert_equal('A.F', objdict.o_a.F())
12720 assert_equal('B.F', objdict.o_b.F())
12721 assert_equal([100, 101], objdict.o_a.n)
12722 assert_equal([200, 201], objdict.o_b.n)
12723
12724 var l = []
12725 for v in values(objdict)
12726 add(l, v.F())
12727 endfor
12728 assert_equal(['A.F', 'B.F'], l)
12729
12730 # Add a new dict item
12731 objdict['o_b2'] = B.new('b2')
12732 assert_equal('b2', objdict.o_b2.name)
12733 END
12734 v9.CheckSourceSuccess(lines)
12735
12736 lines =<< trim END
12737 vim9script
12738
12739 class A
12740 endclass
12741 class B
12742 endclass
12743 class C
12744 endclass
12745 var objdict = {a: A.new(), b: B.new()}
12746 def Fn()
12747 objdict['c'] = C.new()
12748 enddef
12749
12750 try
12751 Fn()
12752 catch
12753 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12754 endtry
12755
12756 try
12757 objdict['c'] = C.new()
12758 catch
12759 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12760 endtry
12761 END
12762 v9.CheckSourceSuccess(lines)
12763
12764 # Adding an enum to a Dict of objects should fail
12765 lines =<< trim END
12766 vim9script
12767 class A
12768 endclass
12769 class B
12770 endclass
12771 enum C
12772 Red,
12773 Green,
12774 endenum
12775 var items = {o_a: A.new(), o_b: B.new()}
12776 def Fn()
12777 items['o_c'] = C.Red
12778 enddef
12779
12780 try
12781 Fn()
12782 catch
12783 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
12784 endtry
12785
12786 try
12787 items['o_c'] = C.Green
12788 catch
12789 assert_exception('Vim(var):E1012: Type mismatch; expected object<any> but got enum<C>')
12790 endtry
12791
12792 var items2 = {red: C.Red, green: C.Green}
12793 def Fn2()
12794 items2['o_a'] = A.new()
12795 enddef
12796 try
12797 Fn2()
12798 catch
12799 assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<A>')
12800 endtry
12801
12802 try
12803 items2['o_a'] = B.new()
12804 catch
12805 assert_exception('Vim(var):E1012: Type mismatch; expected enum<C> but got object<B>')
12806 endtry
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012807 END
12808 v9.CheckSourceSuccess(lines)
12809enddef
12810
Bram Moolenaar00b28d62022-12-08 15:32:33 +000012811" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker