blob: 4aa9bb3b36bc826d86dce4a820463cd1d3cbb0f6 [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
Yegappan Lakshmanan5ce1e4a2025-04-07 21:09:18 +02001924 # Space is not allowed before the object member variable name
1925 lines =<< trim END
1926 vim9script
1927 class A
1928 var n: number = 10
1929 endclass
1930
1931 def Fn()
1932 var a = A.new()
1933 var y = a. n
1934 enddef
1935 defcompile
1936 END
1937 v9.CheckSourceFailure(lines, "E1202: No white space allowed after '.': . n", 2)
1938
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001939 # Access a non-existing member
1940 lines =<< trim END
1941 vim9script
1942 class A
1943 endclass
1944 var a = A.new()
1945 var v = a.bar
1946 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02001947 v9.CheckSourceFailure(lines, 'E1326: Variable "bar" not found in object "A"', 5)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001948enddef
1949
Ernie Raele6c9aa52023-10-06 19:55:52 +02001950" These messages should show the defining class of the variable (base class),
1951" not the class that did the reference (super class)
1952def Test_defining_class_message()
1953 var lines =<< trim END
1954 vim9script
1955
1956 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001957 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001958 endclass
1959
1960 class Child extends Base
1961 endclass
1962
1963 var o = Child.new()
1964 var x = o._v1
1965 END
Ernie Rael03042a22023-11-11 08:53:32 +01001966 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 11)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001967 lines =<< trim END
1968 vim9script
1969
1970 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001971 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001972 endclass
1973
1974 class Child extends Base
1975 endclass
1976
1977 def F()
1978 var o = Child.new()
1979 var x = o._v1
1980 enddef
1981 F()
1982 END
Ernie Rael03042a22023-11-11 08:53:32 +01001983 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001984 lines =<< trim END
1985 vim9script
1986
1987 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001988 var v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001989 endclass
1990
1991 class Child extends Base
1992 endclass
1993
1994 var o = Child.new()
1995 o.v1 = []
1996 END
1997 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 11)
1998 lines =<< trim END
1999 vim9script
2000
2001 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01002002 var v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002003 endclass
2004
2005 class Child extends Base
2006 endclass
2007
2008 def F()
2009 var o = Child.new()
2010 o.v1 = []
2011 enddef
2012 F()
2013 END
2014
Ernie Rael03042a22023-11-11 08:53:32 +01002015 # Attempt to read a protected variable that is in the middle
Ernie Raele6c9aa52023-10-06 19:55:52 +02002016 # of the class hierarchy.
2017 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 2)
2018 lines =<< trim END
2019 vim9script
2020
2021 class Base0
2022 endclass
2023
2024 class Base extends Base0
Doug Kearns74da0ee2023-12-14 20:26:26 +01002025 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002026 endclass
2027
2028 class Child extends Base
2029 endclass
2030
2031 def F()
2032 var o = Child.new()
2033 var x = o._v1
2034 enddef
2035 F()
2036 END
Ernie Rael03042a22023-11-11 08:53:32 +01002037 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002038
Ernie Rael03042a22023-11-11 08:53:32 +01002039 # Attempt to read a protected variable that is at the start
Ernie Raele6c9aa52023-10-06 19:55:52 +02002040 # of the class hierarchy.
2041 lines =<< trim END
2042 vim9script
2043
2044 class Base0
2045 endclass
2046
2047 class Base extends Base0
2048 endclass
2049
2050 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01002051 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002052 endclass
2053
2054 def F()
2055 var o = Child.new()
2056 var x = o._v1
2057 enddef
2058 F()
2059 END
Ernie Rael03042a22023-11-11 08:53:32 +01002060 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Child"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002061enddef
2062
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002063func Test_class_garbagecollect()
2064 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002065 vim9script
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002066
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002067 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002068 var p = [2, 3]
2069 static var pl = ['a', 'b']
2070 static var pd = {a: 'a', b: 'b'}
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002071 endclass
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002072
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002073 echo Point.pl Point.pd
2074 call test_garbagecollect_now()
2075 echo Point.pl Point.pd
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002076 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002077 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002078
2079 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002080 vim9script
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002081
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002082 interface View
2083 endinterface
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002084
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002085 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01002086 var view: View
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002087 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002088
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002089 class MyView implements View
Doug Kearns74da0ee2023-12-14 20:26:26 +01002090 var widget: Widget
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002091
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002092 def new()
2093 # this will result in a circular reference to this object
Doug Kearns74da0ee2023-12-14 20:26:26 +01002094 var widget = Widget.new(this)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002095 enddef
2096 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002097
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002098 var view = MyView.new()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002099
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002100 # overwrite "view", will be garbage-collected next
2101 view = MyView.new()
2102 test_garbagecollect_now()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002103 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002104 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002105endfunc
2106
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002107" Test interface garbage collection
2108func Test_interface_garbagecollect()
2109 let lines =<< trim END
2110 vim9script
2111
2112 interface I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002113 var ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002114
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002115 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002116 endinterface
2117
2118 class A implements I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002119 static var ro_class_var: number = 10
2120 public static var rw_class_var: number = 20
2121 static var _priv_class_var: number = 30
2122 var ro_obj_var: number = 40
2123 var _priv_obj_var: number = 60
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002124
2125 static def _ClassBar(): number
2126 return _priv_class_var
2127 enddef
2128
2129 static def ClassFoo(): number
2130 return ro_class_var + rw_class_var + A._ClassBar()
2131 enddef
2132
2133 def _ObjBar(): number
2134 return this._priv_obj_var
2135 enddef
2136
2137 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002138 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002139 enddef
2140 endclass
2141
2142 assert_equal(60, A.ClassFoo())
2143 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002144 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002145 test_garbagecollect_now()
2146 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002147 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002148 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002149 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002150endfunc
2151
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002152def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002153 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002154 vim9script
2155 class Value
Doug Kearns74da0ee2023-12-14 20:26:26 +01002156 var value = 0
2157 static var objects = 0
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002158
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002159 def new(v: number)
2160 this.value = v
2161 ++objects
2162 enddef
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002163
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002164 static def GetCount(): number
2165 return objects
2166 enddef
2167 endclass
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002168
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002169 assert_equal(0, Value.GetCount())
2170 var v1 = Value.new(2)
2171 assert_equal(1, Value.GetCount())
2172 var v2 = Value.new(7)
2173 assert_equal(2, Value.GetCount())
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002174 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002175 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002176
2177 # Test for cleaning up after a class definition failure when using class
2178 # functions.
2179 lines =<< trim END
2180 vim9script
2181 class A
2182 static def Foo()
2183 enddef
2184 aaa
2185 endclass
2186 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002187 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: aaa', 5)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002188
2189 # Test for calling a class method from another class method without the class
2190 # name prefix.
2191 lines =<< trim END
2192 vim9script
2193 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01002194 static var myList: list<number> = [1]
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002195 static def Foo(n: number)
2196 myList->add(n)
2197 enddef
2198 static def Bar()
2199 Foo(2)
2200 enddef
2201 def Baz()
2202 Foo(3)
2203 enddef
2204 endclass
2205 A.Bar()
2206 var a = A.new()
2207 a.Baz()
2208 assert_equal([1, 2, 3], A.myList)
2209 END
2210 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002211enddef
2212
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002213def Test_class_defcompile()
2214 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002215 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002216
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002217 class C
2218 def Fo(i: number): string
2219 return i
2220 enddef
2221 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002222
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002223 defcompile C.Fo
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002224 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002225 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number', 1)
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002226
2227 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002228 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002229
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002230 class C
2231 static def Fc(): number
2232 return 'x'
2233 enddef
2234 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002235
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002236 defcompile C.Fc
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002237 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002238 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002239
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002240 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002241 vim9script
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002242
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002243 class C
2244 static def new()
2245 enddef
2246 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002247
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002248 defcompile C.new
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002249 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002250 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static', 5)
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002251
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002252 # Trying to compile a function using a non-existing class variable
2253 lines =<< trim END
2254 vim9script
2255 defcompile x.Foo()
2256 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002257 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002258
2259 # Trying to compile a function using a variable which is not a class
2260 lines =<< trim END
2261 vim9script
2262 var x: number
2263 defcompile x.Foo()
2264 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002265 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002266
2267 # Trying to compile a function without specifying the name
2268 lines =<< trim END
2269 vim9script
2270 class A
2271 endclass
2272 defcompile A.
2273 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002274 v9.CheckSourceFailure(lines, 'E475: Invalid argument: A.', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002275
2276 # Trying to compile a non-existing class object member function
2277 lines =<< trim END
2278 vim9script
2279 class A
2280 endclass
2281 var a = A.new()
2282 defcompile a.Foo()
2283 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02002284 v9.CheckSourceFailureList(lines, ['E1326: Variable "Foo" not found in object "A"', 'E475: Invalid argument: a.Foo()'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002285enddef
2286
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002287def Test_class_object_to_string()
2288 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002289 vim9script
2290 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01002291 var lnum = 1
2292 var col = 22
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002293 endclass
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002294
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002295 assert_equal("class TextPosition", string(TextPosition))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002296
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002297 var pos = TextPosition.new()
2298 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002299 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002300 v9.CheckSourceSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +02002301
2302 # check string() with object nesting
2303 lines =<< trim END
2304 vim9script
2305 class C
2306 var nest1: C
2307 var nest2: C
2308 def Init(n1: C, n2: C)
2309 this.nest1 = n1
2310 this.nest2 = n2
2311 enddef
2312 endclass
2313
2314 var o1 = C.new()
2315 var o2 = C.new()
2316 o1.Init(o1, o2)
2317 o2.Init(o2, o1)
2318
2319 # The following previously put's vim into an infinite loop.
2320
2321 var expect = "object of C {nest1: object of C {...}, nest2: object of C {nest1: object of C {...}, nest2: object of C {...}}}"
2322 assert_equal(expect, string(o1))
2323 END
2324 v9.CheckSourceSuccess(lines)
2325
2326 lines =<< trim END
2327 vim9script
2328
2329 class B
2330 endclass
2331
2332 class C
2333 var b: B
2334 var c: C
2335 endclass
2336
2337 var o1 = C.new(B.new(), C.new(B.new()))
2338 var expect = "object of C {b: object of B {}, c: object of C {b: object of B {}, c: object of [unknown]}}"
2339 assert_equal(expect, string(o1))
2340 END
2341 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002342enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00002343
Bram Moolenaar554d0312023-01-05 19:59:18 +00002344def Test_interface_basics()
2345 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002346 vim9script
2347 interface Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01002348 var ro_var: list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002349 def GetCount(): number
2350 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002351 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002352 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002353
2354 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002355 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002356 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002357 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002358 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002359 v9.CheckSourceFailure(lines, 'E1342: Interface can only be defined in Vim9 script', 1)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002360
2361 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002362 vim9script
Bram Moolenaar554d0312023-01-05 19:59:18 +00002363
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002364 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002365 var value: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002366 def Method(value: number)
2367 endinterface
Bram Moolenaard40f00c2023-01-13 17:36:49 +00002368 END
h-east61378a12023-04-18 19:07:29 +01002369 # The argument name and the object member name are the same, but this is not a
2370 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002371 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002372
2373 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002374 vim9script
2375 interface somethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002376 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002377 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002378 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002379 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong', 2)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002380
2381 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002382 vim9script
2383 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002384 var value: string
2385 var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002386 def GetCount(): number
2387 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002388 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002389 v9.CheckSourceFailure(lines, 'E1344: Cannot initialize a variable in an interface', 4)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002390
2391 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002392 vim9script
2393 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002394 var value: string
2395 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002396 def GetCount(): number
2397 return 5
2398 enddef
2399 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002400 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002401 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5', 6)
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002402
h-eastaa979c72025-01-03 10:19:45 +01002403 # Test for "interface" cannot be abbreviated
2404 lines =<< trim END
2405 vim9script
2406 inte Something
2407 endinterface
2408 END
2409 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: inte Something', 2)
2410
2411 # Test for "endinterface" cannot be abbreviated
2412 lines =<< trim END
2413 vim9script
2414 interface Something
2415 endin
2416 END
2417 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endin', 3)
2418
Yegappan Lakshmananac773182024-04-27 11:36:12 +02002419 # Additional commands after "interface name"
2420 lines =<< trim END
2421 vim9script
2422 interface Something | var x = 10 | var y = 20
2423 endinterface
2424 END
2425 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
2426
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002427 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002428 vim9script
2429 export interface EnterExit
2430 def Enter(): void
2431 def Exit(): void
2432 endinterface
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002433 END
2434 writefile(lines, 'XdefIntf.vim', 'D')
2435
2436 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002437 vim9script
2438 import './XdefIntf.vim' as defIntf
2439 export def With(ee: defIntf.EnterExit, F: func)
2440 ee.Enter()
2441 try
2442 F()
2443 finally
2444 ee.Exit()
2445 endtry
2446 enddef
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002447 END
2448 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002449
2450 var imported =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002451 vim9script
2452 export abstract class EnterExit
2453 def Enter(): void
2454 enddef
2455 def Exit(): void
2456 enddef
2457 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +00002458 END
2459 writefile(imported, 'XdefIntf2.vim', 'D')
2460
2461 lines[1] = " import './XdefIntf2.vim' as defIntf"
2462 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002463enddef
2464
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01002465" Test for using string() with an interface
2466def Test_interface_to_string()
2467 var lines =<< trim END
2468 vim9script
2469 interface Intf
2470 def Method(nr: number)
2471 endinterface
2472 assert_equal("interface Intf", string(Intf))
2473 END
2474 v9.CheckSourceSuccess(lines)
2475enddef
2476
Bram Moolenaar94674f22023-01-06 18:42:20 +00002477def Test_class_implements_interface()
2478 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002479 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002480
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002481 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002482 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002483 def Method(nr: number)
2484 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002485
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002486 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002487 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002488 def Method(nr: number)
2489 echo nr
2490 enddef
2491 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002492
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002493 interface Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002494 var member: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002495 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002496
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002497 class AnotherImpl implements Some, Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002498 var member = 'abc'
2499 var count = 20
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002500 def Method(nr: number)
2501 echo nr
2502 enddef
2503 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002504 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002505 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002506
2507 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002508 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002509
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002510 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002511 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002512 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002513
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002514 class SomeImpl implements Some implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002515 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002516 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002517 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002518 v9.CheckSourceFailure(lines, 'E1350: Duplicate "implements"', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002519
2520 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002521 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002522
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002523 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002524 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002525 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002526
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002527 class SomeImpl implements Some, Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002528 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002529 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002530 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002531 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002532
2533 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002534 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002535
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002536 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002537 var counter: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002538 def Method(nr: number)
2539 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002540
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002541 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002542 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002543 def Method(nr: number)
2544 echo nr
2545 enddef
2546 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002547 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002548 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented', 13)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002549
2550 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002551 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002552
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002553 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002554 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002555 def Methods(nr: number)
2556 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002557
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002558 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002559 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002560 def Method(nr: number)
2561 echo nr
2562 enddef
2563 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002564 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002565 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented', 13)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002566
2567 # Check different order of members in class and interface works.
2568 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002569 vim9script
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002570
2571 interface Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002572 var label: string
2573 var errpos: number
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002574 endinterface
2575
2576 # order of members is opposite of interface
2577 class Failure implements Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002578 public var lnum: number = 5
2579 var errpos: number = 42
2580 var label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002581 endclass
2582
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002583 def Test()
2584 var result: Result = Failure.new()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002585
2586 assert_equal('label', result.label)
2587 assert_equal(42, result.errpos)
2588 enddef
2589
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002590 Test()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002591 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002592 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002593
2594 # Interface name after "extends" doesn't end in a space or NUL character
2595 lines =<< trim END
2596 vim9script
2597 interface A
2598 endinterface
2599 class B extends A"
2600 endclass
2601 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002602 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002603
2604 # Trailing characters after a class name
2605 lines =<< trim END
2606 vim9script
2607 class A bbb
2608 endclass
2609 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002610 v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002611
2612 # using "implements" with a non-existing class
2613 lines =<< trim END
2614 vim9script
2615 class A implements B
2616 endclass
2617 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002618 v9.CheckSourceFailure(lines, 'E1346: Interface name not found: B', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002619
2620 # using "implements" with a regular class
2621 lines =<< trim END
2622 vim9script
2623 class A
2624 endclass
2625 class B implements A
2626 endclass
2627 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002628 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: A', 5)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002629
2630 # using "implements" with a variable
2631 lines =<< trim END
2632 vim9script
2633 var T: number = 10
2634 class A implements T
2635 endclass
2636 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002637 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: T', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002638
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002639 # implements should be followed by a white space
2640 lines =<< trim END
2641 vim9script
2642 interface A
2643 endinterface
2644 class B implements A;
2645 endclass
2646 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002647 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A;', 4)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002648
LemonBoyc5d27442023-08-19 13:02:35 +02002649 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002650 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002651
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002652 interface One
2653 def IsEven(nr: number): bool
2654 endinterface
2655 class Two implements One
2656 def IsEven(nr: number): string
2657 enddef
2658 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002659 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002660 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002661
2662 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002663 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002664
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002665 interface One
2666 def IsEven(nr: number): bool
2667 endinterface
2668 class Two implements One
2669 def IsEven(nr: bool): bool
2670 enddef
2671 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002672 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002673 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002674
2675 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002676 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002677
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002678 interface One
2679 def IsEven(nr: number): bool
2680 endinterface
2681 class Two implements One
2682 def IsEven(nr: number, ...extra: list<number>): bool
2683 enddef
2684 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002685 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002686 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 +02002687
2688 # access superclass interface members from subclass, mix variable order
2689 lines =<< trim END
2690 vim9script
2691
2692 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002693 var mvar1: number
2694 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002695 endinterface
2696
2697 # NOTE: the order is swapped
2698 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002699 var mvar2: number
2700 var mvar1: number
2701 public static var svar2: number
2702 public static var svar1: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002703 def new()
2704 svar1 = 11
2705 svar2 = 12
2706 this.mvar1 = 111
2707 this.mvar2 = 112
2708 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002709 endclass
2710
2711 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002712 def new()
2713 this.mvar1 = 121
2714 this.mvar2 = 122
2715 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002716 endclass
2717
2718 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002719 def new()
2720 this.mvar1 = 131
2721 this.mvar2 = 132
2722 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002723 endclass
2724
Ernie Raelcf138d42023-09-06 20:45:03 +02002725 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002726 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002727 enddef
2728
2729 var oa = A.new()
2730 var ob = B.new()
2731 var oc = C.new()
2732
Ernie Raelcf138d42023-09-06 20:45:03 +02002733 assert_equal([111, 112], F2(oa))
2734 assert_equal([121, 122], F2(ob))
2735 assert_equal([131, 132], F2(oc))
2736 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002737 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002738
2739 # Access superclass interface members from subclass, mix variable order.
2740 # Two interfaces, one on A, one on B; each has both kinds of variables
2741 lines =<< trim END
2742 vim9script
2743
2744 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002745 var mvar1: number
2746 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002747 endinterface
2748
2749 interface I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002750 var mvar3: number
2751 var mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002752 endinterface
2753
2754 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002755 public static var svar1: number
2756 public static var svar2: number
2757 var mvar1: number
2758 var mvar2: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002759 def new()
2760 svar1 = 11
2761 svar2 = 12
2762 this.mvar1 = 111
2763 this.mvar2 = 112
2764 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002765 endclass
2766
2767 class B extends A implements I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002768 static var svar3: number
2769 static var svar4: number
2770 var mvar3: number
2771 var mvar4: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002772 def new()
2773 svar3 = 23
2774 svar4 = 24
2775 this.mvar1 = 121
2776 this.mvar2 = 122
2777 this.mvar3 = 123
2778 this.mvar4 = 124
2779 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002780 endclass
2781
2782 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01002783 public static var svar5: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002784 def new()
2785 svar5 = 1001
2786 this.mvar1 = 131
2787 this.mvar2 = 132
2788 this.mvar3 = 133
2789 this.mvar4 = 134
2790 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002791 endclass
2792
Ernie Raelcf138d42023-09-06 20:45:03 +02002793 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002794 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002795 enddef
2796
Ernie Raelcf138d42023-09-06 20:45:03 +02002797 def F4(i: I2): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002798 return [ i.mvar3, i.mvar4 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002799 enddef
2800
Ernie Raelcf138d42023-09-06 20:45:03 +02002801 var oa = A.new()
2802 var ob = B.new()
2803 var oc = C.new()
2804
Ernie Raelcf138d42023-09-06 20:45:03 +02002805 assert_equal([[111, 112]], [F2(oa)])
2806 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2807 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002808 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002809 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002810
2811 # Using two interface names without a space after the ","
2812 lines =<< trim END
2813 vim9script
2814 interface A
2815 endinterface
2816 interface B
2817 endinterface
2818 class C implements A,B
2819 endclass
2820 END
2821 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2822
2823 # No interface name after a comma
2824 lines =<< trim END
2825 vim9script
2826 interface A
2827 endinterface
2828 class B implements A,
2829 endclass
2830 END
2831 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2832
2833 # No interface name after implements
2834 lines =<< trim END
2835 vim9script
2836 class A implements
2837 endclass
2838 END
2839 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002840enddef
2841
Bram Moolenaard0200c82023-01-28 15:19:40 +00002842def Test_call_interface_method()
2843 var lines =<< trim END
2844 vim9script
2845 interface Base
2846 def Enter(): void
2847 endinterface
2848
2849 class Child implements Base
2850 def Enter(): void
2851 g:result ..= 'child'
2852 enddef
2853 endclass
2854
2855 def F(obj: Base)
2856 obj.Enter()
2857 enddef
2858
2859 g:result = ''
2860 F(Child.new())
2861 assert_equal('child', g:result)
2862 unlet g:result
2863 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002864 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002865
2866 lines =<< trim END
2867 vim9script
2868 class Base
2869 def Enter(): void
2870 g:result ..= 'base'
2871 enddef
2872 endclass
2873
2874 class Child extends Base
2875 def Enter(): void
2876 g:result ..= 'child'
2877 enddef
2878 endclass
2879
2880 def F(obj: Base)
2881 obj.Enter()
2882 enddef
2883
2884 g:result = ''
2885 F(Child.new())
2886 assert_equal('child', g:result)
2887 unlet g:result
2888 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002889 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002890
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002891 # method of interface returns a value
2892 lines =<< trim END
2893 vim9script
2894 interface Base
2895 def Enter(): string
2896 endinterface
2897
2898 class Child implements Base
2899 def Enter(): string
2900 g:result ..= 'child'
2901 return "/resource"
2902 enddef
2903 endclass
2904
2905 def F(obj: Base)
2906 var r = obj.Enter()
2907 g:result ..= r
2908 enddef
2909
2910 g:result = ''
2911 F(Child.new())
2912 assert_equal('child/resource', g:result)
2913 unlet g:result
2914 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002915 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002916
2917 lines =<< trim END
2918 vim9script
2919 class Base
2920 def Enter(): string
2921 return null_string
2922 enddef
2923 endclass
2924
2925 class Child extends Base
2926 def Enter(): string
2927 g:result ..= 'child'
2928 return "/resource"
2929 enddef
2930 endclass
2931
2932 def F(obj: Base)
2933 var r = obj.Enter()
2934 g:result ..= r
2935 enddef
2936
2937 g:result = ''
2938 F(Child.new())
2939 assert_equal('child/resource', g:result)
2940 unlet g:result
2941 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002942 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002943
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002944 # No class that implements the interface.
2945 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002946 vim9script
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002947
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002948 interface IWithEE
2949 def Enter(): any
2950 def Exit(): void
2951 endinterface
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002952
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002953 def With1(ee: IWithEE, F: func)
2954 var r = ee.Enter()
2955 enddef
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002956
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002957 defcompile
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002958 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002959 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002960enddef
2961
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002962def Test_class_used_as_type()
2963 var 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 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002967 var x = 0
2968 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002969 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002970
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002971 var p: Point
2972 p = Point.new(2, 33)
2973 assert_equal(2, p.x)
2974 assert_equal(33, p.y)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002975 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002976 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002977
2978 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002979 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002980
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002981 interface HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002982 var x: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002983 endinterface
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002984
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002985 class Point implements HasX
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 = Point.new(2, 33)
2992 var hx = p
2993 assert_equal(2, hx.x)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002994 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002995 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002996
2997 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002998 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002999
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003000 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01003001 var x = 0
3002 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003003 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00003004
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003005 var p: Point
3006 p = 'text'
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00003007 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003008 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string', 9)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00003009enddef
3010
Bram Moolenaar83677162023-01-08 19:54:10 +00003011def Test_class_extends()
3012 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003013 vim9script
3014 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003015 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003016 def GetOne(): number
3017 return this.one
Bram Moolenaar6aa09372023-01-11 17:59:38 +00003018 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003019 endclass
3020 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003021 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003022 def GetTotal(): number
3023 return this.one + this.two
3024 enddef
3025 endclass
3026 var o = Child.new()
3027 assert_equal(1, o.one)
3028 assert_equal(2, o.two)
3029 assert_equal(1, o.GetOne())
3030 assert_equal(3, o.GetTotal())
Bram Moolenaar6481acc2023-01-11 21:14:17 +00003031 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003032 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003033
3034 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003035 vim9script
3036 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003037 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003038 endclass
3039 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003040 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003041 endclass
3042 var o = Child.new(3, 44)
3043 assert_equal(3, o.one)
3044 assert_equal(44, o.two)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003045 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003046 v9.CheckSourceSuccess(lines)
3047
3048 lines =<< trim END
3049 vim9script
3050 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003051 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003052 endclass
3053 class Child extends Base extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003054 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003055 endclass
3056 END
3057 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"', 5)
3058
3059 lines =<< trim END
3060 vim9script
3061 class Child extends BaseClass
Doug Kearns74da0ee2023-12-14 20:26:26 +01003062 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003063 endclass
3064 END
3065 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass', 4)
3066
3067 lines =<< trim END
3068 vim9script
3069 var SomeVar = 99
3070 class Child extends SomeVar
Doug Kearns74da0ee2023-12-14 20:26:26 +01003071 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003072 endclass
3073 END
3074 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar', 5)
3075
3076 lines =<< trim END
3077 vim9script
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003078 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003079 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003080 def ToString(): number
3081 return this.age
3082 enddef
3083 def ToString(): string
3084 return this.age
3085 enddef
3086 endclass
3087 END
3088 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
3089
3090 lines =<< trim END
3091 vim9script
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003092 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003093 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003094 static def ToString(): string
3095 return 'Base class'
3096 enddef
3097 endclass
3098
3099 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003100 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003101 def ToString(): string
3102 return Base.ToString() .. ': ' .. this.age
3103 enddef
3104 endclass
3105
3106 var o = Child.new('John', 42)
3107 assert_equal('Base class: 42', o.ToString())
3108 END
3109 v9.CheckSourceSuccess(lines)
3110
3111 lines =<< trim END
3112 vim9script
3113 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003114 var value = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003115 def new(init: number)
3116 this.value = number + 1
3117 enddef
3118 endclass
3119 class Child extends Base
3120 def new()
3121 this.new(3)
3122 enddef
3123 endclass
3124 var c = Child.new()
3125 END
3126 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003127
3128 # base class with more than one object member
3129 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003130 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003131
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003132 class Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01003133 var success: bool
3134 var value: any = null
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003135 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003136
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003137 class Success extends Result
3138 def new(this.value = v:none)
3139 this.success = true
3140 enddef
3141 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003142
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003143 var v = Success.new('asdf')
3144 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003145 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003146 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003147
3148 # class name after "extends" doesn't end in a space or NUL character
3149 lines =<< trim END
3150 vim9script
3151 class A
3152 endclass
3153 class B extends A"
3154 endclass
3155 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003156 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00003157enddef
3158
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003159def Test_using_base_class()
3160 var lines =<< trim END
3161 vim9script
3162
3163 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003164 def Enter(): any
3165 return null
3166 enddef
3167 def Exit(resource: any): void
3168 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003169 endclass
3170
3171 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003172 def Enter(): any
3173 return 42
3174 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003175
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003176 def Exit(resource: number): void
3177 g:result ..= '/exit'
3178 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003179 endclass
3180
3181 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003182 var r = ee.Enter()
3183 try
3184 g:result ..= r
3185 finally
3186 g:result ..= '/finally'
3187 ee.Exit(r)
3188 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003189 enddef
3190
3191 g:result = ''
3192 With(ChildEE.new())
3193 assert_equal('42/finally/exit', g:result)
3194 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003195 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003196 unlet g:result
3197enddef
3198
Ernie Raelbce60c42025-01-19 10:03:00 +01003199" Test for using a method from the super class
Ernie Rael58c95792024-08-13 23:27:22 +02003200def Test_super_dispatch()
3201 # See #15448 and #15463
3202 var lines =<< trim END
3203 vim9script
3204
3205 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003206 def String(): string
3207 return 'A'
3208 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003209 endclass
3210
3211 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003212 def String(): string
3213 return super.String()
3214 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003215 endclass
3216
3217 class C extends B
3218 endclass
3219
3220 assert_equal('A', C.new().String())
3221 END
3222 v9.CheckSourceSuccess(lines)
3223
3224 lines =<< trim END
3225 vim9script
3226
3227 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003228 def F(): string
3229 return 'AA'
3230 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003231 endclass
3232
3233 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003234 def F(): string
3235 return 'BB'
3236 enddef
3237 def S(): string
3238 return super.F()
3239 enddef
3240 def S0(): string
3241 return this.S()
3242 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003243 endclass
3244
3245 class C extends B
Ernie Raelbce60c42025-01-19 10:03:00 +01003246 def F(): string
3247 return 'CC'
3248 enddef
3249 def ToB(): string
3250 return super.F()
3251 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003252 endclass
3253
3254 assert_equal('AA', B.new().S())
3255 assert_equal('AA', C.new().S())
3256 assert_equal('AA', B.new().S0())
3257 assert_equal('AA', C.new().S0())
3258
3259 assert_equal('BB', C.new().ToB())
3260
3261 assert_equal('CC', C.new().F())
3262 assert_equal('BB', B.new().F())
3263 assert_equal('AA', A.new().F())
3264 END
3265 v9.CheckSourceSuccess(lines)
3266
3267 lines =<< trim END
3268 vim9script
3269
3270 var call_chain: list<string>
3271
3272 abstract class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003273 abstract def _G(): string
Ernie Rael58c95792024-08-13 23:27:22 +02003274
Ernie Raelbce60c42025-01-19 10:03:00 +01003275 def F(): string
3276 call_chain->add('A.F()')
3277 return this._G()
3278 enddef
3279 def _H(): string
3280 call_chain->add('A._H()')
3281 return this.F()
3282 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003283 endclass
3284
3285 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003286 def _G(): string
3287 call_chain->add('B.G()')
3288 return 'BBB'
3289 enddef
3290 def SF(): string
3291 call_chain->add('B.SF()')
3292 return super._H()
3293 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003294 endclass
3295
3296 class C extends B
3297 endclass
3298
3299 class D extends C
Ernie Raelbce60c42025-01-19 10:03:00 +01003300 def SF(): string
3301 call_chain->add('D.SF()')
3302 return super.SF()
3303 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003304 endclass
3305
3306 class E extends D
Ernie Raelbce60c42025-01-19 10:03:00 +01003307 def SF(): string
3308 call_chain->add('E.SF()')
3309 return super.SF()
3310 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003311 endclass
3312
3313 class F extends E
Ernie Raelbce60c42025-01-19 10:03:00 +01003314 def _G(): string
3315 call_chain->add('F._G()')
3316 return 'FFF'
3317 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003318 endclass
3319
3320 # E.new() -> A.F() -> B._G()
3321 call_chain = []
3322 var o1 = E.new()
3323 assert_equal('BBB', o1.F())
3324 assert_equal(['A.F()', 'B.G()'], call_chain)
3325
3326 # F.new() -> E.SF() -> D.SF() -> B.SF() -> A._H() -> A.F() -> F._G()
3327 call_chain = []
3328 var o2 = F.new()
3329 assert_equal('FFF', o2.SF())
3330 assert_equal(['E.SF()', 'D.SF()', 'B.SF()', 'A._H()', 'A.F()', 'F._G()'], call_chain)
3331 END
3332 v9.CheckSourceSuccess(lines)
Ernie Raelbce60c42025-01-19 10:03:00 +01003333
3334 # problems with method dispatch: super -> abstract
3335 # https://github.com/vim/vim/issues/15514
3336 lines =<< trim END
3337 vim9script
3338 abstract class B
3339 abstract def ToString(): string
3340 endclass
3341
3342 class C extends B
3343 def ToString(): string
3344 return super.ToString()
3345 enddef
3346 endclass
3347
3348 try
3349 defcompile C.ToString
3350 call assert_false(1, 'command should have failed')
3351 catch
3352 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3353 endtry
3354 END
3355 v9.CheckSourceSuccess(lines)
3356
3357 # problems with method dispatch: super -> abstract -> concrete
3358 lines =<< trim END
3359 vim9script
3360
3361 class A
3362 def ToString()
3363 echo 'A'
3364 enddef
3365 endclass
3366
3367 abstract class B extends A
3368 abstract def ToString()
3369 endclass
3370
3371 class C extends B
3372 def ToString()
3373 super.ToString()
3374 enddef
3375 endclass
3376
3377 try
3378 defcompile C.ToString
3379 call assert_false(1, 'command should have failed')
3380 catch
3381 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3382 endtry
3383 END
3384 v9.CheckSourceSuccess(lines)
3385
3386 # Invoking a super method and an interface method which have the same name.
3387 lines =<< trim END
3388 vim9script
3389
3390 interface I
3391 def ToString(): string
3392 endinterface
3393
3394 # Note that A does not implement I.
3395 class A
3396 def ToString(): string
3397 return 'A'
3398 enddef
3399 endclass
3400
3401 class B extends A implements I
3402 def ToString(): string
3403 return super.ToString()
3404 enddef
3405 endclass
3406
3407 def TestI(i: I): string
3408 return i.ToString()
3409 enddef
3410
3411 assert_equal('A', B.new().ToString())
3412 assert_equal('A', TestI(B.new()))
3413 END
3414 v9.CheckSourceSuccess(lines)
3415
3416 # super and an abstract class with no abstract methods
3417 lines =<< trim END
3418 vim9script
3419
3420 class A
3421 def ToString(): string
3422 return 'A'
3423 enddef
3424 endclass
3425
3426 # An abstract class with no abstract methods.
3427 abstract class B extends A
3428 endclass
3429
3430 class C extends B
3431 def ToString(): string
3432 return super.ToString()
3433 enddef
3434 endclass
3435
3436 def TestA(a: A): string
3437 return a.ToString()
3438 enddef
3439
3440 def TestB(b: B): string
3441 return b.ToString()
3442 enddef
3443
3444 assert_equal('A', C.new().ToString())
3445 assert_equal('A', TestA(A.new()))
3446 assert_equal('A', TestA(C.new()))
3447 assert_equal('A', TestB(C.new()))
3448 END
3449 v9.CheckSourceSuccess(lines)
3450
3451 # super and an abstract class with no abstract methods and the initial
3452 # implements clause
3453 lines =<< trim END
3454 vim9script
3455
3456 interface I
3457 def ToString(): string
3458 endinterface
3459
3460 # Note that A does not implement I.
3461 class A
3462 def ToString(): string
3463 return 'A'
3464 enddef
3465 endclass
3466
3467 # An abstract class with no abstract methods.
3468 abstract class B extends A implements I
3469 endclass
3470
3471 class C extends B implements I
3472 def ToString(): string
3473 return super.ToString()
3474 enddef
3475 endclass
3476
3477 # Note that A.ToString() is different from I.ToString().
3478 def TestA(a: A): string
3479 return a.ToString()
3480 enddef
3481
3482 assert_equal('A', C.new().ToString())
3483 assert_equal('A', TestA(A.new()))
3484 assert_equal('A', TestA(C.new()))
3485 END
3486 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan5ce1e4a2025-04-07 21:09:18 +02003487
3488 # Invoking a class method in the parent class using "super" should fail
3489 lines =<< trim END
3490 vim9script
3491
3492 class A
3493 static def Fn(): string
3494 return 'A'
3495 enddef
3496 endclass
3497
3498 class B extends A
3499 static def Fn(): string
3500 return super.Fn()
3501 enddef
3502 endclass
3503 defcompile
3504 END
3505 v9.CheckSourceFailure(lines, 'E1325: Method "Fn" not found in class "B"')
3506
3507 # Missing name after "super" keyword
3508 lines =<< trim END
3509 vim9script
3510 class A
3511 endclass
3512 class B extends A
3513 def Fn()
3514 var x = super.()
3515 enddef
3516 endclass
3517 defcompile
3518 END
3519 v9.CheckSourceFailure(lines, 'E1127: Missing name after dot', 1)
Ernie Rael58c95792024-08-13 23:27:22 +02003520enddef
3521
Bram Moolenaara86655a2023-01-12 17:06:27 +00003522def Test_class_import()
3523 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003524 vim9script
3525 export class Animal
Doug Kearns74da0ee2023-12-14 20:26:26 +01003526 var kind: string
3527 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003528 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003529 END
3530 writefile(lines, 'Xanimal.vim', 'D')
3531
3532 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003533 vim9script
3534 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003535
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003536 var a: animal.Animal
3537 a = animal.Animal.new('fish', 'Eric')
3538 assert_equal('fish', a.kind)
3539 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003540
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003541 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3542 assert_equal('cat', b.kind)
3543 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003544 END
3545 v9.CheckScriptSuccess(lines)
3546enddef
3547
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003548" Test for importing a class into a legacy script and calling the class method
3549def Test_class_method_from_legacy_script()
3550 var lines =<< trim END
3551 vim9script
3552 export class A
3553 static var name: string = 'a'
3554 static def SetName(n: string)
3555 name = n
3556 enddef
3557 endclass
3558 END
3559 writefile(lines, 'Xvim9export.vim', 'D')
3560
3561 lines =<< trim END
3562 import './Xvim9export.vim' as vim9
3563
3564 call s:vim9.A.SetName('b')
3565 call assert_equal('b', s:vim9.A.name)
3566 END
3567 v9.CheckScriptSuccess(lines)
3568enddef
3569
Yegappan Lakshmanand2e1c832023-12-14 19:59:45 +01003570" Test for implementing an imported interface
3571def Test_implement_imported_interface()
3572 var lines =<< trim END
3573 vim9script
3574 export interface Imp_Intf1
3575 def Fn1(): number
3576 endinterface
3577 export interface Imp_Intf2
3578 def Fn2(): number
3579 endinterface
3580 END
3581 writefile(lines, 'Ximportinterface.vim', 'D')
3582
3583 lines =<< trim END
3584 vim9script
3585 import './Ximportinterface.vim' as Xintf
3586
3587 class A implements Xintf.Imp_Intf1, Xintf.Imp_Intf2
3588 def Fn1(): number
3589 return 10
3590 enddef
3591 def Fn2(): number
3592 return 20
3593 enddef
3594 endclass
3595 var a = A.new()
3596 assert_equal(10, a.Fn1())
3597 assert_equal(20, a.Fn2())
3598 END
3599 v9.CheckScriptSuccess(lines)
3600enddef
3601
3602" Test for extending an imported class
3603def Test_extend_imported_class()
3604 var lines =<< trim END
3605 vim9script
3606 export class Imp_C1
3607 def Fn1(): number
3608 return 5
3609 enddef
3610 endclass
3611 END
3612 writefile(lines, 'Xextendimportclass.vim', 'D')
3613
3614 lines =<< trim END
3615 vim9script
3616 import './Xextendimportclass.vim' as XClass
3617
3618 class A extends XClass.Imp_C1
3619 endclass
3620 var a = A.new()
3621 assert_equal(5, a.Fn1())
3622 END
3623 v9.CheckScriptSuccess(lines)
3624enddef
3625
Christian Brabandtd9a1f262025-01-21 22:17:50 +01003626def Test_abstract_class()
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003627 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003628 vim9script
3629 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003630 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003631 endclass
3632 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003633 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003634 endclass
3635 var p: Base = Person.new('Peter', 42)
3636 assert_equal('Peter', p.name)
3637 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003638 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003639 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003640
3641 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003642 vim9script
3643 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003644 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003645 endclass
3646 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003647 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003648 endclass
3649 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003650 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003651 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003652
3653 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003654 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003655 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003656 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003657 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003658 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003659
h-eastaa979c72025-01-03 10:19:45 +01003660 # Test for "abstract" cannot be abbreviated
3661 lines =<< trim END
3662 vim9script
3663 abs class A
3664 endclass
3665 END
3666 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs class A', 2)
3667
Yegappan Lakshmananac773182024-04-27 11:36:12 +02003668 # Additional commands after "abstract class"
3669 lines =<< trim END
3670 vim9script
3671 abstract class Something | var x = []
3672 endclass
3673 END
3674 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = []", 2)
3675
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003676 # Abstract class cannot have a "new" function
3677 lines =<< trim END
3678 vim9script
3679 abstract class Base
3680 def new()
3681 enddef
3682 endclass
3683 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003684 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003685
3686 # extending an abstract class with class methods and variables
3687 lines =<< trim END
3688 vim9script
3689 abstract class A
3690 static var s: string = 'vim'
3691 static def Fn(): list<number>
3692 return [10]
3693 enddef
3694 endclass
3695 class B extends A
3696 endclass
3697 var b = B.new()
3698 assert_equal('vim', A.s)
3699 assert_equal([10], A.Fn())
3700 END
3701 v9.CheckScriptSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003702enddef
3703
Bram Moolenaar486fc252023-01-18 14:51:07 +00003704def Test_closure_in_class()
3705 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003706 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003707
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003708 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01003709 var y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003710
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003711 def new()
3712 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3713 enddef
3714 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003715
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003716 Foo.new()
3717 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003718 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003719 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003720enddef
3721
Ernie Rael9ed53752023-12-11 17:40:46 +01003722def Test_construct_object_from_legacy()
3723 # Cannot directly invoke constructor from legacy
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003724 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003725 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003726
Ernie Rael9ed53752023-12-11 17:40:46 +01003727 var newCalled = false
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003728
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003729 class A
Ernie Rael9ed53752023-12-11 17:40:46 +01003730 def new(arg: string)
3731 newCalled = true
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003732 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003733 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003734
Ernie Rael9ed53752023-12-11 17:40:46 +01003735 export def CreateA(...args: list<any>): A
3736 return call(A.new, args)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003737 enddef
3738
Ernie Rael9ed53752023-12-11 17:40:46 +01003739 g:P = CreateA
3740 legacy call g:P('some_arg')
3741 assert_equal(true, newCalled)
3742 unlet g:P
3743 END
3744 v9.CheckSourceSuccess(lines)
3745
3746 lines =<< trim END
3747 vim9script
3748
3749 var newCalled = false
3750
3751 class A
3752 static def CreateA(options = {}): any
3753 return A.new()
3754 enddef
3755 def new()
3756 newCalled = true
3757 enddef
3758 endclass
3759
3760 g:P = A.CreateA
3761 legacy call g:P()
3762 assert_equal(true, newCalled)
3763 unlet g:P
3764 END
3765 v9.CheckSourceSuccess(lines)
3766
3767 # This also tests invoking "new()" with "call"
3768 lines =<< trim END
3769 vim9script
3770
3771 var createdObject: any
3772
3773 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01003774 var val1: number
3775 var val2: number
Ernie Rael9ed53752023-12-11 17:40:46 +01003776 static def CreateA(...args: list<any>): any
3777 createdObject = call(A.new, args)
3778 return createdObject
3779 enddef
3780 endclass
3781
3782 g:P = A.CreateA
3783 legacy call g:P(3, 5)
3784 assert_equal(3, createdObject.val1)
3785 assert_equal(5, createdObject.val2)
3786 legacy call g:P()
3787 assert_equal(0, createdObject.val1)
3788 assert_equal(0, createdObject.val2)
3789 legacy call g:P(7)
3790 assert_equal(7, createdObject.val1)
3791 assert_equal(0, createdObject.val2)
3792 unlet g:P
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003793 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003794 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003795enddef
3796
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003797def Test_defer_with_object()
3798 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003799 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003800
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003801 class CWithEE
3802 def Enter()
3803 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003804 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003805 def Exit()
3806 g:result ..= "exited"
3807 enddef
3808 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003809
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003810 def With(ee: CWithEE, F: func)
3811 ee.Enter()
3812 defer ee.Exit()
3813 F()
3814 enddef
3815
3816 g:result = ''
3817 var obj = CWithEE.new()
3818 obj->With(() => {
3819 g:result ..= "called/"
3820 })
3821 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003822 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003823 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003824 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003825
3826 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003827 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003828
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003829 class BaseWithEE
3830 def Enter()
3831 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003832 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003833 def Exit()
3834 g:result ..= "exited-base"
3835 enddef
3836 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003837
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003838 class CWithEE extends BaseWithEE
3839 def Enter()
3840 g:result ..= "entered-child/"
3841 enddef
3842 def Exit()
3843 g:result ..= "exited-child"
3844 enddef
3845 endclass
3846
3847 def With(ee: BaseWithEE, F: func)
3848 ee.Enter()
3849 defer ee.Exit()
3850 F()
3851 enddef
3852
3853 g:result = ''
3854 var obj = CWithEE.new()
3855 obj->With(() => {
3856 g:result ..= "called/"
3857 })
3858 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003859 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003860 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003861 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003862enddef
3863
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003864" The following test used to crash Vim (Github issue #12676)
3865def Test_extends_method_crashes_vim()
3866 var lines =<< trim END
3867 vim9script
3868
3869 class Observer
3870 endclass
3871
3872 class Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003873 var value: any
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003874
3875 def Set(v: any)
3876 if v != this.value
3877 this.value = v
3878 endif
3879 enddef
3880
3881 def Register(observer: Observer)
3882 enddef
3883 endclass
3884
3885 class Bool extends Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003886 var value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003887 endclass
3888
3889 def Observe(obj: Property, who: Observer)
3890 obj.Register(who)
3891 enddef
3892
3893 var p = Bool.new(false)
3894 var myObserver = Observer.new()
3895
3896 Observe(p, myObserver)
3897
3898 p.Set(true)
3899 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003900 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003901enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003902
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003903" Test for calling a method in a class that is extended
3904def Test_call_method_in_extended_class()
3905 var lines =<< trim END
3906 vim9script
3907
3908 var prop_init_called = false
3909 var prop_register_called = false
3910
3911 class Property
3912 def Init()
3913 prop_init_called = true
3914 enddef
3915
3916 def Register()
3917 prop_register_called = true
3918 enddef
3919 endclass
3920
3921 class Bool extends Property
3922 endclass
3923
3924 def Observe(obj: Property)
3925 obj.Register()
3926 enddef
3927
3928 var p = Property.new()
3929 Observe(p)
3930
3931 p.Init()
3932 assert_true(prop_init_called)
3933 assert_true(prop_register_called)
3934 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003935 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003936enddef
3937
LemonBoyafe04662023-08-23 21:08:11 +02003938def Test_instanceof()
3939 var lines =<< trim END
3940 vim9script
3941
3942 class Base1
3943 endclass
3944
3945 class Base2 extends Base1
3946 endclass
3947
3948 interface Intf1
3949 endinterface
3950
3951 class Mix1 implements Intf1
3952 endclass
3953
3954 class Base3 extends Mix1
3955 endclass
3956
Ernie Rael2025af12023-12-12 16:58:00 +01003957 type AliasBase1 = Base1
3958 type AliasBase2 = Base2
3959 type AliasIntf1 = Intf1
3960 type AliasMix1 = Mix1
3961
LemonBoyafe04662023-08-23 21:08:11 +02003962 var b1 = Base1.new()
3963 var b2 = Base2.new()
3964 var b3 = Base3.new()
3965
3966 assert_true(instanceof(b1, Base1))
3967 assert_true(instanceof(b2, Base1))
3968 assert_false(instanceof(b1, Base2))
3969 assert_true(instanceof(b3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003970 assert_true(instanceof(b3, Base1, Base2, Intf1))
3971
3972 assert_true(instanceof(b1, AliasBase1))
3973 assert_true(instanceof(b2, AliasBase1))
3974 assert_false(instanceof(b1, AliasBase2))
3975 assert_true(instanceof(b3, AliasMix1))
3976 assert_true(instanceof(b3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003977
3978 def Foo()
3979 var a1 = Base1.new()
3980 var a2 = Base2.new()
3981 var a3 = Base3.new()
3982
3983 assert_true(instanceof(a1, Base1))
3984 assert_true(instanceof(a2, Base1))
3985 assert_false(instanceof(a1, Base2))
3986 assert_true(instanceof(a3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003987 assert_true(instanceof(a3, Base1, Base2, Intf1))
3988
3989 assert_true(instanceof(a1, AliasBase1))
3990 assert_true(instanceof(a2, AliasBase1))
3991 assert_false(instanceof(a1, AliasBase2))
3992 assert_true(instanceof(a3, AliasMix1))
3993 assert_true(instanceof(a3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003994 enddef
3995 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003996
3997 var o_null: Base1
3998 assert_false(instanceof(o_null, Base1))
3999
LemonBoyafe04662023-08-23 21:08:11 +02004000 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004001 v9.CheckSourceSuccess(lines)
Ernie Rael2025af12023-12-12 16:58:00 +01004002
4003 lines =<< trim END
4004 vim9script
4005
4006 class Base1
4007 endclass
4008 instanceof(Base1.new())
4009 END
4010 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
4011
4012 lines =<< trim END
4013 vim9script
4014
4015 class Base1
4016 endclass
4017 def F()
4018 instanceof(Base1.new())
4019 enddef
4020 F()
4021 END
4022 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
4023
4024 lines =<< trim END
4025 vim9script
4026
4027 class Base1
4028 endclass
4029
4030 class Base2
4031 endclass
4032
4033 var o = Base2.new()
4034 instanceof(o, Base1, Base2, 3)
4035 END
4036 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4', 10)
4037
4038 lines =<< trim END
4039 vim9script
4040
4041 class Base1
4042 endclass
4043
4044 class Base2
4045 endclass
4046
4047 def F()
4048 var o = Base2.new()
4049 instanceof(o, Base1, Base2, 3)
4050 enddef
4051 F()
4052 END
4053 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4')
LemonBoyafe04662023-08-23 21:08:11 +02004054enddef
4055
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004056" Test for calling a method in the parent class that is extended partially.
4057" This used to fail with the 'E118: Too many arguments for function: Text' error
4058" message (Github issue #12524).
4059def Test_call_method_in_parent_class()
4060 var lines =<< trim END
4061 vim9script
4062
4063 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01004064 var _lnum: number = 1
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004065
4066 def SetY(lnum: number)
4067 this._lnum = lnum
4068 enddef
4069
4070 def Text(): string
4071 return ''
4072 enddef
4073 endclass
4074
4075 class Foo extends Widget
4076 def Text(): string
4077 return '<Foo>'
4078 enddef
4079 endclass
4080
4081 def Stack(w1: Widget, w2: Widget): list<Widget>
4082 w1.SetY(1)
4083 w2.SetY(2)
4084 return [w1, w2]
4085 enddef
4086
4087 var foo1 = Foo.new()
4088 var foo2 = Foo.new()
4089 var l = Stack(foo1, foo2)
4090 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004091 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004092enddef
4093
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004094" Test for calling methods from three levels of classes
4095def Test_multi_level_method_call()
4096 var lines =<< trim END
4097 vim9script
4098
4099 var A_func1: number = 0
4100 var A_func2: number = 0
4101 var A_func3: number = 0
4102 var B_func2: number = 0
4103 var B_func3: number = 0
4104 var C_func3: number = 0
4105
4106 class A
4107 def Func1()
4108 A_func1 += 1
4109 enddef
4110
4111 def Func2()
4112 A_func2 += 1
4113 enddef
4114
4115 def Func3()
4116 A_func3 += 1
4117 enddef
4118 endclass
4119
4120 class B extends A
4121 def Func2()
4122 B_func2 += 1
4123 enddef
4124
4125 def Func3()
4126 B_func3 += 1
4127 enddef
4128 endclass
4129
4130 class C extends B
4131 def Func3()
4132 C_func3 += 1
4133 enddef
4134 endclass
4135
4136 def A_CallFuncs(a: A)
4137 a.Func1()
4138 a.Func2()
4139 a.Func3()
4140 enddef
4141
4142 def B_CallFuncs(b: B)
4143 b.Func1()
4144 b.Func2()
4145 b.Func3()
4146 enddef
4147
4148 def C_CallFuncs(c: C)
4149 c.Func1()
4150 c.Func2()
4151 c.Func3()
4152 enddef
4153
4154 var cobj = C.new()
4155 A_CallFuncs(cobj)
4156 B_CallFuncs(cobj)
4157 C_CallFuncs(cobj)
4158 assert_equal(3, A_func1)
4159 assert_equal(0, A_func2)
4160 assert_equal(0, A_func3)
4161 assert_equal(3, B_func2)
4162 assert_equal(0, B_func3)
4163 assert_equal(3, C_func3)
4164 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004165 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004166enddef
4167
4168" Test for using members from three levels of classes
4169def Test_multi_level_member_access()
4170 var lines =<< trim END
4171 vim9script
4172
4173 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004174 public var val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004175 endclass
4176
4177 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004178 public var val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004179 endclass
4180
4181 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01004182 public var val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004183 endclass
4184
4185 def A_members(a: A)
4186 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004187 enddef
4188
4189 def B_members(b: B)
4190 b.val1 += 1
4191 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004192 enddef
4193
4194 def C_members(c: C)
4195 c.val1 += 1
4196 c.val2 += 1
4197 c.val3 += 1
4198 enddef
4199
4200 var cobj = C.new()
4201 A_members(cobj)
4202 B_members(cobj)
4203 C_members(cobj)
4204 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004205 assert_equal(2, cobj.val2)
4206 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004207 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004208 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004209enddef
4210
LemonBoy0ffc17a2023-08-20 18:09:11 +02004211" Test expansion of <stack> with class methods.
4212def Test_stack_expansion_with_methods()
4213 var lines =<< trim END
4214 vim9script
4215
4216 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004217 def M1()
4218 F0()
4219 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02004220 endclass
4221
4222 def F0()
Ernie Rael16cdfa62024-04-02 19:05:39 +02004223 assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
LemonBoy0ffc17a2023-08-20 18:09:11 +02004224 enddef
4225
4226 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004227 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02004228 enddef
4229
4230 F()
4231 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004232 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02004233enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004234
4235" Test the return type of the new() constructor
4236def Test_new_return_type()
4237 # new() uses the default return type and there is no return statement
4238 var lines =<< trim END
4239 vim9script
4240
4241 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004242 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004243
4244 def new(this._bufnr)
4245 if !bufexists(this._bufnr)
4246 this._bufnr = -1
4247 endif
4248 enddef
4249 endclass
4250
4251 var c = C.new(12345)
4252 assert_equal('object<C>', typename(c))
4253
4254 var v1: C
4255 v1 = C.new(12345)
4256 assert_equal('object<C>', typename(v1))
4257
4258 def F()
4259 var v2: C
4260 v2 = C.new(12345)
4261 assert_equal('object<C>', typename(v2))
4262 enddef
4263 F()
4264 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004265 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004266
4267 # new() uses the default return type and an empty 'return' statement
4268 lines =<< trim END
4269 vim9script
4270
4271 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004272 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004273
4274 def new(this._bufnr)
4275 if !bufexists(this._bufnr)
4276 this._bufnr = -1
4277 return
4278 endif
4279 enddef
4280 endclass
4281
4282 var c = C.new(12345)
4283 assert_equal('object<C>', typename(c))
4284
4285 var v1: C
4286 v1 = C.new(12345)
4287 assert_equal('object<C>', typename(v1))
4288
4289 def F()
4290 var v2: C
4291 v2 = C.new(12345)
4292 assert_equal('object<C>', typename(v2))
4293 enddef
4294 F()
4295 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004296 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004297
4298 # new() uses "any" return type and returns "this"
4299 lines =<< trim END
4300 vim9script
4301
4302 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004303 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004304
4305 def new(this._bufnr): any
4306 if !bufexists(this._bufnr)
4307 this._bufnr = -1
4308 return this
4309 endif
4310 enddef
4311 endclass
4312 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004313 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004314
4315 # new() uses 'Dict' return type and returns a Dict
4316 lines =<< trim END
4317 vim9script
4318
4319 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004320 var _state: dict<any>
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004321
4322 def new(): dict<any>
4323 this._state = {}
4324 return this._state
4325 enddef
4326 endclass
4327
4328 var c = C.new()
4329 assert_equal('object<C>', typename(c))
4330 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004331 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004332enddef
4333
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004334" Test for checking a member initialization type at run time.
4335def Test_runtime_type_check_for_member_init()
4336 var lines =<< trim END
4337 vim9script
4338
4339 var retnum: bool = false
4340
4341 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004342 retnum = !retnum
4343 if retnum
4344 return 1
4345 else
4346 return "hello"
4347 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004348 enddef
4349
4350 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004351 var _foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004352 endclass
4353
4354 var c1 = C.new()
4355 var c2 = C.new()
4356 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004357 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004358enddef
4359
4360" Test for locking a variable referring to an object and reassigning to another
4361" object.
Ernie Raelee865f32023-09-29 19:53:55 +02004362def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004363 var lines =<< trim END
4364 vim9script
4365
4366 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004367 var val: number
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004368 def new(this.val)
4369 enddef
4370 endclass
4371
4372 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
4373 lockvar 2 some_dict
4374
4375 var current: C
4376 current = some_dict['c']
4377 assert_equal(3, current.val)
4378 current = some_dict['b']
4379 assert_equal(2, current.val)
4380
4381 def F()
4382 current = some_dict['c']
4383 enddef
4384
4385 def G()
4386 current = some_dict['b']
4387 enddef
4388
4389 F()
4390 assert_equal(3, current.val)
4391 G()
4392 assert_equal(2, current.val)
4393 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004394 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004395enddef
4396
Ernie Raelee865f32023-09-29 19:53:55 +02004397" Test trying to lock an object variable from various places
4398def Test_lockvar_object_variable()
4399 # An object variable lockvar has several cases:
4400 # object method, scriptlevel, scriplevel from :def, :def arg
4401 # method arg, static method arg.
4402 # Also different depths
4403
Ernie Raelee865f32023-09-29 19:53:55 +02004404 #
4405 # lockvar of read-only object variable
4406 #
4407
4408 # read-only lockvar from object method
4409 var lines =<< trim END
4410 vim9script
4411
4412 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004413 var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004414 def Lock()
4415 lockvar this.val1
4416 enddef
4417 endclass
4418 var o = C.new(3)
4419 o.Lock()
4420 END
Ernie Rael64885642023-10-04 20:16:22 +02004421 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004422
4423 # read-only lockvar from scriptlevel
4424 lines =<< trim END
4425 vim9script
4426
4427 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004428 var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004429 endclass
4430 var o = C.new(3)
4431 lockvar o.val2
4432 END
4433 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
4434
4435 # read-only lockvar of scriptlevel variable from def
4436 lines =<< trim END
4437 vim9script
4438
4439 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004440 var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004441 endclass
4442 var o = C.new(3)
4443 def Lock()
4444 lockvar o.val3
4445 enddef
4446 Lock()
4447 END
4448 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
4449
4450 # read-only lockvar of def argument variable
4451 lines =<< trim END
4452 vim9script
4453
4454 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004455 var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004456 endclass
4457 def Lock(o: C)
4458 lockvar o.val4
4459 enddef
4460 Lock(C.new(3))
4461 END
4462 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
4463
Ernie Raelee865f32023-09-29 19:53:55 +02004464 # read-only lockvar from object method arg
4465 lines =<< trim END
4466 vim9script
4467
4468 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004469 var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004470 def Lock(c: C)
4471 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004472 enddef
4473 endclass
4474 var o = C.new(3)
4475 o.Lock(C.new(5))
4476 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004477 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004478
4479 # read-only lockvar from class method arg
4480 lines =<< trim END
4481 vim9script
4482
4483 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004484 var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004485 static def Lock(c: C)
4486 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004487 enddef
4488 endclass
4489 var o = C.new(3)
4490 C.Lock(o)
4491 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004492 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004493
4494 #
4495 # lockvar of public object variable
4496 #
4497
4498 # lockvar from object method
4499 lines =<< trim END
4500 vim9script
4501
4502 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004503 public var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004504 def Lock()
4505 lockvar this.val1
4506 enddef
4507 endclass
4508 var o = C.new(3)
4509 o.Lock()
4510 END
4511 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
4512
4513 # lockvar from scriptlevel
4514 lines =<< trim END
4515 vim9script
4516
4517 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004518 public var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004519 endclass
4520 var o = C.new(3)
4521 lockvar o.val2
4522 END
4523 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
4524
4525 # lockvar of scriptlevel variable from def
4526 lines =<< trim END
4527 vim9script
4528
4529 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004530 public var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004531 endclass
4532 var o = C.new(3)
4533 def Lock()
4534 lockvar o.val3
4535 enddef
4536 Lock()
4537 END
4538 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
4539
4540 # lockvar of def argument variable
4541 lines =<< trim END
4542 vim9script
4543
4544 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004545 public var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004546 endclass
4547 def Lock(o: C)
4548 lockvar o.val4
4549 enddef
4550 Lock(C.new(3))
4551 END
4552 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
4553
4554 # lockvar from object method arg
4555 lines =<< trim END
4556 vim9script
4557
4558 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004559 public var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004560 def Lock(c: C)
4561 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004562 enddef
4563 endclass
4564 var o = C.new(3)
4565 o.Lock(C.new(5))
4566 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004567 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004568
4569 # lockvar from class method arg
4570 lines =<< trim END
4571 vim9script
4572
4573 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004574 public var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004575 static def Lock(c: C)
4576 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004577 enddef
4578 endclass
4579 var o = C.new(3)
4580 C.Lock(o)
4581 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004582 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004583enddef
4584
4585" Test trying to lock a class variable from various places
4586def Test_lockvar_class_variable()
4587
4588 # lockvar bare static from object method
4589 var lines =<< trim END
4590 vim9script
4591
4592 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004593 public static var sval1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004594 def Lock()
4595 lockvar sval1
4596 enddef
4597 endclass
4598 var o = C.new()
4599 o.Lock()
4600 END
4601 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
4602
4603 # lockvar C.static from object method
4604 lines =<< trim END
4605 vim9script
4606
4607 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004608 public static var sval2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004609 def Lock()
4610 lockvar C.sval2
4611 enddef
4612 endclass
4613 var o = C.new()
4614 o.Lock()
4615 END
4616 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
4617
4618 # lockvar bare static from class method
4619 lines =<< trim END
4620 vim9script
4621
4622 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004623 public static var sval3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004624 static def Lock()
4625 lockvar sval3
4626 enddef
4627 endclass
4628 C.Lock()
4629 END
4630 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
4631
4632 # lockvar C.static from class method
4633 lines =<< trim END
4634 vim9script
4635
4636 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004637 public static var sval4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004638 static def Lock()
4639 lockvar C.sval4
4640 enddef
4641 endclass
4642 C.Lock()
4643 END
4644 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
4645
4646 # lockvar C.static from script level
4647 lines =<< trim END
4648 vim9script
4649
4650 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004651 public static var sval5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004652 endclass
4653 lockvar C.sval5
4654 END
4655 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
4656
4657 # lockvar o.static from script level
4658 lines =<< trim END
4659 vim9script
4660
4661 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004662 public static var sval6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004663 endclass
4664 var o = C.new()
4665 lockvar o.sval6
4666 END
4667 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
4668enddef
4669
4670" Test locking an argument to :def
4671def Test_lockvar_argument()
4672 # Lockvar a function arg
4673 var lines =<< trim END
4674 vim9script
4675
4676 def Lock(val: any)
4677 lockvar val
4678 enddef
4679
4680 var d = {a: 1, b: 2}
4681 Lock(d)
4682
4683 d->extend({c: 3})
4684 END
4685 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
4686
4687 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
4688 # class member in "C". This tests lval_root_is_arg.
4689 lines =<< trim END
4690 vim9script
4691
4692 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004693 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004694 endclass
4695
4696 def Lock2(sval: any)
4697 lockvar sval
4698 enddef
4699
4700 var o = C.new()
4701 Lock2(o)
4702 END
4703 v9.CheckSourceSuccess(lines)
4704
4705 # Lock a class.
4706 lines =<< trim END
4707 vim9script
4708
4709 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004710 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004711 endclass
4712
4713 def Lock2(sval: any)
4714 lockvar sval
4715 enddef
4716
4717 Lock2(C)
4718 END
Ernie Raelb077b582023-12-14 20:11:44 +01004719 v9.CheckSourceFailure(lines, 'E1405: Class "C" cannot be used as a value')
Ernie Raelee865f32023-09-29 19:53:55 +02004720
4721 # Lock an object.
4722 lines =<< trim END
4723 vim9script
4724
4725 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004726 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004727 endclass
4728
4729 def Lock2(sval: any)
4730 lockvar sval
4731 enddef
4732
4733 Lock2(C.new())
4734 END
4735 v9.CheckSourceSuccess(lines)
4736
4737 # In this case (unlike previous) "lockvar sval" is a class member.
4738 lines =<< trim END
4739 vim9script
4740
4741 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004742 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004743 def Lock2()
4744 lockvar sval
4745 enddef
4746 endclass
4747
4748
4749 var o = C.new()
4750 o.Lock2()
4751 END
4752 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4753enddef
4754
4755" Test that this can be locked without error
4756def Test_lockvar_this()
4757 # lockvar this
4758 var lines =<< trim END
4759 vim9script
4760 class C
4761 def TLock()
4762 lockvar this
4763 enddef
4764 endclass
4765 var o = C.new()
4766 o.TLock()
4767 END
4768 v9.CheckSourceSuccess(lines)
4769
4770 # lockvar four (four letter word, but not this)
4771 lines =<< trim END
4772 vim9script
4773 class C
4774 def TLock4()
4775 var four: number
4776 lockvar four
4777 enddef
4778 endclass
4779 var o = C.new()
4780 o.TLock4()
4781 END
4782 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4783
4784 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4785 lines =<< trim END
4786 vim9script
4787 class C
4788 def TLock5()
4789 var this5: number
4790 lockvar this5
4791 enddef
4792 endclass
4793 var o = C.new()
4794 o.TLock5()
4795 END
4796 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4797enddef
4798
4799" Test some general lockvar cases
4800def Test_lockvar_general()
4801 # lockvar an object and a class. It does nothing
4802 var lines =<< trim END
4803 vim9script
4804 class C
4805 endclass
4806 var o = C.new()
4807 lockvar o
4808 lockvar C
4809 END
4810 v9.CheckSourceSuccess(lines)
4811
4812 # Lock a list element that's nested in an object variable from a :def
4813 lines =<< trim END
4814 vim9script
4815
4816 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004817 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004818 endclass
4819 def Lock2(obj: any)
4820 lockvar obj.val[1]
4821 enddef
4822
4823 var o = C.new()
4824 Lock2(o)
4825 o.val[0] = [9]
4826 assert_equal([ [9], [2], [3] ], o.val)
4827 try
4828 o.val[1] = [999]
4829 call assert_false(true, 'assign should have failed')
4830 catch
4831 assert_exception('E741:')
4832 endtry
4833 o.val[2] = [8]
4834 assert_equal([ [9], [2], [8] ], o.val)
4835 END
4836 v9.CheckSourceSuccess(lines)
4837
4838 # Lock a list element that's nested in an object variable from scriptlevel
4839 lines =<< trim END
4840 vim9script
4841
4842 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004843 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004844 endclass
4845
4846 var o = C.new()
4847 lockvar o.val[1]
4848 o.val[0] = [9]
4849 assert_equal([ [9], [2], [3] ], o.val)
4850 try
4851 o.val[1] = [999]
4852 call assert_false(true, 'assign should have failed')
4853 catch
4854 assert_exception('E741:')
4855 endtry
4856 o.val[2] = [8]
4857 assert_equal([ [9], [2], [8] ], o.val)
4858 END
4859 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004860
4861 # lock a script level variable from an object method
4862 lines =<< trim END
4863 vim9script
4864
4865 class C
4866 def Lock()
4867 lockvar l
4868 enddef
4869 endclass
4870
4871 var l = [1]
4872 C.new().Lock()
4873 l[0] = 11
4874 END
4875 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4876
Ernie Rael03042a22023-11-11 08:53:32 +01004877 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004878 # in an object fetched via a script level list
4879 lines =<< trim END
4880 vim9script
4881
4882 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004883 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004884 def Lock()
4885 lockvar lc[0]._v1[1]
4886 enddef
4887 endclass
4888
4889 var l = [[1], [2], [3]]
4890 var o = C.new(l)
4891 var lc: list<C> = [ o ]
4892
4893 o.Lock()
4894 l[0] = [22]
4895 l[1] = [33]
4896 END
4897 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4898
4899 # similar to the previous test, except the locking code is executing
Ernie Rael03042a22023-11-11 08:53:32 +01004900 # in a class that does not own the protected variable.
4901 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02004902 # the same name.
4903 lines =<< trim END
4904 vim9script
4905
4906 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004907 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004908 def Lock(obj: any)
4909 lockvar lc[0]._v1[1]
4910 enddef
4911 endclass
4912
4913 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004914 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004915 endclass
4916
4917 var l = [[1], [2], [3]]
4918 var o = C.new(l)
4919 var lc: list<C> = [ o ]
4920
4921 var o2 = C2.new()
4922 o2.Lock(o)
4923 END
Ernie Rael03042a22023-11-11 08:53:32 +01004924 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004925enddef
4926
Ernie Rael9771b2a2023-10-07 22:05:40 +02004927" Test builtin islocked()
4928def Test_lockvar_islocked()
4929 # Can't lock class/object variable
4930 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01004931 # Lock item of variable's value (a list item)
4932 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02004933 var lines =<< trim END
4934 vim9script
4935
4936 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004937 var o0: list<list<number>> = [ [0], [1], [2]]
4938 var o1: list<list<number>> = [[10], [11], [12]]
4939 static var c0: list<list<number>> = [[20], [21], [22]]
4940 static var c1: list<list<number>> = [[30], [31], [32]]
Ernie Rael9771b2a2023-10-07 22:05:40 +02004941 endclass
4942
4943 def LockIt(arg: any)
4944 lockvar arg
4945 enddef
4946
4947 def UnlockIt(arg: any)
4948 unlockvar arg
4949 enddef
4950
4951 var obj = C.new()
4952 #lockvar obj.o1 # can't lock something you can't write to
4953
4954 try
4955 lockvar obj.o1 # can't lock something you can't write to
4956 call assert_false(1, '"lockvar obj.o1" should have failed')
4957 catch
4958 call assert_exception('E1335:')
4959 endtry
4960
4961 LockIt(obj.o1) # but can lock it's value
4962 assert_equal(1, islocked("obj.o1"))
4963 assert_equal(1, islocked("obj.o1[0]"))
4964 assert_equal(1, islocked("obj.o1[1]"))
4965 UnlockIt(obj.o1)
4966 assert_equal(0, islocked("obj.o1"))
4967 assert_equal(0, islocked("obj.o1[0]"))
4968
4969 lockvar obj.o1[0]
4970 assert_equal(0, islocked("obj.o1"))
4971 assert_equal(1, islocked("obj.o1[0]"))
4972 assert_equal(0, islocked("obj.o1[1]"))
4973 unlockvar obj.o1[0]
4974 assert_equal(0, islocked("obj.o1"))
4975 assert_equal(0, islocked("obj.o1[0]"))
4976
4977 # Same thing, but with a static
4978
4979 try
4980 lockvar C.c1 # can't lock something you can't write to
4981 call assert_false(1, '"lockvar C.c1" should have failed')
4982 catch
4983 call assert_exception('E1335:')
4984 endtry
4985
4986 LockIt(C.c1) # but can lock it's value
4987 assert_equal(1, islocked("C.c1"))
4988 assert_equal(1, islocked("C.c1[0]"))
4989 assert_equal(1, islocked("C.c1[1]"))
4990 UnlockIt(C.c1)
4991 assert_equal(0, islocked("C.c1"))
4992 assert_equal(0, islocked("C.c1[0]"))
4993
4994 lockvar C.c1[0]
4995 assert_equal(0, islocked("C.c1"))
4996 assert_equal(1, islocked("C.c1[0]"))
4997 assert_equal(0, islocked("C.c1[1]"))
4998 unlockvar C.c1[0]
4999 assert_equal(0, islocked("C.c1"))
5000 assert_equal(0, islocked("C.c1[0]"))
5001 END
5002 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02005003
5004 # Do islocked() from an object method
5005 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02005006 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02005007 vim9script
5008
5009 var l0o0 = [ [0], [1], [2]]
5010 var l0o1 = [ [10], [11], [12]]
5011 var l0c0 = [[120], [121], [122]]
5012 var l0c1 = [[130], [131], [132]]
5013
5014 class C0
Doug Kearns74da0ee2023-12-14 20:26:26 +01005015 var o0: list<list<number>> = l0o0
5016 var o1: list<list<number>> = l0o1
5017 static var c0: list<list<number>> = l0c0
5018 static var c1: list<list<number>> = l0c1
Ernie Rael4c8da022023-10-11 21:35:11 +02005019 def Islocked(arg: string): number
5020 return islocked(arg)
5021 enddef
5022 static def SIslocked(arg: string): number
5023 return islocked(arg)
5024 enddef
5025 endclass
5026
5027 var l2o0 = [[20000], [20001], [20002]]
5028 var l2o1 = [[20010], [20011], [20012]]
5029 var l2c0 = [[20120], [20121], [20122]]
5030 var l2c1 = [[20130], [20131], [20132]]
5031
5032 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01005033 var o0: list<list<number>> = l2o0
5034 var o1: list<list<number>> = l2o1
5035 static var c0: list<list<number>> = l2c0
5036 static var c1: list<list<number>> = l2c1
Ernie Rael4c8da022023-10-11 21:35:11 +02005037 def Islocked(arg: string): number
5038 return islocked(arg)
5039 enddef
5040 static def SIslocked(arg: string): number
5041 return islocked(arg)
5042 enddef
5043 endclass
5044
5045 var obj0 = C0.new()
5046 var obj2 = C2.new()
5047
5048 var l = [ obj0, null_object, obj2 ]
5049
5050 # lock list, object func access through script var expr
5051 assert_equal(0, obj0.Islocked("l[0].o0"))
5052 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
5053 lockvar l0o0
5054 assert_equal(1, obj0.Islocked("l[0].o0"))
5055 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
5056
5057 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
5058
5059 # lock list element, object func access through script var expr
5060 lockvar l0o1[1]
5061 assert_equal(0, obj0.Islocked("this.o1[0]"))
5062 assert_equal(1, obj0.Islocked("this.o1[1]"))
5063
5064 assert_equal(0, obj0.Islocked("this.o1"))
5065 lockvar l0o1
5066 assert_equal(1, obj0.Islocked("this.o1"))
5067 unlockvar l0o1
5068
5069 lockvar l0c1[1]
5070
5071 # static by class name member expr from same class
5072 assert_equal(0, obj0.Islocked("C0.c1[0]"))
5073 assert_equal(1, obj0.Islocked("C0.c1[1]"))
5074 # static by bare name member expr from same class
5075 assert_equal(0, obj0.Islocked("c1[0]"))
5076 assert_equal(1, obj0.Islocked("c1[1]"))
5077
5078 # static by class name member expr from other class
5079 assert_equal(0, obj2.Islocked("C0.c1[0]"))
5080 assert_equal(1, obj2.Islocked("C0.c1[1]"))
5081 # static by bare name member expr from other class
5082 assert_equal(0, obj2.Islocked("c1[0]"))
5083 assert_equal(0, obj2.Islocked("c1[1]"))
5084
5085
5086 # static by bare name in same class
5087 assert_equal(0, obj0.Islocked("c0"))
5088 lockvar l0c0
5089 assert_equal(1, obj0.Islocked("c0"))
5090
5091 #
5092 # similar stuff, but use static method
5093 #
5094
5095 unlockvar l0o0
5096
5097 # lock list, object func access through script var expr
5098 assert_equal(0, C0.SIslocked("l[0].o0"))
5099 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
5100 lockvar l0o0
5101 assert_equal(1, C0.SIslocked("l[0].o0"))
5102 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
5103
5104 unlockvar l0o1
5105
5106 # can't access "this" from class method
5107 try
5108 C0.SIslocked("this.o1[0]")
5109 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
5110 catch
5111 call assert_exception('E121: Undefined variable: this')
5112 endtry
5113
5114 lockvar l0c1[1]
5115
5116 # static by class name member expr from same class
5117 assert_equal(0, C0.SIslocked("C0.c1[0]"))
5118 assert_equal(1, C0.SIslocked("C0.c1[1]"))
5119 # static by bare name member expr from same class
5120 assert_equal(0, C0.SIslocked("c1[0]"))
5121 assert_equal(1, C0.SIslocked("c1[1]"))
5122
5123 # static by class name member expr from other class
5124 assert_equal(0, C2.SIslocked("C0.c1[0]"))
5125 assert_equal(1, C2.SIslocked("C0.c1[1]"))
5126 # static by bare name member expr from other class
5127 assert_equal(0, C2.SIslocked("c1[0]"))
5128 assert_equal(0, C2.SIslocked("c1[1]"))
5129
5130
5131 # static by bare name in same class
5132 unlockvar l0c0
5133 assert_equal(0, C0.SIslocked("c0"))
5134 lockvar l0c0
5135 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02005136 END
Ernie Rael4c8da022023-10-11 21:35:11 +02005137 v9.CheckSourceSuccess(lines)
5138
5139 # Check islocked class/object from various places.
5140 lines =<< trim END
5141 vim9script
5142
5143 class C
5144 def Islocked(arg: string): number
5145 return islocked(arg)
5146 enddef
5147 static def SIslocked(arg: string): number
5148 return islocked(arg)
5149 enddef
5150 endclass
5151 var obj = C.new()
5152
5153 # object method
5154 assert_equal(0, obj.Islocked("this"))
5155 assert_equal(0, obj.Islocked("C"))
5156
5157 # class method
5158 ### assert_equal(0, C.SIslocked("this"))
5159 assert_equal(0, C.SIslocked("C"))
5160
5161 #script level
5162 var v: number
5163 v = islocked("C")
5164 assert_equal(0, v)
5165 v = islocked("obj")
5166 assert_equal(0, v)
5167 END
5168 v9.CheckSourceSuccess(lines)
5169enddef
5170
5171def Test_lockvar_islocked_notfound()
5172 # Try non-existent things
5173 var lines =<< trim END
5174 vim9script
5175
5176 class C
5177 def Islocked(arg: string): number
5178 return islocked(arg)
5179 enddef
5180 static def SIslocked(arg: string): number
5181 return islocked(arg)
5182 enddef
5183 endclass
5184 var obj = C.new()
5185 assert_equal(-1, obj.Islocked("anywhere"))
5186 assert_equal(-1, C.SIslocked("notanywhere"))
5187 END
5188 v9.CheckSourceSuccess(lines)
5189
5190 # Something not found of the form "name1.name2" is an error
5191 lines =<< trim END
5192 vim9script
5193
5194 islocked("one.two")
5195 END
5196 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
5197
5198 lines =<< trim END
5199 vim9script
5200
5201 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005202 var val = { key: "value" }
Ernie Rael4c8da022023-10-11 21:35:11 +02005203 def Islocked(arg: string): number
5204 return islocked(arg)
5205 enddef
5206 endclass
5207 var obj = C.new()
5208 obj.Islocked("this.val.not_there"))
5209 END
5210 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
5211
5212 lines =<< trim END
5213 vim9script
5214
5215 class C
5216 def Islocked(arg: string): number
5217 return islocked(arg)
5218 enddef
5219 endclass
5220 var obj = C.new()
5221 obj.Islocked("this.notobjmember")
5222 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005223 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02005224
5225 # access a script variable through methods
5226 lines =<< trim END
5227 vim9script
5228
5229 var l = [1]
5230 class C
5231 def Islocked(arg: string): number
5232 return islocked(arg)
5233 enddef
5234 static def SIslocked(arg: string): number
5235 return islocked(arg)
5236 enddef
5237 endclass
5238 var obj = C.new()
5239 assert_equal(0, obj.Islocked("l"))
5240 assert_equal(0, C.SIslocked("l"))
5241 lockvar l
5242 assert_equal(1, obj.Islocked("l"))
5243 assert_equal(1, C.SIslocked("l"))
5244 END
5245 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02005246enddef
5247
Ernie Rael03042a22023-11-11 08:53:32 +01005248" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005249def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005250 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005251 var lines =<< trim END
5252 vim9script
5253
5254 class A
5255 def _Foo(): number
5256 return 1234
5257 enddef
5258 endclass
5259 var a = A.new()
5260 a._Foo()
5261 END
Ernie Rael03042a22023-11-11 08:53:32 +01005262 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005263
Ernie Rael03042a22023-11-11 08:53:32 +01005264 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005265 lines =<< trim END
5266 vim9script
5267
5268 class A
5269 def _Foo(): number
5270 return 1234
5271 enddef
5272 endclass
5273 def T()
5274 var a = A.new()
5275 a._Foo()
5276 enddef
5277 T()
5278 END
Ernie Rael03042a22023-11-11 08:53:32 +01005279 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005280
Ernie Rael03042a22023-11-11 08:53:32 +01005281 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005282 lines =<< trim END
5283 vim9script
5284
5285 class A
5286 def _Foo(): number
5287 return 1234
5288 enddef
5289 def Bar(): number
5290 return this._Foo()
5291 enddef
5292 endclass
5293 var a = A.new()
5294 assert_equal(1234, a.Bar())
5295 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005296 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005297
Ernie Rael03042a22023-11-11 08:53:32 +01005298 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005299 lines =<< trim END
5300 vim9script
5301
5302 class A
5303 def _Foo(): number
5304 return 1234
5305 enddef
5306 def Bar(): number
5307 return this._Foo()
5308 enddef
5309 endclass
5310 def T()
5311 var a = A.new()
5312 assert_equal(1234, a.Bar())
5313 enddef
5314 T()
5315 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005316 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005317
Ernie Rael03042a22023-11-11 08:53:32 +01005318 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005319 lines =<< trim END
5320 vim9script
5321
5322 class A
5323 def _Foo(): number
5324 return 1234
5325 enddef
5326 def Bar(): number
5327 return _Foo()
5328 enddef
5329 endclass
5330 var a = A.new()
5331 a.Bar()
5332 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005333 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005334
Ernie Rael03042a22023-11-11 08:53:32 +01005335 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005336 lines =<< trim END
5337 vim9script
5338
5339 class A
5340 def _Foo(): number
5341 return 1234
5342 enddef
5343 endclass
5344 A._Foo()
5345 END
Ernie Rael03042a22023-11-11 08:53:32 +01005346 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005347
Ernie Rael03042a22023-11-11 08:53:32 +01005348 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005349 lines =<< trim END
5350 vim9script
5351
5352 class A
5353 def _Foo()
5354 enddef
5355 def _Foo()
5356 enddef
5357 endclass
5358 var a = A.new()
5359 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005360 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005361
Ernie Rael03042a22023-11-11 08:53:32 +01005362 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005363 lines =<< trim END
5364 vim9script
5365
5366 class A
5367 def _Foo()
5368 enddef
5369 def Foo()
5370 enddef
5371 endclass
5372 var a = A.new()
5373 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005374 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005375
Ernie Rael03042a22023-11-11 08:53:32 +01005376 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005377 lines =<< trim END
5378 vim9script
5379
5380 class A
5381 def Foo()
5382 enddef
5383 def _Foo()
5384 enddef
5385 endclass
5386 var a = A.new()
5387 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005388 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005389
Ernie Rael03042a22023-11-11 08:53:32 +01005390 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005391 lines =<< trim END
5392 vim9script
5393
5394 class A
5395 def Foo(): number
5396 return 100
5397 enddef
5398 def _Bar(): number
5399 return 200
5400 enddef
5401 def _Baz()
5402 assert_equal(100, this.Foo())
5403 assert_equal(200, this._Bar())
5404 enddef
5405 def T()
5406 this._Baz()
5407 enddef
5408 endclass
5409 var a = A.new()
5410 a.T()
5411 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005412 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005413
Ernie Rael03042a22023-11-11 08:53:32 +01005414 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005415 lines =<< trim END
5416 vim9script
5417
5418 class A
5419 def _Foo(): number
5420 return 100
5421 enddef
5422 endclass
5423 class B
5424 def Foo(): number
5425 var a = A.new()
5426 a._Foo()
5427 enddef
5428 endclass
5429 var b = B.new()
5430 b.Foo()
5431 END
Ernie Rael03042a22023-11-11 08:53:32 +01005432 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005433
Ernie Rael03042a22023-11-11 08:53:32 +01005434 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005435 lines =<< trim END
5436 vim9script
5437 class A
5438 def _Foo(): number
5439 return 1234
5440 enddef
5441 endclass
5442 class B extends A
5443 def Bar()
5444 enddef
5445 endclass
5446 class C extends B
5447 def Baz(): number
5448 return this._Foo()
5449 enddef
5450 endclass
5451 var c = C.new()
5452 assert_equal(1234, c.Baz())
5453 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005454 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005455
Ernie Rael03042a22023-11-11 08:53:32 +01005456 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005457 lines =<< trim END
5458 vim9script
5459 class A
5460 def _Foo(): number
5461 return 1234
5462 enddef
5463 endclass
5464 class B extends A
5465 def Bar()
5466 enddef
5467 endclass
5468 class C extends B
5469 def Baz(): number
5470 enddef
5471 endclass
5472 var c = C.new()
5473 assert_equal(1234, c._Foo())
5474 END
Ernie Rael03042a22023-11-11 08:53:32 +01005475 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005476
5477 # Using "_" prefix in a method name should fail outside of a class
5478 lines =<< trim END
5479 vim9script
5480 def _Foo(): number
5481 return 1234
5482 enddef
5483 var a = _Foo()
5484 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005485 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005486enddef
5487
Ernie Rael03042a22023-11-11 08:53:32 +01005488" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005489def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005490 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005491 var lines =<< trim END
5492 vim9script
5493
5494 class A
5495 static def _Foo(): number
5496 return 1234
5497 enddef
5498 endclass
5499 A._Foo()
5500 END
Ernie Rael03042a22023-11-11 08:53:32 +01005501 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005502
Ernie Rael03042a22023-11-11 08:53:32 +01005503 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005504 lines =<< trim END
5505 vim9script
5506
5507 class A
5508 static def _Foo(): number
5509 return 1234
5510 enddef
5511 endclass
5512 def T()
5513 A._Foo()
5514 enddef
5515 T()
5516 END
Ernie Rael03042a22023-11-11 08:53:32 +01005517 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005518
Ernie Rael03042a22023-11-11 08:53:32 +01005519 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005520 lines =<< trim END
5521 vim9script
5522
5523 class A
5524 static def _Foo(): number
5525 return 1234
5526 enddef
5527 endclass
5528 var a = A.new()
5529 a._Foo()
5530 END
Ernie Rael03042a22023-11-11 08:53:32 +01005531 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005532
Ernie Rael03042a22023-11-11 08:53:32 +01005533 # Try calling a class protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005534 lines =<< trim END
5535 vim9script
5536
5537 class A
5538 static def _Foo(): number
5539 return 1234
5540 enddef
5541 endclass
5542 def T()
5543 var a = A.new()
5544 a._Foo()
5545 enddef
5546 T()
5547 END
Ernie Rael03042a22023-11-11 08:53:32 +01005548 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005549
Ernie Rael03042a22023-11-11 08:53:32 +01005550 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005551 lines =<< trim END
5552 vim9script
5553
5554 class A
5555 static def _Foo(): number
5556 return 1234
5557 enddef
5558 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005559 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005560 enddef
5561 endclass
5562 var a = A.new()
5563 a.Bar()
5564 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005565 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005566
Ernie Rael03042a22023-11-11 08:53:32 +01005567 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005568 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005569 lines =<< trim END
5570 vim9script
5571
5572 class A
5573 static def _Foo1(): number
5574 return 1234
5575 enddef
5576 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005577 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005578 enddef
5579 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005580 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005581 enddef
5582 endclass
5583 var a = A.new()
5584 a.Bar()
5585 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005586 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005587
Ernie Rael03042a22023-11-11 08:53:32 +01005588 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005589 lines =<< trim END
5590 vim9script
5591
5592 class A
5593 static def _Foo()
5594 enddef
5595 static def Foo()
5596 enddef
5597 endclass
5598 var a = A.new()
5599 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005600 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005601
Ernie Rael03042a22023-11-11 08:53:32 +01005602 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005603 lines =<< trim END
5604 vim9script
5605
5606 class A
5607 static def _Foo(): number
5608 return 1234
5609 enddef
5610 endclass
5611 class B
5612 def Foo(): number
5613 return A._Foo()
5614 enddef
5615 endclass
5616 var b = B.new()
5617 assert_equal(1234, b.Foo())
5618 END
Ernie Rael03042a22023-11-11 08:53:32 +01005619 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005620
Ernie Rael03042a22023-11-11 08:53:32 +01005621 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005622 lines =<< trim END
5623 vim9script
5624 class A
5625 static def _Foo(): number
5626 return 1234
5627 enddef
5628 endclass
5629 class B extends A
5630 def Bar()
5631 enddef
5632 endclass
5633 class C extends B
5634 def Baz(): number
5635 return A._Foo()
5636 enddef
5637 endclass
5638 var c = C.new()
5639 assert_equal(1234, c.Baz())
5640 END
Ernie Rael03042a22023-11-11 08:53:32 +01005641 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005642
Ernie Rael03042a22023-11-11 08:53:32 +01005643 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005644 lines =<< trim END
5645 vim9script
5646 class A
5647 static def _Foo(): number
5648 return 1234
5649 enddef
5650 endclass
5651 class B extends A
5652 def Bar()
5653 enddef
5654 endclass
5655 class C extends B
5656 static def Baz(): number
5657 return A._Foo()
5658 enddef
5659 endclass
5660 assert_equal(1234, C.Baz())
5661 END
Ernie Rael03042a22023-11-11 08:53:32 +01005662 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005663
Ernie Rael03042a22023-11-11 08:53:32 +01005664 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005665 lines =<< trim END
5666 vim9script
5667 class A
5668 static def _Foo(): number
5669 return 1234
5670 enddef
5671 endclass
5672 class B extends A
5673 def Bar()
5674 enddef
5675 endclass
5676 class C extends B
5677 def Baz(): number
5678 enddef
5679 endclass
5680 var c = C.new()
5681 assert_equal(1234, C._Foo())
5682 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005683 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005684enddef
5685
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005686" Test for using the return value of a class/object method as a function
5687" argument.
5688def Test_objmethod_funcarg()
5689 var lines =<< trim END
5690 vim9script
5691
5692 class C
5693 def Foo(): string
5694 return 'foo'
5695 enddef
5696 endclass
5697
5698 def Bar(a: number, s: string): string
5699 return s
5700 enddef
5701
5702 def Baz(c: C)
5703 assert_equal('foo', Bar(10, c.Foo()))
5704 enddef
5705
5706 var t = C.new()
5707 Baz(t)
5708 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005709 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005710
5711 lines =<< trim END
5712 vim9script
5713
5714 class C
5715 static def Foo(): string
5716 return 'foo'
5717 enddef
5718 endclass
5719
5720 def Bar(a: number, s: string): string
5721 return s
5722 enddef
5723
5724 def Baz()
5725 assert_equal('foo', Bar(10, C.Foo()))
5726 enddef
5727
5728 Baz()
5729 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005730 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005731enddef
5732
Ernie Raelcf138d42023-09-06 20:45:03 +02005733def Test_static_inheritence()
5734 # subclasses get their own static copy
5735 var lines =<< trim END
5736 vim9script
5737
5738 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005739 static var _svar: number
5740 var _mvar: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005741 def new()
5742 _svar = 1
5743 this._mvar = 101
5744 enddef
5745 def AccessObject(): number
5746 return this._mvar
5747 enddef
5748 def AccessStaticThroughObject(): number
5749 return _svar
5750 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005751 endclass
5752
5753 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005754 def new()
5755 this._mvar = 102
5756 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005757 endclass
5758
5759 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005760 def new()
5761 this._mvar = 103
5762 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005763
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005764 def AccessPrivateStaticThroughClassName(): number
5765 assert_equal(1, A._svar)
5766 return 444
5767 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005768 endclass
5769
5770 var oa = A.new()
5771 var ob = B.new()
5772 var oc = C.new()
5773 assert_equal(101, oa.AccessObject())
5774 assert_equal(102, ob.AccessObject())
5775 assert_equal(103, oc.AccessObject())
5776
Ernie Rael03042a22023-11-11 08:53:32 +01005777 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005778
5779 # verify object properly resolves to correct static
5780 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005781 assert_equal(1, ob.AccessStaticThroughObject())
5782 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005783 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005784 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005785enddef
5786
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005787" Test for declaring duplicate object and class members
5788def Test_dup_member_variable()
5789 # Duplicate member variable
5790 var lines =<< trim END
5791 vim9script
5792 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005793 var val = 10
5794 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005795 endclass
5796 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005797 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005798
Ernie Rael03042a22023-11-11 08:53:32 +01005799 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005800 lines =<< trim END
5801 vim9script
5802 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005803 var _val = 10
5804 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005805 endclass
5806 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005807 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005808
5809 # Duplicate public member variable
5810 lines =<< trim END
5811 vim9script
5812 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005813 public var val = 10
5814 public var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005815 endclass
5816 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005817 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005818
Ernie Rael03042a22023-11-11 08:53:32 +01005819 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005820 lines =<< trim END
5821 vim9script
5822 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005823 var val = 10
5824 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005825 endclass
5826 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005827 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005828
Ernie Rael03042a22023-11-11 08:53:32 +01005829 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005830 lines =<< trim END
5831 vim9script
5832 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005833 var _val = 20
5834 public var val = 10
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005835 endclass
5836 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005837 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005838
5839 # Duplicate class member variable
5840 lines =<< trim END
5841 vim9script
5842 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005843 static var s: string = "abc"
5844 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005845 endclass
5846 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005847 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005848
Ernie Rael03042a22023-11-11 08:53:32 +01005849 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005850 lines =<< trim END
5851 vim9script
5852 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005853 public static var s: string = "abc"
5854 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005855 endclass
5856 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005857 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005858
5859 # Duplicate class and object member variable
5860 lines =<< trim END
5861 vim9script
5862 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005863 static var val = 10
5864 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005865 def new()
5866 enddef
5867 endclass
5868 var c = C.new()
5869 assert_equal(10, C.val)
5870 assert_equal(20, c.val)
5871 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005872 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005873
5874 # Duplicate object member variable in a derived class
5875 lines =<< trim END
5876 vim9script
5877 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005878 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005879 endclass
5880 class B extends A
5881 endclass
5882 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005883 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005884 endclass
5885 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005886 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005887
Ernie Rael03042a22023-11-11 08:53:32 +01005888 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005889 lines =<< trim END
5890 vim9script
5891 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005892 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005893 endclass
5894 class B extends A
5895 endclass
5896 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005897 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005898 endclass
5899 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005900 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005901
Ernie Rael03042a22023-11-11 08:53:32 +01005902 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005903 lines =<< trim END
5904 vim9script
5905 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005906 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005907 endclass
5908 class B extends A
5909 endclass
5910 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005911 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005912 endclass
5913 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005914 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005915
5916 # Duplicate object member variable in a derived class
5917 lines =<< trim END
5918 vim9script
5919 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005920 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005921 endclass
5922 class B extends A
5923 endclass
5924 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005925 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005926 endclass
5927 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005928 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005929
5930 # Two member variables with a common prefix
5931 lines =<< trim END
5932 vim9script
5933 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005934 public static var svar2: number
5935 public static var svar: number
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005936 endclass
5937 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005938 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005939enddef
5940
Ernie Rael03042a22023-11-11 08:53:32 +01005941" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005942def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01005943 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005944 var lines =<< trim END
5945 vim9script
5946 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005947 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005948 def GetVal(): number
5949 return this._val
5950 enddef
5951 endclass
5952 def T()
5953 var a = A.new()
5954 a._val = 20
5955 enddef
5956 T()
5957 END
Ernie Rael03042a22023-11-11 08:53:32 +01005958 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005959
Ernie Rael03042a22023-11-11 08:53:32 +01005960 # access a non-existing protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005961 lines =<< trim END
5962 vim9script
5963 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005964 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005965 endclass
5966 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005967 var a = A.new()
5968 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005969 enddef
5970 T()
5971 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005972 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005973
Ernie Rael03042a22023-11-11 08:53:32 +01005974 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005975 lines =<< trim END
5976 vim9script
5977 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005978 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005979 endclass
5980 def T()
5981 var a = A.new()
5982 var x = a._val
5983 enddef
5984 T()
5985 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005986 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005987
Ernie Rael03042a22023-11-11 08:53:32 +01005988 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005989 lines =<< trim END
5990 vim9script
5991 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005992 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005993 endclass
5994 def T()
5995 var a = A.new()
5996 a._val = 3
5997 enddef
5998 T()
5999 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006000 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02006001
Ernie Rael03042a22023-11-11 08:53:32 +01006002 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02006003 lines =<< trim END
6004 vim9script
6005 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006006 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006007 endclass
6008 def T()
6009 var x = A._val
6010 enddef
6011 T()
6012 END
Ernie Rael03042a22023-11-11 08:53:32 +01006013 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02006014
Ernie Rael03042a22023-11-11 08:53:32 +01006015 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02006016 lines =<< trim END
6017 vim9script
6018 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006019 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006020 endclass
6021 def T()
6022 A._val = 3
6023 enddef
6024 T()
6025 END
Ernie Rael03042a22023-11-11 08:53:32 +01006026 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006027enddef
6028
6029" Test for changing the member access of an interface in a implementation class
6030def Test_change_interface_member_access()
6031 var lines =<< trim END
6032 vim9script
6033 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006034 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006035 endinterface
6036 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006037 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006038 endclass
6039 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006040 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006041
6042 lines =<< trim END
6043 vim9script
6044 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006045 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006046 endinterface
6047 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006048 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006049 endclass
6050 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006051 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006052enddef
6053
6054" Test for trying to change a readonly member from a def function
6055def Test_readonly_member_change_in_def_func()
6056 var lines =<< trim END
6057 vim9script
6058 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006059 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006060 endclass
6061 def T()
6062 var a = A.new()
6063 a.val = 20
6064 enddef
6065 T()
6066 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006067 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006068enddef
6069
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006070" Test for reading and writing a class member from a def function
6071def Test_modify_class_member_from_def_function()
6072 var lines =<< trim END
6073 vim9script
6074 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006075 var var1: number = 10
6076 public static var var2: list<number> = [1, 2]
6077 public static var var3: dict<number> = {a: 1, b: 2}
6078 static var _priv_var4: number = 40
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006079 endclass
6080 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02006081 assert_equal([1, 2], A.var2)
6082 assert_equal({a: 1, b: 2}, A.var3)
6083 A.var2 = [3, 4]
6084 A.var3 = {c: 3, d: 4}
6085 assert_equal([3, 4], A.var2)
6086 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael03042a22023-11-11 08:53:32 +01006087 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006088 enddef
6089 T()
6090 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006091 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006092enddef
6093
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006094" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006095def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006096 var lines =<< trim END
6097 vim9script
6098 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006099 public static var svar1: list<number> = [1]
6100 public static var svar2: list<number> = [2]
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006101 endclass
6102
6103 A.svar1->add(3)
6104 A.svar2->add(4)
6105 assert_equal([1, 3], A.svar1)
6106 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006107
6108 def Foo()
6109 A.svar1->add(7)
6110 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006111 assert_equal([1, 3, 7], A.svar1)
6112 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006113 enddef
6114 Foo()
6115 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006116 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006117
6118 # Cannot read from a class variable using an object in script context
6119 lines =<< trim END
6120 vim9script
6121 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006122 public var var1: number
6123 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006124 endclass
6125
6126 var a = A.new()
6127 echo a.svar2
6128 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006129 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006130
6131 # Cannot write to a class variable using an object in script context
6132 lines =<< trim END
6133 vim9script
6134 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006135 public var var1: number
6136 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006137 endclass
6138
6139 var a = A.new()
6140 a.svar2 = [2]
6141 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006142 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006143
6144 # Cannot read from a class variable using an object in def method context
6145 lines =<< trim END
6146 vim9script
6147 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006148 public var var1: number
6149 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006150 endclass
6151
6152 def T()
6153 var a = A.new()
6154 echo a.svar2
6155 enddef
6156 T()
6157 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006158 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006159
6160 # Cannot write to a class variable using an object in def method context
6161 lines =<< trim END
6162 vim9script
6163 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006164 public var var1: number
6165 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006166 endclass
6167
6168 def T()
6169 var a = A.new()
6170 a.svar2 = [2]
6171 enddef
6172 T()
6173 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006174 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006175enddef
6176
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006177" Test for using a interface method using a child object
6178def Test_interface_method_from_child()
6179 var lines =<< trim END
6180 vim9script
6181
6182 interface A
6183 def Foo(): string
6184 endinterface
6185
6186 class B implements A
6187 def Foo(): string
6188 return 'foo'
6189 enddef
6190 endclass
6191
6192 class C extends B
6193 def Bar(): string
6194 return 'bar'
6195 enddef
6196 endclass
6197
6198 def T1(a: A)
6199 assert_equal('foo', a.Foo())
6200 enddef
6201
6202 def T2(b: B)
6203 assert_equal('foo', b.Foo())
6204 enddef
6205
6206 var c = C.new()
6207 T1(c)
6208 T2(c)
6209 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006210 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006211enddef
6212
6213" Test for using an interface method using a child object when it is overridden
6214" by the child class.
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01006215def Test_interface_overridden_method_from_child()
6216 var lines =<< trim END
6217 vim9script
6218
6219 interface A
6220 def Foo(): string
6221 endinterface
6222
6223 class B implements A
6224 def Foo(): string
6225 return 'b-foo'
6226 enddef
6227 endclass
6228
6229 class C extends B
6230 def Bar(): string
6231 return 'bar'
6232 enddef
6233 def Foo(): string
6234 return 'c-foo'
6235 enddef
6236 endclass
6237
6238 def T1(a: A)
6239 assert_equal('c-foo', a.Foo())
6240 enddef
6241
6242 def T2(b: B)
6243 assert_equal('c-foo', b.Foo())
6244 enddef
6245
6246 var c = C.new()
6247 T1(c)
6248 T2(c)
6249 END
6250 v9.CheckSourceSuccess(lines)
6251enddef
6252
6253" Test for interface inheritance
6254def Test_interface_inheritance()
6255 var lines =<< trim END
6256 vim9script
6257
6258 interface A
6259 def A_Fn(): string
6260 endinterface
6261
6262 interface B
6263 def B_Fn(): string
6264 endinterface
6265
6266 interface C
6267 def C_Fn(): string
6268 endinterface
6269
6270 class C1 implements A
6271 def A_Fn(): string
6272 return 'c1-a'
6273 enddef
6274 endclass
6275
6276 class C2 extends C1 implements B
6277 def B_Fn(): string
6278 return 'c2-b'
6279 enddef
6280 def A_Fn(): string
6281 return 'c2-a'
6282 enddef
6283 endclass
6284
6285 class C3 extends C2 implements C
6286 def C_Fn(): string
6287 return 'c3-c'
6288 enddef
6289 def A_Fn(): string
6290 return 'c3-a'
6291 enddef
6292 def B_Fn(): string
6293 return 'c3-b'
6294 enddef
6295 endclass
6296
6297 def T1(a: A, s: string)
6298 assert_equal(s, a.A_Fn())
6299 enddef
6300
6301 def T2(b: B, s: string)
6302 assert_equal(s, b.B_Fn())
6303 enddef
6304
6305 def T3(c: C, s: string)
6306 assert_equal(s, c.C_Fn())
6307 enddef
6308
6309 def T4(c1: C1)
6310 T1(c1, 'c3-a')
6311 enddef
6312
6313 def T5(c2: C2)
6314 T1(c2, 'c3-a')
6315 T2(c2, 'c3-b')
6316 enddef
6317
6318 def T6(c3: C3)
6319 T1(c3, 'c3-a')
6320 T2(c3, 'c3-b')
6321 T3(c3, 'c3-c')
6322 enddef
6323
6324 var o3 = C3.new()
6325 T4(o3)
6326 T5(o3)
6327 T6(o3)
6328 END
6329 v9.CheckSourceSuccess(lines)
6330
6331 # Both the parent and child classes implement the same interface
6332 lines =<< trim END
6333 vim9script
6334
6335 interface I
6336 def Foo(): string
6337 endinterface
6338
6339 class A implements I
6340 def Foo(): string
6341 return 'A-foo'
6342 enddef
6343 endclass
6344
6345 class B implements I
6346 def Foo(): string
6347 return 'B-foo'
6348 enddef
6349 endclass
6350
6351 def Bar(i1: I): string
6352 return i1.Foo()
6353 enddef
6354
6355 var b = B.new()
6356 assert_equal('B-foo', Bar(b))
6357 END
6358 v9.CheckSourceSuccess(lines)
6359enddef
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006360
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006361" Test for abstract methods
6362def Test_abstract_method()
6363 # Use two abstract methods
6364 var lines =<< trim END
6365 vim9script
6366 abstract class A
6367 def M1(): number
6368 return 10
6369 enddef
6370 abstract def M2(): number
6371 abstract def M3(): number
6372 endclass
6373 class B extends A
6374 def M2(): number
6375 return 20
6376 enddef
6377 def M3(): number
6378 return 30
6379 enddef
6380 endclass
6381 var b = B.new()
6382 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6383 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006384 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006385
6386 # Don't define an abstract method
6387 lines =<< trim END
6388 vim9script
6389 abstract class A
6390 abstract def Foo()
6391 endclass
6392 class B extends A
6393 endclass
6394 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006395 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006396
6397 # Use abstract method in a concrete class
6398 lines =<< trim END
6399 vim9script
6400 class A
6401 abstract def Foo()
6402 endclass
6403 class B extends A
6404 endclass
6405 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006406 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006407
6408 # Use abstract method in an interface
6409 lines =<< trim END
6410 vim9script
6411 interface A
6412 abstract def Foo()
6413 endinterface
6414 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006415 def Foo()
6416 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006417 endclass
6418 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006419 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6420
6421 # Use abstract static method in an interface
6422 lines =<< trim END
6423 vim9script
6424 interface A
6425 abstract static def Foo()
6426 enddef
6427 endinterface
6428 END
6429 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6430
6431 # Use abstract static variable in an interface
6432 lines =<< trim END
6433 vim9script
6434 interface A
6435 abstract static foo: number = 10
6436 endinterface
6437 END
6438 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006439
6440 # Abbreviate the "abstract" keyword
6441 lines =<< trim END
6442 vim9script
6443 class A
6444 abs def Foo()
6445 endclass
6446 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006447 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006448
6449 # Use "abstract" with a member variable
6450 lines =<< trim END
6451 vim9script
6452 abstract class A
6453 abstract this.val = 10
6454 endclass
6455 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006456 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006457
6458 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006459 lines =<< trim END
6460 vim9script
6461 abstract class A
6462 abstract static def Foo(): number
6463 endclass
6464 END
6465 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006466
6467 # Type mismatch between abstract method and concrete method
6468 lines =<< trim END
6469 vim9script
6470 abstract class A
6471 abstract def Foo(a: string, b: number): list<number>
6472 endclass
6473 class B extends A
6474 def Foo(a: number, b: string): list<string>
6475 return []
6476 enddef
6477 endclass
6478 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006479 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 +02006480
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006481 # Invoke an abstract method from a def function
6482 lines =<< trim END
6483 vim9script
6484 abstract class A
6485 abstract def Foo(): list<number>
6486 endclass
6487 class B extends A
6488 def Foo(): list<number>
6489 return [3, 5]
6490 enddef
6491 endclass
6492 def Bar(c: B)
6493 assert_equal([3, 5], c.Foo())
6494 enddef
6495 var b = B.new()
6496 Bar(b)
6497 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006498 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006499
6500 # Use a static method in an abstract class
6501 lines =<< trim END
6502 vim9script
6503 abstract class A
6504 static def Foo(): string
6505 return 'foo'
6506 enddef
6507 endclass
6508 assert_equal('foo', A.Foo())
6509 END
6510 v9.CheckSourceSuccess(lines)
Ernie Rael7c92e882025-01-18 17:26:39 +01006511
6512 # Invoke method returning a value through the abstract class. See #15432.
6513 lines =<< trim END
6514 vim9script
6515
6516 abstract class A
6517 abstract def String(): string
6518 endclass
6519
6520 class B extends A
6521 def String(): string
6522 return 'B'
6523 enddef
6524 endclass
6525
6526 def F(o: A)
6527 assert_equal('B', o.String())
6528 enddef
6529 F(B.new())
6530 END
6531 v9.CheckSourceSuccess(lines)
6532
6533 # Invoke abstract method returning a value does not compile
6534 lines =<< trim END
6535 vim9script
6536
6537 abstract class A
6538 abstract def String(): string
6539 return 'X'
6540 enddef
6541 endclass
6542 END
6543 v9.CheckScriptFailure(lines, "E1318: Not a valid command in a class: return 'X'")
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006544enddef
6545
6546" Test for calling a class method from a subclass
6547def Test_class_method_call_from_subclass()
6548 # class method call from a subclass
6549 var lines =<< trim END
6550 vim9script
6551
6552 class A
6553 static def Foo()
6554 echo "foo"
6555 enddef
6556 endclass
6557
6558 class B extends A
6559 def Bar()
6560 Foo()
6561 enddef
6562 endclass
6563
6564 var b = B.new()
6565 b.Bar()
6566 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006567 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006568enddef
6569
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006570" Test for calling a class method using an object in a def function context and
6571" script context.
6572def Test_class_method_call_using_object()
6573 # script context
6574 var lines =<< trim END
6575 vim9script
6576 class A
6577 static def Foo(): list<string>
6578 return ['a', 'b']
6579 enddef
6580 def Bar()
6581 assert_equal(['a', 'b'], A.Foo())
6582 assert_equal(['a', 'b'], Foo())
6583 enddef
6584 endclass
6585
6586 def T()
6587 assert_equal(['a', 'b'], A.Foo())
6588 var t_a = A.new()
6589 t_a.Bar()
6590 enddef
6591
6592 assert_equal(['a', 'b'], A.Foo())
6593 var a = A.new()
6594 a.Bar()
6595 T()
6596 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006597 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006598
6599 # script context
6600 lines =<< trim END
6601 vim9script
6602 class A
6603 static def Foo(): string
6604 return 'foo'
6605 enddef
6606 endclass
6607
6608 var a = A.new()
6609 assert_equal('foo', a.Foo())
6610 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006611 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006612
6613 # def function context
6614 lines =<< trim END
6615 vim9script
6616 class A
6617 static def Foo(): string
6618 return 'foo'
6619 enddef
6620 endclass
6621
6622 def T()
6623 var a = A.new()
6624 assert_equal('foo', a.Foo())
6625 enddef
6626 T()
6627 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006628 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006629enddef
6630
6631def Test_class_variable()
6632 var lines =<< trim END
6633 vim9script
6634
6635 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006636 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006637 static def ClassFunc()
6638 assert_equal(10, val)
6639 enddef
6640 def ObjFunc()
6641 assert_equal(10, val)
6642 enddef
6643 endclass
6644
6645 class B extends A
6646 endclass
6647
6648 assert_equal(10, A.val)
6649 A.ClassFunc()
6650 var a = A.new()
6651 a.ObjFunc()
6652 var b = B.new()
6653 b.ObjFunc()
6654
6655 def T1(a1: A)
6656 a1.ObjFunc()
6657 A.ClassFunc()
6658 enddef
6659 T1(b)
6660
6661 A.val = 20
6662 assert_equal(20, A.val)
6663 END
6664 v9.CheckSourceSuccess(lines)
6665
6666 # Modifying a parent class variable from a child class method
6667 lines =<< trim END
6668 vim9script
6669
6670 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006671 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006672 endclass
6673
6674 class B extends A
6675 static def ClassFunc()
6676 val = 20
6677 enddef
6678 endclass
6679 B.ClassFunc()
6680 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006681 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006682
6683 # Reading a parent class variable from a child class method
6684 lines =<< trim END
6685 vim9script
6686
6687 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006688 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006689 endclass
6690
6691 class B extends A
6692 static def ClassFunc()
6693 var i = val
6694 enddef
6695 endclass
6696 B.ClassFunc()
6697 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006698 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006699
6700 # Modifying a parent class variable from a child object method
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
6708 class B extends A
6709 def ObjFunc()
6710 val = 20
6711 enddef
6712 endclass
6713 var b = B.new()
6714 b.ObjFunc()
6715 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006716 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006717
6718 # Reading a parent class variable from a child object method
6719 lines =<< trim END
6720 vim9script
6721
6722 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006723 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006724 endclass
6725
6726 class B extends A
6727 def ObjFunc()
6728 var i = val
6729 enddef
6730 endclass
6731 var b = B.new()
6732 b.ObjFunc()
6733 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006734 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006735
6736 # Modifying a class variable using an object at script level
6737 lines =<< trim END
6738 vim9script
6739
6740 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006741 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006742 endclass
6743 var a = A.new()
6744 a.val = 20
6745 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006746 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006747
6748 # Reading a class variable using an object at script level
6749 lines =<< trim END
6750 vim9script
6751
6752 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006753 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006754 endclass
6755 var a = A.new()
6756 var i = a.val
6757 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006758 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006759
6760 # Modifying a class variable using an object at function level
6761 lines =<< trim END
6762 vim9script
6763
6764 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006765 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006766 endclass
6767
6768 def T()
6769 var a = A.new()
6770 a.val = 20
6771 enddef
6772 T()
6773 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006774 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006775
6776 # Reading a class variable using an object at function level
6777 lines =<< trim END
6778 vim9script
6779
6780 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006781 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006782 endclass
6783 def T()
6784 var a = A.new()
6785 var i = a.val
6786 enddef
6787 T()
6788 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006789 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006790
6791 # Use old implicit var declaration syntax (without initialization)
6792 lines =<< trim END
6793 vim9script
6794
6795 class A
6796 static val: number
6797 endclass
6798 END
6799 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6800
6801 # Use old implicit var declaration syntax (with initialization)
6802 lines =<< trim END
6803 vim9script
6804
6805 class A
6806 static val: number = 10
6807 endclass
6808 END
6809 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6810
6811 # Use old implicit var declaration syntax (type inferred)
6812 lines =<< trim END
6813 vim9script
6814
6815 class A
6816 static val = 10
6817 endclass
6818 END
6819 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6820
6821 # Missing ":var" in "var" class variable declaration (without initialization)
6822 lines =<< trim END
6823 vim9script
6824
6825 class A
6826 static var: number
6827 endclass
6828 END
6829 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6830
6831 # Missing ":var" in "var" class variable declaration (with initialization)
6832 lines =<< trim END
6833 vim9script
6834
6835 class A
6836 static var: number = 10
6837 endclass
6838 END
6839 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6840
6841 # Missing ":var" in "var" class variable declaration (type inferred)
6842 lines =<< trim END
6843 vim9script
6844
6845 class A
6846 static var = 10
6847 endclass
6848 END
6849 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6850
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006851enddef
6852
6853" Test for using a duplicate class method and class variable in a child class
6854def Test_dup_class_member()
6855 # duplicate class variable, class method and overridden object method
6856 var lines =<< trim END
6857 vim9script
6858 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006859 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006860 static def Check()
6861 assert_equal(100, sval)
6862 enddef
6863 def GetVal(): number
6864 return sval
6865 enddef
6866 endclass
6867
6868 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006869 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006870 static def Check()
6871 assert_equal(200, sval)
6872 enddef
6873 def GetVal(): number
6874 return sval
6875 enddef
6876 endclass
6877
6878 def T1(aa: A): number
6879 return aa.GetVal()
6880 enddef
6881
6882 def T2(bb: B): number
6883 return bb.GetVal()
6884 enddef
6885
6886 assert_equal(100, A.sval)
6887 assert_equal(200, B.sval)
6888 var a = A.new()
6889 assert_equal(100, a.GetVal())
6890 var b = B.new()
6891 assert_equal(200, b.GetVal())
6892 assert_equal(200, T1(b))
6893 assert_equal(200, T2(b))
6894 END
6895 v9.CheckSourceSuccess(lines)
6896
6897 # duplicate class variable and class method
6898 lines =<< trim END
6899 vim9script
6900 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006901 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006902 static def Check()
6903 assert_equal(100, sval)
6904 enddef
6905 def GetVal(): number
6906 return sval
6907 enddef
6908 endclass
6909
6910 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006911 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006912 static def Check()
6913 assert_equal(200, sval)
6914 enddef
6915 endclass
6916
6917 def T1(aa: A): number
6918 return aa.GetVal()
6919 enddef
6920
6921 def T2(bb: B): number
6922 return bb.GetVal()
6923 enddef
6924
6925 assert_equal(100, A.sval)
6926 assert_equal(200, B.sval)
6927 var a = A.new()
6928 assert_equal(100, a.GetVal())
6929 var b = B.new()
6930 assert_equal(100, b.GetVal())
6931 assert_equal(100, T1(b))
6932 assert_equal(100, T2(b))
6933 END
6934 v9.CheckSourceSuccess(lines)
6935enddef
6936
6937" Test for calling an instance method using the class
6938def Test_instance_method_call_using_class()
6939 # Invoke an object method using a class in script context
6940 var lines =<< trim END
6941 vim9script
6942 class A
6943 def Foo()
6944 echo "foo"
6945 enddef
6946 endclass
6947 A.Foo()
6948 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006949 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006950
6951 # Invoke an object method using a class in def function context
6952 lines =<< trim END
6953 vim9script
6954 class A
6955 def Foo()
6956 echo "foo"
6957 enddef
6958 endclass
6959 def T()
6960 A.Foo()
6961 enddef
6962 T()
6963 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006964 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006965enddef
6966
6967" Test for duplicate class method and instance method
6968def Test_dup_classmethod_objmethod()
6969 # Duplicate instance method
6970 var lines =<< trim END
6971 vim9script
6972 class A
6973 static def Foo()
6974 enddef
6975 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 +02006980
Ernie Rael03042a22023-11-11 08:53:32 +01006981 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006982 lines =<< trim END
6983 vim9script
6984 class A
6985 static def Foo()
6986 enddef
6987 def _Foo()
6988 enddef
6989 endclass
6990 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006991 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006992
6993 # Duplicate class method
6994 lines =<< trim END
6995 vim9script
6996 class A
6997 def Foo()
6998 enddef
6999 static def Foo()
7000 enddef
7001 endclass
7002 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007003 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007004
Ernie Rael03042a22023-11-11 08:53:32 +01007005 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007006 lines =<< trim END
7007 vim9script
7008 class A
7009 def Foo()
7010 enddef
7011 static def _Foo()
7012 enddef
7013 endclass
7014 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007015 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007016
Ernie Rael03042a22023-11-11 08:53:32 +01007017 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007018 lines =<< trim END
7019 vim9script
7020 class A
7021 def _Foo()
7022 enddef
7023 static def _Foo()
7024 enddef
7025 endclass
7026 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007027 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007028enddef
7029
7030" Test for an instance method access level comparison with parent instance
7031" methods.
7032def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01007033 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007034 var lines =<< trim END
7035 vim9script
7036 class A
7037 def Foo()
7038 enddef
7039 endclass
7040 class B extends A
7041 endclass
7042 class C extends B
7043 def _Foo()
7044 enddef
7045 endclass
7046 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007047 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007048
7049 # Public method in subclass
7050 lines =<< trim END
7051 vim9script
7052 class A
7053 def _Foo()
7054 enddef
7055 endclass
7056 class B extends A
7057 endclass
7058 class C extends B
7059 def Foo()
7060 enddef
7061 endclass
7062 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007063 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007064enddef
7065
7066def Test_extend_empty_class()
7067 var lines =<< trim END
7068 vim9script
7069 class A
7070 endclass
7071 class B extends A
7072 endclass
7073 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007074 public static var rw_class_var = 1
7075 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007076 static def ClassMethod(): number
7077 return 3
7078 enddef
7079 def ObjMethod(): number
7080 return 4
7081 enddef
7082 endclass
7083 assert_equal(1, C.rw_class_var)
7084 assert_equal(3, C.ClassMethod())
7085 var c = C.new()
7086 assert_equal(2, c.rw_obj_var)
7087 assert_equal(4, c.ObjMethod())
7088 END
7089 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02007090enddef
7091
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007092" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01007093" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007094def Test_interface_with_unsupported_members()
7095 var lines =<< trim END
7096 vim9script
7097 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007098 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007099 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 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007107 endinterface
7108 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007109 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007110
7111 lines =<< trim END
7112 vim9script
7113 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007114 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007115 endinterface
7116 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007117 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007118
7119 lines =<< trim END
7120 vim9script
7121 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007122 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007123 endinterface
7124 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007125 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007126
7127 lines =<< trim END
7128 vim9script
7129 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007130 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007131 endinterface
7132 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007133 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007134
7135 lines =<< trim END
7136 vim9script
7137 interface A
7138 static def Foo(d: dict<any>): list<string>
7139 endinterface
7140 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007141 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007142
7143 lines =<< trim END
7144 vim9script
7145 interface A
7146 static def _Foo(d: dict<any>): list<string>
7147 endinterface
7148 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007149 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007150
7151 lines =<< trim END
7152 vim9script
7153 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007154 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007155 endinterface
7156 END
Ernie Rael03042a22023-11-11 08:53:32 +01007157 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007158
7159 lines =<< trim END
7160 vim9script
7161 interface A
7162 def _Foo(d: dict<any>): list<string>
7163 endinterface
7164 END
Ernie Rael03042a22023-11-11 08:53:32 +01007165 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007166enddef
7167
7168" Test for extending an interface
7169def Test_extend_interface()
7170 var lines =<< trim END
7171 vim9script
7172 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007173 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007174 def Foo()
7175 endinterface
7176 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007177 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007178 def Bar()
7179 endinterface
7180 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007181 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007182 def Foo()
7183 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007184 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007185 def Bar()
7186 enddef
7187 endclass
7188 END
7189 v9.CheckSourceSuccess(lines)
7190
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007191 # extending empty interface
7192 lines =<< trim END
7193 vim9script
7194 interface A
7195 endinterface
7196 interface B extends A
7197 endinterface
7198 class C implements B
7199 endclass
7200 END
7201 v9.CheckSourceSuccess(lines)
7202
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007203 lines =<< trim END
7204 vim9script
7205 interface A
7206 def Foo()
7207 endinterface
7208 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007209 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007210 endinterface
7211 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007212 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007213 endclass
7214 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007215 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007216
7217 lines =<< trim END
7218 vim9script
7219 interface A
7220 def Foo()
7221 endinterface
7222 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007223 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007224 endinterface
7225 class C implements A, B
7226 def Foo()
7227 enddef
7228 endclass
7229 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007230 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007231
7232 # interface cannot extend a class
7233 lines =<< trim END
7234 vim9script
7235 class A
7236 endclass
7237 interface B extends A
7238 endinterface
7239 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007240 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007241
7242 # class cannot extend an interface
7243 lines =<< trim END
7244 vim9script
7245 interface A
7246 endinterface
7247 class B extends A
7248 endclass
7249 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007250 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007251
7252 # interface cannot implement another interface
7253 lines =<< trim END
7254 vim9script
7255 interface A
7256 endinterface
7257 interface B implements A
7258 endinterface
7259 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007260 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007261
7262 # interface cannot extend multiple interfaces
7263 lines =<< trim END
7264 vim9script
7265 interface A
7266 endinterface
7267 interface B
7268 endinterface
7269 interface C extends A, B
7270 endinterface
7271 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007272 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007273
7274 # Variable type in an extended interface is of different type
7275 lines =<< trim END
7276 vim9script
7277 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007278 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007279 endinterface
7280 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007281 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007282 endinterface
7283 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007284 var val1: string
7285 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007286 endinterface
7287 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007288 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007289enddef
7290
7291" Test for a child class implementing an interface when some of the methods are
7292" defined in the parent class.
7293def Test_child_class_implements_interface()
7294 var lines =<< trim END
7295 vim9script
7296
7297 interface Intf
7298 def F1(): list<list<number>>
7299 def F2(): list<list<number>>
7300 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007301 var var1: list<dict<number>>
7302 var var2: list<dict<number>>
7303 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007304 endinterface
7305
7306 class A
7307 def A1()
7308 enddef
7309 def F3(): list<list<number>>
7310 return [[3]]
7311 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007312 var v1: list<list<number>> = [[0]]
7313 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007314 endclass
7315
7316 class B extends A
7317 def B1()
7318 enddef
7319 def F2(): list<list<number>>
7320 return [[2]]
7321 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007322 var v2: list<list<number>> = [[0]]
7323 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007324 endclass
7325
7326 class C extends B implements Intf
7327 def C1()
7328 enddef
7329 def F1(): list<list<number>>
7330 return [[1]]
7331 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007332 var v3: list<list<number>> = [[0]]
7333 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007334 endclass
7335
7336 def T(if: Intf)
7337 assert_equal([[1]], if.F1())
7338 assert_equal([[2]], if.F2())
7339 assert_equal([[3]], if.F3())
7340 assert_equal([{a: 10}], if.var1)
7341 assert_equal([{b: 20}], if.var2)
7342 assert_equal([{c: 30}], if.var3)
7343 enddef
7344
7345 var c = C.new()
7346 T(c)
7347 assert_equal([[1]], c.F1())
7348 assert_equal([[2]], c.F2())
7349 assert_equal([[3]], c.F3())
7350 assert_equal([{a: 10}], c.var1)
7351 assert_equal([{b: 20}], c.var2)
7352 assert_equal([{c: 30}], c.var3)
7353 END
7354 v9.CheckSourceSuccess(lines)
7355
7356 # One of the interface methods is not found
7357 lines =<< trim END
7358 vim9script
7359
7360 interface Intf
7361 def F1()
7362 def F2()
7363 def F3()
7364 endinterface
7365
7366 class A
7367 def A1()
7368 enddef
7369 endclass
7370
7371 class B extends A
7372 def B1()
7373 enddef
7374 def F2()
7375 enddef
7376 endclass
7377
7378 class C extends B implements Intf
7379 def C1()
7380 enddef
7381 def F1()
7382 enddef
7383 endclass
7384 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007385 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007386
7387 # One of the interface methods is of different type
7388 lines =<< trim END
7389 vim9script
7390
7391 interface Intf
7392 def F1()
7393 def F2()
7394 def F3()
7395 endinterface
7396
7397 class A
7398 def F3(): number
7399 return 0
7400 enddef
7401 def A1()
7402 enddef
7403 endclass
7404
7405 class B extends A
7406 def B1()
7407 enddef
7408 def F2()
7409 enddef
7410 endclass
7411
7412 class C extends B implements Intf
7413 def C1()
7414 enddef
7415 def F1()
7416 enddef
7417 endclass
7418 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007419 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007420
7421 # One of the interface variables is not present
7422 lines =<< trim END
7423 vim9script
7424
7425 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007426 var var1: list<dict<number>>
7427 var var2: list<dict<number>>
7428 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007429 endinterface
7430
7431 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007432 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007433 endclass
7434
7435 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007436 var v2: list<list<number>> = [[0]]
7437 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007438 endclass
7439
7440 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007441 var v3: list<list<number>> = [[0]]
7442 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007443 endclass
7444 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007445 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007446
7447 # One of the interface variables is of different type
7448 lines =<< trim END
7449 vim9script
7450
7451 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007452 var var1: list<dict<number>>
7453 var var2: list<dict<number>>
7454 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007455 endinterface
7456
7457 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007458 var v1: list<list<number>> = [[0]]
7459 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007460 endclass
7461
7462 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007463 var v2: list<list<number>> = [[0]]
7464 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007465 endclass
7466
7467 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007468 var v3: list<list<number>> = [[0]]
7469 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007470 endclass
7471 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007472 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 +02007473enddef
7474
7475" Test for extending an interface with duplicate variables and methods
7476def Test_interface_extends_with_dup_members()
7477 var lines =<< trim END
7478 vim9script
7479 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007480 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007481 def Foo1(): number
7482 endinterface
7483 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007484 var n2: number
7485 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007486 def Foo2(): number
7487 def Foo1(): number
7488 endinterface
7489 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007490 var n1 = 10
7491 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007492 def Foo1(): number
7493 return 30
7494 enddef
7495 def Foo2(): number
7496 return 40
7497 enddef
7498 endclass
7499 def T1(a: A)
7500 assert_equal(10, a.n1)
7501 assert_equal(30, a.Foo1())
7502 enddef
7503 def T2(b: B)
7504 assert_equal(10, b.n1)
7505 assert_equal(20, b.n2)
7506 assert_equal(30, b.Foo1())
7507 assert_equal(40, b.Foo2())
7508 enddef
7509 var c = C.new()
7510 T1(c)
7511 T2(c)
7512 END
7513 v9.CheckSourceSuccess(lines)
7514enddef
7515
Yegappan Lakshmananc10342d2025-01-11 09:39:01 +01007516" Test for implementing an interface with different ordering for the interface
7517" member variables.
7518def Test_implement_interface_with_different_variable_order()
7519 var lines =<< trim END
7520 vim9script
7521
7522 interface IX
7523 var F: func(): string
7524 endinterface
7525
7526 class X implements IX
7527 var x: number
7528 var F: func(): string = () => 'ok'
7529 endclass
7530
7531 def Foo(ix: IX): string
7532 return ix.F()
7533 enddef
7534
7535 var x0 = X.new(0)
7536 assert_equal('ok', Foo(x0))
7537 END
7538 v9.CheckSourceSuccess(lines)
7539enddef
7540
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01007541" Test for inheriting interfaces from an imported super class
7542def Test_interface_inheritance_with_imported_super()
7543 var lines =<< trim END
7544 vim9script
7545
7546 export interface I
7547 def F(): string
7548 endinterface
7549
7550 export class A implements I
7551 def F(): string
7552 return 'A'
7553 enddef
7554 endclass
7555 END
7556 writefile(lines, 'Xinheritintfimportclass.vim', 'D')
7557
7558 lines =<< trim END
7559 vim9script
7560
7561 import './Xinheritintfimportclass.vim' as i_imp
7562
7563 # class C extends i_imp.A
7564 class C extends i_imp.A implements i_imp.I
7565 def F(): string
7566 return 'C'
7567 enddef
7568 endclass
7569
7570 def TestI(i: i_imp.I): string
7571 return i.F()
7572 enddef
7573
7574 assert_equal('C', TestI(C.new()))
7575 END
7576 v9.CheckSourceSuccess(lines)
7577enddef
7578
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007579" Test for using "any" type for a variable in a sub-class while it has a
7580" concrete type in the interface
7581def Test_implements_using_var_type_any()
7582 var lines =<< trim END
7583 vim9script
7584 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007585 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007586 endinterface
7587 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007588 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007589 endclass
7590 var b = B.new()
7591 assert_equal([{a: '1'}, {b: '2'}], b.val)
7592 END
7593 v9.CheckSourceSuccess(lines)
7594
7595 # initialize instance variable using a different type
7596 lines =<< trim END
7597 vim9script
7598 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007599 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007600 endinterface
7601 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007602 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007603 endclass
7604 var b = B.new()
7605 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007606 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007607enddef
7608
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007609" Test for assigning to a member variable in a nested class
7610def Test_nested_object_assignment()
7611 var lines =<< trim END
7612 vim9script
7613
7614 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007615 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007616 endclass
7617
7618 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007619 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007620 endclass
7621
7622 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007623 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007624 endclass
7625
7626 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007627 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007628 endclass
7629
7630 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007631 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007632 enddef
7633
7634 var d = D.new()
7635 T(d)
7636 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007637 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007638enddef
7639
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007640" Test for calling methods using a null object
7641def Test_null_object_method_call()
7642 # Calling a object method using a null object in script context
7643 var lines =<< trim END
7644 vim9script
7645
7646 class C
7647 def Foo()
7648 assert_report('This method should not be executed')
7649 enddef
7650 endclass
7651
7652 var o: C
7653 o.Foo()
7654 END
7655 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7656
7657 # Calling a object method using a null object in def function context
7658 lines =<< trim END
7659 vim9script
7660
7661 class C
7662 def Foo()
7663 assert_report('This method should not be executed')
7664 enddef
7665 endclass
7666
7667 def T()
7668 var o: C
7669 o.Foo()
7670 enddef
7671 T()
7672 END
7673 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7674
7675 # Calling a object method through another class method using a null object in
7676 # script context
7677 lines =<< trim END
7678 vim9script
7679
7680 class C
7681 def Foo()
7682 assert_report('This method should not be executed')
7683 enddef
7684
7685 static def Bar(o_any: any)
7686 var o_typed: C = o_any
7687 o_typed.Foo()
7688 enddef
7689 endclass
7690
7691 var o: C
7692 C.Bar(o)
7693 END
7694 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7695
7696 # Calling a object method through another class method using a null object in
7697 # def function context
7698 lines =<< trim END
7699 vim9script
7700
7701 class C
7702 def Foo()
7703 assert_report('This method should not be executed')
7704 enddef
7705
7706 static def Bar(o_any: any)
7707 var o_typed: C = o_any
7708 o_typed.Foo()
7709 enddef
7710 endclass
7711
7712 def T()
7713 var o: C
7714 C.Bar(o)
7715 enddef
7716 T()
7717 END
7718 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007719
7720 # Calling an object method defined in a class that is extended. This differs
7721 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7722 lines =<< trim END
7723 vim9script
7724
7725 class C0
7726 def F()
7727 enddef
7728 endclass
7729
7730 class C extends C0
7731 endclass
7732
7733 def X()
7734 var o: C0 = null_object
7735 o.F()
7736 enddef
7737 X()
7738 END
7739 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7740
7741 # Getting a function ref an object method.
7742 lines =<< trim END
7743 vim9script
7744
7745 class C0
7746 def F()
7747 enddef
7748 endclass
7749
7750 class C extends C0
7751 endclass
7752
7753 def X()
7754 var o: C0 = null_object
7755 var XXX = o.F
7756 enddef
7757 X()
7758 END
7759 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007760enddef
7761
7762" Test for using a dict as an object member
7763def Test_dict_object_member()
7764 var lines =<< trim END
7765 vim9script
7766
7767 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007768 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007769 def GetState(): dict<number>
7770 return this.state
7771 enddef
7772 endclass
7773
7774 var ctx = Context.new()
7775 ctx.state->extend({a: 1})
7776 ctx.state['b'] = 2
7777 assert_equal({a: 1, b: 2}, ctx.GetState())
7778
7779 def F()
7780 ctx.state['c'] = 3
7781 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7782 enddef
7783 F()
7784 assert_equal(3, ctx.state.c)
7785 ctx.state.c = 4
7786 assert_equal(4, ctx.state.c)
7787 END
7788 v9.CheckSourceSuccess(lines)
7789enddef
7790
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007791" The following test was failing after 9.0.1914. This was caused by using a
7792" freed object from a previous method call.
7793def Test_freed_object_from_previous_method_call()
7794 var lines =<< trim END
7795 vim9script
7796
7797 class Context
7798 endclass
7799
7800 class Result
7801 endclass
7802
7803 def Failure(): Result
7804 return Result.new()
7805 enddef
7806
7807 def GetResult(ctx: Context): Result
7808 return Failure()
7809 enddef
7810
7811 def Test_GetResult()
7812 var ctx = Context.new()
7813 var result = GetResult(ctx)
7814 enddef
7815
7816 Test_GetResult()
7817 END
7818 v9.CheckSourceSuccess(lines)
7819enddef
7820
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007821" Test for duplicate object and class variable
7822def Test_duplicate_variable()
7823 # Object variable name is same as the class variable name
7824 var lines =<< trim END
7825 vim9script
7826 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007827 public static var sval: number
7828 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007829 endclass
7830 var a = A.new()
7831 END
7832 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7833
7834 # Duplicate variable name and calling a class method
7835 lines =<< trim END
7836 vim9script
7837 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007838 public static var sval: number
7839 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007840 def F1()
7841 echo this.sval
7842 enddef
7843 static def F2()
7844 echo sval
7845 enddef
7846 endclass
7847 A.F2()
7848 END
7849 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7850
7851 # Duplicate variable with an empty constructor
7852 lines =<< trim END
7853 vim9script
7854 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007855 public static var sval: number
7856 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007857 def new()
7858 enddef
7859 endclass
7860 var a = A.new()
7861 END
7862 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7863enddef
7864
7865" Test for using a reserved keyword as a variable name
7866def Test_reserved_varname()
7867 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7868 'null_function', 'null_list', 'null_partial', 'null_string',
7869 'null_channel', 'null_job', 'super', 'this']
7870
7871 var lines =<< trim eval END
7872 vim9script
7873 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007874 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007875 endclass
7876 var o = C.new()
7877 END
7878 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7879
7880 lines =<< trim eval END
7881 vim9script
7882 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007883 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007884 def new()
7885 enddef
7886 endclass
7887 var o = C.new()
7888 END
7889 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7890
7891 lines =<< trim eval END
7892 vim9script
7893 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007894 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007895 def new()
7896 enddef
7897 def F()
7898 echo this.{kword}
7899 enddef
7900 endclass
7901 var o = C.new()
7902 o.F()
7903 END
7904 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007905
7906 # class variable name
7907 if kword != 'this'
7908 lines =<< trim eval END
7909 vim9script
7910 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007911 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007912 endclass
7913 END
7914 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7915 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007916 endfor
7917enddef
7918
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007919" Test for checking the type of the arguments and the return value of a object
7920" method in an extended class.
7921def Test_extended_obj_method_type_check()
7922 var 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: C): B
7940 return B.new()
7941 enddef
7942 endclass
7943 END
7944 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
7945
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): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007964 return C.new()
7965 enddef
7966 endclass
7967 END
7968 v9.CheckSourceSuccess(lines)
7969
7970 lines =<< trim END
7971 vim9script
7972
7973 class A
7974 endclass
7975 class B extends A
7976 endclass
7977 class C extends B
7978 endclass
7979
7980 class Foo
7981 def Doit(p: B): B
7982 return B.new()
7983 enddef
7984 endclass
7985
7986 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007987 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007988 return B.new()
7989 enddef
7990 endclass
7991 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007992 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 +02007993
7994 lines =<< trim END
7995 vim9script
7996
7997 class A
7998 endclass
7999 class B extends A
8000 endclass
8001 class C extends B
8002 endclass
8003
8004 class Foo
8005 def Doit(p: B): B
8006 return B.new()
8007 enddef
8008 endclass
8009
8010 class Bar extends Foo
8011 def Doit(p: B): A
8012 return A.new()
8013 enddef
8014 endclass
8015 END
8016 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 +02008017
8018 # check varargs type mismatch
8019 lines =<< trim END
8020 vim9script
8021
8022 class B
8023 def F(...xxx: list<any>)
8024 enddef
8025 endclass
8026 class C extends B
8027 def F(xxx: list<any>)
8028 enddef
8029 endclass
8030 END
8031 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 +02008032enddef
8033
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008034" Test type checking for class variable in assignments
8035func Test_class_variable_complex_type_check()
8036 " class variable with a specific type. Try assigning a different type at
8037 " script level.
8038 let lines =<< trim END
8039 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008040 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008041 return {}
8042 enddef
8043 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008044 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008045 endclass
8046 test_garbagecollect_now()
8047 A.Fn = "abc"
8048 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008049 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 +02008050
8051 " class variable with a specific type. Try assigning a different type at
8052 " class def method level.
8053 let lines =<< trim END
8054 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008055 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008056 return {}
8057 enddef
8058 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008059 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008060 def Bar()
8061 Fn = "abc"
8062 enddef
8063 endclass
8064 var a = A.new()
8065 test_garbagecollect_now()
8066 a.Bar()
8067 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008068 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 +02008069
8070 " class variable with a specific type. Try assigning a different type at
8071 " script def method level.
8072 let lines =<< trim END
8073 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008074 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008075 return {}
8076 enddef
8077 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008078 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008079 endclass
8080 def Bar()
8081 A.Fn = "abc"
8082 enddef
8083 test_garbagecollect_now()
8084 Bar()
8085 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008086 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 +02008087
8088 " class variable without any type. Should be set to the initialization
8089 " expression type. Try assigning a different type from script level.
8090 let lines =<< trim END
8091 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008092 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008093 return {}
8094 enddef
8095 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008096 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008097 endclass
8098 test_garbagecollect_now()
8099 A.Fn = "abc"
8100 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008101 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 +02008102
8103 " class variable without any type. Should be set to the initialization
8104 " expression type. Try assigning a different type at class def level.
8105 let lines =<< trim END
8106 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008107 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008108 return {}
8109 enddef
8110 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008111 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008112 def Bar()
8113 Fn = "abc"
8114 enddef
8115 endclass
8116 var a = A.new()
8117 test_garbagecollect_now()
8118 a.Bar()
8119 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008120 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 +02008121
8122 " class variable without any type. Should be set to the initialization
8123 " expression type. Try assigning a different type at script def level.
8124 let lines =<< trim END
8125 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008126 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008127 return {}
8128 enddef
8129 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008130 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008131 endclass
8132 def Bar()
8133 A.Fn = "abc"
8134 enddef
8135 test_garbagecollect_now()
8136 Bar()
8137 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008138 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 +02008139
8140 " class variable with 'any" type. Can be assigned different types.
8141 let lines =<< trim END
8142 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008143 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008144 return {}
8145 enddef
8146 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008147 public static var Fn: any = Foo
8148 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008149 endclass
8150 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008151 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008152 A.Fn = "abc"
8153 test_garbagecollect_now()
8154 assert_equal('string', typename(A.Fn))
8155 A.Fn2 = Foo
8156 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008157 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008158 A.Fn2 = "xyz"
8159 test_garbagecollect_now()
8160 assert_equal('string', typename(A.Fn2))
8161 END
8162 call v9.CheckSourceSuccess(lines)
8163
8164 " class variable with 'any" type. Can be assigned different types.
8165 let lines =<< trim END
8166 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008167 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008168 return {}
8169 enddef
8170 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008171 public static var Fn: any = Foo
8172 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008173
8174 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008175 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008176 Fn = "abc"
8177 assert_equal('string', typename(Fn))
8178 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008179 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008180 Fn2 = "xyz"
8181 assert_equal('string', typename(Fn2))
8182 enddef
8183 endclass
8184 var a = A.new()
8185 test_garbagecollect_now()
8186 a.Bar()
8187 test_garbagecollect_now()
8188 A.Fn = Foo
8189 a.Bar()
8190 END
8191 call v9.CheckSourceSuccess(lines)
8192
8193 " class variable with 'any" type. Can be assigned different types.
8194 let lines =<< trim END
8195 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008196 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008197 return {}
8198 enddef
8199 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008200 public static var Fn: any = Foo
8201 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008202 endclass
8203
8204 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008205 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008206 A.Fn = "abc"
8207 assert_equal('string', typename(A.Fn))
8208 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008209 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008210 A.Fn2 = "xyz"
8211 assert_equal('string', typename(A.Fn2))
8212 enddef
8213 Bar()
8214 test_garbagecollect_now()
8215 A.Fn = Foo
8216 Bar()
8217 END
8218 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008219
8220 let lines =<< trim END
8221 vim9script
8222 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008223 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008224 endclass
8225 assert_equal([0z10, 0z20], A.foo)
8226 A.foo = [0z30]
8227 assert_equal([0z30], A.foo)
8228 var a = A.foo
8229 assert_equal([0z30], a)
8230 END
8231 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008232endfunc
8233
8234" Test type checking for object variable in assignments
8235func Test_object_variable_complex_type_check()
8236 " object variable with a specific type. Try assigning a different type at
8237 " script level.
8238 let lines =<< trim END
8239 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008240 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008241 return {}
8242 enddef
8243 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008244 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008245 endclass
8246 var a = A.new()
8247 test_garbagecollect_now()
8248 a.Fn = "abc"
8249 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008250 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 +02008251
8252 " object variable with a specific type. Try assigning a different type at
8253 " object def method level.
8254 let lines =<< trim END
8255 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008256 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008257 return {}
8258 enddef
8259 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008260 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008261 def Bar()
8262 this.Fn = "abc"
8263 this.Fn = Foo
8264 enddef
8265 endclass
8266 var a = A.new()
8267 test_garbagecollect_now()
8268 a.Bar()
8269 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008270 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 +02008271
8272 " object variable with a specific type. Try assigning a different type at
8273 " script def method level.
8274 let lines =<< trim END
8275 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008276 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008277 return {}
8278 enddef
8279 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008280 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008281 endclass
8282 def Bar()
8283 var a = A.new()
8284 a.Fn = "abc"
8285 a.Fn = Foo
8286 enddef
8287 test_garbagecollect_now()
8288 Bar()
8289 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008290 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 +02008291
8292 " object variable without any type. Should be set to the initialization
8293 " expression type. Try assigning a different type from script level.
8294 let lines =<< trim END
8295 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008296 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008297 return {}
8298 enddef
8299 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008300 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008301 endclass
8302 var a = A.new()
8303 test_garbagecollect_now()
8304 a.Fn = "abc"
8305 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008306 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 +02008307
8308 " object variable without any type. Should be set to the initialization
8309 " expression type. Try assigning a different type at object def level.
8310 let lines =<< trim END
8311 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008312 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008313 return {}
8314 enddef
8315 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008316 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008317 def Bar()
8318 this.Fn = "abc"
8319 this.Fn = Foo
8320 enddef
8321 endclass
8322 var a = A.new()
8323 test_garbagecollect_now()
8324 a.Bar()
8325 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008326 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 +02008327
8328 " object variable without any type. Should be set to the initialization
8329 " expression type. Try assigning a different type at script def level.
8330 let lines =<< trim END
8331 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008332 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008333 return {}
8334 enddef
8335 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008336 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008337 endclass
8338 def Bar()
8339 var a = A.new()
8340 a.Fn = "abc"
8341 a.Fn = Foo
8342 enddef
8343 test_garbagecollect_now()
8344 Bar()
8345 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008346 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 +02008347
8348 " object variable with 'any" type. Can be assigned different types.
8349 let lines =<< trim END
8350 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008351 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008352 return {}
8353 enddef
8354 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008355 public var Fn: any = Foo
8356 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008357 endclass
8358
8359 var a = A.new()
8360 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008361 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008362 a.Fn = "abc"
8363 test_garbagecollect_now()
8364 assert_equal('string', typename(a.Fn))
8365 a.Fn2 = Foo
8366 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008367 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008368 a.Fn2 = "xyz"
8369 test_garbagecollect_now()
8370 assert_equal('string', typename(a.Fn2))
8371 END
8372 call v9.CheckSourceSuccess(lines)
8373
8374 " object variable with 'any" type. Can be assigned different types.
8375 let lines =<< trim END
8376 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008377 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008378 return {}
8379 enddef
8380 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008381 public var Fn: any = Foo
8382 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008383
8384 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008385 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008386 this.Fn = "abc"
8387 assert_equal('string', typename(this.Fn))
8388 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008389 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008390 this.Fn2 = "xyz"
8391 assert_equal('string', typename(this.Fn2))
8392 enddef
8393 endclass
8394
8395 var a = A.new()
8396 test_garbagecollect_now()
8397 a.Bar()
8398 test_garbagecollect_now()
8399 a.Fn = Foo
8400 a.Bar()
8401 END
8402 call v9.CheckSourceSuccess(lines)
8403
8404 " object variable with 'any" type. Can be assigned different types.
8405 let lines =<< trim END
8406 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008407 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008408 return {}
8409 enddef
8410 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008411 public var Fn: any = Foo
8412 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008413 endclass
8414
8415 def Bar()
8416 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008417 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008418 a.Fn = "abc"
8419 assert_equal('string', typename(a.Fn))
8420 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008421 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008422 a.Fn2 = "xyz"
8423 assert_equal('string', typename(a.Fn2))
8424 enddef
8425 test_garbagecollect_now()
8426 Bar()
8427 test_garbagecollect_now()
8428 Bar()
8429 END
8430 call v9.CheckSourceSuccess(lines)
8431endfunc
8432
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008433" Test for recursively calling an object method. This used to cause an
8434" use-after-free error.
8435def Test_recursive_object_method_call()
8436 var lines =<< trim END
8437 vim9script
8438 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008439 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008440 def Foo(): number
8441 if this.val >= 90
8442 return this.val
8443 endif
8444 this.val += 1
8445 return this.Foo()
8446 enddef
8447 endclass
8448 var a = A.new()
8449 assert_equal(90, a.Foo())
8450 END
8451 v9.CheckSourceSuccess(lines)
8452enddef
8453
8454" Test for recursively calling a class method.
8455def Test_recursive_class_method_call()
8456 var lines =<< trim END
8457 vim9script
8458 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008459 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008460 static def Foo(): number
8461 if val >= 90
8462 return val
8463 endif
8464 val += 1
8465 return Foo()
8466 enddef
8467 endclass
8468 assert_equal(90, A.Foo())
8469 END
8470 v9.CheckSourceSuccess(lines)
8471enddef
8472
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008473" Test for checking the argument types and the return type when assigning a
8474" funcref to make sure the invariant class type is used.
8475def Test_funcref_argtype_returntype_check()
8476 var lines =<< trim END
8477 vim9script
8478 class A
8479 endclass
8480 class B extends A
8481 endclass
8482
8483 def Foo(p: B): B
8484 return B.new()
8485 enddef
8486
8487 var Bar: func(A): A = Foo
8488 END
8489 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8490
8491 lines =<< trim END
8492 vim9script
8493 class A
8494 endclass
8495 class B extends A
8496 endclass
8497
8498 def Foo(p: B): B
8499 return B.new()
8500 enddef
8501
8502 def Baz()
8503 var Bar: func(A): A = Foo
8504 enddef
8505 Baz()
8506 END
8507 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8508enddef
8509
Ernie Rael96952b22023-10-17 18:15:01 +02008510def Test_funcref_argtype_invariance_check()
8511 var lines =<< trim END
8512 vim9script
8513
8514 class A
8515 endclass
8516 class B extends A
8517 endclass
8518 class C extends B
8519 endclass
8520
8521 var Func: func(B): number
8522 Func = (o: B): number => 3
8523 assert_equal(3, Func(B.new()))
8524 END
8525 v9.CheckSourceSuccess(lines)
8526
8527 lines =<< trim END
8528 vim9script
8529
8530 class A
8531 endclass
8532 class B extends A
8533 endclass
8534 class C extends B
8535 endclass
8536
8537 var Func: func(B): number
8538 Func = (o: A): number => 3
8539 END
8540 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8541
8542 lines =<< trim END
8543 vim9script
8544
8545 class A
8546 endclass
8547 class B extends A
8548 endclass
8549 class C extends B
8550 endclass
8551
8552 var Func: func(B): number
8553 Func = (o: C): number => 3
8554 END
8555 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8556enddef
8557
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008558" Test for using an operator (e.g. +) with an assignment
8559def Test_op_and_assignment()
8560 # Using += with a class variable
8561 var lines =<< trim END
8562 vim9script
8563 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008564 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008565 static def Foo(): list<number>
8566 val += [1]
8567 return val
8568 enddef
8569 endclass
8570 def Bar(): list<number>
8571 A.val += [2]
8572 return A.val
8573 enddef
8574 assert_equal([1], A.Foo())
8575 assert_equal([1, 2], Bar())
8576 A.val += [3]
8577 assert_equal([1, 2, 3], A.val)
8578 END
8579 v9.CheckSourceSuccess(lines)
8580
8581 # Using += with an object variable
8582 lines =<< trim END
8583 vim9script
8584 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008585 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008586 def Foo(): list<number>
8587 this.val += [1]
8588 return this.val
8589 enddef
8590 endclass
8591 def Bar(bar_a: A): list<number>
8592 bar_a.val += [2]
8593 return bar_a.val
8594 enddef
8595 var a = A.new()
8596 assert_equal([1], a.Foo())
8597 assert_equal([1, 2], Bar(a))
8598 a.val += [3]
8599 assert_equal([1, 2, 3], a.val)
8600 END
8601 v9.CheckSourceSuccess(lines)
8602enddef
8603
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008604" Test for using an object method as a funcref
8605def Test_object_funcref()
8606 # Using object method funcref from a def function
8607 var lines =<< trim END
8608 vim9script
8609 class A
8610 def Foo(): list<number>
8611 return [3, 2, 1]
8612 enddef
8613 endclass
8614 def Bar()
8615 var a = A.new()
8616 var Fn = a.Foo
8617 assert_equal([3, 2, 1], Fn())
8618 enddef
8619 Bar()
8620 END
8621 v9.CheckSourceSuccess(lines)
8622
8623 # Using object method funcref at the script level
8624 lines =<< trim END
8625 vim9script
8626 class A
8627 def Foo(): dict<number>
8628 return {a: 1, b: 2}
8629 enddef
8630 endclass
8631 var a = A.new()
8632 var Fn = a.Foo
8633 assert_equal({a: 1, b: 2}, Fn())
8634 END
8635 v9.CheckSourceSuccess(lines)
8636
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008637 # Using object method funcref at the script level
8638 lines =<< trim END
8639 vim9script
8640 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008641 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008642 def Foo(): number
8643 return this.val
8644 enddef
8645 endclass
8646 var a = A.new(345)
8647 var Fn = a.Foo
8648 assert_equal(345, Fn())
8649 END
8650 v9.CheckSourceSuccess(lines)
8651
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008652 # Using object method funcref from another object method
8653 lines =<< trim END
8654 vim9script
8655 class A
8656 def Foo(): list<number>
8657 return [3, 2, 1]
8658 enddef
8659 def Bar()
8660 var Fn = this.Foo
8661 assert_equal([3, 2, 1], Fn())
8662 enddef
8663 endclass
8664 var a = A.new()
8665 a.Bar()
8666 END
8667 v9.CheckSourceSuccess(lines)
8668
8669 # Using function() to get a object method funcref
8670 lines =<< trim END
8671 vim9script
8672 class A
8673 def Foo(l: list<any>): list<any>
8674 return l
8675 enddef
8676 endclass
8677 var a = A.new()
8678 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8679 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8680 END
8681 v9.CheckSourceSuccess(lines)
8682
8683 # Use an object method with a function returning a funcref and then call the
8684 # funcref.
8685 lines =<< trim END
8686 vim9script
8687
8688 def Map(F: func(number): number): func(number): number
8689 return (n: number) => F(n)
8690 enddef
8691
8692 class Math
8693 def Double(n: number): number
8694 return 2 * n
8695 enddef
8696 endclass
8697
8698 const math = Math.new()
8699 assert_equal(48, Map(math.Double)(24))
8700 END
8701 v9.CheckSourceSuccess(lines)
8702
Ernie Rael03042a22023-11-11 08:53:32 +01008703 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008704 lines =<< trim END
8705 vim9script
8706 class A
8707 def _Foo()
8708 enddef
8709 endclass
8710 def Bar()
8711 var a = A.new()
8712 var Fn = a._Foo
8713 enddef
8714 Bar()
8715 END
Ernie Rael03042a22023-11-11 08:53:32 +01008716 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008717
Ernie Rael03042a22023-11-11 08:53:32 +01008718 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008719 lines =<< trim END
8720 vim9script
8721 class A
8722 def _Foo()
8723 enddef
8724 endclass
8725 var a = A.new()
8726 var Fn = a._Foo
8727 END
Ernie Rael03042a22023-11-11 08:53:32 +01008728 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008729
Ernie Rael03042a22023-11-11 08:53:32 +01008730 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008731 lines =<< trim END
8732 vim9script
8733 class A
8734 def _Foo(): list<number>
8735 return [3, 2, 1]
8736 enddef
8737 def Bar()
8738 var Fn = this._Foo
8739 assert_equal([3, 2, 1], Fn())
8740 enddef
8741 endclass
8742 var a = A.new()
8743 a.Bar()
8744 END
8745 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008746
8747 # Using object method funcref using call()
8748 lines =<< trim END
8749 vim9script
8750 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008751 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008752 def Foo(): number
8753 return this.val
8754 enddef
8755 endclass
8756
8757 def Bar(obj: A)
8758 assert_equal(123, call(obj.Foo, []))
8759 enddef
8760
8761 var a = A.new(123)
8762 Bar(a)
8763 assert_equal(123, call(a.Foo, []))
8764 END
8765 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008766enddef
8767
8768" Test for using a class method as a funcref
8769def Test_class_funcref()
8770 # Using class method funcref in a def function
8771 var lines =<< trim END
8772 vim9script
8773 class A
8774 static def Foo(): list<number>
8775 return [3, 2, 1]
8776 enddef
8777 endclass
8778 def Bar()
8779 var Fn = A.Foo
8780 assert_equal([3, 2, 1], Fn())
8781 enddef
8782 Bar()
8783 END
8784 v9.CheckSourceSuccess(lines)
8785
8786 # Using class method funcref at script level
8787 lines =<< trim END
8788 vim9script
8789 class A
8790 static def Foo(): dict<number>
8791 return {a: 1, b: 2}
8792 enddef
8793 endclass
8794 var Fn = A.Foo
8795 assert_equal({a: 1, b: 2}, Fn())
8796 END
8797 v9.CheckSourceSuccess(lines)
8798
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008799 # Using class method funcref at the script level
8800 lines =<< trim END
8801 vim9script
8802 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008803 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008804 static def Foo(): number
8805 return val
8806 enddef
8807 endclass
8808 A.val = 567
8809 var Fn = A.Foo
8810 assert_equal(567, Fn())
8811 END
8812 v9.CheckSourceSuccess(lines)
8813
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008814 # Using function() to get a class method funcref
8815 lines =<< trim END
8816 vim9script
8817 class A
8818 static def Foo(l: list<any>): list<any>
8819 return l
8820 enddef
8821 endclass
8822 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8823 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8824 END
8825 v9.CheckSourceSuccess(lines)
8826
8827 # Using a class method funcref from another class method
8828 lines =<< trim END
8829 vim9script
8830 class A
8831 static def Foo(): list<number>
8832 return [3, 2, 1]
8833 enddef
8834 static def Bar()
8835 var Fn = Foo
8836 assert_equal([3, 2, 1], Fn())
8837 enddef
8838 endclass
8839 A.Bar()
8840 END
8841 v9.CheckSourceSuccess(lines)
8842
8843 # Use a class method with a function returning a funcref and then call the
8844 # funcref.
8845 lines =<< trim END
8846 vim9script
8847
8848 def Map(F: func(number): number): func(number): number
8849 return (n: number) => F(n)
8850 enddef
8851
8852 class Math
8853 static def StaticDouble(n: number): number
8854 return 2 * n
8855 enddef
8856 endclass
8857
8858 assert_equal(48, Map(Math.StaticDouble)(24))
8859 END
8860 v9.CheckSourceSuccess(lines)
8861
Ernie Rael03042a22023-11-11 08:53:32 +01008862 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008863 lines =<< trim END
8864 vim9script
8865 class A
8866 static def _Foo()
8867 enddef
8868 endclass
8869 def Bar()
8870 var Fn = A._Foo
8871 enddef
8872 Bar()
8873 END
Ernie Rael03042a22023-11-11 08:53:32 +01008874 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008875
Ernie Rael03042a22023-11-11 08:53:32 +01008876 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008877 lines =<< trim END
8878 vim9script
8879 class A
8880 static def _Foo()
8881 enddef
8882 endclass
8883 var Fn = A._Foo
8884 END
Ernie Rael03042a22023-11-11 08:53:32 +01008885 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008886
Ernie Rael03042a22023-11-11 08:53:32 +01008887 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008888 lines =<< trim END
8889 vim9script
8890 class A
8891 static def _Foo(): list<number>
8892 return [3, 2, 1]
8893 enddef
8894 static def Bar()
8895 var Fn = _Foo
8896 assert_equal([3, 2, 1], Fn())
8897 enddef
8898 endclass
8899 A.Bar()
8900 END
8901 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008902
8903 # Using class method funcref using call()
8904 lines =<< trim END
8905 vim9script
8906 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008907 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008908 static def Foo(): number
8909 return val
8910 enddef
8911 endclass
8912
8913 def Bar()
8914 A.val = 468
8915 assert_equal(468, call(A.Foo, []))
8916 enddef
8917 Bar()
8918 assert_equal(468, call(A.Foo, []))
8919 END
8920 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008921enddef
8922
8923" Test for using an object member as a funcref
8924def Test_object_member_funcref()
8925 # Using a funcref object variable in an object method
8926 var lines =<< trim END
8927 vim9script
8928 def Foo(n: number): number
8929 return n * 10
8930 enddef
8931
8932 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008933 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008934 def Bar()
8935 assert_equal(200, this.Cb(20))
8936 enddef
8937 endclass
8938
8939 var a = A.new()
8940 a.Bar()
8941 END
8942 v9.CheckSourceSuccess(lines)
8943
8944 # Using a funcref object variable in a def method
8945 lines =<< trim END
8946 vim9script
8947 def Foo(n: number): number
8948 return n * 10
8949 enddef
8950
8951 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008952 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008953 endclass
8954
8955 def Bar()
8956 var a = A.new()
8957 assert_equal(200, a.Cb(20))
8958 enddef
8959 Bar()
8960 END
8961 v9.CheckSourceSuccess(lines)
8962
8963 # Using a funcref object variable at script level
8964 lines =<< trim END
8965 vim9script
8966 def Foo(n: number): number
8967 return n * 10
8968 enddef
8969
8970 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008971 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008972 endclass
8973
8974 var a = A.new()
8975 assert_equal(200, a.Cb(20))
8976 END
8977 v9.CheckSourceSuccess(lines)
8978
8979 # Using a funcref object variable pointing to an object method in an object
8980 # method.
8981 lines =<< trim END
8982 vim9script
8983 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008984 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008985 def Foo(n: number): number
8986 return n * 10
8987 enddef
8988 def Bar()
8989 assert_equal(200, this.Cb(20))
8990 enddef
8991 endclass
8992
8993 var a = A.new()
8994 a.Bar()
8995 END
8996 v9.CheckSourceSuccess(lines)
8997
8998 # Using a funcref object variable pointing to an object method in a def
8999 # method.
9000 lines =<< trim END
9001 vim9script
9002 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009003 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009004 def Foo(n: number): number
9005 return n * 10
9006 enddef
9007 endclass
9008
9009 def Bar()
9010 var a = A.new()
9011 assert_equal(200, a.Cb(20))
9012 enddef
9013 Bar()
9014 END
9015 v9.CheckSourceSuccess(lines)
9016
9017 # Using a funcref object variable pointing to an object method at script
9018 # level.
9019 lines =<< trim END
9020 vim9script
9021 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009022 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009023 def Foo(n: number): number
9024 return n * 10
9025 enddef
9026 endclass
9027
9028 var a = A.new()
9029 assert_equal(200, a.Cb(20))
9030 END
9031 v9.CheckSourceSuccess(lines)
9032enddef
9033
9034" Test for using a class member as a funcref
9035def Test_class_member_funcref()
9036 # Using a funcref class variable in a class method
9037 var lines =<< trim END
9038 vim9script
9039 def Foo(n: number): number
9040 return n * 10
9041 enddef
9042
9043 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009044 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009045 static def Bar()
9046 assert_equal(200, Cb(20))
9047 enddef
9048 endclass
9049
9050 A.Bar()
9051 END
9052 v9.CheckSourceSuccess(lines)
9053
9054 # Using a funcref class variable in a def method
9055 lines =<< trim END
9056 vim9script
9057 def Foo(n: number): number
9058 return n * 10
9059 enddef
9060
9061 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009062 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009063 endclass
9064
9065 def Bar()
9066 assert_equal(200, A.Cb(20))
9067 enddef
9068 Bar()
9069 END
9070 v9.CheckSourceSuccess(lines)
9071
9072 # Using a funcref class variable at script level
9073 lines =<< trim END
9074 vim9script
9075 def Foo(n: number): number
9076 return n * 10
9077 enddef
9078
9079 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009080 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009081 endclass
9082
9083 assert_equal(200, A.Cb(20))
9084 END
9085 v9.CheckSourceSuccess(lines)
9086
9087 # Using a funcref class variable pointing to a class method in a class
9088 # method.
9089 lines =<< trim END
9090 vim9script
9091 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009092 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009093 static def Foo(n: number): number
9094 return n * 10
9095 enddef
9096 static def Init()
9097 Cb = Foo
9098 enddef
9099 static def Bar()
9100 assert_equal(200, Cb(20))
9101 enddef
9102 endclass
9103
9104 A.Init()
9105 A.Bar()
9106 END
9107 v9.CheckSourceSuccess(lines)
9108
9109 # Using a funcref class variable pointing to a class method in a def method.
9110 lines =<< trim END
9111 vim9script
9112 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009113 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009114 static def Foo(n: number): number
9115 return n * 10
9116 enddef
9117 static def Init()
9118 Cb = Foo
9119 enddef
9120 endclass
9121
9122 def Bar()
9123 A.Init()
9124 assert_equal(200, A.Cb(20))
9125 enddef
9126 Bar()
9127 END
9128 v9.CheckSourceSuccess(lines)
9129
9130 # Using a funcref class variable pointing to a class method at script level.
9131 lines =<< trim END
9132 vim9script
9133 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009134 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009135 static def Foo(n: number): number
9136 return n * 10
9137 enddef
9138 static def Init()
9139 Cb = Foo
9140 enddef
9141 endclass
9142
9143 A.Init()
9144 assert_equal(200, A.Cb(20))
9145 END
9146 v9.CheckSourceSuccess(lines)
9147enddef
9148
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009149" Test for using object methods as popup callback functions
9150def Test_objmethod_popup_callback()
9151 # Use the popup from the script level
9152 var lines =<< trim END
9153 vim9script
9154
9155 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009156 var selection: number = -1
9157 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009158
9159 def PopupFilter(id: number, key: string): bool
9160 add(this.filterkeys, key)
9161 return popup_filter_yesno(id, key)
9162 enddef
9163
9164 def PopupCb(id: number, result: number)
9165 this.selection = result ? 100 : 200
9166 enddef
9167 endclass
9168
9169 var a = A.new()
9170 feedkeys('', 'xt')
9171 var winid = popup_create('Y/N?',
9172 {filter: a.PopupFilter, callback: a.PopupCb})
9173 feedkeys('y', 'xt')
9174 popup_close(winid)
9175 assert_equal(100, a.selection)
9176 assert_equal(['y'], a.filterkeys)
9177 feedkeys('', 'xt')
9178 winid = popup_create('Y/N?',
9179 {filter: a.PopupFilter, callback: a.PopupCb})
9180 feedkeys('n', 'xt')
9181 popup_close(winid)
9182 assert_equal(200, a.selection)
9183 assert_equal(['y', 'n'], a.filterkeys)
9184 END
9185 v9.CheckSourceSuccess(lines)
9186
9187 # Use the popup from a def function
9188 lines =<< trim END
9189 vim9script
9190
9191 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009192 var selection: number = -1
9193 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009194
9195 def PopupFilter(id: number, key: string): bool
9196 add(this.filterkeys, key)
9197 return popup_filter_yesno(id, key)
9198 enddef
9199
9200 def PopupCb(id: number, result: number)
9201 this.selection = result ? 100 : 200
9202 enddef
9203 endclass
9204
9205 def Foo()
9206 var a = A.new()
9207 feedkeys('', 'xt')
9208 var winid = popup_create('Y/N?',
9209 {filter: a.PopupFilter, callback: a.PopupCb})
9210 feedkeys('y', 'xt')
9211 popup_close(winid)
9212 assert_equal(100, a.selection)
9213 assert_equal(['y'], a.filterkeys)
9214 feedkeys('', 'xt')
9215 winid = popup_create('Y/N?',
9216 {filter: a.PopupFilter, callback: a.PopupCb})
9217 feedkeys('n', 'xt')
9218 popup_close(winid)
9219 assert_equal(200, a.selection)
9220 assert_equal(['y', 'n'], a.filterkeys)
9221 enddef
9222 Foo()
9223 END
9224 v9.CheckSourceSuccess(lines)
9225enddef
9226
9227" Test for using class methods as popup callback functions
9228def Test_classmethod_popup_callback()
9229 # Use the popup from the script level
9230 var lines =<< trim END
9231 vim9script
9232
9233 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009234 static var selection: number = -1
9235 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009236
9237 static def PopupFilter(id: number, key: string): bool
9238 add(filterkeys, key)
9239 return popup_filter_yesno(id, key)
9240 enddef
9241
9242 static def PopupCb(id: number, result: number)
9243 selection = result ? 100 : 200
9244 enddef
9245 endclass
9246
9247 feedkeys('', 'xt')
9248 var winid = popup_create('Y/N?',
9249 {filter: A.PopupFilter, callback: A.PopupCb})
9250 feedkeys('y', 'xt')
9251 popup_close(winid)
9252 assert_equal(100, A.selection)
9253 assert_equal(['y'], A.filterkeys)
9254 feedkeys('', 'xt')
9255 winid = popup_create('Y/N?',
9256 {filter: A.PopupFilter, callback: A.PopupCb})
9257 feedkeys('n', 'xt')
9258 popup_close(winid)
9259 assert_equal(200, A.selection)
9260 assert_equal(['y', 'n'], A.filterkeys)
9261 END
9262 v9.CheckSourceSuccess(lines)
9263
9264 # Use the popup from a def function
9265 lines =<< trim END
9266 vim9script
9267
9268 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009269 static var selection: number = -1
9270 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009271
9272 static def PopupFilter(id: number, key: string): bool
9273 add(filterkeys, key)
9274 return popup_filter_yesno(id, key)
9275 enddef
9276
9277 static def PopupCb(id: number, result: number)
9278 selection = result ? 100 : 200
9279 enddef
9280 endclass
9281
9282 def Foo()
9283 feedkeys('', 'xt')
9284 var winid = popup_create('Y/N?',
9285 {filter: A.PopupFilter, callback: A.PopupCb})
9286 feedkeys('y', 'xt')
9287 popup_close(winid)
9288 assert_equal(100, A.selection)
9289 assert_equal(['y'], A.filterkeys)
9290 feedkeys('', 'xt')
9291 winid = popup_create('Y/N?',
9292 {filter: A.PopupFilter, callback: A.PopupCb})
9293 feedkeys('n', 'xt')
9294 popup_close(winid)
9295 assert_equal(200, A.selection)
9296 assert_equal(['y', 'n'], A.filterkeys)
9297 enddef
9298 Foo()
9299 END
9300 v9.CheckSourceSuccess(lines)
9301enddef
9302
9303" Test for using an object method as a timer callback function
9304def Test_objmethod_timer_callback()
9305 # Use the timer callback from script level
9306 var lines =<< trim END
9307 vim9script
9308
9309 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009310 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009311 def TimerCb(timerID: number)
9312 this.timerTick = 6
9313 enddef
9314 endclass
9315
9316 var a = A.new()
9317 timer_start(0, a.TimerCb)
9318 var maxWait = 5
9319 while maxWait > 0 && a.timerTick == -1
9320 :sleep 10m
9321 maxWait -= 1
9322 endwhile
9323 assert_equal(6, a.timerTick)
9324 END
9325 v9.CheckSourceSuccess(lines)
9326
9327 # Use the timer callback from a def function
9328 lines =<< trim END
9329 vim9script
9330
9331 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009332 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009333 def TimerCb(timerID: number)
9334 this.timerTick = 6
9335 enddef
9336 endclass
9337
9338 def Foo()
9339 var a = A.new()
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
9353" Test for using a class method as a timer callback function
9354def Test_classmethod_timer_callback()
9355 # Use the timer callback from script level
9356 var lines =<< trim END
9357 vim9script
9358
9359 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009360 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009361 static def TimerCb(timerID: number)
9362 timerTick = 6
9363 enddef
9364 endclass
9365
9366 timer_start(0, A.TimerCb)
9367 var maxWait = 5
9368 while maxWait > 0 && A.timerTick == -1
9369 :sleep 10m
9370 maxWait -= 1
9371 endwhile
9372 assert_equal(6, A.timerTick)
9373 END
9374 v9.CheckSourceSuccess(lines)
9375
9376 # Use the timer callback from a def function
9377 lines =<< trim END
9378 vim9script
9379
9380 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009381 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009382 static def TimerCb(timerID: number)
9383 timerTick = 6
9384 enddef
9385 endclass
9386
9387 def Foo()
9388 timer_start(0, A.TimerCb)
9389 var maxWait = 5
9390 while maxWait > 0 && A.timerTick == -1
9391 :sleep 10m
9392 maxWait -= 1
9393 endwhile
9394 assert_equal(6, A.timerTick)
9395 enddef
9396 Foo()
9397 END
9398 v9.CheckSourceSuccess(lines)
9399enddef
9400
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009401" Test for using a class variable as the first and/or second operand of a binary
9402" operator.
9403def Test_class_variable_as_operands()
9404 var lines =<< trim END
9405 vim9script
9406 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009407 static var truthy: bool = true
9408 public static var TruthyFn: func
9409 static var list: list<any> = []
9410 static var four: number = 4
9411 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009412
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009413 static def Str(): string
9414 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009415 enddef
9416
9417 static def Four(): number
9418 return four
9419 enddef
9420
9421 static def List(): list<any>
9422 return list
9423 enddef
9424
9425 static def Truthy(): bool
9426 return truthy
9427 enddef
9428
9429 def TestOps()
9430 assert_true(Tests.truthy == truthy)
9431 assert_true(truthy == Tests.truthy)
9432 assert_true(Tests.list isnot [])
9433 assert_true([] isnot Tests.list)
9434 assert_equal(2, Tests.four >> 1)
9435 assert_equal(16, 1 << Tests.four)
9436 assert_equal(8, Tests.four + four)
9437 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009438 assert_equal('hellohello', Tests.str .. str)
9439 assert_equal('hellohello', str .. Tests.str)
9440
9441 # Using class variable for list indexing
9442 var l = range(10)
9443 assert_equal(4, l[Tests.four])
9444 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9445
9446 # Using class variable for Dict key
9447 var d = {hello: 'abc'}
9448 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009449 enddef
9450 endclass
9451
9452 def TestOps2()
9453 assert_true(Tests.truthy == Tests.Truthy())
9454 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009455 assert_true(Tests.truthy == Tests.TruthyFn())
9456 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009457 assert_true(Tests.list is Tests.List())
9458 assert_true(Tests.List() is Tests.list)
9459 assert_equal(2, Tests.four >> 1)
9460 assert_equal(16, 1 << Tests.four)
9461 assert_equal(8, Tests.four + Tests.Four())
9462 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009463 assert_equal('hellohello', Tests.str .. Tests.Str())
9464 assert_equal('hellohello', Tests.Str() .. Tests.str)
9465
9466 # Using class variable for list indexing
9467 var l = range(10)
9468 assert_equal(4, l[Tests.four])
9469 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9470
9471 # Using class variable for Dict key
9472 var d = {hello: 'abc'}
9473 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009474 enddef
9475
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009476 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009477 var t = Tests.new()
9478 t.TestOps()
9479 TestOps2()
9480
9481 assert_true(Tests.truthy == Tests.Truthy())
9482 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009483 assert_true(Tests.truthy == Tests.TruthyFn())
9484 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009485 assert_true(Tests.list is Tests.List())
9486 assert_true(Tests.List() is Tests.list)
9487 assert_equal(2, Tests.four >> 1)
9488 assert_equal(16, 1 << Tests.four)
9489 assert_equal(8, Tests.four + Tests.Four())
9490 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009491 assert_equal('hellohello', Tests.str .. Tests.Str())
9492 assert_equal('hellohello', Tests.Str() .. Tests.str)
9493
9494 # Using class variable for list indexing
9495 var l = range(10)
9496 assert_equal(4, l[Tests.four])
9497 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9498
9499 # Using class variable for Dict key
9500 var d = {hello: 'abc'}
9501 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009502 END
9503 v9.CheckSourceSuccess(lines)
9504enddef
9505
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009506" Test for checking the type of the key used to access an object dict member.
9507def Test_dict_member_key_type_check()
9508 var lines =<< trim END
9509 vim9script
9510
9511 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009512 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009513 endclass
9514
9515 class Test extends State
9516 def ObjMethodTests()
9517 var cursor: number = 0
9518 var z: number = 0
9519 [this.numbers[cursor]] = ['zero.1']
9520 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9521 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9522 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9523 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9524 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9525 [this.numbers[cursor], z] = ['zero.4', 1]
9526 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9527 [z, this.numbers[cursor]] = [1, 'zero.5']
9528 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9529 enddef
9530
9531 static def ClassMethodTests(that: State)
9532 var cursor: number = 0
9533 var z: number = 0
9534 [that.numbers[cursor]] = ['zero.1']
9535 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9536 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9537 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9538 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9539 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9540 [that.numbers[cursor], z] = ['zero.4', 1]
9541 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9542 [z, that.numbers[cursor]] = [1, 'zero.5']
9543 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9544 enddef
9545
9546 def new()
9547 enddef
9548
9549 def newMethodTests()
9550 var cursor: number = 0
9551 var z: number
9552 [this.numbers[cursor]] = ['zero.1']
9553 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9554 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9555 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9556 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9557 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9558 [this.numbers[cursor], z] = ['zero.4', 1]
9559 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9560 [z, this.numbers[cursor]] = [1, 'zero.5']
9561 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9562 enddef
9563 endclass
9564
9565 def DefFuncTests(that: Test)
9566 var cursor: number = 0
9567 var z: number
9568 [that.numbers[cursor]] = ['zero.1']
9569 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9570 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9571 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9572 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9573 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9574 [that.numbers[cursor], z] = ['zero.4', 1]
9575 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9576 [z, that.numbers[cursor]] = [1, 'zero.5']
9577 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9578 enddef
9579
9580 Test.newMethodTests()
9581 Test.new().ObjMethodTests()
9582 Test.ClassMethodTests(Test.new())
9583 DefFuncTests(Test.new())
9584
9585 const test: Test = Test.new()
9586 var cursor: number = 0
9587 [test.numbers[cursor], cursor] = ['zero', 1]
9588 [cursor, test.numbers[cursor]] = [1, 'one']
9589 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9590 END
9591 v9.CheckSourceSuccess(lines)
9592
9593 lines =<< trim END
9594 vim9script
9595
9596 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009597 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009598
9599 def new()
9600 enddef
9601
9602 def Foo()
9603 var z: number
9604 [this.numbers.a, z] = [{}, 10]
9605 enddef
9606 endclass
9607
9608 var a = A.new()
9609 a.Foo()
9610 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009611 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009612
9613 lines =<< trim END
9614 vim9script
9615
9616 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009617 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009618
9619 def new()
9620 enddef
9621
9622 def Foo()
9623 var x: string = 'a'
9624 var y: number
9625 [this.numbers[x], y] = [{}, 10]
9626 enddef
9627 endclass
9628
9629 var a = A.new()
9630 a.Foo()
9631 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009632 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009633enddef
9634
mityua5550692023-11-25 15:41:20 +01009635def Test_compile_many_def_functions_in_funcref_instr()
9636 # This used to crash Vim. This is reproducible only when run on new instance
9637 # of Vim.
9638 var lines =<< trim END
9639 vim9script
9640
9641 class A
9642 def new()
9643 this.TakeFunc(this.F00)
9644 enddef
9645
9646 def TakeFunc(F: func)
9647 enddef
9648
9649 def F00()
9650 this.F01()
9651 this.F02()
9652 this.F03()
9653 this.F04()
9654 this.F05()
9655 this.F06()
9656 this.F07()
9657 this.F08()
9658 this.F09()
9659 this.F10()
9660 this.F11()
9661 this.F12()
9662 this.F13()
9663 this.F14()
9664 this.F15()
9665 this.F16()
9666 this.F17()
9667 this.F18()
9668 this.F19()
9669 this.F20()
9670 this.F21()
9671 this.F22()
9672 this.F23()
9673 this.F24()
9674 this.F25()
9675 this.F26()
9676 this.F27()
9677 this.F28()
9678 this.F29()
9679 this.F30()
9680 this.F31()
9681 this.F32()
9682 this.F33()
9683 this.F34()
9684 this.F35()
9685 this.F36()
9686 this.F37()
9687 this.F38()
9688 this.F39()
9689 this.F40()
9690 this.F41()
9691 this.F42()
9692 this.F43()
9693 this.F44()
9694 this.F45()
9695 this.F46()
9696 this.F47()
9697 enddef
9698
9699 def F01()
9700 enddef
9701 def F02()
9702 enddef
9703 def F03()
9704 enddef
9705 def F04()
9706 enddef
9707 def F05()
9708 enddef
9709 def F06()
9710 enddef
9711 def F07()
9712 enddef
9713 def F08()
9714 enddef
9715 def F09()
9716 enddef
9717 def F10()
9718 enddef
9719 def F11()
9720 enddef
9721 def F12()
9722 enddef
9723 def F13()
9724 enddef
9725 def F14()
9726 enddef
9727 def F15()
9728 enddef
9729 def F16()
9730 enddef
9731 def F17()
9732 enddef
9733 def F18()
9734 enddef
9735 def F19()
9736 enddef
9737 def F20()
9738 enddef
9739 def F21()
9740 enddef
9741 def F22()
9742 enddef
9743 def F23()
9744 enddef
9745 def F24()
9746 enddef
9747 def F25()
9748 enddef
9749 def F26()
9750 enddef
9751 def F27()
9752 enddef
9753 def F28()
9754 enddef
9755 def F29()
9756 enddef
9757 def F30()
9758 enddef
9759 def F31()
9760 enddef
9761 def F32()
9762 enddef
9763 def F33()
9764 enddef
9765 def F34()
9766 enddef
9767 def F35()
9768 enddef
9769 def F36()
9770 enddef
9771 def F37()
9772 enddef
9773 def F38()
9774 enddef
9775 def F39()
9776 enddef
9777 def F40()
9778 enddef
9779 def F41()
9780 enddef
9781 def F42()
9782 enddef
9783 def F43()
9784 enddef
9785 def F44()
9786 enddef
9787 def F45()
9788 enddef
9789 def F46()
9790 enddef
9791 def F47()
9792 enddef
9793 endclass
9794
9795 A.new()
9796 END
9797 writefile(lines, 'Xscript', 'D')
9798 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9799 assert_equal(0, v:shell_error)
9800enddef
9801
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009802" Test for 'final' class and object variables
9803def Test_final_class_object_variable()
9804 # Test for changing a final object variable from an object function
9805 var lines =<< trim END
9806 vim9script
9807 class A
9808 final foo: string = "abc"
9809 def Foo()
9810 this.foo = "def"
9811 enddef
9812 endclass
9813 defcompile A.Foo
9814 END
9815 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9816
9817 # Test for changing a final object variable from the 'new' function
9818 lines =<< trim END
9819 vim9script
9820 class A
9821 final s1: string
9822 final s2: string
9823 def new(this.s1)
9824 this.s2 = 'def'
9825 enddef
9826 endclass
9827 var a = A.new('abc')
9828 assert_equal('abc', a.s1)
9829 assert_equal('def', a.s2)
9830 END
9831 v9.CheckSourceSuccess(lines)
9832
9833 # Test for a final class variable
9834 lines =<< trim END
9835 vim9script
9836 class A
9837 static final s1: string = "abc"
9838 endclass
9839 assert_equal('abc', A.s1)
9840 END
9841 v9.CheckSourceSuccess(lines)
9842
9843 # Test for changing a final class variable from a class function
9844 lines =<< trim END
9845 vim9script
9846 class A
9847 static final s1: string = "abc"
9848 static def Foo()
9849 s1 = "def"
9850 enddef
9851 endclass
9852 A.Foo()
9853 END
9854 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9855
9856 # Test for changing a public final class variable at script level
9857 lines =<< trim END
9858 vim9script
9859 class A
9860 public static final s1: string = "abc"
9861 endclass
9862 assert_equal('abc', A.s1)
9863 A.s1 = 'def'
9864 END
9865 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9866
9867 # Test for changing a public final class variable from a class function
9868 lines =<< trim END
9869 vim9script
9870 class A
9871 public static final s1: string = "abc"
9872 static def Foo()
9873 s1 = "def"
9874 enddef
9875 endclass
9876 A.Foo()
9877 END
9878 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9879
9880 # Test for changing a public final class variable from a function
9881 lines =<< trim END
9882 vim9script
9883 class A
9884 public static final s1: string = "abc"
9885 endclass
9886 def Foo()
9887 A.s1 = 'def'
9888 enddef
9889 defcompile
9890 END
9891 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9892
9893 # Test for using a final variable of composite type
9894 lines =<< trim END
9895 vim9script
9896 class A
9897 public final l: list<number>
9898 def new()
9899 this.l = [1, 2]
9900 enddef
9901 def Foo()
9902 this.l[0] = 3
9903 this.l->add(4)
9904 enddef
9905 endclass
9906 var a = A.new()
9907 assert_equal([1, 2], a.l)
9908 a.Foo()
9909 assert_equal([3, 2, 4], a.l)
9910 END
9911 v9.CheckSourceSuccess(lines)
9912
9913 # Test for changing a final variable of composite type from another object
9914 # function
9915 lines =<< trim END
9916 vim9script
9917 class A
9918 public final l: list<number> = [1, 2]
9919 def Foo()
9920 this.l = [3, 4]
9921 enddef
9922 endclass
9923 var a = A.new()
9924 a.Foo()
9925 END
9926 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9927
9928 # Test for modifying a final variable of composite type at script level
9929 lines =<< trim END
9930 vim9script
9931 class A
9932 public final l: list<number> = [1, 2]
9933 endclass
9934 var a = A.new()
9935 a.l[0] = 3
9936 a.l->add(4)
9937 assert_equal([3, 2, 4], a.l)
9938 END
9939 v9.CheckSourceSuccess(lines)
9940
9941 # Test for modifying a final variable of composite type from a function
9942 lines =<< trim END
9943 vim9script
9944 class A
9945 public final l: list<number> = [1, 2]
9946 endclass
9947 def Foo()
9948 var a = A.new()
9949 a.l[0] = 3
9950 a.l->add(4)
9951 assert_equal([3, 2, 4], a.l)
9952 enddef
9953 Foo()
9954 END
9955 v9.CheckSourceSuccess(lines)
9956
9957 # Test for modifying a final variable of composite type from another object
9958 # function
9959 lines =<< trim END
9960 vim9script
9961 class A
9962 public final l: list<number> = [1, 2]
9963 def Foo()
9964 this.l[0] = 3
9965 this.l->add(4)
9966 enddef
9967 endclass
9968 var a = A.new()
9969 a.Foo()
9970 assert_equal([3, 2, 4], a.l)
9971 END
9972 v9.CheckSourceSuccess(lines)
9973
9974 # Test for assigning a new value to a final variable of composite type at
9975 # script level
9976 lines =<< trim END
9977 vim9script
9978 class A
9979 public final l: list<number> = [1, 2]
9980 endclass
9981 var a = A.new()
9982 a.l = [3, 4]
9983 END
9984 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
9985
9986 # Test for assigning a new value to a final variable of composite type from
9987 # another object function
9988 lines =<< trim END
9989 vim9script
9990 class A
9991 public final l: list<number> = [1, 2]
9992 def Foo()
9993 this.l = [3, 4]
9994 enddef
9995 endclass
9996 var a = A.new()
9997 a.Foo()
9998 END
9999 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10000
10001 # Test for assigning a new value to a final variable of composite type from
10002 # another function
10003 lines =<< trim END
10004 vim9script
10005 class A
10006 public final l: list<number> = [1, 2]
10007 endclass
10008 def Foo()
10009 var a = A.new()
10010 a.l = [3, 4]
10011 enddef
10012 Foo()
10013 END
10014 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10015
10016 # Error case: Use 'final' with just a variable name
10017 lines =<< trim END
10018 vim9script
10019 class A
10020 final foo
10021 endclass
10022 var a = A.new()
10023 END
10024 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10025
10026 # Error case: Use 'final' followed by 'public'
10027 lines =<< trim END
10028 vim9script
10029 class A
10030 final public foo: number
10031 endclass
10032 var a = A.new()
10033 END
10034 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10035
10036 # Error case: Use 'final' followed by 'static'
10037 lines =<< trim END
10038 vim9script
10039 class A
10040 final static foo: number
10041 endclass
10042 var a = A.new()
10043 END
10044 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10045
10046 # Error case: 'final' cannot be used in an interface
10047 lines =<< trim END
10048 vim9script
10049 interface A
10050 final foo: number = 10
10051 endinterface
10052 END
10053 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
10054
10055 # Error case: 'final' not supported for an object method
10056 lines =<< trim END
10057 vim9script
10058 class A
10059 final def Foo()
10060 enddef
10061 endclass
10062 END
10063 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10064
10065 # Error case: 'final' not supported for a class method
10066 lines =<< trim END
10067 vim9script
10068 class A
10069 static final def Foo()
10070 enddef
10071 endclass
10072 END
10073 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10074enddef
10075
10076" Test for 'const' class and object variables
10077def Test_const_class_object_variable()
10078 # Test for changing a const object variable from an object function
10079 var lines =<< trim END
10080 vim9script
10081 class A
10082 const foo: string = "abc"
10083 def Foo()
10084 this.foo = "def"
10085 enddef
10086 endclass
10087 defcompile A.Foo
10088 END
10089 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
10090
10091 # Test for changing a const object variable from the 'new' function
10092 lines =<< trim END
10093 vim9script
10094 class A
10095 const s1: string
10096 const s2: string
10097 def new(this.s1)
10098 this.s2 = 'def'
10099 enddef
10100 endclass
10101 var a = A.new('abc')
10102 assert_equal('abc', a.s1)
10103 assert_equal('def', a.s2)
10104 END
10105 v9.CheckSourceSuccess(lines)
10106
10107 # Test for changing a const object variable from an object method called from
10108 # the 'new' function
10109 lines =<< trim END
10110 vim9script
10111 class A
10112 const s1: string = 'abc'
10113 def new()
10114 this.ChangeStr()
10115 enddef
10116 def ChangeStr()
10117 this.s1 = 'def'
10118 enddef
10119 endclass
10120 var a = A.new()
10121 END
10122 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10123
10124 # Test for a const class variable
10125 lines =<< trim END
10126 vim9script
10127 class A
10128 static const s1: string = "abc"
10129 endclass
10130 assert_equal('abc', A.s1)
10131 END
10132 v9.CheckSourceSuccess(lines)
10133
10134 # Test for changing a const class variable from a class function
10135 lines =<< trim END
10136 vim9script
10137 class A
10138 static const s1: string = "abc"
10139 static def Foo()
10140 s1 = "def"
10141 enddef
10142 endclass
10143 A.Foo()
10144 END
10145 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10146
10147 # Test for changing a public const class variable at script level
10148 lines =<< trim END
10149 vim9script
10150 class A
10151 public static const s1: string = "abc"
10152 endclass
10153 assert_equal('abc', A.s1)
10154 A.s1 = 'def'
10155 END
10156 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
10157
10158 # Test for changing a public const class variable from a class function
10159 lines =<< trim END
10160 vim9script
10161 class A
10162 public static const s1: string = "abc"
10163 static def Foo()
10164 s1 = "def"
10165 enddef
10166 endclass
10167 A.Foo()
10168 END
10169 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10170
10171 # Test for changing a public const class variable from a function
10172 lines =<< trim END
10173 vim9script
10174 class A
10175 public static const s1: string = "abc"
10176 endclass
10177 def Foo()
10178 A.s1 = 'def'
10179 enddef
10180 defcompile
10181 END
10182 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10183
10184 # Test for changing a const List item from an object function
10185 lines =<< trim END
10186 vim9script
10187 class A
10188 public const l: list<number>
10189 def new()
10190 this.l = [1, 2]
10191 enddef
10192 def Foo()
10193 this.l[0] = 3
10194 enddef
10195 endclass
10196 var a = A.new()
10197 assert_equal([1, 2], a.l)
10198 a.Foo()
10199 END
10200 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10201
10202 # Test for adding a value to a const List from an object function
10203 lines =<< trim END
10204 vim9script
10205 class A
10206 public const l: list<number>
10207 def new()
10208 this.l = [1, 2]
10209 enddef
10210 def Foo()
10211 this.l->add(3)
10212 enddef
10213 endclass
10214 var a = A.new()
10215 a.Foo()
10216 END
10217 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10218
10219 # Test for reassigning a const List from an object function
10220 lines =<< trim END
10221 vim9script
10222 class A
10223 public const l: list<number> = [1, 2]
10224 def Foo()
10225 this.l = [3, 4]
10226 enddef
10227 endclass
10228 var a = A.new()
10229 a.Foo()
10230 END
10231 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10232
10233 # Test for changing a const List item at script level
10234 lines =<< trim END
10235 vim9script
10236 class A
10237 public const l: list<number> = [1, 2]
10238 endclass
10239 var a = A.new()
10240 a.l[0] = 3
10241 END
10242 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10243
10244 # Test for adding a value to a const List item at script level
10245 lines =<< trim END
10246 vim9script
10247 class A
10248 public const l: list<number> = [1, 2]
10249 endclass
10250 var a = A.new()
10251 a.l->add(4)
10252 END
10253 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10254
10255 # Test for changing a const List item from a function
10256 lines =<< trim END
10257 vim9script
10258 class A
10259 public const l: list<number> = [1, 2]
10260 endclass
10261 def Foo()
10262 var a = A.new()
10263 a.l[0] = 3
10264 enddef
10265 Foo()
10266 END
10267 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
10268
10269 # Test for adding a value to a const List item from a function
10270 lines =<< trim END
10271 vim9script
10272 class A
10273 public const l: list<number> = [1, 2]
10274 endclass
10275 def Foo()
10276 var a = A.new()
10277 a.l->add(4)
10278 enddef
10279 Foo()
10280 END
10281 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
10282
10283 # Test for changing a const List item from an object method
10284 lines =<< trim END
10285 vim9script
10286 class A
10287 public const l: list<number> = [1, 2]
10288 def Foo()
10289 this.l[0] = 3
10290 enddef
10291 endclass
10292 var a = A.new()
10293 a.Foo()
10294 END
10295 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10296
10297 # Test for adding a value to a const List item from an object method
10298 lines =<< trim END
10299 vim9script
10300 class A
10301 public const l: list<number> = [1, 2]
10302 def Foo()
10303 this.l->add(4)
10304 enddef
10305 endclass
10306 var a = A.new()
10307 a.Foo()
10308 END
10309 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10310
10311 # Test for reassigning a const List object variable at script level
10312 lines =<< trim END
10313 vim9script
10314 class A
10315 public const l: list<number> = [1, 2]
10316 endclass
10317 var a = A.new()
10318 a.l = [3, 4]
10319 END
10320 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10321
10322 # Test for reassigning a const List object variable from an object method
10323 lines =<< trim END
10324 vim9script
10325 class A
10326 public const l: list<number> = [1, 2]
10327 def Foo()
10328 this.l = [3, 4]
10329 enddef
10330 endclass
10331 var a = A.new()
10332 a.Foo()
10333 END
10334 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10335
10336 # Test for reassigning a const List object variable from another function
10337 lines =<< trim END
10338 vim9script
10339 class A
10340 public const l: list<number> = [1, 2]
10341 endclass
10342 def Foo()
10343 var a = A.new()
10344 a.l = [3, 4]
10345 enddef
10346 Foo()
10347 END
10348 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10349
10350 # Error case: Use 'const' with just a variable name
10351 lines =<< trim END
10352 vim9script
10353 class A
10354 const foo
10355 endclass
10356 var a = A.new()
10357 END
10358 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10359
10360 # Error case: Use 'const' followed by 'public'
10361 lines =<< trim END
10362 vim9script
10363 class A
10364 const public foo: number
10365 endclass
10366 var a = A.new()
10367 END
10368 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10369
10370 # Error case: Use 'const' followed by 'static'
10371 lines =<< trim END
10372 vim9script
10373 class A
10374 const static foo: number
10375 endclass
10376 var a = A.new()
10377 END
10378 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10379
10380 # Error case: 'const' cannot be used in an interface
10381 lines =<< trim END
10382 vim9script
10383 interface A
10384 const foo: number = 10
10385 endinterface
10386 END
10387 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10388
10389 # Error case: 'const' not supported for an object method
10390 lines =<< trim END
10391 vim9script
10392 class A
10393 const def Foo()
10394 enddef
10395 endclass
10396 END
10397 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10398
10399 # Error case: 'const' not supported for a class method
10400 lines =<< trim END
10401 vim9script
10402 class A
10403 static const def Foo()
10404 enddef
10405 endclass
10406 END
10407 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10408enddef
10409
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010410" Test for compiling class/object methods using :defcompile
10411def Test_defcompile_class()
10412 # defcompile all the classes in the current script
10413 var lines =<< trim END
10414 vim9script
10415 class A
10416 def Foo()
10417 var i = 10
10418 enddef
10419 endclass
10420 class B
10421 def Bar()
10422 var i = 20
10423 xxx
10424 enddef
10425 endclass
10426 defcompile
10427 END
10428 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10429
10430 # defcompile a specific class
10431 lines =<< trim END
10432 vim9script
10433 class A
10434 def Foo()
10435 xxx
10436 enddef
10437 endclass
10438 class B
10439 def Bar()
10440 yyy
10441 enddef
10442 endclass
10443 defcompile B
10444 END
10445 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10446
10447 # defcompile a non-class
10448 lines =<< trim END
10449 vim9script
10450 class A
10451 def Foo()
10452 enddef
10453 endclass
10454 var X: list<number> = []
10455 defcompile X
10456 END
10457 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10458
10459 # defcompile a class twice
10460 lines =<< trim END
10461 vim9script
10462 class A
10463 def new()
10464 enddef
10465 endclass
10466 defcompile A
10467 defcompile A
10468 assert_equal('Function A.new does not need compiling', v:statusmsg)
10469 END
10470 v9.CheckSourceSuccess(lines)
10471
10472 # defcompile should not compile an imported class
10473 lines =<< trim END
10474 vim9script
10475 export class A
10476 def Foo()
10477 xxx
10478 enddef
10479 endclass
10480 END
10481 writefile(lines, 'Xdefcompileimport.vim', 'D')
10482 lines =<< trim END
10483 vim9script
10484
10485 import './Xdefcompileimport.vim'
10486 class B
10487 endclass
10488 defcompile
10489 END
10490 v9.CheckScriptSuccess(lines)
10491enddef
10492
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010493" Test for cases common to all the object builtin methods
10494def Test_object_builtin_method()
10495 var lines =<< trim END
10496 vim9script
10497 class A
10498 def abc()
10499 enddef
10500 endclass
10501 END
10502 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10503
10504 for funcname in ["len", "string", "empty"]
10505 lines =<< trim eval END
10506 vim9script
10507 class A
10508 static def {funcname}(): number
10509 enddef
10510 endclass
10511 END
10512 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10513 endfor
10514enddef
10515
10516" Test for using the empty() builtin method with an object
10517" This is a legacy function to use the test_garbagecollect_now() function.
10518func Test_object_empty()
10519 let lines =<< trim END
10520 vim9script
10521 class A
10522 def empty(): bool
10523 return true
10524 enddef
10525 endclass
10526
10527 def Foo()
10528 var afoo = A.new()
10529 assert_equal(true, empty(afoo))
10530 assert_equal(true, afoo->empty())
10531 enddef
10532
10533 var a = A.new()
10534 assert_equal(1, empty(a))
10535 assert_equal(1, a->empty())
10536 test_garbagecollect_now()
10537 assert_equal(1, empty(a))
10538 Foo()
10539 test_garbagecollect_now()
10540 Foo()
10541 END
10542 call v9.CheckSourceSuccess(lines)
10543
10544 " empty() should return 1 without a builtin method
10545 let lines =<< trim END
10546 vim9script
10547 class A
10548 endclass
10549
10550 def Foo()
10551 var afoo = A.new()
10552 assert_equal(1, empty(afoo))
10553 enddef
10554
10555 var a = A.new()
10556 assert_equal(1, empty(a))
10557 Foo()
10558 END
10559 call v9.CheckSourceSuccess(lines)
10560
10561 " Unsupported signature for the empty() method
10562 let lines =<< trim END
10563 vim9script
10564 class A
10565 def empty()
10566 enddef
10567 endclass
10568 END
10569 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10570
10571 " Error when calling the empty() method
10572 let lines =<< trim END
10573 vim9script
10574 class A
10575 def empty(): bool
10576 throw "Failed to check emptiness"
10577 enddef
10578 endclass
10579
10580 def Foo()
10581 var afoo = A.new()
10582 var i = empty(afoo)
10583 enddef
10584
10585 var a = A.new()
10586 assert_fails('empty(a)', 'Failed to check emptiness')
10587 assert_fails('Foo()', 'Failed to check emptiness')
10588 END
10589 call v9.CheckSourceSuccess(lines)
10590
10591 " call empty() using an object from a script
10592 let lines =<< trim END
10593 vim9script
10594 class A
10595 def empty(): bool
10596 return true
10597 enddef
10598 endclass
10599 var afoo = A.new()
10600 assert_equal(true, afoo.empty())
10601 END
10602 call v9.CheckSourceSuccess(lines)
10603
10604 " call empty() using an object from a method
10605 let lines =<< trim END
10606 vim9script
10607 class A
10608 def empty(): bool
10609 return true
10610 enddef
10611 endclass
10612 def Foo()
10613 var afoo = A.new()
10614 assert_equal(true, afoo.empty())
10615 enddef
10616 Foo()
10617 END
10618 call v9.CheckSourceSuccess(lines)
10619
10620 " call empty() using "this" from an object method
10621 let lines =<< trim END
10622 vim9script
10623 class A
10624 def empty(): bool
10625 return true
10626 enddef
10627 def Foo(): bool
10628 return this.empty()
10629 enddef
10630 endclass
10631 def Bar()
10632 var abar = A.new()
10633 assert_equal(true, abar.Foo())
10634 enddef
10635 Bar()
10636 END
10637 call v9.CheckSourceSuccess(lines)
10638
10639 " Call empty() from a derived object
10640 let lines =<< trim END
10641 vim9script
10642 class A
10643 def empty(): bool
10644 return false
10645 enddef
10646 endclass
10647 class B extends A
10648 def empty(): bool
10649 return true
10650 enddef
10651 endclass
10652 def Foo(afoo: A)
10653 assert_equal(true, empty(afoo))
10654 var bfoo = B.new()
10655 assert_equal(true, empty(bfoo))
10656 enddef
10657 var b = B.new()
10658 assert_equal(1, empty(b))
10659 Foo(b)
10660 END
10661 call v9.CheckSourceSuccess(lines)
10662
10663 " Invoking empty method using an interface
10664 let lines =<< trim END
10665 vim9script
10666 interface A
10667 def empty(): bool
10668 endinterface
10669 class B implements A
10670 def empty(): bool
10671 return false
10672 enddef
10673 endclass
10674 def Foo(a: A)
10675 assert_equal(false, empty(a))
10676 enddef
10677 var b = B.new()
10678 Foo(b)
10679 END
10680 call v9.CheckSourceSuccess(lines)
10681endfunc
10682
10683" Test for using the len() builtin method with an object
10684" This is a legacy function to use the test_garbagecollect_now() function.
10685func Test_object_length()
10686 let lines =<< trim END
10687 vim9script
10688 class A
10689 var mylen: number = 0
10690 def new(n: number)
10691 this.mylen = n
10692 enddef
10693 def len(): number
10694 return this.mylen
10695 enddef
10696 endclass
10697
10698 def Foo()
10699 var afoo = A.new(12)
10700 assert_equal(12, len(afoo))
10701 assert_equal(12, afoo->len())
10702 enddef
10703
10704 var a = A.new(22)
10705 assert_equal(22, len(a))
10706 assert_equal(22, a->len())
10707 test_garbagecollect_now()
10708 assert_equal(22, len(a))
10709 Foo()
10710 test_garbagecollect_now()
10711 Foo()
10712 END
10713 call v9.CheckSourceSuccess(lines)
10714
10715 " len() should return 0 without a builtin method
10716 let lines =<< trim END
10717 vim9script
10718 class A
10719 endclass
10720
10721 def Foo()
10722 var afoo = A.new()
10723 assert_equal(0, len(afoo))
10724 enddef
10725
10726 var a = A.new()
10727 assert_equal(0, len(a))
10728 Foo()
10729 END
10730 call v9.CheckSourceSuccess(lines)
10731
10732 " Unsupported signature for the len() method
10733 let lines =<< trim END
10734 vim9script
10735 class A
10736 def len()
10737 enddef
10738 endclass
10739 END
10740 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10741
10742 " Error when calling the len() method
10743 let lines =<< trim END
10744 vim9script
10745 class A
10746 def len(): number
10747 throw "Failed to compute length"
10748 enddef
10749 endclass
10750
10751 def Foo()
10752 var afoo = A.new()
10753 var i = len(afoo)
10754 enddef
10755
10756 var a = A.new()
10757 assert_fails('len(a)', 'Failed to compute length')
10758 assert_fails('Foo()', 'Failed to compute length')
10759 END
10760 call v9.CheckSourceSuccess(lines)
10761
10762 " call len() using an object from a script
10763 let lines =<< trim END
10764 vim9script
10765 class A
10766 def len(): number
10767 return 5
10768 enddef
10769 endclass
10770 var afoo = A.new()
10771 assert_equal(5, afoo.len())
10772 END
10773 call v9.CheckSourceSuccess(lines)
10774
10775 " call len() using an object from a method
10776 let lines =<< trim END
10777 vim9script
10778 class A
10779 def len(): number
10780 return 5
10781 enddef
10782 endclass
10783 def Foo()
10784 var afoo = A.new()
10785 assert_equal(5, afoo.len())
10786 enddef
10787 Foo()
10788 END
10789 call v9.CheckSourceSuccess(lines)
10790
10791 " call len() using "this" from an object method
10792 let lines =<< trim END
10793 vim9script
10794 class A
10795 def len(): number
10796 return 8
10797 enddef
10798 def Foo(): number
10799 return this.len()
10800 enddef
10801 endclass
10802 def Bar()
10803 var abar = A.new()
10804 assert_equal(8, abar.Foo())
10805 enddef
10806 Bar()
10807 END
10808 call v9.CheckSourceSuccess(lines)
10809
10810 " Call len() from a derived object
10811 let lines =<< trim END
10812 vim9script
10813 class A
10814 def len(): number
10815 return 10
10816 enddef
10817 endclass
10818 class B extends A
10819 def len(): number
10820 return 20
10821 enddef
10822 endclass
10823 def Foo(afoo: A)
10824 assert_equal(20, len(afoo))
10825 var bfoo = B.new()
10826 assert_equal(20, len(bfoo))
10827 enddef
10828 var b = B.new()
10829 assert_equal(20, len(b))
10830 Foo(b)
10831 END
10832 call v9.CheckSourceSuccess(lines)
10833
10834 " Invoking len method using an interface
10835 let lines =<< trim END
10836 vim9script
10837 interface A
10838 def len(): number
10839 endinterface
10840 class B implements A
10841 def len(): number
10842 return 123
10843 enddef
10844 endclass
10845 def Foo(a: A)
10846 assert_equal(123, len(a))
10847 enddef
10848 var b = B.new()
10849 Foo(b)
10850 END
10851 call v9.CheckSourceSuccess(lines)
10852endfunc
10853
10854" Test for using the string() builtin method with an object
10855" This is a legacy function to use the test_garbagecollect_now() function.
10856func Test_object_string()
10857 let lines =<< trim END
10858 vim9script
10859 class A
10860 var name: string
10861 def string(): string
10862 return this.name
10863 enddef
10864 endclass
10865
10866 def Foo()
10867 var afoo = A.new("foo-A")
10868 assert_equal('foo-A', string(afoo))
10869 assert_equal('foo-A', afoo->string())
10870 enddef
10871
10872 var a = A.new("script-A")
10873 assert_equal('script-A', string(a))
10874 assert_equal('script-A', a->string())
10875 assert_equal(['script-A'], execute('echo a')->split("\n"))
10876 test_garbagecollect_now()
10877 assert_equal('script-A', string(a))
10878 Foo()
10879 test_garbagecollect_now()
10880 Foo()
10881 END
10882 call v9.CheckSourceSuccess(lines)
10883
10884 " string() should return "object of A {}" without a builtin method
10885 let lines =<< trim END
10886 vim9script
10887 class A
10888 endclass
10889
10890 def Foo()
10891 var afoo = A.new()
10892 assert_equal('object of A {}', string(afoo))
10893 enddef
10894
10895 var a = A.new()
10896 assert_equal('object of A {}', string(a))
10897 Foo()
10898 END
10899 call v9.CheckSourceSuccess(lines)
10900
10901 " Unsupported signature for the string() method
10902 let lines =<< trim END
10903 vim9script
10904 class A
10905 def string()
10906 enddef
10907 endclass
10908 END
10909 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
10910
10911 " Error when calling the string() method
10912 let lines =<< trim END
10913 vim9script
10914 class A
10915 def string(): string
10916 throw "Failed to get text"
10917 enddef
10918 endclass
10919
10920 def Foo()
10921 var afoo = A.new()
10922 var i = string(afoo)
10923 enddef
10924
10925 var a = A.new()
10926 assert_fails('string(a)', 'Failed to get text')
10927 assert_fails('Foo()', 'Failed to get text')
10928 END
10929 call v9.CheckSourceSuccess(lines)
10930
10931 " call string() using an object from a script
10932 let lines =<< trim END
10933 vim9script
10934 class A
10935 def string(): string
10936 return 'A'
10937 enddef
10938 endclass
10939 var afoo = A.new()
10940 assert_equal('A', afoo.string())
10941 END
10942 call v9.CheckSourceSuccess(lines)
10943
10944 " call string() using an object from a method
10945 let lines =<< trim END
10946 vim9script
10947 class A
10948 def string(): string
10949 return 'A'
10950 enddef
10951 endclass
10952 def Foo()
10953 var afoo = A.new()
10954 assert_equal('A', afoo.string())
10955 enddef
10956 Foo()
10957 END
10958 call v9.CheckSourceSuccess(lines)
10959
10960 " call string() using "this" from an object method
10961 let lines =<< trim END
10962 vim9script
10963 class A
10964 def string(): string
10965 return 'A'
10966 enddef
10967 def Foo(): string
10968 return this.string()
10969 enddef
10970 endclass
10971 def Bar()
10972 var abar = A.new()
10973 assert_equal('A', abar.string())
10974 enddef
10975 Bar()
10976 END
10977 call v9.CheckSourceSuccess(lines)
10978
10979 " Call string() from a derived object
10980 let lines =<< trim END
10981 vim9script
10982 class A
10983 def string(): string
10984 return 'A'
10985 enddef
10986 endclass
10987 class B extends A
10988 def string(): string
10989 return 'B'
10990 enddef
10991 endclass
10992 def Foo(afoo: A)
10993 assert_equal('B', string(afoo))
10994 var bfoo = B.new()
10995 assert_equal('B', string(bfoo))
10996 enddef
10997 var b = B.new()
10998 assert_equal('B', string(b))
10999 Foo(b)
11000 END
11001 call v9.CheckSourceSuccess(lines)
11002
11003 " Invoking string method using an interface
11004 let lines =<< trim END
11005 vim9script
11006 interface A
11007 def string(): string
11008 endinterface
11009 class B implements A
11010 def string(): string
11011 return 'B'
11012 enddef
11013 endclass
11014 def Foo(a: A)
11015 assert_equal('B', string(a))
11016 enddef
11017 var b = B.new()
11018 Foo(b)
11019 END
11020 call v9.CheckSourceSuccess(lines)
11021endfunc
11022
Ernie Rael9d779c52024-07-07 20:41:44 +020011023" Test for using the string() builtin method with an object's method
11024def Test_method_string()
11025 var lines =<< trim END
11026 vim9script
11027 class A
11028 def F()
11029 enddef
11030 endclass
11031 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
11032 END
11033 v9.CheckScriptSuccess(lines)
11034enddef
11035
11036
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010011037" Test for using a class in the class definition
11038def Test_Ref_Class_Within_Same_Class()
11039 var lines =<< trim END
11040 vim9script
11041 class A
11042 var n: number = 0
11043 def Equals(other: A): bool
11044 return this.n == other.n
11045 enddef
11046 endclass
11047
11048 var a1 = A.new(10)
11049 var a2 = A.new(10)
11050 var a3 = A.new(20)
11051 assert_equal(true, a1.Equals(a2))
11052 assert_equal(false, a2.Equals(a3))
11053 END
11054 v9.CheckScriptSuccess(lines)
11055
11056 lines =<< trim END
11057 vim9script
11058
11059 class Foo
11060 var num: number
11061 def Clone(): Foo
11062 return Foo.new(this.num)
11063 enddef
11064 endclass
11065
11066 var f1 = Foo.new(1)
11067
11068 def F()
11069 var f2: Foo = f1.Clone()
11070 assert_equal(false, f2 is f1)
11071 assert_equal(true, f2.num == f1.num)
11072 enddef
11073 F()
11074
11075 var f3: Foo = f1.Clone()
11076 assert_equal(false, f3 is f1)
11077 assert_equal(true, f3.num == f1.num)
11078 END
11079 v9.CheckScriptSuccess(lines)
11080
11081 # Test for trying to use a class to extend when defining the same class
11082 lines =<< trim END
11083 vim9script
11084 class A extends A
11085 endclass
11086 END
11087 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
11088
11089 # Test for trying to use a class to implement when defining the same class
11090 lines =<< trim END
11091 vim9script
11092 class A implements A
11093 endclass
11094 END
11095 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
11096enddef
11097
Ernie Raelf0e69142024-06-22 11:12:00 +020011098" Test for comparing a class referencing itself
11099def Test_Object_Compare_With_Recursive_Class_Ref()
11100 var lines =<< trim END
11101 vim9script
11102
11103 class C
11104 public var nest: C
11105 endclass
11106
11107 var o1 = C.new()
11108 o1.nest = o1
11109
11110 var result = o1 == o1
11111 assert_equal(true, result)
11112 END
11113 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020011114
11115 lines =<< trim END
11116 vim9script
11117
11118 class C
11119 public var nest: C
11120 endclass
11121 var o1 = C.new()
11122 var o2 = C.new(C.new())
11123
11124 var result = o1 == o2
11125 assert_equal(false, result)
11126 END
11127 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020011128
11129 lines =<< trim END
11130 vim9script
11131 class C
11132 var nest1: C
11133 var nest2: C
11134 def Init(n1: C, n2: C)
11135 this.nest1 = n1
11136 this.nest2 = n2
11137 enddef
11138 endclass
11139
11140 var o1 = C.new()
11141 var o2 = C.new()
11142 o1.Init(o1, o2)
11143 o2.Init(o2, o1)
11144
11145 var result = o1 == o2
11146 assert_equal(true, result)
11147 END
11148 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020011149enddef
11150
Ernie Raelf3975492024-07-06 11:44:37 +020011151" Test for comparing a class with nesting objects
11152def Test_Object_Compare_With_Nesting_Objects()
11153 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
11154 # return the compare is equal.
11155 # Test that limit
11156
11157 var lines =<< trim END
11158 vim9script
11159 class C
11160 public var n: number
11161 public var nest: C
11162
11163 # Create a "C" that chains/nests to indicated depth.
11164 # return {head: firstC, tail: lastC}
11165 static def CreateNested(depth: number): dict<C>
11166 var first = C.new(1, null_object)
11167 var last = first
11168 for i in range(2, depth)
11169 last.nest = C.new(i, null_object)
11170 last = last.nest
11171 endfor
11172 return {head: first, tail: last}
11173 enddef
11174
11175 # Return pointer to nth item in chain.
11176 def GetLink(depth: number): C
11177 var count = 1
11178 var p: C = this
11179 while count < depth
11180 p = p.nest
11181 if p == null
11182 throw "too deep"
11183 endif
11184 count += 1
11185 endwhile
11186 return p
11187 enddef
11188
11189 # Return the length of the chain
11190 def len(): number
11191 var count = 1
11192 var p: C = this
11193 while p.nest != null
11194 p = p.nest
11195 count += 1
11196 endwhile
11197 return count
11198 enddef
11199 endclass
11200
11201 var chain = C.CreateNested(3)
11202 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
11203 assert_equal(s, string(chain.head))
11204 assert_equal(3, chain.head->len())
11205
11206 var chain1 = C.CreateNested(100)
11207 var chain2 = C.CreateNested(100)
11208 assert_true(chain1.head == chain2.head)
11209
11210 # modify the tail of chain2, compare not equal
11211 chain2.tail.n = 123456
11212 assert_true(chain1.head != chain2.head)
11213
11214 # a tail of a different length compares not equal
11215 chain2 = C.CreateNested(101)
11216 assert_true(chain1.head != chain2.head)
11217
11218 chain1 = C.CreateNested(1000)
11219 chain2 = C.CreateNested(1000)
11220 assert_true(chain1.head == chain2.head)
11221
11222 # modify the tail of chain2, compare not equal
11223 chain2.tail.n = 123456
11224 assert_true(chain1.head != chain2.head)
11225
11226 # try a chain longer that the limit
11227 chain1 = C.CreateNested(1001)
11228 chain2 = C.CreateNested(1001)
11229 assert_true(chain1.head == chain2.head)
11230
11231 # modify the tail, but still equal
11232 chain2.tail.n = 123456
11233 assert_true(chain1.head == chain2.head)
11234
11235 # remove 2 items from front, shorten the chain by two.
11236 chain1.head = chain1.head.GetLink(3)
11237 chain2.head = chain2.head.GetLink(3)
11238 assert_equal(3, chain1.head.n)
11239 assert_equal(3, chain2.head.n)
11240 assert_equal(999, chain1.head->len())
11241 assert_equal(999, chain2.head->len())
11242 # Now less than the limit, compare not equal
11243 assert_true(chain1.head != chain2.head)
11244 END
11245 v9.CheckScriptSuccess(lines)
11246enddef
11247
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011248" Test for using a compound operator from a lambda function in an object method
11249def Test_compound_op_in_objmethod_lambda()
11250 # Test using the "+=" operator
11251 var lines =<< trim END
11252 vim9script
11253 class A
11254 var n: number = 10
11255 def Foo()
11256 var Fn = () => {
11257 this.n += 1
11258 }
11259 Fn()
11260 enddef
11261 endclass
11262
11263 var a = A.new()
11264 a.Foo()
11265 assert_equal(11, a.n)
11266 END
11267 v9.CheckScriptSuccess(lines)
11268
11269 # Test using the "..=" operator
11270 lines =<< trim END
11271 vim9script
11272 class A
11273 var s: string = "a"
11274 def Foo()
11275 var Fn = () => {
11276 this.s ..= "a"
11277 }
11278 Fn()
11279 enddef
11280 endclass
11281
11282 var a = A.new()
11283 a.Foo()
11284 a.Foo()
11285 assert_equal("aaa", a.s)
11286 END
11287 v9.CheckScriptSuccess(lines)
11288enddef
11289
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011290" Test for using test_refcount() with a class and an object
11291def Test_class_object_refcount()
11292 var lines =<< trim END
11293 vim9script
11294 class A
11295 endclass
11296 var a: A = A.new()
11297 assert_equal(2, test_refcount(A))
11298 assert_equal(1, test_refcount(a))
11299 var b = a
11300 assert_equal(2, test_refcount(A))
11301 assert_equal(2, test_refcount(a))
11302 assert_equal(2, test_refcount(b))
11303 END
11304 v9.CheckScriptSuccess(lines)
11305enddef
11306
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011307" call a lambda function in one object from another object
11308def Test_lambda_invocation_across_classes()
11309 var lines =<< trim END
11310 vim9script
11311 class A
11312 var s: string = "foo"
11313 def GetFn(): func
11314 var Fn = (): string => {
11315 return this.s
11316 }
11317 return Fn
11318 enddef
11319 endclass
11320
11321 class B
11322 var s: string = "bar"
11323 def GetFn(): func
11324 var a = A.new()
11325 return a.GetFn()
11326 enddef
11327 endclass
11328
11329 var b = B.new()
11330 var Fn = b.GetFn()
11331 assert_equal("foo", Fn())
11332 END
11333 v9.CheckScriptSuccess(lines)
11334enddef
11335
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011336" Test for using a class member which is an object of the current class
11337def Test_current_class_object_class_member()
11338 var lines =<< trim END
11339 vim9script
11340 class A
11341 public static var obj1: A = A.new(10)
11342 var n: number
11343 endclass
11344 defcompile
11345 assert_equal(10, A.obj1.n)
11346 END
11347 v9.CheckScriptSuccess(lines)
11348enddef
11349
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011350" Test for updating a base class variable from a base class method without the
11351" class name. This used to crash Vim (Github issue #14352).
11352def Test_use_base_class_variable_from_base_class_method()
11353 var lines =<< trim END
11354 vim9script
11355
11356 class DictKeyClass
11357 static var _obj_id_count = 1
11358 def _GenerateKey()
11359 _obj_id_count += 1
11360 enddef
11361 static def GetIdCount(): number
11362 return _obj_id_count
11363 enddef
11364 endclass
11365
11366 class C extends DictKeyClass
11367 def F()
11368 this._GenerateKey()
11369 enddef
11370 endclass
11371
11372 C.new().F()
11373 assert_equal(2, DictKeyClass.GetIdCount())
11374 END
11375 v9.CheckScriptSuccess(lines)
11376enddef
11377
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011378" Test for accessing protected funcref object and class variables
11379def Test_protected_funcref()
11380 # protected funcref object variable
11381 var lines =<< trim END
11382 vim9script
11383 class Test1
11384 const _Id: func(any): any = (v) => v
11385 endclass
11386 var n = Test1.new()._Id(1)
11387 END
11388 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11389
11390 # protected funcref class variable
11391 lines =<< trim END
11392 vim9script
11393 class Test2
11394 static const _Id: func(any): any = (v) => v
11395 endclass
11396 var n = Test2._Id(2)
11397 END
11398 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11399enddef
11400
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011401" Test for using lambda block in classes
11402def Test_lambda_block_in_class()
11403 # This used to crash Vim
11404 var lines =<< trim END
11405 vim9script
11406 class IdClass1
11407 const Id: func(number): number = (num: number): number => {
11408 # Return a ID
11409 return num * 10
11410 }
11411 endclass
11412 var id = IdClass1.new()
11413 assert_equal(20, id.Id(2))
11414 END
11415 v9.CheckScriptSuccess(lines)
11416
11417 # This used to crash Vim
11418 lines =<< trim END
11419 vim9script
11420 class IdClass2
11421 static const Id: func(number): number = (num: number): number => {
11422 # Return a ID
11423 return num * 2
11424 }
11425 endclass
11426 assert_equal(16, IdClass2.Id(8))
11427 END
11428 v9.CheckScriptSuccess(lines)
11429enddef
11430
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011431" Test for defcompiling an abstract method
11432def Test_abstract_method_defcompile()
11433 # Compile an abstract class with abstract object methods
11434 var lines =<< trim END
11435 vim9script
11436 abstract class A
11437 abstract def Foo(): string
11438 abstract def Bar(): list<string>
11439 endclass
11440 defcompile
11441 END
11442 v9.CheckScriptSuccess(lines)
11443
11444 # Compile a concrete object method in an abstract class
11445 lines =<< trim END
11446 vim9script
11447 abstract class A
11448 abstract def Foo(): string
11449 abstract def Bar(): list<string>
11450 def Baz(): string
11451 pass
11452 enddef
11453 endclass
11454 defcompile
11455 END
11456 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11457
11458 # Compile a concrete class method in an abstract class
11459 lines =<< trim END
11460 vim9script
11461 abstract class A
11462 abstract def Foo(): string
11463 abstract def Bar(): list<string>
11464 static def Baz(): string
11465 pass
11466 enddef
11467 endclass
11468 defcompile
11469 END
11470 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11471enddef
11472
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011473" Test for defining a class in a function
11474def Test_class_definition_in_a_function()
11475 var lines =<< trim END
11476 vim9script
11477 def Foo()
11478 class A
11479 endclass
11480 enddef
11481 defcompile
11482 END
11483 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11484enddef
11485
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011486" Test for using [] with a class and an object
11487def Test_class_object_index()
11488 var lines =<< trim END
11489 vim9script
11490 class A
11491 endclass
11492 A[10] = 1
11493 END
11494 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11495
11496 lines =<< trim END
11497 vim9script
11498 class A
11499 endclass
11500 var a = A.new()
11501 a[10] = 1
11502 END
11503 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11504enddef
11505
LemonBoyf4af3312024-07-04 13:43:12 +020011506def Test_class_member_init_typecheck()
11507 # Ensure the class member is assigned its declared type.
11508 var lines =<< trim END
11509 vim9script
11510 class S
11511 static var l: list<string> = []
11512 endclass
11513 S.l->add(123)
11514 END
11515 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11516
11517 # Ensure the initializer value and the declared type match.
11518 lines =<< trim END
11519 vim9script
11520 class S
11521 var l: list<string> = [1, 2, 3]
11522 endclass
11523 var o = S.new()
11524 END
11525 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11526
11527 # Ensure the class member is assigned its declared type.
11528 lines =<< trim END
11529 vim9script
11530 class S
11531 var l: list<string> = []
11532 endclass
11533 var o = S.new()
11534 o.l->add(123)
11535 END
11536 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11537enddef
11538
LemonBoy50d48542024-07-04 17:03:17 +020011539def Test_class_cast()
11540 var lines =<< trim END
11541 vim9script
11542 class A
11543 endclass
11544 class B extends A
11545 var mylen: number
11546 endclass
11547 def F(o: A): number
11548 return (<B>o).mylen
11549 enddef
11550
11551 defcompile F
11552 END
11553 v9.CheckScriptSuccess(lines)
11554enddef
11555
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011556" Test for using a variable of type "any" with an object
11557def Test_any_obj_var_type()
11558 var lines =<< trim END
11559 vim9script
11560 class A
11561 var name: string = "foobar"
11562 def Foo(): string
11563 return "func foo"
11564 enddef
11565 endclass
11566
11567 def CheckVals(x: any)
11568 assert_equal("foobar", x.name)
11569 assert_equal("func foo", x.Foo())
11570 enddef
11571
11572 var a = A.new()
11573 CheckVals(a)
11574 END
11575 v9.CheckScriptSuccess(lines)
11576
11577 # Try to set a non-existing variable
11578 lines =<< trim END
11579 vim9script
11580 class A
11581 var name: string = "foobar"
11582 endclass
11583
11584 def SetNonExistingVar(x: any)
11585 x.bar = [1, 2, 3]
11586 enddef
11587
11588 var a = A.new()
11589 SetNonExistingVar(a)
11590 END
11591 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11592
11593 # Try to read a non-existing variable
11594 lines =<< trim END
11595 vim9script
11596 class A
11597 var name: string = "foobar"
11598 endclass
11599
11600 def GetNonExistingVar(x: any)
11601 var i: dict<any> = x.bar
11602 enddef
11603
11604 var a = A.new()
11605 GetNonExistingVar(a)
11606 END
11607 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11608
11609 # Try to invoke a non-existing method
11610 lines =<< trim END
11611 vim9script
11612 class A
11613 def Foo(): number
11614 return 10
11615 enddef
11616 endclass
11617
11618 def CallNonExistingMethod(x: any)
11619 var i: number = x.Bar()
11620 enddef
11621
11622 var a = A.new()
11623 CallNonExistingMethod(a)
11624 END
11625 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11626
11627 # Use an object which is a Dict value
11628 lines =<< trim END
11629 vim9script
11630 class Foo
11631 def Bar(): number
11632 return 369
11633 enddef
11634 endclass
11635
11636 def GetValue(FooDict: dict<any>): number
11637 var n: number = 0
11638 for foo in values(FooDict)
11639 n += foo.Bar()
11640 endfor
11641 return n
11642 enddef
11643
11644 var d = {'x': Foo.new()}
11645 assert_equal(369, GetValue(d))
11646 END
11647 v9.CheckScriptSuccess(lines)
11648
zeertzjqd32bf0a2024-12-17 20:55:13 +010011649 # Nested data. Object containing a Dict containing another Object.
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011650 lines =<< trim END
11651 vim9script
11652 class Context
11653 public var state: dict<any> = {}
11654 endclass
11655
11656 class Metadata
11657 public var value = 0
11658 endclass
11659
11660 var ctx = Context.new()
11661 ctx.state["meta"] = Metadata.new(2468)
11662
11663 const foo = ctx.state.meta.value
11664
11665 def F(): number
11666 const bar = ctx.state.meta.value
11667 return bar
11668 enddef
11669
11670 assert_equal(2468, F())
11671 END
11672 v9.CheckScriptSuccess(lines)
11673
11674 # Accessing an object from a method inside the class using any type
11675 lines =<< trim END
11676 vim9script
11677 class C
11678 def _G(): string
11679 return '_G'
11680 enddef
11681 static def S(o_any: any): string
11682 return o_any._G()
11683 enddef
11684 endclass
11685
11686 var o1 = C.new()
11687 assert_equal('_G', C.S(o1))
11688 END
11689 v9.CheckScriptSuccess(lines)
11690
11691 # Modifying an object private variable from a method in another class using
11692 # any type
11693 lines =<< trim END
11694 vim9script
11695
11696 class A
11697 var num = 10
11698 endclass
11699
11700 class B
11701 def SetVal(x: any)
11702 x.num = 20
11703 enddef
11704 endclass
11705
11706 var a = A.new()
11707 var b = B.new()
11708 b.SetVal(a)
11709 END
11710 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11711
11712 # Accessing a object protected variable from a method in another class using
11713 # any type
11714 lines =<< trim END
11715 vim9script
11716
11717 class A
11718 var _num = 10
11719 endclass
11720
11721 class B
11722 def GetVal(x: any): number
11723 return x._num
11724 enddef
11725 endclass
11726
11727 var a = A.new()
11728 var b = B.new()
11729 var i = b.GetVal(a)
11730 END
11731 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11732
11733 # Accessing an object returned from an imported function and class
11734 lines =<< trim END
11735 vim9script
11736 export class Foo
11737 public var name: string
11738 endclass
11739
11740 export def ReturnFooObject(): Foo
11741 var r = Foo.new('star')
11742 return r
11743 enddef
11744 END
11745 writefile(lines, 'Xanyvar1.vim', 'D')
11746
11747 lines =<< trim END
11748 vim9script
11749
11750 import './Xanyvar1.vim'
11751
11752 def GetName(): string
11753 var whatever = Xanyvar1.ReturnFooObject()
11754 return whatever.name
11755 enddef
11756
11757 assert_equal('star', GetName())
11758 END
11759 v9.CheckScriptSuccess(lines)
11760
11761 # Try to modify a private object variable using a variable of type "any"
11762 lines =<< trim END
11763 vim9script
11764
11765 class Foo
11766 var n: number = 10
11767 endclass
11768 def Fn(x: any)
11769 x.n = 20
11770 enddef
11771 var a = Foo.new()
11772 Fn(a)
11773 END
11774 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11775
11776 # Try to read a protected object variable using a variable of type "any"
11777 lines =<< trim END
11778 vim9script
11779
11780 class Foo
11781 var _n: number = 10
11782 endclass
11783 def Fn(x: any): number
11784 return x._n
11785 enddef
11786
11787 var a = Foo.new()
11788 Fn(a)
11789 END
11790 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11791
11792 # Read a protected object variable using a variable of type "any" in an object
11793 # method
11794 lines =<< trim END
11795 vim9script
11796
11797 class Foo
11798 var _n: number = 10
11799 def Fn(x: any): number
11800 return x._n
11801 enddef
11802 endclass
11803
11804 var a = Foo.new()
11805 assert_equal(10, a.Fn(a))
11806 END
11807 v9.CheckScriptSuccess(lines)
11808
11809 # Try to call a protected object method using a "any" type variable
11810 lines =<< trim END
11811 vim9script
11812
11813 class Foo
11814 def _GetVal(): number
11815 return 234
11816 enddef
11817 endclass
11818 def Fn(x: any): number
11819 return x._GetVal()
11820 enddef
11821
11822 var a = Foo.new()
11823 Fn(a)
11824 END
11825 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11826
11827 # Call a protected object method using a "any" type variable from another
11828 # object method
11829 lines =<< trim END
11830 vim9script
11831
11832 class Foo
11833 def _GetVal(): number
11834 return 234
11835 enddef
11836 def FooVal(x: any): number
11837 return x._GetVal()
11838 enddef
11839 endclass
11840
11841 var a = Foo.new()
11842 assert_equal(234, a.FooVal(a))
11843 END
11844 v9.CheckScriptSuccess(lines)
11845
11846 # Method chaining
11847 lines =<< trim END
11848 vim9script
11849
11850 export class T
11851 var id: number = 268
11852 def F(): any
11853 return this
11854 enddef
11855 endclass
11856
11857 def H()
11858 var a = T.new().F().F()
11859 assert_equal(268, a.id)
11860 enddef
11861 H()
11862
11863 var b: T = T.new().F().F()
11864 assert_equal(268, b.id)
11865 END
11866 v9.CheckScriptSuccess(lines)
11867
11868 # Using a null object to access a member variable
11869 lines =<< trim END
11870 vim9script
11871 def Fn(x: any): number
11872 return x.num
11873 enddef
11874
11875 Fn(null_object)
11876 END
11877 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11878
11879 # Using a null object to invoke a method
11880 lines =<< trim END
11881 vim9script
11882 def Fn(x: any)
11883 x.Foo()
11884 enddef
11885
11886 Fn(null_object)
11887 END
11888 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
Yegappan Lakshmanane7984462024-11-12 21:03:00 +010011889
11890 # Try to change a const object variable using a "any" variable
11891 lines =<< trim END
11892 vim9script
11893 class A
11894 public const v1: number = 123
11895 endclass
11896
11897 def Fn(o: any)
11898 o.v1 = 321
11899 enddef
11900
11901 var a = A.new()
11902 Fn(a)
11903 END
11904 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11905
11906 # Try to change a final object variable using a "any" variable
11907 lines =<< trim END
11908 vim9script
11909 class A
11910 public final v1: number = 123
11911 endclass
11912
11913 def Fn(o: any)
11914 o.v1 = 321
11915 enddef
11916
11917 var a = A.new()
11918 Fn(a)
11919 END
11920 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11921
11922 # Assign a different type of value to an "any" type object variable
11923 lines =<< trim END
11924 vim9script
11925 class A
11926 public var v1: list<any> = [1, 2]
11927 endclass
11928
11929 def Fn(o: A)
11930 o.v1 = 'abc'
11931 enddef
11932
11933 var a = A.new()
11934 Fn(a)
11935 END
11936 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 1)
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011937enddef
11938
Yegappan Lakshmanan481992c2024-12-06 18:35:12 +010011939" Test for using an object method with mapnew()
11940def Test_mapnew_with_instance_method()
11941 var lines =<< trim END
11942 vim9script
11943
11944 class Foo
11945 var str: string
11946 var nums: list<number> = [1, 2, 3]
11947
11948 def InstanceMethod(n: number): string
11949 return this.str .. n
11950 enddef
11951
11952 def MapperMethod(idx: number, elem: number): string
11953 return elem->this.InstanceMethod()
11954 enddef
11955
11956 def MapTest()
11957 this.str = "foo"
11958 var l = ['foo1', 'foo2', 'foo3']
11959 assert_equal(l, this.nums->mapnew(this.MapperMethod))
11960 enddef
11961 endclass
11962
11963 Foo.new().MapTest()
11964 END
11965 v9.CheckSourceSuccess(lines)
11966
11967 # Error in the mapnew() function
11968 lines =<< trim END
11969 vim9script
11970
11971 class Foo
11972 var str: string
11973 var nums: list<number> = [1, 2, 3]
11974
11975 def InstanceMethod(n: number): string
11976 throw "InstanceMethod failed"
11977 enddef
11978
11979 def MapperMethod(idx: number, elem: number): string
11980 return elem->this.InstanceMethod()
11981 enddef
11982
11983 def MapTest()
11984 this.str = "foo"
11985 var caught_exception: bool = false
11986 try
11987 this.nums->mapnew(this.MapperMethod)
11988 catch /InstanceMethod failed/
11989 caught_exception = true
11990 endtry
11991 assert_true(caught_exception)
11992 enddef
11993 endclass
11994
11995 Foo.new().MapTest()
11996 END
11997 v9.CheckSourceSuccess(lines)
11998enddef
11999
Yegappan Lakshmananb0206e92024-12-30 09:52:16 +010012000" Test for using an object method in a method call.
12001def Test_use_object_method_in_a_method_call()
12002 var lines =<< trim END
12003 vim9script
12004
12005 class Foo
12006 def Cost(nums: list<number>): number
12007 return nums[0] * nums[1]
12008 enddef
12009
12010 def ShowCost(): string
12011 var g = [4, 5]
12012 return $"Cost is: {g->this.Cost()}"
12013 enddef
12014 endclass
12015
12016 var d = Foo.new()
12017 assert_equal('Cost is: 20', d.ShowCost())
12018 END
12019 v9.CheckSourceSuccess(lines)
12020
12021 # Test for using a non-existing object method in string interpolation
12022 lines =<< trim END
12023 vim9script
12024
12025 class Foo
12026 def Cost(nums: list<number>): number
12027 return nums[0] * nums[1]
12028 enddef
12029
12030 def ShowCost(): string
12031 var g = [4, 5]
12032 echo $"Cost is: {g->this.NewCost()}"
12033 enddef
12034 endclass
12035
12036 var d = Foo.new()
12037 d.ShowCost()
12038 END
12039 v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
12040enddef
12041
Yegappan Lakshmananb04af4c2025-01-03 10:50:08 +010012042" Test for referencing an object variable which is not yet initialized
12043def Test_uninitialized_object_var()
12044 var lines =<< trim END
12045 vim9script
12046 class Foo
12047 const two: number = Foo.Two(this)
12048 const one: number = 1
12049
12050 static def Two(that: Foo): number
12051 return that.one + 2
12052 enddef
12053 endclass
12054
12055 echo Foo.Two(Foo.new())
12056 END
12057 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
12058
12059 lines =<< trim END
12060 vim9script
12061 class Foo
12062 const one: number = Foo.One(this)
12063
12064 static def One(that: Foo): number
12065 return 1
12066 enddef
12067 endclass
12068
12069 assert_equal(1, Foo.One(Foo.new()))
12070 END
12071 v9.CheckSourceSuccess(lines)
12072
12073 lines =<< trim END
12074 vim9script
12075 class Foo
12076 const one: number = 1
12077 const two: number = Foo.Two(this)
12078
12079 static def Two(that: Foo): number
12080 return that.one + 1
12081 enddef
12082 endclass
12083
12084 assert_equal(2, Foo.Two(Foo.new()))
12085 END
12086 v9.CheckSourceSuccess(lines)
12087
12088 lines =<< trim END
12089 vim9script
12090 class Foo
12091 const Id: func(any): any = ((_) => (v) => v)(this)
12092
12093 static def Id(that: Foo): func(any): any
12094 return that.Id
12095 enddef
12096 endclass
12097
12098 assert_equal(5, Foo.Id(Foo.new())(5))
12099 assert_equal(7, Foo.new().Id(7))
12100 END
12101 v9.CheckSourceSuccess(lines)
12102
12103 lines =<< trim END
12104 vim9script
12105 class Foo
12106 const Id: func(any): any = ((that) => (_) => that)(this)
12107
12108 static def Id(that: Foo): func(any): any
12109 return that.Id
12110 enddef
12111 endclass
12112
12113 const Id0: func(any): any = Foo.Id(Foo.new())
12114 const Id1: func(any): any = Foo.new().Id
12115 END
12116 v9.CheckSourceSuccess(lines)
12117
12118 lines =<< trim END
12119 vim9script
12120 class Foo
12121 const Id: any = Foo.Id(this)
12122
12123 static def Id(that: Foo): any
12124 return that.Id
12125 enddef
12126 endclass
12127
12128 const Id2: any = Foo.Id(Foo.new())
12129 const Id3: any = Foo.new().Id
12130 END
12131 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
12132
12133 lines =<< trim END
12134 vim9script
12135
12136 class Foo
12137 var x: string = ''
12138 var Y: func(): string = () => this.x
12139 endclass
12140
12141 var foo = Foo.new('ok')
12142 assert_equal('ok', foo.Y())
12143 END
12144 v9.CheckSourceSuccess(lines)
12145
12146 lines =<< trim END
12147 vim9script
12148
12149 class Foo
12150 var x: string = this.x
12151 endclass
12152
12153 var foo = Foo.new('ok')
12154 END
12155 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
12156enddef
12157
Yegappan Lakshmanan2050dcc2025-01-06 18:34:49 +010012158" Test for initializing member variables of compound type in the constructor
12159def Test_constructor_init_compound_member_var()
12160 var lines =<< trim END
12161 vim9script
12162
12163 class Foo
12164 var v1: string = "aaa"
12165 var v2: list<number> = [1, 2]
12166 var v3: dict<string> = {a: 'a', b: 'b'}
12167 endclass
12168
12169 class Bar
12170 var v4: string = "bbb"
12171 var v5: Foo = Foo.new()
12172 var v6: list<number> = [1, 2]
12173 endclass
12174
12175 var b: Bar = Bar.new()
12176 assert_equal("aaa", b.v5.v1)
12177 assert_equal([1, 2], b.v5.v2)
12178 assert_equal({a: 'a', b: 'b'}, b.v5.v3)
12179 assert_equal("bbb", b.v4)
12180 assert_equal([1, 2], b.v6)
12181 END
12182 v9.CheckSourceSuccess(lines)
12183enddef
12184
Yegappan Lakshmanan68d08582025-02-09 19:39:52 +010012185" Test for using a concrete method in an abstract extended class which is
12186" further extended
12187def Test_abstract_method_across_hierarchy()
12188 var lines =<< trim END
12189 vim9script
12190
12191 abstract class A
12192 abstract def Foo(): string
12193 endclass
12194
12195 abstract class B extends A
12196 abstract def Bar(): string
12197 endclass
12198
12199 class C extends B
12200 def Foo(): string
12201 return 'foo'
12202 enddef
12203
12204 def Bar(): string
12205 return 'bar'
12206 enddef
12207 endclass
12208
12209 def Fn1(a: A): string
12210 return a.Foo()
12211 enddef
12212
12213 def Fn2(b: B): string
12214 return b.Bar()
12215 enddef
12216
12217 var c = C.new()
12218 assert_equal('foo', Fn1(c))
12219 assert_equal('bar', Fn2(c))
12220 END
12221 v9.CheckSourceSuccess(lines)
12222
12223 lines =<< trim END
12224 vim9script
12225
12226 abstract class A
12227 abstract def Foo(): string
12228 endclass
12229
12230 abstract class B extends A
12231 abstract def Bar(): string
12232 endclass
12233
12234 class C extends B
12235 def Bar(): string
12236 return 'bar'
12237 enddef
12238 endclass
12239
12240 defcompile
12241 END
12242 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
12243
12244 lines =<< trim END
12245 vim9script
12246
12247 abstract class A
12248 abstract def M1(): string
12249 abstract def M2(): string
12250 endclass
12251
12252 abstract class B extends A
12253 def M1(): string
12254 return 'B: M1'
12255 enddef
12256
12257 def M2(): string
12258 return 'B: M2'
12259 enddef
12260 endclass
12261
12262 class C1 extends B
12263 def M1(): string
12264 return 'C1: M1'
12265 enddef
12266 endclass
12267
12268 class C2 extends B
12269 def M2(): string
12270 return 'C2: M2'
12271 enddef
12272 endclass
12273
12274 class D1 extends C1
12275 endclass
12276
12277 class D2 extends C2
12278 endclass
12279
12280 var l: list<string> = []
12281 for Type in ['C1', 'C2', 'D1', 'D2']
12282 l->add(eval($'{Type}.new().M1()'))
12283 l->add(eval($'{Type}.new().M2()'))
12284 endfor
12285 assert_equal(['C1: M1', 'B: M2', 'B: M1', 'C2: M2', 'C1: M1', 'B: M2', 'B: M1', 'C2: M2'], l)
12286 END
12287 v9.CheckSourceSuccess(lines)
12288
12289 lines =<< trim END
12290 vim9script
12291
12292 abstract class A
12293 abstract def M1(): string
12294 abstract def M2(): string
12295 endclass
12296
12297 class B extends A
12298 def M1(): string
12299 return 'B: M1'
12300 enddef
12301
12302 def M2(): string
12303 return 'B: M2'
12304 enddef
12305 endclass
12306
12307 abstract class C extends B
12308 endclass
12309
12310 class D1 extends C
12311 def M1(): string
12312 return 'D1: M1'
12313 enddef
12314 endclass
12315
12316 class D2 extends C
12317 def M2(): string
12318 return 'D2: M2'
12319 enddef
12320 endclass
12321
12322 class E1 extends D1
12323 endclass
12324
12325 class E2 extends D2
12326 endclass
12327
12328 var l: list<string> = []
12329 for Type in ['B', 'D1', 'D2', 'E1', 'E2']
12330 l->add(eval($'{Type}.new().M1()'))
12331 l->add( eval($'{Type}.new().M2()'))
12332 endfor
12333 assert_equal(['B: M1', 'B: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2'], l)
12334 END
12335 v9.CheckSourceSuccess(lines)
12336enddef
12337
Yegappan Lakshmanan7e898002025-02-11 22:07:05 +010012338" Test for using a protected new() method (singleton design pattern)
12339def Test_protected_new_method()
12340 var lines =<< trim END
12341 vim9script
12342 class A
12343 def _new()
12344 enddef
12345 endclass
12346 var a = A.new()
12347 END
12348 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "A"', 6)
12349
12350 lines =<< trim END
12351 vim9script
12352 class A
12353 static var _instance: A
12354 var str: string
12355 def _new(str: string)
12356 this.str = str
12357 enddef
12358 static def GetInstance(str: string): A
12359 if _instance == null
12360 _instance = A._new(str)
12361 endif
12362 return _instance
12363 enddef
12364 endclass
12365 var a: A = A.GetInstance('foo')
12366 var b: A = A.GetInstance('bar')
12367 assert_equal('foo', a.str)
12368 assert_equal('foo', b.str)
12369 END
12370 v9.CheckSourceSuccess(lines)
12371enddef
12372
Yegappan Lakshmananb5f463c2025-02-16 16:25:24 +010012373" Test for using 'super' in a closure function inside an object method
12374def Test_super_in_closure()
12375 var lines =<< trim END
12376 vim9script
12377
12378 class A
12379 const _value: number
12380
12381 def Fn(): func(any): number
12382 return (_: any) => this._value
12383 enddef
12384 endclass
12385
12386 class B extends A
12387 def Fn(): func(any): number
12388 return (_: any) => super._value
12389 enddef
12390 endclass
12391
12392 assert_equal(100, A.new(100).Fn()(null))
12393 assert_equal(200, B.new(200).Fn()(null))
12394 END
12395 v9.CheckSourceSuccess(lines)
12396enddef
12397
12398" Test for using 'super' to access methods and variables
12399def Test_super_keyword()
12400 var lines =<< trim END
12401 vim9script
12402 class Base
12403 var name: string
12404 def ToString(): string
12405 return this.name
12406 enddef
12407 endclass
12408
12409 class Child extends Base
12410 var age: number
12411 def ToString(): string
12412 return super.ToString() .. ': ' .. this.age
12413 enddef
12414 endclass
12415
12416 var o = Child.new('John', 42)
12417 assert_equal('John: 42', o.ToString())
12418 END
12419 v9.CheckSourceSuccess(lines)
12420
12421 lines =<< trim END
12422 vim9script
12423 class Child
12424 var age: number
12425 def ToString(): string
12426 return super .ToString() .. ': ' .. this.age
12427 enddef
12428 endclass
12429 var o = Child.new(42)
12430 echo o.ToString()
12431 END
12432 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
12433
12434 lines =<< trim END
12435 vim9script
12436 class Base
12437 var name: string
12438 def ToString(): string
12439 return this.name
12440 enddef
12441 endclass
12442
12443 var age = 42
12444 def ToString(): string
12445 return super.ToString() .. ': ' .. age
12446 enddef
12447 echo ToString()
12448 END
12449 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
12450
12451 lines =<< trim END
12452 vim9script
12453 class Child
12454 var age: number
12455 def ToString(): string
12456 return super.ToString() .. ': ' .. this.age
12457 enddef
12458 endclass
12459 var o = Child.new(42)
12460 echo o.ToString()
12461 END
12462 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
12463
12464 # Using super, Child invokes Base method which has optional arg. #12471
12465 lines =<< trim END
12466 vim9script
12467
12468 class Base
12469 var success: bool = false
12470 def Method(arg = 0)
12471 this.success = true
12472 enddef
12473 endclass
12474
12475 class Child extends Base
12476 def new()
12477 super.Method()
12478 enddef
12479 endclass
12480
12481 var obj = Child.new()
12482 assert_equal(true, obj.success)
12483 END
12484 v9.CheckSourceSuccess(lines)
12485
12486 # Using 'super' to access an object variable in the parent
12487 lines =<< trim END
12488 vim9script
12489
12490 class A
12491 var foo: string = 'xxx'
12492 endclass
12493
12494 class B extends A
12495 def GetString(): string
12496 return super.foo
12497 enddef
12498 endclass
12499
12500 var b: B = B.new()
12501 echo b.GetString()
12502 END
12503 v9.CheckSourceSuccess(lines)
12504
Yegappan Lakshmanan5ce1e4a2025-04-07 21:09:18 +020012505 # Using 'super' to access an static class variable in the parent should fail
12506 lines =<< trim END
12507 vim9script
12508
12509 class A
12510 static var foo: string = 'xxx'
12511 endclass
12512
12513 class B extends A
12514 def GetString(): string
12515 return super.foo
12516 enddef
12517 endclass
12518
12519 defcompile
12520 END
12521 v9.CheckSourceFailure(lines, 'E1326: Variable "foo" not found in object "B"')
12522
Yegappan Lakshmananb5f463c2025-02-16 16:25:24 +010012523 # Using super to access an overriden method in the parent class
12524 lines =<< trim END
12525 vim9script
12526
12527 class A
12528 def Foo(): string
12529 return 'A.Foo'
12530 enddef
12531 endclass
12532
12533 class B extends A
12534 def Foo(): string
12535 return 'B.Foo'
12536 enddef
12537
12538 def Bar(): string
12539 return $'{super.Foo()} {this.Foo()}'
12540 enddef
12541 endclass
12542
12543 var b = B.new()
12544 assert_equal('A.Foo B.Foo', b.Bar())
12545 END
12546 v9.CheckSourceSuccess(lines)
12547enddef
12548
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012549" Test for using a list of objects
12550def Test_method_call_from_list_of_objects()
12551 var lines =<< trim END
12552 vim9script
12553
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012554 class A
12555 var n: list<number> = [100, 101]
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012556 def F(): string
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012557 return 'A.F'
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012558 enddef
12559 endclass
12560
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012561 class B
12562 var name: string
12563 var n: list<number> = [200, 201]
12564 def new(this.name)
12565 enddef
12566 def F(): string
12567 return 'B.F'
12568 enddef
12569 endclass
12570
12571 var obj1 = A.new()
12572 var obj2 = B.new('b1')
12573
12574 def CheckObjectList()
12575 var objlist = [obj1, obj2]
12576 assert_equal('list<object<any>>', typename(objlist))
12577
12578 # Use a member function
12579 assert_equal('A.F', objlist[0].F())
12580 assert_equal('B.F', objlist[1].F())
12581
12582 # Use a member variable on the RHS
12583 assert_equal([100, 101], objlist[0].n)
12584 assert_equal([200, 201], objlist[1].n)
12585
12586 # Use a member variable on the LHS
12587 objlist[0].n[1] = 110
12588 objlist[1].n[1] = 210
12589 assert_equal([100, 110], objlist[0].n)
12590 assert_equal([200, 210], objlist[1].n)
12591
12592 # Iterate using a for loop
12593 var s1 = []
12594 for o in objlist
12595 add(s1, o.F())
12596 endfor
12597 assert_equal(['A.F', 'B.F'], s1)
12598
12599 # Iterate using foreach()
12600 var s2 = []
12601 foreach(objlist, (k, v) => add(s2, v.F()))
12602 assert_equal(['A.F', 'B.F'], s2)
12603
12604 # Add a new list item
12605 objlist->add(B.new('b2'))
12606 assert_equal('b2', objlist[2].name)
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012607 enddef
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012608
12609 CheckObjectList()
12610
12611 var objlist = [A.new(), B.new('b2')]
12612 assert_equal('list<object<any>>', typename(objlist))
12613
12614 # Use a member function
12615 assert_equal('A.F', objlist[0].F())
12616 assert_equal('B.F', objlist[1].F())
12617
12618 # Use a member variable on the RHS
12619 assert_equal([100, 101], objlist[0].n)
12620 assert_equal([200, 201], objlist[1].n)
12621
12622 # Use a member variable on the LHS
12623 objlist[0].n[1] = 110
12624 objlist[1].n[1] = 210
12625 assert_equal([100, 110], objlist[0].n)
12626 assert_equal([200, 210], objlist[1].n)
12627
12628 # Iterate using a for loop
12629 var s1 = []
12630 for o in objlist
12631 add(s1, o.F())
12632 endfor
12633 assert_equal(['A.F', 'B.F'], s1)
12634
12635 # Iterate using foreach()
12636 var s2 = []
12637 foreach(objlist, (k, v) => add(s2, v.F()))
12638 assert_equal(['A.F', 'B.F'], s2)
12639
12640 # Add a new list item
12641 objlist->add(B.new('b2'))
12642 assert_equal('b2', objlist[2].name)
12643 END
12644 v9.CheckSourceSuccess(lines)
12645
12646 lines =<< trim END
12647 vim9script
12648
12649 class A
12650 endclass
12651
12652 class B
12653 endclass
12654
12655 var objlist = [A.new(), B.new()]
12656 def Fn()
12657 objlist->add(10)
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012658 enddef
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012659
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012660 try
12661 Fn()
12662 catch
12663 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12664 endtry
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012665
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012666 try
12667 objlist->add(10)
12668 catch
12669 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12670 endtry
12671 END
12672 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012673
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012674 # Adding an enum to a List of objects should fail
12675 lines =<< trim END
12676 vim9script
12677 class A
12678 endclass
12679 class B
12680 endclass
12681 enum C
12682 Red,
12683 Green,
12684 endenum
12685 var items = [A.new(), B.new()]
12686 def Fn()
12687 items->add(C.Red)
12688 enddef
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012689
Yegappan Lakshmanande8f8f72025-04-01 20:43:36 +020012690 try
12691 Fn()
12692 catch
12693 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
12694 endtry
12695
12696 try
12697 items->add(C.Green)
12698 catch
12699 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
12700 endtry
12701
12702 var items2 = [C.Red, C.Green]
12703 def Fn2()
12704 items2->add(A.new())
12705 enddef
12706 try
12707 Fn2()
12708 catch
12709 assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<A>')
12710 endtry
12711
12712 try
12713 items2->add(B.new())
12714 catch
12715 assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<B>')
12716 endtry
12717 END
12718 v9.CheckSourceSuccess(lines)
12719enddef
12720
12721" Test for using a dict of objects
12722def Test_dict_of_objects()
12723 var lines =<< trim END
12724 vim9script
12725
12726 class A
12727 var n: list<number> = [100, 101]
12728 def F(): string
12729 return 'A.F'
12730 enddef
12731 endclass
12732
12733 class B
12734 var name: string
12735 var n: list<number> = [200, 201]
12736 def new(this.name)
12737 enddef
12738 def F(): string
12739 return 'B.F'
12740 enddef
12741 endclass
12742
12743 var obj1 = A.new()
12744 var obj2 = B.new('b1')
12745
12746 def CheckObjectDict()
12747 var objdict = {o_a: obj1, o_b: obj2}
12748 assert_equal('dict<object<any>>', typename(objdict))
12749
12750 # Use a member function
12751 assert_equal('A.F', objdict.o_a.F())
12752 assert_equal('B.F', objdict.o_b.F())
12753
12754 # Use a member variable on the RHS
12755 assert_equal([100, 101], objdict.o_a.n)
12756 assert_equal([200, 201], objdict.o_b.n)
12757
12758 # Use a member variable on the LHS
12759 objdict.o_a.n[1] = 110
12760 objdict.o_b.n[1] = 210
12761 assert_equal([100, 110], objdict.o_a.n)
12762 assert_equal([200, 210], objdict.o_b.n)
12763
12764 # Iterate using a for loop
12765 var l = []
12766 for v in values(objdict)
12767 add(l, v.F())
12768 endfor
12769 assert_equal(['A.F', 'B.F'], l)
12770
12771 # Iterate using foreach()
12772 l = []
12773 foreach(objdict, (k, v) => add(l, v.F()))
12774 assert_equal(['A.F', 'B.F'], l)
12775
12776 # Add a new dict item
12777 objdict['o_b2'] = B.new('b2')
12778 assert_equal('b2', objdict.o_b2.name)
12779 enddef
12780
12781 CheckObjectDict()
12782
12783 var objdict = {o_a: A.new(), o_b: B.new('b2')}
12784 assert_equal('dict<object<any>>', typename(objdict))
12785 assert_equal('A.F', objdict.o_a.F())
12786 assert_equal('B.F', objdict.o_b.F())
12787 assert_equal([100, 101], objdict.o_a.n)
12788 assert_equal([200, 201], objdict.o_b.n)
12789
12790 var l = []
12791 for v in values(objdict)
12792 add(l, v.F())
12793 endfor
12794 assert_equal(['A.F', 'B.F'], l)
12795
12796 # Add a new dict item
12797 objdict['o_b2'] = B.new('b2')
12798 assert_equal('b2', objdict.o_b2.name)
12799 END
12800 v9.CheckSourceSuccess(lines)
12801
12802 lines =<< trim END
12803 vim9script
12804
12805 class A
12806 endclass
12807 class B
12808 endclass
12809 class C
12810 endclass
12811 var objdict = {a: A.new(), b: B.new()}
12812 def Fn()
12813 objdict['c'] = C.new()
12814 enddef
12815
12816 try
12817 Fn()
12818 catch
12819 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12820 endtry
12821
12822 try
12823 objdict['c'] = C.new()
12824 catch
12825 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got number')
12826 endtry
12827 END
12828 v9.CheckSourceSuccess(lines)
12829
12830 # Adding an enum to a Dict of objects should fail
12831 lines =<< trim END
12832 vim9script
12833 class A
12834 endclass
12835 class B
12836 endclass
12837 enum C
12838 Red,
12839 Green,
12840 endenum
12841 var items = {o_a: A.new(), o_b: B.new()}
12842 def Fn()
12843 items['o_c'] = C.Red
12844 enddef
12845
12846 try
12847 Fn()
12848 catch
12849 assert_exception('Vim(eval):E1012: Type mismatch; expected object<any> but got enum<C>')
12850 endtry
12851
12852 try
12853 items['o_c'] = C.Green
12854 catch
12855 assert_exception('Vim(var):E1012: Type mismatch; expected object<any> but got enum<C>')
12856 endtry
12857
12858 var items2 = {red: C.Red, green: C.Green}
12859 def Fn2()
12860 items2['o_a'] = A.new()
12861 enddef
12862 try
12863 Fn2()
12864 catch
12865 assert_exception('Vim(eval):E1012: Type mismatch; expected enum<C> but got object<A>')
12866 endtry
12867
12868 try
12869 items2['o_a'] = B.new()
12870 catch
12871 assert_exception('Vim(var):E1012: Type mismatch; expected enum<C> but got object<B>')
12872 endtry
Yegappan Lakshmananb1d6db02025-03-31 20:35:44 +020012873 END
12874 v9.CheckSourceSuccess(lines)
12875enddef
12876
Yegappan Lakshmanan6fa62082025-04-03 21:26:34 +020012877" Test for using the type() and typename() functions with a variable of type
12878" object
12879def Test_type_typename_funcs_with_object_variable()
12880 var lines =<< trim END
12881 vim9script
12882
12883 class A
12884 endclass
12885
12886 class B
12887 endclass
12888
12889 var o1: object<any>
12890 assert_equal([13, 'object<any>'], [type(o1), typename(o1)])
12891
12892 var o2: object<A>
12893 assert_equal([13, 'object<any>'], [type(o2), typename(o2)])
12894
12895 var o3: A
12896 assert_equal([13, 'object<any>'], [type(o3), typename(o3)])
12897
12898 var o4 = A.new()
12899 assert_equal([13, 'object<A>'], [type(o4), typename(o4)])
12900
12901 var l = [A.new(), B.new()]
12902 assert_equal([13, 'object<B>'], [type(l[1]), typename(l[1])])
12903
12904 var d = {o_a: A.new(), o_b: B.new()}
12905 assert_equal([13, 'object<B>'], [type(d.o_b), typename(d.o_b)])
12906 END
12907 v9.CheckSourceSuccess(lines)
12908enddef
12909
12910" Test for object<any> type
12911def Test_object_any_type()
12912 # assigning different objects to variable of type object<any>
12913 var lines =<< trim END
12914 vim9script
12915 class A
12916 endclass
12917 class B
12918 endclass
12919 var x: object<any>
12920 x = A.new()
12921 assert_true(instanceof(x, A))
12922 x = B.new()
12923 assert_true(instanceof(x, B))
12924 x = null_object
12925 assert_true(instanceof(x, null_class))
12926 END
12927 v9.CheckSourceSuccess(lines)
12928
12929 # Use a list of object<any> variable
12930 lines =<< trim END
12931 vim9script
12932 class A
12933 endclass
12934 class B
12935 endclass
12936 var l: list<object<any>>
12937 l->add(A.new())
12938 l->add(B.new())
12939 assert_true(instanceof(l[0], A))
12940 assert_true(instanceof(l[1], B))
12941 END
12942 v9.CheckSourceSuccess(lines)
12943
12944 # Using object<any> as a function argument type and the return type
12945 lines =<< trim END
12946 vim9script
12947 class A
12948 endclass
12949 class B
12950 endclass
12951 def Fn(x: object<any>): object<any>
12952 return x
12953 enddef
12954 assert_true(instanceof(Fn(A.new()), A))
12955 assert_true(instanceof(Fn(B.new()), B))
12956 END
12957
12958 # Try assigning a different type of value to a object<any> variable
12959 lines =<< trim END
12960 var x: object<any> = []
12961 END
12962 v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got list<any>', 'E1012: Type mismatch; expected object<any> but got list<any>'])
12963
12964 # Try assigning a different type of value to a object<any> variable
12965 lines =<< trim END
12966 var x: object<any>
12967 x = 0z10
12968 END
12969 v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got blob', 'E1012: Type mismatch; expected object<any> but got blob'])
12970
12971 # Try adding a different type of value to a list<object<any>> variable
12972 lines =<< trim END
12973 var x: list<object<any>>
12974 x->add({})
12975 END
12976 v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got dict<any>', 'E1012: Type mismatch; expected object<any> but got dict<any>'])
12977
12978 # Try adding a different type of value to a dict<object<any>> variable
12979 lines =<< trim END
12980 var x: dict<object<any>>
12981 x['a'] = {}
12982 END
12983 v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got dict<any>', 'E1012: Type mismatch; expected object<any> but got dict<any>'])
12984enddef
12985
12986" Test for object<{class}> type
12987def Test_object_of_class_type()
12988 var lines =<< trim END
12989 vim9script
12990 class A
12991 endclass
12992 var x: object<A>
12993 x = A.new()
12994 assert_true(instanceof(x, A))
12995 var y: object<A> = A.new()
12996 assert_true(instanceof(y, A))
12997 END
12998 v9.CheckSourceSuccess(lines)
12999
13000 lines =<< trim END
13001 vim9script
13002 class A
13003 endclass
13004 class B
13005 endclass
13006 var x: object<A>
13007 x = B.new()
13008 END
13009 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got object<B>')
13010
13011 lines =<< trim END
13012 vim9script
13013 class A
13014 endclass
13015 class B
13016 endclass
13017 def Fn(x: object<A>): object<B>
13018 return B.new()
13019 enddef
13020 assert_true(instanceof(Fn(A.new()), B))
13021 END
13022 v9.CheckSourceSuccess(lines)
13023
13024 lines =<< trim END
13025 var x: object
13026 END
13027 v9.CheckSourceDefAndScriptFailure(lines, ['E1008: Missing <type> after object', 'E1008: Missing <type> after object'])
13028
13029 lines =<< trim END
13030 var x: object <any>
13031 END
13032 v9.CheckSourceDefAndScriptFailure(lines, ['E1068: No white space allowed before ''<'': <any>', 'E1068: No white space allowed before ''<'': <any>'])
13033
13034 lines =<< trim END
13035 var x: object<any
13036 END
13037 v9.CheckSourceDefAndScriptFailure(lines, ['E1009: Missing > after type: <any', 'E1009: Missing > after type: <any'])
13038
13039 lines =<< trim END
13040 var x: object<any,any>
13041 END
13042 v9.CheckSourceDefFailure(lines, 'E1009: Missing > after type: <any,any>')
13043
13044 lines =<< trim END
13045 vim9script
13046 var x: object<any,any>
13047 END
13048 v9.CheckSourceFailure(lines, 'E488: Trailing characters: ,any>')
Yegappan Lakshmanan5ce1e4a2025-04-07 21:09:18 +020013049
13050 lines =<< trim END
13051 var x: object<number>
13052 END
13053 v9.CheckSourceDefAndScriptFailure(lines, [
13054 \ 'E1353: Class name not found: <number>',
13055 \ 'E1353: Class name not found: <number>'])
Yegappan Lakshmanan6fa62082025-04-03 21:26:34 +020013056enddef
13057
Bram Moolenaar00b28d62022-12-08 15:32:33 +000013058" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker