blob: 23281bcad75f11d7af094fd377ea85759189a15b [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 Lakshmananb90e3bc2023-09-28 23:06:48 +0200547 v9.CheckDefExecAndScriptFailure(lines, ['E715: Dictionary required', '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))
567 assert_equal('class<Unknown>', typename(null_class))
568 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
646 # TODO: this should not give an error but be handled at runtime
647 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200648 vim9script
Ernie Raelf77a7f72023-03-03 15:05:30 +0000649
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200650 class Class
Doug Kearns74da0ee2023-12-14 20:26:26 +0100651 var id: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200652 def Method1()
653 echo 'Method1' .. this.id
Ernie Raelf77a7f72023-03-03 15:05:30 +0000654 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200655 endclass
656
657 var obj = null_object
658 def Func()
659 obj.Method1()
660 enddef
661 Func()
Ernie Raelf77a7f72023-03-03 15:05:30 +0000662 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200663 v9.CheckSourceFailure(lines, 'E1363: Incomplete type', 1)
Ernie Raelbe828252024-07-26 18:37:02 +0200664
665 # Reference a object variable through a null class object which is stored in a
666 # variable of type "any".
667 lines =<< trim END
668 vim9script
669
670 def Z()
671 var o: any = null_object
672 o.v = 4
673 enddef
674 Z()
675 END
676 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
677
678 # Do "echom" of a null object variable.
679 lines =<< trim END
680 vim9script
681
682 def X()
683 var x = null_object
684 echom x
685 enddef
686 X()
687 END
688 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 2)
Ernie Rael94082b62024-07-26 19:40:29 +0200689
690 # Use a null object variable that vim wants to force to number.
691 lines =<< trim END
692 vim9script
693
694 def X()
695 var o = null_object
696 var l = [ 1, o]
697 sort(l, 'N')
698 enddef
699 X()
700 END
701 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 3)
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000702enddef
703
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200704" Null object assignment and comparison
Ernie Rael5c018be2023-08-27 18:40:26 +0200705def Test_null_object_assign_compare()
706 var lines =<< trim END
707 vim9script
708
709 var nullo = null_object
710 def F(): any
711 return nullo
712 enddef
713 assert_equal('object<Unknown>', typename(F()))
714
715 var o0 = F()
716 assert_true(o0 == null_object)
717 assert_true(o0 == null)
718
719 var o1: any = nullo
720 assert_true(o1 == null_object)
721 assert_true(o1 == null)
722
723 def G()
724 var x = null_object
725 enddef
726
727 class C
728 endclass
729 var o2: C
730 assert_true(o2 == null_object)
731 assert_true(o2 == null)
732
733 o2 = null_object
734 assert_true(o2 == null)
735
736 o2 = C.new()
737 assert_true(o2 != null)
738
739 o2 = null_object
740 assert_true(o2 == null)
741 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200742 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200743enddef
744
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200745" Test for object member initialization and disassembly
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000746def Test_class_member_initializer()
747 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200748 vim9script
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000749
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200750 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100751 var lnum: number = 1
752 var col: number = 1
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000753
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200754 # constructor with only the line number
755 def new(lnum: number)
756 this.lnum = lnum
757 enddef
758 endclass
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000759
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200760 var pos = TextPosition.new(3)
761 assert_equal(3, pos.lnum)
762 assert_equal(1, pos.col)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000763
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200764 var instr = execute('disassemble TextPosition.new')
765 assert_match('new\_s*' ..
766 '0 NEW TextPosition size \d\+\_s*' ..
767 '\d PUSHNR 1\_s*' ..
768 '\d STORE_THIS 0\_s*' ..
769 '\d PUSHNR 1\_s*' ..
770 '\d STORE_THIS 1\_s*' ..
771 'this.lnum = lnum\_s*' ..
772 '\d LOAD arg\[-1]\_s*' ..
773 '\d PUSHNR 0\_s*' ..
774 '\d LOAD $0\_s*' ..
775 '\d\+ STOREINDEX object\_s*' ..
776 '\d\+ RETURN object.*',
777 instr)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000778 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200779 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000780enddef
781
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000782def Test_member_any_used_as_object()
783 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200784 vim9script
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000785
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200786 class Inner
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +0100787 public var value: number = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200788 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000789
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200790 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100791 var inner: any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200792 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000793
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200794 def F(outer: Outer)
795 outer.inner.value = 1
796 enddef
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000797
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200798 var inner_obj = Inner.new(0)
799 var outer_obj = Outer.new(inner_obj)
800 F(outer_obj)
801 assert_equal(1, inner_obj.value)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000802 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200803 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000804
Ernie Rael03042a22023-11-11 08:53:32 +0100805 # Try modifying a protected variable using an "any" object
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200806 lines =<< trim END
807 vim9script
808
809 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100810 var _value: string = ''
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200811 endclass
812
813 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100814 var inner: any
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200815 endclass
816
817 def F(outer: Outer)
818 outer.inner._value = 'b'
819 enddef
820
821 var inner_obj = Inner.new('a')
822 var outer_obj = Outer.new(inner_obj)
823 F(outer_obj)
824 END
Ernie Rael03042a22023-11-11 08:53:32 +0100825 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_value" in class "Inner"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200826
827 # Try modifying a non-existing variable using an "any" object
828 lines =<< trim END
829 vim9script
830
831 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100832 var value: string = ''
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200833 endclass
834
835 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100836 var inner: any
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200837 endclass
838
839 def F(outer: Outer)
840 outer.inner.someval = 'b'
841 enddef
842
843 var inner_obj = Inner.new('a')
844 var outer_obj = Outer.new(inner_obj)
845 F(outer_obj)
846 END
Ernie Raeld4802ec2023-10-20 11:59:00 +0200847 v9.CheckSourceFailure(lines, 'E1326: Variable "someval" not found in object "Inner"', 1)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000848enddef
849
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200850" Nested assignment to a object variable which is of another class type
851def Test_assignment_nested_type()
852 var lines =<< trim END
853 vim9script
854
855 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100856 public var value: number = 0
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200857 endclass
858
859 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100860 var inner: Inner
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200861 endclass
862
863 def F(outer: Outer)
864 outer.inner.value = 1
865 enddef
866
867 def Test_assign_to_nested_typed_member()
868 var inner = Inner.new(0)
869 var outer = Outer.new(inner)
870 F(outer)
871 assert_equal(1, inner.value)
872 enddef
873
874 Test_assign_to_nested_typed_member()
Ernie Rael98e68c02023-09-20 20:13:06 +0200875
876 var script_inner = Inner.new(0)
877 var script_outer = Outer.new(script_inner)
878 script_outer.inner.value = 1
879 assert_equal(1, script_inner.value)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200880 END
881 v9.CheckSourceSuccess(lines)
Ernie Rael98e68c02023-09-20 20:13:06 +0200882
883 # Assignment where target item is read only in :def
884 lines =<< trim END
885 vim9script
886
887 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100888 var value: number = 0
Ernie Rael98e68c02023-09-20 20:13:06 +0200889 endclass
890
891 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100892 var inner: Inner
Ernie Rael98e68c02023-09-20 20:13:06 +0200893 endclass
894
895 def F(outer: Outer)
896 outer.inner.value = 1
897 enddef
898
899 def Test_assign_to_nested_typed_member()
900 var inner = Inner.new(0)
901 var outer = Outer.new(inner)
902 F(outer)
903 assert_equal(1, inner.value)
904 enddef
905
906 Test_assign_to_nested_typed_member()
907 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200908 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 1)
Ernie Rael98e68c02023-09-20 20:13:06 +0200909
910 # Assignment where target item is read only script level
911 lines =<< trim END
912 vim9script
913
914 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100915 var value: number = 0
Ernie Rael98e68c02023-09-20 20:13:06 +0200916 endclass
917
918 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100919 var inner: Inner
Ernie Rael98e68c02023-09-20 20:13:06 +0200920 endclass
921
922 def F(outer: Outer)
923 outer.inner.value = 1
924 enddef
925
926 var script_inner = Inner.new(0)
927 var script_outer = Outer.new(script_inner)
928 script_outer.inner.value = 1
929 assert_equal(1, script_inner.value)
930 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200931 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 17)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200932enddef
933
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000934def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200935 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000936 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200937 vim9script
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000938
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200939 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +0100940 public var x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000941
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200942 def Add(n: number)
943 this.x += n
Bram Moolenaar22363c62023-04-24 17:15:25 +0100944 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200945 endclass
Bram Moolenaar22363c62023-04-24 17:15:25 +0100946
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200947 var f = Foo.new(3)
948 f.Add(17)
949 assert_equal(20, f.x)
950
951 def AddToFoo(obj: Foo)
952 obj.x += 3
953 enddef
954
955 AddToFoo(f)
956 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000957 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200958 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000959enddef
960
Bram Moolenaarf4508042023-01-15 16:54:57 +0000961def Test_list_of_objects()
962 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200963 vim9script
Bram Moolenaarf4508042023-01-15 16:54:57 +0000964
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200965 class Foo
966 def Add()
Bram Moolenaarf4508042023-01-15 16:54:57 +0000967 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200968 endclass
Bram Moolenaarf4508042023-01-15 16:54:57 +0000969
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200970 def ProcessList(fooList: list<Foo>)
971 for foo in fooList
972 foo.Add()
973 endfor
974 enddef
975
976 var l: list<Foo> = [Foo.new()]
977 ProcessList(l)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000978 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200979 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000980enddef
981
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000982def Test_expr_after_using_object()
983 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200984 vim9script
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000985
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200986 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100987 var label: string = ''
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200988 endclass
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000989
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200990 def Foo(): Something
991 var v = Something.new()
992 echo 'in Foo(): ' .. typename(v)
993 return v
994 enddef
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000995
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200996 Foo()
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000997 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200998 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000999enddef
1000
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001001def Test_class_default_new()
1002 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001003 vim9script
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001004
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001005 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001006 var lnum: number = 1
1007 var col: number = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001008 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001009
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001010 var pos = TextPosition.new()
1011 assert_equal(1, pos.lnum)
1012 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001013
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001014 pos = TextPosition.new(v:none, v:none)
1015 assert_equal(1, pos.lnum)
1016 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001017
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001018 pos = TextPosition.new(3, 22)
1019 assert_equal(3, pos.lnum)
1020 assert_equal(22, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001021
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001022 pos = TextPosition.new(v:none, 33)
1023 assert_equal(1, pos.lnum)
1024 assert_equal(33, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001025 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001026 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001027
1028 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001029 vim9script
1030 class Person
Doug Kearns74da0ee2023-12-14 20:26:26 +01001031 var name: string
1032 var age: number = 42
1033 var education: string = "unknown"
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001034
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001035 def new(this.name, this.age = v:none, this.education = v:none)
1036 enddef
1037 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001038
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001039 var piet = Person.new("Piet")
1040 assert_equal("Piet", piet.name)
1041 assert_equal(42, piet.age)
1042 assert_equal("unknown", piet.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001043
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001044 var chris = Person.new("Chris", 4, "none")
1045 assert_equal("Chris", chris.name)
1046 assert_equal(4, chris.age)
1047 assert_equal("none", chris.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001048 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001049 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001050
1051 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001052 vim9script
1053 class Person
Doug Kearns74da0ee2023-12-14 20:26:26 +01001054 var name: string
1055 var age: number = 42
1056 var education: string = "unknown"
Bram Moolenaar74e12742022-12-13 21:14:28 +00001057
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001058 def new(this.name, this.age = v:none, this.education = v:none)
1059 enddef
1060 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001061
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001062 var missing = Person.new()
Bram Moolenaar74e12742022-12-13 21:14:28 +00001063 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001064 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001065
1066 # Using a specific value to initialize an instance variable in the new()
1067 # method.
1068 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001069 vim9script
1070 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001071 var val: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001072 def new(this.val = 'a')
1073 enddef
1074 endclass
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001075 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001076 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'", 4)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001077enddef
1078
h-east2261c892023-08-16 21:49:54 +09001079def Test_class_new_with_object_member()
1080 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001081 vim9script
h-east2261c892023-08-16 21:49:54 +09001082
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001083 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001084 var str: string
1085 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001086 def new(this.str, this.num)
h-east2261c892023-08-16 21:49:54 +09001087 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001088 def newVals(this.str, this.num)
1089 enddef
1090 endclass
h-east2261c892023-08-16 21:49:54 +09001091
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001092 def Check()
1093 try
1094 var c = C.new('cats', 2)
1095 assert_equal('cats', c.str)
1096 assert_equal(2, c.num)
1097
1098 c = C.newVals('dogs', 4)
1099 assert_equal('dogs', c.str)
1100 assert_equal(4, c.num)
1101 catch
1102 assert_report($'Unexpected exception was caught: {v:exception}')
1103 endtry
1104 enddef
1105
1106 Check()
h-east2261c892023-08-16 21:49:54 +09001107 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001108 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +09001109
1110 lines =<< trim END
h-eastdb385522023-09-28 22:18:19 +02001111 vim9script
1112
1113 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001114 var str: string
1115 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001116 def new(this.str, this.num)
h-eastdb385522023-09-28 22:18:19 +02001117 enddef
1118 endclass
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001119
1120 def Check()
1121 try
1122 var c = C.new(1, 2)
1123 catch
1124 assert_report($'Unexpected exception was caught: {v:exception}')
1125 endtry
1126 enddef
1127
1128 Check()
h-eastdb385522023-09-28 22:18:19 +02001129 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001130 v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 2)
h-eastdb385522023-09-28 22:18:19 +02001131
1132 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001133 vim9script
h-eastb895b0f2023-09-24 15:46:31 +02001134
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001135 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001136 var str: string
1137 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001138 def newVals(this.str, this.num)
h-eastb895b0f2023-09-24 15:46:31 +02001139 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001140 endclass
h-eastb895b0f2023-09-24 15:46:31 +02001141
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001142 def Check()
1143 try
1144 var c = C.newVals('dogs', 'apes')
1145 catch
1146 assert_report($'Unexpected exception was caught: {v:exception}')
1147 endtry
1148 enddef
1149
1150 Check()
1151 END
1152 v9.CheckSourceFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string', 2)
1153
1154 lines =<< trim END
1155 vim9script
1156
1157 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001158 var str: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001159 def new(str: any)
1160 enddef
1161 endclass
1162
1163 def Check()
1164 try
1165 var c = C.new(1)
1166 catch
1167 assert_report($'Unexpected exception was caught: {v:exception}')
1168 endtry
1169 enddef
1170
1171 Check()
h-eastb895b0f2023-09-24 15:46:31 +02001172 END
1173 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001174
1175 # Try using "this." argument in a class method
1176 lines =<< trim END
1177 vim9script
1178 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001179 var val = 10
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001180 static def Foo(this.val: number)
1181 enddef
1182 endclass
1183 END
1184 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
1185
1186 # Try using "this." argument in an object method
1187 lines =<< trim END
1188 vim9script
1189 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001190 var val = 10
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001191 def Foo(this.val: number)
1192 enddef
1193 endclass
1194 END
1195 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
h-east2261c892023-08-16 21:49:54 +09001196enddef
1197
Bram Moolenaar74e12742022-12-13 21:14:28 +00001198def Test_class_object_member_inits()
1199 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001200 vim9script
1201 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001202 var lnum: number
1203 var col = 1
1204 var addcol: number = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001205 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001206
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001207 var pos = TextPosition.new()
1208 assert_equal(0, pos.lnum)
1209 assert_equal(1, pos.col)
1210 assert_equal(2, pos.addcol)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001211 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001212 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001213
1214 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001215 vim9script
1216 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001217 var lnum
1218 var col = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001219 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001220 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001221 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001222
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001223 # If the type is not specified for a member, then it should be set during
1224 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +00001225 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001226 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001227
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001228 var init_count = 0
1229 def Init(): string
1230 init_count += 1
1231 return 'foo'
1232 enddef
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001233
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001234 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001235 var str1 = Init()
1236 var str2: string = Init()
1237 var col = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001238 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001239
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001240 assert_equal(init_count, 0)
1241 var a = A.new()
1242 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001243 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001244 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001245
1246 # Test for initializing an object member with an unknown variable/type
1247 lines =<< trim END
1248 vim9script
1249 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001250 var value = init_val
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001251 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001252 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001253 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001254 v9.CheckSourceFailure(lines, 'E1001: Variable not found: init_val', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001255
1256 # Test for initializing an object member with an special type
1257 lines =<< trim END
1258 vim9script
1259 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001260 var value: void
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001261 endclass
1262 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001263 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001264enddef
1265
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001266" Test for instance variable access
1267def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001268 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001269 vim9script
1270 class Triple
Doug Kearns74da0ee2023-12-14 20:26:26 +01001271 var _one = 1
1272 var two = 2
1273 public var three = 3
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001274
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001275 def GetOne(): number
1276 return this._one
1277 enddef
1278 endclass
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001279
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001280 var trip = Triple.new()
1281 assert_equal(1, trip.GetOne())
1282 assert_equal(2, trip.two)
1283 assert_equal(3, trip.three)
Ernie Rael03042a22023-11-11 08:53:32 +01001284 assert_fails('echo trip._one', 'E1333: Cannot access protected variable "_one" in class "Triple"')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001285
Ernie Rael03042a22023-11-11 08:53:32 +01001286 assert_fails('trip._one = 11', 'E1333: Cannot access protected variable "_one" in class "Triple"')
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001287 assert_fails('trip.two = 22', 'E1335: Variable "two" in class "Triple" is not writable')
1288 trip.three = 33
1289 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001290
Ernie Raeld4802ec2023-10-20 11:59:00 +02001291 assert_fails('trip.four = 4', 'E1326: Variable "four" not found in object "Triple"')
Bram Moolenaard505d172022-12-18 21:42:55 +00001292 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001293 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001294
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001295 # Test for a public member variable name beginning with an underscore
1296 lines =<< trim END
1297 vim9script
1298 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001299 public var _val = 10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001300 endclass
1301 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02001302 v9.CheckSourceFailure(lines, 'E1332: public variable name cannot start with underscore: public var _val = 10', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001303
Bram Moolenaar590162c2022-12-24 21:24:06 +00001304 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001305 vim9script
Bram Moolenaar590162c2022-12-24 21:24:06 +00001306
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001307 class MyCar
Doug Kearns74da0ee2023-12-14 20:26:26 +01001308 var make: string
1309 var age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001310
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001311 def new(make_arg: string)
1312 this.make = make_arg
Bram Moolenaar574950d2023-01-03 19:08:50 +00001313 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001314
1315 def GetMake(): string
1316 return $"make = {this.make}"
1317 enddef
1318 def GetAge(): number
1319 return this.age
1320 enddef
1321 endclass
1322
1323 var c = MyCar.new("abc")
1324 assert_equal('make = abc', c.GetMake())
1325
1326 c = MyCar.new("def")
1327 assert_equal('make = def', c.GetMake())
1328
1329 var c2 = MyCar.new("123")
1330 assert_equal('make = 123', c2.GetMake())
1331
1332 def CheckCar()
1333 assert_equal("make = def", c.GetMake())
1334 assert_equal(5, c.GetAge())
1335 enddef
1336 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001337 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001338 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001339
1340 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001341 vim9script
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001342
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001343 class MyCar
Doug Kearns74da0ee2023-12-14 20:26:26 +01001344 var make: string
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001345
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001346 def new(make_arg: string)
1347 this.make = make_arg
1348 enddef
1349 endclass
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001350
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001351 var c = MyCar.new("abc")
1352 var c = MyCar.new("def")
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001353 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001354 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "c"', 12)
Bram Moolenaarb149d222023-01-24 13:03:37 +00001355
1356 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001357 vim9script
Bram Moolenaarb149d222023-01-24 13:03:37 +00001358
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001359 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001360 var x: list<number> = []
Bram Moolenaarb149d222023-01-24 13:03:37 +00001361
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001362 def Add(n: number): any
1363 this.x->add(n)
1364 return this
1365 enddef
1366 endclass
Bram Moolenaarb149d222023-01-24 13:03:37 +00001367
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001368 echo Foo.new().Add(1).Add(2).x
1369 echo Foo.new().Add(1).Add(2)
1370 .x
1371 echo Foo.new().Add(1)
1372 .Add(2).x
1373 echo Foo.new()
1374 .Add(1).Add(2).x
1375 echo Foo.new()
1376 .Add(1)
1377 .Add(2)
1378 .x
Bram Moolenaarb149d222023-01-24 13:03:37 +00001379 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001380 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001381
1382 # Test for "public" cannot be abbreviated
1383 lines =<< trim END
1384 vim9script
1385 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001386 pub var val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001387 endclass
1388 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001389 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: pub var val = 1', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001390
Doug Kearns74da0ee2023-12-14 20:26:26 +01001391 # Test for "public" keyword must be followed by "var" or "static".
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001392 lines =<< trim END
1393 vim9script
1394 class Something
1395 public val = 1
1396 endclass
1397 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02001398 v9.CheckSourceFailure(lines, 'E1331: public must be followed by "var" or "static"', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001399
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001400 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001401 lines =<< trim END
1402 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001403 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001404 public var val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001405 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001406 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001407 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001408 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001409
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001410 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001411 lines =<< trim END
1412 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001413 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001414 public var val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001415 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001416 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001417 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001418 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001419
1420 # Modify a instance variable using the class name in a def function
1421 lines =<< trim END
1422 vim9script
1423 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001424 public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001425 endclass
1426 def T()
1427 A.val = 1
1428 enddef
1429 T()
1430 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001431 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001432
1433 # Read a instance variable using the class name in a def function
1434 lines =<< trim END
1435 vim9script
1436 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001437 public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001438 endclass
1439 def T()
1440 var i = A.val
1441 enddef
1442 T()
1443 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001444 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Ernie Raelcf138d42023-09-06 20:45:03 +02001445
1446 # Access from child class extending a class:
1447 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001448 vim9script
1449 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001450 var ro_obj_var = 10
1451 public var rw_obj_var = 20
1452 var _priv_obj_var = 30
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001453 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001454
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001455 class B extends A
1456 def Foo()
1457 var x: number
1458 x = this.ro_obj_var
1459 this.ro_obj_var = 0
1460 x = this.rw_obj_var
1461 this.rw_obj_var = 0
1462 x = this._priv_obj_var
1463 this._priv_obj_var = 0
1464 enddef
1465 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001466
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001467 var b = B.new()
1468 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001469 END
1470 v9.CheckSourceSuccess(lines)
1471enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001472
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001473" Test for class variable access
1474def Test_class_variable_access()
1475 # Test for "static" cannot be abbreviated
1476 var lines =<< trim END
1477 vim9script
1478 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001479 stat var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001480 endclass
1481 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001482 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: stat var val = 1', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001483
1484 # Test for "static" cannot be followed by "public".
1485 lines =<< trim END
1486 vim9script
1487 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001488 static public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001489 endclass
1490 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001491 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001492
1493 # A readonly class variable cannot be modified from a child class
1494 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001495 vim9script
1496 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001497 static var ro_class_var = 40
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001498 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001499
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001500 class B extends A
1501 def Foo()
1502 A.ro_class_var = 50
1503 enddef
1504 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001505
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001506 var b = B.new()
1507 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001508 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001509 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001510
Ernie Rael03042a22023-11-11 08:53:32 +01001511 # A protected class variable cannot be accessed from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001512 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001513 vim9script
1514 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001515 static var _priv_class_var = 60
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001516 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001517
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001518 class B extends A
1519 def Foo()
1520 var i = A._priv_class_var
1521 enddef
1522 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001523
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001524 var b = B.new()
1525 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001526 END
Ernie Rael03042a22023-11-11 08:53:32 +01001527 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001528
Ernie Rael03042a22023-11-11 08:53:32 +01001529 # A protected class variable cannot be modified from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001530 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001531 vim9script
1532 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001533 static var _priv_class_var = 60
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001534 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001535
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001536 class B extends A
1537 def Foo()
1538 A._priv_class_var = 0
1539 enddef
1540 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001541
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001542 var b = B.new()
1543 b.Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001544 END
Ernie Rael03042a22023-11-11 08:53:32 +01001545 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001546
1547 # Access from child class extending a class and from script context
1548 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001549 vim9script
1550 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001551 static var ro_class_var = 10
1552 public static var rw_class_var = 20
1553 static var _priv_class_var = 30
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001554 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001555
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001556 class B extends A
1557 def Foo()
1558 var x: number
1559 x = A.ro_class_var
1560 assert_equal(10, x)
1561 x = A.rw_class_var
1562 assert_equal(25, x)
1563 A.rw_class_var = 20
1564 assert_equal(20, A.rw_class_var)
1565 enddef
1566 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001567
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001568 assert_equal(10, A.ro_class_var)
1569 assert_equal(20, A.rw_class_var)
1570 A.rw_class_var = 25
1571 assert_equal(25, A.rw_class_var)
1572 var b = B.new()
1573 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001574 END
1575 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001576enddef
1577
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001578def Test_class_object_compare()
1579 var class_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001580 vim9script
1581 class Item
Doug Kearns74da0ee2023-12-14 20:26:26 +01001582 var nr = 0
1583 var name = 'xx'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001584 endclass
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001585 END
1586
1587 # used at the script level and in a compiled function
1588 var test_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001589 var i1 = Item.new()
1590 assert_equal(i1, i1)
1591 assert_true(i1 is i1)
1592 var i2 = Item.new()
1593 assert_equal(i1, i2)
1594 assert_false(i1 is i2)
1595 var i3 = Item.new(0, 'xx')
1596 assert_equal(i1, i3)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001597
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001598 var io1 = Item.new(1, 'xx')
1599 assert_notequal(i1, io1)
1600 var io2 = Item.new(0, 'yy')
1601 assert_notequal(i1, io2)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001602 END
1603
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001604 v9.CheckSourceSuccess(class_lines + test_lines)
1605 v9.CheckSourceSuccess(
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001606 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001607
1608 for op in ['>', '>=', '<', '<=', '=~', '!~']
1609 var op_lines = [
1610 'var i1 = Item.new()',
1611 'var i2 = Item.new()',
1612 'echo i1 ' .. op .. ' i2',
1613 ]
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001614 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object', 8)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001615 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001616 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001617 endfor
1618enddef
1619
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001620def Test_object_type()
1621 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001622 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001623
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001624 class One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001625 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001626 endclass
1627 class Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001628 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001629 endclass
1630 class TwoMore extends Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001631 var more = 9
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001632 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001633
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001634 var o: One = One.new()
1635 var t: Two = Two.new()
1636 var m: TwoMore = TwoMore.new()
1637 var tm: Two = TwoMore.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001638
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001639 t = m
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001640 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001641 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001642
1643 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001644 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001645
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001646 class One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001647 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001648 endclass
1649 class Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001650 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001651 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001652
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001653 var o: One = Two.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001654 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001655 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>', 10)
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001656
1657 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001658 vim9script
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001659
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001660 interface One
1661 def GetMember(): number
1662 endinterface
1663 class Two implements One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001664 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001665 def GetMember(): number
1666 return this.one
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001667 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001668 endclass
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001669
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001670 var o: One = Two.new(5)
1671 assert_equal(5, o.GetMember())
1672 END
1673 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001674
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001675 lines =<< trim END
1676 vim9script
1677
1678 class Num
Doug Kearns74da0ee2023-12-14 20:26:26 +01001679 var n: number = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001680 endclass
1681
1682 def Ref(name: string): func(Num): Num
1683 return (arg: Num): Num => {
1684 return eval(name)(arg)
1685 }
1686 enddef
1687
1688 const Fn = Ref('Double')
1689 var Double = (m: Num): Num => Num.new(m.n * 2)
1690
1691 echo Fn(Num.new(4))
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001692 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001693 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001694enddef
1695
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001696def Test_class_member()
1697 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001698 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001699 vim9script
1700 class TextPos
Doug Kearns74da0ee2023-12-14 20:26:26 +01001701 var lnum = 1
1702 var col = 1
1703 static var counter = 0
1704 static var _secret = 7
1705 public static var anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001706
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001707 static def AddToCounter(nr: number)
1708 counter += nr
1709 enddef
1710 endclass
Bram Moolenaard505d172022-12-18 21:42:55 +00001711
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001712 assert_equal(0, TextPos.counter)
1713 TextPos.AddToCounter(3)
1714 assert_equal(3, TextPos.counter)
1715 assert_fails('echo TextPos.noSuchMember', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001716
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001717 def GetCounter(): number
1718 return TextPos.counter
1719 enddef
1720 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001721
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001722 assert_fails('TextPos.noSuchMember = 2', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
1723 assert_fails('TextPos.counter = 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
1724 assert_fails('TextPos.counter += 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001725
Ernie Rael03042a22023-11-11 08:53:32 +01001726 assert_fails('echo TextPos._secret', 'E1333: Cannot access protected variable "_secret" in class "TextPos"')
1727 assert_fails('TextPos._secret = 8', 'E1333: Cannot access protected variable "_secret" in class "TextPos"')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001728
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001729 assert_equal(42, TextPos.anybody)
1730 TextPos.anybody = 12
1731 assert_equal(12, TextPos.anybody)
1732 TextPos.anybody += 5
1733 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001734 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001735 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001736
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001737 # example in the help
1738 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001739 vim9script
1740 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +01001741 var size: number
1742 static var totalSize: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001743
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001744 def new(this.size)
1745 totalSize += this.size
1746 enddef
1747 endclass
1748 assert_equal(0, OtherThing.totalSize)
1749 var to3 = OtherThing.new(3)
1750 assert_equal(3, OtherThing.totalSize)
1751 var to7 = OtherThing.new(7)
1752 assert_equal(10, OtherThing.totalSize)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001753 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001754 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001755
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001756 # using static class member twice
1757 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001758 vim9script
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001759
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001760 class HTML
Doug Kearns74da0ee2023-12-14 20:26:26 +01001761 static var author: string = 'John Doe'
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001762
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001763 static def MacroSubstitute(s: string): string
1764 return substitute(s, '{{author}}', author, 'gi')
1765 enddef
1766 endclass
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001767
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001768 assert_equal('some text', HTML.MacroSubstitute('some text'))
1769 assert_equal('some text', HTML.MacroSubstitute('some text'))
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001770 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001771 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001772
Ernie Rael03042a22023-11-11 08:53:32 +01001773 # access protected member in lambda
Bram Moolenaar62a69232023-01-24 15:07:04 +00001774 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001775 vim9script
Bram Moolenaar62a69232023-01-24 15:07:04 +00001776
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001777 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001778 var _x: number = 0
Bram Moolenaar62a69232023-01-24 15:07:04 +00001779
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001780 def Add(n: number): number
1781 const F = (): number => this._x + n
1782 return F()
1783 enddef
1784 endclass
Bram Moolenaar62a69232023-01-24 15:07:04 +00001785
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001786 var foo = Foo.new()
1787 assert_equal(5, foo.Add(5))
Bram Moolenaar62a69232023-01-24 15:07:04 +00001788 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001789 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001790
Ernie Rael03042a22023-11-11 08:53:32 +01001791 # access protected member in lambda body
h-east2bd6a092023-05-19 19:01:17 +01001792 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001793 vim9script
h-east2bd6a092023-05-19 19:01:17 +01001794
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001795 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001796 var _x: number = 6
h-east2bd6a092023-05-19 19:01:17 +01001797
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001798 def Add(n: number): number
1799 var Lam = () => {
1800 this._x = this._x + n
1801 }
1802 Lam()
1803 return this._x
1804 enddef
1805 endclass
h-east2bd6a092023-05-19 19:01:17 +01001806
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001807 var foo = Foo.new()
1808 assert_equal(13, foo.Add(7))
h-east2bd6a092023-05-19 19:01:17 +01001809 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001810 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001811
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001812 # check shadowing
1813 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001814 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001815
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001816 class Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01001817 static var count = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001818 def Method(count: number)
1819 echo count
1820 enddef
1821 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001822
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001823 var s = Some.new()
1824 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001825 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001826 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001827
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001828 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001829 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001830 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001831
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001832 class Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01001833 static var count = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001834 def Method(arg: number)
1835 var count = 3
1836 echo arg count
1837 enddef
1838 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001839
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001840 var s = Some.new()
1841 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001842 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001843 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001844
1845 # Test for using an invalid type for a member variable
1846 lines =<< trim END
1847 vim9script
1848 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001849 var val: xxx
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001850 endclass
1851 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001852 v9.CheckSourceFailure(lines, 'E1010: Type not recognized: xxx', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001853
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001854 # Test for setting a member on a null object
1855 lines =<< trim END
1856 vim9script
1857 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001858 public var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001859 endclass
1860
1861 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001862 var obj: A
1863 obj.val = ""
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001864 enddef
1865 F()
1866 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001867 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001868
1869 # Test for accessing a member on a null object
1870 lines =<< trim END
1871 vim9script
1872 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001873 var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001874 endclass
1875
1876 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001877 var obj: A
1878 echo obj.val
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001879 enddef
1880 F()
1881 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001882 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001883
1884 # Test for setting a member on a null object, at script level
1885 lines =<< trim END
1886 vim9script
1887 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001888 public var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001889 endclass
1890
1891 var obj: A
1892 obj.val = ""
1893 END
Ernie Rael4c8da022023-10-11 21:35:11 +02001894 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001895
1896 # Test for accessing a member on a null object, at script level
1897 lines =<< trim END
1898 vim9script
1899 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001900 var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001901 endclass
1902
1903 var obj: A
1904 echo obj.val
1905 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001906 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001907
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001908 # Test for no space before or after the '=' when initializing a member
1909 # variable
1910 lines =<< trim END
1911 vim9script
1912 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001913 var val: number= 10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001914 endclass
1915 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001916 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001917 lines =<< trim END
1918 vim9script
1919 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001920 var val: number =10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001921 endclass
1922 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001923 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001924
1925 # Access a non-existing member
1926 lines =<< trim END
1927 vim9script
1928 class A
1929 endclass
1930 var a = A.new()
1931 var v = a.bar
1932 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02001933 v9.CheckSourceFailure(lines, 'E1326: Variable "bar" not found in object "A"', 5)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001934enddef
1935
Ernie Raele6c9aa52023-10-06 19:55:52 +02001936" These messages should show the defining class of the variable (base class),
1937" not the class that did the reference (super class)
1938def Test_defining_class_message()
1939 var lines =<< trim END
1940 vim9script
1941
1942 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001943 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001944 endclass
1945
1946 class Child extends Base
1947 endclass
1948
1949 var o = Child.new()
1950 var x = o._v1
1951 END
Ernie Rael03042a22023-11-11 08:53:32 +01001952 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 11)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001953 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 def F()
1964 var o = Child.new()
1965 var x = o._v1
1966 enddef
1967 F()
1968 END
Ernie Rael03042a22023-11-11 08:53:32 +01001969 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001970 lines =<< trim END
1971 vim9script
1972
1973 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001974 var v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001975 endclass
1976
1977 class Child extends Base
1978 endclass
1979
1980 var o = Child.new()
1981 o.v1 = []
1982 END
1983 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 11)
1984 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 def F()
1995 var o = Child.new()
1996 o.v1 = []
1997 enddef
1998 F()
1999 END
2000
Ernie Rael03042a22023-11-11 08:53:32 +01002001 # Attempt to read a protected variable that is in the middle
Ernie Raele6c9aa52023-10-06 19:55:52 +02002002 # of the class hierarchy.
2003 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 2)
2004 lines =<< trim END
2005 vim9script
2006
2007 class Base0
2008 endclass
2009
2010 class Base extends Base0
Doug Kearns74da0ee2023-12-14 20:26:26 +01002011 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002012 endclass
2013
2014 class Child extends Base
2015 endclass
2016
2017 def F()
2018 var o = Child.new()
2019 var x = o._v1
2020 enddef
2021 F()
2022 END
Ernie Rael03042a22023-11-11 08:53:32 +01002023 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002024
Ernie Rael03042a22023-11-11 08:53:32 +01002025 # Attempt to read a protected variable that is at the start
Ernie Raele6c9aa52023-10-06 19:55:52 +02002026 # of the class hierarchy.
2027 lines =<< trim END
2028 vim9script
2029
2030 class Base0
2031 endclass
2032
2033 class Base extends Base0
2034 endclass
2035
2036 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01002037 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002038 endclass
2039
2040 def F()
2041 var o = Child.new()
2042 var x = o._v1
2043 enddef
2044 F()
2045 END
Ernie Rael03042a22023-11-11 08:53:32 +01002046 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Child"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002047enddef
2048
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002049func Test_class_garbagecollect()
2050 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002051 vim9script
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002052
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002053 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002054 var p = [2, 3]
2055 static var pl = ['a', 'b']
2056 static var pd = {a: 'a', b: 'b'}
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002057 endclass
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002058
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002059 echo Point.pl Point.pd
2060 call test_garbagecollect_now()
2061 echo Point.pl Point.pd
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002062 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002063 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002064
2065 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002066 vim9script
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002067
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002068 interface View
2069 endinterface
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002070
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002071 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01002072 var view: View
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002073 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002074
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002075 class MyView implements View
Doug Kearns74da0ee2023-12-14 20:26:26 +01002076 var widget: Widget
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002077
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002078 def new()
2079 # this will result in a circular reference to this object
Doug Kearns74da0ee2023-12-14 20:26:26 +01002080 var widget = Widget.new(this)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002081 enddef
2082 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002083
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002084 var view = MyView.new()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002085
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002086 # overwrite "view", will be garbage-collected next
2087 view = MyView.new()
2088 test_garbagecollect_now()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002089 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002090 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002091endfunc
2092
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002093" Test interface garbage collection
2094func Test_interface_garbagecollect()
2095 let lines =<< trim END
2096 vim9script
2097
2098 interface I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002099 var ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002100
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002101 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002102 endinterface
2103
2104 class A implements I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002105 static var ro_class_var: number = 10
2106 public static var rw_class_var: number = 20
2107 static var _priv_class_var: number = 30
2108 var ro_obj_var: number = 40
2109 var _priv_obj_var: number = 60
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002110
2111 static def _ClassBar(): number
2112 return _priv_class_var
2113 enddef
2114
2115 static def ClassFoo(): number
2116 return ro_class_var + rw_class_var + A._ClassBar()
2117 enddef
2118
2119 def _ObjBar(): number
2120 return this._priv_obj_var
2121 enddef
2122
2123 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002124 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002125 enddef
2126 endclass
2127
2128 assert_equal(60, A.ClassFoo())
2129 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002130 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002131 test_garbagecollect_now()
2132 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002133 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002134 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002135 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002136endfunc
2137
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002138def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002139 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002140 vim9script
2141 class Value
Doug Kearns74da0ee2023-12-14 20:26:26 +01002142 var value = 0
2143 static var objects = 0
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002144
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002145 def new(v: number)
2146 this.value = v
2147 ++objects
2148 enddef
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002149
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002150 static def GetCount(): number
2151 return objects
2152 enddef
2153 endclass
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002154
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002155 assert_equal(0, Value.GetCount())
2156 var v1 = Value.new(2)
2157 assert_equal(1, Value.GetCount())
2158 var v2 = Value.new(7)
2159 assert_equal(2, Value.GetCount())
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002160 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002161 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002162
2163 # Test for cleaning up after a class definition failure when using class
2164 # functions.
2165 lines =<< trim END
2166 vim9script
2167 class A
2168 static def Foo()
2169 enddef
2170 aaa
2171 endclass
2172 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002173 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: aaa', 5)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002174
2175 # Test for calling a class method from another class method without the class
2176 # name prefix.
2177 lines =<< trim END
2178 vim9script
2179 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01002180 static var myList: list<number> = [1]
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002181 static def Foo(n: number)
2182 myList->add(n)
2183 enddef
2184 static def Bar()
2185 Foo(2)
2186 enddef
2187 def Baz()
2188 Foo(3)
2189 enddef
2190 endclass
2191 A.Bar()
2192 var a = A.new()
2193 a.Baz()
2194 assert_equal([1, 2, 3], A.myList)
2195 END
2196 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002197enddef
2198
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002199def Test_class_defcompile()
2200 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002201 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002202
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002203 class C
2204 def Fo(i: number): string
2205 return i
2206 enddef
2207 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002208
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002209 defcompile C.Fo
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002210 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002211 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number', 1)
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002212
2213 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002214 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002215
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002216 class C
2217 static def Fc(): number
2218 return 'x'
2219 enddef
2220 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002221
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002222 defcompile C.Fc
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002223 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002224 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002225
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002226 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002227 vim9script
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002228
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002229 class C
2230 static def new()
2231 enddef
2232 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002233
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002234 defcompile C.new
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002235 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002236 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static', 5)
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002237
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002238 # Trying to compile a function using a non-existing class variable
2239 lines =<< trim END
2240 vim9script
2241 defcompile x.Foo()
2242 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002243 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002244
2245 # Trying to compile a function using a variable which is not a class
2246 lines =<< trim END
2247 vim9script
2248 var x: number
2249 defcompile x.Foo()
2250 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002251 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002252
2253 # Trying to compile a function without specifying the name
2254 lines =<< trim END
2255 vim9script
2256 class A
2257 endclass
2258 defcompile A.
2259 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002260 v9.CheckSourceFailure(lines, 'E475: Invalid argument: A.', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002261
2262 # Trying to compile a non-existing class object member function
2263 lines =<< trim END
2264 vim9script
2265 class A
2266 endclass
2267 var a = A.new()
2268 defcompile a.Foo()
2269 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02002270 v9.CheckSourceFailureList(lines, ['E1326: Variable "Foo" not found in object "A"', 'E475: Invalid argument: a.Foo()'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002271enddef
2272
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002273def Test_class_object_to_string()
2274 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002275 vim9script
2276 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01002277 var lnum = 1
2278 var col = 22
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002279 endclass
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002280
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002281 assert_equal("class TextPosition", string(TextPosition))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002282
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002283 var pos = TextPosition.new()
2284 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002285 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002286 v9.CheckSourceSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +02002287
2288 # check string() with object nesting
2289 lines =<< trim END
2290 vim9script
2291 class C
2292 var nest1: C
2293 var nest2: C
2294 def Init(n1: C, n2: C)
2295 this.nest1 = n1
2296 this.nest2 = n2
2297 enddef
2298 endclass
2299
2300 var o1 = C.new()
2301 var o2 = C.new()
2302 o1.Init(o1, o2)
2303 o2.Init(o2, o1)
2304
2305 # The following previously put's vim into an infinite loop.
2306
2307 var expect = "object of C {nest1: object of C {...}, nest2: object of C {nest1: object of C {...}, nest2: object of C {...}}}"
2308 assert_equal(expect, string(o1))
2309 END
2310 v9.CheckSourceSuccess(lines)
2311
2312 lines =<< trim END
2313 vim9script
2314
2315 class B
2316 endclass
2317
2318 class C
2319 var b: B
2320 var c: C
2321 endclass
2322
2323 var o1 = C.new(B.new(), C.new(B.new()))
2324 var expect = "object of C {b: object of B {}, c: object of C {b: object of B {}, c: object of [unknown]}}"
2325 assert_equal(expect, string(o1))
2326 END
2327 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002328enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00002329
Bram Moolenaar554d0312023-01-05 19:59:18 +00002330def Test_interface_basics()
2331 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002332 vim9script
2333 interface Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01002334 var ro_var: list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002335 def GetCount(): number
2336 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002337 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002338 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002339
2340 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002341 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002342 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002343 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002344 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002345 v9.CheckSourceFailure(lines, 'E1342: Interface can only be defined in Vim9 script', 1)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002346
2347 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002348 vim9script
Bram Moolenaar554d0312023-01-05 19:59:18 +00002349
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002350 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002351 var value: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002352 def Method(value: number)
2353 endinterface
Bram Moolenaard40f00c2023-01-13 17:36:49 +00002354 END
h-east61378a12023-04-18 19:07:29 +01002355 # The argument name and the object member name are the same, but this is not a
2356 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002357 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002358
2359 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002360 vim9script
2361 interface somethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002362 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002363 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002364 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002365 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong', 2)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002366
2367 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002368 vim9script
2369 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002370 var value: string
2371 var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002372 def GetCount(): number
2373 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002374 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002375 v9.CheckSourceFailure(lines, 'E1344: Cannot initialize a variable in an interface', 4)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002376
2377 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002378 vim9script
2379 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002380 var value: string
2381 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002382 def GetCount(): number
2383 return 5
2384 enddef
2385 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002386 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002387 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5', 6)
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002388
h-eastaa979c72025-01-03 10:19:45 +01002389 # Test for "interface" cannot be abbreviated
2390 lines =<< trim END
2391 vim9script
2392 inte Something
2393 endinterface
2394 END
2395 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: inte Something', 2)
2396
2397 # Test for "endinterface" cannot be abbreviated
2398 lines =<< trim END
2399 vim9script
2400 interface Something
2401 endin
2402 END
2403 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endin', 3)
2404
Yegappan Lakshmananac773182024-04-27 11:36:12 +02002405 # Additional commands after "interface name"
2406 lines =<< trim END
2407 vim9script
2408 interface Something | var x = 10 | var y = 20
2409 endinterface
2410 END
2411 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
2412
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002413 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002414 vim9script
2415 export interface EnterExit
2416 def Enter(): void
2417 def Exit(): void
2418 endinterface
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002419 END
2420 writefile(lines, 'XdefIntf.vim', 'D')
2421
2422 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002423 vim9script
2424 import './XdefIntf.vim' as defIntf
2425 export def With(ee: defIntf.EnterExit, F: func)
2426 ee.Enter()
2427 try
2428 F()
2429 finally
2430 ee.Exit()
2431 endtry
2432 enddef
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002433 END
2434 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002435
2436 var imported =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002437 vim9script
2438 export abstract class EnterExit
2439 def Enter(): void
2440 enddef
2441 def Exit(): void
2442 enddef
2443 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +00002444 END
2445 writefile(imported, 'XdefIntf2.vim', 'D')
2446
2447 lines[1] = " import './XdefIntf2.vim' as defIntf"
2448 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002449enddef
2450
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01002451" Test for using string() with an interface
2452def Test_interface_to_string()
2453 var lines =<< trim END
2454 vim9script
2455 interface Intf
2456 def Method(nr: number)
2457 endinterface
2458 assert_equal("interface Intf", string(Intf))
2459 END
2460 v9.CheckSourceSuccess(lines)
2461enddef
2462
Bram Moolenaar94674f22023-01-06 18:42:20 +00002463def Test_class_implements_interface()
2464 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002465 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002466
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002467 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002468 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002469 def Method(nr: number)
2470 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002471
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002472 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002473 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002474 def Method(nr: number)
2475 echo nr
2476 enddef
2477 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002478
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002479 interface Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002480 var member: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002481 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002482
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002483 class AnotherImpl implements Some, Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002484 var member = 'abc'
2485 var count = 20
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002486 def Method(nr: number)
2487 echo nr
2488 enddef
2489 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002490 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002491 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002492
2493 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002494 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002495
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002496 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002497 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002498 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002499
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002500 class SomeImpl implements Some implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002501 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002502 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002503 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002504 v9.CheckSourceFailure(lines, 'E1350: Duplicate "implements"', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002505
2506 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002507 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002508
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002509 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002510 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002511 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002512
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002513 class SomeImpl implements Some, Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002514 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002515 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002516 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002517 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002518
2519 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002520 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002521
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002522 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002523 var counter: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002524 def Method(nr: number)
2525 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002526
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002527 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002528 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002529 def Method(nr: number)
2530 echo nr
2531 enddef
2532 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002533 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002534 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented', 13)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002535
2536 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002537 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002538
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002539 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002540 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002541 def Methods(nr: number)
2542 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002543
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002544 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002545 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002546 def Method(nr: number)
2547 echo nr
2548 enddef
2549 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002550 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002551 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented', 13)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002552
2553 # Check different order of members in class and interface works.
2554 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002555 vim9script
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002556
2557 interface Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002558 var label: string
2559 var errpos: number
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002560 endinterface
2561
2562 # order of members is opposite of interface
2563 class Failure implements Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002564 public var lnum: number = 5
2565 var errpos: number = 42
2566 var label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002567 endclass
2568
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002569 def Test()
2570 var result: Result = Failure.new()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002571
2572 assert_equal('label', result.label)
2573 assert_equal(42, result.errpos)
2574 enddef
2575
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002576 Test()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002577 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002578 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002579
2580 # Interface name after "extends" doesn't end in a space or NUL character
2581 lines =<< trim END
2582 vim9script
2583 interface A
2584 endinterface
2585 class B extends A"
2586 endclass
2587 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002588 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002589
2590 # Trailing characters after a class name
2591 lines =<< trim END
2592 vim9script
2593 class A bbb
2594 endclass
2595 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002596 v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002597
2598 # using "implements" with a non-existing class
2599 lines =<< trim END
2600 vim9script
2601 class A implements B
2602 endclass
2603 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002604 v9.CheckSourceFailure(lines, 'E1346: Interface name not found: B', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002605
2606 # using "implements" with a regular class
2607 lines =<< trim END
2608 vim9script
2609 class A
2610 endclass
2611 class B implements A
2612 endclass
2613 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002614 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: A', 5)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002615
2616 # using "implements" with a variable
2617 lines =<< trim END
2618 vim9script
2619 var T: number = 10
2620 class A implements T
2621 endclass
2622 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002623 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: T', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002624
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002625 # implements should be followed by a white space
2626 lines =<< trim END
2627 vim9script
2628 interface A
2629 endinterface
2630 class B implements A;
2631 endclass
2632 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002633 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A;', 4)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002634
LemonBoyc5d27442023-08-19 13:02:35 +02002635 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002636 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002637
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002638 interface One
2639 def IsEven(nr: number): bool
2640 endinterface
2641 class Two implements One
2642 def IsEven(nr: number): string
2643 enddef
2644 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002645 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002646 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002647
2648 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002649 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002650
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002651 interface One
2652 def IsEven(nr: number): bool
2653 endinterface
2654 class Two implements One
2655 def IsEven(nr: bool): bool
2656 enddef
2657 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002658 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002659 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002660
2661 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002662 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002663
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002664 interface One
2665 def IsEven(nr: number): bool
2666 endinterface
2667 class Two implements One
2668 def IsEven(nr: number, ...extra: list<number>): bool
2669 enddef
2670 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002671 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002672 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 +02002673
2674 # access superclass interface members from subclass, mix variable order
2675 lines =<< trim END
2676 vim9script
2677
2678 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002679 var mvar1: number
2680 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002681 endinterface
2682
2683 # NOTE: the order is swapped
2684 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002685 var mvar2: number
2686 var mvar1: number
2687 public static var svar2: number
2688 public static var svar1: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002689 def new()
2690 svar1 = 11
2691 svar2 = 12
2692 this.mvar1 = 111
2693 this.mvar2 = 112
2694 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002695 endclass
2696
2697 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002698 def new()
2699 this.mvar1 = 121
2700 this.mvar2 = 122
2701 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002702 endclass
2703
2704 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002705 def new()
2706 this.mvar1 = 131
2707 this.mvar2 = 132
2708 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002709 endclass
2710
Ernie Raelcf138d42023-09-06 20:45:03 +02002711 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002712 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002713 enddef
2714
2715 var oa = A.new()
2716 var ob = B.new()
2717 var oc = C.new()
2718
Ernie Raelcf138d42023-09-06 20:45:03 +02002719 assert_equal([111, 112], F2(oa))
2720 assert_equal([121, 122], F2(ob))
2721 assert_equal([131, 132], F2(oc))
2722 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002723 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002724
2725 # Access superclass interface members from subclass, mix variable order.
2726 # Two interfaces, one on A, one on B; each has both kinds of variables
2727 lines =<< trim END
2728 vim9script
2729
2730 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002731 var mvar1: number
2732 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002733 endinterface
2734
2735 interface I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002736 var mvar3: number
2737 var mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002738 endinterface
2739
2740 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002741 public static var svar1: number
2742 public static var svar2: number
2743 var mvar1: number
2744 var mvar2: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002745 def new()
2746 svar1 = 11
2747 svar2 = 12
2748 this.mvar1 = 111
2749 this.mvar2 = 112
2750 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002751 endclass
2752
2753 class B extends A implements I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002754 static var svar3: number
2755 static var svar4: number
2756 var mvar3: number
2757 var mvar4: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002758 def new()
2759 svar3 = 23
2760 svar4 = 24
2761 this.mvar1 = 121
2762 this.mvar2 = 122
2763 this.mvar3 = 123
2764 this.mvar4 = 124
2765 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002766 endclass
2767
2768 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01002769 public static var svar5: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002770 def new()
2771 svar5 = 1001
2772 this.mvar1 = 131
2773 this.mvar2 = 132
2774 this.mvar3 = 133
2775 this.mvar4 = 134
2776 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002777 endclass
2778
Ernie Raelcf138d42023-09-06 20:45:03 +02002779 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002780 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002781 enddef
2782
Ernie Raelcf138d42023-09-06 20:45:03 +02002783 def F4(i: I2): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002784 return [ i.mvar3, i.mvar4 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002785 enddef
2786
Ernie Raelcf138d42023-09-06 20:45:03 +02002787 var oa = A.new()
2788 var ob = B.new()
2789 var oc = C.new()
2790
Ernie Raelcf138d42023-09-06 20:45:03 +02002791 assert_equal([[111, 112]], [F2(oa)])
2792 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2793 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002794 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002795 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002796
2797 # Using two interface names without a space after the ","
2798 lines =<< trim END
2799 vim9script
2800 interface A
2801 endinterface
2802 interface B
2803 endinterface
2804 class C implements A,B
2805 endclass
2806 END
2807 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2808
2809 # No interface name after a comma
2810 lines =<< trim END
2811 vim9script
2812 interface A
2813 endinterface
2814 class B implements A,
2815 endclass
2816 END
2817 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2818
2819 # No interface name after implements
2820 lines =<< trim END
2821 vim9script
2822 class A implements
2823 endclass
2824 END
2825 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002826enddef
2827
Bram Moolenaard0200c82023-01-28 15:19:40 +00002828def Test_call_interface_method()
2829 var lines =<< trim END
2830 vim9script
2831 interface Base
2832 def Enter(): void
2833 endinterface
2834
2835 class Child implements Base
2836 def Enter(): void
2837 g:result ..= 'child'
2838 enddef
2839 endclass
2840
2841 def F(obj: Base)
2842 obj.Enter()
2843 enddef
2844
2845 g:result = ''
2846 F(Child.new())
2847 assert_equal('child', g:result)
2848 unlet g:result
2849 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002850 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002851
2852 lines =<< trim END
2853 vim9script
2854 class Base
2855 def Enter(): void
2856 g:result ..= 'base'
2857 enddef
2858 endclass
2859
2860 class Child extends Base
2861 def Enter(): void
2862 g:result ..= 'child'
2863 enddef
2864 endclass
2865
2866 def F(obj: Base)
2867 obj.Enter()
2868 enddef
2869
2870 g:result = ''
2871 F(Child.new())
2872 assert_equal('child', g:result)
2873 unlet g:result
2874 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002875 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002876
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002877 # method of interface returns a value
2878 lines =<< trim END
2879 vim9script
2880 interface Base
2881 def Enter(): string
2882 endinterface
2883
2884 class Child implements Base
2885 def Enter(): string
2886 g:result ..= 'child'
2887 return "/resource"
2888 enddef
2889 endclass
2890
2891 def F(obj: Base)
2892 var r = obj.Enter()
2893 g:result ..= r
2894 enddef
2895
2896 g:result = ''
2897 F(Child.new())
2898 assert_equal('child/resource', g:result)
2899 unlet g:result
2900 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002901 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002902
2903 lines =<< trim END
2904 vim9script
2905 class Base
2906 def Enter(): string
2907 return null_string
2908 enddef
2909 endclass
2910
2911 class Child extends Base
2912 def Enter(): string
2913 g:result ..= 'child'
2914 return "/resource"
2915 enddef
2916 endclass
2917
2918 def F(obj: Base)
2919 var r = obj.Enter()
2920 g:result ..= r
2921 enddef
2922
2923 g:result = ''
2924 F(Child.new())
2925 assert_equal('child/resource', g:result)
2926 unlet g:result
2927 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002928 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002929
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002930 # No class that implements the interface.
2931 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002932 vim9script
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002933
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002934 interface IWithEE
2935 def Enter(): any
2936 def Exit(): void
2937 endinterface
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002938
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002939 def With1(ee: IWithEE, F: func)
2940 var r = ee.Enter()
2941 enddef
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002942
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002943 defcompile
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002944 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002945 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002946enddef
2947
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002948def Test_class_used_as_type()
2949 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002950 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002951
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002952 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002953 var x = 0
2954 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002955 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002956
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002957 var p: Point
2958 p = Point.new(2, 33)
2959 assert_equal(2, p.x)
2960 assert_equal(33, p.y)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002961 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002962 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002963
2964 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002965 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002966
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002967 interface HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002968 var x: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002969 endinterface
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002970
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002971 class Point implements HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002972 var x = 0
2973 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002974 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002975
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002976 var p: Point
2977 p = Point.new(2, 33)
2978 var hx = p
2979 assert_equal(2, hx.x)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002980 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002981 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002982
2983 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002984 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002985
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002986 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002987 var x = 0
2988 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002989 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002990
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002991 var p: Point
2992 p = 'text'
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002993 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002994 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string', 9)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002995enddef
2996
Bram Moolenaar83677162023-01-08 19:54:10 +00002997def Test_class_extends()
2998 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002999 vim9script
3000 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003001 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003002 def GetOne(): number
3003 return this.one
Bram Moolenaar6aa09372023-01-11 17:59:38 +00003004 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003005 endclass
3006 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003007 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003008 def GetTotal(): number
3009 return this.one + this.two
3010 enddef
3011 endclass
3012 var o = Child.new()
3013 assert_equal(1, o.one)
3014 assert_equal(2, o.two)
3015 assert_equal(1, o.GetOne())
3016 assert_equal(3, o.GetTotal())
Bram Moolenaar6481acc2023-01-11 21:14:17 +00003017 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003018 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003019
3020 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003021 vim9script
3022 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003023 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003024 endclass
3025 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003026 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003027 endclass
3028 var o = Child.new(3, 44)
3029 assert_equal(3, o.one)
3030 assert_equal(44, o.two)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003031 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003032 v9.CheckSourceSuccess(lines)
3033
3034 lines =<< trim END
3035 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 extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003040 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003041 endclass
3042 END
3043 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"', 5)
3044
3045 lines =<< trim END
3046 vim9script
3047 class Child extends BaseClass
Doug Kearns74da0ee2023-12-14 20:26:26 +01003048 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003049 endclass
3050 END
3051 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass', 4)
3052
3053 lines =<< trim END
3054 vim9script
3055 var SomeVar = 99
3056 class Child extends SomeVar
Doug Kearns74da0ee2023-12-14 20:26:26 +01003057 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003058 endclass
3059 END
3060 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar', 5)
3061
3062 lines =<< trim END
3063 vim9script
3064 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003065 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003066 def ToString(): string
3067 return this.name
3068 enddef
3069 endclass
3070
3071 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003072 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003073 def ToString(): string
3074 return super.ToString() .. ': ' .. this.age
3075 enddef
3076 endclass
3077
3078 var o = Child.new('John', 42)
3079 assert_equal('John: 42', o.ToString())
3080 END
3081 v9.CheckSourceSuccess(lines)
3082
3083 lines =<< trim END
3084 vim9script
3085 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003086 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003087 def ToString(): number
3088 return this.age
3089 enddef
3090 def ToString(): string
3091 return this.age
3092 enddef
3093 endclass
3094 END
3095 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
3096
3097 lines =<< trim END
3098 vim9script
3099 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003100 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003101 def ToString(): string
3102 return super .ToString() .. ': ' .. this.age
3103 enddef
3104 endclass
3105 var o = Child.new(42)
3106 echo o.ToString()
3107 END
3108 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
3109
3110 lines =<< trim END
3111 vim9script
3112 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003113 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003114 def ToString(): string
3115 return this.name
3116 enddef
3117 endclass
3118
3119 var age = 42
3120 def ToString(): string
3121 return super.ToString() .. ': ' .. age
3122 enddef
3123 echo ToString()
3124 END
3125 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
3126
3127 lines =<< trim END
3128 vim9script
3129 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003130 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003131 def ToString(): string
3132 return super.ToString() .. ': ' .. this.age
3133 enddef
3134 endclass
3135 var o = Child.new(42)
3136 echo o.ToString()
3137 END
3138 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
3139
3140 lines =<< trim END
3141 vim9script
3142 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003143 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003144 static def ToString(): string
3145 return 'Base class'
3146 enddef
3147 endclass
3148
3149 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003150 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003151 def ToString(): string
3152 return Base.ToString() .. ': ' .. this.age
3153 enddef
3154 endclass
3155
3156 var o = Child.new('John', 42)
3157 assert_equal('Base class: 42', o.ToString())
3158 END
3159 v9.CheckSourceSuccess(lines)
3160
3161 lines =<< trim END
3162 vim9script
3163 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003164 var value = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003165 def new(init: number)
3166 this.value = number + 1
3167 enddef
3168 endclass
3169 class Child extends Base
3170 def new()
3171 this.new(3)
3172 enddef
3173 endclass
3174 var c = Child.new()
3175 END
3176 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003177
3178 # base class with more than one object member
3179 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003180 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003181
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003182 class Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01003183 var success: bool
3184 var value: any = null
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003185 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003186
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003187 class Success extends Result
3188 def new(this.value = v:none)
3189 this.success = true
3190 enddef
3191 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003192
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003193 var v = Success.new('asdf')
3194 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003195 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003196 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003197
3198 # class name after "extends" doesn't end in a space or NUL character
3199 lines =<< trim END
3200 vim9script
3201 class A
3202 endclass
3203 class B extends A"
3204 endclass
3205 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003206 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00003207enddef
3208
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003209def Test_using_base_class()
3210 var lines =<< trim END
3211 vim9script
3212
3213 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003214 def Enter(): any
3215 return null
3216 enddef
3217 def Exit(resource: any): void
3218 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003219 endclass
3220
3221 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003222 def Enter(): any
3223 return 42
3224 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003225
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003226 def Exit(resource: number): void
3227 g:result ..= '/exit'
3228 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003229 endclass
3230
3231 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003232 var r = ee.Enter()
3233 try
3234 g:result ..= r
3235 finally
3236 g:result ..= '/finally'
3237 ee.Exit(r)
3238 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003239 enddef
3240
3241 g:result = ''
3242 With(ChildEE.new())
3243 assert_equal('42/finally/exit', g:result)
3244 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003245 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003246 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01003247
3248 # Using super, Child invokes Base method which has optional arg. #12471
3249 lines =<< trim END
3250 vim9script
3251
3252 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003253 var success: bool = false
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003254 def Method(arg = 0)
3255 this.success = true
3256 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01003257 endclass
3258
3259 class Child extends Base
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003260 def new()
3261 super.Method()
3262 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01003263 endclass
3264
3265 var obj = Child.new()
3266 assert_equal(true, obj.success)
3267 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003268 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003269enddef
3270
Ernie Rael58c95792024-08-13 23:27:22 +02003271def Test_super_dispatch()
3272 # See #15448 and #15463
3273 var lines =<< trim END
3274 vim9script
3275
3276 class A
3277 def String(): string
3278 return 'A'
3279 enddef
3280 endclass
3281
3282 class B extends A
3283 def String(): string
3284 return super.String()
3285 enddef
3286 endclass
3287
3288 class C extends B
3289 endclass
3290
3291 assert_equal('A', C.new().String())
3292 END
3293 v9.CheckSourceSuccess(lines)
3294
3295 lines =<< trim END
3296 vim9script
3297
3298 class A
3299 def F(): string
3300 return 'AA'
3301 enddef
3302 endclass
3303
3304 class B extends A
3305 def F(): string
3306 return 'BB'
3307 enddef
3308 def S(): string
3309 return super.F()
3310 enddef
3311 def S0(): string
3312 return this.S()
3313 enddef
3314 endclass
3315
3316 class C extends B
3317 def F(): string
3318 return 'CC'
3319 enddef
3320 def ToB(): string
3321 return super.F()
3322 enddef
3323 endclass
3324
3325 assert_equal('AA', B.new().S())
3326 assert_equal('AA', C.new().S())
3327 assert_equal('AA', B.new().S0())
3328 assert_equal('AA', C.new().S0())
3329
3330 assert_equal('BB', C.new().ToB())
3331
3332 assert_equal('CC', C.new().F())
3333 assert_equal('BB', B.new().F())
3334 assert_equal('AA', A.new().F())
3335 END
3336 v9.CheckSourceSuccess(lines)
3337
3338 lines =<< trim END
3339 vim9script
3340
3341 var call_chain: list<string>
3342
3343 abstract class A
3344 abstract def _G(): string
3345
3346 def F(): string
3347 call_chain->add('A.F()')
3348 return this._G()
3349 enddef
3350 def _H(): string
3351 call_chain->add('A._H()')
3352 return this.F()
3353 enddef
3354 endclass
3355
3356 class B extends A
3357 def _G(): string
3358 call_chain->add('B.G()')
3359 return 'BBB'
3360 enddef
3361 def SF(): string
3362 call_chain->add('B.SF()')
3363 return super._H()
3364 enddef
3365 endclass
3366
3367 class C extends B
3368 endclass
3369
3370 class D extends C
3371 def SF(): string
3372 call_chain->add('D.SF()')
3373 return super.SF()
3374 enddef
3375 endclass
3376
3377 class E extends D
3378 def SF(): string
3379 call_chain->add('E.SF()')
3380 return super.SF()
3381 enddef
3382 endclass
3383
3384 class F extends E
3385 def _G(): string
3386 call_chain->add('F._G()')
3387 return 'FFF'
3388 enddef
3389 endclass
3390
3391 # E.new() -> A.F() -> B._G()
3392 call_chain = []
3393 var o1 = E.new()
3394 assert_equal('BBB', o1.F())
3395 assert_equal(['A.F()', 'B.G()'], call_chain)
3396
3397 # F.new() -> E.SF() -> D.SF() -> B.SF() -> A._H() -> A.F() -> F._G()
3398 call_chain = []
3399 var o2 = F.new()
3400 assert_equal('FFF', o2.SF())
3401 assert_equal(['E.SF()', 'D.SF()', 'B.SF()', 'A._H()', 'A.F()', 'F._G()'], call_chain)
3402 END
3403 v9.CheckSourceSuccess(lines)
3404enddef
3405
Bram Moolenaara86655a2023-01-12 17:06:27 +00003406def Test_class_import()
3407 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003408 vim9script
3409 export class Animal
Doug Kearns74da0ee2023-12-14 20:26:26 +01003410 var kind: string
3411 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003412 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003413 END
3414 writefile(lines, 'Xanimal.vim', 'D')
3415
3416 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003417 vim9script
3418 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003419
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003420 var a: animal.Animal
3421 a = animal.Animal.new('fish', 'Eric')
3422 assert_equal('fish', a.kind)
3423 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003424
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003425 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3426 assert_equal('cat', b.kind)
3427 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003428 END
3429 v9.CheckScriptSuccess(lines)
3430enddef
3431
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003432" Test for importing a class into a legacy script and calling the class method
3433def Test_class_method_from_legacy_script()
3434 var lines =<< trim END
3435 vim9script
3436 export class A
3437 static var name: string = 'a'
3438 static def SetName(n: string)
3439 name = n
3440 enddef
3441 endclass
3442 END
3443 writefile(lines, 'Xvim9export.vim', 'D')
3444
3445 lines =<< trim END
3446 import './Xvim9export.vim' as vim9
3447
3448 call s:vim9.A.SetName('b')
3449 call assert_equal('b', s:vim9.A.name)
3450 END
3451 v9.CheckScriptSuccess(lines)
3452enddef
3453
Yegappan Lakshmanand2e1c832023-12-14 19:59:45 +01003454" Test for implementing an imported interface
3455def Test_implement_imported_interface()
3456 var lines =<< trim END
3457 vim9script
3458 export interface Imp_Intf1
3459 def Fn1(): number
3460 endinterface
3461 export interface Imp_Intf2
3462 def Fn2(): number
3463 endinterface
3464 END
3465 writefile(lines, 'Ximportinterface.vim', 'D')
3466
3467 lines =<< trim END
3468 vim9script
3469 import './Ximportinterface.vim' as Xintf
3470
3471 class A implements Xintf.Imp_Intf1, Xintf.Imp_Intf2
3472 def Fn1(): number
3473 return 10
3474 enddef
3475 def Fn2(): number
3476 return 20
3477 enddef
3478 endclass
3479 var a = A.new()
3480 assert_equal(10, a.Fn1())
3481 assert_equal(20, a.Fn2())
3482 END
3483 v9.CheckScriptSuccess(lines)
3484enddef
3485
3486" Test for extending an imported class
3487def Test_extend_imported_class()
3488 var lines =<< trim END
3489 vim9script
3490 export class Imp_C1
3491 def Fn1(): number
3492 return 5
3493 enddef
3494 endclass
3495 END
3496 writefile(lines, 'Xextendimportclass.vim', 'D')
3497
3498 lines =<< trim END
3499 vim9script
3500 import './Xextendimportclass.vim' as XClass
3501
3502 class A extends XClass.Imp_C1
3503 endclass
3504 var a = A.new()
3505 assert_equal(5, a.Fn1())
3506 END
3507 v9.CheckScriptSuccess(lines)
3508enddef
3509
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003510def Test_abstract_class()
3511 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003512 vim9script
3513 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003514 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003515 endclass
3516 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003517 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003518 endclass
3519 var p: Base = Person.new('Peter', 42)
3520 assert_equal('Peter', p.name)
3521 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003522 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003523 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003524
3525 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003526 vim9script
3527 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003528 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003529 endclass
3530 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003531 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003532 endclass
3533 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003534 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003535 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003536
3537 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003538 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003539 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003540 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003541 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003542 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003543
h-eastaa979c72025-01-03 10:19:45 +01003544 # Test for "abstract" cannot be abbreviated
3545 lines =<< trim END
3546 vim9script
3547 abs class A
3548 endclass
3549 END
3550 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs class A', 2)
3551
Yegappan Lakshmananac773182024-04-27 11:36:12 +02003552 # Additional commands after "abstract class"
3553 lines =<< trim END
3554 vim9script
3555 abstract class Something | var x = []
3556 endclass
3557 END
3558 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = []", 2)
3559
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003560 # Abstract class cannot have a "new" function
3561 lines =<< trim END
3562 vim9script
3563 abstract class Base
3564 def new()
3565 enddef
3566 endclass
3567 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003568 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003569
3570 # extending an abstract class with class methods and variables
3571 lines =<< trim END
3572 vim9script
3573 abstract class A
3574 static var s: string = 'vim'
3575 static def Fn(): list<number>
3576 return [10]
3577 enddef
3578 endclass
3579 class B extends A
3580 endclass
3581 var b = B.new()
3582 assert_equal('vim', A.s)
3583 assert_equal([10], A.Fn())
3584 END
3585 v9.CheckScriptSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003586enddef
3587
Bram Moolenaar486fc252023-01-18 14:51:07 +00003588def Test_closure_in_class()
3589 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003590 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003591
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003592 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01003593 var y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003594
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003595 def new()
3596 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3597 enddef
3598 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003599
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003600 Foo.new()
3601 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003602 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003603 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003604enddef
3605
Ernie Rael9ed53752023-12-11 17:40:46 +01003606def Test_construct_object_from_legacy()
3607 # Cannot directly invoke constructor from legacy
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003608 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003609 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003610
Ernie Rael9ed53752023-12-11 17:40:46 +01003611 var newCalled = false
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003612
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003613 class A
Ernie Rael9ed53752023-12-11 17:40:46 +01003614 def new(arg: string)
3615 newCalled = true
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003616 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003617 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003618
Ernie Rael9ed53752023-12-11 17:40:46 +01003619 export def CreateA(...args: list<any>): A
3620 return call(A.new, args)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003621 enddef
3622
Ernie Rael9ed53752023-12-11 17:40:46 +01003623 g:P = CreateA
3624 legacy call g:P('some_arg')
3625 assert_equal(true, newCalled)
3626 unlet g:P
3627 END
3628 v9.CheckSourceSuccess(lines)
3629
3630 lines =<< trim END
3631 vim9script
3632
3633 var newCalled = false
3634
3635 class A
3636 static def CreateA(options = {}): any
3637 return A.new()
3638 enddef
3639 def new()
3640 newCalled = true
3641 enddef
3642 endclass
3643
3644 g:P = A.CreateA
3645 legacy call g:P()
3646 assert_equal(true, newCalled)
3647 unlet g:P
3648 END
3649 v9.CheckSourceSuccess(lines)
3650
3651 # This also tests invoking "new()" with "call"
3652 lines =<< trim END
3653 vim9script
3654
3655 var createdObject: any
3656
3657 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01003658 var val1: number
3659 var val2: number
Ernie Rael9ed53752023-12-11 17:40:46 +01003660 static def CreateA(...args: list<any>): any
3661 createdObject = call(A.new, args)
3662 return createdObject
3663 enddef
3664 endclass
3665
3666 g:P = A.CreateA
3667 legacy call g:P(3, 5)
3668 assert_equal(3, createdObject.val1)
3669 assert_equal(5, createdObject.val2)
3670 legacy call g:P()
3671 assert_equal(0, createdObject.val1)
3672 assert_equal(0, createdObject.val2)
3673 legacy call g:P(7)
3674 assert_equal(7, createdObject.val1)
3675 assert_equal(0, createdObject.val2)
3676 unlet g:P
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003677 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003678 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003679enddef
3680
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003681def Test_defer_with_object()
3682 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003683 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003684
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003685 class CWithEE
3686 def Enter()
3687 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003688 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003689 def Exit()
3690 g:result ..= "exited"
3691 enddef
3692 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003693
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003694 def With(ee: CWithEE, F: func)
3695 ee.Enter()
3696 defer ee.Exit()
3697 F()
3698 enddef
3699
3700 g:result = ''
3701 var obj = CWithEE.new()
3702 obj->With(() => {
3703 g:result ..= "called/"
3704 })
3705 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003706 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003707 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003708 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003709
3710 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003711 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003712
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003713 class BaseWithEE
3714 def Enter()
3715 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003716 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003717 def Exit()
3718 g:result ..= "exited-base"
3719 enddef
3720 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003721
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003722 class CWithEE extends BaseWithEE
3723 def Enter()
3724 g:result ..= "entered-child/"
3725 enddef
3726 def Exit()
3727 g:result ..= "exited-child"
3728 enddef
3729 endclass
3730
3731 def With(ee: BaseWithEE, F: func)
3732 ee.Enter()
3733 defer ee.Exit()
3734 F()
3735 enddef
3736
3737 g:result = ''
3738 var obj = CWithEE.new()
3739 obj->With(() => {
3740 g:result ..= "called/"
3741 })
3742 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003743 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003744 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003745 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003746enddef
3747
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003748" The following test used to crash Vim (Github issue #12676)
3749def Test_extends_method_crashes_vim()
3750 var lines =<< trim END
3751 vim9script
3752
3753 class Observer
3754 endclass
3755
3756 class Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003757 var value: any
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003758
3759 def Set(v: any)
3760 if v != this.value
3761 this.value = v
3762 endif
3763 enddef
3764
3765 def Register(observer: Observer)
3766 enddef
3767 endclass
3768
3769 class Bool extends Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003770 var value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003771 endclass
3772
3773 def Observe(obj: Property, who: Observer)
3774 obj.Register(who)
3775 enddef
3776
3777 var p = Bool.new(false)
3778 var myObserver = Observer.new()
3779
3780 Observe(p, myObserver)
3781
3782 p.Set(true)
3783 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003784 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003785enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003786
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003787" Test for calling a method in a class that is extended
3788def Test_call_method_in_extended_class()
3789 var lines =<< trim END
3790 vim9script
3791
3792 var prop_init_called = false
3793 var prop_register_called = false
3794
3795 class Property
3796 def Init()
3797 prop_init_called = true
3798 enddef
3799
3800 def Register()
3801 prop_register_called = true
3802 enddef
3803 endclass
3804
3805 class Bool extends Property
3806 endclass
3807
3808 def Observe(obj: Property)
3809 obj.Register()
3810 enddef
3811
3812 var p = Property.new()
3813 Observe(p)
3814
3815 p.Init()
3816 assert_true(prop_init_called)
3817 assert_true(prop_register_called)
3818 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003819 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003820enddef
3821
LemonBoyafe04662023-08-23 21:08:11 +02003822def Test_instanceof()
3823 var lines =<< trim END
3824 vim9script
3825
3826 class Base1
3827 endclass
3828
3829 class Base2 extends Base1
3830 endclass
3831
3832 interface Intf1
3833 endinterface
3834
3835 class Mix1 implements Intf1
3836 endclass
3837
3838 class Base3 extends Mix1
3839 endclass
3840
Ernie Rael2025af12023-12-12 16:58:00 +01003841 type AliasBase1 = Base1
3842 type AliasBase2 = Base2
3843 type AliasIntf1 = Intf1
3844 type AliasMix1 = Mix1
3845
LemonBoyafe04662023-08-23 21:08:11 +02003846 var b1 = Base1.new()
3847 var b2 = Base2.new()
3848 var b3 = Base3.new()
3849
3850 assert_true(instanceof(b1, Base1))
3851 assert_true(instanceof(b2, Base1))
3852 assert_false(instanceof(b1, Base2))
3853 assert_true(instanceof(b3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003854 assert_true(instanceof(b3, Base1, Base2, Intf1))
3855
3856 assert_true(instanceof(b1, AliasBase1))
3857 assert_true(instanceof(b2, AliasBase1))
3858 assert_false(instanceof(b1, AliasBase2))
3859 assert_true(instanceof(b3, AliasMix1))
3860 assert_true(instanceof(b3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003861
3862 def Foo()
3863 var a1 = Base1.new()
3864 var a2 = Base2.new()
3865 var a3 = Base3.new()
3866
3867 assert_true(instanceof(a1, Base1))
3868 assert_true(instanceof(a2, Base1))
3869 assert_false(instanceof(a1, Base2))
3870 assert_true(instanceof(a3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003871 assert_true(instanceof(a3, Base1, Base2, Intf1))
3872
3873 assert_true(instanceof(a1, AliasBase1))
3874 assert_true(instanceof(a2, AliasBase1))
3875 assert_false(instanceof(a1, AliasBase2))
3876 assert_true(instanceof(a3, AliasMix1))
3877 assert_true(instanceof(a3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003878 enddef
3879 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003880
3881 var o_null: Base1
3882 assert_false(instanceof(o_null, Base1))
3883
LemonBoyafe04662023-08-23 21:08:11 +02003884 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003885 v9.CheckSourceSuccess(lines)
Ernie Rael2025af12023-12-12 16:58:00 +01003886
3887 lines =<< trim END
3888 vim9script
3889
3890 class Base1
3891 endclass
3892 instanceof(Base1.new())
3893 END
3894 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3895
3896 lines =<< trim END
3897 vim9script
3898
3899 class Base1
3900 endclass
3901 def F()
3902 instanceof(Base1.new())
3903 enddef
3904 F()
3905 END
3906 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3907
3908 lines =<< trim END
3909 vim9script
3910
3911 class Base1
3912 endclass
3913
3914 class Base2
3915 endclass
3916
3917 var o = Base2.new()
3918 instanceof(o, Base1, Base2, 3)
3919 END
3920 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4', 10)
3921
3922 lines =<< trim END
3923 vim9script
3924
3925 class Base1
3926 endclass
3927
3928 class Base2
3929 endclass
3930
3931 def F()
3932 var o = Base2.new()
3933 instanceof(o, Base1, Base2, 3)
3934 enddef
3935 F()
3936 END
3937 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4')
LemonBoyafe04662023-08-23 21:08:11 +02003938enddef
3939
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003940" Test for calling a method in the parent class that is extended partially.
3941" This used to fail with the 'E118: Too many arguments for function: Text' error
3942" message (Github issue #12524).
3943def Test_call_method_in_parent_class()
3944 var lines =<< trim END
3945 vim9script
3946
3947 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01003948 var _lnum: number = 1
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003949
3950 def SetY(lnum: number)
3951 this._lnum = lnum
3952 enddef
3953
3954 def Text(): string
3955 return ''
3956 enddef
3957 endclass
3958
3959 class Foo extends Widget
3960 def Text(): string
3961 return '<Foo>'
3962 enddef
3963 endclass
3964
3965 def Stack(w1: Widget, w2: Widget): list<Widget>
3966 w1.SetY(1)
3967 w2.SetY(2)
3968 return [w1, w2]
3969 enddef
3970
3971 var foo1 = Foo.new()
3972 var foo2 = Foo.new()
3973 var l = Stack(foo1, foo2)
3974 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003975 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003976enddef
3977
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003978" Test for calling methods from three levels of classes
3979def Test_multi_level_method_call()
3980 var lines =<< trim END
3981 vim9script
3982
3983 var A_func1: number = 0
3984 var A_func2: number = 0
3985 var A_func3: number = 0
3986 var B_func2: number = 0
3987 var B_func3: number = 0
3988 var C_func3: number = 0
3989
3990 class A
3991 def Func1()
3992 A_func1 += 1
3993 enddef
3994
3995 def Func2()
3996 A_func2 += 1
3997 enddef
3998
3999 def Func3()
4000 A_func3 += 1
4001 enddef
4002 endclass
4003
4004 class B extends A
4005 def Func2()
4006 B_func2 += 1
4007 enddef
4008
4009 def Func3()
4010 B_func3 += 1
4011 enddef
4012 endclass
4013
4014 class C extends B
4015 def Func3()
4016 C_func3 += 1
4017 enddef
4018 endclass
4019
4020 def A_CallFuncs(a: A)
4021 a.Func1()
4022 a.Func2()
4023 a.Func3()
4024 enddef
4025
4026 def B_CallFuncs(b: B)
4027 b.Func1()
4028 b.Func2()
4029 b.Func3()
4030 enddef
4031
4032 def C_CallFuncs(c: C)
4033 c.Func1()
4034 c.Func2()
4035 c.Func3()
4036 enddef
4037
4038 var cobj = C.new()
4039 A_CallFuncs(cobj)
4040 B_CallFuncs(cobj)
4041 C_CallFuncs(cobj)
4042 assert_equal(3, A_func1)
4043 assert_equal(0, A_func2)
4044 assert_equal(0, A_func3)
4045 assert_equal(3, B_func2)
4046 assert_equal(0, B_func3)
4047 assert_equal(3, C_func3)
4048 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004049 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004050enddef
4051
4052" Test for using members from three levels of classes
4053def Test_multi_level_member_access()
4054 var lines =<< trim END
4055 vim9script
4056
4057 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004058 public var val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004059 endclass
4060
4061 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004062 public var val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004063 endclass
4064
4065 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01004066 public var val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004067 endclass
4068
4069 def A_members(a: A)
4070 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004071 enddef
4072
4073 def B_members(b: B)
4074 b.val1 += 1
4075 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004076 enddef
4077
4078 def C_members(c: C)
4079 c.val1 += 1
4080 c.val2 += 1
4081 c.val3 += 1
4082 enddef
4083
4084 var cobj = C.new()
4085 A_members(cobj)
4086 B_members(cobj)
4087 C_members(cobj)
4088 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004089 assert_equal(2, cobj.val2)
4090 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004091 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004092 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004093enddef
4094
LemonBoy0ffc17a2023-08-20 18:09:11 +02004095" Test expansion of <stack> with class methods.
4096def Test_stack_expansion_with_methods()
4097 var lines =<< trim END
4098 vim9script
4099
4100 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004101 def M1()
4102 F0()
4103 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02004104 endclass
4105
4106 def F0()
Ernie Rael16cdfa62024-04-02 19:05:39 +02004107 assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
LemonBoy0ffc17a2023-08-20 18:09:11 +02004108 enddef
4109
4110 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004111 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02004112 enddef
4113
4114 F()
4115 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004116 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02004117enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004118
4119" Test the return type of the new() constructor
4120def Test_new_return_type()
4121 # new() uses the default return type and there is no return statement
4122 var lines =<< trim END
4123 vim9script
4124
4125 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004126 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004127
4128 def new(this._bufnr)
4129 if !bufexists(this._bufnr)
4130 this._bufnr = -1
4131 endif
4132 enddef
4133 endclass
4134
4135 var c = C.new(12345)
4136 assert_equal('object<C>', typename(c))
4137
4138 var v1: C
4139 v1 = C.new(12345)
4140 assert_equal('object<C>', typename(v1))
4141
4142 def F()
4143 var v2: C
4144 v2 = C.new(12345)
4145 assert_equal('object<C>', typename(v2))
4146 enddef
4147 F()
4148 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004149 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004150
4151 # new() uses the default return type and an empty 'return' statement
4152 lines =<< trim END
4153 vim9script
4154
4155 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004156 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004157
4158 def new(this._bufnr)
4159 if !bufexists(this._bufnr)
4160 this._bufnr = -1
4161 return
4162 endif
4163 enddef
4164 endclass
4165
4166 var c = C.new(12345)
4167 assert_equal('object<C>', typename(c))
4168
4169 var v1: C
4170 v1 = C.new(12345)
4171 assert_equal('object<C>', typename(v1))
4172
4173 def F()
4174 var v2: C
4175 v2 = C.new(12345)
4176 assert_equal('object<C>', typename(v2))
4177 enddef
4178 F()
4179 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004180 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004181
4182 # new() uses "any" return type and returns "this"
4183 lines =<< trim END
4184 vim9script
4185
4186 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004187 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004188
4189 def new(this._bufnr): any
4190 if !bufexists(this._bufnr)
4191 this._bufnr = -1
4192 return this
4193 endif
4194 enddef
4195 endclass
4196 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004197 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004198
4199 # new() uses 'Dict' return type and returns a Dict
4200 lines =<< trim END
4201 vim9script
4202
4203 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004204 var _state: dict<any>
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004205
4206 def new(): dict<any>
4207 this._state = {}
4208 return this._state
4209 enddef
4210 endclass
4211
4212 var c = C.new()
4213 assert_equal('object<C>', typename(c))
4214 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004215 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004216enddef
4217
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004218" Test for checking a member initialization type at run time.
4219def Test_runtime_type_check_for_member_init()
4220 var lines =<< trim END
4221 vim9script
4222
4223 var retnum: bool = false
4224
4225 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004226 retnum = !retnum
4227 if retnum
4228 return 1
4229 else
4230 return "hello"
4231 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004232 enddef
4233
4234 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004235 var _foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004236 endclass
4237
4238 var c1 = C.new()
4239 var c2 = C.new()
4240 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004241 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004242enddef
4243
4244" Test for locking a variable referring to an object and reassigning to another
4245" object.
Ernie Raelee865f32023-09-29 19:53:55 +02004246def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004247 var lines =<< trim END
4248 vim9script
4249
4250 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004251 var val: number
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004252 def new(this.val)
4253 enddef
4254 endclass
4255
4256 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
4257 lockvar 2 some_dict
4258
4259 var current: C
4260 current = some_dict['c']
4261 assert_equal(3, current.val)
4262 current = some_dict['b']
4263 assert_equal(2, current.val)
4264
4265 def F()
4266 current = some_dict['c']
4267 enddef
4268
4269 def G()
4270 current = some_dict['b']
4271 enddef
4272
4273 F()
4274 assert_equal(3, current.val)
4275 G()
4276 assert_equal(2, current.val)
4277 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004278 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004279enddef
4280
Ernie Raelee865f32023-09-29 19:53:55 +02004281" Test trying to lock an object variable from various places
4282def Test_lockvar_object_variable()
4283 # An object variable lockvar has several cases:
4284 # object method, scriptlevel, scriplevel from :def, :def arg
4285 # method arg, static method arg.
4286 # Also different depths
4287
Ernie Raelee865f32023-09-29 19:53:55 +02004288 #
4289 # lockvar of read-only object variable
4290 #
4291
4292 # read-only lockvar from object method
4293 var lines =<< trim END
4294 vim9script
4295
4296 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004297 var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004298 def Lock()
4299 lockvar this.val1
4300 enddef
4301 endclass
4302 var o = C.new(3)
4303 o.Lock()
4304 END
Ernie Rael64885642023-10-04 20:16:22 +02004305 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004306
4307 # read-only lockvar from scriptlevel
4308 lines =<< trim END
4309 vim9script
4310
4311 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004312 var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004313 endclass
4314 var o = C.new(3)
4315 lockvar o.val2
4316 END
4317 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
4318
4319 # read-only lockvar of scriptlevel variable from def
4320 lines =<< trim END
4321 vim9script
4322
4323 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004324 var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004325 endclass
4326 var o = C.new(3)
4327 def Lock()
4328 lockvar o.val3
4329 enddef
4330 Lock()
4331 END
4332 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
4333
4334 # read-only lockvar of def argument variable
4335 lines =<< trim END
4336 vim9script
4337
4338 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004339 var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004340 endclass
4341 def Lock(o: C)
4342 lockvar o.val4
4343 enddef
4344 Lock(C.new(3))
4345 END
4346 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
4347
Ernie Raelee865f32023-09-29 19:53:55 +02004348 # read-only lockvar from object method arg
4349 lines =<< trim END
4350 vim9script
4351
4352 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004353 var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004354 def Lock(c: C)
4355 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004356 enddef
4357 endclass
4358 var o = C.new(3)
4359 o.Lock(C.new(5))
4360 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004361 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004362
4363 # read-only lockvar from class method arg
4364 lines =<< trim END
4365 vim9script
4366
4367 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004368 var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004369 static def Lock(c: C)
4370 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004371 enddef
4372 endclass
4373 var o = C.new(3)
4374 C.Lock(o)
4375 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004376 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004377
4378 #
4379 # lockvar of public object variable
4380 #
4381
4382 # lockvar from object method
4383 lines =<< trim END
4384 vim9script
4385
4386 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004387 public var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004388 def Lock()
4389 lockvar this.val1
4390 enddef
4391 endclass
4392 var o = C.new(3)
4393 o.Lock()
4394 END
4395 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
4396
4397 # lockvar from scriptlevel
4398 lines =<< trim END
4399 vim9script
4400
4401 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004402 public var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004403 endclass
4404 var o = C.new(3)
4405 lockvar o.val2
4406 END
4407 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
4408
4409 # lockvar of scriptlevel variable from def
4410 lines =<< trim END
4411 vim9script
4412
4413 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004414 public var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004415 endclass
4416 var o = C.new(3)
4417 def Lock()
4418 lockvar o.val3
4419 enddef
4420 Lock()
4421 END
4422 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
4423
4424 # lockvar of def argument variable
4425 lines =<< trim END
4426 vim9script
4427
4428 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004429 public var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004430 endclass
4431 def Lock(o: C)
4432 lockvar o.val4
4433 enddef
4434 Lock(C.new(3))
4435 END
4436 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
4437
4438 # lockvar from object method arg
4439 lines =<< trim END
4440 vim9script
4441
4442 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004443 public var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004444 def Lock(c: C)
4445 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004446 enddef
4447 endclass
4448 var o = C.new(3)
4449 o.Lock(C.new(5))
4450 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004451 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004452
4453 # lockvar from class method arg
4454 lines =<< trim END
4455 vim9script
4456
4457 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004458 public var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004459 static def Lock(c: C)
4460 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004461 enddef
4462 endclass
4463 var o = C.new(3)
4464 C.Lock(o)
4465 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004466 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004467enddef
4468
4469" Test trying to lock a class variable from various places
4470def Test_lockvar_class_variable()
4471
4472 # lockvar bare static from object method
4473 var lines =<< trim END
4474 vim9script
4475
4476 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004477 public static var sval1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004478 def Lock()
4479 lockvar sval1
4480 enddef
4481 endclass
4482 var o = C.new()
4483 o.Lock()
4484 END
4485 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
4486
4487 # lockvar C.static from object method
4488 lines =<< trim END
4489 vim9script
4490
4491 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004492 public static var sval2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004493 def Lock()
4494 lockvar C.sval2
4495 enddef
4496 endclass
4497 var o = C.new()
4498 o.Lock()
4499 END
4500 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
4501
4502 # lockvar bare static from class method
4503 lines =<< trim END
4504 vim9script
4505
4506 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004507 public static var sval3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004508 static def Lock()
4509 lockvar sval3
4510 enddef
4511 endclass
4512 C.Lock()
4513 END
4514 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
4515
4516 # lockvar C.static from class method
4517 lines =<< trim END
4518 vim9script
4519
4520 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004521 public static var sval4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004522 static def Lock()
4523 lockvar C.sval4
4524 enddef
4525 endclass
4526 C.Lock()
4527 END
4528 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
4529
4530 # lockvar C.static from script level
4531 lines =<< trim END
4532 vim9script
4533
4534 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004535 public static var sval5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004536 endclass
4537 lockvar C.sval5
4538 END
4539 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
4540
4541 # lockvar o.static from script level
4542 lines =<< trim END
4543 vim9script
4544
4545 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004546 public static var sval6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004547 endclass
4548 var o = C.new()
4549 lockvar o.sval6
4550 END
4551 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
4552enddef
4553
4554" Test locking an argument to :def
4555def Test_lockvar_argument()
4556 # Lockvar a function arg
4557 var lines =<< trim END
4558 vim9script
4559
4560 def Lock(val: any)
4561 lockvar val
4562 enddef
4563
4564 var d = {a: 1, b: 2}
4565 Lock(d)
4566
4567 d->extend({c: 3})
4568 END
4569 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
4570
4571 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
4572 # class member in "C". This tests lval_root_is_arg.
4573 lines =<< trim END
4574 vim9script
4575
4576 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004577 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004578 endclass
4579
4580 def Lock2(sval: any)
4581 lockvar sval
4582 enddef
4583
4584 var o = C.new()
4585 Lock2(o)
4586 END
4587 v9.CheckSourceSuccess(lines)
4588
4589 # Lock a class.
4590 lines =<< trim END
4591 vim9script
4592
4593 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004594 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004595 endclass
4596
4597 def Lock2(sval: any)
4598 lockvar sval
4599 enddef
4600
4601 Lock2(C)
4602 END
Ernie Raelb077b582023-12-14 20:11:44 +01004603 v9.CheckSourceFailure(lines, 'E1405: Class "C" cannot be used as a value')
Ernie Raelee865f32023-09-29 19:53:55 +02004604
4605 # Lock an object.
4606 lines =<< trim END
4607 vim9script
4608
4609 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004610 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004611 endclass
4612
4613 def Lock2(sval: any)
4614 lockvar sval
4615 enddef
4616
4617 Lock2(C.new())
4618 END
4619 v9.CheckSourceSuccess(lines)
4620
4621 # In this case (unlike previous) "lockvar sval" is a class member.
4622 lines =<< trim END
4623 vim9script
4624
4625 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004626 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004627 def Lock2()
4628 lockvar sval
4629 enddef
4630 endclass
4631
4632
4633 var o = C.new()
4634 o.Lock2()
4635 END
4636 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4637enddef
4638
4639" Test that this can be locked without error
4640def Test_lockvar_this()
4641 # lockvar this
4642 var lines =<< trim END
4643 vim9script
4644 class C
4645 def TLock()
4646 lockvar this
4647 enddef
4648 endclass
4649 var o = C.new()
4650 o.TLock()
4651 END
4652 v9.CheckSourceSuccess(lines)
4653
4654 # lockvar four (four letter word, but not this)
4655 lines =<< trim END
4656 vim9script
4657 class C
4658 def TLock4()
4659 var four: number
4660 lockvar four
4661 enddef
4662 endclass
4663 var o = C.new()
4664 o.TLock4()
4665 END
4666 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4667
4668 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4669 lines =<< trim END
4670 vim9script
4671 class C
4672 def TLock5()
4673 var this5: number
4674 lockvar this5
4675 enddef
4676 endclass
4677 var o = C.new()
4678 o.TLock5()
4679 END
4680 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4681enddef
4682
4683" Test some general lockvar cases
4684def Test_lockvar_general()
4685 # lockvar an object and a class. It does nothing
4686 var lines =<< trim END
4687 vim9script
4688 class C
4689 endclass
4690 var o = C.new()
4691 lockvar o
4692 lockvar C
4693 END
4694 v9.CheckSourceSuccess(lines)
4695
4696 # Lock a list element that's nested in an object variable from a :def
4697 lines =<< trim END
4698 vim9script
4699
4700 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004701 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004702 endclass
4703 def Lock2(obj: any)
4704 lockvar obj.val[1]
4705 enddef
4706
4707 var o = C.new()
4708 Lock2(o)
4709 o.val[0] = [9]
4710 assert_equal([ [9], [2], [3] ], o.val)
4711 try
4712 o.val[1] = [999]
4713 call assert_false(true, 'assign should have failed')
4714 catch
4715 assert_exception('E741:')
4716 endtry
4717 o.val[2] = [8]
4718 assert_equal([ [9], [2], [8] ], o.val)
4719 END
4720 v9.CheckSourceSuccess(lines)
4721
4722 # Lock a list element that's nested in an object variable from scriptlevel
4723 lines =<< trim END
4724 vim9script
4725
4726 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004727 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004728 endclass
4729
4730 var o = C.new()
4731 lockvar o.val[1]
4732 o.val[0] = [9]
4733 assert_equal([ [9], [2], [3] ], o.val)
4734 try
4735 o.val[1] = [999]
4736 call assert_false(true, 'assign should have failed')
4737 catch
4738 assert_exception('E741:')
4739 endtry
4740 o.val[2] = [8]
4741 assert_equal([ [9], [2], [8] ], o.val)
4742 END
4743 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004744
4745 # lock a script level variable from an object method
4746 lines =<< trim END
4747 vim9script
4748
4749 class C
4750 def Lock()
4751 lockvar l
4752 enddef
4753 endclass
4754
4755 var l = [1]
4756 C.new().Lock()
4757 l[0] = 11
4758 END
4759 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4760
Ernie Rael03042a22023-11-11 08:53:32 +01004761 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004762 # in an object fetched via a script level list
4763 lines =<< trim END
4764 vim9script
4765
4766 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004767 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004768 def Lock()
4769 lockvar lc[0]._v1[1]
4770 enddef
4771 endclass
4772
4773 var l = [[1], [2], [3]]
4774 var o = C.new(l)
4775 var lc: list<C> = [ o ]
4776
4777 o.Lock()
4778 l[0] = [22]
4779 l[1] = [33]
4780 END
4781 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4782
4783 # similar to the previous test, except the locking code is executing
Ernie Rael03042a22023-11-11 08:53:32 +01004784 # in a class that does not own the protected variable.
4785 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02004786 # the same name.
4787 lines =<< trim END
4788 vim9script
4789
4790 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004791 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004792 def Lock(obj: any)
4793 lockvar lc[0]._v1[1]
4794 enddef
4795 endclass
4796
4797 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004798 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004799 endclass
4800
4801 var l = [[1], [2], [3]]
4802 var o = C.new(l)
4803 var lc: list<C> = [ o ]
4804
4805 var o2 = C2.new()
4806 o2.Lock(o)
4807 END
Ernie Rael03042a22023-11-11 08:53:32 +01004808 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004809enddef
4810
Ernie Rael9771b2a2023-10-07 22:05:40 +02004811" Test builtin islocked()
4812def Test_lockvar_islocked()
4813 # Can't lock class/object variable
4814 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01004815 # Lock item of variable's value (a list item)
4816 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02004817 var lines =<< trim END
4818 vim9script
4819
4820 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004821 var o0: list<list<number>> = [ [0], [1], [2]]
4822 var o1: list<list<number>> = [[10], [11], [12]]
4823 static var c0: list<list<number>> = [[20], [21], [22]]
4824 static var c1: list<list<number>> = [[30], [31], [32]]
Ernie Rael9771b2a2023-10-07 22:05:40 +02004825 endclass
4826
4827 def LockIt(arg: any)
4828 lockvar arg
4829 enddef
4830
4831 def UnlockIt(arg: any)
4832 unlockvar arg
4833 enddef
4834
4835 var obj = C.new()
4836 #lockvar obj.o1 # can't lock something you can't write to
4837
4838 try
4839 lockvar obj.o1 # can't lock something you can't write to
4840 call assert_false(1, '"lockvar obj.o1" should have failed')
4841 catch
4842 call assert_exception('E1335:')
4843 endtry
4844
4845 LockIt(obj.o1) # but can lock it's value
4846 assert_equal(1, islocked("obj.o1"))
4847 assert_equal(1, islocked("obj.o1[0]"))
4848 assert_equal(1, islocked("obj.o1[1]"))
4849 UnlockIt(obj.o1)
4850 assert_equal(0, islocked("obj.o1"))
4851 assert_equal(0, islocked("obj.o1[0]"))
4852
4853 lockvar obj.o1[0]
4854 assert_equal(0, islocked("obj.o1"))
4855 assert_equal(1, islocked("obj.o1[0]"))
4856 assert_equal(0, islocked("obj.o1[1]"))
4857 unlockvar obj.o1[0]
4858 assert_equal(0, islocked("obj.o1"))
4859 assert_equal(0, islocked("obj.o1[0]"))
4860
4861 # Same thing, but with a static
4862
4863 try
4864 lockvar C.c1 # can't lock something you can't write to
4865 call assert_false(1, '"lockvar C.c1" should have failed')
4866 catch
4867 call assert_exception('E1335:')
4868 endtry
4869
4870 LockIt(C.c1) # but can lock it's value
4871 assert_equal(1, islocked("C.c1"))
4872 assert_equal(1, islocked("C.c1[0]"))
4873 assert_equal(1, islocked("C.c1[1]"))
4874 UnlockIt(C.c1)
4875 assert_equal(0, islocked("C.c1"))
4876 assert_equal(0, islocked("C.c1[0]"))
4877
4878 lockvar C.c1[0]
4879 assert_equal(0, islocked("C.c1"))
4880 assert_equal(1, islocked("C.c1[0]"))
4881 assert_equal(0, islocked("C.c1[1]"))
4882 unlockvar C.c1[0]
4883 assert_equal(0, islocked("C.c1"))
4884 assert_equal(0, islocked("C.c1[0]"))
4885 END
4886 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02004887
4888 # Do islocked() from an object method
4889 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02004890 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02004891 vim9script
4892
4893 var l0o0 = [ [0], [1], [2]]
4894 var l0o1 = [ [10], [11], [12]]
4895 var l0c0 = [[120], [121], [122]]
4896 var l0c1 = [[130], [131], [132]]
4897
4898 class C0
Doug Kearns74da0ee2023-12-14 20:26:26 +01004899 var o0: list<list<number>> = l0o0
4900 var o1: list<list<number>> = l0o1
4901 static var c0: list<list<number>> = l0c0
4902 static var c1: list<list<number>> = l0c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004903 def Islocked(arg: string): number
4904 return islocked(arg)
4905 enddef
4906 static def SIslocked(arg: string): number
4907 return islocked(arg)
4908 enddef
4909 endclass
4910
4911 var l2o0 = [[20000], [20001], [20002]]
4912 var l2o1 = [[20010], [20011], [20012]]
4913 var l2c0 = [[20120], [20121], [20122]]
4914 var l2c1 = [[20130], [20131], [20132]]
4915
4916 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004917 var o0: list<list<number>> = l2o0
4918 var o1: list<list<number>> = l2o1
4919 static var c0: list<list<number>> = l2c0
4920 static var c1: list<list<number>> = l2c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004921 def Islocked(arg: string): number
4922 return islocked(arg)
4923 enddef
4924 static def SIslocked(arg: string): number
4925 return islocked(arg)
4926 enddef
4927 endclass
4928
4929 var obj0 = C0.new()
4930 var obj2 = C2.new()
4931
4932 var l = [ obj0, null_object, obj2 ]
4933
4934 # lock list, object func access through script var expr
4935 assert_equal(0, obj0.Islocked("l[0].o0"))
4936 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
4937 lockvar l0o0
4938 assert_equal(1, obj0.Islocked("l[0].o0"))
4939 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
4940
4941 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
4942
4943 # lock list element, object func access through script var expr
4944 lockvar l0o1[1]
4945 assert_equal(0, obj0.Islocked("this.o1[0]"))
4946 assert_equal(1, obj0.Islocked("this.o1[1]"))
4947
4948 assert_equal(0, obj0.Islocked("this.o1"))
4949 lockvar l0o1
4950 assert_equal(1, obj0.Islocked("this.o1"))
4951 unlockvar l0o1
4952
4953 lockvar l0c1[1]
4954
4955 # static by class name member expr from same class
4956 assert_equal(0, obj0.Islocked("C0.c1[0]"))
4957 assert_equal(1, obj0.Islocked("C0.c1[1]"))
4958 # static by bare name member expr from same class
4959 assert_equal(0, obj0.Islocked("c1[0]"))
4960 assert_equal(1, obj0.Islocked("c1[1]"))
4961
4962 # static by class name member expr from other class
4963 assert_equal(0, obj2.Islocked("C0.c1[0]"))
4964 assert_equal(1, obj2.Islocked("C0.c1[1]"))
4965 # static by bare name member expr from other class
4966 assert_equal(0, obj2.Islocked("c1[0]"))
4967 assert_equal(0, obj2.Islocked("c1[1]"))
4968
4969
4970 # static by bare name in same class
4971 assert_equal(0, obj0.Islocked("c0"))
4972 lockvar l0c0
4973 assert_equal(1, obj0.Islocked("c0"))
4974
4975 #
4976 # similar stuff, but use static method
4977 #
4978
4979 unlockvar l0o0
4980
4981 # lock list, object func access through script var expr
4982 assert_equal(0, C0.SIslocked("l[0].o0"))
4983 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
4984 lockvar l0o0
4985 assert_equal(1, C0.SIslocked("l[0].o0"))
4986 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
4987
4988 unlockvar l0o1
4989
4990 # can't access "this" from class method
4991 try
4992 C0.SIslocked("this.o1[0]")
4993 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
4994 catch
4995 call assert_exception('E121: Undefined variable: this')
4996 endtry
4997
4998 lockvar l0c1[1]
4999
5000 # static by class name member expr from same class
5001 assert_equal(0, C0.SIslocked("C0.c1[0]"))
5002 assert_equal(1, C0.SIslocked("C0.c1[1]"))
5003 # static by bare name member expr from same class
5004 assert_equal(0, C0.SIslocked("c1[0]"))
5005 assert_equal(1, C0.SIslocked("c1[1]"))
5006
5007 # static by class name member expr from other class
5008 assert_equal(0, C2.SIslocked("C0.c1[0]"))
5009 assert_equal(1, C2.SIslocked("C0.c1[1]"))
5010 # static by bare name member expr from other class
5011 assert_equal(0, C2.SIslocked("c1[0]"))
5012 assert_equal(0, C2.SIslocked("c1[1]"))
5013
5014
5015 # static by bare name in same class
5016 unlockvar l0c0
5017 assert_equal(0, C0.SIslocked("c0"))
5018 lockvar l0c0
5019 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02005020 END
Ernie Rael4c8da022023-10-11 21:35:11 +02005021 v9.CheckSourceSuccess(lines)
5022
5023 # Check islocked class/object from various places.
5024 lines =<< trim END
5025 vim9script
5026
5027 class C
5028 def Islocked(arg: string): number
5029 return islocked(arg)
5030 enddef
5031 static def SIslocked(arg: string): number
5032 return islocked(arg)
5033 enddef
5034 endclass
5035 var obj = C.new()
5036
5037 # object method
5038 assert_equal(0, obj.Islocked("this"))
5039 assert_equal(0, obj.Islocked("C"))
5040
5041 # class method
5042 ### assert_equal(0, C.SIslocked("this"))
5043 assert_equal(0, C.SIslocked("C"))
5044
5045 #script level
5046 var v: number
5047 v = islocked("C")
5048 assert_equal(0, v)
5049 v = islocked("obj")
5050 assert_equal(0, v)
5051 END
5052 v9.CheckSourceSuccess(lines)
5053enddef
5054
5055def Test_lockvar_islocked_notfound()
5056 # Try non-existent things
5057 var lines =<< trim END
5058 vim9script
5059
5060 class C
5061 def Islocked(arg: string): number
5062 return islocked(arg)
5063 enddef
5064 static def SIslocked(arg: string): number
5065 return islocked(arg)
5066 enddef
5067 endclass
5068 var obj = C.new()
5069 assert_equal(-1, obj.Islocked("anywhere"))
5070 assert_equal(-1, C.SIslocked("notanywhere"))
5071 END
5072 v9.CheckSourceSuccess(lines)
5073
5074 # Something not found of the form "name1.name2" is an error
5075 lines =<< trim END
5076 vim9script
5077
5078 islocked("one.two")
5079 END
5080 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
5081
5082 lines =<< trim END
5083 vim9script
5084
5085 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005086 var val = { key: "value" }
Ernie Rael4c8da022023-10-11 21:35:11 +02005087 def Islocked(arg: string): number
5088 return islocked(arg)
5089 enddef
5090 endclass
5091 var obj = C.new()
5092 obj.Islocked("this.val.not_there"))
5093 END
5094 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
5095
5096 lines =<< trim END
5097 vim9script
5098
5099 class C
5100 def Islocked(arg: string): number
5101 return islocked(arg)
5102 enddef
5103 endclass
5104 var obj = C.new()
5105 obj.Islocked("this.notobjmember")
5106 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005107 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02005108
5109 # access a script variable through methods
5110 lines =<< trim END
5111 vim9script
5112
5113 var l = [1]
5114 class C
5115 def Islocked(arg: string): number
5116 return islocked(arg)
5117 enddef
5118 static def SIslocked(arg: string): number
5119 return islocked(arg)
5120 enddef
5121 endclass
5122 var obj = C.new()
5123 assert_equal(0, obj.Islocked("l"))
5124 assert_equal(0, C.SIslocked("l"))
5125 lockvar l
5126 assert_equal(1, obj.Islocked("l"))
5127 assert_equal(1, C.SIslocked("l"))
5128 END
5129 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02005130enddef
5131
Ernie Rael03042a22023-11-11 08:53:32 +01005132" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005133def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005134 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005135 var lines =<< trim END
5136 vim9script
5137
5138 class A
5139 def _Foo(): number
5140 return 1234
5141 enddef
5142 endclass
5143 var a = A.new()
5144 a._Foo()
5145 END
Ernie Rael03042a22023-11-11 08:53:32 +01005146 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005147
Ernie Rael03042a22023-11-11 08:53:32 +01005148 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005149 lines =<< trim END
5150 vim9script
5151
5152 class A
5153 def _Foo(): number
5154 return 1234
5155 enddef
5156 endclass
5157 def T()
5158 var a = A.new()
5159 a._Foo()
5160 enddef
5161 T()
5162 END
Ernie Rael03042a22023-11-11 08:53:32 +01005163 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005164
Ernie Rael03042a22023-11-11 08:53:32 +01005165 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005166 lines =<< trim END
5167 vim9script
5168
5169 class A
5170 def _Foo(): number
5171 return 1234
5172 enddef
5173 def Bar(): number
5174 return this._Foo()
5175 enddef
5176 endclass
5177 var a = A.new()
5178 assert_equal(1234, a.Bar())
5179 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005180 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005181
Ernie Rael03042a22023-11-11 08:53:32 +01005182 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005183 lines =<< trim END
5184 vim9script
5185
5186 class A
5187 def _Foo(): number
5188 return 1234
5189 enddef
5190 def Bar(): number
5191 return this._Foo()
5192 enddef
5193 endclass
5194 def T()
5195 var a = A.new()
5196 assert_equal(1234, a.Bar())
5197 enddef
5198 T()
5199 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005200 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005201
Ernie Rael03042a22023-11-11 08:53:32 +01005202 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005203 lines =<< trim END
5204 vim9script
5205
5206 class A
5207 def _Foo(): number
5208 return 1234
5209 enddef
5210 def Bar(): number
5211 return _Foo()
5212 enddef
5213 endclass
5214 var a = A.new()
5215 a.Bar()
5216 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005217 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005218
Ernie Rael03042a22023-11-11 08:53:32 +01005219 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005220 lines =<< trim END
5221 vim9script
5222
5223 class A
5224 def _Foo(): number
5225 return 1234
5226 enddef
5227 endclass
5228 A._Foo()
5229 END
Ernie Rael03042a22023-11-11 08:53:32 +01005230 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005231
Ernie Rael03042a22023-11-11 08:53:32 +01005232 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005233 lines =<< trim END
5234 vim9script
5235
5236 class A
5237 def _Foo()
5238 enddef
5239 def _Foo()
5240 enddef
5241 endclass
5242 var a = A.new()
5243 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005244 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005245
Ernie Rael03042a22023-11-11 08:53:32 +01005246 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005247 lines =<< trim END
5248 vim9script
5249
5250 class A
5251 def _Foo()
5252 enddef
5253 def Foo()
5254 enddef
5255 endclass
5256 var a = A.new()
5257 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005258 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005259
Ernie Rael03042a22023-11-11 08:53:32 +01005260 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005261 lines =<< trim END
5262 vim9script
5263
5264 class A
5265 def Foo()
5266 enddef
5267 def _Foo()
5268 enddef
5269 endclass
5270 var a = A.new()
5271 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005272 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005273
Ernie Rael03042a22023-11-11 08:53:32 +01005274 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005275 lines =<< trim END
5276 vim9script
5277
5278 class A
5279 def Foo(): number
5280 return 100
5281 enddef
5282 def _Bar(): number
5283 return 200
5284 enddef
5285 def _Baz()
5286 assert_equal(100, this.Foo())
5287 assert_equal(200, this._Bar())
5288 enddef
5289 def T()
5290 this._Baz()
5291 enddef
5292 endclass
5293 var a = A.new()
5294 a.T()
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 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005299 lines =<< trim END
5300 vim9script
5301
5302 class A
5303 def _Foo(): number
5304 return 100
5305 enddef
5306 endclass
5307 class B
5308 def Foo(): number
5309 var a = A.new()
5310 a._Foo()
5311 enddef
5312 endclass
5313 var b = B.new()
5314 b.Foo()
5315 END
Ernie Rael03042a22023-11-11 08:53:32 +01005316 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005317
Ernie Rael03042a22023-11-11 08:53:32 +01005318 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005319 lines =<< trim END
5320 vim9script
5321 class A
5322 def _Foo(): number
5323 return 1234
5324 enddef
5325 endclass
5326 class B extends A
5327 def Bar()
5328 enddef
5329 endclass
5330 class C extends B
5331 def Baz(): number
5332 return this._Foo()
5333 enddef
5334 endclass
5335 var c = C.new()
5336 assert_equal(1234, c.Baz())
5337 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005338 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005339
Ernie Rael03042a22023-11-11 08:53:32 +01005340 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005341 lines =<< trim END
5342 vim9script
5343 class A
5344 def _Foo(): number
5345 return 1234
5346 enddef
5347 endclass
5348 class B extends A
5349 def Bar()
5350 enddef
5351 endclass
5352 class C extends B
5353 def Baz(): number
5354 enddef
5355 endclass
5356 var c = C.new()
5357 assert_equal(1234, c._Foo())
5358 END
Ernie Rael03042a22023-11-11 08:53:32 +01005359 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005360
5361 # Using "_" prefix in a method name should fail outside of a class
5362 lines =<< trim END
5363 vim9script
5364 def _Foo(): number
5365 return 1234
5366 enddef
5367 var a = _Foo()
5368 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005369 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005370enddef
5371
Ernie Rael03042a22023-11-11 08:53:32 +01005372" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005373def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005374 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005375 var lines =<< trim END
5376 vim9script
5377
5378 class A
5379 static def _Foo(): number
5380 return 1234
5381 enddef
5382 endclass
5383 A._Foo()
5384 END
Ernie Rael03042a22023-11-11 08:53:32 +01005385 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005386
Ernie Rael03042a22023-11-11 08:53:32 +01005387 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005388 lines =<< trim END
5389 vim9script
5390
5391 class A
5392 static def _Foo(): number
5393 return 1234
5394 enddef
5395 endclass
5396 def T()
5397 A._Foo()
5398 enddef
5399 T()
5400 END
Ernie Rael03042a22023-11-11 08:53:32 +01005401 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005402
Ernie Rael03042a22023-11-11 08:53:32 +01005403 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005404 lines =<< trim END
5405 vim9script
5406
5407 class A
5408 static def _Foo(): number
5409 return 1234
5410 enddef
5411 endclass
5412 var a = A.new()
5413 a._Foo()
5414 END
Ernie Rael03042a22023-11-11 08:53:32 +01005415 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005416
Ernie Rael03042a22023-11-11 08:53:32 +01005417 # Try calling a class protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005418 lines =<< trim END
5419 vim9script
5420
5421 class A
5422 static def _Foo(): number
5423 return 1234
5424 enddef
5425 endclass
5426 def T()
5427 var a = A.new()
5428 a._Foo()
5429 enddef
5430 T()
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 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005435 lines =<< trim END
5436 vim9script
5437
5438 class A
5439 static def _Foo(): number
5440 return 1234
5441 enddef
5442 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005443 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005444 enddef
5445 endclass
5446 var a = A.new()
5447 a.Bar()
5448 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005449 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005450
Ernie Rael03042a22023-11-11 08:53:32 +01005451 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005452 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005453 lines =<< trim END
5454 vim9script
5455
5456 class A
5457 static def _Foo1(): number
5458 return 1234
5459 enddef
5460 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005461 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005462 enddef
5463 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005464 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005465 enddef
5466 endclass
5467 var a = A.new()
5468 a.Bar()
5469 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005470 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005471
Ernie Rael03042a22023-11-11 08:53:32 +01005472 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005473 lines =<< trim END
5474 vim9script
5475
5476 class A
5477 static def _Foo()
5478 enddef
5479 static def Foo()
5480 enddef
5481 endclass
5482 var a = A.new()
5483 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005484 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005485
Ernie Rael03042a22023-11-11 08:53:32 +01005486 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005487 lines =<< trim END
5488 vim9script
5489
5490 class A
5491 static def _Foo(): number
5492 return 1234
5493 enddef
5494 endclass
5495 class B
5496 def Foo(): number
5497 return A._Foo()
5498 enddef
5499 endclass
5500 var b = B.new()
5501 assert_equal(1234, b.Foo())
5502 END
Ernie Rael03042a22023-11-11 08:53:32 +01005503 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005504
Ernie Rael03042a22023-11-11 08:53:32 +01005505 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005506 lines =<< trim END
5507 vim9script
5508 class A
5509 static def _Foo(): number
5510 return 1234
5511 enddef
5512 endclass
5513 class B extends A
5514 def Bar()
5515 enddef
5516 endclass
5517 class C extends B
5518 def Baz(): number
5519 return A._Foo()
5520 enddef
5521 endclass
5522 var c = C.new()
5523 assert_equal(1234, c.Baz())
5524 END
Ernie Rael03042a22023-11-11 08:53:32 +01005525 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005526
Ernie Rael03042a22023-11-11 08:53:32 +01005527 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005528 lines =<< trim END
5529 vim9script
5530 class A
5531 static def _Foo(): number
5532 return 1234
5533 enddef
5534 endclass
5535 class B extends A
5536 def Bar()
5537 enddef
5538 endclass
5539 class C extends B
5540 static def Baz(): number
5541 return A._Foo()
5542 enddef
5543 endclass
5544 assert_equal(1234, C.Baz())
5545 END
Ernie Rael03042a22023-11-11 08:53:32 +01005546 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005547
Ernie Rael03042a22023-11-11 08:53:32 +01005548 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005549 lines =<< trim END
5550 vim9script
5551 class A
5552 static def _Foo(): number
5553 return 1234
5554 enddef
5555 endclass
5556 class B extends A
5557 def Bar()
5558 enddef
5559 endclass
5560 class C extends B
5561 def Baz(): number
5562 enddef
5563 endclass
5564 var c = C.new()
5565 assert_equal(1234, C._Foo())
5566 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005567 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005568enddef
5569
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005570" Test for using the return value of a class/object method as a function
5571" argument.
5572def Test_objmethod_funcarg()
5573 var lines =<< trim END
5574 vim9script
5575
5576 class C
5577 def Foo(): string
5578 return 'foo'
5579 enddef
5580 endclass
5581
5582 def Bar(a: number, s: string): string
5583 return s
5584 enddef
5585
5586 def Baz(c: C)
5587 assert_equal('foo', Bar(10, c.Foo()))
5588 enddef
5589
5590 var t = C.new()
5591 Baz(t)
5592 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005593 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005594
5595 lines =<< trim END
5596 vim9script
5597
5598 class C
5599 static def Foo(): string
5600 return 'foo'
5601 enddef
5602 endclass
5603
5604 def Bar(a: number, s: string): string
5605 return s
5606 enddef
5607
5608 def Baz()
5609 assert_equal('foo', Bar(10, C.Foo()))
5610 enddef
5611
5612 Baz()
5613 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005614 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005615enddef
5616
Ernie Raelcf138d42023-09-06 20:45:03 +02005617def Test_static_inheritence()
5618 # subclasses get their own static copy
5619 var lines =<< trim END
5620 vim9script
5621
5622 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005623 static var _svar: number
5624 var _mvar: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005625 def new()
5626 _svar = 1
5627 this._mvar = 101
5628 enddef
5629 def AccessObject(): number
5630 return this._mvar
5631 enddef
5632 def AccessStaticThroughObject(): number
5633 return _svar
5634 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005635 endclass
5636
5637 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005638 def new()
5639 this._mvar = 102
5640 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005641 endclass
5642
5643 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005644 def new()
5645 this._mvar = 103
5646 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005647
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005648 def AccessPrivateStaticThroughClassName(): number
5649 assert_equal(1, A._svar)
5650 return 444
5651 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005652 endclass
5653
5654 var oa = A.new()
5655 var ob = B.new()
5656 var oc = C.new()
5657 assert_equal(101, oa.AccessObject())
5658 assert_equal(102, ob.AccessObject())
5659 assert_equal(103, oc.AccessObject())
5660
Ernie Rael03042a22023-11-11 08:53:32 +01005661 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005662
5663 # verify object properly resolves to correct static
5664 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005665 assert_equal(1, ob.AccessStaticThroughObject())
5666 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005667 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005668 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005669enddef
5670
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005671" Test for declaring duplicate object and class members
5672def Test_dup_member_variable()
5673 # Duplicate member variable
5674 var lines =<< trim END
5675 vim9script
5676 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005677 var val = 10
5678 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005679 endclass
5680 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005681 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005682
Ernie Rael03042a22023-11-11 08:53:32 +01005683 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005684 lines =<< trim END
5685 vim9script
5686 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005687 var _val = 10
5688 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005689 endclass
5690 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005691 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005692
5693 # Duplicate public member variable
5694 lines =<< trim END
5695 vim9script
5696 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005697 public var val = 10
5698 public var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005699 endclass
5700 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005701 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005702
Ernie Rael03042a22023-11-11 08:53:32 +01005703 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005704 lines =<< trim END
5705 vim9script
5706 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005707 var val = 10
5708 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005709 endclass
5710 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005711 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005712
Ernie Rael03042a22023-11-11 08:53:32 +01005713 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005714 lines =<< trim END
5715 vim9script
5716 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005717 var _val = 20
5718 public var val = 10
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005719 endclass
5720 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005721 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005722
5723 # Duplicate class member variable
5724 lines =<< trim END
5725 vim9script
5726 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005727 static var s: string = "abc"
5728 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005729 endclass
5730 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005731 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005732
Ernie Rael03042a22023-11-11 08:53:32 +01005733 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005734 lines =<< trim END
5735 vim9script
5736 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005737 public static var s: string = "abc"
5738 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005739 endclass
5740 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005741 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005742
5743 # Duplicate class and object member variable
5744 lines =<< trim END
5745 vim9script
5746 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005747 static var val = 10
5748 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005749 def new()
5750 enddef
5751 endclass
5752 var c = C.new()
5753 assert_equal(10, C.val)
5754 assert_equal(20, c.val)
5755 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005756 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005757
5758 # Duplicate object member variable in a derived class
5759 lines =<< trim END
5760 vim9script
5761 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005762 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005763 endclass
5764 class B extends A
5765 endclass
5766 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005767 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005768 endclass
5769 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005770 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005771
Ernie Rael03042a22023-11-11 08:53:32 +01005772 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005773 lines =<< trim END
5774 vim9script
5775 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005776 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005777 endclass
5778 class B extends A
5779 endclass
5780 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005781 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005782 endclass
5783 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005784 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005785
Ernie Rael03042a22023-11-11 08:53:32 +01005786 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005787 lines =<< trim END
5788 vim9script
5789 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005790 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005791 endclass
5792 class B extends A
5793 endclass
5794 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005795 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005796 endclass
5797 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005798 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005799
5800 # Duplicate object member variable in a derived class
5801 lines =<< trim END
5802 vim9script
5803 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005804 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005805 endclass
5806 class B extends A
5807 endclass
5808 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005809 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005810 endclass
5811 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005812 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005813
5814 # Two member variables with a common prefix
5815 lines =<< trim END
5816 vim9script
5817 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005818 public static var svar2: number
5819 public static var svar: number
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005820 endclass
5821 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005822 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005823enddef
5824
Ernie Rael03042a22023-11-11 08:53:32 +01005825" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005826def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01005827 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005828 var lines =<< trim END
5829 vim9script
5830 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005831 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005832 def GetVal(): number
5833 return this._val
5834 enddef
5835 endclass
5836 def T()
5837 var a = A.new()
5838 a._val = 20
5839 enddef
5840 T()
5841 END
Ernie Rael03042a22023-11-11 08:53:32 +01005842 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005843
Ernie Rael03042a22023-11-11 08:53:32 +01005844 # access a non-existing protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005845 lines =<< trim END
5846 vim9script
5847 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005848 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005849 endclass
5850 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005851 var a = A.new()
5852 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005853 enddef
5854 T()
5855 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005856 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005857
Ernie Rael03042a22023-11-11 08:53:32 +01005858 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005859 lines =<< trim END
5860 vim9script
5861 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005862 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005863 endclass
5864 def T()
5865 var a = A.new()
5866 var x = a._val
5867 enddef
5868 T()
5869 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005870 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005871
Ernie Rael03042a22023-11-11 08:53:32 +01005872 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005873 lines =<< trim END
5874 vim9script
5875 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005876 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005877 endclass
5878 def T()
5879 var a = A.new()
5880 a._val = 3
5881 enddef
5882 T()
5883 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005884 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005885
Ernie Rael03042a22023-11-11 08:53:32 +01005886 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005887 lines =<< trim END
5888 vim9script
5889 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005890 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005891 endclass
5892 def T()
5893 var x = A._val
5894 enddef
5895 T()
5896 END
Ernie Rael03042a22023-11-11 08:53:32 +01005897 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02005898
Ernie Rael03042a22023-11-11 08:53:32 +01005899 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005900 lines =<< trim END
5901 vim9script
5902 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005903 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005904 endclass
5905 def T()
5906 A._val = 3
5907 enddef
5908 T()
5909 END
Ernie Rael03042a22023-11-11 08:53:32 +01005910 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005911enddef
5912
5913" Test for changing the member access of an interface in a implementation class
5914def Test_change_interface_member_access()
5915 var lines =<< trim END
5916 vim9script
5917 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005918 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005919 endinterface
5920 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005921 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005922 endclass
5923 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005924 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005925
5926 lines =<< trim END
5927 vim9script
5928 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005929 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005930 endinterface
5931 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005932 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005933 endclass
5934 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005935 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005936enddef
5937
5938" Test for trying to change a readonly member from a def function
5939def Test_readonly_member_change_in_def_func()
5940 var lines =<< trim END
5941 vim9script
5942 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005943 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005944 endclass
5945 def T()
5946 var a = A.new()
5947 a.val = 20
5948 enddef
5949 T()
5950 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005951 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005952enddef
5953
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005954" Test for reading and writing a class member from a def function
5955def Test_modify_class_member_from_def_function()
5956 var lines =<< trim END
5957 vim9script
5958 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005959 var var1: number = 10
5960 public static var var2: list<number> = [1, 2]
5961 public static var var3: dict<number> = {a: 1, b: 2}
5962 static var _priv_var4: number = 40
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005963 endclass
5964 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02005965 assert_equal([1, 2], A.var2)
5966 assert_equal({a: 1, b: 2}, A.var3)
5967 A.var2 = [3, 4]
5968 A.var3 = {c: 3, d: 4}
5969 assert_equal([3, 4], A.var2)
5970 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael03042a22023-11-11 08:53:32 +01005971 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005972 enddef
5973 T()
5974 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005975 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005976enddef
5977
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005978" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005979def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005980 var lines =<< trim END
5981 vim9script
5982 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005983 public static var svar1: list<number> = [1]
5984 public static var svar2: list<number> = [2]
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005985 endclass
5986
5987 A.svar1->add(3)
5988 A.svar2->add(4)
5989 assert_equal([1, 3], A.svar1)
5990 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005991
5992 def Foo()
5993 A.svar1->add(7)
5994 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005995 assert_equal([1, 3, 7], A.svar1)
5996 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005997 enddef
5998 Foo()
5999 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006000 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006001
6002 # Cannot read from a class variable using an object in script context
6003 lines =<< trim END
6004 vim9script
6005 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006006 public var var1: number
6007 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006008 endclass
6009
6010 var a = A.new()
6011 echo a.svar2
6012 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006013 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006014
6015 # Cannot write to a class variable using an object in script context
6016 lines =<< trim END
6017 vim9script
6018 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006019 public var var1: number
6020 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006021 endclass
6022
6023 var a = A.new()
6024 a.svar2 = [2]
6025 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006026 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006027
6028 # Cannot read from a class variable using an object in def method context
6029 lines =<< trim END
6030 vim9script
6031 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006032 public var var1: number
6033 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006034 endclass
6035
6036 def T()
6037 var a = A.new()
6038 echo a.svar2
6039 enddef
6040 T()
6041 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006042 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006043
6044 # Cannot write to a class variable using an object in def method context
6045 lines =<< trim END
6046 vim9script
6047 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006048 public var var1: number
6049 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006050 endclass
6051
6052 def T()
6053 var a = A.new()
6054 a.svar2 = [2]
6055 enddef
6056 T()
6057 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006058 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006059enddef
6060
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006061" Test for using a interface method using a child object
6062def Test_interface_method_from_child()
6063 var lines =<< trim END
6064 vim9script
6065
6066 interface A
6067 def Foo(): string
6068 endinterface
6069
6070 class B implements A
6071 def Foo(): string
6072 return 'foo'
6073 enddef
6074 endclass
6075
6076 class C extends B
6077 def Bar(): string
6078 return 'bar'
6079 enddef
6080 endclass
6081
6082 def T1(a: A)
6083 assert_equal('foo', a.Foo())
6084 enddef
6085
6086 def T2(b: B)
6087 assert_equal('foo', b.Foo())
6088 enddef
6089
6090 var c = C.new()
6091 T1(c)
6092 T2(c)
6093 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006094 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006095enddef
6096
6097" Test for using an interface method using a child object when it is overridden
6098" by the child class.
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01006099def Test_interface_overridden_method_from_child()
6100 var lines =<< trim END
6101 vim9script
6102
6103 interface A
6104 def Foo(): string
6105 endinterface
6106
6107 class B implements A
6108 def Foo(): string
6109 return 'b-foo'
6110 enddef
6111 endclass
6112
6113 class C extends B
6114 def Bar(): string
6115 return 'bar'
6116 enddef
6117 def Foo(): string
6118 return 'c-foo'
6119 enddef
6120 endclass
6121
6122 def T1(a: A)
6123 assert_equal('c-foo', a.Foo())
6124 enddef
6125
6126 def T2(b: B)
6127 assert_equal('c-foo', b.Foo())
6128 enddef
6129
6130 var c = C.new()
6131 T1(c)
6132 T2(c)
6133 END
6134 v9.CheckSourceSuccess(lines)
6135enddef
6136
6137" Test for interface inheritance
6138def Test_interface_inheritance()
6139 var lines =<< trim END
6140 vim9script
6141
6142 interface A
6143 def A_Fn(): string
6144 endinterface
6145
6146 interface B
6147 def B_Fn(): string
6148 endinterface
6149
6150 interface C
6151 def C_Fn(): string
6152 endinterface
6153
6154 class C1 implements A
6155 def A_Fn(): string
6156 return 'c1-a'
6157 enddef
6158 endclass
6159
6160 class C2 extends C1 implements B
6161 def B_Fn(): string
6162 return 'c2-b'
6163 enddef
6164 def A_Fn(): string
6165 return 'c2-a'
6166 enddef
6167 endclass
6168
6169 class C3 extends C2 implements C
6170 def C_Fn(): string
6171 return 'c3-c'
6172 enddef
6173 def A_Fn(): string
6174 return 'c3-a'
6175 enddef
6176 def B_Fn(): string
6177 return 'c3-b'
6178 enddef
6179 endclass
6180
6181 def T1(a: A, s: string)
6182 assert_equal(s, a.A_Fn())
6183 enddef
6184
6185 def T2(b: B, s: string)
6186 assert_equal(s, b.B_Fn())
6187 enddef
6188
6189 def T3(c: C, s: string)
6190 assert_equal(s, c.C_Fn())
6191 enddef
6192
6193 def T4(c1: C1)
6194 T1(c1, 'c3-a')
6195 enddef
6196
6197 def T5(c2: C2)
6198 T1(c2, 'c3-a')
6199 T2(c2, 'c3-b')
6200 enddef
6201
6202 def T6(c3: C3)
6203 T1(c3, 'c3-a')
6204 T2(c3, 'c3-b')
6205 T3(c3, 'c3-c')
6206 enddef
6207
6208 var o3 = C3.new()
6209 T4(o3)
6210 T5(o3)
6211 T6(o3)
6212 END
6213 v9.CheckSourceSuccess(lines)
6214
6215 # Both the parent and child classes implement the same interface
6216 lines =<< trim END
6217 vim9script
6218
6219 interface I
6220 def Foo(): string
6221 endinterface
6222
6223 class A implements I
6224 def Foo(): string
6225 return 'A-foo'
6226 enddef
6227 endclass
6228
6229 class B implements I
6230 def Foo(): string
6231 return 'B-foo'
6232 enddef
6233 endclass
6234
6235 def Bar(i1: I): string
6236 return i1.Foo()
6237 enddef
6238
6239 var b = B.new()
6240 assert_equal('B-foo', Bar(b))
6241 END
6242 v9.CheckSourceSuccess(lines)
6243enddef
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006244
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006245" Test for abstract methods
6246def Test_abstract_method()
6247 # Use two abstract methods
6248 var lines =<< trim END
6249 vim9script
6250 abstract class A
6251 def M1(): number
6252 return 10
6253 enddef
6254 abstract def M2(): number
6255 abstract def M3(): number
6256 endclass
6257 class B extends A
6258 def M2(): number
6259 return 20
6260 enddef
6261 def M3(): number
6262 return 30
6263 enddef
6264 endclass
6265 var b = B.new()
6266 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6267 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006268 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006269
6270 # Don't define an abstract method
6271 lines =<< trim END
6272 vim9script
6273 abstract class A
6274 abstract def Foo()
6275 endclass
6276 class B extends A
6277 endclass
6278 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006279 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006280
6281 # Use abstract method in a concrete class
6282 lines =<< trim END
6283 vim9script
6284 class A
6285 abstract def Foo()
6286 endclass
6287 class B extends A
6288 endclass
6289 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006290 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006291
6292 # Use abstract method in an interface
6293 lines =<< trim END
6294 vim9script
6295 interface A
6296 abstract def Foo()
6297 endinterface
6298 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006299 def Foo()
6300 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006301 endclass
6302 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006303 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6304
6305 # Use abstract static method in an interface
6306 lines =<< trim END
6307 vim9script
6308 interface A
6309 abstract static def Foo()
6310 enddef
6311 endinterface
6312 END
6313 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6314
6315 # Use abstract static variable in an interface
6316 lines =<< trim END
6317 vim9script
6318 interface A
6319 abstract static foo: number = 10
6320 endinterface
6321 END
6322 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006323
6324 # Abbreviate the "abstract" keyword
6325 lines =<< trim END
6326 vim9script
6327 class A
6328 abs def Foo()
6329 endclass
6330 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006331 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006332
6333 # Use "abstract" with a member variable
6334 lines =<< trim END
6335 vim9script
6336 abstract class A
6337 abstract this.val = 10
6338 endclass
6339 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006340 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006341
6342 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006343 lines =<< trim END
6344 vim9script
6345 abstract class A
6346 abstract static def Foo(): number
6347 endclass
6348 END
6349 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006350
6351 # Type mismatch between abstract method and concrete method
6352 lines =<< trim END
6353 vim9script
6354 abstract class A
6355 abstract def Foo(a: string, b: number): list<number>
6356 endclass
6357 class B extends A
6358 def Foo(a: number, b: string): list<string>
6359 return []
6360 enddef
6361 endclass
6362 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006363 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 +02006364
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006365 # Invoke an abstract method from a def function
6366 lines =<< trim END
6367 vim9script
6368 abstract class A
6369 abstract def Foo(): list<number>
6370 endclass
6371 class B extends A
6372 def Foo(): list<number>
6373 return [3, 5]
6374 enddef
6375 endclass
6376 def Bar(c: B)
6377 assert_equal([3, 5], c.Foo())
6378 enddef
6379 var b = B.new()
6380 Bar(b)
6381 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006382 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006383
6384 # Use a static method in an abstract class
6385 lines =<< trim END
6386 vim9script
6387 abstract class A
6388 static def Foo(): string
6389 return 'foo'
6390 enddef
6391 endclass
6392 assert_equal('foo', A.Foo())
6393 END
6394 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006395enddef
6396
6397" Test for calling a class method from a subclass
6398def Test_class_method_call_from_subclass()
6399 # class method call from a subclass
6400 var lines =<< trim END
6401 vim9script
6402
6403 class A
6404 static def Foo()
6405 echo "foo"
6406 enddef
6407 endclass
6408
6409 class B extends A
6410 def Bar()
6411 Foo()
6412 enddef
6413 endclass
6414
6415 var b = B.new()
6416 b.Bar()
6417 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006418 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006419enddef
6420
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006421" Test for calling a class method using an object in a def function context and
6422" script context.
6423def Test_class_method_call_using_object()
6424 # script context
6425 var lines =<< trim END
6426 vim9script
6427 class A
6428 static def Foo(): list<string>
6429 return ['a', 'b']
6430 enddef
6431 def Bar()
6432 assert_equal(['a', 'b'], A.Foo())
6433 assert_equal(['a', 'b'], Foo())
6434 enddef
6435 endclass
6436
6437 def T()
6438 assert_equal(['a', 'b'], A.Foo())
6439 var t_a = A.new()
6440 t_a.Bar()
6441 enddef
6442
6443 assert_equal(['a', 'b'], A.Foo())
6444 var a = A.new()
6445 a.Bar()
6446 T()
6447 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006448 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006449
6450 # script context
6451 lines =<< trim END
6452 vim9script
6453 class A
6454 static def Foo(): string
6455 return 'foo'
6456 enddef
6457 endclass
6458
6459 var a = A.new()
6460 assert_equal('foo', a.Foo())
6461 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006462 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006463
6464 # def function context
6465 lines =<< trim END
6466 vim9script
6467 class A
6468 static def Foo(): string
6469 return 'foo'
6470 enddef
6471 endclass
6472
6473 def T()
6474 var a = A.new()
6475 assert_equal('foo', a.Foo())
6476 enddef
6477 T()
6478 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006479 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006480enddef
6481
6482def Test_class_variable()
6483 var lines =<< trim END
6484 vim9script
6485
6486 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006487 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006488 static def ClassFunc()
6489 assert_equal(10, val)
6490 enddef
6491 def ObjFunc()
6492 assert_equal(10, val)
6493 enddef
6494 endclass
6495
6496 class B extends A
6497 endclass
6498
6499 assert_equal(10, A.val)
6500 A.ClassFunc()
6501 var a = A.new()
6502 a.ObjFunc()
6503 var b = B.new()
6504 b.ObjFunc()
6505
6506 def T1(a1: A)
6507 a1.ObjFunc()
6508 A.ClassFunc()
6509 enddef
6510 T1(b)
6511
6512 A.val = 20
6513 assert_equal(20, A.val)
6514 END
6515 v9.CheckSourceSuccess(lines)
6516
6517 # Modifying a parent class variable from a child class method
6518 lines =<< trim END
6519 vim9script
6520
6521 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006522 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006523 endclass
6524
6525 class B extends A
6526 static def ClassFunc()
6527 val = 20
6528 enddef
6529 endclass
6530 B.ClassFunc()
6531 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006532 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006533
6534 # Reading a parent class variable from a child class method
6535 lines =<< trim END
6536 vim9script
6537
6538 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006539 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006540 endclass
6541
6542 class B extends A
6543 static def ClassFunc()
6544 var i = val
6545 enddef
6546 endclass
6547 B.ClassFunc()
6548 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006549 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006550
6551 # Modifying a parent class variable from a child object method
6552 lines =<< trim END
6553 vim9script
6554
6555 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006556 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006557 endclass
6558
6559 class B extends A
6560 def ObjFunc()
6561 val = 20
6562 enddef
6563 endclass
6564 var b = B.new()
6565 b.ObjFunc()
6566 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006567 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006568
6569 # Reading a parent class variable from a child object method
6570 lines =<< trim END
6571 vim9script
6572
6573 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006574 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006575 endclass
6576
6577 class B extends A
6578 def ObjFunc()
6579 var i = val
6580 enddef
6581 endclass
6582 var b = B.new()
6583 b.ObjFunc()
6584 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006585 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006586
6587 # Modifying a class variable using an object at script level
6588 lines =<< trim END
6589 vim9script
6590
6591 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006592 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006593 endclass
6594 var a = A.new()
6595 a.val = 20
6596 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006597 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006598
6599 # Reading a class variable using an object at script level
6600 lines =<< trim END
6601 vim9script
6602
6603 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006604 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006605 endclass
6606 var a = A.new()
6607 var i = a.val
6608 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006609 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006610
6611 # Modifying a class variable using an object at function level
6612 lines =<< trim END
6613 vim9script
6614
6615 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006616 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006617 endclass
6618
6619 def T()
6620 var a = A.new()
6621 a.val = 20
6622 enddef
6623 T()
6624 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006625 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006626
6627 # Reading a class variable using an object at function level
6628 lines =<< trim END
6629 vim9script
6630
6631 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006632 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006633 endclass
6634 def T()
6635 var a = A.new()
6636 var i = a.val
6637 enddef
6638 T()
6639 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006640 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006641
6642 # Use old implicit var declaration syntax (without initialization)
6643 lines =<< trim END
6644 vim9script
6645
6646 class A
6647 static val: number
6648 endclass
6649 END
6650 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6651
6652 # Use old implicit var declaration syntax (with initialization)
6653 lines =<< trim END
6654 vim9script
6655
6656 class A
6657 static val: number = 10
6658 endclass
6659 END
6660 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6661
6662 # Use old implicit var declaration syntax (type inferred)
6663 lines =<< trim END
6664 vim9script
6665
6666 class A
6667 static val = 10
6668 endclass
6669 END
6670 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6671
6672 # Missing ":var" in "var" class variable declaration (without initialization)
6673 lines =<< trim END
6674 vim9script
6675
6676 class A
6677 static var: number
6678 endclass
6679 END
6680 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6681
6682 # Missing ":var" in "var" class variable declaration (with initialization)
6683 lines =<< trim END
6684 vim9script
6685
6686 class A
6687 static var: number = 10
6688 endclass
6689 END
6690 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6691
6692 # Missing ":var" in "var" class variable declaration (type inferred)
6693 lines =<< trim END
6694 vim9script
6695
6696 class A
6697 static var = 10
6698 endclass
6699 END
6700 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6701
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006702enddef
6703
6704" Test for using a duplicate class method and class variable in a child class
6705def Test_dup_class_member()
6706 # duplicate class variable, class method and overridden object method
6707 var lines =<< trim END
6708 vim9script
6709 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006710 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006711 static def Check()
6712 assert_equal(100, sval)
6713 enddef
6714 def GetVal(): number
6715 return sval
6716 enddef
6717 endclass
6718
6719 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006720 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006721 static def Check()
6722 assert_equal(200, sval)
6723 enddef
6724 def GetVal(): number
6725 return sval
6726 enddef
6727 endclass
6728
6729 def T1(aa: A): number
6730 return aa.GetVal()
6731 enddef
6732
6733 def T2(bb: B): number
6734 return bb.GetVal()
6735 enddef
6736
6737 assert_equal(100, A.sval)
6738 assert_equal(200, B.sval)
6739 var a = A.new()
6740 assert_equal(100, a.GetVal())
6741 var b = B.new()
6742 assert_equal(200, b.GetVal())
6743 assert_equal(200, T1(b))
6744 assert_equal(200, T2(b))
6745 END
6746 v9.CheckSourceSuccess(lines)
6747
6748 # duplicate class variable and class method
6749 lines =<< trim END
6750 vim9script
6751 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006752 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006753 static def Check()
6754 assert_equal(100, sval)
6755 enddef
6756 def GetVal(): number
6757 return sval
6758 enddef
6759 endclass
6760
6761 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006762 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006763 static def Check()
6764 assert_equal(200, sval)
6765 enddef
6766 endclass
6767
6768 def T1(aa: A): number
6769 return aa.GetVal()
6770 enddef
6771
6772 def T2(bb: B): number
6773 return bb.GetVal()
6774 enddef
6775
6776 assert_equal(100, A.sval)
6777 assert_equal(200, B.sval)
6778 var a = A.new()
6779 assert_equal(100, a.GetVal())
6780 var b = B.new()
6781 assert_equal(100, b.GetVal())
6782 assert_equal(100, T1(b))
6783 assert_equal(100, T2(b))
6784 END
6785 v9.CheckSourceSuccess(lines)
6786enddef
6787
6788" Test for calling an instance method using the class
6789def Test_instance_method_call_using_class()
6790 # Invoke an object method using a class in script context
6791 var lines =<< trim END
6792 vim9script
6793 class A
6794 def Foo()
6795 echo "foo"
6796 enddef
6797 endclass
6798 A.Foo()
6799 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006800 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006801
6802 # Invoke an object method using a class in def function context
6803 lines =<< trim END
6804 vim9script
6805 class A
6806 def Foo()
6807 echo "foo"
6808 enddef
6809 endclass
6810 def T()
6811 A.Foo()
6812 enddef
6813 T()
6814 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006815 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006816enddef
6817
6818" Test for duplicate class method and instance method
6819def Test_dup_classmethod_objmethod()
6820 # Duplicate instance method
6821 var lines =<< trim END
6822 vim9script
6823 class A
6824 static def Foo()
6825 enddef
6826 def Foo()
6827 enddef
6828 endclass
6829 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006830 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006831
Ernie Rael03042a22023-11-11 08:53:32 +01006832 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006833 lines =<< trim END
6834 vim9script
6835 class A
6836 static def Foo()
6837 enddef
6838 def _Foo()
6839 enddef
6840 endclass
6841 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006842 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006843
6844 # Duplicate class method
6845 lines =<< trim END
6846 vim9script
6847 class A
6848 def Foo()
6849 enddef
6850 static def Foo()
6851 enddef
6852 endclass
6853 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006854 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006855
Ernie Rael03042a22023-11-11 08:53:32 +01006856 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006857 lines =<< trim END
6858 vim9script
6859 class A
6860 def Foo()
6861 enddef
6862 static def _Foo()
6863 enddef
6864 endclass
6865 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006866 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006867
Ernie Rael03042a22023-11-11 08:53:32 +01006868 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006869 lines =<< trim END
6870 vim9script
6871 class A
6872 def _Foo()
6873 enddef
6874 static def _Foo()
6875 enddef
6876 endclass
6877 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006878 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006879enddef
6880
6881" Test for an instance method access level comparison with parent instance
6882" methods.
6883def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01006884 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006885 var lines =<< trim END
6886 vim9script
6887 class A
6888 def Foo()
6889 enddef
6890 endclass
6891 class B extends A
6892 endclass
6893 class C extends B
6894 def _Foo()
6895 enddef
6896 endclass
6897 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006898 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006899
6900 # Public method in subclass
6901 lines =<< trim END
6902 vim9script
6903 class A
6904 def _Foo()
6905 enddef
6906 endclass
6907 class B extends A
6908 endclass
6909 class C extends B
6910 def Foo()
6911 enddef
6912 endclass
6913 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006914 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006915enddef
6916
6917def Test_extend_empty_class()
6918 var lines =<< trim END
6919 vim9script
6920 class A
6921 endclass
6922 class B extends A
6923 endclass
6924 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006925 public static var rw_class_var = 1
6926 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006927 static def ClassMethod(): number
6928 return 3
6929 enddef
6930 def ObjMethod(): number
6931 return 4
6932 enddef
6933 endclass
6934 assert_equal(1, C.rw_class_var)
6935 assert_equal(3, C.ClassMethod())
6936 var c = C.new()
6937 assert_equal(2, c.rw_obj_var)
6938 assert_equal(4, c.ObjMethod())
6939 END
6940 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006941enddef
6942
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006943" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01006944" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006945def Test_interface_with_unsupported_members()
6946 var lines =<< trim END
6947 vim9script
6948 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006949 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006950 endinterface
6951 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006952 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006953
6954 lines =<< trim END
6955 vim9script
6956 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006957 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006958 endinterface
6959 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006960 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006961
6962 lines =<< trim END
6963 vim9script
6964 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006965 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006966 endinterface
6967 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02006968 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006969
6970 lines =<< trim END
6971 vim9script
6972 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006973 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006974 endinterface
6975 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02006976 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006977
6978 lines =<< trim END
6979 vim9script
6980 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006981 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006982 endinterface
6983 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006984 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006985
6986 lines =<< trim END
6987 vim9script
6988 interface A
6989 static def Foo(d: dict<any>): list<string>
6990 endinterface
6991 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006992 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006993
6994 lines =<< trim END
6995 vim9script
6996 interface A
6997 static def _Foo(d: dict<any>): list<string>
6998 endinterface
6999 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007000 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007001
7002 lines =<< trim END
7003 vim9script
7004 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007005 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007006 endinterface
7007 END
Ernie Rael03042a22023-11-11 08:53:32 +01007008 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007009
7010 lines =<< trim END
7011 vim9script
7012 interface A
7013 def _Foo(d: dict<any>): list<string>
7014 endinterface
7015 END
Ernie Rael03042a22023-11-11 08:53:32 +01007016 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007017enddef
7018
7019" Test for extending an interface
7020def Test_extend_interface()
7021 var lines =<< trim END
7022 vim9script
7023 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007024 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007025 def Foo()
7026 endinterface
7027 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007028 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007029 def Bar()
7030 endinterface
7031 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007032 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007033 def Foo()
7034 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007035 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007036 def Bar()
7037 enddef
7038 endclass
7039 END
7040 v9.CheckSourceSuccess(lines)
7041
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007042 # extending empty interface
7043 lines =<< trim END
7044 vim9script
7045 interface A
7046 endinterface
7047 interface B extends A
7048 endinterface
7049 class C implements B
7050 endclass
7051 END
7052 v9.CheckSourceSuccess(lines)
7053
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007054 lines =<< trim END
7055 vim9script
7056 interface A
7057 def Foo()
7058 endinterface
7059 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007060 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007061 endinterface
7062 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007063 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007064 endclass
7065 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007066 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007067
7068 lines =<< trim END
7069 vim9script
7070 interface A
7071 def Foo()
7072 endinterface
7073 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007074 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007075 endinterface
7076 class C implements A, B
7077 def Foo()
7078 enddef
7079 endclass
7080 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007081 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007082
7083 # interface cannot extend a class
7084 lines =<< trim END
7085 vim9script
7086 class A
7087 endclass
7088 interface B extends A
7089 endinterface
7090 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007091 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007092
7093 # class cannot extend an interface
7094 lines =<< trim END
7095 vim9script
7096 interface A
7097 endinterface
7098 class B extends A
7099 endclass
7100 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007101 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007102
7103 # interface cannot implement another interface
7104 lines =<< trim END
7105 vim9script
7106 interface A
7107 endinterface
7108 interface B implements A
7109 endinterface
7110 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007111 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007112
7113 # interface cannot extend multiple interfaces
7114 lines =<< trim END
7115 vim9script
7116 interface A
7117 endinterface
7118 interface B
7119 endinterface
7120 interface C extends A, B
7121 endinterface
7122 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007123 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007124
7125 # Variable type in an extended interface is of different type
7126 lines =<< trim END
7127 vim9script
7128 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007129 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007130 endinterface
7131 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007132 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007133 endinterface
7134 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007135 var val1: string
7136 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007137 endinterface
7138 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007139 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007140enddef
7141
7142" Test for a child class implementing an interface when some of the methods are
7143" defined in the parent class.
7144def Test_child_class_implements_interface()
7145 var lines =<< trim END
7146 vim9script
7147
7148 interface Intf
7149 def F1(): list<list<number>>
7150 def F2(): list<list<number>>
7151 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007152 var var1: list<dict<number>>
7153 var var2: list<dict<number>>
7154 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007155 endinterface
7156
7157 class A
7158 def A1()
7159 enddef
7160 def F3(): list<list<number>>
7161 return [[3]]
7162 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007163 var v1: list<list<number>> = [[0]]
7164 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007165 endclass
7166
7167 class B extends A
7168 def B1()
7169 enddef
7170 def F2(): list<list<number>>
7171 return [[2]]
7172 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007173 var v2: list<list<number>> = [[0]]
7174 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007175 endclass
7176
7177 class C extends B implements Intf
7178 def C1()
7179 enddef
7180 def F1(): list<list<number>>
7181 return [[1]]
7182 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007183 var v3: list<list<number>> = [[0]]
7184 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007185 endclass
7186
7187 def T(if: Intf)
7188 assert_equal([[1]], if.F1())
7189 assert_equal([[2]], if.F2())
7190 assert_equal([[3]], if.F3())
7191 assert_equal([{a: 10}], if.var1)
7192 assert_equal([{b: 20}], if.var2)
7193 assert_equal([{c: 30}], if.var3)
7194 enddef
7195
7196 var c = C.new()
7197 T(c)
7198 assert_equal([[1]], c.F1())
7199 assert_equal([[2]], c.F2())
7200 assert_equal([[3]], c.F3())
7201 assert_equal([{a: 10}], c.var1)
7202 assert_equal([{b: 20}], c.var2)
7203 assert_equal([{c: 30}], c.var3)
7204 END
7205 v9.CheckSourceSuccess(lines)
7206
7207 # One of the interface methods is not found
7208 lines =<< trim END
7209 vim9script
7210
7211 interface Intf
7212 def F1()
7213 def F2()
7214 def F3()
7215 endinterface
7216
7217 class A
7218 def A1()
7219 enddef
7220 endclass
7221
7222 class B extends A
7223 def B1()
7224 enddef
7225 def F2()
7226 enddef
7227 endclass
7228
7229 class C extends B implements Intf
7230 def C1()
7231 enddef
7232 def F1()
7233 enddef
7234 endclass
7235 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007236 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007237
7238 # One of the interface methods is of different type
7239 lines =<< trim END
7240 vim9script
7241
7242 interface Intf
7243 def F1()
7244 def F2()
7245 def F3()
7246 endinterface
7247
7248 class A
7249 def F3(): number
7250 return 0
7251 enddef
7252 def A1()
7253 enddef
7254 endclass
7255
7256 class B extends A
7257 def B1()
7258 enddef
7259 def F2()
7260 enddef
7261 endclass
7262
7263 class C extends B implements Intf
7264 def C1()
7265 enddef
7266 def F1()
7267 enddef
7268 endclass
7269 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007270 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007271
7272 # One of the interface variables is not present
7273 lines =<< trim END
7274 vim9script
7275
7276 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007277 var var1: list<dict<number>>
7278 var var2: list<dict<number>>
7279 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007280 endinterface
7281
7282 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007283 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007284 endclass
7285
7286 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007287 var v2: list<list<number>> = [[0]]
7288 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007289 endclass
7290
7291 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007292 var v3: list<list<number>> = [[0]]
7293 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007294 endclass
7295 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007296 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007297
7298 # One of the interface variables is of different type
7299 lines =<< trim END
7300 vim9script
7301
7302 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007303 var var1: list<dict<number>>
7304 var var2: list<dict<number>>
7305 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007306 endinterface
7307
7308 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007309 var v1: list<list<number>> = [[0]]
7310 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007311 endclass
7312
7313 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007314 var v2: list<list<number>> = [[0]]
7315 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007316 endclass
7317
7318 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007319 var v3: list<list<number>> = [[0]]
7320 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007321 endclass
7322 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007323 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 +02007324enddef
7325
7326" Test for extending an interface with duplicate variables and methods
7327def Test_interface_extends_with_dup_members()
7328 var lines =<< trim END
7329 vim9script
7330 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007331 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007332 def Foo1(): number
7333 endinterface
7334 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007335 var n2: number
7336 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007337 def Foo2(): number
7338 def Foo1(): number
7339 endinterface
7340 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007341 var n1 = 10
7342 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007343 def Foo1(): number
7344 return 30
7345 enddef
7346 def Foo2(): number
7347 return 40
7348 enddef
7349 endclass
7350 def T1(a: A)
7351 assert_equal(10, a.n1)
7352 assert_equal(30, a.Foo1())
7353 enddef
7354 def T2(b: B)
7355 assert_equal(10, b.n1)
7356 assert_equal(20, b.n2)
7357 assert_equal(30, b.Foo1())
7358 assert_equal(40, b.Foo2())
7359 enddef
7360 var c = C.new()
7361 T1(c)
7362 T2(c)
7363 END
7364 v9.CheckSourceSuccess(lines)
7365enddef
7366
Yegappan Lakshmananc10342d2025-01-11 09:39:01 +01007367" Test for implementing an interface with different ordering for the interface
7368" member variables.
7369def Test_implement_interface_with_different_variable_order()
7370 var lines =<< trim END
7371 vim9script
7372
7373 interface IX
7374 var F: func(): string
7375 endinterface
7376
7377 class X implements IX
7378 var x: number
7379 var F: func(): string = () => 'ok'
7380 endclass
7381
7382 def Foo(ix: IX): string
7383 return ix.F()
7384 enddef
7385
7386 var x0 = X.new(0)
7387 assert_equal('ok', Foo(x0))
7388 END
7389 v9.CheckSourceSuccess(lines)
7390enddef
7391
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01007392" Test for inheriting interfaces from an imported super class
7393def Test_interface_inheritance_with_imported_super()
7394 var lines =<< trim END
7395 vim9script
7396
7397 export interface I
7398 def F(): string
7399 endinterface
7400
7401 export class A implements I
7402 def F(): string
7403 return 'A'
7404 enddef
7405 endclass
7406 END
7407 writefile(lines, 'Xinheritintfimportclass.vim', 'D')
7408
7409 lines =<< trim END
7410 vim9script
7411
7412 import './Xinheritintfimportclass.vim' as i_imp
7413
7414 # class C extends i_imp.A
7415 class C extends i_imp.A implements i_imp.I
7416 def F(): string
7417 return 'C'
7418 enddef
7419 endclass
7420
7421 def TestI(i: i_imp.I): string
7422 return i.F()
7423 enddef
7424
7425 assert_equal('C', TestI(C.new()))
7426 END
7427 v9.CheckSourceSuccess(lines)
7428enddef
7429
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007430" Test for using "any" type for a variable in a sub-class while it has a
7431" concrete type in the interface
7432def Test_implements_using_var_type_any()
7433 var lines =<< trim END
7434 vim9script
7435 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007436 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007437 endinterface
7438 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007439 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007440 endclass
7441 var b = B.new()
7442 assert_equal([{a: '1'}, {b: '2'}], b.val)
7443 END
7444 v9.CheckSourceSuccess(lines)
7445
7446 # initialize instance variable using a different type
7447 lines =<< trim END
7448 vim9script
7449 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007450 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007451 endinterface
7452 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007453 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007454 endclass
7455 var b = B.new()
7456 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007457 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007458enddef
7459
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007460" Test for assigning to a member variable in a nested class
7461def Test_nested_object_assignment()
7462 var lines =<< trim END
7463 vim9script
7464
7465 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007466 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007467 endclass
7468
7469 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007470 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007471 endclass
7472
7473 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007474 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007475 endclass
7476
7477 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007478 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007479 endclass
7480
7481 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007482 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007483 enddef
7484
7485 var d = D.new()
7486 T(d)
7487 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007488 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007489enddef
7490
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007491" Test for calling methods using a null object
7492def Test_null_object_method_call()
7493 # Calling a object method using a null object in script context
7494 var lines =<< trim END
7495 vim9script
7496
7497 class C
7498 def Foo()
7499 assert_report('This method should not be executed')
7500 enddef
7501 endclass
7502
7503 var o: C
7504 o.Foo()
7505 END
7506 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7507
7508 # Calling a object method using a null object in def function context
7509 lines =<< trim END
7510 vim9script
7511
7512 class C
7513 def Foo()
7514 assert_report('This method should not be executed')
7515 enddef
7516 endclass
7517
7518 def T()
7519 var o: C
7520 o.Foo()
7521 enddef
7522 T()
7523 END
7524 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7525
7526 # Calling a object method through another class method using a null object in
7527 # script context
7528 lines =<< trim END
7529 vim9script
7530
7531 class C
7532 def Foo()
7533 assert_report('This method should not be executed')
7534 enddef
7535
7536 static def Bar(o_any: any)
7537 var o_typed: C = o_any
7538 o_typed.Foo()
7539 enddef
7540 endclass
7541
7542 var o: C
7543 C.Bar(o)
7544 END
7545 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7546
7547 # Calling a object method through another class method using a null object in
7548 # def function context
7549 lines =<< trim END
7550 vim9script
7551
7552 class C
7553 def Foo()
7554 assert_report('This method should not be executed')
7555 enddef
7556
7557 static def Bar(o_any: any)
7558 var o_typed: C = o_any
7559 o_typed.Foo()
7560 enddef
7561 endclass
7562
7563 def T()
7564 var o: C
7565 C.Bar(o)
7566 enddef
7567 T()
7568 END
7569 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007570
7571 # Calling an object method defined in a class that is extended. This differs
7572 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7573 lines =<< trim END
7574 vim9script
7575
7576 class C0
7577 def F()
7578 enddef
7579 endclass
7580
7581 class C extends C0
7582 endclass
7583
7584 def X()
7585 var o: C0 = null_object
7586 o.F()
7587 enddef
7588 X()
7589 END
7590 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7591
7592 # Getting a function ref an object method.
7593 lines =<< trim END
7594 vim9script
7595
7596 class C0
7597 def F()
7598 enddef
7599 endclass
7600
7601 class C extends C0
7602 endclass
7603
7604 def X()
7605 var o: C0 = null_object
7606 var XXX = o.F
7607 enddef
7608 X()
7609 END
7610 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007611enddef
7612
7613" Test for using a dict as an object member
7614def Test_dict_object_member()
7615 var lines =<< trim END
7616 vim9script
7617
7618 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007619 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007620 def GetState(): dict<number>
7621 return this.state
7622 enddef
7623 endclass
7624
7625 var ctx = Context.new()
7626 ctx.state->extend({a: 1})
7627 ctx.state['b'] = 2
7628 assert_equal({a: 1, b: 2}, ctx.GetState())
7629
7630 def F()
7631 ctx.state['c'] = 3
7632 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7633 enddef
7634 F()
7635 assert_equal(3, ctx.state.c)
7636 ctx.state.c = 4
7637 assert_equal(4, ctx.state.c)
7638 END
7639 v9.CheckSourceSuccess(lines)
7640enddef
7641
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007642" The following test was failing after 9.0.1914. This was caused by using a
7643" freed object from a previous method call.
7644def Test_freed_object_from_previous_method_call()
7645 var lines =<< trim END
7646 vim9script
7647
7648 class Context
7649 endclass
7650
7651 class Result
7652 endclass
7653
7654 def Failure(): Result
7655 return Result.new()
7656 enddef
7657
7658 def GetResult(ctx: Context): Result
7659 return Failure()
7660 enddef
7661
7662 def Test_GetResult()
7663 var ctx = Context.new()
7664 var result = GetResult(ctx)
7665 enddef
7666
7667 Test_GetResult()
7668 END
7669 v9.CheckSourceSuccess(lines)
7670enddef
7671
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007672" Test for duplicate object and class variable
7673def Test_duplicate_variable()
7674 # Object variable name is same as the class variable name
7675 var lines =<< trim END
7676 vim9script
7677 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007678 public static var sval: number
7679 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007680 endclass
7681 var a = A.new()
7682 END
7683 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7684
7685 # Duplicate variable name and calling a class method
7686 lines =<< trim END
7687 vim9script
7688 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007689 public static var sval: number
7690 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007691 def F1()
7692 echo this.sval
7693 enddef
7694 static def F2()
7695 echo sval
7696 enddef
7697 endclass
7698 A.F2()
7699 END
7700 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7701
7702 # Duplicate variable with an empty constructor
7703 lines =<< trim END
7704 vim9script
7705 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007706 public static var sval: number
7707 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007708 def new()
7709 enddef
7710 endclass
7711 var a = A.new()
7712 END
7713 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7714enddef
7715
7716" Test for using a reserved keyword as a variable name
7717def Test_reserved_varname()
7718 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7719 'null_function', 'null_list', 'null_partial', 'null_string',
7720 'null_channel', 'null_job', 'super', 'this']
7721
7722 var lines =<< trim eval END
7723 vim9script
7724 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007725 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007726 endclass
7727 var o = C.new()
7728 END
7729 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7730
7731 lines =<< trim eval END
7732 vim9script
7733 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007734 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007735 def new()
7736 enddef
7737 endclass
7738 var o = C.new()
7739 END
7740 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7741
7742 lines =<< trim eval END
7743 vim9script
7744 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007745 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007746 def new()
7747 enddef
7748 def F()
7749 echo this.{kword}
7750 enddef
7751 endclass
7752 var o = C.new()
7753 o.F()
7754 END
7755 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007756
7757 # class variable name
7758 if kword != 'this'
7759 lines =<< trim eval END
7760 vim9script
7761 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007762 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007763 endclass
7764 END
7765 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7766 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007767 endfor
7768enddef
7769
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007770" Test for checking the type of the arguments and the return value of a object
7771" method in an extended class.
7772def Test_extended_obj_method_type_check()
7773 var lines =<< trim END
7774 vim9script
7775
7776 class A
7777 endclass
7778 class B extends A
7779 endclass
7780 class C extends B
7781 endclass
7782
7783 class Foo
7784 def Doit(p: B): B
7785 return B.new()
7786 enddef
7787 endclass
7788
7789 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007790 def Doit(p: C): B
7791 return B.new()
7792 enddef
7793 endclass
7794 END
7795 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
7796
7797 lines =<< trim END
7798 vim9script
7799
7800 class A
7801 endclass
7802 class B extends A
7803 endclass
7804 class C extends B
7805 endclass
7806
7807 class Foo
7808 def Doit(p: B): B
7809 return B.new()
7810 enddef
7811 endclass
7812
7813 class Bar extends Foo
7814 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007815 return C.new()
7816 enddef
7817 endclass
7818 END
7819 v9.CheckSourceSuccess(lines)
7820
7821 lines =<< trim END
7822 vim9script
7823
7824 class A
7825 endclass
7826 class B extends A
7827 endclass
7828 class C extends B
7829 endclass
7830
7831 class Foo
7832 def Doit(p: B): B
7833 return B.new()
7834 enddef
7835 endclass
7836
7837 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007838 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007839 return B.new()
7840 enddef
7841 endclass
7842 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007843 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 +02007844
7845 lines =<< trim END
7846 vim9script
7847
7848 class A
7849 endclass
7850 class B extends A
7851 endclass
7852 class C extends B
7853 endclass
7854
7855 class Foo
7856 def Doit(p: B): B
7857 return B.new()
7858 enddef
7859 endclass
7860
7861 class Bar extends Foo
7862 def Doit(p: B): A
7863 return A.new()
7864 enddef
7865 endclass
7866 END
7867 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 +02007868
7869 # check varargs type mismatch
7870 lines =<< trim END
7871 vim9script
7872
7873 class B
7874 def F(...xxx: list<any>)
7875 enddef
7876 endclass
7877 class C extends B
7878 def F(xxx: list<any>)
7879 enddef
7880 endclass
7881 END
7882 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 +02007883enddef
7884
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007885" Test type checking for class variable in assignments
7886func Test_class_variable_complex_type_check()
7887 " class variable with a specific type. Try assigning a different type at
7888 " script level.
7889 let lines =<< trim END
7890 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007891 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007892 return {}
7893 enddef
7894 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007895 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007896 endclass
7897 test_garbagecollect_now()
7898 A.Fn = "abc"
7899 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007900 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 +02007901
7902 " class variable with a specific type. Try assigning a different type at
7903 " class def method level.
7904 let lines =<< trim END
7905 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007906 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007907 return {}
7908 enddef
7909 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007910 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007911 def Bar()
7912 Fn = "abc"
7913 enddef
7914 endclass
7915 var a = A.new()
7916 test_garbagecollect_now()
7917 a.Bar()
7918 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007919 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 +02007920
7921 " class variable with a specific type. Try assigning a different type at
7922 " script def method level.
7923 let lines =<< trim END
7924 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007925 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007926 return {}
7927 enddef
7928 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007929 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007930 endclass
7931 def Bar()
7932 A.Fn = "abc"
7933 enddef
7934 test_garbagecollect_now()
7935 Bar()
7936 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007937 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 +02007938
7939 " class variable without any type. Should be set to the initialization
7940 " expression type. Try assigning a different type from script level.
7941 let lines =<< trim END
7942 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007943 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007944 return {}
7945 enddef
7946 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007947 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007948 endclass
7949 test_garbagecollect_now()
7950 A.Fn = "abc"
7951 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007952 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 +02007953
7954 " class variable without any type. Should be set to the initialization
7955 " expression type. Try assigning a different type at class def level.
7956 let lines =<< trim END
7957 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007958 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007959 return {}
7960 enddef
7961 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007962 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007963 def Bar()
7964 Fn = "abc"
7965 enddef
7966 endclass
7967 var a = A.new()
7968 test_garbagecollect_now()
7969 a.Bar()
7970 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007971 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 +02007972
7973 " class variable without any type. Should be set to the initialization
7974 " expression type. Try assigning a different type at script def level.
7975 let lines =<< trim END
7976 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007977 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007978 return {}
7979 enddef
7980 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007981 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007982 endclass
7983 def Bar()
7984 A.Fn = "abc"
7985 enddef
7986 test_garbagecollect_now()
7987 Bar()
7988 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007989 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 +02007990
7991 " class variable with 'any" type. Can be assigned different types.
7992 let lines =<< trim END
7993 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007994 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007995 return {}
7996 enddef
7997 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007998 public static var Fn: any = Foo
7999 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008000 endclass
8001 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008002 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008003 A.Fn = "abc"
8004 test_garbagecollect_now()
8005 assert_equal('string', typename(A.Fn))
8006 A.Fn2 = Foo
8007 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008008 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008009 A.Fn2 = "xyz"
8010 test_garbagecollect_now()
8011 assert_equal('string', typename(A.Fn2))
8012 END
8013 call v9.CheckSourceSuccess(lines)
8014
8015 " class variable with 'any" type. Can be assigned different types.
8016 let lines =<< trim END
8017 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008018 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008019 return {}
8020 enddef
8021 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008022 public static var Fn: any = Foo
8023 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008024
8025 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008026 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008027 Fn = "abc"
8028 assert_equal('string', typename(Fn))
8029 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008030 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008031 Fn2 = "xyz"
8032 assert_equal('string', typename(Fn2))
8033 enddef
8034 endclass
8035 var a = A.new()
8036 test_garbagecollect_now()
8037 a.Bar()
8038 test_garbagecollect_now()
8039 A.Fn = Foo
8040 a.Bar()
8041 END
8042 call v9.CheckSourceSuccess(lines)
8043
8044 " class variable with 'any" type. Can be assigned different types.
8045 let lines =<< trim END
8046 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008047 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008048 return {}
8049 enddef
8050 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008051 public static var Fn: any = Foo
8052 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008053 endclass
8054
8055 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008056 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008057 A.Fn = "abc"
8058 assert_equal('string', typename(A.Fn))
8059 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008060 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008061 A.Fn2 = "xyz"
8062 assert_equal('string', typename(A.Fn2))
8063 enddef
8064 Bar()
8065 test_garbagecollect_now()
8066 A.Fn = Foo
8067 Bar()
8068 END
8069 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008070
8071 let lines =<< trim END
8072 vim9script
8073 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008074 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008075 endclass
8076 assert_equal([0z10, 0z20], A.foo)
8077 A.foo = [0z30]
8078 assert_equal([0z30], A.foo)
8079 var a = A.foo
8080 assert_equal([0z30], a)
8081 END
8082 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008083endfunc
8084
8085" Test type checking for object variable in assignments
8086func Test_object_variable_complex_type_check()
8087 " object variable with a specific type. Try assigning a different type at
8088 " script level.
8089 let lines =<< trim END
8090 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008091 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008092 return {}
8093 enddef
8094 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008095 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008096 endclass
8097 var a = A.new()
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', 10)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008102
8103 " object variable with a specific type. Try assigning a different type at
8104 " object def method 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 var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008112 def Bar()
8113 this.Fn = "abc"
8114 this.Fn = Foo
8115 enddef
8116 endclass
8117 var a = A.new()
8118 test_garbagecollect_now()
8119 a.Bar()
8120 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008121 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 +02008122
8123 " object variable with a specific type. Try assigning a different type at
8124 " script def method level.
8125 let lines =<< trim END
8126 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008127 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008128 return {}
8129 enddef
8130 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008131 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008132 endclass
8133 def Bar()
8134 var a = A.new()
8135 a.Fn = "abc"
8136 a.Fn = Foo
8137 enddef
8138 test_garbagecollect_now()
8139 Bar()
8140 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008141 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 +02008142
8143 " object variable without any type. Should be set to the initialization
8144 " expression type. Try assigning a different type from script level.
8145 let lines =<< trim END
8146 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008147 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008148 return {}
8149 enddef
8150 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008151 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008152 endclass
8153 var a = A.new()
8154 test_garbagecollect_now()
8155 a.Fn = "abc"
8156 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008157 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 +02008158
8159 " object variable without any type. Should be set to the initialization
8160 " expression type. Try assigning a different type at object def level.
8161 let lines =<< trim END
8162 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008163 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008164 return {}
8165 enddef
8166 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008167 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008168 def Bar()
8169 this.Fn = "abc"
8170 this.Fn = Foo
8171 enddef
8172 endclass
8173 var a = A.new()
8174 test_garbagecollect_now()
8175 a.Bar()
8176 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008177 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 +02008178
8179 " object variable without any type. Should be set to the initialization
8180 " expression type. Try assigning a different type at script def level.
8181 let lines =<< trim END
8182 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008183 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008184 return {}
8185 enddef
8186 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008187 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008188 endclass
8189 def Bar()
8190 var a = A.new()
8191 a.Fn = "abc"
8192 a.Fn = Foo
8193 enddef
8194 test_garbagecollect_now()
8195 Bar()
8196 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008197 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 +02008198
8199 " object variable with 'any" type. Can be assigned different types.
8200 let lines =<< trim END
8201 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008202 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008203 return {}
8204 enddef
8205 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008206 public var Fn: any = Foo
8207 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008208 endclass
8209
8210 var a = A.new()
8211 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008212 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008213 a.Fn = "abc"
8214 test_garbagecollect_now()
8215 assert_equal('string', typename(a.Fn))
8216 a.Fn2 = Foo
8217 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008218 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008219 a.Fn2 = "xyz"
8220 test_garbagecollect_now()
8221 assert_equal('string', typename(a.Fn2))
8222 END
8223 call v9.CheckSourceSuccess(lines)
8224
8225 " object variable with 'any" type. Can be assigned different types.
8226 let lines =<< trim END
8227 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008228 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008229 return {}
8230 enddef
8231 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008232 public var Fn: any = Foo
8233 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008234
8235 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008236 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008237 this.Fn = "abc"
8238 assert_equal('string', typename(this.Fn))
8239 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008240 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008241 this.Fn2 = "xyz"
8242 assert_equal('string', typename(this.Fn2))
8243 enddef
8244 endclass
8245
8246 var a = A.new()
8247 test_garbagecollect_now()
8248 a.Bar()
8249 test_garbagecollect_now()
8250 a.Fn = Foo
8251 a.Bar()
8252 END
8253 call v9.CheckSourceSuccess(lines)
8254
8255 " object variable with 'any" type. Can be assigned different types.
8256 let lines =<< trim END
8257 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008258 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008259 return {}
8260 enddef
8261 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008262 public var Fn: any = Foo
8263 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008264 endclass
8265
8266 def Bar()
8267 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008268 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008269 a.Fn = "abc"
8270 assert_equal('string', typename(a.Fn))
8271 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008272 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008273 a.Fn2 = "xyz"
8274 assert_equal('string', typename(a.Fn2))
8275 enddef
8276 test_garbagecollect_now()
8277 Bar()
8278 test_garbagecollect_now()
8279 Bar()
8280 END
8281 call v9.CheckSourceSuccess(lines)
8282endfunc
8283
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008284" Test for recursively calling an object method. This used to cause an
8285" use-after-free error.
8286def Test_recursive_object_method_call()
8287 var lines =<< trim END
8288 vim9script
8289 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008290 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008291 def Foo(): number
8292 if this.val >= 90
8293 return this.val
8294 endif
8295 this.val += 1
8296 return this.Foo()
8297 enddef
8298 endclass
8299 var a = A.new()
8300 assert_equal(90, a.Foo())
8301 END
8302 v9.CheckSourceSuccess(lines)
8303enddef
8304
8305" Test for recursively calling a class method.
8306def Test_recursive_class_method_call()
8307 var lines =<< trim END
8308 vim9script
8309 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008310 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008311 static def Foo(): number
8312 if val >= 90
8313 return val
8314 endif
8315 val += 1
8316 return Foo()
8317 enddef
8318 endclass
8319 assert_equal(90, A.Foo())
8320 END
8321 v9.CheckSourceSuccess(lines)
8322enddef
8323
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008324" Test for checking the argument types and the return type when assigning a
8325" funcref to make sure the invariant class type is used.
8326def Test_funcref_argtype_returntype_check()
8327 var lines =<< trim END
8328 vim9script
8329 class A
8330 endclass
8331 class B extends A
8332 endclass
8333
8334 def Foo(p: B): B
8335 return B.new()
8336 enddef
8337
8338 var Bar: func(A): A = Foo
8339 END
8340 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8341
8342 lines =<< trim END
8343 vim9script
8344 class A
8345 endclass
8346 class B extends A
8347 endclass
8348
8349 def Foo(p: B): B
8350 return B.new()
8351 enddef
8352
8353 def Baz()
8354 var Bar: func(A): A = Foo
8355 enddef
8356 Baz()
8357 END
8358 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8359enddef
8360
Ernie Rael96952b22023-10-17 18:15:01 +02008361def Test_funcref_argtype_invariance_check()
8362 var lines =<< trim END
8363 vim9script
8364
8365 class A
8366 endclass
8367 class B extends A
8368 endclass
8369 class C extends B
8370 endclass
8371
8372 var Func: func(B): number
8373 Func = (o: B): number => 3
8374 assert_equal(3, Func(B.new()))
8375 END
8376 v9.CheckSourceSuccess(lines)
8377
8378 lines =<< trim END
8379 vim9script
8380
8381 class A
8382 endclass
8383 class B extends A
8384 endclass
8385 class C extends B
8386 endclass
8387
8388 var Func: func(B): number
8389 Func = (o: A): number => 3
8390 END
8391 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8392
8393 lines =<< trim END
8394 vim9script
8395
8396 class A
8397 endclass
8398 class B extends A
8399 endclass
8400 class C extends B
8401 endclass
8402
8403 var Func: func(B): number
8404 Func = (o: C): number => 3
8405 END
8406 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8407enddef
8408
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008409" Test for using an operator (e.g. +) with an assignment
8410def Test_op_and_assignment()
8411 # Using += with a class variable
8412 var lines =<< trim END
8413 vim9script
8414 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008415 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008416 static def Foo(): list<number>
8417 val += [1]
8418 return val
8419 enddef
8420 endclass
8421 def Bar(): list<number>
8422 A.val += [2]
8423 return A.val
8424 enddef
8425 assert_equal([1], A.Foo())
8426 assert_equal([1, 2], Bar())
8427 A.val += [3]
8428 assert_equal([1, 2, 3], A.val)
8429 END
8430 v9.CheckSourceSuccess(lines)
8431
8432 # Using += with an object variable
8433 lines =<< trim END
8434 vim9script
8435 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008436 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008437 def Foo(): list<number>
8438 this.val += [1]
8439 return this.val
8440 enddef
8441 endclass
8442 def Bar(bar_a: A): list<number>
8443 bar_a.val += [2]
8444 return bar_a.val
8445 enddef
8446 var a = A.new()
8447 assert_equal([1], a.Foo())
8448 assert_equal([1, 2], Bar(a))
8449 a.val += [3]
8450 assert_equal([1, 2, 3], a.val)
8451 END
8452 v9.CheckSourceSuccess(lines)
8453enddef
8454
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008455" Test for using an object method as a funcref
8456def Test_object_funcref()
8457 # Using object method funcref from a def function
8458 var lines =<< trim END
8459 vim9script
8460 class A
8461 def Foo(): list<number>
8462 return [3, 2, 1]
8463 enddef
8464 endclass
8465 def Bar()
8466 var a = A.new()
8467 var Fn = a.Foo
8468 assert_equal([3, 2, 1], Fn())
8469 enddef
8470 Bar()
8471 END
8472 v9.CheckSourceSuccess(lines)
8473
8474 # Using object method funcref at the script level
8475 lines =<< trim END
8476 vim9script
8477 class A
8478 def Foo(): dict<number>
8479 return {a: 1, b: 2}
8480 enddef
8481 endclass
8482 var a = A.new()
8483 var Fn = a.Foo
8484 assert_equal({a: 1, b: 2}, Fn())
8485 END
8486 v9.CheckSourceSuccess(lines)
8487
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008488 # Using object method funcref at the script level
8489 lines =<< trim END
8490 vim9script
8491 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008492 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008493 def Foo(): number
8494 return this.val
8495 enddef
8496 endclass
8497 var a = A.new(345)
8498 var Fn = a.Foo
8499 assert_equal(345, Fn())
8500 END
8501 v9.CheckSourceSuccess(lines)
8502
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008503 # Using object method funcref from another object method
8504 lines =<< trim END
8505 vim9script
8506 class A
8507 def Foo(): list<number>
8508 return [3, 2, 1]
8509 enddef
8510 def Bar()
8511 var Fn = this.Foo
8512 assert_equal([3, 2, 1], Fn())
8513 enddef
8514 endclass
8515 var a = A.new()
8516 a.Bar()
8517 END
8518 v9.CheckSourceSuccess(lines)
8519
8520 # Using function() to get a object method funcref
8521 lines =<< trim END
8522 vim9script
8523 class A
8524 def Foo(l: list<any>): list<any>
8525 return l
8526 enddef
8527 endclass
8528 var a = A.new()
8529 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8530 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8531 END
8532 v9.CheckSourceSuccess(lines)
8533
8534 # Use an object method with a function returning a funcref and then call the
8535 # funcref.
8536 lines =<< trim END
8537 vim9script
8538
8539 def Map(F: func(number): number): func(number): number
8540 return (n: number) => F(n)
8541 enddef
8542
8543 class Math
8544 def Double(n: number): number
8545 return 2 * n
8546 enddef
8547 endclass
8548
8549 const math = Math.new()
8550 assert_equal(48, Map(math.Double)(24))
8551 END
8552 v9.CheckSourceSuccess(lines)
8553
Ernie Rael03042a22023-11-11 08:53:32 +01008554 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008555 lines =<< trim END
8556 vim9script
8557 class A
8558 def _Foo()
8559 enddef
8560 endclass
8561 def Bar()
8562 var a = A.new()
8563 var Fn = a._Foo
8564 enddef
8565 Bar()
8566 END
Ernie Rael03042a22023-11-11 08:53:32 +01008567 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008568
Ernie Rael03042a22023-11-11 08:53:32 +01008569 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008570 lines =<< trim END
8571 vim9script
8572 class A
8573 def _Foo()
8574 enddef
8575 endclass
8576 var a = A.new()
8577 var Fn = a._Foo
8578 END
Ernie Rael03042a22023-11-11 08:53:32 +01008579 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008580
Ernie Rael03042a22023-11-11 08:53:32 +01008581 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008582 lines =<< trim END
8583 vim9script
8584 class A
8585 def _Foo(): list<number>
8586 return [3, 2, 1]
8587 enddef
8588 def Bar()
8589 var Fn = this._Foo
8590 assert_equal([3, 2, 1], Fn())
8591 enddef
8592 endclass
8593 var a = A.new()
8594 a.Bar()
8595 END
8596 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008597
8598 # Using object method funcref using call()
8599 lines =<< trim END
8600 vim9script
8601 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008602 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008603 def Foo(): number
8604 return this.val
8605 enddef
8606 endclass
8607
8608 def Bar(obj: A)
8609 assert_equal(123, call(obj.Foo, []))
8610 enddef
8611
8612 var a = A.new(123)
8613 Bar(a)
8614 assert_equal(123, call(a.Foo, []))
8615 END
8616 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008617enddef
8618
8619" Test for using a class method as a funcref
8620def Test_class_funcref()
8621 # Using class method funcref in a def function
8622 var lines =<< trim END
8623 vim9script
8624 class A
8625 static def Foo(): list<number>
8626 return [3, 2, 1]
8627 enddef
8628 endclass
8629 def Bar()
8630 var Fn = A.Foo
8631 assert_equal([3, 2, 1], Fn())
8632 enddef
8633 Bar()
8634 END
8635 v9.CheckSourceSuccess(lines)
8636
8637 # Using class method funcref at script level
8638 lines =<< trim END
8639 vim9script
8640 class A
8641 static def Foo(): dict<number>
8642 return {a: 1, b: 2}
8643 enddef
8644 endclass
8645 var Fn = A.Foo
8646 assert_equal({a: 1, b: 2}, Fn())
8647 END
8648 v9.CheckSourceSuccess(lines)
8649
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008650 # Using class method funcref at the script level
8651 lines =<< trim END
8652 vim9script
8653 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008654 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008655 static def Foo(): number
8656 return val
8657 enddef
8658 endclass
8659 A.val = 567
8660 var Fn = A.Foo
8661 assert_equal(567, Fn())
8662 END
8663 v9.CheckSourceSuccess(lines)
8664
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008665 # Using function() to get a class method funcref
8666 lines =<< trim END
8667 vim9script
8668 class A
8669 static def Foo(l: list<any>): list<any>
8670 return l
8671 enddef
8672 endclass
8673 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8674 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8675 END
8676 v9.CheckSourceSuccess(lines)
8677
8678 # Using a class method funcref from another class method
8679 lines =<< trim END
8680 vim9script
8681 class A
8682 static def Foo(): list<number>
8683 return [3, 2, 1]
8684 enddef
8685 static def Bar()
8686 var Fn = Foo
8687 assert_equal([3, 2, 1], Fn())
8688 enddef
8689 endclass
8690 A.Bar()
8691 END
8692 v9.CheckSourceSuccess(lines)
8693
8694 # Use a class method with a function returning a funcref and then call the
8695 # funcref.
8696 lines =<< trim END
8697 vim9script
8698
8699 def Map(F: func(number): number): func(number): number
8700 return (n: number) => F(n)
8701 enddef
8702
8703 class Math
8704 static def StaticDouble(n: number): number
8705 return 2 * n
8706 enddef
8707 endclass
8708
8709 assert_equal(48, Map(Math.StaticDouble)(24))
8710 END
8711 v9.CheckSourceSuccess(lines)
8712
Ernie Rael03042a22023-11-11 08:53:32 +01008713 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008714 lines =<< trim END
8715 vim9script
8716 class A
8717 static def _Foo()
8718 enddef
8719 endclass
8720 def Bar()
8721 var Fn = A._Foo
8722 enddef
8723 Bar()
8724 END
Ernie Rael03042a22023-11-11 08:53:32 +01008725 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008726
Ernie Rael03042a22023-11-11 08:53:32 +01008727 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008728 lines =<< trim END
8729 vim9script
8730 class A
8731 static def _Foo()
8732 enddef
8733 endclass
8734 var Fn = A._Foo
8735 END
Ernie Rael03042a22023-11-11 08:53:32 +01008736 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008737
Ernie Rael03042a22023-11-11 08:53:32 +01008738 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008739 lines =<< trim END
8740 vim9script
8741 class A
8742 static def _Foo(): list<number>
8743 return [3, 2, 1]
8744 enddef
8745 static def Bar()
8746 var Fn = _Foo
8747 assert_equal([3, 2, 1], Fn())
8748 enddef
8749 endclass
8750 A.Bar()
8751 END
8752 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008753
8754 # Using class method funcref using call()
8755 lines =<< trim END
8756 vim9script
8757 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008758 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008759 static def Foo(): number
8760 return val
8761 enddef
8762 endclass
8763
8764 def Bar()
8765 A.val = 468
8766 assert_equal(468, call(A.Foo, []))
8767 enddef
8768 Bar()
8769 assert_equal(468, call(A.Foo, []))
8770 END
8771 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008772enddef
8773
8774" Test for using an object member as a funcref
8775def Test_object_member_funcref()
8776 # Using a funcref object variable in an object method
8777 var lines =<< trim END
8778 vim9script
8779 def Foo(n: number): number
8780 return n * 10
8781 enddef
8782
8783 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008784 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008785 def Bar()
8786 assert_equal(200, this.Cb(20))
8787 enddef
8788 endclass
8789
8790 var a = A.new()
8791 a.Bar()
8792 END
8793 v9.CheckSourceSuccess(lines)
8794
8795 # Using a funcref object variable in a def method
8796 lines =<< trim END
8797 vim9script
8798 def Foo(n: number): number
8799 return n * 10
8800 enddef
8801
8802 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008803 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008804 endclass
8805
8806 def Bar()
8807 var a = A.new()
8808 assert_equal(200, a.Cb(20))
8809 enddef
8810 Bar()
8811 END
8812 v9.CheckSourceSuccess(lines)
8813
8814 # Using a funcref object variable at script level
8815 lines =<< trim END
8816 vim9script
8817 def Foo(n: number): number
8818 return n * 10
8819 enddef
8820
8821 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008822 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008823 endclass
8824
8825 var a = A.new()
8826 assert_equal(200, a.Cb(20))
8827 END
8828 v9.CheckSourceSuccess(lines)
8829
8830 # Using a funcref object variable pointing to an object method in an object
8831 # method.
8832 lines =<< trim END
8833 vim9script
8834 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008835 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008836 def Foo(n: number): number
8837 return n * 10
8838 enddef
8839 def Bar()
8840 assert_equal(200, this.Cb(20))
8841 enddef
8842 endclass
8843
8844 var a = A.new()
8845 a.Bar()
8846 END
8847 v9.CheckSourceSuccess(lines)
8848
8849 # Using a funcref object variable pointing to an object method in a def
8850 # method.
8851 lines =<< trim END
8852 vim9script
8853 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008854 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008855 def Foo(n: number): number
8856 return n * 10
8857 enddef
8858 endclass
8859
8860 def Bar()
8861 var a = A.new()
8862 assert_equal(200, a.Cb(20))
8863 enddef
8864 Bar()
8865 END
8866 v9.CheckSourceSuccess(lines)
8867
8868 # Using a funcref object variable pointing to an object method at script
8869 # level.
8870 lines =<< trim END
8871 vim9script
8872 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008873 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008874 def Foo(n: number): number
8875 return n * 10
8876 enddef
8877 endclass
8878
8879 var a = A.new()
8880 assert_equal(200, a.Cb(20))
8881 END
8882 v9.CheckSourceSuccess(lines)
8883enddef
8884
8885" Test for using a class member as a funcref
8886def Test_class_member_funcref()
8887 # Using a funcref class variable in a class method
8888 var lines =<< trim END
8889 vim9script
8890 def Foo(n: number): number
8891 return n * 10
8892 enddef
8893
8894 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008895 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008896 static def Bar()
8897 assert_equal(200, Cb(20))
8898 enddef
8899 endclass
8900
8901 A.Bar()
8902 END
8903 v9.CheckSourceSuccess(lines)
8904
8905 # Using a funcref class variable in a def method
8906 lines =<< trim END
8907 vim9script
8908 def Foo(n: number): number
8909 return n * 10
8910 enddef
8911
8912 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008913 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008914 endclass
8915
8916 def Bar()
8917 assert_equal(200, A.Cb(20))
8918 enddef
8919 Bar()
8920 END
8921 v9.CheckSourceSuccess(lines)
8922
8923 # Using a funcref class variable at script level
8924 lines =<< trim END
8925 vim9script
8926 def Foo(n: number): number
8927 return n * 10
8928 enddef
8929
8930 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008931 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008932 endclass
8933
8934 assert_equal(200, A.Cb(20))
8935 END
8936 v9.CheckSourceSuccess(lines)
8937
8938 # Using a funcref class variable pointing to a class method in a class
8939 # method.
8940 lines =<< trim END
8941 vim9script
8942 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008943 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008944 static def Foo(n: number): number
8945 return n * 10
8946 enddef
8947 static def Init()
8948 Cb = Foo
8949 enddef
8950 static def Bar()
8951 assert_equal(200, Cb(20))
8952 enddef
8953 endclass
8954
8955 A.Init()
8956 A.Bar()
8957 END
8958 v9.CheckSourceSuccess(lines)
8959
8960 # Using a funcref class variable pointing to a class method in a def method.
8961 lines =<< trim END
8962 vim9script
8963 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008964 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008965 static def Foo(n: number): number
8966 return n * 10
8967 enddef
8968 static def Init()
8969 Cb = Foo
8970 enddef
8971 endclass
8972
8973 def Bar()
8974 A.Init()
8975 assert_equal(200, A.Cb(20))
8976 enddef
8977 Bar()
8978 END
8979 v9.CheckSourceSuccess(lines)
8980
8981 # Using a funcref class variable pointing to a class method at script level.
8982 lines =<< trim END
8983 vim9script
8984 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008985 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008986 static def Foo(n: number): number
8987 return n * 10
8988 enddef
8989 static def Init()
8990 Cb = Foo
8991 enddef
8992 endclass
8993
8994 A.Init()
8995 assert_equal(200, A.Cb(20))
8996 END
8997 v9.CheckSourceSuccess(lines)
8998enddef
8999
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009000" Test for using object methods as popup callback functions
9001def Test_objmethod_popup_callback()
9002 # Use the popup from the script level
9003 var lines =<< trim END
9004 vim9script
9005
9006 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009007 var selection: number = -1
9008 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009009
9010 def PopupFilter(id: number, key: string): bool
9011 add(this.filterkeys, key)
9012 return popup_filter_yesno(id, key)
9013 enddef
9014
9015 def PopupCb(id: number, result: number)
9016 this.selection = result ? 100 : 200
9017 enddef
9018 endclass
9019
9020 var a = A.new()
9021 feedkeys('', 'xt')
9022 var winid = popup_create('Y/N?',
9023 {filter: a.PopupFilter, callback: a.PopupCb})
9024 feedkeys('y', 'xt')
9025 popup_close(winid)
9026 assert_equal(100, a.selection)
9027 assert_equal(['y'], a.filterkeys)
9028 feedkeys('', 'xt')
9029 winid = popup_create('Y/N?',
9030 {filter: a.PopupFilter, callback: a.PopupCb})
9031 feedkeys('n', 'xt')
9032 popup_close(winid)
9033 assert_equal(200, a.selection)
9034 assert_equal(['y', 'n'], a.filterkeys)
9035 END
9036 v9.CheckSourceSuccess(lines)
9037
9038 # Use the popup from a def function
9039 lines =<< trim END
9040 vim9script
9041
9042 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009043 var selection: number = -1
9044 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009045
9046 def PopupFilter(id: number, key: string): bool
9047 add(this.filterkeys, key)
9048 return popup_filter_yesno(id, key)
9049 enddef
9050
9051 def PopupCb(id: number, result: number)
9052 this.selection = result ? 100 : 200
9053 enddef
9054 endclass
9055
9056 def Foo()
9057 var a = A.new()
9058 feedkeys('', 'xt')
9059 var winid = popup_create('Y/N?',
9060 {filter: a.PopupFilter, callback: a.PopupCb})
9061 feedkeys('y', 'xt')
9062 popup_close(winid)
9063 assert_equal(100, a.selection)
9064 assert_equal(['y'], a.filterkeys)
9065 feedkeys('', 'xt')
9066 winid = popup_create('Y/N?',
9067 {filter: a.PopupFilter, callback: a.PopupCb})
9068 feedkeys('n', 'xt')
9069 popup_close(winid)
9070 assert_equal(200, a.selection)
9071 assert_equal(['y', 'n'], a.filterkeys)
9072 enddef
9073 Foo()
9074 END
9075 v9.CheckSourceSuccess(lines)
9076enddef
9077
9078" Test for using class methods as popup callback functions
9079def Test_classmethod_popup_callback()
9080 # Use the popup from the script level
9081 var lines =<< trim END
9082 vim9script
9083
9084 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009085 static var selection: number = -1
9086 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009087
9088 static def PopupFilter(id: number, key: string): bool
9089 add(filterkeys, key)
9090 return popup_filter_yesno(id, key)
9091 enddef
9092
9093 static def PopupCb(id: number, result: number)
9094 selection = result ? 100 : 200
9095 enddef
9096 endclass
9097
9098 feedkeys('', 'xt')
9099 var winid = popup_create('Y/N?',
9100 {filter: A.PopupFilter, callback: A.PopupCb})
9101 feedkeys('y', 'xt')
9102 popup_close(winid)
9103 assert_equal(100, A.selection)
9104 assert_equal(['y'], A.filterkeys)
9105 feedkeys('', 'xt')
9106 winid = popup_create('Y/N?',
9107 {filter: A.PopupFilter, callback: A.PopupCb})
9108 feedkeys('n', 'xt')
9109 popup_close(winid)
9110 assert_equal(200, A.selection)
9111 assert_equal(['y', 'n'], A.filterkeys)
9112 END
9113 v9.CheckSourceSuccess(lines)
9114
9115 # Use the popup from a def function
9116 lines =<< trim END
9117 vim9script
9118
9119 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009120 static var selection: number = -1
9121 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009122
9123 static def PopupFilter(id: number, key: string): bool
9124 add(filterkeys, key)
9125 return popup_filter_yesno(id, key)
9126 enddef
9127
9128 static def PopupCb(id: number, result: number)
9129 selection = result ? 100 : 200
9130 enddef
9131 endclass
9132
9133 def Foo()
9134 feedkeys('', 'xt')
9135 var winid = popup_create('Y/N?',
9136 {filter: A.PopupFilter, callback: A.PopupCb})
9137 feedkeys('y', 'xt')
9138 popup_close(winid)
9139 assert_equal(100, A.selection)
9140 assert_equal(['y'], A.filterkeys)
9141 feedkeys('', 'xt')
9142 winid = popup_create('Y/N?',
9143 {filter: A.PopupFilter, callback: A.PopupCb})
9144 feedkeys('n', 'xt')
9145 popup_close(winid)
9146 assert_equal(200, A.selection)
9147 assert_equal(['y', 'n'], A.filterkeys)
9148 enddef
9149 Foo()
9150 END
9151 v9.CheckSourceSuccess(lines)
9152enddef
9153
9154" Test for using an object method as a timer callback function
9155def Test_objmethod_timer_callback()
9156 # Use the timer callback from script level
9157 var lines =<< trim END
9158 vim9script
9159
9160 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009161 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009162 def TimerCb(timerID: number)
9163 this.timerTick = 6
9164 enddef
9165 endclass
9166
9167 var a = A.new()
9168 timer_start(0, a.TimerCb)
9169 var maxWait = 5
9170 while maxWait > 0 && a.timerTick == -1
9171 :sleep 10m
9172 maxWait -= 1
9173 endwhile
9174 assert_equal(6, a.timerTick)
9175 END
9176 v9.CheckSourceSuccess(lines)
9177
9178 # Use the timer callback from a def function
9179 lines =<< trim END
9180 vim9script
9181
9182 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009183 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009184 def TimerCb(timerID: number)
9185 this.timerTick = 6
9186 enddef
9187 endclass
9188
9189 def Foo()
9190 var a = A.new()
9191 timer_start(0, a.TimerCb)
9192 var maxWait = 5
9193 while maxWait > 0 && a.timerTick == -1
9194 :sleep 10m
9195 maxWait -= 1
9196 endwhile
9197 assert_equal(6, a.timerTick)
9198 enddef
9199 Foo()
9200 END
9201 v9.CheckSourceSuccess(lines)
9202enddef
9203
9204" Test for using a class method as a timer callback function
9205def Test_classmethod_timer_callback()
9206 # Use the timer callback from script level
9207 var lines =<< trim END
9208 vim9script
9209
9210 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009211 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009212 static def TimerCb(timerID: number)
9213 timerTick = 6
9214 enddef
9215 endclass
9216
9217 timer_start(0, A.TimerCb)
9218 var maxWait = 5
9219 while maxWait > 0 && A.timerTick == -1
9220 :sleep 10m
9221 maxWait -= 1
9222 endwhile
9223 assert_equal(6, A.timerTick)
9224 END
9225 v9.CheckSourceSuccess(lines)
9226
9227 # Use the timer callback from a def function
9228 lines =<< trim END
9229 vim9script
9230
9231 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009232 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009233 static def TimerCb(timerID: number)
9234 timerTick = 6
9235 enddef
9236 endclass
9237
9238 def Foo()
9239 timer_start(0, A.TimerCb)
9240 var maxWait = 5
9241 while maxWait > 0 && A.timerTick == -1
9242 :sleep 10m
9243 maxWait -= 1
9244 endwhile
9245 assert_equal(6, A.timerTick)
9246 enddef
9247 Foo()
9248 END
9249 v9.CheckSourceSuccess(lines)
9250enddef
9251
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009252" Test for using a class variable as the first and/or second operand of a binary
9253" operator.
9254def Test_class_variable_as_operands()
9255 var lines =<< trim END
9256 vim9script
9257 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009258 static var truthy: bool = true
9259 public static var TruthyFn: func
9260 static var list: list<any> = []
9261 static var four: number = 4
9262 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009263
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009264 static def Str(): string
9265 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009266 enddef
9267
9268 static def Four(): number
9269 return four
9270 enddef
9271
9272 static def List(): list<any>
9273 return list
9274 enddef
9275
9276 static def Truthy(): bool
9277 return truthy
9278 enddef
9279
9280 def TestOps()
9281 assert_true(Tests.truthy == truthy)
9282 assert_true(truthy == Tests.truthy)
9283 assert_true(Tests.list isnot [])
9284 assert_true([] isnot Tests.list)
9285 assert_equal(2, Tests.four >> 1)
9286 assert_equal(16, 1 << Tests.four)
9287 assert_equal(8, Tests.four + four)
9288 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009289 assert_equal('hellohello', Tests.str .. str)
9290 assert_equal('hellohello', str .. Tests.str)
9291
9292 # Using class variable for list indexing
9293 var l = range(10)
9294 assert_equal(4, l[Tests.four])
9295 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9296
9297 # Using class variable for Dict key
9298 var d = {hello: 'abc'}
9299 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009300 enddef
9301 endclass
9302
9303 def TestOps2()
9304 assert_true(Tests.truthy == Tests.Truthy())
9305 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009306 assert_true(Tests.truthy == Tests.TruthyFn())
9307 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009308 assert_true(Tests.list is Tests.List())
9309 assert_true(Tests.List() is Tests.list)
9310 assert_equal(2, Tests.four >> 1)
9311 assert_equal(16, 1 << Tests.four)
9312 assert_equal(8, Tests.four + Tests.Four())
9313 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009314 assert_equal('hellohello', Tests.str .. Tests.Str())
9315 assert_equal('hellohello', Tests.Str() .. Tests.str)
9316
9317 # Using class variable for list indexing
9318 var l = range(10)
9319 assert_equal(4, l[Tests.four])
9320 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9321
9322 # Using class variable for Dict key
9323 var d = {hello: 'abc'}
9324 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009325 enddef
9326
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009327 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009328 var t = Tests.new()
9329 t.TestOps()
9330 TestOps2()
9331
9332 assert_true(Tests.truthy == Tests.Truthy())
9333 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009334 assert_true(Tests.truthy == Tests.TruthyFn())
9335 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009336 assert_true(Tests.list is Tests.List())
9337 assert_true(Tests.List() is Tests.list)
9338 assert_equal(2, Tests.four >> 1)
9339 assert_equal(16, 1 << Tests.four)
9340 assert_equal(8, Tests.four + Tests.Four())
9341 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009342 assert_equal('hellohello', Tests.str .. Tests.Str())
9343 assert_equal('hellohello', Tests.Str() .. Tests.str)
9344
9345 # Using class variable for list indexing
9346 var l = range(10)
9347 assert_equal(4, l[Tests.four])
9348 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9349
9350 # Using class variable for Dict key
9351 var d = {hello: 'abc'}
9352 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009353 END
9354 v9.CheckSourceSuccess(lines)
9355enddef
9356
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009357" Test for checking the type of the key used to access an object dict member.
9358def Test_dict_member_key_type_check()
9359 var lines =<< trim END
9360 vim9script
9361
9362 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009363 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009364 endclass
9365
9366 class Test extends State
9367 def ObjMethodTests()
9368 var cursor: number = 0
9369 var z: number = 0
9370 [this.numbers[cursor]] = ['zero.1']
9371 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9372 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9373 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9374 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9375 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9376 [this.numbers[cursor], z] = ['zero.4', 1]
9377 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9378 [z, this.numbers[cursor]] = [1, 'zero.5']
9379 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9380 enddef
9381
9382 static def ClassMethodTests(that: State)
9383 var cursor: number = 0
9384 var z: number = 0
9385 [that.numbers[cursor]] = ['zero.1']
9386 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9387 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9388 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9389 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9390 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9391 [that.numbers[cursor], z] = ['zero.4', 1]
9392 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9393 [z, that.numbers[cursor]] = [1, 'zero.5']
9394 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9395 enddef
9396
9397 def new()
9398 enddef
9399
9400 def newMethodTests()
9401 var cursor: number = 0
9402 var z: number
9403 [this.numbers[cursor]] = ['zero.1']
9404 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9405 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9406 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9407 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9408 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9409 [this.numbers[cursor], z] = ['zero.4', 1]
9410 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9411 [z, this.numbers[cursor]] = [1, 'zero.5']
9412 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9413 enddef
9414 endclass
9415
9416 def DefFuncTests(that: Test)
9417 var cursor: number = 0
9418 var z: number
9419 [that.numbers[cursor]] = ['zero.1']
9420 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9421 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9422 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9423 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9424 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9425 [that.numbers[cursor], z] = ['zero.4', 1]
9426 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9427 [z, that.numbers[cursor]] = [1, 'zero.5']
9428 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9429 enddef
9430
9431 Test.newMethodTests()
9432 Test.new().ObjMethodTests()
9433 Test.ClassMethodTests(Test.new())
9434 DefFuncTests(Test.new())
9435
9436 const test: Test = Test.new()
9437 var cursor: number = 0
9438 [test.numbers[cursor], cursor] = ['zero', 1]
9439 [cursor, test.numbers[cursor]] = [1, 'one']
9440 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9441 END
9442 v9.CheckSourceSuccess(lines)
9443
9444 lines =<< trim END
9445 vim9script
9446
9447 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009448 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009449
9450 def new()
9451 enddef
9452
9453 def Foo()
9454 var z: number
9455 [this.numbers.a, z] = [{}, 10]
9456 enddef
9457 endclass
9458
9459 var a = A.new()
9460 a.Foo()
9461 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009462 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009463
9464 lines =<< trim END
9465 vim9script
9466
9467 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009468 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009469
9470 def new()
9471 enddef
9472
9473 def Foo()
9474 var x: string = 'a'
9475 var y: number
9476 [this.numbers[x], y] = [{}, 10]
9477 enddef
9478 endclass
9479
9480 var a = A.new()
9481 a.Foo()
9482 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009483 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009484enddef
9485
mityua5550692023-11-25 15:41:20 +01009486def Test_compile_many_def_functions_in_funcref_instr()
9487 # This used to crash Vim. This is reproducible only when run on new instance
9488 # of Vim.
9489 var lines =<< trim END
9490 vim9script
9491
9492 class A
9493 def new()
9494 this.TakeFunc(this.F00)
9495 enddef
9496
9497 def TakeFunc(F: func)
9498 enddef
9499
9500 def F00()
9501 this.F01()
9502 this.F02()
9503 this.F03()
9504 this.F04()
9505 this.F05()
9506 this.F06()
9507 this.F07()
9508 this.F08()
9509 this.F09()
9510 this.F10()
9511 this.F11()
9512 this.F12()
9513 this.F13()
9514 this.F14()
9515 this.F15()
9516 this.F16()
9517 this.F17()
9518 this.F18()
9519 this.F19()
9520 this.F20()
9521 this.F21()
9522 this.F22()
9523 this.F23()
9524 this.F24()
9525 this.F25()
9526 this.F26()
9527 this.F27()
9528 this.F28()
9529 this.F29()
9530 this.F30()
9531 this.F31()
9532 this.F32()
9533 this.F33()
9534 this.F34()
9535 this.F35()
9536 this.F36()
9537 this.F37()
9538 this.F38()
9539 this.F39()
9540 this.F40()
9541 this.F41()
9542 this.F42()
9543 this.F43()
9544 this.F44()
9545 this.F45()
9546 this.F46()
9547 this.F47()
9548 enddef
9549
9550 def F01()
9551 enddef
9552 def F02()
9553 enddef
9554 def F03()
9555 enddef
9556 def F04()
9557 enddef
9558 def F05()
9559 enddef
9560 def F06()
9561 enddef
9562 def F07()
9563 enddef
9564 def F08()
9565 enddef
9566 def F09()
9567 enddef
9568 def F10()
9569 enddef
9570 def F11()
9571 enddef
9572 def F12()
9573 enddef
9574 def F13()
9575 enddef
9576 def F14()
9577 enddef
9578 def F15()
9579 enddef
9580 def F16()
9581 enddef
9582 def F17()
9583 enddef
9584 def F18()
9585 enddef
9586 def F19()
9587 enddef
9588 def F20()
9589 enddef
9590 def F21()
9591 enddef
9592 def F22()
9593 enddef
9594 def F23()
9595 enddef
9596 def F24()
9597 enddef
9598 def F25()
9599 enddef
9600 def F26()
9601 enddef
9602 def F27()
9603 enddef
9604 def F28()
9605 enddef
9606 def F29()
9607 enddef
9608 def F30()
9609 enddef
9610 def F31()
9611 enddef
9612 def F32()
9613 enddef
9614 def F33()
9615 enddef
9616 def F34()
9617 enddef
9618 def F35()
9619 enddef
9620 def F36()
9621 enddef
9622 def F37()
9623 enddef
9624 def F38()
9625 enddef
9626 def F39()
9627 enddef
9628 def F40()
9629 enddef
9630 def F41()
9631 enddef
9632 def F42()
9633 enddef
9634 def F43()
9635 enddef
9636 def F44()
9637 enddef
9638 def F45()
9639 enddef
9640 def F46()
9641 enddef
9642 def F47()
9643 enddef
9644 endclass
9645
9646 A.new()
9647 END
9648 writefile(lines, 'Xscript', 'D')
9649 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9650 assert_equal(0, v:shell_error)
9651enddef
9652
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009653" Test for 'final' class and object variables
9654def Test_final_class_object_variable()
9655 # Test for changing a final object variable from an object function
9656 var lines =<< trim END
9657 vim9script
9658 class A
9659 final foo: string = "abc"
9660 def Foo()
9661 this.foo = "def"
9662 enddef
9663 endclass
9664 defcompile A.Foo
9665 END
9666 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9667
9668 # Test for changing a final object variable from the 'new' function
9669 lines =<< trim END
9670 vim9script
9671 class A
9672 final s1: string
9673 final s2: string
9674 def new(this.s1)
9675 this.s2 = 'def'
9676 enddef
9677 endclass
9678 var a = A.new('abc')
9679 assert_equal('abc', a.s1)
9680 assert_equal('def', a.s2)
9681 END
9682 v9.CheckSourceSuccess(lines)
9683
9684 # Test for a final class variable
9685 lines =<< trim END
9686 vim9script
9687 class A
9688 static final s1: string = "abc"
9689 endclass
9690 assert_equal('abc', A.s1)
9691 END
9692 v9.CheckSourceSuccess(lines)
9693
9694 # Test for changing a final class variable from a class function
9695 lines =<< trim END
9696 vim9script
9697 class A
9698 static final s1: string = "abc"
9699 static def Foo()
9700 s1 = "def"
9701 enddef
9702 endclass
9703 A.Foo()
9704 END
9705 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9706
9707 # Test for changing a public final class variable at script level
9708 lines =<< trim END
9709 vim9script
9710 class A
9711 public static final s1: string = "abc"
9712 endclass
9713 assert_equal('abc', A.s1)
9714 A.s1 = 'def'
9715 END
9716 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9717
9718 # Test for changing a public final class variable from a class function
9719 lines =<< trim END
9720 vim9script
9721 class A
9722 public static final s1: string = "abc"
9723 static def Foo()
9724 s1 = "def"
9725 enddef
9726 endclass
9727 A.Foo()
9728 END
9729 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9730
9731 # Test for changing a public final class variable from a function
9732 lines =<< trim END
9733 vim9script
9734 class A
9735 public static final s1: string = "abc"
9736 endclass
9737 def Foo()
9738 A.s1 = 'def'
9739 enddef
9740 defcompile
9741 END
9742 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9743
9744 # Test for using a final variable of composite type
9745 lines =<< trim END
9746 vim9script
9747 class A
9748 public final l: list<number>
9749 def new()
9750 this.l = [1, 2]
9751 enddef
9752 def Foo()
9753 this.l[0] = 3
9754 this.l->add(4)
9755 enddef
9756 endclass
9757 var a = A.new()
9758 assert_equal([1, 2], a.l)
9759 a.Foo()
9760 assert_equal([3, 2, 4], a.l)
9761 END
9762 v9.CheckSourceSuccess(lines)
9763
9764 # Test for changing a final variable of composite type from another object
9765 # function
9766 lines =<< trim END
9767 vim9script
9768 class A
9769 public final l: list<number> = [1, 2]
9770 def Foo()
9771 this.l = [3, 4]
9772 enddef
9773 endclass
9774 var a = A.new()
9775 a.Foo()
9776 END
9777 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9778
9779 # Test for modifying a final variable of composite type at script level
9780 lines =<< trim END
9781 vim9script
9782 class A
9783 public final l: list<number> = [1, 2]
9784 endclass
9785 var a = A.new()
9786 a.l[0] = 3
9787 a.l->add(4)
9788 assert_equal([3, 2, 4], a.l)
9789 END
9790 v9.CheckSourceSuccess(lines)
9791
9792 # Test for modifying a final variable of composite type from a function
9793 lines =<< trim END
9794 vim9script
9795 class A
9796 public final l: list<number> = [1, 2]
9797 endclass
9798 def Foo()
9799 var a = A.new()
9800 a.l[0] = 3
9801 a.l->add(4)
9802 assert_equal([3, 2, 4], a.l)
9803 enddef
9804 Foo()
9805 END
9806 v9.CheckSourceSuccess(lines)
9807
9808 # Test for modifying a final variable of composite type from another object
9809 # function
9810 lines =<< trim END
9811 vim9script
9812 class A
9813 public final l: list<number> = [1, 2]
9814 def Foo()
9815 this.l[0] = 3
9816 this.l->add(4)
9817 enddef
9818 endclass
9819 var a = A.new()
9820 a.Foo()
9821 assert_equal([3, 2, 4], a.l)
9822 END
9823 v9.CheckSourceSuccess(lines)
9824
9825 # Test for assigning a new value to a final variable of composite type at
9826 # script level
9827 lines =<< trim END
9828 vim9script
9829 class A
9830 public final l: list<number> = [1, 2]
9831 endclass
9832 var a = A.new()
9833 a.l = [3, 4]
9834 END
9835 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
9836
9837 # Test for assigning a new value to a final variable of composite type from
9838 # another object function
9839 lines =<< trim END
9840 vim9script
9841 class A
9842 public final l: list<number> = [1, 2]
9843 def Foo()
9844 this.l = [3, 4]
9845 enddef
9846 endclass
9847 var a = A.new()
9848 a.Foo()
9849 END
9850 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9851
9852 # Test for assigning a new value to a final variable of composite type from
9853 # another function
9854 lines =<< trim END
9855 vim9script
9856 class A
9857 public final l: list<number> = [1, 2]
9858 endclass
9859 def Foo()
9860 var a = A.new()
9861 a.l = [3, 4]
9862 enddef
9863 Foo()
9864 END
9865 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
9866
9867 # Error case: Use 'final' with just a variable name
9868 lines =<< trim END
9869 vim9script
9870 class A
9871 final foo
9872 endclass
9873 var a = A.new()
9874 END
9875 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9876
9877 # Error case: Use 'final' followed by 'public'
9878 lines =<< trim END
9879 vim9script
9880 class A
9881 final public foo: number
9882 endclass
9883 var a = A.new()
9884 END
9885 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9886
9887 # Error case: Use 'final' followed by 'static'
9888 lines =<< trim END
9889 vim9script
9890 class A
9891 final static foo: number
9892 endclass
9893 var a = A.new()
9894 END
9895 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9896
9897 # Error case: 'final' cannot be used in an interface
9898 lines =<< trim END
9899 vim9script
9900 interface A
9901 final foo: number = 10
9902 endinterface
9903 END
9904 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
9905
9906 # Error case: 'final' not supported for an object method
9907 lines =<< trim END
9908 vim9script
9909 class A
9910 final def Foo()
9911 enddef
9912 endclass
9913 END
9914 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9915
9916 # Error case: 'final' not supported for a class method
9917 lines =<< trim END
9918 vim9script
9919 class A
9920 static final def Foo()
9921 enddef
9922 endclass
9923 END
9924 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9925enddef
9926
9927" Test for 'const' class and object variables
9928def Test_const_class_object_variable()
9929 # Test for changing a const object variable from an object function
9930 var lines =<< trim END
9931 vim9script
9932 class A
9933 const foo: string = "abc"
9934 def Foo()
9935 this.foo = "def"
9936 enddef
9937 endclass
9938 defcompile A.Foo
9939 END
9940 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9941
9942 # Test for changing a const object variable from the 'new' function
9943 lines =<< trim END
9944 vim9script
9945 class A
9946 const s1: string
9947 const s2: string
9948 def new(this.s1)
9949 this.s2 = 'def'
9950 enddef
9951 endclass
9952 var a = A.new('abc')
9953 assert_equal('abc', a.s1)
9954 assert_equal('def', a.s2)
9955 END
9956 v9.CheckSourceSuccess(lines)
9957
9958 # Test for changing a const object variable from an object method called from
9959 # the 'new' function
9960 lines =<< trim END
9961 vim9script
9962 class A
9963 const s1: string = 'abc'
9964 def new()
9965 this.ChangeStr()
9966 enddef
9967 def ChangeStr()
9968 this.s1 = 'def'
9969 enddef
9970 endclass
9971 var a = A.new()
9972 END
9973 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9974
9975 # Test for a const class variable
9976 lines =<< trim END
9977 vim9script
9978 class A
9979 static const s1: string = "abc"
9980 endclass
9981 assert_equal('abc', A.s1)
9982 END
9983 v9.CheckSourceSuccess(lines)
9984
9985 # Test for changing a const class variable from a class function
9986 lines =<< trim END
9987 vim9script
9988 class A
9989 static const s1: string = "abc"
9990 static def Foo()
9991 s1 = "def"
9992 enddef
9993 endclass
9994 A.Foo()
9995 END
9996 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9997
9998 # Test for changing a public const class variable at script level
9999 lines =<< trim END
10000 vim9script
10001 class A
10002 public static const s1: string = "abc"
10003 endclass
10004 assert_equal('abc', A.s1)
10005 A.s1 = 'def'
10006 END
10007 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
10008
10009 # Test for changing a public const class variable from a class function
10010 lines =<< trim END
10011 vim9script
10012 class A
10013 public static const s1: string = "abc"
10014 static def Foo()
10015 s1 = "def"
10016 enddef
10017 endclass
10018 A.Foo()
10019 END
10020 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10021
10022 # Test for changing a public const class variable from a function
10023 lines =<< trim END
10024 vim9script
10025 class A
10026 public static const s1: string = "abc"
10027 endclass
10028 def Foo()
10029 A.s1 = 'def'
10030 enddef
10031 defcompile
10032 END
10033 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10034
10035 # Test for changing a const List item from an object function
10036 lines =<< trim END
10037 vim9script
10038 class A
10039 public const l: list<number>
10040 def new()
10041 this.l = [1, 2]
10042 enddef
10043 def Foo()
10044 this.l[0] = 3
10045 enddef
10046 endclass
10047 var a = A.new()
10048 assert_equal([1, 2], a.l)
10049 a.Foo()
10050 END
10051 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10052
10053 # Test for adding a value to a const List from an object function
10054 lines =<< trim END
10055 vim9script
10056 class A
10057 public const l: list<number>
10058 def new()
10059 this.l = [1, 2]
10060 enddef
10061 def Foo()
10062 this.l->add(3)
10063 enddef
10064 endclass
10065 var a = A.new()
10066 a.Foo()
10067 END
10068 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10069
10070 # Test for reassigning a const List from an object function
10071 lines =<< trim END
10072 vim9script
10073 class A
10074 public const l: list<number> = [1, 2]
10075 def Foo()
10076 this.l = [3, 4]
10077 enddef
10078 endclass
10079 var a = A.new()
10080 a.Foo()
10081 END
10082 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10083
10084 # Test for changing a const List item at script level
10085 lines =<< trim END
10086 vim9script
10087 class A
10088 public const l: list<number> = [1, 2]
10089 endclass
10090 var a = A.new()
10091 a.l[0] = 3
10092 END
10093 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10094
10095 # Test for adding a value to a const List item at script level
10096 lines =<< trim END
10097 vim9script
10098 class A
10099 public const l: list<number> = [1, 2]
10100 endclass
10101 var a = A.new()
10102 a.l->add(4)
10103 END
10104 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10105
10106 # Test for changing a const List item from a function
10107 lines =<< trim END
10108 vim9script
10109 class A
10110 public const l: list<number> = [1, 2]
10111 endclass
10112 def Foo()
10113 var a = A.new()
10114 a.l[0] = 3
10115 enddef
10116 Foo()
10117 END
10118 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
10119
10120 # Test for adding a value to a const List item from a function
10121 lines =<< trim END
10122 vim9script
10123 class A
10124 public const l: list<number> = [1, 2]
10125 endclass
10126 def Foo()
10127 var a = A.new()
10128 a.l->add(4)
10129 enddef
10130 Foo()
10131 END
10132 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
10133
10134 # Test for changing a const List item from an object method
10135 lines =<< trim END
10136 vim9script
10137 class A
10138 public const l: list<number> = [1, 2]
10139 def Foo()
10140 this.l[0] = 3
10141 enddef
10142 endclass
10143 var a = A.new()
10144 a.Foo()
10145 END
10146 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10147
10148 # Test for adding a value to a const List item from an object method
10149 lines =<< trim END
10150 vim9script
10151 class A
10152 public const l: list<number> = [1, 2]
10153 def Foo()
10154 this.l->add(4)
10155 enddef
10156 endclass
10157 var a = A.new()
10158 a.Foo()
10159 END
10160 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10161
10162 # Test for reassigning a const List object variable at script level
10163 lines =<< trim END
10164 vim9script
10165 class A
10166 public const l: list<number> = [1, 2]
10167 endclass
10168 var a = A.new()
10169 a.l = [3, 4]
10170 END
10171 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10172
10173 # Test for reassigning a const List object variable from an object method
10174 lines =<< trim END
10175 vim9script
10176 class A
10177 public const l: list<number> = [1, 2]
10178 def Foo()
10179 this.l = [3, 4]
10180 enddef
10181 endclass
10182 var a = A.new()
10183 a.Foo()
10184 END
10185 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10186
10187 # Test for reassigning a const List object variable from another function
10188 lines =<< trim END
10189 vim9script
10190 class A
10191 public const l: list<number> = [1, 2]
10192 endclass
10193 def Foo()
10194 var a = A.new()
10195 a.l = [3, 4]
10196 enddef
10197 Foo()
10198 END
10199 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10200
10201 # Error case: Use 'const' with just a variable name
10202 lines =<< trim END
10203 vim9script
10204 class A
10205 const foo
10206 endclass
10207 var a = A.new()
10208 END
10209 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10210
10211 # Error case: Use 'const' followed by 'public'
10212 lines =<< trim END
10213 vim9script
10214 class A
10215 const public foo: number
10216 endclass
10217 var a = A.new()
10218 END
10219 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10220
10221 # Error case: Use 'const' followed by 'static'
10222 lines =<< trim END
10223 vim9script
10224 class A
10225 const static foo: number
10226 endclass
10227 var a = A.new()
10228 END
10229 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10230
10231 # Error case: 'const' cannot be used in an interface
10232 lines =<< trim END
10233 vim9script
10234 interface A
10235 const foo: number = 10
10236 endinterface
10237 END
10238 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10239
10240 # Error case: 'const' not supported for an object method
10241 lines =<< trim END
10242 vim9script
10243 class A
10244 const def Foo()
10245 enddef
10246 endclass
10247 END
10248 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10249
10250 # Error case: 'const' not supported for a class method
10251 lines =<< trim END
10252 vim9script
10253 class A
10254 static const def Foo()
10255 enddef
10256 endclass
10257 END
10258 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10259enddef
10260
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010261" Test for compiling class/object methods using :defcompile
10262def Test_defcompile_class()
10263 # defcompile all the classes in the current script
10264 var lines =<< trim END
10265 vim9script
10266 class A
10267 def Foo()
10268 var i = 10
10269 enddef
10270 endclass
10271 class B
10272 def Bar()
10273 var i = 20
10274 xxx
10275 enddef
10276 endclass
10277 defcompile
10278 END
10279 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10280
10281 # defcompile a specific class
10282 lines =<< trim END
10283 vim9script
10284 class A
10285 def Foo()
10286 xxx
10287 enddef
10288 endclass
10289 class B
10290 def Bar()
10291 yyy
10292 enddef
10293 endclass
10294 defcompile B
10295 END
10296 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10297
10298 # defcompile a non-class
10299 lines =<< trim END
10300 vim9script
10301 class A
10302 def Foo()
10303 enddef
10304 endclass
10305 var X: list<number> = []
10306 defcompile X
10307 END
10308 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10309
10310 # defcompile a class twice
10311 lines =<< trim END
10312 vim9script
10313 class A
10314 def new()
10315 enddef
10316 endclass
10317 defcompile A
10318 defcompile A
10319 assert_equal('Function A.new does not need compiling', v:statusmsg)
10320 END
10321 v9.CheckSourceSuccess(lines)
10322
10323 # defcompile should not compile an imported class
10324 lines =<< trim END
10325 vim9script
10326 export class A
10327 def Foo()
10328 xxx
10329 enddef
10330 endclass
10331 END
10332 writefile(lines, 'Xdefcompileimport.vim', 'D')
10333 lines =<< trim END
10334 vim9script
10335
10336 import './Xdefcompileimport.vim'
10337 class B
10338 endclass
10339 defcompile
10340 END
10341 v9.CheckScriptSuccess(lines)
10342enddef
10343
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010344" Test for cases common to all the object builtin methods
10345def Test_object_builtin_method()
10346 var lines =<< trim END
10347 vim9script
10348 class A
10349 def abc()
10350 enddef
10351 endclass
10352 END
10353 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10354
10355 for funcname in ["len", "string", "empty"]
10356 lines =<< trim eval END
10357 vim9script
10358 class A
10359 static def {funcname}(): number
10360 enddef
10361 endclass
10362 END
10363 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10364 endfor
10365enddef
10366
10367" Test for using the empty() builtin method with an object
10368" This is a legacy function to use the test_garbagecollect_now() function.
10369func Test_object_empty()
10370 let lines =<< trim END
10371 vim9script
10372 class A
10373 def empty(): bool
10374 return true
10375 enddef
10376 endclass
10377
10378 def Foo()
10379 var afoo = A.new()
10380 assert_equal(true, empty(afoo))
10381 assert_equal(true, afoo->empty())
10382 enddef
10383
10384 var a = A.new()
10385 assert_equal(1, empty(a))
10386 assert_equal(1, a->empty())
10387 test_garbagecollect_now()
10388 assert_equal(1, empty(a))
10389 Foo()
10390 test_garbagecollect_now()
10391 Foo()
10392 END
10393 call v9.CheckSourceSuccess(lines)
10394
10395 " empty() should return 1 without a builtin method
10396 let lines =<< trim END
10397 vim9script
10398 class A
10399 endclass
10400
10401 def Foo()
10402 var afoo = A.new()
10403 assert_equal(1, empty(afoo))
10404 enddef
10405
10406 var a = A.new()
10407 assert_equal(1, empty(a))
10408 Foo()
10409 END
10410 call v9.CheckSourceSuccess(lines)
10411
10412 " Unsupported signature for the empty() method
10413 let lines =<< trim END
10414 vim9script
10415 class A
10416 def empty()
10417 enddef
10418 endclass
10419 END
10420 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10421
10422 " Error when calling the empty() method
10423 let lines =<< trim END
10424 vim9script
10425 class A
10426 def empty(): bool
10427 throw "Failed to check emptiness"
10428 enddef
10429 endclass
10430
10431 def Foo()
10432 var afoo = A.new()
10433 var i = empty(afoo)
10434 enddef
10435
10436 var a = A.new()
10437 assert_fails('empty(a)', 'Failed to check emptiness')
10438 assert_fails('Foo()', 'Failed to check emptiness')
10439 END
10440 call v9.CheckSourceSuccess(lines)
10441
10442 " call empty() using an object from a script
10443 let lines =<< trim END
10444 vim9script
10445 class A
10446 def empty(): bool
10447 return true
10448 enddef
10449 endclass
10450 var afoo = A.new()
10451 assert_equal(true, afoo.empty())
10452 END
10453 call v9.CheckSourceSuccess(lines)
10454
10455 " call empty() using an object from a method
10456 let lines =<< trim END
10457 vim9script
10458 class A
10459 def empty(): bool
10460 return true
10461 enddef
10462 endclass
10463 def Foo()
10464 var afoo = A.new()
10465 assert_equal(true, afoo.empty())
10466 enddef
10467 Foo()
10468 END
10469 call v9.CheckSourceSuccess(lines)
10470
10471 " call empty() using "this" from an object method
10472 let lines =<< trim END
10473 vim9script
10474 class A
10475 def empty(): bool
10476 return true
10477 enddef
10478 def Foo(): bool
10479 return this.empty()
10480 enddef
10481 endclass
10482 def Bar()
10483 var abar = A.new()
10484 assert_equal(true, abar.Foo())
10485 enddef
10486 Bar()
10487 END
10488 call v9.CheckSourceSuccess(lines)
10489
10490 " Call empty() from a derived object
10491 let lines =<< trim END
10492 vim9script
10493 class A
10494 def empty(): bool
10495 return false
10496 enddef
10497 endclass
10498 class B extends A
10499 def empty(): bool
10500 return true
10501 enddef
10502 endclass
10503 def Foo(afoo: A)
10504 assert_equal(true, empty(afoo))
10505 var bfoo = B.new()
10506 assert_equal(true, empty(bfoo))
10507 enddef
10508 var b = B.new()
10509 assert_equal(1, empty(b))
10510 Foo(b)
10511 END
10512 call v9.CheckSourceSuccess(lines)
10513
10514 " Invoking empty method using an interface
10515 let lines =<< trim END
10516 vim9script
10517 interface A
10518 def empty(): bool
10519 endinterface
10520 class B implements A
10521 def empty(): bool
10522 return false
10523 enddef
10524 endclass
10525 def Foo(a: A)
10526 assert_equal(false, empty(a))
10527 enddef
10528 var b = B.new()
10529 Foo(b)
10530 END
10531 call v9.CheckSourceSuccess(lines)
10532endfunc
10533
10534" Test for using the len() builtin method with an object
10535" This is a legacy function to use the test_garbagecollect_now() function.
10536func Test_object_length()
10537 let lines =<< trim END
10538 vim9script
10539 class A
10540 var mylen: number = 0
10541 def new(n: number)
10542 this.mylen = n
10543 enddef
10544 def len(): number
10545 return this.mylen
10546 enddef
10547 endclass
10548
10549 def Foo()
10550 var afoo = A.new(12)
10551 assert_equal(12, len(afoo))
10552 assert_equal(12, afoo->len())
10553 enddef
10554
10555 var a = A.new(22)
10556 assert_equal(22, len(a))
10557 assert_equal(22, a->len())
10558 test_garbagecollect_now()
10559 assert_equal(22, len(a))
10560 Foo()
10561 test_garbagecollect_now()
10562 Foo()
10563 END
10564 call v9.CheckSourceSuccess(lines)
10565
10566 " len() should return 0 without a builtin method
10567 let lines =<< trim END
10568 vim9script
10569 class A
10570 endclass
10571
10572 def Foo()
10573 var afoo = A.new()
10574 assert_equal(0, len(afoo))
10575 enddef
10576
10577 var a = A.new()
10578 assert_equal(0, len(a))
10579 Foo()
10580 END
10581 call v9.CheckSourceSuccess(lines)
10582
10583 " Unsupported signature for the len() method
10584 let lines =<< trim END
10585 vim9script
10586 class A
10587 def len()
10588 enddef
10589 endclass
10590 END
10591 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10592
10593 " Error when calling the len() method
10594 let lines =<< trim END
10595 vim9script
10596 class A
10597 def len(): number
10598 throw "Failed to compute length"
10599 enddef
10600 endclass
10601
10602 def Foo()
10603 var afoo = A.new()
10604 var i = len(afoo)
10605 enddef
10606
10607 var a = A.new()
10608 assert_fails('len(a)', 'Failed to compute length')
10609 assert_fails('Foo()', 'Failed to compute length')
10610 END
10611 call v9.CheckSourceSuccess(lines)
10612
10613 " call len() using an object from a script
10614 let lines =<< trim END
10615 vim9script
10616 class A
10617 def len(): number
10618 return 5
10619 enddef
10620 endclass
10621 var afoo = A.new()
10622 assert_equal(5, afoo.len())
10623 END
10624 call v9.CheckSourceSuccess(lines)
10625
10626 " call len() using an object from a method
10627 let lines =<< trim END
10628 vim9script
10629 class A
10630 def len(): number
10631 return 5
10632 enddef
10633 endclass
10634 def Foo()
10635 var afoo = A.new()
10636 assert_equal(5, afoo.len())
10637 enddef
10638 Foo()
10639 END
10640 call v9.CheckSourceSuccess(lines)
10641
10642 " call len() using "this" from an object method
10643 let lines =<< trim END
10644 vim9script
10645 class A
10646 def len(): number
10647 return 8
10648 enddef
10649 def Foo(): number
10650 return this.len()
10651 enddef
10652 endclass
10653 def Bar()
10654 var abar = A.new()
10655 assert_equal(8, abar.Foo())
10656 enddef
10657 Bar()
10658 END
10659 call v9.CheckSourceSuccess(lines)
10660
10661 " Call len() from a derived object
10662 let lines =<< trim END
10663 vim9script
10664 class A
10665 def len(): number
10666 return 10
10667 enddef
10668 endclass
10669 class B extends A
10670 def len(): number
10671 return 20
10672 enddef
10673 endclass
10674 def Foo(afoo: A)
10675 assert_equal(20, len(afoo))
10676 var bfoo = B.new()
10677 assert_equal(20, len(bfoo))
10678 enddef
10679 var b = B.new()
10680 assert_equal(20, len(b))
10681 Foo(b)
10682 END
10683 call v9.CheckSourceSuccess(lines)
10684
10685 " Invoking len method using an interface
10686 let lines =<< trim END
10687 vim9script
10688 interface A
10689 def len(): number
10690 endinterface
10691 class B implements A
10692 def len(): number
10693 return 123
10694 enddef
10695 endclass
10696 def Foo(a: A)
10697 assert_equal(123, len(a))
10698 enddef
10699 var b = B.new()
10700 Foo(b)
10701 END
10702 call v9.CheckSourceSuccess(lines)
10703endfunc
10704
10705" Test for using the string() builtin method with an object
10706" This is a legacy function to use the test_garbagecollect_now() function.
10707func Test_object_string()
10708 let lines =<< trim END
10709 vim9script
10710 class A
10711 var name: string
10712 def string(): string
10713 return this.name
10714 enddef
10715 endclass
10716
10717 def Foo()
10718 var afoo = A.new("foo-A")
10719 assert_equal('foo-A', string(afoo))
10720 assert_equal('foo-A', afoo->string())
10721 enddef
10722
10723 var a = A.new("script-A")
10724 assert_equal('script-A', string(a))
10725 assert_equal('script-A', a->string())
10726 assert_equal(['script-A'], execute('echo a')->split("\n"))
10727 test_garbagecollect_now()
10728 assert_equal('script-A', string(a))
10729 Foo()
10730 test_garbagecollect_now()
10731 Foo()
10732 END
10733 call v9.CheckSourceSuccess(lines)
10734
10735 " string() should return "object of A {}" without a builtin method
10736 let lines =<< trim END
10737 vim9script
10738 class A
10739 endclass
10740
10741 def Foo()
10742 var afoo = A.new()
10743 assert_equal('object of A {}', string(afoo))
10744 enddef
10745
10746 var a = A.new()
10747 assert_equal('object of A {}', string(a))
10748 Foo()
10749 END
10750 call v9.CheckSourceSuccess(lines)
10751
10752 " Unsupported signature for the string() method
10753 let lines =<< trim END
10754 vim9script
10755 class A
10756 def string()
10757 enddef
10758 endclass
10759 END
10760 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
10761
10762 " Error when calling the string() method
10763 let lines =<< trim END
10764 vim9script
10765 class A
10766 def string(): string
10767 throw "Failed to get text"
10768 enddef
10769 endclass
10770
10771 def Foo()
10772 var afoo = A.new()
10773 var i = string(afoo)
10774 enddef
10775
10776 var a = A.new()
10777 assert_fails('string(a)', 'Failed to get text')
10778 assert_fails('Foo()', 'Failed to get text')
10779 END
10780 call v9.CheckSourceSuccess(lines)
10781
10782 " call string() using an object from a script
10783 let lines =<< trim END
10784 vim9script
10785 class A
10786 def string(): string
10787 return 'A'
10788 enddef
10789 endclass
10790 var afoo = A.new()
10791 assert_equal('A', afoo.string())
10792 END
10793 call v9.CheckSourceSuccess(lines)
10794
10795 " call string() using an object from a method
10796 let lines =<< trim END
10797 vim9script
10798 class A
10799 def string(): string
10800 return 'A'
10801 enddef
10802 endclass
10803 def Foo()
10804 var afoo = A.new()
10805 assert_equal('A', afoo.string())
10806 enddef
10807 Foo()
10808 END
10809 call v9.CheckSourceSuccess(lines)
10810
10811 " call string() using "this" from an object method
10812 let lines =<< trim END
10813 vim9script
10814 class A
10815 def string(): string
10816 return 'A'
10817 enddef
10818 def Foo(): string
10819 return this.string()
10820 enddef
10821 endclass
10822 def Bar()
10823 var abar = A.new()
10824 assert_equal('A', abar.string())
10825 enddef
10826 Bar()
10827 END
10828 call v9.CheckSourceSuccess(lines)
10829
10830 " Call string() from a derived object
10831 let lines =<< trim END
10832 vim9script
10833 class A
10834 def string(): string
10835 return 'A'
10836 enddef
10837 endclass
10838 class B extends A
10839 def string(): string
10840 return 'B'
10841 enddef
10842 endclass
10843 def Foo(afoo: A)
10844 assert_equal('B', string(afoo))
10845 var bfoo = B.new()
10846 assert_equal('B', string(bfoo))
10847 enddef
10848 var b = B.new()
10849 assert_equal('B', string(b))
10850 Foo(b)
10851 END
10852 call v9.CheckSourceSuccess(lines)
10853
10854 " Invoking string method using an interface
10855 let lines =<< trim END
10856 vim9script
10857 interface A
10858 def string(): string
10859 endinterface
10860 class B implements A
10861 def string(): string
10862 return 'B'
10863 enddef
10864 endclass
10865 def Foo(a: A)
10866 assert_equal('B', string(a))
10867 enddef
10868 var b = B.new()
10869 Foo(b)
10870 END
10871 call v9.CheckSourceSuccess(lines)
10872endfunc
10873
Ernie Rael9d779c52024-07-07 20:41:44 +020010874" Test for using the string() builtin method with an object's method
10875def Test_method_string()
10876 var lines =<< trim END
10877 vim9script
10878 class A
10879 def F()
10880 enddef
10881 endclass
10882 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
10883 END
10884 v9.CheckScriptSuccess(lines)
10885enddef
10886
10887
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010010888" Test for using a class in the class definition
10889def Test_Ref_Class_Within_Same_Class()
10890 var lines =<< trim END
10891 vim9script
10892 class A
10893 var n: number = 0
10894 def Equals(other: A): bool
10895 return this.n == other.n
10896 enddef
10897 endclass
10898
10899 var a1 = A.new(10)
10900 var a2 = A.new(10)
10901 var a3 = A.new(20)
10902 assert_equal(true, a1.Equals(a2))
10903 assert_equal(false, a2.Equals(a3))
10904 END
10905 v9.CheckScriptSuccess(lines)
10906
10907 lines =<< trim END
10908 vim9script
10909
10910 class Foo
10911 var num: number
10912 def Clone(): Foo
10913 return Foo.new(this.num)
10914 enddef
10915 endclass
10916
10917 var f1 = Foo.new(1)
10918
10919 def F()
10920 var f2: Foo = f1.Clone()
10921 assert_equal(false, f2 is f1)
10922 assert_equal(true, f2.num == f1.num)
10923 enddef
10924 F()
10925
10926 var f3: Foo = f1.Clone()
10927 assert_equal(false, f3 is f1)
10928 assert_equal(true, f3.num == f1.num)
10929 END
10930 v9.CheckScriptSuccess(lines)
10931
10932 # Test for trying to use a class to extend when defining the same class
10933 lines =<< trim END
10934 vim9script
10935 class A extends A
10936 endclass
10937 END
10938 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
10939
10940 # Test for trying to use a class to implement when defining the same class
10941 lines =<< trim END
10942 vim9script
10943 class A implements A
10944 endclass
10945 END
10946 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
10947enddef
10948
Ernie Raelf0e69142024-06-22 11:12:00 +020010949" Test for comparing a class referencing itself
10950def Test_Object_Compare_With_Recursive_Class_Ref()
10951 var lines =<< trim END
10952 vim9script
10953
10954 class C
10955 public var nest: C
10956 endclass
10957
10958 var o1 = C.new()
10959 o1.nest = o1
10960
10961 var result = o1 == o1
10962 assert_equal(true, result)
10963 END
10964 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020010965
10966 lines =<< trim END
10967 vim9script
10968
10969 class C
10970 public var nest: C
10971 endclass
10972 var o1 = C.new()
10973 var o2 = C.new(C.new())
10974
10975 var result = o1 == o2
10976 assert_equal(false, result)
10977 END
10978 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020010979
10980 lines =<< trim END
10981 vim9script
10982 class C
10983 var nest1: C
10984 var nest2: C
10985 def Init(n1: C, n2: C)
10986 this.nest1 = n1
10987 this.nest2 = n2
10988 enddef
10989 endclass
10990
10991 var o1 = C.new()
10992 var o2 = C.new()
10993 o1.Init(o1, o2)
10994 o2.Init(o2, o1)
10995
10996 var result = o1 == o2
10997 assert_equal(true, result)
10998 END
10999 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020011000enddef
11001
Ernie Raelf3975492024-07-06 11:44:37 +020011002" Test for comparing a class with nesting objects
11003def Test_Object_Compare_With_Nesting_Objects()
11004 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
11005 # return the compare is equal.
11006 # Test that limit
11007
11008 var lines =<< trim END
11009 vim9script
11010 class C
11011 public var n: number
11012 public var nest: C
11013
11014 # Create a "C" that chains/nests to indicated depth.
11015 # return {head: firstC, tail: lastC}
11016 static def CreateNested(depth: number): dict<C>
11017 var first = C.new(1, null_object)
11018 var last = first
11019 for i in range(2, depth)
11020 last.nest = C.new(i, null_object)
11021 last = last.nest
11022 endfor
11023 return {head: first, tail: last}
11024 enddef
11025
11026 # Return pointer to nth item in chain.
11027 def GetLink(depth: number): C
11028 var count = 1
11029 var p: C = this
11030 while count < depth
11031 p = p.nest
11032 if p == null
11033 throw "too deep"
11034 endif
11035 count += 1
11036 endwhile
11037 return p
11038 enddef
11039
11040 # Return the length of the chain
11041 def len(): number
11042 var count = 1
11043 var p: C = this
11044 while p.nest != null
11045 p = p.nest
11046 count += 1
11047 endwhile
11048 return count
11049 enddef
11050 endclass
11051
11052 var chain = C.CreateNested(3)
11053 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
11054 assert_equal(s, string(chain.head))
11055 assert_equal(3, chain.head->len())
11056
11057 var chain1 = C.CreateNested(100)
11058 var chain2 = C.CreateNested(100)
11059 assert_true(chain1.head == chain2.head)
11060
11061 # modify the tail of chain2, compare not equal
11062 chain2.tail.n = 123456
11063 assert_true(chain1.head != chain2.head)
11064
11065 # a tail of a different length compares not equal
11066 chain2 = C.CreateNested(101)
11067 assert_true(chain1.head != chain2.head)
11068
11069 chain1 = C.CreateNested(1000)
11070 chain2 = C.CreateNested(1000)
11071 assert_true(chain1.head == chain2.head)
11072
11073 # modify the tail of chain2, compare not equal
11074 chain2.tail.n = 123456
11075 assert_true(chain1.head != chain2.head)
11076
11077 # try a chain longer that the limit
11078 chain1 = C.CreateNested(1001)
11079 chain2 = C.CreateNested(1001)
11080 assert_true(chain1.head == chain2.head)
11081
11082 # modify the tail, but still equal
11083 chain2.tail.n = 123456
11084 assert_true(chain1.head == chain2.head)
11085
11086 # remove 2 items from front, shorten the chain by two.
11087 chain1.head = chain1.head.GetLink(3)
11088 chain2.head = chain2.head.GetLink(3)
11089 assert_equal(3, chain1.head.n)
11090 assert_equal(3, chain2.head.n)
11091 assert_equal(999, chain1.head->len())
11092 assert_equal(999, chain2.head->len())
11093 # Now less than the limit, compare not equal
11094 assert_true(chain1.head != chain2.head)
11095 END
11096 v9.CheckScriptSuccess(lines)
11097enddef
11098
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011099" Test for using a compound operator from a lambda function in an object method
11100def Test_compound_op_in_objmethod_lambda()
11101 # Test using the "+=" operator
11102 var lines =<< trim END
11103 vim9script
11104 class A
11105 var n: number = 10
11106 def Foo()
11107 var Fn = () => {
11108 this.n += 1
11109 }
11110 Fn()
11111 enddef
11112 endclass
11113
11114 var a = A.new()
11115 a.Foo()
11116 assert_equal(11, a.n)
11117 END
11118 v9.CheckScriptSuccess(lines)
11119
11120 # Test using the "..=" operator
11121 lines =<< trim END
11122 vim9script
11123 class A
11124 var s: string = "a"
11125 def Foo()
11126 var Fn = () => {
11127 this.s ..= "a"
11128 }
11129 Fn()
11130 enddef
11131 endclass
11132
11133 var a = A.new()
11134 a.Foo()
11135 a.Foo()
11136 assert_equal("aaa", a.s)
11137 END
11138 v9.CheckScriptSuccess(lines)
11139enddef
11140
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011141" Test for using test_refcount() with a class and an object
11142def Test_class_object_refcount()
11143 var lines =<< trim END
11144 vim9script
11145 class A
11146 endclass
11147 var a: A = A.new()
11148 assert_equal(2, test_refcount(A))
11149 assert_equal(1, test_refcount(a))
11150 var b = a
11151 assert_equal(2, test_refcount(A))
11152 assert_equal(2, test_refcount(a))
11153 assert_equal(2, test_refcount(b))
11154 END
11155 v9.CheckScriptSuccess(lines)
11156enddef
11157
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011158" call a lambda function in one object from another object
11159def Test_lambda_invocation_across_classes()
11160 var lines =<< trim END
11161 vim9script
11162 class A
11163 var s: string = "foo"
11164 def GetFn(): func
11165 var Fn = (): string => {
11166 return this.s
11167 }
11168 return Fn
11169 enddef
11170 endclass
11171
11172 class B
11173 var s: string = "bar"
11174 def GetFn(): func
11175 var a = A.new()
11176 return a.GetFn()
11177 enddef
11178 endclass
11179
11180 var b = B.new()
11181 var Fn = b.GetFn()
11182 assert_equal("foo", Fn())
11183 END
11184 v9.CheckScriptSuccess(lines)
11185enddef
11186
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011187" Test for using a class member which is an object of the current class
11188def Test_current_class_object_class_member()
11189 var lines =<< trim END
11190 vim9script
11191 class A
11192 public static var obj1: A = A.new(10)
11193 var n: number
11194 endclass
11195 defcompile
11196 assert_equal(10, A.obj1.n)
11197 END
11198 v9.CheckScriptSuccess(lines)
11199enddef
11200
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011201" Test for updating a base class variable from a base class method without the
11202" class name. This used to crash Vim (Github issue #14352).
11203def Test_use_base_class_variable_from_base_class_method()
11204 var lines =<< trim END
11205 vim9script
11206
11207 class DictKeyClass
11208 static var _obj_id_count = 1
11209 def _GenerateKey()
11210 _obj_id_count += 1
11211 enddef
11212 static def GetIdCount(): number
11213 return _obj_id_count
11214 enddef
11215 endclass
11216
11217 class C extends DictKeyClass
11218 def F()
11219 this._GenerateKey()
11220 enddef
11221 endclass
11222
11223 C.new().F()
11224 assert_equal(2, DictKeyClass.GetIdCount())
11225 END
11226 v9.CheckScriptSuccess(lines)
11227enddef
11228
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011229" Test for accessing protected funcref object and class variables
11230def Test_protected_funcref()
11231 # protected funcref object variable
11232 var lines =<< trim END
11233 vim9script
11234 class Test1
11235 const _Id: func(any): any = (v) => v
11236 endclass
11237 var n = Test1.new()._Id(1)
11238 END
11239 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11240
11241 # protected funcref class variable
11242 lines =<< trim END
11243 vim9script
11244 class Test2
11245 static const _Id: func(any): any = (v) => v
11246 endclass
11247 var n = Test2._Id(2)
11248 END
11249 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11250enddef
11251
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011252" Test for using lambda block in classes
11253def Test_lambda_block_in_class()
11254 # This used to crash Vim
11255 var lines =<< trim END
11256 vim9script
11257 class IdClass1
11258 const Id: func(number): number = (num: number): number => {
11259 # Return a ID
11260 return num * 10
11261 }
11262 endclass
11263 var id = IdClass1.new()
11264 assert_equal(20, id.Id(2))
11265 END
11266 v9.CheckScriptSuccess(lines)
11267
11268 # This used to crash Vim
11269 lines =<< trim END
11270 vim9script
11271 class IdClass2
11272 static const Id: func(number): number = (num: number): number => {
11273 # Return a ID
11274 return num * 2
11275 }
11276 endclass
11277 assert_equal(16, IdClass2.Id(8))
11278 END
11279 v9.CheckScriptSuccess(lines)
11280enddef
11281
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011282" Test for defcompiling an abstract method
11283def Test_abstract_method_defcompile()
11284 # Compile an abstract class with abstract object methods
11285 var lines =<< trim END
11286 vim9script
11287 abstract class A
11288 abstract def Foo(): string
11289 abstract def Bar(): list<string>
11290 endclass
11291 defcompile
11292 END
11293 v9.CheckScriptSuccess(lines)
11294
11295 # Compile a concrete object method in an abstract class
11296 lines =<< trim END
11297 vim9script
11298 abstract class A
11299 abstract def Foo(): string
11300 abstract def Bar(): list<string>
11301 def Baz(): string
11302 pass
11303 enddef
11304 endclass
11305 defcompile
11306 END
11307 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11308
11309 # Compile a concrete class method in an abstract class
11310 lines =<< trim END
11311 vim9script
11312 abstract class A
11313 abstract def Foo(): string
11314 abstract def Bar(): list<string>
11315 static def Baz(): string
11316 pass
11317 enddef
11318 endclass
11319 defcompile
11320 END
11321 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11322enddef
11323
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011324" Test for defining a class in a function
11325def Test_class_definition_in_a_function()
11326 var lines =<< trim END
11327 vim9script
11328 def Foo()
11329 class A
11330 endclass
11331 enddef
11332 defcompile
11333 END
11334 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11335enddef
11336
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011337" Test for using [] with a class and an object
11338def Test_class_object_index()
11339 var lines =<< trim END
11340 vim9script
11341 class A
11342 endclass
11343 A[10] = 1
11344 END
11345 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11346
11347 lines =<< trim END
11348 vim9script
11349 class A
11350 endclass
11351 var a = A.new()
11352 a[10] = 1
11353 END
11354 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11355enddef
11356
LemonBoyf4af3312024-07-04 13:43:12 +020011357def Test_class_member_init_typecheck()
11358 # Ensure the class member is assigned its declared type.
11359 var lines =<< trim END
11360 vim9script
11361 class S
11362 static var l: list<string> = []
11363 endclass
11364 S.l->add(123)
11365 END
11366 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11367
11368 # Ensure the initializer value and the declared type match.
11369 lines =<< trim END
11370 vim9script
11371 class S
11372 var l: list<string> = [1, 2, 3]
11373 endclass
11374 var o = S.new()
11375 END
11376 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11377
11378 # Ensure the class member is assigned its declared type.
11379 lines =<< trim END
11380 vim9script
11381 class S
11382 var l: list<string> = []
11383 endclass
11384 var o = S.new()
11385 o.l->add(123)
11386 END
11387 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11388enddef
11389
LemonBoy50d48542024-07-04 17:03:17 +020011390def Test_class_cast()
11391 var lines =<< trim END
11392 vim9script
11393 class A
11394 endclass
11395 class B extends A
11396 var mylen: number
11397 endclass
11398 def F(o: A): number
11399 return (<B>o).mylen
11400 enddef
11401
11402 defcompile F
11403 END
11404 v9.CheckScriptSuccess(lines)
11405enddef
11406
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011407" Test for using a variable of type "any" with an object
11408def Test_any_obj_var_type()
11409 var lines =<< trim END
11410 vim9script
11411 class A
11412 var name: string = "foobar"
11413 def Foo(): string
11414 return "func foo"
11415 enddef
11416 endclass
11417
11418 def CheckVals(x: any)
11419 assert_equal("foobar", x.name)
11420 assert_equal("func foo", x.Foo())
11421 enddef
11422
11423 var a = A.new()
11424 CheckVals(a)
11425 END
11426 v9.CheckScriptSuccess(lines)
11427
11428 # Try to set a non-existing variable
11429 lines =<< trim END
11430 vim9script
11431 class A
11432 var name: string = "foobar"
11433 endclass
11434
11435 def SetNonExistingVar(x: any)
11436 x.bar = [1, 2, 3]
11437 enddef
11438
11439 var a = A.new()
11440 SetNonExistingVar(a)
11441 END
11442 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11443
11444 # Try to read a non-existing variable
11445 lines =<< trim END
11446 vim9script
11447 class A
11448 var name: string = "foobar"
11449 endclass
11450
11451 def GetNonExistingVar(x: any)
11452 var i: dict<any> = x.bar
11453 enddef
11454
11455 var a = A.new()
11456 GetNonExistingVar(a)
11457 END
11458 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11459
11460 # Try to invoke a non-existing method
11461 lines =<< trim END
11462 vim9script
11463 class A
11464 def Foo(): number
11465 return 10
11466 enddef
11467 endclass
11468
11469 def CallNonExistingMethod(x: any)
11470 var i: number = x.Bar()
11471 enddef
11472
11473 var a = A.new()
11474 CallNonExistingMethod(a)
11475 END
11476 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11477
11478 # Use an object which is a Dict value
11479 lines =<< trim END
11480 vim9script
11481 class Foo
11482 def Bar(): number
11483 return 369
11484 enddef
11485 endclass
11486
11487 def GetValue(FooDict: dict<any>): number
11488 var n: number = 0
11489 for foo in values(FooDict)
11490 n += foo.Bar()
11491 endfor
11492 return n
11493 enddef
11494
11495 var d = {'x': Foo.new()}
11496 assert_equal(369, GetValue(d))
11497 END
11498 v9.CheckScriptSuccess(lines)
11499
zeertzjqd32bf0a2024-12-17 20:55:13 +010011500 # Nested data. Object containing a Dict containing another Object.
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011501 lines =<< trim END
11502 vim9script
11503 class Context
11504 public var state: dict<any> = {}
11505 endclass
11506
11507 class Metadata
11508 public var value = 0
11509 endclass
11510
11511 var ctx = Context.new()
11512 ctx.state["meta"] = Metadata.new(2468)
11513
11514 const foo = ctx.state.meta.value
11515
11516 def F(): number
11517 const bar = ctx.state.meta.value
11518 return bar
11519 enddef
11520
11521 assert_equal(2468, F())
11522 END
11523 v9.CheckScriptSuccess(lines)
11524
11525 # Accessing an object from a method inside the class using any type
11526 lines =<< trim END
11527 vim9script
11528 class C
11529 def _G(): string
11530 return '_G'
11531 enddef
11532 static def S(o_any: any): string
11533 return o_any._G()
11534 enddef
11535 endclass
11536
11537 var o1 = C.new()
11538 assert_equal('_G', C.S(o1))
11539 END
11540 v9.CheckScriptSuccess(lines)
11541
11542 # Modifying an object private variable from a method in another class using
11543 # any type
11544 lines =<< trim END
11545 vim9script
11546
11547 class A
11548 var num = 10
11549 endclass
11550
11551 class B
11552 def SetVal(x: any)
11553 x.num = 20
11554 enddef
11555 endclass
11556
11557 var a = A.new()
11558 var b = B.new()
11559 b.SetVal(a)
11560 END
11561 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11562
11563 # Accessing a object protected variable from a method in another class using
11564 # any type
11565 lines =<< trim END
11566 vim9script
11567
11568 class A
11569 var _num = 10
11570 endclass
11571
11572 class B
11573 def GetVal(x: any): number
11574 return x._num
11575 enddef
11576 endclass
11577
11578 var a = A.new()
11579 var b = B.new()
11580 var i = b.GetVal(a)
11581 END
11582 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11583
11584 # Accessing an object returned from an imported function and class
11585 lines =<< trim END
11586 vim9script
11587 export class Foo
11588 public var name: string
11589 endclass
11590
11591 export def ReturnFooObject(): Foo
11592 var r = Foo.new('star')
11593 return r
11594 enddef
11595 END
11596 writefile(lines, 'Xanyvar1.vim', 'D')
11597
11598 lines =<< trim END
11599 vim9script
11600
11601 import './Xanyvar1.vim'
11602
11603 def GetName(): string
11604 var whatever = Xanyvar1.ReturnFooObject()
11605 return whatever.name
11606 enddef
11607
11608 assert_equal('star', GetName())
11609 END
11610 v9.CheckScriptSuccess(lines)
11611
11612 # Try to modify a private object variable using a variable of type "any"
11613 lines =<< trim END
11614 vim9script
11615
11616 class Foo
11617 var n: number = 10
11618 endclass
11619 def Fn(x: any)
11620 x.n = 20
11621 enddef
11622 var a = Foo.new()
11623 Fn(a)
11624 END
11625 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11626
11627 # Try to read a protected object variable using a variable of type "any"
11628 lines =<< trim END
11629 vim9script
11630
11631 class Foo
11632 var _n: number = 10
11633 endclass
11634 def Fn(x: any): number
11635 return x._n
11636 enddef
11637
11638 var a = Foo.new()
11639 Fn(a)
11640 END
11641 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11642
11643 # Read a protected object variable using a variable of type "any" in an object
11644 # method
11645 lines =<< trim END
11646 vim9script
11647
11648 class Foo
11649 var _n: number = 10
11650 def Fn(x: any): number
11651 return x._n
11652 enddef
11653 endclass
11654
11655 var a = Foo.new()
11656 assert_equal(10, a.Fn(a))
11657 END
11658 v9.CheckScriptSuccess(lines)
11659
11660 # Try to call a protected object method using a "any" type variable
11661 lines =<< trim END
11662 vim9script
11663
11664 class Foo
11665 def _GetVal(): number
11666 return 234
11667 enddef
11668 endclass
11669 def Fn(x: any): number
11670 return x._GetVal()
11671 enddef
11672
11673 var a = Foo.new()
11674 Fn(a)
11675 END
11676 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11677
11678 # Call a protected object method using a "any" type variable from another
11679 # object method
11680 lines =<< trim END
11681 vim9script
11682
11683 class Foo
11684 def _GetVal(): number
11685 return 234
11686 enddef
11687 def FooVal(x: any): number
11688 return x._GetVal()
11689 enddef
11690 endclass
11691
11692 var a = Foo.new()
11693 assert_equal(234, a.FooVal(a))
11694 END
11695 v9.CheckScriptSuccess(lines)
11696
11697 # Method chaining
11698 lines =<< trim END
11699 vim9script
11700
11701 export class T
11702 var id: number = 268
11703 def F(): any
11704 return this
11705 enddef
11706 endclass
11707
11708 def H()
11709 var a = T.new().F().F()
11710 assert_equal(268, a.id)
11711 enddef
11712 H()
11713
11714 var b: T = T.new().F().F()
11715 assert_equal(268, b.id)
11716 END
11717 v9.CheckScriptSuccess(lines)
11718
11719 # Using a null object to access a member variable
11720 lines =<< trim END
11721 vim9script
11722 def Fn(x: any): number
11723 return x.num
11724 enddef
11725
11726 Fn(null_object)
11727 END
11728 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11729
11730 # Using a null object to invoke a method
11731 lines =<< trim END
11732 vim9script
11733 def Fn(x: any)
11734 x.Foo()
11735 enddef
11736
11737 Fn(null_object)
11738 END
11739 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
Yegappan Lakshmanane7984462024-11-12 21:03:00 +010011740
11741 # Try to change a const object variable using a "any" variable
11742 lines =<< trim END
11743 vim9script
11744 class A
11745 public const v1: number = 123
11746 endclass
11747
11748 def Fn(o: any)
11749 o.v1 = 321
11750 enddef
11751
11752 var a = A.new()
11753 Fn(a)
11754 END
11755 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11756
11757 # Try to change a final object variable using a "any" variable
11758 lines =<< trim END
11759 vim9script
11760 class A
11761 public final v1: number = 123
11762 endclass
11763
11764 def Fn(o: any)
11765 o.v1 = 321
11766 enddef
11767
11768 var a = A.new()
11769 Fn(a)
11770 END
11771 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11772
11773 # Assign a different type of value to an "any" type object variable
11774 lines =<< trim END
11775 vim9script
11776 class A
11777 public var v1: list<any> = [1, 2]
11778 endclass
11779
11780 def Fn(o: A)
11781 o.v1 = 'abc'
11782 enddef
11783
11784 var a = A.new()
11785 Fn(a)
11786 END
11787 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 1)
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011788enddef
11789
Yegappan Lakshmanan481992c2024-12-06 18:35:12 +010011790" Test for using an object method with mapnew()
11791def Test_mapnew_with_instance_method()
11792 var lines =<< trim END
11793 vim9script
11794
11795 class Foo
11796 var str: string
11797 var nums: list<number> = [1, 2, 3]
11798
11799 def InstanceMethod(n: number): string
11800 return this.str .. n
11801 enddef
11802
11803 def MapperMethod(idx: number, elem: number): string
11804 return elem->this.InstanceMethod()
11805 enddef
11806
11807 def MapTest()
11808 this.str = "foo"
11809 var l = ['foo1', 'foo2', 'foo3']
11810 assert_equal(l, this.nums->mapnew(this.MapperMethod))
11811 enddef
11812 endclass
11813
11814 Foo.new().MapTest()
11815 END
11816 v9.CheckSourceSuccess(lines)
11817
11818 # Error in the mapnew() function
11819 lines =<< trim END
11820 vim9script
11821
11822 class Foo
11823 var str: string
11824 var nums: list<number> = [1, 2, 3]
11825
11826 def InstanceMethod(n: number): string
11827 throw "InstanceMethod failed"
11828 enddef
11829
11830 def MapperMethod(idx: number, elem: number): string
11831 return elem->this.InstanceMethod()
11832 enddef
11833
11834 def MapTest()
11835 this.str = "foo"
11836 var caught_exception: bool = false
11837 try
11838 this.nums->mapnew(this.MapperMethod)
11839 catch /InstanceMethod failed/
11840 caught_exception = true
11841 endtry
11842 assert_true(caught_exception)
11843 enddef
11844 endclass
11845
11846 Foo.new().MapTest()
11847 END
11848 v9.CheckSourceSuccess(lines)
11849enddef
11850
Yegappan Lakshmananb0206e92024-12-30 09:52:16 +010011851" Test for using an object method in a method call.
11852def Test_use_object_method_in_a_method_call()
11853 var lines =<< trim END
11854 vim9script
11855
11856 class Foo
11857 def Cost(nums: list<number>): number
11858 return nums[0] * nums[1]
11859 enddef
11860
11861 def ShowCost(): string
11862 var g = [4, 5]
11863 return $"Cost is: {g->this.Cost()}"
11864 enddef
11865 endclass
11866
11867 var d = Foo.new()
11868 assert_equal('Cost is: 20', d.ShowCost())
11869 END
11870 v9.CheckSourceSuccess(lines)
11871
11872 # Test for using a non-existing object method in string interpolation
11873 lines =<< trim END
11874 vim9script
11875
11876 class Foo
11877 def Cost(nums: list<number>): number
11878 return nums[0] * nums[1]
11879 enddef
11880
11881 def ShowCost(): string
11882 var g = [4, 5]
11883 echo $"Cost is: {g->this.NewCost()}"
11884 enddef
11885 endclass
11886
11887 var d = Foo.new()
11888 d.ShowCost()
11889 END
11890 v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
11891enddef
11892
Yegappan Lakshmananb04af4c2025-01-03 10:50:08 +010011893" Test for referencing an object variable which is not yet initialized
11894def Test_uninitialized_object_var()
11895 var lines =<< trim END
11896 vim9script
11897 class Foo
11898 const two: number = Foo.Two(this)
11899 const one: number = 1
11900
11901 static def Two(that: Foo): number
11902 return that.one + 2
11903 enddef
11904 endclass
11905
11906 echo Foo.Two(Foo.new())
11907 END
11908 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
11909
11910 lines =<< trim END
11911 vim9script
11912 class Foo
11913 const one: number = Foo.One(this)
11914
11915 static def One(that: Foo): number
11916 return 1
11917 enddef
11918 endclass
11919
11920 assert_equal(1, Foo.One(Foo.new()))
11921 END
11922 v9.CheckSourceSuccess(lines)
11923
11924 lines =<< trim END
11925 vim9script
11926 class Foo
11927 const one: number = 1
11928 const two: number = Foo.Two(this)
11929
11930 static def Two(that: Foo): number
11931 return that.one + 1
11932 enddef
11933 endclass
11934
11935 assert_equal(2, Foo.Two(Foo.new()))
11936 END
11937 v9.CheckSourceSuccess(lines)
11938
11939 lines =<< trim END
11940 vim9script
11941 class Foo
11942 const Id: func(any): any = ((_) => (v) => v)(this)
11943
11944 static def Id(that: Foo): func(any): any
11945 return that.Id
11946 enddef
11947 endclass
11948
11949 assert_equal(5, Foo.Id(Foo.new())(5))
11950 assert_equal(7, Foo.new().Id(7))
11951 END
11952 v9.CheckSourceSuccess(lines)
11953
11954 lines =<< trim END
11955 vim9script
11956 class Foo
11957 const Id: func(any): any = ((that) => (_) => that)(this)
11958
11959 static def Id(that: Foo): func(any): any
11960 return that.Id
11961 enddef
11962 endclass
11963
11964 const Id0: func(any): any = Foo.Id(Foo.new())
11965 const Id1: func(any): any = Foo.new().Id
11966 END
11967 v9.CheckSourceSuccess(lines)
11968
11969 lines =<< trim END
11970 vim9script
11971 class Foo
11972 const Id: any = Foo.Id(this)
11973
11974 static def Id(that: Foo): any
11975 return that.Id
11976 enddef
11977 endclass
11978
11979 const Id2: any = Foo.Id(Foo.new())
11980 const Id3: any = Foo.new().Id
11981 END
11982 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
11983
11984 lines =<< trim END
11985 vim9script
11986
11987 class Foo
11988 var x: string = ''
11989 var Y: func(): string = () => this.x
11990 endclass
11991
11992 var foo = Foo.new('ok')
11993 assert_equal('ok', foo.Y())
11994 END
11995 v9.CheckSourceSuccess(lines)
11996
11997 lines =<< trim END
11998 vim9script
11999
12000 class Foo
12001 var x: string = this.x
12002 endclass
12003
12004 var foo = Foo.new('ok')
12005 END
12006 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
12007enddef
12008
Yegappan Lakshmanan2050dcc2025-01-06 18:34:49 +010012009" Test for initializing member variables of compound type in the constructor
12010def Test_constructor_init_compound_member_var()
12011 var lines =<< trim END
12012 vim9script
12013
12014 class Foo
12015 var v1: string = "aaa"
12016 var v2: list<number> = [1, 2]
12017 var v3: dict<string> = {a: 'a', b: 'b'}
12018 endclass
12019
12020 class Bar
12021 var v4: string = "bbb"
12022 var v5: Foo = Foo.new()
12023 var v6: list<number> = [1, 2]
12024 endclass
12025
12026 var b: Bar = Bar.new()
12027 assert_equal("aaa", b.v5.v1)
12028 assert_equal([1, 2], b.v5.v2)
12029 assert_equal({a: 'a', b: 'b'}, b.v5.v3)
12030 assert_equal("bbb", b.v4)
12031 assert_equal([1, 2], b.v6)
12032 END
12033 v9.CheckSourceSuccess(lines)
12034enddef
12035
Bram Moolenaar00b28d62022-12-08 15:32:33 +000012036" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker