blob: c20de25337dc26065518417576224a6decab2a0f [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.
6099" FIXME: This test fails.
6100" def Test_interface_overridden_method_from_child()
6101" var lines =<< trim END
6102" vim9script
6103"
6104" interface A
6105" def Foo(): string
6106" endinterface
6107"
6108" class B implements A
6109" def Foo(): string
6110" return 'b-foo'
6111" enddef
6112" endclass
6113"
6114" class C extends B
6115" def Bar(): string
6116" return 'bar'
6117" enddef
6118" def Foo(): string
6119" return 'c-foo'
6120" enddef
6121" endclass
6122"
6123" def T1(a: A)
6124" assert_equal('c-foo', a.Foo())
6125" enddef
6126"
6127" def T2(b: B)
6128" assert_equal('c-foo', b.Foo())
6129" enddef
6130"
6131" var c = C.new()
6132" T1(c)
6133" T2(c)
6134" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006135" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006136" enddef
6137
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006138" Test for abstract methods
6139def Test_abstract_method()
6140 # Use two abstract methods
6141 var lines =<< trim END
6142 vim9script
6143 abstract class A
6144 def M1(): number
6145 return 10
6146 enddef
6147 abstract def M2(): number
6148 abstract def M3(): number
6149 endclass
6150 class B extends A
6151 def M2(): number
6152 return 20
6153 enddef
6154 def M3(): number
6155 return 30
6156 enddef
6157 endclass
6158 var b = B.new()
6159 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6160 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006161 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006162
6163 # Don't define an abstract method
6164 lines =<< trim END
6165 vim9script
6166 abstract class A
6167 abstract def Foo()
6168 endclass
6169 class B extends A
6170 endclass
6171 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006172 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006173
6174 # Use abstract method in a concrete class
6175 lines =<< trim END
6176 vim9script
6177 class A
6178 abstract def Foo()
6179 endclass
6180 class B extends A
6181 endclass
6182 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006183 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006184
6185 # Use abstract method in an interface
6186 lines =<< trim END
6187 vim9script
6188 interface A
6189 abstract def Foo()
6190 endinterface
6191 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006192 def Foo()
6193 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006194 endclass
6195 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006196 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6197
6198 # Use abstract static method in an interface
6199 lines =<< trim END
6200 vim9script
6201 interface A
6202 abstract static def Foo()
6203 enddef
6204 endinterface
6205 END
6206 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6207
6208 # Use abstract static variable in an interface
6209 lines =<< trim END
6210 vim9script
6211 interface A
6212 abstract static foo: number = 10
6213 endinterface
6214 END
6215 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006216
6217 # Abbreviate the "abstract" keyword
6218 lines =<< trim END
6219 vim9script
6220 class A
6221 abs def Foo()
6222 endclass
6223 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006224 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006225
6226 # Use "abstract" with a member variable
6227 lines =<< trim END
6228 vim9script
6229 abstract class A
6230 abstract this.val = 10
6231 endclass
6232 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006233 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006234
6235 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006236 lines =<< trim END
6237 vim9script
6238 abstract class A
6239 abstract static def Foo(): number
6240 endclass
6241 END
6242 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006243
6244 # Type mismatch between abstract method and concrete method
6245 lines =<< trim END
6246 vim9script
6247 abstract class A
6248 abstract def Foo(a: string, b: number): list<number>
6249 endclass
6250 class B extends A
6251 def Foo(a: number, b: string): list<string>
6252 return []
6253 enddef
6254 endclass
6255 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006256 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 +02006257
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006258 # Invoke an abstract method from a def function
6259 lines =<< trim END
6260 vim9script
6261 abstract class A
6262 abstract def Foo(): list<number>
6263 endclass
6264 class B extends A
6265 def Foo(): list<number>
6266 return [3, 5]
6267 enddef
6268 endclass
6269 def Bar(c: B)
6270 assert_equal([3, 5], c.Foo())
6271 enddef
6272 var b = B.new()
6273 Bar(b)
6274 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006275 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006276
6277 # Use a static method in an abstract class
6278 lines =<< trim END
6279 vim9script
6280 abstract class A
6281 static def Foo(): string
6282 return 'foo'
6283 enddef
6284 endclass
6285 assert_equal('foo', A.Foo())
6286 END
6287 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006288enddef
6289
6290" Test for calling a class method from a subclass
6291def Test_class_method_call_from_subclass()
6292 # class method call from a subclass
6293 var lines =<< trim END
6294 vim9script
6295
6296 class A
6297 static def Foo()
6298 echo "foo"
6299 enddef
6300 endclass
6301
6302 class B extends A
6303 def Bar()
6304 Foo()
6305 enddef
6306 endclass
6307
6308 var b = B.new()
6309 b.Bar()
6310 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006311 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006312enddef
6313
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006314" Test for calling a class method using an object in a def function context and
6315" script context.
6316def Test_class_method_call_using_object()
6317 # script context
6318 var lines =<< trim END
6319 vim9script
6320 class A
6321 static def Foo(): list<string>
6322 return ['a', 'b']
6323 enddef
6324 def Bar()
6325 assert_equal(['a', 'b'], A.Foo())
6326 assert_equal(['a', 'b'], Foo())
6327 enddef
6328 endclass
6329
6330 def T()
6331 assert_equal(['a', 'b'], A.Foo())
6332 var t_a = A.new()
6333 t_a.Bar()
6334 enddef
6335
6336 assert_equal(['a', 'b'], A.Foo())
6337 var a = A.new()
6338 a.Bar()
6339 T()
6340 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006341 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006342
6343 # script context
6344 lines =<< trim END
6345 vim9script
6346 class A
6347 static def Foo(): string
6348 return 'foo'
6349 enddef
6350 endclass
6351
6352 var a = A.new()
6353 assert_equal('foo', a.Foo())
6354 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006355 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006356
6357 # def function context
6358 lines =<< trim END
6359 vim9script
6360 class A
6361 static def Foo(): string
6362 return 'foo'
6363 enddef
6364 endclass
6365
6366 def T()
6367 var a = A.new()
6368 assert_equal('foo', a.Foo())
6369 enddef
6370 T()
6371 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006372 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006373enddef
6374
6375def Test_class_variable()
6376 var lines =<< trim END
6377 vim9script
6378
6379 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006380 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006381 static def ClassFunc()
6382 assert_equal(10, val)
6383 enddef
6384 def ObjFunc()
6385 assert_equal(10, val)
6386 enddef
6387 endclass
6388
6389 class B extends A
6390 endclass
6391
6392 assert_equal(10, A.val)
6393 A.ClassFunc()
6394 var a = A.new()
6395 a.ObjFunc()
6396 var b = B.new()
6397 b.ObjFunc()
6398
6399 def T1(a1: A)
6400 a1.ObjFunc()
6401 A.ClassFunc()
6402 enddef
6403 T1(b)
6404
6405 A.val = 20
6406 assert_equal(20, A.val)
6407 END
6408 v9.CheckSourceSuccess(lines)
6409
6410 # Modifying a parent class variable from a child class method
6411 lines =<< trim END
6412 vim9script
6413
6414 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006415 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006416 endclass
6417
6418 class B extends A
6419 static def ClassFunc()
6420 val = 20
6421 enddef
6422 endclass
6423 B.ClassFunc()
6424 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006425 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006426
6427 # Reading a parent class variable from a child class method
6428 lines =<< trim END
6429 vim9script
6430
6431 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006432 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006433 endclass
6434
6435 class B extends A
6436 static def ClassFunc()
6437 var i = val
6438 enddef
6439 endclass
6440 B.ClassFunc()
6441 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006442 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006443
6444 # Modifying a parent class variable from a child object method
6445 lines =<< trim END
6446 vim9script
6447
6448 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006449 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006450 endclass
6451
6452 class B extends A
6453 def ObjFunc()
6454 val = 20
6455 enddef
6456 endclass
6457 var b = B.new()
6458 b.ObjFunc()
6459 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006460 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006461
6462 # Reading a parent class variable from a child object method
6463 lines =<< trim END
6464 vim9script
6465
6466 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006467 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006468 endclass
6469
6470 class B extends A
6471 def ObjFunc()
6472 var i = val
6473 enddef
6474 endclass
6475 var b = B.new()
6476 b.ObjFunc()
6477 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006478 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006479
6480 # Modifying a class variable using an object at script level
6481 lines =<< trim END
6482 vim9script
6483
6484 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006485 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006486 endclass
6487 var a = A.new()
6488 a.val = 20
6489 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006490 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006491
6492 # Reading a class variable using an object at script level
6493 lines =<< trim END
6494 vim9script
6495
6496 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006497 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006498 endclass
6499 var a = A.new()
6500 var i = a.val
6501 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006502 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006503
6504 # Modifying a class variable using an object at function level
6505 lines =<< trim END
6506 vim9script
6507
6508 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006509 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006510 endclass
6511
6512 def T()
6513 var a = A.new()
6514 a.val = 20
6515 enddef
6516 T()
6517 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006518 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006519
6520 # Reading a class variable using an object at function level
6521 lines =<< trim END
6522 vim9script
6523
6524 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006525 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006526 endclass
6527 def T()
6528 var a = A.new()
6529 var i = a.val
6530 enddef
6531 T()
6532 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006533 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006534
6535 # Use old implicit var declaration syntax (without initialization)
6536 lines =<< trim END
6537 vim9script
6538
6539 class A
6540 static val: number
6541 endclass
6542 END
6543 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6544
6545 # Use old implicit var declaration syntax (with initialization)
6546 lines =<< trim END
6547 vim9script
6548
6549 class A
6550 static val: number = 10
6551 endclass
6552 END
6553 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6554
6555 # Use old implicit var declaration syntax (type inferred)
6556 lines =<< trim END
6557 vim9script
6558
6559 class A
6560 static val = 10
6561 endclass
6562 END
6563 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6564
6565 # Missing ":var" in "var" class variable declaration (without initialization)
6566 lines =<< trim END
6567 vim9script
6568
6569 class A
6570 static var: number
6571 endclass
6572 END
6573 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6574
6575 # Missing ":var" in "var" class variable declaration (with initialization)
6576 lines =<< trim END
6577 vim9script
6578
6579 class A
6580 static var: number = 10
6581 endclass
6582 END
6583 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6584
6585 # Missing ":var" in "var" class variable declaration (type inferred)
6586 lines =<< trim END
6587 vim9script
6588
6589 class A
6590 static var = 10
6591 endclass
6592 END
6593 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6594
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006595enddef
6596
6597" Test for using a duplicate class method and class variable in a child class
6598def Test_dup_class_member()
6599 # duplicate class variable, class method and overridden object method
6600 var lines =<< trim END
6601 vim9script
6602 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006603 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006604 static def Check()
6605 assert_equal(100, sval)
6606 enddef
6607 def GetVal(): number
6608 return sval
6609 enddef
6610 endclass
6611
6612 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006613 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006614 static def Check()
6615 assert_equal(200, sval)
6616 enddef
6617 def GetVal(): number
6618 return sval
6619 enddef
6620 endclass
6621
6622 def T1(aa: A): number
6623 return aa.GetVal()
6624 enddef
6625
6626 def T2(bb: B): number
6627 return bb.GetVal()
6628 enddef
6629
6630 assert_equal(100, A.sval)
6631 assert_equal(200, B.sval)
6632 var a = A.new()
6633 assert_equal(100, a.GetVal())
6634 var b = B.new()
6635 assert_equal(200, b.GetVal())
6636 assert_equal(200, T1(b))
6637 assert_equal(200, T2(b))
6638 END
6639 v9.CheckSourceSuccess(lines)
6640
6641 # duplicate class variable and class method
6642 lines =<< trim END
6643 vim9script
6644 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006645 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006646 static def Check()
6647 assert_equal(100, sval)
6648 enddef
6649 def GetVal(): number
6650 return sval
6651 enddef
6652 endclass
6653
6654 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006655 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006656 static def Check()
6657 assert_equal(200, sval)
6658 enddef
6659 endclass
6660
6661 def T1(aa: A): number
6662 return aa.GetVal()
6663 enddef
6664
6665 def T2(bb: B): number
6666 return bb.GetVal()
6667 enddef
6668
6669 assert_equal(100, A.sval)
6670 assert_equal(200, B.sval)
6671 var a = A.new()
6672 assert_equal(100, a.GetVal())
6673 var b = B.new()
6674 assert_equal(100, b.GetVal())
6675 assert_equal(100, T1(b))
6676 assert_equal(100, T2(b))
6677 END
6678 v9.CheckSourceSuccess(lines)
6679enddef
6680
6681" Test for calling an instance method using the class
6682def Test_instance_method_call_using_class()
6683 # Invoke an object method using a class in script context
6684 var lines =<< trim END
6685 vim9script
6686 class A
6687 def Foo()
6688 echo "foo"
6689 enddef
6690 endclass
6691 A.Foo()
6692 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006693 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006694
6695 # Invoke an object method using a class in def function context
6696 lines =<< trim END
6697 vim9script
6698 class A
6699 def Foo()
6700 echo "foo"
6701 enddef
6702 endclass
6703 def T()
6704 A.Foo()
6705 enddef
6706 T()
6707 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006708 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006709enddef
6710
6711" Test for duplicate class method and instance method
6712def Test_dup_classmethod_objmethod()
6713 # Duplicate instance method
6714 var lines =<< trim END
6715 vim9script
6716 class A
6717 static def Foo()
6718 enddef
6719 def Foo()
6720 enddef
6721 endclass
6722 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006723 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006724
Ernie Rael03042a22023-11-11 08:53:32 +01006725 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006726 lines =<< trim END
6727 vim9script
6728 class A
6729 static def Foo()
6730 enddef
6731 def _Foo()
6732 enddef
6733 endclass
6734 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006735 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006736
6737 # Duplicate class method
6738 lines =<< trim END
6739 vim9script
6740 class A
6741 def Foo()
6742 enddef
6743 static def Foo()
6744 enddef
6745 endclass
6746 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006747 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006748
Ernie Rael03042a22023-11-11 08:53:32 +01006749 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006750 lines =<< trim END
6751 vim9script
6752 class A
6753 def Foo()
6754 enddef
6755 static def _Foo()
6756 enddef
6757 endclass
6758 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006759 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006760
Ernie Rael03042a22023-11-11 08:53:32 +01006761 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006762 lines =<< trim END
6763 vim9script
6764 class A
6765 def _Foo()
6766 enddef
6767 static def _Foo()
6768 enddef
6769 endclass
6770 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006771 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006772enddef
6773
6774" Test for an instance method access level comparison with parent instance
6775" methods.
6776def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01006777 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006778 var lines =<< trim END
6779 vim9script
6780 class A
6781 def Foo()
6782 enddef
6783 endclass
6784 class B extends A
6785 endclass
6786 class C extends B
6787 def _Foo()
6788 enddef
6789 endclass
6790 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006791 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006792
6793 # Public method in subclass
6794 lines =<< trim END
6795 vim9script
6796 class A
6797 def _Foo()
6798 enddef
6799 endclass
6800 class B extends A
6801 endclass
6802 class C extends B
6803 def Foo()
6804 enddef
6805 endclass
6806 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006807 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006808enddef
6809
6810def Test_extend_empty_class()
6811 var lines =<< trim END
6812 vim9script
6813 class A
6814 endclass
6815 class B extends A
6816 endclass
6817 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006818 public static var rw_class_var = 1
6819 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006820 static def ClassMethod(): number
6821 return 3
6822 enddef
6823 def ObjMethod(): number
6824 return 4
6825 enddef
6826 endclass
6827 assert_equal(1, C.rw_class_var)
6828 assert_equal(3, C.ClassMethod())
6829 var c = C.new()
6830 assert_equal(2, c.rw_obj_var)
6831 assert_equal(4, c.ObjMethod())
6832 END
6833 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006834enddef
6835
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006836" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01006837" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006838def Test_interface_with_unsupported_members()
6839 var lines =<< trim END
6840 vim9script
6841 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006842 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006843 endinterface
6844 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006845 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006846
6847 lines =<< trim END
6848 vim9script
6849 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006850 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006851 endinterface
6852 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006853 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006854
6855 lines =<< trim END
6856 vim9script
6857 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006858 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006859 endinterface
6860 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02006861 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006862
6863 lines =<< trim END
6864 vim9script
6865 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006866 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006867 endinterface
6868 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02006869 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006870
6871 lines =<< trim END
6872 vim9script
6873 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006874 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006875 endinterface
6876 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006877 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006878
6879 lines =<< trim END
6880 vim9script
6881 interface A
6882 static def Foo(d: dict<any>): list<string>
6883 endinterface
6884 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006885 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006886
6887 lines =<< trim END
6888 vim9script
6889 interface A
6890 static def _Foo(d: dict<any>): list<string>
6891 endinterface
6892 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006893 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006894
6895 lines =<< trim END
6896 vim9script
6897 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006898 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006899 endinterface
6900 END
Ernie Rael03042a22023-11-11 08:53:32 +01006901 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006902
6903 lines =<< trim END
6904 vim9script
6905 interface A
6906 def _Foo(d: dict<any>): list<string>
6907 endinterface
6908 END
Ernie Rael03042a22023-11-11 08:53:32 +01006909 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006910enddef
6911
6912" Test for extending an interface
6913def Test_extend_interface()
6914 var lines =<< trim END
6915 vim9script
6916 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006917 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006918 def Foo()
6919 endinterface
6920 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006921 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006922 def Bar()
6923 endinterface
6924 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006925 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006926 def Foo()
6927 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01006928 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006929 def Bar()
6930 enddef
6931 endclass
6932 END
6933 v9.CheckSourceSuccess(lines)
6934
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02006935 # extending empty interface
6936 lines =<< trim END
6937 vim9script
6938 interface A
6939 endinterface
6940 interface B extends A
6941 endinterface
6942 class C implements B
6943 endclass
6944 END
6945 v9.CheckSourceSuccess(lines)
6946
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006947 lines =<< trim END
6948 vim9script
6949 interface A
6950 def Foo()
6951 endinterface
6952 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006953 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006954 endinterface
6955 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006956 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006957 endclass
6958 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006959 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006960
6961 lines =<< trim END
6962 vim9script
6963 interface A
6964 def Foo()
6965 endinterface
6966 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006967 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006968 endinterface
6969 class C implements A, B
6970 def Foo()
6971 enddef
6972 endclass
6973 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006974 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006975
6976 # interface cannot extend a class
6977 lines =<< trim END
6978 vim9script
6979 class A
6980 endclass
6981 interface B extends A
6982 endinterface
6983 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006984 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006985
6986 # class cannot extend an interface
6987 lines =<< trim END
6988 vim9script
6989 interface A
6990 endinterface
6991 class B extends A
6992 endclass
6993 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006994 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006995
6996 # interface cannot implement another interface
6997 lines =<< trim END
6998 vim9script
6999 interface A
7000 endinterface
7001 interface B implements A
7002 endinterface
7003 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007004 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007005
7006 # interface cannot extend multiple interfaces
7007 lines =<< trim END
7008 vim9script
7009 interface A
7010 endinterface
7011 interface B
7012 endinterface
7013 interface C extends A, B
7014 endinterface
7015 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007016 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007017
7018 # Variable type in an extended interface is of different type
7019 lines =<< trim END
7020 vim9script
7021 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007022 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007023 endinterface
7024 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007025 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007026 endinterface
7027 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007028 var val1: string
7029 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007030 endinterface
7031 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007032 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007033enddef
7034
7035" Test for a child class implementing an interface when some of the methods are
7036" defined in the parent class.
7037def Test_child_class_implements_interface()
7038 var lines =<< trim END
7039 vim9script
7040
7041 interface Intf
7042 def F1(): list<list<number>>
7043 def F2(): list<list<number>>
7044 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007045 var var1: list<dict<number>>
7046 var var2: list<dict<number>>
7047 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007048 endinterface
7049
7050 class A
7051 def A1()
7052 enddef
7053 def F3(): list<list<number>>
7054 return [[3]]
7055 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007056 var v1: list<list<number>> = [[0]]
7057 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007058 endclass
7059
7060 class B extends A
7061 def B1()
7062 enddef
7063 def F2(): list<list<number>>
7064 return [[2]]
7065 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007066 var v2: list<list<number>> = [[0]]
7067 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007068 endclass
7069
7070 class C extends B implements Intf
7071 def C1()
7072 enddef
7073 def F1(): list<list<number>>
7074 return [[1]]
7075 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007076 var v3: list<list<number>> = [[0]]
7077 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007078 endclass
7079
7080 def T(if: Intf)
7081 assert_equal([[1]], if.F1())
7082 assert_equal([[2]], if.F2())
7083 assert_equal([[3]], if.F3())
7084 assert_equal([{a: 10}], if.var1)
7085 assert_equal([{b: 20}], if.var2)
7086 assert_equal([{c: 30}], if.var3)
7087 enddef
7088
7089 var c = C.new()
7090 T(c)
7091 assert_equal([[1]], c.F1())
7092 assert_equal([[2]], c.F2())
7093 assert_equal([[3]], c.F3())
7094 assert_equal([{a: 10}], c.var1)
7095 assert_equal([{b: 20}], c.var2)
7096 assert_equal([{c: 30}], c.var3)
7097 END
7098 v9.CheckSourceSuccess(lines)
7099
7100 # One of the interface methods is not found
7101 lines =<< trim END
7102 vim9script
7103
7104 interface Intf
7105 def F1()
7106 def F2()
7107 def F3()
7108 endinterface
7109
7110 class A
7111 def A1()
7112 enddef
7113 endclass
7114
7115 class B extends A
7116 def B1()
7117 enddef
7118 def F2()
7119 enddef
7120 endclass
7121
7122 class C extends B implements Intf
7123 def C1()
7124 enddef
7125 def F1()
7126 enddef
7127 endclass
7128 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007129 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007130
7131 # One of the interface methods is of different type
7132 lines =<< trim END
7133 vim9script
7134
7135 interface Intf
7136 def F1()
7137 def F2()
7138 def F3()
7139 endinterface
7140
7141 class A
7142 def F3(): number
7143 return 0
7144 enddef
7145 def A1()
7146 enddef
7147 endclass
7148
7149 class B extends A
7150 def B1()
7151 enddef
7152 def F2()
7153 enddef
7154 endclass
7155
7156 class C extends B implements Intf
7157 def C1()
7158 enddef
7159 def F1()
7160 enddef
7161 endclass
7162 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007163 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007164
7165 # One of the interface variables is not present
7166 lines =<< trim END
7167 vim9script
7168
7169 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007170 var var1: list<dict<number>>
7171 var var2: list<dict<number>>
7172 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007173 endinterface
7174
7175 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007176 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007177 endclass
7178
7179 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007180 var v2: list<list<number>> = [[0]]
7181 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007182 endclass
7183
7184 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007185 var v3: list<list<number>> = [[0]]
7186 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007187 endclass
7188 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007189 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007190
7191 # One of the interface variables is of different type
7192 lines =<< trim END
7193 vim9script
7194
7195 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007196 var var1: list<dict<number>>
7197 var var2: list<dict<number>>
7198 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007199 endinterface
7200
7201 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007202 var v1: list<list<number>> = [[0]]
7203 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007204 endclass
7205
7206 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007207 var v2: list<list<number>> = [[0]]
7208 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007209 endclass
7210
7211 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007212 var v3: list<list<number>> = [[0]]
7213 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007214 endclass
7215 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007216 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 +02007217enddef
7218
7219" Test for extending an interface with duplicate variables and methods
7220def Test_interface_extends_with_dup_members()
7221 var lines =<< trim END
7222 vim9script
7223 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007224 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007225 def Foo1(): number
7226 endinterface
7227 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007228 var n2: number
7229 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007230 def Foo2(): number
7231 def Foo1(): number
7232 endinterface
7233 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007234 var n1 = 10
7235 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007236 def Foo1(): number
7237 return 30
7238 enddef
7239 def Foo2(): number
7240 return 40
7241 enddef
7242 endclass
7243 def T1(a: A)
7244 assert_equal(10, a.n1)
7245 assert_equal(30, a.Foo1())
7246 enddef
7247 def T2(b: B)
7248 assert_equal(10, b.n1)
7249 assert_equal(20, b.n2)
7250 assert_equal(30, b.Foo1())
7251 assert_equal(40, b.Foo2())
7252 enddef
7253 var c = C.new()
7254 T1(c)
7255 T2(c)
7256 END
7257 v9.CheckSourceSuccess(lines)
7258enddef
7259
Yegappan Lakshmananc10342d2025-01-11 09:39:01 +01007260" Test for implementing an interface with different ordering for the interface
7261" member variables.
7262def Test_implement_interface_with_different_variable_order()
7263 var lines =<< trim END
7264 vim9script
7265
7266 interface IX
7267 var F: func(): string
7268 endinterface
7269
7270 class X implements IX
7271 var x: number
7272 var F: func(): string = () => 'ok'
7273 endclass
7274
7275 def Foo(ix: IX): string
7276 return ix.F()
7277 enddef
7278
7279 var x0 = X.new(0)
7280 assert_equal('ok', Foo(x0))
7281 END
7282 v9.CheckSourceSuccess(lines)
7283enddef
7284
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007285" Test for using "any" type for a variable in a sub-class while it has a
7286" concrete type in the interface
7287def Test_implements_using_var_type_any()
7288 var lines =<< trim END
7289 vim9script
7290 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007291 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007292 endinterface
7293 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007294 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007295 endclass
7296 var b = B.new()
7297 assert_equal([{a: '1'}, {b: '2'}], b.val)
7298 END
7299 v9.CheckSourceSuccess(lines)
7300
7301 # initialize instance variable using a different type
7302 lines =<< trim END
7303 vim9script
7304 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007305 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007306 endinterface
7307 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007308 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007309 endclass
7310 var b = B.new()
7311 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007312 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007313enddef
7314
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007315" Test for assigning to a member variable in a nested class
7316def Test_nested_object_assignment()
7317 var lines =<< trim END
7318 vim9script
7319
7320 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007321 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007322 endclass
7323
7324 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007325 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007326 endclass
7327
7328 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007329 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007330 endclass
7331
7332 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007333 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007334 endclass
7335
7336 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007337 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007338 enddef
7339
7340 var d = D.new()
7341 T(d)
7342 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007343 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007344enddef
7345
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007346" Test for calling methods using a null object
7347def Test_null_object_method_call()
7348 # Calling a object method using a null object in script context
7349 var lines =<< trim END
7350 vim9script
7351
7352 class C
7353 def Foo()
7354 assert_report('This method should not be executed')
7355 enddef
7356 endclass
7357
7358 var o: C
7359 o.Foo()
7360 END
7361 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7362
7363 # Calling a object method using a null object in def function context
7364 lines =<< trim END
7365 vim9script
7366
7367 class C
7368 def Foo()
7369 assert_report('This method should not be executed')
7370 enddef
7371 endclass
7372
7373 def T()
7374 var o: C
7375 o.Foo()
7376 enddef
7377 T()
7378 END
7379 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7380
7381 # Calling a object method through another class method using a null object in
7382 # script context
7383 lines =<< trim END
7384 vim9script
7385
7386 class C
7387 def Foo()
7388 assert_report('This method should not be executed')
7389 enddef
7390
7391 static def Bar(o_any: any)
7392 var o_typed: C = o_any
7393 o_typed.Foo()
7394 enddef
7395 endclass
7396
7397 var o: C
7398 C.Bar(o)
7399 END
7400 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7401
7402 # Calling a object method through another class method using a null object in
7403 # def function context
7404 lines =<< trim END
7405 vim9script
7406
7407 class C
7408 def Foo()
7409 assert_report('This method should not be executed')
7410 enddef
7411
7412 static def Bar(o_any: any)
7413 var o_typed: C = o_any
7414 o_typed.Foo()
7415 enddef
7416 endclass
7417
7418 def T()
7419 var o: C
7420 C.Bar(o)
7421 enddef
7422 T()
7423 END
7424 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007425
7426 # Calling an object method defined in a class that is extended. This differs
7427 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7428 lines =<< trim END
7429 vim9script
7430
7431 class C0
7432 def F()
7433 enddef
7434 endclass
7435
7436 class C extends C0
7437 endclass
7438
7439 def X()
7440 var o: C0 = null_object
7441 o.F()
7442 enddef
7443 X()
7444 END
7445 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7446
7447 # Getting a function ref an object method.
7448 lines =<< trim END
7449 vim9script
7450
7451 class C0
7452 def F()
7453 enddef
7454 endclass
7455
7456 class C extends C0
7457 endclass
7458
7459 def X()
7460 var o: C0 = null_object
7461 var XXX = o.F
7462 enddef
7463 X()
7464 END
7465 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007466enddef
7467
7468" Test for using a dict as an object member
7469def Test_dict_object_member()
7470 var lines =<< trim END
7471 vim9script
7472
7473 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007474 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007475 def GetState(): dict<number>
7476 return this.state
7477 enddef
7478 endclass
7479
7480 var ctx = Context.new()
7481 ctx.state->extend({a: 1})
7482 ctx.state['b'] = 2
7483 assert_equal({a: 1, b: 2}, ctx.GetState())
7484
7485 def F()
7486 ctx.state['c'] = 3
7487 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7488 enddef
7489 F()
7490 assert_equal(3, ctx.state.c)
7491 ctx.state.c = 4
7492 assert_equal(4, ctx.state.c)
7493 END
7494 v9.CheckSourceSuccess(lines)
7495enddef
7496
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007497" The following test was failing after 9.0.1914. This was caused by using a
7498" freed object from a previous method call.
7499def Test_freed_object_from_previous_method_call()
7500 var lines =<< trim END
7501 vim9script
7502
7503 class Context
7504 endclass
7505
7506 class Result
7507 endclass
7508
7509 def Failure(): Result
7510 return Result.new()
7511 enddef
7512
7513 def GetResult(ctx: Context): Result
7514 return Failure()
7515 enddef
7516
7517 def Test_GetResult()
7518 var ctx = Context.new()
7519 var result = GetResult(ctx)
7520 enddef
7521
7522 Test_GetResult()
7523 END
7524 v9.CheckSourceSuccess(lines)
7525enddef
7526
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007527" Test for duplicate object and class variable
7528def Test_duplicate_variable()
7529 # Object variable name is same as the class variable name
7530 var lines =<< trim END
7531 vim9script
7532 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007533 public static var sval: number
7534 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007535 endclass
7536 var a = A.new()
7537 END
7538 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7539
7540 # Duplicate variable name and calling a class method
7541 lines =<< trim END
7542 vim9script
7543 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007544 public static var sval: number
7545 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007546 def F1()
7547 echo this.sval
7548 enddef
7549 static def F2()
7550 echo sval
7551 enddef
7552 endclass
7553 A.F2()
7554 END
7555 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7556
7557 # Duplicate variable with an empty constructor
7558 lines =<< trim END
7559 vim9script
7560 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007561 public static var sval: number
7562 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007563 def new()
7564 enddef
7565 endclass
7566 var a = A.new()
7567 END
7568 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7569enddef
7570
7571" Test for using a reserved keyword as a variable name
7572def Test_reserved_varname()
7573 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7574 'null_function', 'null_list', 'null_partial', 'null_string',
7575 'null_channel', 'null_job', 'super', 'this']
7576
7577 var lines =<< trim eval END
7578 vim9script
7579 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007580 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007581 endclass
7582 var o = C.new()
7583 END
7584 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7585
7586 lines =<< trim eval END
7587 vim9script
7588 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007589 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007590 def new()
7591 enddef
7592 endclass
7593 var o = C.new()
7594 END
7595 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7596
7597 lines =<< trim eval END
7598 vim9script
7599 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007600 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007601 def new()
7602 enddef
7603 def F()
7604 echo this.{kword}
7605 enddef
7606 endclass
7607 var o = C.new()
7608 o.F()
7609 END
7610 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007611
7612 # class variable name
7613 if kword != 'this'
7614 lines =<< trim eval END
7615 vim9script
7616 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007617 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007618 endclass
7619 END
7620 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7621 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007622 endfor
7623enddef
7624
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007625" Test for checking the type of the arguments and the return value of a object
7626" method in an extended class.
7627def Test_extended_obj_method_type_check()
7628 var lines =<< trim END
7629 vim9script
7630
7631 class A
7632 endclass
7633 class B extends A
7634 endclass
7635 class C extends B
7636 endclass
7637
7638 class Foo
7639 def Doit(p: B): B
7640 return B.new()
7641 enddef
7642 endclass
7643
7644 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007645 def Doit(p: C): B
7646 return B.new()
7647 enddef
7648 endclass
7649 END
7650 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
7651
7652 lines =<< trim END
7653 vim9script
7654
7655 class A
7656 endclass
7657 class B extends A
7658 endclass
7659 class C extends B
7660 endclass
7661
7662 class Foo
7663 def Doit(p: B): B
7664 return B.new()
7665 enddef
7666 endclass
7667
7668 class Bar extends Foo
7669 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007670 return C.new()
7671 enddef
7672 endclass
7673 END
7674 v9.CheckSourceSuccess(lines)
7675
7676 lines =<< trim END
7677 vim9script
7678
7679 class A
7680 endclass
7681 class B extends A
7682 endclass
7683 class C extends B
7684 endclass
7685
7686 class Foo
7687 def Doit(p: B): B
7688 return B.new()
7689 enddef
7690 endclass
7691
7692 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007693 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007694 return B.new()
7695 enddef
7696 endclass
7697 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007698 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 +02007699
7700 lines =<< trim END
7701 vim9script
7702
7703 class A
7704 endclass
7705 class B extends A
7706 endclass
7707 class C extends B
7708 endclass
7709
7710 class Foo
7711 def Doit(p: B): B
7712 return B.new()
7713 enddef
7714 endclass
7715
7716 class Bar extends Foo
7717 def Doit(p: B): A
7718 return A.new()
7719 enddef
7720 endclass
7721 END
7722 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 +02007723
7724 # check varargs type mismatch
7725 lines =<< trim END
7726 vim9script
7727
7728 class B
7729 def F(...xxx: list<any>)
7730 enddef
7731 endclass
7732 class C extends B
7733 def F(xxx: list<any>)
7734 enddef
7735 endclass
7736 END
7737 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 +02007738enddef
7739
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007740" Test type checking for class variable in assignments
7741func Test_class_variable_complex_type_check()
7742 " class variable with a specific type. Try assigning a different type at
7743 " script level.
7744 let lines =<< trim END
7745 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007746 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007747 return {}
7748 enddef
7749 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007750 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007751 endclass
7752 test_garbagecollect_now()
7753 A.Fn = "abc"
7754 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007755 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 +02007756
7757 " class variable with a specific type. Try assigning a different type at
7758 " class def method level.
7759 let lines =<< trim END
7760 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007761 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007762 return {}
7763 enddef
7764 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007765 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007766 def Bar()
7767 Fn = "abc"
7768 enddef
7769 endclass
7770 var a = A.new()
7771 test_garbagecollect_now()
7772 a.Bar()
7773 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007774 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 +02007775
7776 " class variable with a specific type. Try assigning a different type at
7777 " script def method level.
7778 let lines =<< trim END
7779 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007780 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007781 return {}
7782 enddef
7783 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007784 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007785 endclass
7786 def Bar()
7787 A.Fn = "abc"
7788 enddef
7789 test_garbagecollect_now()
7790 Bar()
7791 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007792 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 +02007793
7794 " class variable without any type. Should be set to the initialization
7795 " expression type. Try assigning a different type from script level.
7796 let lines =<< trim END
7797 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007798 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007799 return {}
7800 enddef
7801 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007802 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007803 endclass
7804 test_garbagecollect_now()
7805 A.Fn = "abc"
7806 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007807 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 +02007808
7809 " class variable without any type. Should be set to the initialization
7810 " expression type. Try assigning a different type at class def level.
7811 let lines =<< trim END
7812 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007813 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007814 return {}
7815 enddef
7816 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007817 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007818 def Bar()
7819 Fn = "abc"
7820 enddef
7821 endclass
7822 var a = A.new()
7823 test_garbagecollect_now()
7824 a.Bar()
7825 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007826 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 +02007827
7828 " class variable without any type. Should be set to the initialization
7829 " expression type. Try assigning a different type at script def level.
7830 let lines =<< trim END
7831 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007832 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007833 return {}
7834 enddef
7835 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007836 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007837 endclass
7838 def Bar()
7839 A.Fn = "abc"
7840 enddef
7841 test_garbagecollect_now()
7842 Bar()
7843 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007844 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 +02007845
7846 " class variable with 'any" type. Can be assigned different types.
7847 let lines =<< trim END
7848 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007849 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007850 return {}
7851 enddef
7852 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007853 public static var Fn: any = Foo
7854 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007855 endclass
7856 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007857 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007858 A.Fn = "abc"
7859 test_garbagecollect_now()
7860 assert_equal('string', typename(A.Fn))
7861 A.Fn2 = Foo
7862 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007863 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007864 A.Fn2 = "xyz"
7865 test_garbagecollect_now()
7866 assert_equal('string', typename(A.Fn2))
7867 END
7868 call v9.CheckSourceSuccess(lines)
7869
7870 " class variable with 'any" type. Can be assigned different types.
7871 let lines =<< trim END
7872 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007873 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007874 return {}
7875 enddef
7876 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007877 public static var Fn: any = Foo
7878 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007879
7880 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007881 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007882 Fn = "abc"
7883 assert_equal('string', typename(Fn))
7884 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007885 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007886 Fn2 = "xyz"
7887 assert_equal('string', typename(Fn2))
7888 enddef
7889 endclass
7890 var a = A.new()
7891 test_garbagecollect_now()
7892 a.Bar()
7893 test_garbagecollect_now()
7894 A.Fn = Foo
7895 a.Bar()
7896 END
7897 call v9.CheckSourceSuccess(lines)
7898
7899 " class variable with 'any" type. Can be assigned different types.
7900 let lines =<< trim END
7901 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007902 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007903 return {}
7904 enddef
7905 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007906 public static var Fn: any = Foo
7907 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007908 endclass
7909
7910 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007911 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007912 A.Fn = "abc"
7913 assert_equal('string', typename(A.Fn))
7914 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007915 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007916 A.Fn2 = "xyz"
7917 assert_equal('string', typename(A.Fn2))
7918 enddef
7919 Bar()
7920 test_garbagecollect_now()
7921 A.Fn = Foo
7922 Bar()
7923 END
7924 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007925
7926 let lines =<< trim END
7927 vim9script
7928 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007929 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007930 endclass
7931 assert_equal([0z10, 0z20], A.foo)
7932 A.foo = [0z30]
7933 assert_equal([0z30], A.foo)
7934 var a = A.foo
7935 assert_equal([0z30], a)
7936 END
7937 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007938endfunc
7939
7940" Test type checking for object variable in assignments
7941func Test_object_variable_complex_type_check()
7942 " object variable with a specific type. Try assigning a different type at
7943 " script level.
7944 let lines =<< trim END
7945 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007946 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007947 return {}
7948 enddef
7949 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007950 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007951 endclass
7952 var a = A.new()
7953 test_garbagecollect_now()
7954 a.Fn = "abc"
7955 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007956 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 +02007957
7958 " object variable with a specific type. Try assigning a different type at
7959 " object def method level.
7960 let lines =<< trim END
7961 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007962 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007963 return {}
7964 enddef
7965 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007966 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007967 def Bar()
7968 this.Fn = "abc"
7969 this.Fn = Foo
7970 enddef
7971 endclass
7972 var a = A.new()
7973 test_garbagecollect_now()
7974 a.Bar()
7975 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007976 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 +02007977
7978 " object variable with a specific type. Try assigning a different type at
7979 " script def method level.
7980 let lines =<< trim END
7981 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007982 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007983 return {}
7984 enddef
7985 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007986 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007987 endclass
7988 def Bar()
7989 var a = A.new()
7990 a.Fn = "abc"
7991 a.Fn = Foo
7992 enddef
7993 test_garbagecollect_now()
7994 Bar()
7995 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007996 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 +02007997
7998 " object variable without any type. Should be set to the initialization
7999 " expression type. Try assigning a different type from script level.
8000 let lines =<< trim END
8001 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008002 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008003 return {}
8004 enddef
8005 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008006 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008007 endclass
8008 var a = A.new()
8009 test_garbagecollect_now()
8010 a.Fn = "abc"
8011 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008012 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 +02008013
8014 " object variable without any type. Should be set to the initialization
8015 " expression type. Try assigning a different type at object def level.
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 var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008023 def Bar()
8024 this.Fn = "abc"
8025 this.Fn = Foo
8026 enddef
8027 endclass
8028 var a = A.new()
8029 test_garbagecollect_now()
8030 a.Bar()
8031 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008032 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 +02008033
8034 " object variable without any type. Should be set to the initialization
8035 " expression type. Try assigning a different type at script def level.
8036 let lines =<< trim END
8037 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008038 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008039 return {}
8040 enddef
8041 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008042 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008043 endclass
8044 def Bar()
8045 var a = A.new()
8046 a.Fn = "abc"
8047 a.Fn = Foo
8048 enddef
8049 test_garbagecollect_now()
8050 Bar()
8051 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008052 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 +02008053
8054 " object variable with 'any" type. Can be assigned different types.
8055 let lines =<< trim END
8056 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008057 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008058 return {}
8059 enddef
8060 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008061 public var Fn: any = Foo
8062 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008063 endclass
8064
8065 var a = A.new()
8066 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008067 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008068 a.Fn = "abc"
8069 test_garbagecollect_now()
8070 assert_equal('string', typename(a.Fn))
8071 a.Fn2 = Foo
8072 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008073 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008074 a.Fn2 = "xyz"
8075 test_garbagecollect_now()
8076 assert_equal('string', typename(a.Fn2))
8077 END
8078 call v9.CheckSourceSuccess(lines)
8079
8080 " object variable with 'any" type. Can be assigned different types.
8081 let lines =<< trim END
8082 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008083 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008084 return {}
8085 enddef
8086 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008087 public var Fn: any = Foo
8088 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008089
8090 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008091 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008092 this.Fn = "abc"
8093 assert_equal('string', typename(this.Fn))
8094 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008095 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008096 this.Fn2 = "xyz"
8097 assert_equal('string', typename(this.Fn2))
8098 enddef
8099 endclass
8100
8101 var a = A.new()
8102 test_garbagecollect_now()
8103 a.Bar()
8104 test_garbagecollect_now()
8105 a.Fn = Foo
8106 a.Bar()
8107 END
8108 call v9.CheckSourceSuccess(lines)
8109
8110 " object variable with 'any" type. Can be assigned different types.
8111 let lines =<< trim END
8112 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008113 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008114 return {}
8115 enddef
8116 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008117 public var Fn: any = Foo
8118 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008119 endclass
8120
8121 def Bar()
8122 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008123 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008124 a.Fn = "abc"
8125 assert_equal('string', typename(a.Fn))
8126 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008127 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008128 a.Fn2 = "xyz"
8129 assert_equal('string', typename(a.Fn2))
8130 enddef
8131 test_garbagecollect_now()
8132 Bar()
8133 test_garbagecollect_now()
8134 Bar()
8135 END
8136 call v9.CheckSourceSuccess(lines)
8137endfunc
8138
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008139" Test for recursively calling an object method. This used to cause an
8140" use-after-free error.
8141def Test_recursive_object_method_call()
8142 var lines =<< trim END
8143 vim9script
8144 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008145 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008146 def Foo(): number
8147 if this.val >= 90
8148 return this.val
8149 endif
8150 this.val += 1
8151 return this.Foo()
8152 enddef
8153 endclass
8154 var a = A.new()
8155 assert_equal(90, a.Foo())
8156 END
8157 v9.CheckSourceSuccess(lines)
8158enddef
8159
8160" Test for recursively calling a class method.
8161def Test_recursive_class_method_call()
8162 var lines =<< trim END
8163 vim9script
8164 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008165 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008166 static def Foo(): number
8167 if val >= 90
8168 return val
8169 endif
8170 val += 1
8171 return Foo()
8172 enddef
8173 endclass
8174 assert_equal(90, A.Foo())
8175 END
8176 v9.CheckSourceSuccess(lines)
8177enddef
8178
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008179" Test for checking the argument types and the return type when assigning a
8180" funcref to make sure the invariant class type is used.
8181def Test_funcref_argtype_returntype_check()
8182 var lines =<< trim END
8183 vim9script
8184 class A
8185 endclass
8186 class B extends A
8187 endclass
8188
8189 def Foo(p: B): B
8190 return B.new()
8191 enddef
8192
8193 var Bar: func(A): A = Foo
8194 END
8195 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8196
8197 lines =<< trim END
8198 vim9script
8199 class A
8200 endclass
8201 class B extends A
8202 endclass
8203
8204 def Foo(p: B): B
8205 return B.new()
8206 enddef
8207
8208 def Baz()
8209 var Bar: func(A): A = Foo
8210 enddef
8211 Baz()
8212 END
8213 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8214enddef
8215
Ernie Rael96952b22023-10-17 18:15:01 +02008216def Test_funcref_argtype_invariance_check()
8217 var lines =<< trim END
8218 vim9script
8219
8220 class A
8221 endclass
8222 class B extends A
8223 endclass
8224 class C extends B
8225 endclass
8226
8227 var Func: func(B): number
8228 Func = (o: B): number => 3
8229 assert_equal(3, Func(B.new()))
8230 END
8231 v9.CheckSourceSuccess(lines)
8232
8233 lines =<< trim END
8234 vim9script
8235
8236 class A
8237 endclass
8238 class B extends A
8239 endclass
8240 class C extends B
8241 endclass
8242
8243 var Func: func(B): number
8244 Func = (o: A): number => 3
8245 END
8246 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8247
8248 lines =<< trim END
8249 vim9script
8250
8251 class A
8252 endclass
8253 class B extends A
8254 endclass
8255 class C extends B
8256 endclass
8257
8258 var Func: func(B): number
8259 Func = (o: C): number => 3
8260 END
8261 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8262enddef
8263
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008264" Test for using an operator (e.g. +) with an assignment
8265def Test_op_and_assignment()
8266 # Using += with a class variable
8267 var lines =<< trim END
8268 vim9script
8269 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008270 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008271 static def Foo(): list<number>
8272 val += [1]
8273 return val
8274 enddef
8275 endclass
8276 def Bar(): list<number>
8277 A.val += [2]
8278 return A.val
8279 enddef
8280 assert_equal([1], A.Foo())
8281 assert_equal([1, 2], Bar())
8282 A.val += [3]
8283 assert_equal([1, 2, 3], A.val)
8284 END
8285 v9.CheckSourceSuccess(lines)
8286
8287 # Using += with an object variable
8288 lines =<< trim END
8289 vim9script
8290 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008291 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008292 def Foo(): list<number>
8293 this.val += [1]
8294 return this.val
8295 enddef
8296 endclass
8297 def Bar(bar_a: A): list<number>
8298 bar_a.val += [2]
8299 return bar_a.val
8300 enddef
8301 var a = A.new()
8302 assert_equal([1], a.Foo())
8303 assert_equal([1, 2], Bar(a))
8304 a.val += [3]
8305 assert_equal([1, 2, 3], a.val)
8306 END
8307 v9.CheckSourceSuccess(lines)
8308enddef
8309
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008310" Test for using an object method as a funcref
8311def Test_object_funcref()
8312 # Using object method funcref from a def function
8313 var lines =<< trim END
8314 vim9script
8315 class A
8316 def Foo(): list<number>
8317 return [3, 2, 1]
8318 enddef
8319 endclass
8320 def Bar()
8321 var a = A.new()
8322 var Fn = a.Foo
8323 assert_equal([3, 2, 1], Fn())
8324 enddef
8325 Bar()
8326 END
8327 v9.CheckSourceSuccess(lines)
8328
8329 # Using object method funcref at the script level
8330 lines =<< trim END
8331 vim9script
8332 class A
8333 def Foo(): dict<number>
8334 return {a: 1, b: 2}
8335 enddef
8336 endclass
8337 var a = A.new()
8338 var Fn = a.Foo
8339 assert_equal({a: 1, b: 2}, Fn())
8340 END
8341 v9.CheckSourceSuccess(lines)
8342
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008343 # Using object method funcref at the script level
8344 lines =<< trim END
8345 vim9script
8346 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008347 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008348 def Foo(): number
8349 return this.val
8350 enddef
8351 endclass
8352 var a = A.new(345)
8353 var Fn = a.Foo
8354 assert_equal(345, Fn())
8355 END
8356 v9.CheckSourceSuccess(lines)
8357
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008358 # Using object method funcref from another object method
8359 lines =<< trim END
8360 vim9script
8361 class A
8362 def Foo(): list<number>
8363 return [3, 2, 1]
8364 enddef
8365 def Bar()
8366 var Fn = this.Foo
8367 assert_equal([3, 2, 1], Fn())
8368 enddef
8369 endclass
8370 var a = A.new()
8371 a.Bar()
8372 END
8373 v9.CheckSourceSuccess(lines)
8374
8375 # Using function() to get a object method funcref
8376 lines =<< trim END
8377 vim9script
8378 class A
8379 def Foo(l: list<any>): list<any>
8380 return l
8381 enddef
8382 endclass
8383 var a = A.new()
8384 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8385 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8386 END
8387 v9.CheckSourceSuccess(lines)
8388
8389 # Use an object method with a function returning a funcref and then call the
8390 # funcref.
8391 lines =<< trim END
8392 vim9script
8393
8394 def Map(F: func(number): number): func(number): number
8395 return (n: number) => F(n)
8396 enddef
8397
8398 class Math
8399 def Double(n: number): number
8400 return 2 * n
8401 enddef
8402 endclass
8403
8404 const math = Math.new()
8405 assert_equal(48, Map(math.Double)(24))
8406 END
8407 v9.CheckSourceSuccess(lines)
8408
Ernie Rael03042a22023-11-11 08:53:32 +01008409 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008410 lines =<< trim END
8411 vim9script
8412 class A
8413 def _Foo()
8414 enddef
8415 endclass
8416 def Bar()
8417 var a = A.new()
8418 var Fn = a._Foo
8419 enddef
8420 Bar()
8421 END
Ernie Rael03042a22023-11-11 08:53:32 +01008422 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008423
Ernie Rael03042a22023-11-11 08:53:32 +01008424 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008425 lines =<< trim END
8426 vim9script
8427 class A
8428 def _Foo()
8429 enddef
8430 endclass
8431 var a = A.new()
8432 var Fn = a._Foo
8433 END
Ernie Rael03042a22023-11-11 08:53:32 +01008434 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008435
Ernie Rael03042a22023-11-11 08:53:32 +01008436 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008437 lines =<< trim END
8438 vim9script
8439 class A
8440 def _Foo(): list<number>
8441 return [3, 2, 1]
8442 enddef
8443 def Bar()
8444 var Fn = this._Foo
8445 assert_equal([3, 2, 1], Fn())
8446 enddef
8447 endclass
8448 var a = A.new()
8449 a.Bar()
8450 END
8451 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008452
8453 # Using object method funcref using call()
8454 lines =<< trim END
8455 vim9script
8456 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008457 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008458 def Foo(): number
8459 return this.val
8460 enddef
8461 endclass
8462
8463 def Bar(obj: A)
8464 assert_equal(123, call(obj.Foo, []))
8465 enddef
8466
8467 var a = A.new(123)
8468 Bar(a)
8469 assert_equal(123, call(a.Foo, []))
8470 END
8471 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008472enddef
8473
8474" Test for using a class method as a funcref
8475def Test_class_funcref()
8476 # Using class method funcref in a def function
8477 var lines =<< trim END
8478 vim9script
8479 class A
8480 static def Foo(): list<number>
8481 return [3, 2, 1]
8482 enddef
8483 endclass
8484 def Bar()
8485 var Fn = A.Foo
8486 assert_equal([3, 2, 1], Fn())
8487 enddef
8488 Bar()
8489 END
8490 v9.CheckSourceSuccess(lines)
8491
8492 # Using class method funcref at script level
8493 lines =<< trim END
8494 vim9script
8495 class A
8496 static def Foo(): dict<number>
8497 return {a: 1, b: 2}
8498 enddef
8499 endclass
8500 var Fn = A.Foo
8501 assert_equal({a: 1, b: 2}, Fn())
8502 END
8503 v9.CheckSourceSuccess(lines)
8504
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008505 # Using class method funcref at the script level
8506 lines =<< trim END
8507 vim9script
8508 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008509 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008510 static def Foo(): number
8511 return val
8512 enddef
8513 endclass
8514 A.val = 567
8515 var Fn = A.Foo
8516 assert_equal(567, Fn())
8517 END
8518 v9.CheckSourceSuccess(lines)
8519
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008520 # Using function() to get a class method funcref
8521 lines =<< trim END
8522 vim9script
8523 class A
8524 static def Foo(l: list<any>): list<any>
8525 return l
8526 enddef
8527 endclass
8528 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8529 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8530 END
8531 v9.CheckSourceSuccess(lines)
8532
8533 # Using a class method funcref from another class method
8534 lines =<< trim END
8535 vim9script
8536 class A
8537 static def Foo(): list<number>
8538 return [3, 2, 1]
8539 enddef
8540 static def Bar()
8541 var Fn = Foo
8542 assert_equal([3, 2, 1], Fn())
8543 enddef
8544 endclass
8545 A.Bar()
8546 END
8547 v9.CheckSourceSuccess(lines)
8548
8549 # Use a class method with a function returning a funcref and then call the
8550 # funcref.
8551 lines =<< trim END
8552 vim9script
8553
8554 def Map(F: func(number): number): func(number): number
8555 return (n: number) => F(n)
8556 enddef
8557
8558 class Math
8559 static def StaticDouble(n: number): number
8560 return 2 * n
8561 enddef
8562 endclass
8563
8564 assert_equal(48, Map(Math.StaticDouble)(24))
8565 END
8566 v9.CheckSourceSuccess(lines)
8567
Ernie Rael03042a22023-11-11 08:53:32 +01008568 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008569 lines =<< trim END
8570 vim9script
8571 class A
8572 static def _Foo()
8573 enddef
8574 endclass
8575 def Bar()
8576 var Fn = A._Foo
8577 enddef
8578 Bar()
8579 END
Ernie Rael03042a22023-11-11 08:53:32 +01008580 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008581
Ernie Rael03042a22023-11-11 08:53:32 +01008582 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008583 lines =<< trim END
8584 vim9script
8585 class A
8586 static def _Foo()
8587 enddef
8588 endclass
8589 var Fn = A._Foo
8590 END
Ernie Rael03042a22023-11-11 08:53:32 +01008591 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008592
Ernie Rael03042a22023-11-11 08:53:32 +01008593 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008594 lines =<< trim END
8595 vim9script
8596 class A
8597 static def _Foo(): list<number>
8598 return [3, 2, 1]
8599 enddef
8600 static def Bar()
8601 var Fn = _Foo
8602 assert_equal([3, 2, 1], Fn())
8603 enddef
8604 endclass
8605 A.Bar()
8606 END
8607 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008608
8609 # Using class method funcref using call()
8610 lines =<< trim END
8611 vim9script
8612 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008613 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008614 static def Foo(): number
8615 return val
8616 enddef
8617 endclass
8618
8619 def Bar()
8620 A.val = 468
8621 assert_equal(468, call(A.Foo, []))
8622 enddef
8623 Bar()
8624 assert_equal(468, call(A.Foo, []))
8625 END
8626 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008627enddef
8628
8629" Test for using an object member as a funcref
8630def Test_object_member_funcref()
8631 # Using a funcref object variable in an object method
8632 var lines =<< trim END
8633 vim9script
8634 def Foo(n: number): number
8635 return n * 10
8636 enddef
8637
8638 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008639 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008640 def Bar()
8641 assert_equal(200, this.Cb(20))
8642 enddef
8643 endclass
8644
8645 var a = A.new()
8646 a.Bar()
8647 END
8648 v9.CheckSourceSuccess(lines)
8649
8650 # Using a funcref object variable in a def method
8651 lines =<< trim END
8652 vim9script
8653 def Foo(n: number): number
8654 return n * 10
8655 enddef
8656
8657 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008658 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008659 endclass
8660
8661 def Bar()
8662 var a = A.new()
8663 assert_equal(200, a.Cb(20))
8664 enddef
8665 Bar()
8666 END
8667 v9.CheckSourceSuccess(lines)
8668
8669 # Using a funcref object variable at script level
8670 lines =<< trim END
8671 vim9script
8672 def Foo(n: number): number
8673 return n * 10
8674 enddef
8675
8676 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008677 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008678 endclass
8679
8680 var a = A.new()
8681 assert_equal(200, a.Cb(20))
8682 END
8683 v9.CheckSourceSuccess(lines)
8684
8685 # Using a funcref object variable pointing to an object method in an object
8686 # method.
8687 lines =<< trim END
8688 vim9script
8689 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008690 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008691 def Foo(n: number): number
8692 return n * 10
8693 enddef
8694 def Bar()
8695 assert_equal(200, this.Cb(20))
8696 enddef
8697 endclass
8698
8699 var a = A.new()
8700 a.Bar()
8701 END
8702 v9.CheckSourceSuccess(lines)
8703
8704 # Using a funcref object variable pointing to an object method in a def
8705 # method.
8706 lines =<< trim END
8707 vim9script
8708 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008709 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008710 def Foo(n: number): number
8711 return n * 10
8712 enddef
8713 endclass
8714
8715 def Bar()
8716 var a = A.new()
8717 assert_equal(200, a.Cb(20))
8718 enddef
8719 Bar()
8720 END
8721 v9.CheckSourceSuccess(lines)
8722
8723 # Using a funcref object variable pointing to an object method at script
8724 # level.
8725 lines =<< trim END
8726 vim9script
8727 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008728 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008729 def Foo(n: number): number
8730 return n * 10
8731 enddef
8732 endclass
8733
8734 var a = A.new()
8735 assert_equal(200, a.Cb(20))
8736 END
8737 v9.CheckSourceSuccess(lines)
8738enddef
8739
8740" Test for using a class member as a funcref
8741def Test_class_member_funcref()
8742 # Using a funcref class variable in a class method
8743 var lines =<< trim END
8744 vim9script
8745 def Foo(n: number): number
8746 return n * 10
8747 enddef
8748
8749 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008750 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008751 static def Bar()
8752 assert_equal(200, Cb(20))
8753 enddef
8754 endclass
8755
8756 A.Bar()
8757 END
8758 v9.CheckSourceSuccess(lines)
8759
8760 # Using a funcref class variable in a def method
8761 lines =<< trim END
8762 vim9script
8763 def Foo(n: number): number
8764 return n * 10
8765 enddef
8766
8767 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008768 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008769 endclass
8770
8771 def Bar()
8772 assert_equal(200, A.Cb(20))
8773 enddef
8774 Bar()
8775 END
8776 v9.CheckSourceSuccess(lines)
8777
8778 # Using a funcref class variable at script level
8779 lines =<< trim END
8780 vim9script
8781 def Foo(n: number): number
8782 return n * 10
8783 enddef
8784
8785 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008786 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008787 endclass
8788
8789 assert_equal(200, A.Cb(20))
8790 END
8791 v9.CheckSourceSuccess(lines)
8792
8793 # Using a funcref class variable pointing to a class method in a class
8794 # method.
8795 lines =<< trim END
8796 vim9script
8797 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008798 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008799 static def Foo(n: number): number
8800 return n * 10
8801 enddef
8802 static def Init()
8803 Cb = Foo
8804 enddef
8805 static def Bar()
8806 assert_equal(200, Cb(20))
8807 enddef
8808 endclass
8809
8810 A.Init()
8811 A.Bar()
8812 END
8813 v9.CheckSourceSuccess(lines)
8814
8815 # Using a funcref class variable pointing to a class method in a def method.
8816 lines =<< trim END
8817 vim9script
8818 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008819 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008820 static def Foo(n: number): number
8821 return n * 10
8822 enddef
8823 static def Init()
8824 Cb = Foo
8825 enddef
8826 endclass
8827
8828 def Bar()
8829 A.Init()
8830 assert_equal(200, A.Cb(20))
8831 enddef
8832 Bar()
8833 END
8834 v9.CheckSourceSuccess(lines)
8835
8836 # Using a funcref class variable pointing to a class method at script level.
8837 lines =<< trim END
8838 vim9script
8839 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008840 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008841 static def Foo(n: number): number
8842 return n * 10
8843 enddef
8844 static def Init()
8845 Cb = Foo
8846 enddef
8847 endclass
8848
8849 A.Init()
8850 assert_equal(200, A.Cb(20))
8851 END
8852 v9.CheckSourceSuccess(lines)
8853enddef
8854
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008855" Test for using object methods as popup callback functions
8856def Test_objmethod_popup_callback()
8857 # Use the popup from the script level
8858 var lines =<< trim END
8859 vim9script
8860
8861 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008862 var selection: number = -1
8863 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008864
8865 def PopupFilter(id: number, key: string): bool
8866 add(this.filterkeys, key)
8867 return popup_filter_yesno(id, key)
8868 enddef
8869
8870 def PopupCb(id: number, result: number)
8871 this.selection = result ? 100 : 200
8872 enddef
8873 endclass
8874
8875 var a = A.new()
8876 feedkeys('', 'xt')
8877 var winid = popup_create('Y/N?',
8878 {filter: a.PopupFilter, callback: a.PopupCb})
8879 feedkeys('y', 'xt')
8880 popup_close(winid)
8881 assert_equal(100, a.selection)
8882 assert_equal(['y'], a.filterkeys)
8883 feedkeys('', 'xt')
8884 winid = popup_create('Y/N?',
8885 {filter: a.PopupFilter, callback: a.PopupCb})
8886 feedkeys('n', 'xt')
8887 popup_close(winid)
8888 assert_equal(200, a.selection)
8889 assert_equal(['y', 'n'], a.filterkeys)
8890 END
8891 v9.CheckSourceSuccess(lines)
8892
8893 # Use the popup from a def function
8894 lines =<< trim END
8895 vim9script
8896
8897 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008898 var selection: number = -1
8899 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008900
8901 def PopupFilter(id: number, key: string): bool
8902 add(this.filterkeys, key)
8903 return popup_filter_yesno(id, key)
8904 enddef
8905
8906 def PopupCb(id: number, result: number)
8907 this.selection = result ? 100 : 200
8908 enddef
8909 endclass
8910
8911 def Foo()
8912 var a = A.new()
8913 feedkeys('', 'xt')
8914 var winid = popup_create('Y/N?',
8915 {filter: a.PopupFilter, callback: a.PopupCb})
8916 feedkeys('y', 'xt')
8917 popup_close(winid)
8918 assert_equal(100, a.selection)
8919 assert_equal(['y'], a.filterkeys)
8920 feedkeys('', 'xt')
8921 winid = popup_create('Y/N?',
8922 {filter: a.PopupFilter, callback: a.PopupCb})
8923 feedkeys('n', 'xt')
8924 popup_close(winid)
8925 assert_equal(200, a.selection)
8926 assert_equal(['y', 'n'], a.filterkeys)
8927 enddef
8928 Foo()
8929 END
8930 v9.CheckSourceSuccess(lines)
8931enddef
8932
8933" Test for using class methods as popup callback functions
8934def Test_classmethod_popup_callback()
8935 # Use the popup from the script level
8936 var lines =<< trim END
8937 vim9script
8938
8939 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008940 static var selection: number = -1
8941 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008942
8943 static def PopupFilter(id: number, key: string): bool
8944 add(filterkeys, key)
8945 return popup_filter_yesno(id, key)
8946 enddef
8947
8948 static def PopupCb(id: number, result: number)
8949 selection = result ? 100 : 200
8950 enddef
8951 endclass
8952
8953 feedkeys('', 'xt')
8954 var winid = popup_create('Y/N?',
8955 {filter: A.PopupFilter, callback: A.PopupCb})
8956 feedkeys('y', 'xt')
8957 popup_close(winid)
8958 assert_equal(100, A.selection)
8959 assert_equal(['y'], A.filterkeys)
8960 feedkeys('', 'xt')
8961 winid = popup_create('Y/N?',
8962 {filter: A.PopupFilter, callback: A.PopupCb})
8963 feedkeys('n', 'xt')
8964 popup_close(winid)
8965 assert_equal(200, A.selection)
8966 assert_equal(['y', 'n'], A.filterkeys)
8967 END
8968 v9.CheckSourceSuccess(lines)
8969
8970 # Use the popup from a def function
8971 lines =<< trim END
8972 vim9script
8973
8974 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008975 static var selection: number = -1
8976 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008977
8978 static def PopupFilter(id: number, key: string): bool
8979 add(filterkeys, key)
8980 return popup_filter_yesno(id, key)
8981 enddef
8982
8983 static def PopupCb(id: number, result: number)
8984 selection = result ? 100 : 200
8985 enddef
8986 endclass
8987
8988 def Foo()
8989 feedkeys('', 'xt')
8990 var winid = popup_create('Y/N?',
8991 {filter: A.PopupFilter, callback: A.PopupCb})
8992 feedkeys('y', 'xt')
8993 popup_close(winid)
8994 assert_equal(100, A.selection)
8995 assert_equal(['y'], A.filterkeys)
8996 feedkeys('', 'xt')
8997 winid = popup_create('Y/N?',
8998 {filter: A.PopupFilter, callback: A.PopupCb})
8999 feedkeys('n', 'xt')
9000 popup_close(winid)
9001 assert_equal(200, A.selection)
9002 assert_equal(['y', 'n'], A.filterkeys)
9003 enddef
9004 Foo()
9005 END
9006 v9.CheckSourceSuccess(lines)
9007enddef
9008
9009" Test for using an object method as a timer callback function
9010def Test_objmethod_timer_callback()
9011 # Use the timer callback from script level
9012 var lines =<< trim END
9013 vim9script
9014
9015 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009016 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009017 def TimerCb(timerID: number)
9018 this.timerTick = 6
9019 enddef
9020 endclass
9021
9022 var a = A.new()
9023 timer_start(0, a.TimerCb)
9024 var maxWait = 5
9025 while maxWait > 0 && a.timerTick == -1
9026 :sleep 10m
9027 maxWait -= 1
9028 endwhile
9029 assert_equal(6, a.timerTick)
9030 END
9031 v9.CheckSourceSuccess(lines)
9032
9033 # Use the timer callback from a def function
9034 lines =<< trim END
9035 vim9script
9036
9037 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009038 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009039 def TimerCb(timerID: number)
9040 this.timerTick = 6
9041 enddef
9042 endclass
9043
9044 def Foo()
9045 var a = A.new()
9046 timer_start(0, a.TimerCb)
9047 var maxWait = 5
9048 while maxWait > 0 && a.timerTick == -1
9049 :sleep 10m
9050 maxWait -= 1
9051 endwhile
9052 assert_equal(6, a.timerTick)
9053 enddef
9054 Foo()
9055 END
9056 v9.CheckSourceSuccess(lines)
9057enddef
9058
9059" Test for using a class method as a timer callback function
9060def Test_classmethod_timer_callback()
9061 # Use the timer callback from script level
9062 var lines =<< trim END
9063 vim9script
9064
9065 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009066 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009067 static def TimerCb(timerID: number)
9068 timerTick = 6
9069 enddef
9070 endclass
9071
9072 timer_start(0, A.TimerCb)
9073 var maxWait = 5
9074 while maxWait > 0 && A.timerTick == -1
9075 :sleep 10m
9076 maxWait -= 1
9077 endwhile
9078 assert_equal(6, A.timerTick)
9079 END
9080 v9.CheckSourceSuccess(lines)
9081
9082 # Use the timer callback from a def function
9083 lines =<< trim END
9084 vim9script
9085
9086 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009087 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009088 static def TimerCb(timerID: number)
9089 timerTick = 6
9090 enddef
9091 endclass
9092
9093 def Foo()
9094 timer_start(0, A.TimerCb)
9095 var maxWait = 5
9096 while maxWait > 0 && A.timerTick == -1
9097 :sleep 10m
9098 maxWait -= 1
9099 endwhile
9100 assert_equal(6, A.timerTick)
9101 enddef
9102 Foo()
9103 END
9104 v9.CheckSourceSuccess(lines)
9105enddef
9106
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009107" Test for using a class variable as the first and/or second operand of a binary
9108" operator.
9109def Test_class_variable_as_operands()
9110 var lines =<< trim END
9111 vim9script
9112 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009113 static var truthy: bool = true
9114 public static var TruthyFn: func
9115 static var list: list<any> = []
9116 static var four: number = 4
9117 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009118
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009119 static def Str(): string
9120 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009121 enddef
9122
9123 static def Four(): number
9124 return four
9125 enddef
9126
9127 static def List(): list<any>
9128 return list
9129 enddef
9130
9131 static def Truthy(): bool
9132 return truthy
9133 enddef
9134
9135 def TestOps()
9136 assert_true(Tests.truthy == truthy)
9137 assert_true(truthy == Tests.truthy)
9138 assert_true(Tests.list isnot [])
9139 assert_true([] isnot Tests.list)
9140 assert_equal(2, Tests.four >> 1)
9141 assert_equal(16, 1 << Tests.four)
9142 assert_equal(8, Tests.four + four)
9143 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009144 assert_equal('hellohello', Tests.str .. str)
9145 assert_equal('hellohello', str .. Tests.str)
9146
9147 # Using class variable for list indexing
9148 var l = range(10)
9149 assert_equal(4, l[Tests.four])
9150 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9151
9152 # Using class variable for Dict key
9153 var d = {hello: 'abc'}
9154 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009155 enddef
9156 endclass
9157
9158 def TestOps2()
9159 assert_true(Tests.truthy == Tests.Truthy())
9160 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009161 assert_true(Tests.truthy == Tests.TruthyFn())
9162 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009163 assert_true(Tests.list is Tests.List())
9164 assert_true(Tests.List() is Tests.list)
9165 assert_equal(2, Tests.four >> 1)
9166 assert_equal(16, 1 << Tests.four)
9167 assert_equal(8, Tests.four + Tests.Four())
9168 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009169 assert_equal('hellohello', Tests.str .. Tests.Str())
9170 assert_equal('hellohello', Tests.Str() .. Tests.str)
9171
9172 # Using class variable for list indexing
9173 var l = range(10)
9174 assert_equal(4, l[Tests.four])
9175 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9176
9177 # Using class variable for Dict key
9178 var d = {hello: 'abc'}
9179 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009180 enddef
9181
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009182 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009183 var t = Tests.new()
9184 t.TestOps()
9185 TestOps2()
9186
9187 assert_true(Tests.truthy == Tests.Truthy())
9188 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009189 assert_true(Tests.truthy == Tests.TruthyFn())
9190 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009191 assert_true(Tests.list is Tests.List())
9192 assert_true(Tests.List() is Tests.list)
9193 assert_equal(2, Tests.four >> 1)
9194 assert_equal(16, 1 << Tests.four)
9195 assert_equal(8, Tests.four + Tests.Four())
9196 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009197 assert_equal('hellohello', Tests.str .. Tests.Str())
9198 assert_equal('hellohello', Tests.Str() .. Tests.str)
9199
9200 # Using class variable for list indexing
9201 var l = range(10)
9202 assert_equal(4, l[Tests.four])
9203 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9204
9205 # Using class variable for Dict key
9206 var d = {hello: 'abc'}
9207 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009208 END
9209 v9.CheckSourceSuccess(lines)
9210enddef
9211
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009212" Test for checking the type of the key used to access an object dict member.
9213def Test_dict_member_key_type_check()
9214 var lines =<< trim END
9215 vim9script
9216
9217 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009218 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009219 endclass
9220
9221 class Test extends State
9222 def ObjMethodTests()
9223 var cursor: number = 0
9224 var z: number = 0
9225 [this.numbers[cursor]] = ['zero.1']
9226 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9227 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9228 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9229 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9230 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9231 [this.numbers[cursor], z] = ['zero.4', 1]
9232 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9233 [z, this.numbers[cursor]] = [1, 'zero.5']
9234 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9235 enddef
9236
9237 static def ClassMethodTests(that: State)
9238 var cursor: number = 0
9239 var z: number = 0
9240 [that.numbers[cursor]] = ['zero.1']
9241 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9242 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9243 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9244 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9245 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9246 [that.numbers[cursor], z] = ['zero.4', 1]
9247 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9248 [z, that.numbers[cursor]] = [1, 'zero.5']
9249 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9250 enddef
9251
9252 def new()
9253 enddef
9254
9255 def newMethodTests()
9256 var cursor: number = 0
9257 var z: number
9258 [this.numbers[cursor]] = ['zero.1']
9259 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9260 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9261 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9262 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9263 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9264 [this.numbers[cursor], z] = ['zero.4', 1]
9265 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9266 [z, this.numbers[cursor]] = [1, 'zero.5']
9267 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9268 enddef
9269 endclass
9270
9271 def DefFuncTests(that: Test)
9272 var cursor: number = 0
9273 var z: number
9274 [that.numbers[cursor]] = ['zero.1']
9275 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9276 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9277 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9278 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9279 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9280 [that.numbers[cursor], z] = ['zero.4', 1]
9281 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9282 [z, that.numbers[cursor]] = [1, 'zero.5']
9283 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9284 enddef
9285
9286 Test.newMethodTests()
9287 Test.new().ObjMethodTests()
9288 Test.ClassMethodTests(Test.new())
9289 DefFuncTests(Test.new())
9290
9291 const test: Test = Test.new()
9292 var cursor: number = 0
9293 [test.numbers[cursor], cursor] = ['zero', 1]
9294 [cursor, test.numbers[cursor]] = [1, 'one']
9295 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9296 END
9297 v9.CheckSourceSuccess(lines)
9298
9299 lines =<< trim END
9300 vim9script
9301
9302 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009303 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009304
9305 def new()
9306 enddef
9307
9308 def Foo()
9309 var z: number
9310 [this.numbers.a, z] = [{}, 10]
9311 enddef
9312 endclass
9313
9314 var a = A.new()
9315 a.Foo()
9316 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009317 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009318
9319 lines =<< trim END
9320 vim9script
9321
9322 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009323 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009324
9325 def new()
9326 enddef
9327
9328 def Foo()
9329 var x: string = 'a'
9330 var y: number
9331 [this.numbers[x], y] = [{}, 10]
9332 enddef
9333 endclass
9334
9335 var a = A.new()
9336 a.Foo()
9337 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009338 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009339enddef
9340
mityua5550692023-11-25 15:41:20 +01009341def Test_compile_many_def_functions_in_funcref_instr()
9342 # This used to crash Vim. This is reproducible only when run on new instance
9343 # of Vim.
9344 var lines =<< trim END
9345 vim9script
9346
9347 class A
9348 def new()
9349 this.TakeFunc(this.F00)
9350 enddef
9351
9352 def TakeFunc(F: func)
9353 enddef
9354
9355 def F00()
9356 this.F01()
9357 this.F02()
9358 this.F03()
9359 this.F04()
9360 this.F05()
9361 this.F06()
9362 this.F07()
9363 this.F08()
9364 this.F09()
9365 this.F10()
9366 this.F11()
9367 this.F12()
9368 this.F13()
9369 this.F14()
9370 this.F15()
9371 this.F16()
9372 this.F17()
9373 this.F18()
9374 this.F19()
9375 this.F20()
9376 this.F21()
9377 this.F22()
9378 this.F23()
9379 this.F24()
9380 this.F25()
9381 this.F26()
9382 this.F27()
9383 this.F28()
9384 this.F29()
9385 this.F30()
9386 this.F31()
9387 this.F32()
9388 this.F33()
9389 this.F34()
9390 this.F35()
9391 this.F36()
9392 this.F37()
9393 this.F38()
9394 this.F39()
9395 this.F40()
9396 this.F41()
9397 this.F42()
9398 this.F43()
9399 this.F44()
9400 this.F45()
9401 this.F46()
9402 this.F47()
9403 enddef
9404
9405 def F01()
9406 enddef
9407 def F02()
9408 enddef
9409 def F03()
9410 enddef
9411 def F04()
9412 enddef
9413 def F05()
9414 enddef
9415 def F06()
9416 enddef
9417 def F07()
9418 enddef
9419 def F08()
9420 enddef
9421 def F09()
9422 enddef
9423 def F10()
9424 enddef
9425 def F11()
9426 enddef
9427 def F12()
9428 enddef
9429 def F13()
9430 enddef
9431 def F14()
9432 enddef
9433 def F15()
9434 enddef
9435 def F16()
9436 enddef
9437 def F17()
9438 enddef
9439 def F18()
9440 enddef
9441 def F19()
9442 enddef
9443 def F20()
9444 enddef
9445 def F21()
9446 enddef
9447 def F22()
9448 enddef
9449 def F23()
9450 enddef
9451 def F24()
9452 enddef
9453 def F25()
9454 enddef
9455 def F26()
9456 enddef
9457 def F27()
9458 enddef
9459 def F28()
9460 enddef
9461 def F29()
9462 enddef
9463 def F30()
9464 enddef
9465 def F31()
9466 enddef
9467 def F32()
9468 enddef
9469 def F33()
9470 enddef
9471 def F34()
9472 enddef
9473 def F35()
9474 enddef
9475 def F36()
9476 enddef
9477 def F37()
9478 enddef
9479 def F38()
9480 enddef
9481 def F39()
9482 enddef
9483 def F40()
9484 enddef
9485 def F41()
9486 enddef
9487 def F42()
9488 enddef
9489 def F43()
9490 enddef
9491 def F44()
9492 enddef
9493 def F45()
9494 enddef
9495 def F46()
9496 enddef
9497 def F47()
9498 enddef
9499 endclass
9500
9501 A.new()
9502 END
9503 writefile(lines, 'Xscript', 'D')
9504 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9505 assert_equal(0, v:shell_error)
9506enddef
9507
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009508" Test for 'final' class and object variables
9509def Test_final_class_object_variable()
9510 # Test for changing a final object variable from an object function
9511 var lines =<< trim END
9512 vim9script
9513 class A
9514 final foo: string = "abc"
9515 def Foo()
9516 this.foo = "def"
9517 enddef
9518 endclass
9519 defcompile A.Foo
9520 END
9521 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9522
9523 # Test for changing a final object variable from the 'new' function
9524 lines =<< trim END
9525 vim9script
9526 class A
9527 final s1: string
9528 final s2: string
9529 def new(this.s1)
9530 this.s2 = 'def'
9531 enddef
9532 endclass
9533 var a = A.new('abc')
9534 assert_equal('abc', a.s1)
9535 assert_equal('def', a.s2)
9536 END
9537 v9.CheckSourceSuccess(lines)
9538
9539 # Test for a final class variable
9540 lines =<< trim END
9541 vim9script
9542 class A
9543 static final s1: string = "abc"
9544 endclass
9545 assert_equal('abc', A.s1)
9546 END
9547 v9.CheckSourceSuccess(lines)
9548
9549 # Test for changing a final class variable from a class function
9550 lines =<< trim END
9551 vim9script
9552 class A
9553 static final s1: string = "abc"
9554 static def Foo()
9555 s1 = "def"
9556 enddef
9557 endclass
9558 A.Foo()
9559 END
9560 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9561
9562 # Test for changing a public final class variable at script level
9563 lines =<< trim END
9564 vim9script
9565 class A
9566 public static final s1: string = "abc"
9567 endclass
9568 assert_equal('abc', A.s1)
9569 A.s1 = 'def'
9570 END
9571 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9572
9573 # Test for changing a public final class variable from a class function
9574 lines =<< trim END
9575 vim9script
9576 class A
9577 public static final s1: string = "abc"
9578 static def Foo()
9579 s1 = "def"
9580 enddef
9581 endclass
9582 A.Foo()
9583 END
9584 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9585
9586 # Test for changing a public final class variable from a function
9587 lines =<< trim END
9588 vim9script
9589 class A
9590 public static final s1: string = "abc"
9591 endclass
9592 def Foo()
9593 A.s1 = 'def'
9594 enddef
9595 defcompile
9596 END
9597 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9598
9599 # Test for using a final variable of composite type
9600 lines =<< trim END
9601 vim9script
9602 class A
9603 public final l: list<number>
9604 def new()
9605 this.l = [1, 2]
9606 enddef
9607 def Foo()
9608 this.l[0] = 3
9609 this.l->add(4)
9610 enddef
9611 endclass
9612 var a = A.new()
9613 assert_equal([1, 2], a.l)
9614 a.Foo()
9615 assert_equal([3, 2, 4], a.l)
9616 END
9617 v9.CheckSourceSuccess(lines)
9618
9619 # Test for changing a final variable of composite type from another object
9620 # function
9621 lines =<< trim END
9622 vim9script
9623 class A
9624 public final l: list<number> = [1, 2]
9625 def Foo()
9626 this.l = [3, 4]
9627 enddef
9628 endclass
9629 var a = A.new()
9630 a.Foo()
9631 END
9632 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9633
9634 # Test for modifying a final variable of composite type at script level
9635 lines =<< trim END
9636 vim9script
9637 class A
9638 public final l: list<number> = [1, 2]
9639 endclass
9640 var a = A.new()
9641 a.l[0] = 3
9642 a.l->add(4)
9643 assert_equal([3, 2, 4], a.l)
9644 END
9645 v9.CheckSourceSuccess(lines)
9646
9647 # Test for modifying a final variable of composite type from a function
9648 lines =<< trim END
9649 vim9script
9650 class A
9651 public final l: list<number> = [1, 2]
9652 endclass
9653 def Foo()
9654 var a = A.new()
9655 a.l[0] = 3
9656 a.l->add(4)
9657 assert_equal([3, 2, 4], a.l)
9658 enddef
9659 Foo()
9660 END
9661 v9.CheckSourceSuccess(lines)
9662
9663 # Test for modifying a final variable of composite type from another object
9664 # function
9665 lines =<< trim END
9666 vim9script
9667 class A
9668 public final l: list<number> = [1, 2]
9669 def Foo()
9670 this.l[0] = 3
9671 this.l->add(4)
9672 enddef
9673 endclass
9674 var a = A.new()
9675 a.Foo()
9676 assert_equal([3, 2, 4], a.l)
9677 END
9678 v9.CheckSourceSuccess(lines)
9679
9680 # Test for assigning a new value to a final variable of composite type at
9681 # script level
9682 lines =<< trim END
9683 vim9script
9684 class A
9685 public final l: list<number> = [1, 2]
9686 endclass
9687 var a = A.new()
9688 a.l = [3, 4]
9689 END
9690 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
9691
9692 # Test for assigning a new value to a final variable of composite type from
9693 # another object function
9694 lines =<< trim END
9695 vim9script
9696 class A
9697 public final l: list<number> = [1, 2]
9698 def Foo()
9699 this.l = [3, 4]
9700 enddef
9701 endclass
9702 var a = A.new()
9703 a.Foo()
9704 END
9705 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9706
9707 # Test for assigning a new value to a final variable of composite type from
9708 # another function
9709 lines =<< trim END
9710 vim9script
9711 class A
9712 public final l: list<number> = [1, 2]
9713 endclass
9714 def Foo()
9715 var a = A.new()
9716 a.l = [3, 4]
9717 enddef
9718 Foo()
9719 END
9720 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
9721
9722 # Error case: Use 'final' with just a variable name
9723 lines =<< trim END
9724 vim9script
9725 class A
9726 final foo
9727 endclass
9728 var a = A.new()
9729 END
9730 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9731
9732 # Error case: Use 'final' followed by 'public'
9733 lines =<< trim END
9734 vim9script
9735 class A
9736 final public foo: number
9737 endclass
9738 var a = A.new()
9739 END
9740 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9741
9742 # Error case: Use 'final' followed by 'static'
9743 lines =<< trim END
9744 vim9script
9745 class A
9746 final static foo: number
9747 endclass
9748 var a = A.new()
9749 END
9750 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9751
9752 # Error case: 'final' cannot be used in an interface
9753 lines =<< trim END
9754 vim9script
9755 interface A
9756 final foo: number = 10
9757 endinterface
9758 END
9759 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
9760
9761 # Error case: 'final' not supported for an object method
9762 lines =<< trim END
9763 vim9script
9764 class A
9765 final def Foo()
9766 enddef
9767 endclass
9768 END
9769 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9770
9771 # Error case: 'final' not supported for a class method
9772 lines =<< trim END
9773 vim9script
9774 class A
9775 static final def Foo()
9776 enddef
9777 endclass
9778 END
9779 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9780enddef
9781
9782" Test for 'const' class and object variables
9783def Test_const_class_object_variable()
9784 # Test for changing a const object variable from an object function
9785 var lines =<< trim END
9786 vim9script
9787 class A
9788 const foo: string = "abc"
9789 def Foo()
9790 this.foo = "def"
9791 enddef
9792 endclass
9793 defcompile A.Foo
9794 END
9795 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9796
9797 # Test for changing a const object variable from the 'new' function
9798 lines =<< trim END
9799 vim9script
9800 class A
9801 const s1: string
9802 const s2: string
9803 def new(this.s1)
9804 this.s2 = 'def'
9805 enddef
9806 endclass
9807 var a = A.new('abc')
9808 assert_equal('abc', a.s1)
9809 assert_equal('def', a.s2)
9810 END
9811 v9.CheckSourceSuccess(lines)
9812
9813 # Test for changing a const object variable from an object method called from
9814 # the 'new' function
9815 lines =<< trim END
9816 vim9script
9817 class A
9818 const s1: string = 'abc'
9819 def new()
9820 this.ChangeStr()
9821 enddef
9822 def ChangeStr()
9823 this.s1 = 'def'
9824 enddef
9825 endclass
9826 var a = A.new()
9827 END
9828 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9829
9830 # Test for a const class variable
9831 lines =<< trim END
9832 vim9script
9833 class A
9834 static const s1: string = "abc"
9835 endclass
9836 assert_equal('abc', A.s1)
9837 END
9838 v9.CheckSourceSuccess(lines)
9839
9840 # Test for changing a const class variable from a class function
9841 lines =<< trim END
9842 vim9script
9843 class A
9844 static const s1: string = "abc"
9845 static def Foo()
9846 s1 = "def"
9847 enddef
9848 endclass
9849 A.Foo()
9850 END
9851 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9852
9853 # Test for changing a public const class variable at script level
9854 lines =<< trim END
9855 vim9script
9856 class A
9857 public static const s1: string = "abc"
9858 endclass
9859 assert_equal('abc', A.s1)
9860 A.s1 = 'def'
9861 END
9862 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9863
9864 # Test for changing a public const class variable from a class function
9865 lines =<< trim END
9866 vim9script
9867 class A
9868 public static const s1: string = "abc"
9869 static def Foo()
9870 s1 = "def"
9871 enddef
9872 endclass
9873 A.Foo()
9874 END
9875 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9876
9877 # Test for changing a public const class variable from a function
9878 lines =<< trim END
9879 vim9script
9880 class A
9881 public static const s1: string = "abc"
9882 endclass
9883 def Foo()
9884 A.s1 = 'def'
9885 enddef
9886 defcompile
9887 END
9888 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9889
9890 # Test for changing a const List item from an object function
9891 lines =<< trim END
9892 vim9script
9893 class A
9894 public const l: list<number>
9895 def new()
9896 this.l = [1, 2]
9897 enddef
9898 def Foo()
9899 this.l[0] = 3
9900 enddef
9901 endclass
9902 var a = A.new()
9903 assert_equal([1, 2], a.l)
9904 a.Foo()
9905 END
9906 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
9907
9908 # Test for adding a value to a const List from an object function
9909 lines =<< trim END
9910 vim9script
9911 class A
9912 public const l: list<number>
9913 def new()
9914 this.l = [1, 2]
9915 enddef
9916 def Foo()
9917 this.l->add(3)
9918 enddef
9919 endclass
9920 var a = A.new()
9921 a.Foo()
9922 END
9923 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
9924
9925 # Test for reassigning a const List from an object function
9926 lines =<< trim END
9927 vim9script
9928 class A
9929 public const l: list<number> = [1, 2]
9930 def Foo()
9931 this.l = [3, 4]
9932 enddef
9933 endclass
9934 var a = A.new()
9935 a.Foo()
9936 END
9937 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9938
9939 # Test for changing a const List item at script level
9940 lines =<< trim END
9941 vim9script
9942 class A
9943 public const l: list<number> = [1, 2]
9944 endclass
9945 var a = A.new()
9946 a.l[0] = 3
9947 END
9948 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
9949
9950 # Test for adding a value to a const List item at script level
9951 lines =<< trim END
9952 vim9script
9953 class A
9954 public const l: list<number> = [1, 2]
9955 endclass
9956 var a = A.new()
9957 a.l->add(4)
9958 END
9959 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
9960
9961 # Test for changing a const List item from a function
9962 lines =<< trim END
9963 vim9script
9964 class A
9965 public const l: list<number> = [1, 2]
9966 endclass
9967 def Foo()
9968 var a = A.new()
9969 a.l[0] = 3
9970 enddef
9971 Foo()
9972 END
9973 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
9974
9975 # Test for adding a value to a const List item from a function
9976 lines =<< trim END
9977 vim9script
9978 class A
9979 public const l: list<number> = [1, 2]
9980 endclass
9981 def Foo()
9982 var a = A.new()
9983 a.l->add(4)
9984 enddef
9985 Foo()
9986 END
9987 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
9988
9989 # Test for changing a const List item from an object method
9990 lines =<< trim END
9991 vim9script
9992 class A
9993 public const l: list<number> = [1, 2]
9994 def Foo()
9995 this.l[0] = 3
9996 enddef
9997 endclass
9998 var a = A.new()
9999 a.Foo()
10000 END
10001 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10002
10003 # Test for adding a value to a const List item from an object method
10004 lines =<< trim END
10005 vim9script
10006 class A
10007 public const l: list<number> = [1, 2]
10008 def Foo()
10009 this.l->add(4)
10010 enddef
10011 endclass
10012 var a = A.new()
10013 a.Foo()
10014 END
10015 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10016
10017 # Test for reassigning a const List object variable at script level
10018 lines =<< trim END
10019 vim9script
10020 class A
10021 public const l: list<number> = [1, 2]
10022 endclass
10023 var a = A.new()
10024 a.l = [3, 4]
10025 END
10026 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10027
10028 # Test for reassigning a const List object variable from an object method
10029 lines =<< trim END
10030 vim9script
10031 class A
10032 public const l: list<number> = [1, 2]
10033 def Foo()
10034 this.l = [3, 4]
10035 enddef
10036 endclass
10037 var a = A.new()
10038 a.Foo()
10039 END
10040 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10041
10042 # Test for reassigning a const List object variable from another function
10043 lines =<< trim END
10044 vim9script
10045 class A
10046 public const l: list<number> = [1, 2]
10047 endclass
10048 def Foo()
10049 var a = A.new()
10050 a.l = [3, 4]
10051 enddef
10052 Foo()
10053 END
10054 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10055
10056 # Error case: Use 'const' with just a variable name
10057 lines =<< trim END
10058 vim9script
10059 class A
10060 const foo
10061 endclass
10062 var a = A.new()
10063 END
10064 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10065
10066 # Error case: Use 'const' followed by 'public'
10067 lines =<< trim END
10068 vim9script
10069 class A
10070 const public foo: number
10071 endclass
10072 var a = A.new()
10073 END
10074 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10075
10076 # Error case: Use 'const' followed by 'static'
10077 lines =<< trim END
10078 vim9script
10079 class A
10080 const static foo: number
10081 endclass
10082 var a = A.new()
10083 END
10084 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10085
10086 # Error case: 'const' cannot be used in an interface
10087 lines =<< trim END
10088 vim9script
10089 interface A
10090 const foo: number = 10
10091 endinterface
10092 END
10093 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10094
10095 # Error case: 'const' not supported for an object method
10096 lines =<< trim END
10097 vim9script
10098 class A
10099 const def Foo()
10100 enddef
10101 endclass
10102 END
10103 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10104
10105 # Error case: 'const' not supported for a class method
10106 lines =<< trim END
10107 vim9script
10108 class A
10109 static const def Foo()
10110 enddef
10111 endclass
10112 END
10113 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10114enddef
10115
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010116" Test for compiling class/object methods using :defcompile
10117def Test_defcompile_class()
10118 # defcompile all the classes in the current script
10119 var lines =<< trim END
10120 vim9script
10121 class A
10122 def Foo()
10123 var i = 10
10124 enddef
10125 endclass
10126 class B
10127 def Bar()
10128 var i = 20
10129 xxx
10130 enddef
10131 endclass
10132 defcompile
10133 END
10134 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10135
10136 # defcompile a specific class
10137 lines =<< trim END
10138 vim9script
10139 class A
10140 def Foo()
10141 xxx
10142 enddef
10143 endclass
10144 class B
10145 def Bar()
10146 yyy
10147 enddef
10148 endclass
10149 defcompile B
10150 END
10151 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10152
10153 # defcompile a non-class
10154 lines =<< trim END
10155 vim9script
10156 class A
10157 def Foo()
10158 enddef
10159 endclass
10160 var X: list<number> = []
10161 defcompile X
10162 END
10163 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10164
10165 # defcompile a class twice
10166 lines =<< trim END
10167 vim9script
10168 class A
10169 def new()
10170 enddef
10171 endclass
10172 defcompile A
10173 defcompile A
10174 assert_equal('Function A.new does not need compiling', v:statusmsg)
10175 END
10176 v9.CheckSourceSuccess(lines)
10177
10178 # defcompile should not compile an imported class
10179 lines =<< trim END
10180 vim9script
10181 export class A
10182 def Foo()
10183 xxx
10184 enddef
10185 endclass
10186 END
10187 writefile(lines, 'Xdefcompileimport.vim', 'D')
10188 lines =<< trim END
10189 vim9script
10190
10191 import './Xdefcompileimport.vim'
10192 class B
10193 endclass
10194 defcompile
10195 END
10196 v9.CheckScriptSuccess(lines)
10197enddef
10198
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010199" Test for cases common to all the object builtin methods
10200def Test_object_builtin_method()
10201 var lines =<< trim END
10202 vim9script
10203 class A
10204 def abc()
10205 enddef
10206 endclass
10207 END
10208 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10209
10210 for funcname in ["len", "string", "empty"]
10211 lines =<< trim eval END
10212 vim9script
10213 class A
10214 static def {funcname}(): number
10215 enddef
10216 endclass
10217 END
10218 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10219 endfor
10220enddef
10221
10222" Test for using the empty() builtin method with an object
10223" This is a legacy function to use the test_garbagecollect_now() function.
10224func Test_object_empty()
10225 let lines =<< trim END
10226 vim9script
10227 class A
10228 def empty(): bool
10229 return true
10230 enddef
10231 endclass
10232
10233 def Foo()
10234 var afoo = A.new()
10235 assert_equal(true, empty(afoo))
10236 assert_equal(true, afoo->empty())
10237 enddef
10238
10239 var a = A.new()
10240 assert_equal(1, empty(a))
10241 assert_equal(1, a->empty())
10242 test_garbagecollect_now()
10243 assert_equal(1, empty(a))
10244 Foo()
10245 test_garbagecollect_now()
10246 Foo()
10247 END
10248 call v9.CheckSourceSuccess(lines)
10249
10250 " empty() should return 1 without a builtin method
10251 let lines =<< trim END
10252 vim9script
10253 class A
10254 endclass
10255
10256 def Foo()
10257 var afoo = A.new()
10258 assert_equal(1, empty(afoo))
10259 enddef
10260
10261 var a = A.new()
10262 assert_equal(1, empty(a))
10263 Foo()
10264 END
10265 call v9.CheckSourceSuccess(lines)
10266
10267 " Unsupported signature for the empty() method
10268 let lines =<< trim END
10269 vim9script
10270 class A
10271 def empty()
10272 enddef
10273 endclass
10274 END
10275 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10276
10277 " Error when calling the empty() method
10278 let lines =<< trim END
10279 vim9script
10280 class A
10281 def empty(): bool
10282 throw "Failed to check emptiness"
10283 enddef
10284 endclass
10285
10286 def Foo()
10287 var afoo = A.new()
10288 var i = empty(afoo)
10289 enddef
10290
10291 var a = A.new()
10292 assert_fails('empty(a)', 'Failed to check emptiness')
10293 assert_fails('Foo()', 'Failed to check emptiness')
10294 END
10295 call v9.CheckSourceSuccess(lines)
10296
10297 " call empty() using an object from a script
10298 let lines =<< trim END
10299 vim9script
10300 class A
10301 def empty(): bool
10302 return true
10303 enddef
10304 endclass
10305 var afoo = A.new()
10306 assert_equal(true, afoo.empty())
10307 END
10308 call v9.CheckSourceSuccess(lines)
10309
10310 " call empty() using an object from a method
10311 let lines =<< trim END
10312 vim9script
10313 class A
10314 def empty(): bool
10315 return true
10316 enddef
10317 endclass
10318 def Foo()
10319 var afoo = A.new()
10320 assert_equal(true, afoo.empty())
10321 enddef
10322 Foo()
10323 END
10324 call v9.CheckSourceSuccess(lines)
10325
10326 " call empty() using "this" from an object method
10327 let lines =<< trim END
10328 vim9script
10329 class A
10330 def empty(): bool
10331 return true
10332 enddef
10333 def Foo(): bool
10334 return this.empty()
10335 enddef
10336 endclass
10337 def Bar()
10338 var abar = A.new()
10339 assert_equal(true, abar.Foo())
10340 enddef
10341 Bar()
10342 END
10343 call v9.CheckSourceSuccess(lines)
10344
10345 " Call empty() from a derived object
10346 let lines =<< trim END
10347 vim9script
10348 class A
10349 def empty(): bool
10350 return false
10351 enddef
10352 endclass
10353 class B extends A
10354 def empty(): bool
10355 return true
10356 enddef
10357 endclass
10358 def Foo(afoo: A)
10359 assert_equal(true, empty(afoo))
10360 var bfoo = B.new()
10361 assert_equal(true, empty(bfoo))
10362 enddef
10363 var b = B.new()
10364 assert_equal(1, empty(b))
10365 Foo(b)
10366 END
10367 call v9.CheckSourceSuccess(lines)
10368
10369 " Invoking empty method using an interface
10370 let lines =<< trim END
10371 vim9script
10372 interface A
10373 def empty(): bool
10374 endinterface
10375 class B implements A
10376 def empty(): bool
10377 return false
10378 enddef
10379 endclass
10380 def Foo(a: A)
10381 assert_equal(false, empty(a))
10382 enddef
10383 var b = B.new()
10384 Foo(b)
10385 END
10386 call v9.CheckSourceSuccess(lines)
10387endfunc
10388
10389" Test for using the len() builtin method with an object
10390" This is a legacy function to use the test_garbagecollect_now() function.
10391func Test_object_length()
10392 let lines =<< trim END
10393 vim9script
10394 class A
10395 var mylen: number = 0
10396 def new(n: number)
10397 this.mylen = n
10398 enddef
10399 def len(): number
10400 return this.mylen
10401 enddef
10402 endclass
10403
10404 def Foo()
10405 var afoo = A.new(12)
10406 assert_equal(12, len(afoo))
10407 assert_equal(12, afoo->len())
10408 enddef
10409
10410 var a = A.new(22)
10411 assert_equal(22, len(a))
10412 assert_equal(22, a->len())
10413 test_garbagecollect_now()
10414 assert_equal(22, len(a))
10415 Foo()
10416 test_garbagecollect_now()
10417 Foo()
10418 END
10419 call v9.CheckSourceSuccess(lines)
10420
10421 " len() should return 0 without a builtin method
10422 let lines =<< trim END
10423 vim9script
10424 class A
10425 endclass
10426
10427 def Foo()
10428 var afoo = A.new()
10429 assert_equal(0, len(afoo))
10430 enddef
10431
10432 var a = A.new()
10433 assert_equal(0, len(a))
10434 Foo()
10435 END
10436 call v9.CheckSourceSuccess(lines)
10437
10438 " Unsupported signature for the len() method
10439 let lines =<< trim END
10440 vim9script
10441 class A
10442 def len()
10443 enddef
10444 endclass
10445 END
10446 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10447
10448 " Error when calling the len() method
10449 let lines =<< trim END
10450 vim9script
10451 class A
10452 def len(): number
10453 throw "Failed to compute length"
10454 enddef
10455 endclass
10456
10457 def Foo()
10458 var afoo = A.new()
10459 var i = len(afoo)
10460 enddef
10461
10462 var a = A.new()
10463 assert_fails('len(a)', 'Failed to compute length')
10464 assert_fails('Foo()', 'Failed to compute length')
10465 END
10466 call v9.CheckSourceSuccess(lines)
10467
10468 " call len() using an object from a script
10469 let lines =<< trim END
10470 vim9script
10471 class A
10472 def len(): number
10473 return 5
10474 enddef
10475 endclass
10476 var afoo = A.new()
10477 assert_equal(5, afoo.len())
10478 END
10479 call v9.CheckSourceSuccess(lines)
10480
10481 " call len() using an object from a method
10482 let lines =<< trim END
10483 vim9script
10484 class A
10485 def len(): number
10486 return 5
10487 enddef
10488 endclass
10489 def Foo()
10490 var afoo = A.new()
10491 assert_equal(5, afoo.len())
10492 enddef
10493 Foo()
10494 END
10495 call v9.CheckSourceSuccess(lines)
10496
10497 " call len() using "this" from an object method
10498 let lines =<< trim END
10499 vim9script
10500 class A
10501 def len(): number
10502 return 8
10503 enddef
10504 def Foo(): number
10505 return this.len()
10506 enddef
10507 endclass
10508 def Bar()
10509 var abar = A.new()
10510 assert_equal(8, abar.Foo())
10511 enddef
10512 Bar()
10513 END
10514 call v9.CheckSourceSuccess(lines)
10515
10516 " Call len() from a derived object
10517 let lines =<< trim END
10518 vim9script
10519 class A
10520 def len(): number
10521 return 10
10522 enddef
10523 endclass
10524 class B extends A
10525 def len(): number
10526 return 20
10527 enddef
10528 endclass
10529 def Foo(afoo: A)
10530 assert_equal(20, len(afoo))
10531 var bfoo = B.new()
10532 assert_equal(20, len(bfoo))
10533 enddef
10534 var b = B.new()
10535 assert_equal(20, len(b))
10536 Foo(b)
10537 END
10538 call v9.CheckSourceSuccess(lines)
10539
10540 " Invoking len method using an interface
10541 let lines =<< trim END
10542 vim9script
10543 interface A
10544 def len(): number
10545 endinterface
10546 class B implements A
10547 def len(): number
10548 return 123
10549 enddef
10550 endclass
10551 def Foo(a: A)
10552 assert_equal(123, len(a))
10553 enddef
10554 var b = B.new()
10555 Foo(b)
10556 END
10557 call v9.CheckSourceSuccess(lines)
10558endfunc
10559
10560" Test for using the string() builtin method with an object
10561" This is a legacy function to use the test_garbagecollect_now() function.
10562func Test_object_string()
10563 let lines =<< trim END
10564 vim9script
10565 class A
10566 var name: string
10567 def string(): string
10568 return this.name
10569 enddef
10570 endclass
10571
10572 def Foo()
10573 var afoo = A.new("foo-A")
10574 assert_equal('foo-A', string(afoo))
10575 assert_equal('foo-A', afoo->string())
10576 enddef
10577
10578 var a = A.new("script-A")
10579 assert_equal('script-A', string(a))
10580 assert_equal('script-A', a->string())
10581 assert_equal(['script-A'], execute('echo a')->split("\n"))
10582 test_garbagecollect_now()
10583 assert_equal('script-A', string(a))
10584 Foo()
10585 test_garbagecollect_now()
10586 Foo()
10587 END
10588 call v9.CheckSourceSuccess(lines)
10589
10590 " string() should return "object of A {}" without a builtin method
10591 let lines =<< trim END
10592 vim9script
10593 class A
10594 endclass
10595
10596 def Foo()
10597 var afoo = A.new()
10598 assert_equal('object of A {}', string(afoo))
10599 enddef
10600
10601 var a = A.new()
10602 assert_equal('object of A {}', string(a))
10603 Foo()
10604 END
10605 call v9.CheckSourceSuccess(lines)
10606
10607 " Unsupported signature for the string() method
10608 let lines =<< trim END
10609 vim9script
10610 class A
10611 def string()
10612 enddef
10613 endclass
10614 END
10615 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
10616
10617 " Error when calling the string() method
10618 let lines =<< trim END
10619 vim9script
10620 class A
10621 def string(): string
10622 throw "Failed to get text"
10623 enddef
10624 endclass
10625
10626 def Foo()
10627 var afoo = A.new()
10628 var i = string(afoo)
10629 enddef
10630
10631 var a = A.new()
10632 assert_fails('string(a)', 'Failed to get text')
10633 assert_fails('Foo()', 'Failed to get text')
10634 END
10635 call v9.CheckSourceSuccess(lines)
10636
10637 " call string() using an object from a script
10638 let lines =<< trim END
10639 vim9script
10640 class A
10641 def string(): string
10642 return 'A'
10643 enddef
10644 endclass
10645 var afoo = A.new()
10646 assert_equal('A', afoo.string())
10647 END
10648 call v9.CheckSourceSuccess(lines)
10649
10650 " call string() using an object from a method
10651 let lines =<< trim END
10652 vim9script
10653 class A
10654 def string(): string
10655 return 'A'
10656 enddef
10657 endclass
10658 def Foo()
10659 var afoo = A.new()
10660 assert_equal('A', afoo.string())
10661 enddef
10662 Foo()
10663 END
10664 call v9.CheckSourceSuccess(lines)
10665
10666 " call string() using "this" from an object method
10667 let lines =<< trim END
10668 vim9script
10669 class A
10670 def string(): string
10671 return 'A'
10672 enddef
10673 def Foo(): string
10674 return this.string()
10675 enddef
10676 endclass
10677 def Bar()
10678 var abar = A.new()
10679 assert_equal('A', abar.string())
10680 enddef
10681 Bar()
10682 END
10683 call v9.CheckSourceSuccess(lines)
10684
10685 " Call string() from a derived object
10686 let lines =<< trim END
10687 vim9script
10688 class A
10689 def string(): string
10690 return 'A'
10691 enddef
10692 endclass
10693 class B extends A
10694 def string(): string
10695 return 'B'
10696 enddef
10697 endclass
10698 def Foo(afoo: A)
10699 assert_equal('B', string(afoo))
10700 var bfoo = B.new()
10701 assert_equal('B', string(bfoo))
10702 enddef
10703 var b = B.new()
10704 assert_equal('B', string(b))
10705 Foo(b)
10706 END
10707 call v9.CheckSourceSuccess(lines)
10708
10709 " Invoking string method using an interface
10710 let lines =<< trim END
10711 vim9script
10712 interface A
10713 def string(): string
10714 endinterface
10715 class B implements A
10716 def string(): string
10717 return 'B'
10718 enddef
10719 endclass
10720 def Foo(a: A)
10721 assert_equal('B', string(a))
10722 enddef
10723 var b = B.new()
10724 Foo(b)
10725 END
10726 call v9.CheckSourceSuccess(lines)
10727endfunc
10728
Ernie Rael9d779c52024-07-07 20:41:44 +020010729" Test for using the string() builtin method with an object's method
10730def Test_method_string()
10731 var lines =<< trim END
10732 vim9script
10733 class A
10734 def F()
10735 enddef
10736 endclass
10737 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
10738 END
10739 v9.CheckScriptSuccess(lines)
10740enddef
10741
10742
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010010743" Test for using a class in the class definition
10744def Test_Ref_Class_Within_Same_Class()
10745 var lines =<< trim END
10746 vim9script
10747 class A
10748 var n: number = 0
10749 def Equals(other: A): bool
10750 return this.n == other.n
10751 enddef
10752 endclass
10753
10754 var a1 = A.new(10)
10755 var a2 = A.new(10)
10756 var a3 = A.new(20)
10757 assert_equal(true, a1.Equals(a2))
10758 assert_equal(false, a2.Equals(a3))
10759 END
10760 v9.CheckScriptSuccess(lines)
10761
10762 lines =<< trim END
10763 vim9script
10764
10765 class Foo
10766 var num: number
10767 def Clone(): Foo
10768 return Foo.new(this.num)
10769 enddef
10770 endclass
10771
10772 var f1 = Foo.new(1)
10773
10774 def F()
10775 var f2: Foo = f1.Clone()
10776 assert_equal(false, f2 is f1)
10777 assert_equal(true, f2.num == f1.num)
10778 enddef
10779 F()
10780
10781 var f3: Foo = f1.Clone()
10782 assert_equal(false, f3 is f1)
10783 assert_equal(true, f3.num == f1.num)
10784 END
10785 v9.CheckScriptSuccess(lines)
10786
10787 # Test for trying to use a class to extend when defining the same class
10788 lines =<< trim END
10789 vim9script
10790 class A extends A
10791 endclass
10792 END
10793 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
10794
10795 # Test for trying to use a class to implement when defining the same class
10796 lines =<< trim END
10797 vim9script
10798 class A implements A
10799 endclass
10800 END
10801 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
10802enddef
10803
Ernie Raelf0e69142024-06-22 11:12:00 +020010804" Test for comparing a class referencing itself
10805def Test_Object_Compare_With_Recursive_Class_Ref()
10806 var lines =<< trim END
10807 vim9script
10808
10809 class C
10810 public var nest: C
10811 endclass
10812
10813 var o1 = C.new()
10814 o1.nest = o1
10815
10816 var result = o1 == o1
10817 assert_equal(true, result)
10818 END
10819 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020010820
10821 lines =<< trim END
10822 vim9script
10823
10824 class C
10825 public var nest: C
10826 endclass
10827 var o1 = C.new()
10828 var o2 = C.new(C.new())
10829
10830 var result = o1 == o2
10831 assert_equal(false, result)
10832 END
10833 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020010834
10835 lines =<< trim END
10836 vim9script
10837 class C
10838 var nest1: C
10839 var nest2: C
10840 def Init(n1: C, n2: C)
10841 this.nest1 = n1
10842 this.nest2 = n2
10843 enddef
10844 endclass
10845
10846 var o1 = C.new()
10847 var o2 = C.new()
10848 o1.Init(o1, o2)
10849 o2.Init(o2, o1)
10850
10851 var result = o1 == o2
10852 assert_equal(true, result)
10853 END
10854 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020010855enddef
10856
Ernie Raelf3975492024-07-06 11:44:37 +020010857" Test for comparing a class with nesting objects
10858def Test_Object_Compare_With_Nesting_Objects()
10859 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
10860 # return the compare is equal.
10861 # Test that limit
10862
10863 var lines =<< trim END
10864 vim9script
10865 class C
10866 public var n: number
10867 public var nest: C
10868
10869 # Create a "C" that chains/nests to indicated depth.
10870 # return {head: firstC, tail: lastC}
10871 static def CreateNested(depth: number): dict<C>
10872 var first = C.new(1, null_object)
10873 var last = first
10874 for i in range(2, depth)
10875 last.nest = C.new(i, null_object)
10876 last = last.nest
10877 endfor
10878 return {head: first, tail: last}
10879 enddef
10880
10881 # Return pointer to nth item in chain.
10882 def GetLink(depth: number): C
10883 var count = 1
10884 var p: C = this
10885 while count < depth
10886 p = p.nest
10887 if p == null
10888 throw "too deep"
10889 endif
10890 count += 1
10891 endwhile
10892 return p
10893 enddef
10894
10895 # Return the length of the chain
10896 def len(): number
10897 var count = 1
10898 var p: C = this
10899 while p.nest != null
10900 p = p.nest
10901 count += 1
10902 endwhile
10903 return count
10904 enddef
10905 endclass
10906
10907 var chain = C.CreateNested(3)
10908 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
10909 assert_equal(s, string(chain.head))
10910 assert_equal(3, chain.head->len())
10911
10912 var chain1 = C.CreateNested(100)
10913 var chain2 = C.CreateNested(100)
10914 assert_true(chain1.head == chain2.head)
10915
10916 # modify the tail of chain2, compare not equal
10917 chain2.tail.n = 123456
10918 assert_true(chain1.head != chain2.head)
10919
10920 # a tail of a different length compares not equal
10921 chain2 = C.CreateNested(101)
10922 assert_true(chain1.head != chain2.head)
10923
10924 chain1 = C.CreateNested(1000)
10925 chain2 = C.CreateNested(1000)
10926 assert_true(chain1.head == chain2.head)
10927
10928 # modify the tail of chain2, compare not equal
10929 chain2.tail.n = 123456
10930 assert_true(chain1.head != chain2.head)
10931
10932 # try a chain longer that the limit
10933 chain1 = C.CreateNested(1001)
10934 chain2 = C.CreateNested(1001)
10935 assert_true(chain1.head == chain2.head)
10936
10937 # modify the tail, but still equal
10938 chain2.tail.n = 123456
10939 assert_true(chain1.head == chain2.head)
10940
10941 # remove 2 items from front, shorten the chain by two.
10942 chain1.head = chain1.head.GetLink(3)
10943 chain2.head = chain2.head.GetLink(3)
10944 assert_equal(3, chain1.head.n)
10945 assert_equal(3, chain2.head.n)
10946 assert_equal(999, chain1.head->len())
10947 assert_equal(999, chain2.head->len())
10948 # Now less than the limit, compare not equal
10949 assert_true(chain1.head != chain2.head)
10950 END
10951 v9.CheckScriptSuccess(lines)
10952enddef
10953
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010010954" Test for using a compound operator from a lambda function in an object method
10955def Test_compound_op_in_objmethod_lambda()
10956 # Test using the "+=" operator
10957 var lines =<< trim END
10958 vim9script
10959 class A
10960 var n: number = 10
10961 def Foo()
10962 var Fn = () => {
10963 this.n += 1
10964 }
10965 Fn()
10966 enddef
10967 endclass
10968
10969 var a = A.new()
10970 a.Foo()
10971 assert_equal(11, a.n)
10972 END
10973 v9.CheckScriptSuccess(lines)
10974
10975 # Test using the "..=" operator
10976 lines =<< trim END
10977 vim9script
10978 class A
10979 var s: string = "a"
10980 def Foo()
10981 var Fn = () => {
10982 this.s ..= "a"
10983 }
10984 Fn()
10985 enddef
10986 endclass
10987
10988 var a = A.new()
10989 a.Foo()
10990 a.Foo()
10991 assert_equal("aaa", a.s)
10992 END
10993 v9.CheckScriptSuccess(lines)
10994enddef
10995
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010010996" Test for using test_refcount() with a class and an object
10997def Test_class_object_refcount()
10998 var lines =<< trim END
10999 vim9script
11000 class A
11001 endclass
11002 var a: A = A.new()
11003 assert_equal(2, test_refcount(A))
11004 assert_equal(1, test_refcount(a))
11005 var b = a
11006 assert_equal(2, test_refcount(A))
11007 assert_equal(2, test_refcount(a))
11008 assert_equal(2, test_refcount(b))
11009 END
11010 v9.CheckScriptSuccess(lines)
11011enddef
11012
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011013" call a lambda function in one object from another object
11014def Test_lambda_invocation_across_classes()
11015 var lines =<< trim END
11016 vim9script
11017 class A
11018 var s: string = "foo"
11019 def GetFn(): func
11020 var Fn = (): string => {
11021 return this.s
11022 }
11023 return Fn
11024 enddef
11025 endclass
11026
11027 class B
11028 var s: string = "bar"
11029 def GetFn(): func
11030 var a = A.new()
11031 return a.GetFn()
11032 enddef
11033 endclass
11034
11035 var b = B.new()
11036 var Fn = b.GetFn()
11037 assert_equal("foo", Fn())
11038 END
11039 v9.CheckScriptSuccess(lines)
11040enddef
11041
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011042" Test for using a class member which is an object of the current class
11043def Test_current_class_object_class_member()
11044 var lines =<< trim END
11045 vim9script
11046 class A
11047 public static var obj1: A = A.new(10)
11048 var n: number
11049 endclass
11050 defcompile
11051 assert_equal(10, A.obj1.n)
11052 END
11053 v9.CheckScriptSuccess(lines)
11054enddef
11055
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011056" Test for updating a base class variable from a base class method without the
11057" class name. This used to crash Vim (Github issue #14352).
11058def Test_use_base_class_variable_from_base_class_method()
11059 var lines =<< trim END
11060 vim9script
11061
11062 class DictKeyClass
11063 static var _obj_id_count = 1
11064 def _GenerateKey()
11065 _obj_id_count += 1
11066 enddef
11067 static def GetIdCount(): number
11068 return _obj_id_count
11069 enddef
11070 endclass
11071
11072 class C extends DictKeyClass
11073 def F()
11074 this._GenerateKey()
11075 enddef
11076 endclass
11077
11078 C.new().F()
11079 assert_equal(2, DictKeyClass.GetIdCount())
11080 END
11081 v9.CheckScriptSuccess(lines)
11082enddef
11083
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011084" Test for accessing protected funcref object and class variables
11085def Test_protected_funcref()
11086 # protected funcref object variable
11087 var lines =<< trim END
11088 vim9script
11089 class Test1
11090 const _Id: func(any): any = (v) => v
11091 endclass
11092 var n = Test1.new()._Id(1)
11093 END
11094 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11095
11096 # protected funcref class variable
11097 lines =<< trim END
11098 vim9script
11099 class Test2
11100 static const _Id: func(any): any = (v) => v
11101 endclass
11102 var n = Test2._Id(2)
11103 END
11104 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11105enddef
11106
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011107" Test for using lambda block in classes
11108def Test_lambda_block_in_class()
11109 # This used to crash Vim
11110 var lines =<< trim END
11111 vim9script
11112 class IdClass1
11113 const Id: func(number): number = (num: number): number => {
11114 # Return a ID
11115 return num * 10
11116 }
11117 endclass
11118 var id = IdClass1.new()
11119 assert_equal(20, id.Id(2))
11120 END
11121 v9.CheckScriptSuccess(lines)
11122
11123 # This used to crash Vim
11124 lines =<< trim END
11125 vim9script
11126 class IdClass2
11127 static const Id: func(number): number = (num: number): number => {
11128 # Return a ID
11129 return num * 2
11130 }
11131 endclass
11132 assert_equal(16, IdClass2.Id(8))
11133 END
11134 v9.CheckScriptSuccess(lines)
11135enddef
11136
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011137" Test for defcompiling an abstract method
11138def Test_abstract_method_defcompile()
11139 # Compile an abstract class with abstract object methods
11140 var lines =<< trim END
11141 vim9script
11142 abstract class A
11143 abstract def Foo(): string
11144 abstract def Bar(): list<string>
11145 endclass
11146 defcompile
11147 END
11148 v9.CheckScriptSuccess(lines)
11149
11150 # Compile a concrete object method in an abstract class
11151 lines =<< trim END
11152 vim9script
11153 abstract class A
11154 abstract def Foo(): string
11155 abstract def Bar(): list<string>
11156 def Baz(): string
11157 pass
11158 enddef
11159 endclass
11160 defcompile
11161 END
11162 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11163
11164 # Compile a concrete class method in an abstract class
11165 lines =<< trim END
11166 vim9script
11167 abstract class A
11168 abstract def Foo(): string
11169 abstract def Bar(): list<string>
11170 static def Baz(): string
11171 pass
11172 enddef
11173 endclass
11174 defcompile
11175 END
11176 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11177enddef
11178
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011179" Test for defining a class in a function
11180def Test_class_definition_in_a_function()
11181 var lines =<< trim END
11182 vim9script
11183 def Foo()
11184 class A
11185 endclass
11186 enddef
11187 defcompile
11188 END
11189 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11190enddef
11191
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011192" Test for using [] with a class and an object
11193def Test_class_object_index()
11194 var lines =<< trim END
11195 vim9script
11196 class A
11197 endclass
11198 A[10] = 1
11199 END
11200 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11201
11202 lines =<< trim END
11203 vim9script
11204 class A
11205 endclass
11206 var a = A.new()
11207 a[10] = 1
11208 END
11209 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11210enddef
11211
LemonBoyf4af3312024-07-04 13:43:12 +020011212def Test_class_member_init_typecheck()
11213 # Ensure the class member is assigned its declared type.
11214 var lines =<< trim END
11215 vim9script
11216 class S
11217 static var l: list<string> = []
11218 endclass
11219 S.l->add(123)
11220 END
11221 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11222
11223 # Ensure the initializer value and the declared type match.
11224 lines =<< trim END
11225 vim9script
11226 class S
11227 var l: list<string> = [1, 2, 3]
11228 endclass
11229 var o = S.new()
11230 END
11231 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11232
11233 # Ensure the class member is assigned its declared type.
11234 lines =<< trim END
11235 vim9script
11236 class S
11237 var l: list<string> = []
11238 endclass
11239 var o = S.new()
11240 o.l->add(123)
11241 END
11242 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11243enddef
11244
LemonBoy50d48542024-07-04 17:03:17 +020011245def Test_class_cast()
11246 var lines =<< trim END
11247 vim9script
11248 class A
11249 endclass
11250 class B extends A
11251 var mylen: number
11252 endclass
11253 def F(o: A): number
11254 return (<B>o).mylen
11255 enddef
11256
11257 defcompile F
11258 END
11259 v9.CheckScriptSuccess(lines)
11260enddef
11261
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011262" Test for using a variable of type "any" with an object
11263def Test_any_obj_var_type()
11264 var lines =<< trim END
11265 vim9script
11266 class A
11267 var name: string = "foobar"
11268 def Foo(): string
11269 return "func foo"
11270 enddef
11271 endclass
11272
11273 def CheckVals(x: any)
11274 assert_equal("foobar", x.name)
11275 assert_equal("func foo", x.Foo())
11276 enddef
11277
11278 var a = A.new()
11279 CheckVals(a)
11280 END
11281 v9.CheckScriptSuccess(lines)
11282
11283 # Try to set a non-existing variable
11284 lines =<< trim END
11285 vim9script
11286 class A
11287 var name: string = "foobar"
11288 endclass
11289
11290 def SetNonExistingVar(x: any)
11291 x.bar = [1, 2, 3]
11292 enddef
11293
11294 var a = A.new()
11295 SetNonExistingVar(a)
11296 END
11297 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11298
11299 # Try to read a non-existing variable
11300 lines =<< trim END
11301 vim9script
11302 class A
11303 var name: string = "foobar"
11304 endclass
11305
11306 def GetNonExistingVar(x: any)
11307 var i: dict<any> = x.bar
11308 enddef
11309
11310 var a = A.new()
11311 GetNonExistingVar(a)
11312 END
11313 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11314
11315 # Try to invoke a non-existing method
11316 lines =<< trim END
11317 vim9script
11318 class A
11319 def Foo(): number
11320 return 10
11321 enddef
11322 endclass
11323
11324 def CallNonExistingMethod(x: any)
11325 var i: number = x.Bar()
11326 enddef
11327
11328 var a = A.new()
11329 CallNonExistingMethod(a)
11330 END
11331 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11332
11333 # Use an object which is a Dict value
11334 lines =<< trim END
11335 vim9script
11336 class Foo
11337 def Bar(): number
11338 return 369
11339 enddef
11340 endclass
11341
11342 def GetValue(FooDict: dict<any>): number
11343 var n: number = 0
11344 for foo in values(FooDict)
11345 n += foo.Bar()
11346 endfor
11347 return n
11348 enddef
11349
11350 var d = {'x': Foo.new()}
11351 assert_equal(369, GetValue(d))
11352 END
11353 v9.CheckScriptSuccess(lines)
11354
zeertzjqd32bf0a2024-12-17 20:55:13 +010011355 # Nested data. Object containing a Dict containing another Object.
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011356 lines =<< trim END
11357 vim9script
11358 class Context
11359 public var state: dict<any> = {}
11360 endclass
11361
11362 class Metadata
11363 public var value = 0
11364 endclass
11365
11366 var ctx = Context.new()
11367 ctx.state["meta"] = Metadata.new(2468)
11368
11369 const foo = ctx.state.meta.value
11370
11371 def F(): number
11372 const bar = ctx.state.meta.value
11373 return bar
11374 enddef
11375
11376 assert_equal(2468, F())
11377 END
11378 v9.CheckScriptSuccess(lines)
11379
11380 # Accessing an object from a method inside the class using any type
11381 lines =<< trim END
11382 vim9script
11383 class C
11384 def _G(): string
11385 return '_G'
11386 enddef
11387 static def S(o_any: any): string
11388 return o_any._G()
11389 enddef
11390 endclass
11391
11392 var o1 = C.new()
11393 assert_equal('_G', C.S(o1))
11394 END
11395 v9.CheckScriptSuccess(lines)
11396
11397 # Modifying an object private variable from a method in another class using
11398 # any type
11399 lines =<< trim END
11400 vim9script
11401
11402 class A
11403 var num = 10
11404 endclass
11405
11406 class B
11407 def SetVal(x: any)
11408 x.num = 20
11409 enddef
11410 endclass
11411
11412 var a = A.new()
11413 var b = B.new()
11414 b.SetVal(a)
11415 END
11416 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11417
11418 # Accessing a object protected variable from a method in another class using
11419 # any type
11420 lines =<< trim END
11421 vim9script
11422
11423 class A
11424 var _num = 10
11425 endclass
11426
11427 class B
11428 def GetVal(x: any): number
11429 return x._num
11430 enddef
11431 endclass
11432
11433 var a = A.new()
11434 var b = B.new()
11435 var i = b.GetVal(a)
11436 END
11437 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11438
11439 # Accessing an object returned from an imported function and class
11440 lines =<< trim END
11441 vim9script
11442 export class Foo
11443 public var name: string
11444 endclass
11445
11446 export def ReturnFooObject(): Foo
11447 var r = Foo.new('star')
11448 return r
11449 enddef
11450 END
11451 writefile(lines, 'Xanyvar1.vim', 'D')
11452
11453 lines =<< trim END
11454 vim9script
11455
11456 import './Xanyvar1.vim'
11457
11458 def GetName(): string
11459 var whatever = Xanyvar1.ReturnFooObject()
11460 return whatever.name
11461 enddef
11462
11463 assert_equal('star', GetName())
11464 END
11465 v9.CheckScriptSuccess(lines)
11466
11467 # Try to modify a private object variable using a variable of type "any"
11468 lines =<< trim END
11469 vim9script
11470
11471 class Foo
11472 var n: number = 10
11473 endclass
11474 def Fn(x: any)
11475 x.n = 20
11476 enddef
11477 var a = Foo.new()
11478 Fn(a)
11479 END
11480 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11481
11482 # Try to read a protected object variable using a variable of type "any"
11483 lines =<< trim END
11484 vim9script
11485
11486 class Foo
11487 var _n: number = 10
11488 endclass
11489 def Fn(x: any): number
11490 return x._n
11491 enddef
11492
11493 var a = Foo.new()
11494 Fn(a)
11495 END
11496 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11497
11498 # Read a protected object variable using a variable of type "any" in an object
11499 # method
11500 lines =<< trim END
11501 vim9script
11502
11503 class Foo
11504 var _n: number = 10
11505 def Fn(x: any): number
11506 return x._n
11507 enddef
11508 endclass
11509
11510 var a = Foo.new()
11511 assert_equal(10, a.Fn(a))
11512 END
11513 v9.CheckScriptSuccess(lines)
11514
11515 # Try to call a protected object method using a "any" type variable
11516 lines =<< trim END
11517 vim9script
11518
11519 class Foo
11520 def _GetVal(): number
11521 return 234
11522 enddef
11523 endclass
11524 def Fn(x: any): number
11525 return x._GetVal()
11526 enddef
11527
11528 var a = Foo.new()
11529 Fn(a)
11530 END
11531 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11532
11533 # Call a protected object method using a "any" type variable from another
11534 # object method
11535 lines =<< trim END
11536 vim9script
11537
11538 class Foo
11539 def _GetVal(): number
11540 return 234
11541 enddef
11542 def FooVal(x: any): number
11543 return x._GetVal()
11544 enddef
11545 endclass
11546
11547 var a = Foo.new()
11548 assert_equal(234, a.FooVal(a))
11549 END
11550 v9.CheckScriptSuccess(lines)
11551
11552 # Method chaining
11553 lines =<< trim END
11554 vim9script
11555
11556 export class T
11557 var id: number = 268
11558 def F(): any
11559 return this
11560 enddef
11561 endclass
11562
11563 def H()
11564 var a = T.new().F().F()
11565 assert_equal(268, a.id)
11566 enddef
11567 H()
11568
11569 var b: T = T.new().F().F()
11570 assert_equal(268, b.id)
11571 END
11572 v9.CheckScriptSuccess(lines)
11573
11574 # Using a null object to access a member variable
11575 lines =<< trim END
11576 vim9script
11577 def Fn(x: any): number
11578 return x.num
11579 enddef
11580
11581 Fn(null_object)
11582 END
11583 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11584
11585 # Using a null object to invoke a method
11586 lines =<< trim END
11587 vim9script
11588 def Fn(x: any)
11589 x.Foo()
11590 enddef
11591
11592 Fn(null_object)
11593 END
11594 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
Yegappan Lakshmanane7984462024-11-12 21:03:00 +010011595
11596 # Try to change a const object variable using a "any" variable
11597 lines =<< trim END
11598 vim9script
11599 class A
11600 public const v1: number = 123
11601 endclass
11602
11603 def Fn(o: any)
11604 o.v1 = 321
11605 enddef
11606
11607 var a = A.new()
11608 Fn(a)
11609 END
11610 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11611
11612 # Try to change a final object variable using a "any" variable
11613 lines =<< trim END
11614 vim9script
11615 class A
11616 public final v1: number = 123
11617 endclass
11618
11619 def Fn(o: any)
11620 o.v1 = 321
11621 enddef
11622
11623 var a = A.new()
11624 Fn(a)
11625 END
11626 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11627
11628 # Assign a different type of value to an "any" type object variable
11629 lines =<< trim END
11630 vim9script
11631 class A
11632 public var v1: list<any> = [1, 2]
11633 endclass
11634
11635 def Fn(o: A)
11636 o.v1 = 'abc'
11637 enddef
11638
11639 var a = A.new()
11640 Fn(a)
11641 END
11642 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 1)
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011643enddef
11644
Yegappan Lakshmanan481992c2024-12-06 18:35:12 +010011645" Test for using an object method with mapnew()
11646def Test_mapnew_with_instance_method()
11647 var lines =<< trim END
11648 vim9script
11649
11650 class Foo
11651 var str: string
11652 var nums: list<number> = [1, 2, 3]
11653
11654 def InstanceMethod(n: number): string
11655 return this.str .. n
11656 enddef
11657
11658 def MapperMethod(idx: number, elem: number): string
11659 return elem->this.InstanceMethod()
11660 enddef
11661
11662 def MapTest()
11663 this.str = "foo"
11664 var l = ['foo1', 'foo2', 'foo3']
11665 assert_equal(l, this.nums->mapnew(this.MapperMethod))
11666 enddef
11667 endclass
11668
11669 Foo.new().MapTest()
11670 END
11671 v9.CheckSourceSuccess(lines)
11672
11673 # Error in the mapnew() function
11674 lines =<< trim END
11675 vim9script
11676
11677 class Foo
11678 var str: string
11679 var nums: list<number> = [1, 2, 3]
11680
11681 def InstanceMethod(n: number): string
11682 throw "InstanceMethod failed"
11683 enddef
11684
11685 def MapperMethod(idx: number, elem: number): string
11686 return elem->this.InstanceMethod()
11687 enddef
11688
11689 def MapTest()
11690 this.str = "foo"
11691 var caught_exception: bool = false
11692 try
11693 this.nums->mapnew(this.MapperMethod)
11694 catch /InstanceMethod failed/
11695 caught_exception = true
11696 endtry
11697 assert_true(caught_exception)
11698 enddef
11699 endclass
11700
11701 Foo.new().MapTest()
11702 END
11703 v9.CheckSourceSuccess(lines)
11704enddef
11705
Yegappan Lakshmananb0206e92024-12-30 09:52:16 +010011706" Test for using an object method in a method call.
11707def Test_use_object_method_in_a_method_call()
11708 var lines =<< trim END
11709 vim9script
11710
11711 class Foo
11712 def Cost(nums: list<number>): number
11713 return nums[0] * nums[1]
11714 enddef
11715
11716 def ShowCost(): string
11717 var g = [4, 5]
11718 return $"Cost is: {g->this.Cost()}"
11719 enddef
11720 endclass
11721
11722 var d = Foo.new()
11723 assert_equal('Cost is: 20', d.ShowCost())
11724 END
11725 v9.CheckSourceSuccess(lines)
11726
11727 # Test for using a non-existing object method in string interpolation
11728 lines =<< trim END
11729 vim9script
11730
11731 class Foo
11732 def Cost(nums: list<number>): number
11733 return nums[0] * nums[1]
11734 enddef
11735
11736 def ShowCost(): string
11737 var g = [4, 5]
11738 echo $"Cost is: {g->this.NewCost()}"
11739 enddef
11740 endclass
11741
11742 var d = Foo.new()
11743 d.ShowCost()
11744 END
11745 v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
11746enddef
11747
Yegappan Lakshmananb04af4c2025-01-03 10:50:08 +010011748" Test for referencing an object variable which is not yet initialized
11749def Test_uninitialized_object_var()
11750 var lines =<< trim END
11751 vim9script
11752 class Foo
11753 const two: number = Foo.Two(this)
11754 const one: number = 1
11755
11756 static def Two(that: Foo): number
11757 return that.one + 2
11758 enddef
11759 endclass
11760
11761 echo Foo.Two(Foo.new())
11762 END
11763 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
11764
11765 lines =<< trim END
11766 vim9script
11767 class Foo
11768 const one: number = Foo.One(this)
11769
11770 static def One(that: Foo): number
11771 return 1
11772 enddef
11773 endclass
11774
11775 assert_equal(1, Foo.One(Foo.new()))
11776 END
11777 v9.CheckSourceSuccess(lines)
11778
11779 lines =<< trim END
11780 vim9script
11781 class Foo
11782 const one: number = 1
11783 const two: number = Foo.Two(this)
11784
11785 static def Two(that: Foo): number
11786 return that.one + 1
11787 enddef
11788 endclass
11789
11790 assert_equal(2, Foo.Two(Foo.new()))
11791 END
11792 v9.CheckSourceSuccess(lines)
11793
11794 lines =<< trim END
11795 vim9script
11796 class Foo
11797 const Id: func(any): any = ((_) => (v) => v)(this)
11798
11799 static def Id(that: Foo): func(any): any
11800 return that.Id
11801 enddef
11802 endclass
11803
11804 assert_equal(5, Foo.Id(Foo.new())(5))
11805 assert_equal(7, Foo.new().Id(7))
11806 END
11807 v9.CheckSourceSuccess(lines)
11808
11809 lines =<< trim END
11810 vim9script
11811 class Foo
11812 const Id: func(any): any = ((that) => (_) => that)(this)
11813
11814 static def Id(that: Foo): func(any): any
11815 return that.Id
11816 enddef
11817 endclass
11818
11819 const Id0: func(any): any = Foo.Id(Foo.new())
11820 const Id1: func(any): any = Foo.new().Id
11821 END
11822 v9.CheckSourceSuccess(lines)
11823
11824 lines =<< trim END
11825 vim9script
11826 class Foo
11827 const Id: any = Foo.Id(this)
11828
11829 static def Id(that: Foo): any
11830 return that.Id
11831 enddef
11832 endclass
11833
11834 const Id2: any = Foo.Id(Foo.new())
11835 const Id3: any = Foo.new().Id
11836 END
11837 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
11838
11839 lines =<< trim END
11840 vim9script
11841
11842 class Foo
11843 var x: string = ''
11844 var Y: func(): string = () => this.x
11845 endclass
11846
11847 var foo = Foo.new('ok')
11848 assert_equal('ok', foo.Y())
11849 END
11850 v9.CheckSourceSuccess(lines)
11851
11852 lines =<< trim END
11853 vim9script
11854
11855 class Foo
11856 var x: string = this.x
11857 endclass
11858
11859 var foo = Foo.new('ok')
11860 END
11861 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
11862enddef
11863
Yegappan Lakshmanan2050dcc2025-01-06 18:34:49 +010011864" Test for initializing member variables of compound type in the constructor
11865def Test_constructor_init_compound_member_var()
11866 var lines =<< trim END
11867 vim9script
11868
11869 class Foo
11870 var v1: string = "aaa"
11871 var v2: list<number> = [1, 2]
11872 var v3: dict<string> = {a: 'a', b: 'b'}
11873 endclass
11874
11875 class Bar
11876 var v4: string = "bbb"
11877 var v5: Foo = Foo.new()
11878 var v6: list<number> = [1, 2]
11879 endclass
11880
11881 var b: Bar = Bar.new()
11882 assert_equal("aaa", b.v5.v1)
11883 assert_equal([1, 2], b.v5.v2)
11884 assert_equal({a: 'a', b: 'b'}, b.v5.v3)
11885 assert_equal("bbb", b.v4)
11886 assert_equal([1, 2], b.v6)
11887 END
11888 v9.CheckSourceSuccess(lines)
11889enddef
11890
Bram Moolenaar00b28d62022-12-08 15:32:33 +000011891" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker