blob: 1e63f22df911f94592512b860bd3c0db2c555cf8 [file] [log] [blame]
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001" Test Vim9 classes
2
3source check.vim
4import './vim9.vim' as v9
5
6def Test_class_basic()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007 # Class supported only in "vim9script"
Bram Moolenaar00b28d62022-12-08 15:32:33 +00008 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02009 class NotWorking
10 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000011 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020012 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000013
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020014 # First character in a class name should be capitalized.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000015 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020016 vim9script
17 class notWorking
18 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000019 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020020 v9.CheckSourceFailure(lines, 'E1314: Class name must start with an uppercase letter: notWorking', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000021
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020022 # Only alphanumeric characters are supported in a class name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000023 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020024 vim9script
25 class Not@working
26 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000027 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020028 v9.CheckSourceFailure(lines, 'E1315: White space required after name: Not@working', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000029
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020030 # Unsupported keyword (instead of class)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000031 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020032 vim9script
33 abstract noclass Something
34 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000035 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020036 v9.CheckSourceFailure(lines, 'E475: Invalid argument: noclass Something', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000037
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +010038 # Only the complete word "class" should be recognized
Bram Moolenaar00b28d62022-12-08 15:32:33 +000039 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020040 vim9script
41 abstract classy Something
42 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000043 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020044 v9.CheckSourceFailure(lines, 'E475: Invalid argument: classy Something', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000045
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020046 # The complete "endclass" should be specified.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000047 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020048 vim9script
49 class Something
50 endcl
Bram Moolenaar00b28d62022-12-08 15:32:33 +000051 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020052 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endcl', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000053
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020054 # Additional words after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000055 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020056 vim9script
57 class Something
58 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000059 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020060 v9.CheckSourceFailure(lines, "E488: Trailing characters: school's out", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000061
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020062 # Additional commands after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000063 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020064 vim9script
65 class Something
66 endclass | echo 'done'
Bram Moolenaar00b28d62022-12-08 15:32:33 +000067 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020068 v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000069
Yegappan Lakshmananac773182024-04-27 11:36:12 +020070 # Additional command after "class name"
71 lines =<< trim END
72 vim9script
73 class Something | var x = 10
74 endclass
75 END
76 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
77
78 # Additional command after "object variable"
79 lines =<< trim END
80 vim9script
81 class Something
82 var l: list<number> = [] | var y = 10
83 endclass
84 END
85 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
86
87 # Additional command after "class variable"
88 lines =<< trim END
89 vim9script
90 class Something
91 static var d = {a: 10} | var y = 10
92 endclass
93 END
94 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
95
96 # Additional command after "object method"
97 lines =<< trim END
98 vim9script
99 class Something
100 def Foo() | var y = 10
101 enddef
102 endclass
103 END
104 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
105
Yegappan Lakshmananfe55c312024-04-28 09:54:09 +0200106 # Comments are allowed after an inline block
107 lines =<< trim END
108 vim9script
109 class Foo
110 static const bar = { # {{{
111 baz: 'qux'
112 } # }}}
113 endclass
114 assert_equal({baz: 'qux'}, Foo.bar)
115 END
116 v9.CheckSourceSuccess(lines)
117
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +0100118 # Try to define a class with the same name as an existing variable
119 lines =<< trim END
120 vim9script
121 var Something: list<number> = [1]
122 class Thing
123 endclass
124 interface Api
125 endinterface
126 class Something extends Thing implements Api
127 var v1: string = ''
128 def Foo()
129 enddef
130 endclass
131 END
132 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 7)
133
zeertzjqe7102202024-02-13 20:32:04 +0100134 # Use old "this." prefixed member variable declaration syntax (without initialization)
Doug Kearns74da0ee2023-12-14 20:26:26 +0100135 lines =<< trim END
136 vim9script
137 class Something
138 this.count: number
139 endclass
140 END
141 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number', 3)
142
zeertzjqe7102202024-02-13 20:32:04 +0100143 # Use old "this." prefixed member variable declaration syntax (with initialization)
Doug Kearns74da0ee2023-12-14 20:26:26 +0100144 lines =<< trim END
145 vim9script
146 class Something
147 this.count: number = 42
148 endclass
149 END
150 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number = 42', 3)
151
152 # Use old "this." prefixed member variable declaration syntax (type inferred)
153 lines =<< trim END
154 vim9script
155 class Something
156 this.count = 42
157 endclass
158 END
159 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count = 42', 3)
160
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200161 # Use "this" without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000162 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200163 vim9script
164 class Something
165 this
166 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000167 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100168 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000169
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200170 # Use "this." without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000171 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200172 vim9script
173 class Something
174 this.
175 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000176 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100177 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000178
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200179 # Space between "this" and ".<variable>"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000180 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200181 vim9script
182 class Something
183 this .count
184 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000185 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100186 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this .count', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000187
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200188 # Space between "this." and the member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000189 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200190 vim9script
191 class Something
192 this. count
193 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000194 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100195 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this. count', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000196
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200197 # Use "that" instead of "this"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000198 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200199 vim9script
200 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100201 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200202 that.count
203 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000204 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200205 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count', 4)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000206
Doug Kearns74da0ee2023-12-14 20:26:26 +0100207 # Use "variable" instead of "var" for member variable declaration (without initialization)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000208 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200209 vim9script
210 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100211 variable count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200212 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000213 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100214 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count: number', 3)
215
216 # Use "variable" instead of "var" for member variable declaration (with initialization)
217 lines =<< trim END
218 vim9script
219 class Something
220 variable count: number = 42
221 endclass
222 END
223 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count: number = 42', 3)
224
225 # Use "variable" instead of "var" for member variable declaration (type inferred)
226 lines =<< trim END
227 vim9script
228 class Something
229 variable count = 42
230 endclass
231 END
232 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count = 42', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000233
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200234 # Use a non-existing member variable in new()
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000235 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200236 vim9script
237 class Something
238 def new()
239 this.state = 0
240 enddef
241 endclass
242 var obj = Something.new()
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000243 END
Ernie Raeld4802ec2023-10-20 11:59:00 +0200244 v9.CheckSourceFailure(lines, 'E1326: Variable "state" not found in object "Something"', 1)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000245
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200246 # Space before ":" in a member variable declaration
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000247 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200248 vim9script
249 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100250 var count : number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200251 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000252 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200253 v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: count : number', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000254
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200255 # No space after ":" in a member variable declaration
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000256 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200257 vim9script
258 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100259 var count:number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200260 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000261 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200262 v9.CheckSourceFailure(lines, "E1069: White space required after ':'", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000263
Doug Kearns74da0ee2023-12-14 20:26:26 +0100264 # Missing ":var" in a "var" member variable declaration (without initialization)
265 lines =<< trim END
266 vim9script
267 class Something
268 var: number
269 endclass
270 END
271 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var: number', 3)
272
273 # Missing ":var" in a "var" member variable declaration (with initialization)
274 lines =<< trim END
275 vim9script
276 class Something
277 var: number = 42
278 endclass
279 END
280 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var: number = 42', 3)
281
282 # Missing ":var" in a "var" member variable declaration (type inferred)
283 lines =<< trim END
284 vim9script
285 class Something
286 var = 42
287 endclass
288 END
289 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var = 42', 3)
290
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200291 # Test for unsupported comment specifier
292 lines =<< trim END
293 vim9script
294 class Something
295 # comment
296 #{
297 endclass
298 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200299 v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200300
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200301 # Test for using class as a bool
302 lines =<< trim END
303 vim9script
304 class A
305 endclass
306 if A
307 endif
308 END
Ernie Raele75fde62023-12-21 17:18:54 +0100309 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200310
311 # Test for using object as a bool
312 lines =<< trim END
313 vim9script
314 class A
315 endclass
316 var a = A.new()
317 if a
318 endif
319 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200320 v9.CheckSourceFailure(lines, 'E1320: Using an Object as a Number', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200321
322 # Test for using class as a float
323 lines =<< trim END
324 vim9script
325 class A
326 endclass
327 sort([1.1, A], 'f')
328 END
Ernie Raelfa831102023-12-14 20:06:39 +0100329 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200330
331 # Test for using object as a float
332 lines =<< trim END
333 vim9script
334 class A
335 endclass
336 var a = A.new()
337 sort([1.1, a], 'f')
338 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200339 v9.CheckSourceFailure(lines, 'E1322: Using an Object as a Float', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200340
341 # Test for using class as a string
342 lines =<< trim END
343 vim9script
344 class A
345 endclass
346 :exe 'call ' .. A
347 END
Ernie Raele75fde62023-12-21 17:18:54 +0100348 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200349
350 # Test for using object as a string
351 lines =<< trim END
352 vim9script
353 class A
354 endclass
355 var a = A.new()
356 :exe 'call ' .. a
357 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200358 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200359
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200360 # Test creating a class with member variables and methods, calling a object
361 # method. Check for using type() and typename() with a class and an object.
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000362 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200363 vim9script
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000364
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200365 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100366 var lnum: number
367 var col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000368
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200369 # make a nicely formatted string
370 def ToString(): string
371 return $'({this.lnum}, {this.col})'
372 enddef
373 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000374
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200375 # use the automatically generated new() method
376 var pos = TextPosition.new(2, 12)
377 assert_equal(2, pos.lnum)
378 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000379
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200380 # call an object method
381 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000382
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200383 assert_equal(v:t_class, type(TextPosition))
384 assert_equal(v:t_object, type(pos))
385 assert_equal('class<TextPosition>', typename(TextPosition))
386 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000387 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200388 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200389
390 # When referencing object methods, space cannot be used after a "."
391 lines =<< trim END
392 vim9script
393 class A
394 def Foo(): number
395 return 10
396 enddef
397 endclass
398 var a = A.new()
399 var v = a. Foo()
400 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200401 v9.CheckSourceFailure(lines, "E1202: No white space allowed after '.'", 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200402
403 # Using an object without specifying a method or a member variable
404 lines =<< trim END
405 vim9script
406 class A
407 def Foo(): number
408 return 10
409 enddef
410 endclass
411 var a = A.new()
412 var v = a.
413 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200414 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a."', 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200415
416 # Error when parsing the arguments of an object method.
417 lines =<< trim END
418 vim9script
419 class A
420 def Foo()
421 enddef
422 endclass
423 var a = A.new()
424 var v = a.Foo(,)
425 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200426 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a.Foo(,)"', 7)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200427
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200428 # Use a multi-line initialization for a member variable
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200429 lines =<< trim END
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200430 vim9script
431 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +0100432 var y = {
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200433 X: 1
434 }
435 endclass
436 var a = A.new()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200437 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200438 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000439enddef
440
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200441" Tests for object/class methods in a class
442def Test_class_def_method()
443 # Using the "public" keyword when defining an object method
444 var lines =<< trim END
445 vim9script
446 class A
447 public def Foo()
448 enddef
449 endclass
450 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200451 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200452
453 # Using the "public" keyword when defining a class method
454 lines =<< trim END
455 vim9script
456 class A
457 public static def Foo()
458 enddef
459 endclass
460 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200461 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200462
Ernie Rael03042a22023-11-11 08:53:32 +0100463 # Using the "public" keyword when defining an object protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200464 lines =<< trim END
465 vim9script
466 class A
467 public def _Foo()
468 enddef
469 endclass
470 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200471 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200472
Ernie Rael03042a22023-11-11 08:53:32 +0100473 # Using the "public" keyword when defining a class protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200474 lines =<< trim END
475 vim9script
476 class A
477 public static def _Foo()
478 enddef
479 endclass
480 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200481 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200482
483 # Using a "def" keyword without an object method name
484 lines =<< trim END
485 vim9script
486 class A
487 def
488 enddef
489 endclass
490 END
491 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: def', 3)
492
493 # Using a "def" keyword without a class method name
494 lines =<< trim END
495 vim9script
496 class A
497 static def
498 enddef
499 endclass
500 END
501 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: static def', 3)
502enddef
503
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000504def Test_class_defined_twice()
505 # class defined twice should fail
506 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200507 vim9script
508 class There
509 endclass
510 class There
511 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000512 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200513 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"', 4)
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000514
515 # one class, reload same script twice is OK
516 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200517 vim9script
518 class There
519 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000520 END
521 writefile(lines, 'XclassTwice.vim', 'D')
522 source XclassTwice.vim
523 source XclassTwice.vim
524enddef
525
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000526def Test_returning_null_object()
527 # this was causing an internal error
528 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200529 vim9script
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000530
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200531 class BufferList
532 def Current(): any
533 return null_object
534 enddef
535 endclass
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000536
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200537 var buffers = BufferList.new()
538 echo buffers.Current()
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000539 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200540 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000541enddef
542
Bram Moolenaard13dd302023-03-11 20:56:35 +0000543def Test_using_null_class()
544 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200545 @_ = null_class.member
Bram Moolenaard13dd302023-03-11 20:56:35 +0000546 END
Yegappan Lakshmanan778ada42025-02-17 20:21:23 +0100547 v9.CheckDefExecAndScriptFailure(lines, ['E1395: Using a null class', 'E1363: Incomplete type'])
Yegappan Lakshmananb2e42b92024-05-01 11:44:17 +0200548
549 # Test for using a null class as a value
550 lines =<< trim END
551 vim9script
552 echo empty(null_class)
553 END
554 v9.CheckSourceFailure(lines, 'E1405: Class "" cannot be used as a value', 2)
555
556 # Test for using a null class with string()
557 lines =<< trim END
558 vim9script
559 assert_equal('class [unknown]', string(null_class))
560 END
561 v9.CheckSourceSuccess(lines)
562
Yegappan Lakshmananda9d3452024-05-02 13:02:36 +0200563 # Test for using a null class with type() and typename()
Yegappan Lakshmananb2e42b92024-05-01 11:44:17 +0200564 lines =<< trim END
565 vim9script
566 assert_equal(12, type(null_class))
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
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003064 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003065 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003066 def ToString(): number
3067 return this.age
3068 enddef
3069 def ToString(): string
3070 return this.age
3071 enddef
3072 endclass
3073 END
3074 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
3075
3076 lines =<< trim END
3077 vim9script
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003078 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003079 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003080 static def ToString(): string
3081 return 'Base class'
3082 enddef
3083 endclass
3084
3085 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003086 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003087 def ToString(): string
3088 return Base.ToString() .. ': ' .. this.age
3089 enddef
3090 endclass
3091
3092 var o = Child.new('John', 42)
3093 assert_equal('Base class: 42', o.ToString())
3094 END
3095 v9.CheckSourceSuccess(lines)
3096
3097 lines =<< trim END
3098 vim9script
3099 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003100 var value = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003101 def new(init: number)
3102 this.value = number + 1
3103 enddef
3104 endclass
3105 class Child extends Base
3106 def new()
3107 this.new(3)
3108 enddef
3109 endclass
3110 var c = Child.new()
3111 END
3112 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003113
3114 # base class with more than one object member
3115 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003116 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003117
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003118 class Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01003119 var success: bool
3120 var value: any = null
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003121 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003122
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003123 class Success extends Result
3124 def new(this.value = v:none)
3125 this.success = true
3126 enddef
3127 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003128
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003129 var v = Success.new('asdf')
3130 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003131 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003132 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003133
3134 # class name after "extends" doesn't end in a space or NUL character
3135 lines =<< trim END
3136 vim9script
3137 class A
3138 endclass
3139 class B extends A"
3140 endclass
3141 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003142 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00003143enddef
3144
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003145def Test_using_base_class()
3146 var lines =<< trim END
3147 vim9script
3148
3149 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003150 def Enter(): any
3151 return null
3152 enddef
3153 def Exit(resource: any): void
3154 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003155 endclass
3156
3157 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003158 def Enter(): any
3159 return 42
3160 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003161
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003162 def Exit(resource: number): void
3163 g:result ..= '/exit'
3164 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003165 endclass
3166
3167 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003168 var r = ee.Enter()
3169 try
3170 g:result ..= r
3171 finally
3172 g:result ..= '/finally'
3173 ee.Exit(r)
3174 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003175 enddef
3176
3177 g:result = ''
3178 With(ChildEE.new())
3179 assert_equal('42/finally/exit', g:result)
3180 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003181 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003182 unlet g:result
3183enddef
3184
Ernie Raelbce60c42025-01-19 10:03:00 +01003185" Test for using a method from the super class
Ernie Rael58c95792024-08-13 23:27:22 +02003186def Test_super_dispatch()
3187 # See #15448 and #15463
3188 var lines =<< trim END
3189 vim9script
3190
3191 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003192 def String(): string
3193 return 'A'
3194 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003195 endclass
3196
3197 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003198 def String(): string
3199 return super.String()
3200 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003201 endclass
3202
3203 class C extends B
3204 endclass
3205
3206 assert_equal('A', C.new().String())
3207 END
3208 v9.CheckSourceSuccess(lines)
3209
3210 lines =<< trim END
3211 vim9script
3212
3213 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003214 def F(): string
3215 return 'AA'
3216 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003217 endclass
3218
3219 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003220 def F(): string
3221 return 'BB'
3222 enddef
3223 def S(): string
3224 return super.F()
3225 enddef
3226 def S0(): string
3227 return this.S()
3228 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003229 endclass
3230
3231 class C extends B
Ernie Raelbce60c42025-01-19 10:03:00 +01003232 def F(): string
3233 return 'CC'
3234 enddef
3235 def ToB(): string
3236 return super.F()
3237 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003238 endclass
3239
3240 assert_equal('AA', B.new().S())
3241 assert_equal('AA', C.new().S())
3242 assert_equal('AA', B.new().S0())
3243 assert_equal('AA', C.new().S0())
3244
3245 assert_equal('BB', C.new().ToB())
3246
3247 assert_equal('CC', C.new().F())
3248 assert_equal('BB', B.new().F())
3249 assert_equal('AA', A.new().F())
3250 END
3251 v9.CheckSourceSuccess(lines)
3252
3253 lines =<< trim END
3254 vim9script
3255
3256 var call_chain: list<string>
3257
3258 abstract class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003259 abstract def _G(): string
Ernie Rael58c95792024-08-13 23:27:22 +02003260
Ernie Raelbce60c42025-01-19 10:03:00 +01003261 def F(): string
3262 call_chain->add('A.F()')
3263 return this._G()
3264 enddef
3265 def _H(): string
3266 call_chain->add('A._H()')
3267 return this.F()
3268 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003269 endclass
3270
3271 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003272 def _G(): string
3273 call_chain->add('B.G()')
3274 return 'BBB'
3275 enddef
3276 def SF(): string
3277 call_chain->add('B.SF()')
3278 return super._H()
3279 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003280 endclass
3281
3282 class C extends B
3283 endclass
3284
3285 class D extends C
Ernie Raelbce60c42025-01-19 10:03:00 +01003286 def SF(): string
3287 call_chain->add('D.SF()')
3288 return super.SF()
3289 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003290 endclass
3291
3292 class E extends D
Ernie Raelbce60c42025-01-19 10:03:00 +01003293 def SF(): string
3294 call_chain->add('E.SF()')
3295 return super.SF()
3296 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003297 endclass
3298
3299 class F extends E
Ernie Raelbce60c42025-01-19 10:03:00 +01003300 def _G(): string
3301 call_chain->add('F._G()')
3302 return 'FFF'
3303 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003304 endclass
3305
3306 # E.new() -> A.F() -> B._G()
3307 call_chain = []
3308 var o1 = E.new()
3309 assert_equal('BBB', o1.F())
3310 assert_equal(['A.F()', 'B.G()'], call_chain)
3311
3312 # F.new() -> E.SF() -> D.SF() -> B.SF() -> A._H() -> A.F() -> F._G()
3313 call_chain = []
3314 var o2 = F.new()
3315 assert_equal('FFF', o2.SF())
3316 assert_equal(['E.SF()', 'D.SF()', 'B.SF()', 'A._H()', 'A.F()', 'F._G()'], call_chain)
3317 END
3318 v9.CheckSourceSuccess(lines)
Ernie Raelbce60c42025-01-19 10:03:00 +01003319
3320 # problems with method dispatch: super -> abstract
3321 # https://github.com/vim/vim/issues/15514
3322 lines =<< trim END
3323 vim9script
3324 abstract class B
3325 abstract def ToString(): string
3326 endclass
3327
3328 class C extends B
3329 def ToString(): string
3330 return super.ToString()
3331 enddef
3332 endclass
3333
3334 try
3335 defcompile C.ToString
3336 call assert_false(1, 'command should have failed')
3337 catch
3338 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3339 endtry
3340 END
3341 v9.CheckSourceSuccess(lines)
3342
3343 # problems with method dispatch: super -> abstract -> concrete
3344 lines =<< trim END
3345 vim9script
3346
3347 class A
3348 def ToString()
3349 echo 'A'
3350 enddef
3351 endclass
3352
3353 abstract class B extends A
3354 abstract def ToString()
3355 endclass
3356
3357 class C extends B
3358 def ToString()
3359 super.ToString()
3360 enddef
3361 endclass
3362
3363 try
3364 defcompile C.ToString
3365 call assert_false(1, 'command should have failed')
3366 catch
3367 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3368 endtry
3369 END
3370 v9.CheckSourceSuccess(lines)
3371
3372 # Invoking a super method and an interface method which have the same name.
3373 lines =<< trim END
3374 vim9script
3375
3376 interface I
3377 def ToString(): string
3378 endinterface
3379
3380 # Note that A does not implement I.
3381 class A
3382 def ToString(): string
3383 return 'A'
3384 enddef
3385 endclass
3386
3387 class B extends A implements I
3388 def ToString(): string
3389 return super.ToString()
3390 enddef
3391 endclass
3392
3393 def TestI(i: I): string
3394 return i.ToString()
3395 enddef
3396
3397 assert_equal('A', B.new().ToString())
3398 assert_equal('A', TestI(B.new()))
3399 END
3400 v9.CheckSourceSuccess(lines)
3401
3402 # super and an abstract class with no abstract methods
3403 lines =<< trim END
3404 vim9script
3405
3406 class A
3407 def ToString(): string
3408 return 'A'
3409 enddef
3410 endclass
3411
3412 # An abstract class with no abstract methods.
3413 abstract class B extends A
3414 endclass
3415
3416 class C extends B
3417 def ToString(): string
3418 return super.ToString()
3419 enddef
3420 endclass
3421
3422 def TestA(a: A): string
3423 return a.ToString()
3424 enddef
3425
3426 def TestB(b: B): string
3427 return b.ToString()
3428 enddef
3429
3430 assert_equal('A', C.new().ToString())
3431 assert_equal('A', TestA(A.new()))
3432 assert_equal('A', TestA(C.new()))
3433 assert_equal('A', TestB(C.new()))
3434 END
3435 v9.CheckSourceSuccess(lines)
3436
3437 # super and an abstract class with no abstract methods and the initial
3438 # implements clause
3439 lines =<< trim END
3440 vim9script
3441
3442 interface I
3443 def ToString(): string
3444 endinterface
3445
3446 # Note that A does not implement I.
3447 class A
3448 def ToString(): string
3449 return 'A'
3450 enddef
3451 endclass
3452
3453 # An abstract class with no abstract methods.
3454 abstract class B extends A implements I
3455 endclass
3456
3457 class C extends B implements I
3458 def ToString(): string
3459 return super.ToString()
3460 enddef
3461 endclass
3462
3463 # Note that A.ToString() is different from I.ToString().
3464 def TestA(a: A): string
3465 return a.ToString()
3466 enddef
3467
3468 assert_equal('A', C.new().ToString())
3469 assert_equal('A', TestA(A.new()))
3470 assert_equal('A', TestA(C.new()))
3471 END
3472 v9.CheckSourceSuccess(lines)
Ernie Rael58c95792024-08-13 23:27:22 +02003473enddef
3474
Bram Moolenaara86655a2023-01-12 17:06:27 +00003475def Test_class_import()
3476 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003477 vim9script
3478 export class Animal
Doug Kearns74da0ee2023-12-14 20:26:26 +01003479 var kind: string
3480 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003481 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003482 END
3483 writefile(lines, 'Xanimal.vim', 'D')
3484
3485 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003486 vim9script
3487 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003488
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003489 var a: animal.Animal
3490 a = animal.Animal.new('fish', 'Eric')
3491 assert_equal('fish', a.kind)
3492 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003493
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003494 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3495 assert_equal('cat', b.kind)
3496 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003497 END
3498 v9.CheckScriptSuccess(lines)
3499enddef
3500
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003501" Test for importing a class into a legacy script and calling the class method
3502def Test_class_method_from_legacy_script()
3503 var lines =<< trim END
3504 vim9script
3505 export class A
3506 static var name: string = 'a'
3507 static def SetName(n: string)
3508 name = n
3509 enddef
3510 endclass
3511 END
3512 writefile(lines, 'Xvim9export.vim', 'D')
3513
3514 lines =<< trim END
3515 import './Xvim9export.vim' as vim9
3516
3517 call s:vim9.A.SetName('b')
3518 call assert_equal('b', s:vim9.A.name)
3519 END
3520 v9.CheckScriptSuccess(lines)
3521enddef
3522
Yegappan Lakshmanand2e1c832023-12-14 19:59:45 +01003523" Test for implementing an imported interface
3524def Test_implement_imported_interface()
3525 var lines =<< trim END
3526 vim9script
3527 export interface Imp_Intf1
3528 def Fn1(): number
3529 endinterface
3530 export interface Imp_Intf2
3531 def Fn2(): number
3532 endinterface
3533 END
3534 writefile(lines, 'Ximportinterface.vim', 'D')
3535
3536 lines =<< trim END
3537 vim9script
3538 import './Ximportinterface.vim' as Xintf
3539
3540 class A implements Xintf.Imp_Intf1, Xintf.Imp_Intf2
3541 def Fn1(): number
3542 return 10
3543 enddef
3544 def Fn2(): number
3545 return 20
3546 enddef
3547 endclass
3548 var a = A.new()
3549 assert_equal(10, a.Fn1())
3550 assert_equal(20, a.Fn2())
3551 END
3552 v9.CheckScriptSuccess(lines)
3553enddef
3554
3555" Test for extending an imported class
3556def Test_extend_imported_class()
3557 var lines =<< trim END
3558 vim9script
3559 export class Imp_C1
3560 def Fn1(): number
3561 return 5
3562 enddef
3563 endclass
3564 END
3565 writefile(lines, 'Xextendimportclass.vim', 'D')
3566
3567 lines =<< trim END
3568 vim9script
3569 import './Xextendimportclass.vim' as XClass
3570
3571 class A extends XClass.Imp_C1
3572 endclass
3573 var a = A.new()
3574 assert_equal(5, a.Fn1())
3575 END
3576 v9.CheckScriptSuccess(lines)
3577enddef
3578
Christian Brabandtd9a1f262025-01-21 22:17:50 +01003579def Test_abstract_class()
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003580 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003581 vim9script
3582 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003583 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003584 endclass
3585 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003586 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003587 endclass
3588 var p: Base = Person.new('Peter', 42)
3589 assert_equal('Peter', p.name)
3590 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003591 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003592 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003593
3594 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003595 vim9script
3596 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003597 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003598 endclass
3599 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003600 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003601 endclass
3602 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003603 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003604 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003605
3606 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003607 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003608 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003609 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003610 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003611 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003612
h-eastaa979c72025-01-03 10:19:45 +01003613 # Test for "abstract" cannot be abbreviated
3614 lines =<< trim END
3615 vim9script
3616 abs class A
3617 endclass
3618 END
3619 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs class A', 2)
3620
Yegappan Lakshmananac773182024-04-27 11:36:12 +02003621 # Additional commands after "abstract class"
3622 lines =<< trim END
3623 vim9script
3624 abstract class Something | var x = []
3625 endclass
3626 END
3627 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = []", 2)
3628
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003629 # Abstract class cannot have a "new" function
3630 lines =<< trim END
3631 vim9script
3632 abstract class Base
3633 def new()
3634 enddef
3635 endclass
3636 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003637 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003638
3639 # extending an abstract class with class methods and variables
3640 lines =<< trim END
3641 vim9script
3642 abstract class A
3643 static var s: string = 'vim'
3644 static def Fn(): list<number>
3645 return [10]
3646 enddef
3647 endclass
3648 class B extends A
3649 endclass
3650 var b = B.new()
3651 assert_equal('vim', A.s)
3652 assert_equal([10], A.Fn())
3653 END
3654 v9.CheckScriptSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003655enddef
3656
Bram Moolenaar486fc252023-01-18 14:51:07 +00003657def Test_closure_in_class()
3658 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003659 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003660
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003661 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01003662 var y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003663
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003664 def new()
3665 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3666 enddef
3667 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003668
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003669 Foo.new()
3670 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003671 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003672 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003673enddef
3674
Ernie Rael9ed53752023-12-11 17:40:46 +01003675def Test_construct_object_from_legacy()
3676 # Cannot directly invoke constructor from legacy
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003677 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003678 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003679
Ernie Rael9ed53752023-12-11 17:40:46 +01003680 var newCalled = false
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003681
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003682 class A
Ernie Rael9ed53752023-12-11 17:40:46 +01003683 def new(arg: string)
3684 newCalled = true
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003685 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003686 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003687
Ernie Rael9ed53752023-12-11 17:40:46 +01003688 export def CreateA(...args: list<any>): A
3689 return call(A.new, args)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003690 enddef
3691
Ernie Rael9ed53752023-12-11 17:40:46 +01003692 g:P = CreateA
3693 legacy call g:P('some_arg')
3694 assert_equal(true, newCalled)
3695 unlet g:P
3696 END
3697 v9.CheckSourceSuccess(lines)
3698
3699 lines =<< trim END
3700 vim9script
3701
3702 var newCalled = false
3703
3704 class A
3705 static def CreateA(options = {}): any
3706 return A.new()
3707 enddef
3708 def new()
3709 newCalled = true
3710 enddef
3711 endclass
3712
3713 g:P = A.CreateA
3714 legacy call g:P()
3715 assert_equal(true, newCalled)
3716 unlet g:P
3717 END
3718 v9.CheckSourceSuccess(lines)
3719
3720 # This also tests invoking "new()" with "call"
3721 lines =<< trim END
3722 vim9script
3723
3724 var createdObject: any
3725
3726 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01003727 var val1: number
3728 var val2: number
Ernie Rael9ed53752023-12-11 17:40:46 +01003729 static def CreateA(...args: list<any>): any
3730 createdObject = call(A.new, args)
3731 return createdObject
3732 enddef
3733 endclass
3734
3735 g:P = A.CreateA
3736 legacy call g:P(3, 5)
3737 assert_equal(3, createdObject.val1)
3738 assert_equal(5, createdObject.val2)
3739 legacy call g:P()
3740 assert_equal(0, createdObject.val1)
3741 assert_equal(0, createdObject.val2)
3742 legacy call g:P(7)
3743 assert_equal(7, createdObject.val1)
3744 assert_equal(0, createdObject.val2)
3745 unlet g:P
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003746 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003747 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003748enddef
3749
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003750def Test_defer_with_object()
3751 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003752 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003753
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003754 class CWithEE
3755 def Enter()
3756 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003757 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003758 def Exit()
3759 g:result ..= "exited"
3760 enddef
3761 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003762
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003763 def With(ee: CWithEE, F: func)
3764 ee.Enter()
3765 defer ee.Exit()
3766 F()
3767 enddef
3768
3769 g:result = ''
3770 var obj = CWithEE.new()
3771 obj->With(() => {
3772 g:result ..= "called/"
3773 })
3774 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003775 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003776 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003777 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003778
3779 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003780 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003781
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003782 class BaseWithEE
3783 def Enter()
3784 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003785 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003786 def Exit()
3787 g:result ..= "exited-base"
3788 enddef
3789 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003790
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003791 class CWithEE extends BaseWithEE
3792 def Enter()
3793 g:result ..= "entered-child/"
3794 enddef
3795 def Exit()
3796 g:result ..= "exited-child"
3797 enddef
3798 endclass
3799
3800 def With(ee: BaseWithEE, F: func)
3801 ee.Enter()
3802 defer ee.Exit()
3803 F()
3804 enddef
3805
3806 g:result = ''
3807 var obj = CWithEE.new()
3808 obj->With(() => {
3809 g:result ..= "called/"
3810 })
3811 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003812 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003813 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003814 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003815enddef
3816
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003817" The following test used to crash Vim (Github issue #12676)
3818def Test_extends_method_crashes_vim()
3819 var lines =<< trim END
3820 vim9script
3821
3822 class Observer
3823 endclass
3824
3825 class Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003826 var value: any
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003827
3828 def Set(v: any)
3829 if v != this.value
3830 this.value = v
3831 endif
3832 enddef
3833
3834 def Register(observer: Observer)
3835 enddef
3836 endclass
3837
3838 class Bool extends Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003839 var value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003840 endclass
3841
3842 def Observe(obj: Property, who: Observer)
3843 obj.Register(who)
3844 enddef
3845
3846 var p = Bool.new(false)
3847 var myObserver = Observer.new()
3848
3849 Observe(p, myObserver)
3850
3851 p.Set(true)
3852 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003853 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003854enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003855
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003856" Test for calling a method in a class that is extended
3857def Test_call_method_in_extended_class()
3858 var lines =<< trim END
3859 vim9script
3860
3861 var prop_init_called = false
3862 var prop_register_called = false
3863
3864 class Property
3865 def Init()
3866 prop_init_called = true
3867 enddef
3868
3869 def Register()
3870 prop_register_called = true
3871 enddef
3872 endclass
3873
3874 class Bool extends Property
3875 endclass
3876
3877 def Observe(obj: Property)
3878 obj.Register()
3879 enddef
3880
3881 var p = Property.new()
3882 Observe(p)
3883
3884 p.Init()
3885 assert_true(prop_init_called)
3886 assert_true(prop_register_called)
3887 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003888 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003889enddef
3890
LemonBoyafe04662023-08-23 21:08:11 +02003891def Test_instanceof()
3892 var lines =<< trim END
3893 vim9script
3894
3895 class Base1
3896 endclass
3897
3898 class Base2 extends Base1
3899 endclass
3900
3901 interface Intf1
3902 endinterface
3903
3904 class Mix1 implements Intf1
3905 endclass
3906
3907 class Base3 extends Mix1
3908 endclass
3909
Ernie Rael2025af12023-12-12 16:58:00 +01003910 type AliasBase1 = Base1
3911 type AliasBase2 = Base2
3912 type AliasIntf1 = Intf1
3913 type AliasMix1 = Mix1
3914
LemonBoyafe04662023-08-23 21:08:11 +02003915 var b1 = Base1.new()
3916 var b2 = Base2.new()
3917 var b3 = Base3.new()
3918
3919 assert_true(instanceof(b1, Base1))
3920 assert_true(instanceof(b2, Base1))
3921 assert_false(instanceof(b1, Base2))
3922 assert_true(instanceof(b3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003923 assert_true(instanceof(b3, Base1, Base2, Intf1))
3924
3925 assert_true(instanceof(b1, AliasBase1))
3926 assert_true(instanceof(b2, AliasBase1))
3927 assert_false(instanceof(b1, AliasBase2))
3928 assert_true(instanceof(b3, AliasMix1))
3929 assert_true(instanceof(b3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003930
3931 def Foo()
3932 var a1 = Base1.new()
3933 var a2 = Base2.new()
3934 var a3 = Base3.new()
3935
3936 assert_true(instanceof(a1, Base1))
3937 assert_true(instanceof(a2, Base1))
3938 assert_false(instanceof(a1, Base2))
3939 assert_true(instanceof(a3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003940 assert_true(instanceof(a3, Base1, Base2, Intf1))
3941
3942 assert_true(instanceof(a1, AliasBase1))
3943 assert_true(instanceof(a2, AliasBase1))
3944 assert_false(instanceof(a1, AliasBase2))
3945 assert_true(instanceof(a3, AliasMix1))
3946 assert_true(instanceof(a3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003947 enddef
3948 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003949
3950 var o_null: Base1
3951 assert_false(instanceof(o_null, Base1))
3952
LemonBoyafe04662023-08-23 21:08:11 +02003953 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003954 v9.CheckSourceSuccess(lines)
Ernie Rael2025af12023-12-12 16:58:00 +01003955
3956 lines =<< trim END
3957 vim9script
3958
3959 class Base1
3960 endclass
3961 instanceof(Base1.new())
3962 END
3963 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3964
3965 lines =<< trim END
3966 vim9script
3967
3968 class Base1
3969 endclass
3970 def F()
3971 instanceof(Base1.new())
3972 enddef
3973 F()
3974 END
3975 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3976
3977 lines =<< trim END
3978 vim9script
3979
3980 class Base1
3981 endclass
3982
3983 class Base2
3984 endclass
3985
3986 var o = Base2.new()
3987 instanceof(o, Base1, Base2, 3)
3988 END
3989 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4', 10)
3990
3991 lines =<< trim END
3992 vim9script
3993
3994 class Base1
3995 endclass
3996
3997 class Base2
3998 endclass
3999
4000 def F()
4001 var o = Base2.new()
4002 instanceof(o, Base1, Base2, 3)
4003 enddef
4004 F()
4005 END
4006 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4')
LemonBoyafe04662023-08-23 21:08:11 +02004007enddef
4008
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004009" Test for calling a method in the parent class that is extended partially.
4010" This used to fail with the 'E118: Too many arguments for function: Text' error
4011" message (Github issue #12524).
4012def Test_call_method_in_parent_class()
4013 var lines =<< trim END
4014 vim9script
4015
4016 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01004017 var _lnum: number = 1
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004018
4019 def SetY(lnum: number)
4020 this._lnum = lnum
4021 enddef
4022
4023 def Text(): string
4024 return ''
4025 enddef
4026 endclass
4027
4028 class Foo extends Widget
4029 def Text(): string
4030 return '<Foo>'
4031 enddef
4032 endclass
4033
4034 def Stack(w1: Widget, w2: Widget): list<Widget>
4035 w1.SetY(1)
4036 w2.SetY(2)
4037 return [w1, w2]
4038 enddef
4039
4040 var foo1 = Foo.new()
4041 var foo2 = Foo.new()
4042 var l = Stack(foo1, foo2)
4043 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004044 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004045enddef
4046
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004047" Test for calling methods from three levels of classes
4048def Test_multi_level_method_call()
4049 var lines =<< trim END
4050 vim9script
4051
4052 var A_func1: number = 0
4053 var A_func2: number = 0
4054 var A_func3: number = 0
4055 var B_func2: number = 0
4056 var B_func3: number = 0
4057 var C_func3: number = 0
4058
4059 class A
4060 def Func1()
4061 A_func1 += 1
4062 enddef
4063
4064 def Func2()
4065 A_func2 += 1
4066 enddef
4067
4068 def Func3()
4069 A_func3 += 1
4070 enddef
4071 endclass
4072
4073 class B extends A
4074 def Func2()
4075 B_func2 += 1
4076 enddef
4077
4078 def Func3()
4079 B_func3 += 1
4080 enddef
4081 endclass
4082
4083 class C extends B
4084 def Func3()
4085 C_func3 += 1
4086 enddef
4087 endclass
4088
4089 def A_CallFuncs(a: A)
4090 a.Func1()
4091 a.Func2()
4092 a.Func3()
4093 enddef
4094
4095 def B_CallFuncs(b: B)
4096 b.Func1()
4097 b.Func2()
4098 b.Func3()
4099 enddef
4100
4101 def C_CallFuncs(c: C)
4102 c.Func1()
4103 c.Func2()
4104 c.Func3()
4105 enddef
4106
4107 var cobj = C.new()
4108 A_CallFuncs(cobj)
4109 B_CallFuncs(cobj)
4110 C_CallFuncs(cobj)
4111 assert_equal(3, A_func1)
4112 assert_equal(0, A_func2)
4113 assert_equal(0, A_func3)
4114 assert_equal(3, B_func2)
4115 assert_equal(0, B_func3)
4116 assert_equal(3, C_func3)
4117 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004118 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004119enddef
4120
4121" Test for using members from three levels of classes
4122def Test_multi_level_member_access()
4123 var lines =<< trim END
4124 vim9script
4125
4126 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004127 public var val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004128 endclass
4129
4130 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004131 public var val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004132 endclass
4133
4134 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01004135 public var val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004136 endclass
4137
4138 def A_members(a: A)
4139 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004140 enddef
4141
4142 def B_members(b: B)
4143 b.val1 += 1
4144 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004145 enddef
4146
4147 def C_members(c: C)
4148 c.val1 += 1
4149 c.val2 += 1
4150 c.val3 += 1
4151 enddef
4152
4153 var cobj = C.new()
4154 A_members(cobj)
4155 B_members(cobj)
4156 C_members(cobj)
4157 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004158 assert_equal(2, cobj.val2)
4159 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004160 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004161 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004162enddef
4163
LemonBoy0ffc17a2023-08-20 18:09:11 +02004164" Test expansion of <stack> with class methods.
4165def Test_stack_expansion_with_methods()
4166 var lines =<< trim END
4167 vim9script
4168
4169 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004170 def M1()
4171 F0()
4172 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02004173 endclass
4174
4175 def F0()
Ernie Rael16cdfa62024-04-02 19:05:39 +02004176 assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
LemonBoy0ffc17a2023-08-20 18:09:11 +02004177 enddef
4178
4179 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004180 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02004181 enddef
4182
4183 F()
4184 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004185 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02004186enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004187
4188" Test the return type of the new() constructor
4189def Test_new_return_type()
4190 # new() uses the default return type and there is no return statement
4191 var lines =<< trim END
4192 vim9script
4193
4194 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004195 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004196
4197 def new(this._bufnr)
4198 if !bufexists(this._bufnr)
4199 this._bufnr = -1
4200 endif
4201 enddef
4202 endclass
4203
4204 var c = C.new(12345)
4205 assert_equal('object<C>', typename(c))
4206
4207 var v1: C
4208 v1 = C.new(12345)
4209 assert_equal('object<C>', typename(v1))
4210
4211 def F()
4212 var v2: C
4213 v2 = C.new(12345)
4214 assert_equal('object<C>', typename(v2))
4215 enddef
4216 F()
4217 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004218 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004219
4220 # new() uses the default return type and an empty 'return' statement
4221 lines =<< trim END
4222 vim9script
4223
4224 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004225 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004226
4227 def new(this._bufnr)
4228 if !bufexists(this._bufnr)
4229 this._bufnr = -1
4230 return
4231 endif
4232 enddef
4233 endclass
4234
4235 var c = C.new(12345)
4236 assert_equal('object<C>', typename(c))
4237
4238 var v1: C
4239 v1 = C.new(12345)
4240 assert_equal('object<C>', typename(v1))
4241
4242 def F()
4243 var v2: C
4244 v2 = C.new(12345)
4245 assert_equal('object<C>', typename(v2))
4246 enddef
4247 F()
4248 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004249 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004250
4251 # new() uses "any" return type and returns "this"
4252 lines =<< trim END
4253 vim9script
4254
4255 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004256 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004257
4258 def new(this._bufnr): any
4259 if !bufexists(this._bufnr)
4260 this._bufnr = -1
4261 return this
4262 endif
4263 enddef
4264 endclass
4265 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004266 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004267
4268 # new() uses 'Dict' return type and returns a Dict
4269 lines =<< trim END
4270 vim9script
4271
4272 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004273 var _state: dict<any>
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004274
4275 def new(): dict<any>
4276 this._state = {}
4277 return this._state
4278 enddef
4279 endclass
4280
4281 var c = C.new()
4282 assert_equal('object<C>', typename(c))
4283 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004284 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004285enddef
4286
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004287" Test for checking a member initialization type at run time.
4288def Test_runtime_type_check_for_member_init()
4289 var lines =<< trim END
4290 vim9script
4291
4292 var retnum: bool = false
4293
4294 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004295 retnum = !retnum
4296 if retnum
4297 return 1
4298 else
4299 return "hello"
4300 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004301 enddef
4302
4303 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004304 var _foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004305 endclass
4306
4307 var c1 = C.new()
4308 var c2 = C.new()
4309 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004310 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004311enddef
4312
4313" Test for locking a variable referring to an object and reassigning to another
4314" object.
Ernie Raelee865f32023-09-29 19:53:55 +02004315def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004316 var lines =<< trim END
4317 vim9script
4318
4319 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004320 var val: number
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004321 def new(this.val)
4322 enddef
4323 endclass
4324
4325 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
4326 lockvar 2 some_dict
4327
4328 var current: C
4329 current = some_dict['c']
4330 assert_equal(3, current.val)
4331 current = some_dict['b']
4332 assert_equal(2, current.val)
4333
4334 def F()
4335 current = some_dict['c']
4336 enddef
4337
4338 def G()
4339 current = some_dict['b']
4340 enddef
4341
4342 F()
4343 assert_equal(3, current.val)
4344 G()
4345 assert_equal(2, current.val)
4346 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004347 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004348enddef
4349
Ernie Raelee865f32023-09-29 19:53:55 +02004350" Test trying to lock an object variable from various places
4351def Test_lockvar_object_variable()
4352 # An object variable lockvar has several cases:
4353 # object method, scriptlevel, scriplevel from :def, :def arg
4354 # method arg, static method arg.
4355 # Also different depths
4356
Ernie Raelee865f32023-09-29 19:53:55 +02004357 #
4358 # lockvar of read-only object variable
4359 #
4360
4361 # read-only lockvar from object method
4362 var lines =<< trim END
4363 vim9script
4364
4365 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004366 var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004367 def Lock()
4368 lockvar this.val1
4369 enddef
4370 endclass
4371 var o = C.new(3)
4372 o.Lock()
4373 END
Ernie Rael64885642023-10-04 20:16:22 +02004374 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004375
4376 # read-only lockvar from scriptlevel
4377 lines =<< trim END
4378 vim9script
4379
4380 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004381 var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004382 endclass
4383 var o = C.new(3)
4384 lockvar o.val2
4385 END
4386 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
4387
4388 # read-only lockvar of scriptlevel variable from def
4389 lines =<< trim END
4390 vim9script
4391
4392 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004393 var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004394 endclass
4395 var o = C.new(3)
4396 def Lock()
4397 lockvar o.val3
4398 enddef
4399 Lock()
4400 END
4401 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
4402
4403 # read-only lockvar of def argument variable
4404 lines =<< trim END
4405 vim9script
4406
4407 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004408 var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004409 endclass
4410 def Lock(o: C)
4411 lockvar o.val4
4412 enddef
4413 Lock(C.new(3))
4414 END
4415 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
4416
Ernie Raelee865f32023-09-29 19:53:55 +02004417 # read-only lockvar from object method arg
4418 lines =<< trim END
4419 vim9script
4420
4421 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004422 var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004423 def Lock(c: C)
4424 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004425 enddef
4426 endclass
4427 var o = C.new(3)
4428 o.Lock(C.new(5))
4429 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004430 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004431
4432 # read-only lockvar from class method arg
4433 lines =<< trim END
4434 vim9script
4435
4436 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004437 var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004438 static def Lock(c: C)
4439 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004440 enddef
4441 endclass
4442 var o = C.new(3)
4443 C.Lock(o)
4444 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004445 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004446
4447 #
4448 # lockvar of public object variable
4449 #
4450
4451 # lockvar from object method
4452 lines =<< trim END
4453 vim9script
4454
4455 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004456 public var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004457 def Lock()
4458 lockvar this.val1
4459 enddef
4460 endclass
4461 var o = C.new(3)
4462 o.Lock()
4463 END
4464 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
4465
4466 # lockvar from scriptlevel
4467 lines =<< trim END
4468 vim9script
4469
4470 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004471 public var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004472 endclass
4473 var o = C.new(3)
4474 lockvar o.val2
4475 END
4476 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
4477
4478 # lockvar of scriptlevel variable from def
4479 lines =<< trim END
4480 vim9script
4481
4482 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004483 public var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004484 endclass
4485 var o = C.new(3)
4486 def Lock()
4487 lockvar o.val3
4488 enddef
4489 Lock()
4490 END
4491 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
4492
4493 # lockvar of def argument variable
4494 lines =<< trim END
4495 vim9script
4496
4497 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004498 public var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004499 endclass
4500 def Lock(o: C)
4501 lockvar o.val4
4502 enddef
4503 Lock(C.new(3))
4504 END
4505 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
4506
4507 # lockvar from object method arg
4508 lines =<< trim END
4509 vim9script
4510
4511 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004512 public var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004513 def Lock(c: C)
4514 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004515 enddef
4516 endclass
4517 var o = C.new(3)
4518 o.Lock(C.new(5))
4519 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004520 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004521
4522 # lockvar from class method arg
4523 lines =<< trim END
4524 vim9script
4525
4526 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004527 public var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004528 static def Lock(c: C)
4529 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004530 enddef
4531 endclass
4532 var o = C.new(3)
4533 C.Lock(o)
4534 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004535 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004536enddef
4537
4538" Test trying to lock a class variable from various places
4539def Test_lockvar_class_variable()
4540
4541 # lockvar bare static from object method
4542 var lines =<< trim END
4543 vim9script
4544
4545 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004546 public static var sval1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004547 def Lock()
4548 lockvar sval1
4549 enddef
4550 endclass
4551 var o = C.new()
4552 o.Lock()
4553 END
4554 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
4555
4556 # lockvar C.static from object method
4557 lines =<< trim END
4558 vim9script
4559
4560 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004561 public static var sval2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004562 def Lock()
4563 lockvar C.sval2
4564 enddef
4565 endclass
4566 var o = C.new()
4567 o.Lock()
4568 END
4569 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
4570
4571 # lockvar bare static from class method
4572 lines =<< trim END
4573 vim9script
4574
4575 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004576 public static var sval3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004577 static def Lock()
4578 lockvar sval3
4579 enddef
4580 endclass
4581 C.Lock()
4582 END
4583 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
4584
4585 # lockvar C.static from class method
4586 lines =<< trim END
4587 vim9script
4588
4589 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004590 public static var sval4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004591 static def Lock()
4592 lockvar C.sval4
4593 enddef
4594 endclass
4595 C.Lock()
4596 END
4597 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
4598
4599 # lockvar C.static from script level
4600 lines =<< trim END
4601 vim9script
4602
4603 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004604 public static var sval5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004605 endclass
4606 lockvar C.sval5
4607 END
4608 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
4609
4610 # lockvar o.static from script level
4611 lines =<< trim END
4612 vim9script
4613
4614 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004615 public static var sval6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004616 endclass
4617 var o = C.new()
4618 lockvar o.sval6
4619 END
4620 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
4621enddef
4622
4623" Test locking an argument to :def
4624def Test_lockvar_argument()
4625 # Lockvar a function arg
4626 var lines =<< trim END
4627 vim9script
4628
4629 def Lock(val: any)
4630 lockvar val
4631 enddef
4632
4633 var d = {a: 1, b: 2}
4634 Lock(d)
4635
4636 d->extend({c: 3})
4637 END
4638 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
4639
4640 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
4641 # class member in "C". This tests lval_root_is_arg.
4642 lines =<< trim END
4643 vim9script
4644
4645 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004646 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004647 endclass
4648
4649 def Lock2(sval: any)
4650 lockvar sval
4651 enddef
4652
4653 var o = C.new()
4654 Lock2(o)
4655 END
4656 v9.CheckSourceSuccess(lines)
4657
4658 # Lock a class.
4659 lines =<< trim END
4660 vim9script
4661
4662 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004663 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004664 endclass
4665
4666 def Lock2(sval: any)
4667 lockvar sval
4668 enddef
4669
4670 Lock2(C)
4671 END
Ernie Raelb077b582023-12-14 20:11:44 +01004672 v9.CheckSourceFailure(lines, 'E1405: Class "C" cannot be used as a value')
Ernie Raelee865f32023-09-29 19:53:55 +02004673
4674 # Lock an object.
4675 lines =<< trim END
4676 vim9script
4677
4678 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004679 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004680 endclass
4681
4682 def Lock2(sval: any)
4683 lockvar sval
4684 enddef
4685
4686 Lock2(C.new())
4687 END
4688 v9.CheckSourceSuccess(lines)
4689
4690 # In this case (unlike previous) "lockvar sval" is a class member.
4691 lines =<< trim END
4692 vim9script
4693
4694 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004695 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004696 def Lock2()
4697 lockvar sval
4698 enddef
4699 endclass
4700
4701
4702 var o = C.new()
4703 o.Lock2()
4704 END
4705 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4706enddef
4707
4708" Test that this can be locked without error
4709def Test_lockvar_this()
4710 # lockvar this
4711 var lines =<< trim END
4712 vim9script
4713 class C
4714 def TLock()
4715 lockvar this
4716 enddef
4717 endclass
4718 var o = C.new()
4719 o.TLock()
4720 END
4721 v9.CheckSourceSuccess(lines)
4722
4723 # lockvar four (four letter word, but not this)
4724 lines =<< trim END
4725 vim9script
4726 class C
4727 def TLock4()
4728 var four: number
4729 lockvar four
4730 enddef
4731 endclass
4732 var o = C.new()
4733 o.TLock4()
4734 END
4735 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4736
4737 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4738 lines =<< trim END
4739 vim9script
4740 class C
4741 def TLock5()
4742 var this5: number
4743 lockvar this5
4744 enddef
4745 endclass
4746 var o = C.new()
4747 o.TLock5()
4748 END
4749 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4750enddef
4751
4752" Test some general lockvar cases
4753def Test_lockvar_general()
4754 # lockvar an object and a class. It does nothing
4755 var lines =<< trim END
4756 vim9script
4757 class C
4758 endclass
4759 var o = C.new()
4760 lockvar o
4761 lockvar C
4762 END
4763 v9.CheckSourceSuccess(lines)
4764
4765 # Lock a list element that's nested in an object variable from a :def
4766 lines =<< trim END
4767 vim9script
4768
4769 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004770 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004771 endclass
4772 def Lock2(obj: any)
4773 lockvar obj.val[1]
4774 enddef
4775
4776 var o = C.new()
4777 Lock2(o)
4778 o.val[0] = [9]
4779 assert_equal([ [9], [2], [3] ], o.val)
4780 try
4781 o.val[1] = [999]
4782 call assert_false(true, 'assign should have failed')
4783 catch
4784 assert_exception('E741:')
4785 endtry
4786 o.val[2] = [8]
4787 assert_equal([ [9], [2], [8] ], o.val)
4788 END
4789 v9.CheckSourceSuccess(lines)
4790
4791 # Lock a list element that's nested in an object variable from scriptlevel
4792 lines =<< trim END
4793 vim9script
4794
4795 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004796 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004797 endclass
4798
4799 var o = C.new()
4800 lockvar o.val[1]
4801 o.val[0] = [9]
4802 assert_equal([ [9], [2], [3] ], o.val)
4803 try
4804 o.val[1] = [999]
4805 call assert_false(true, 'assign should have failed')
4806 catch
4807 assert_exception('E741:')
4808 endtry
4809 o.val[2] = [8]
4810 assert_equal([ [9], [2], [8] ], o.val)
4811 END
4812 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004813
4814 # lock a script level variable from an object method
4815 lines =<< trim END
4816 vim9script
4817
4818 class C
4819 def Lock()
4820 lockvar l
4821 enddef
4822 endclass
4823
4824 var l = [1]
4825 C.new().Lock()
4826 l[0] = 11
4827 END
4828 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4829
Ernie Rael03042a22023-11-11 08:53:32 +01004830 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004831 # in an object fetched via a script level list
4832 lines =<< trim END
4833 vim9script
4834
4835 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004836 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004837 def Lock()
4838 lockvar lc[0]._v1[1]
4839 enddef
4840 endclass
4841
4842 var l = [[1], [2], [3]]
4843 var o = C.new(l)
4844 var lc: list<C> = [ o ]
4845
4846 o.Lock()
4847 l[0] = [22]
4848 l[1] = [33]
4849 END
4850 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4851
4852 # similar to the previous test, except the locking code is executing
Ernie Rael03042a22023-11-11 08:53:32 +01004853 # in a class that does not own the protected variable.
4854 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02004855 # the same name.
4856 lines =<< trim END
4857 vim9script
4858
4859 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004860 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004861 def Lock(obj: any)
4862 lockvar lc[0]._v1[1]
4863 enddef
4864 endclass
4865
4866 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004867 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004868 endclass
4869
4870 var l = [[1], [2], [3]]
4871 var o = C.new(l)
4872 var lc: list<C> = [ o ]
4873
4874 var o2 = C2.new()
4875 o2.Lock(o)
4876 END
Ernie Rael03042a22023-11-11 08:53:32 +01004877 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004878enddef
4879
Ernie Rael9771b2a2023-10-07 22:05:40 +02004880" Test builtin islocked()
4881def Test_lockvar_islocked()
4882 # Can't lock class/object variable
4883 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01004884 # Lock item of variable's value (a list item)
4885 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02004886 var lines =<< trim END
4887 vim9script
4888
4889 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004890 var o0: list<list<number>> = [ [0], [1], [2]]
4891 var o1: list<list<number>> = [[10], [11], [12]]
4892 static var c0: list<list<number>> = [[20], [21], [22]]
4893 static var c1: list<list<number>> = [[30], [31], [32]]
Ernie Rael9771b2a2023-10-07 22:05:40 +02004894 endclass
4895
4896 def LockIt(arg: any)
4897 lockvar arg
4898 enddef
4899
4900 def UnlockIt(arg: any)
4901 unlockvar arg
4902 enddef
4903
4904 var obj = C.new()
4905 #lockvar obj.o1 # can't lock something you can't write to
4906
4907 try
4908 lockvar obj.o1 # can't lock something you can't write to
4909 call assert_false(1, '"lockvar obj.o1" should have failed')
4910 catch
4911 call assert_exception('E1335:')
4912 endtry
4913
4914 LockIt(obj.o1) # but can lock it's value
4915 assert_equal(1, islocked("obj.o1"))
4916 assert_equal(1, islocked("obj.o1[0]"))
4917 assert_equal(1, islocked("obj.o1[1]"))
4918 UnlockIt(obj.o1)
4919 assert_equal(0, islocked("obj.o1"))
4920 assert_equal(0, islocked("obj.o1[0]"))
4921
4922 lockvar obj.o1[0]
4923 assert_equal(0, islocked("obj.o1"))
4924 assert_equal(1, islocked("obj.o1[0]"))
4925 assert_equal(0, islocked("obj.o1[1]"))
4926 unlockvar obj.o1[0]
4927 assert_equal(0, islocked("obj.o1"))
4928 assert_equal(0, islocked("obj.o1[0]"))
4929
4930 # Same thing, but with a static
4931
4932 try
4933 lockvar C.c1 # can't lock something you can't write to
4934 call assert_false(1, '"lockvar C.c1" should have failed')
4935 catch
4936 call assert_exception('E1335:')
4937 endtry
4938
4939 LockIt(C.c1) # but can lock it's value
4940 assert_equal(1, islocked("C.c1"))
4941 assert_equal(1, islocked("C.c1[0]"))
4942 assert_equal(1, islocked("C.c1[1]"))
4943 UnlockIt(C.c1)
4944 assert_equal(0, islocked("C.c1"))
4945 assert_equal(0, islocked("C.c1[0]"))
4946
4947 lockvar C.c1[0]
4948 assert_equal(0, islocked("C.c1"))
4949 assert_equal(1, islocked("C.c1[0]"))
4950 assert_equal(0, islocked("C.c1[1]"))
4951 unlockvar C.c1[0]
4952 assert_equal(0, islocked("C.c1"))
4953 assert_equal(0, islocked("C.c1[0]"))
4954 END
4955 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02004956
4957 # Do islocked() from an object method
4958 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02004959 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02004960 vim9script
4961
4962 var l0o0 = [ [0], [1], [2]]
4963 var l0o1 = [ [10], [11], [12]]
4964 var l0c0 = [[120], [121], [122]]
4965 var l0c1 = [[130], [131], [132]]
4966
4967 class C0
Doug Kearns74da0ee2023-12-14 20:26:26 +01004968 var o0: list<list<number>> = l0o0
4969 var o1: list<list<number>> = l0o1
4970 static var c0: list<list<number>> = l0c0
4971 static var c1: list<list<number>> = l0c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004972 def Islocked(arg: string): number
4973 return islocked(arg)
4974 enddef
4975 static def SIslocked(arg: string): number
4976 return islocked(arg)
4977 enddef
4978 endclass
4979
4980 var l2o0 = [[20000], [20001], [20002]]
4981 var l2o1 = [[20010], [20011], [20012]]
4982 var l2c0 = [[20120], [20121], [20122]]
4983 var l2c1 = [[20130], [20131], [20132]]
4984
4985 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004986 var o0: list<list<number>> = l2o0
4987 var o1: list<list<number>> = l2o1
4988 static var c0: list<list<number>> = l2c0
4989 static var c1: list<list<number>> = l2c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004990 def Islocked(arg: string): number
4991 return islocked(arg)
4992 enddef
4993 static def SIslocked(arg: string): number
4994 return islocked(arg)
4995 enddef
4996 endclass
4997
4998 var obj0 = C0.new()
4999 var obj2 = C2.new()
5000
5001 var l = [ obj0, null_object, obj2 ]
5002
5003 # lock list, object func access through script var expr
5004 assert_equal(0, obj0.Islocked("l[0].o0"))
5005 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
5006 lockvar l0o0
5007 assert_equal(1, obj0.Islocked("l[0].o0"))
5008 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
5009
5010 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
5011
5012 # lock list element, object func access through script var expr
5013 lockvar l0o1[1]
5014 assert_equal(0, obj0.Islocked("this.o1[0]"))
5015 assert_equal(1, obj0.Islocked("this.o1[1]"))
5016
5017 assert_equal(0, obj0.Islocked("this.o1"))
5018 lockvar l0o1
5019 assert_equal(1, obj0.Islocked("this.o1"))
5020 unlockvar l0o1
5021
5022 lockvar l0c1[1]
5023
5024 # static by class name member expr from same class
5025 assert_equal(0, obj0.Islocked("C0.c1[0]"))
5026 assert_equal(1, obj0.Islocked("C0.c1[1]"))
5027 # static by bare name member expr from same class
5028 assert_equal(0, obj0.Islocked("c1[0]"))
5029 assert_equal(1, obj0.Islocked("c1[1]"))
5030
5031 # static by class name member expr from other class
5032 assert_equal(0, obj2.Islocked("C0.c1[0]"))
5033 assert_equal(1, obj2.Islocked("C0.c1[1]"))
5034 # static by bare name member expr from other class
5035 assert_equal(0, obj2.Islocked("c1[0]"))
5036 assert_equal(0, obj2.Islocked("c1[1]"))
5037
5038
5039 # static by bare name in same class
5040 assert_equal(0, obj0.Islocked("c0"))
5041 lockvar l0c0
5042 assert_equal(1, obj0.Islocked("c0"))
5043
5044 #
5045 # similar stuff, but use static method
5046 #
5047
5048 unlockvar l0o0
5049
5050 # lock list, object func access through script var expr
5051 assert_equal(0, C0.SIslocked("l[0].o0"))
5052 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
5053 lockvar l0o0
5054 assert_equal(1, C0.SIslocked("l[0].o0"))
5055 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
5056
5057 unlockvar l0o1
5058
5059 # can't access "this" from class method
5060 try
5061 C0.SIslocked("this.o1[0]")
5062 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
5063 catch
5064 call assert_exception('E121: Undefined variable: this')
5065 endtry
5066
5067 lockvar l0c1[1]
5068
5069 # static by class name member expr from same class
5070 assert_equal(0, C0.SIslocked("C0.c1[0]"))
5071 assert_equal(1, C0.SIslocked("C0.c1[1]"))
5072 # static by bare name member expr from same class
5073 assert_equal(0, C0.SIslocked("c1[0]"))
5074 assert_equal(1, C0.SIslocked("c1[1]"))
5075
5076 # static by class name member expr from other class
5077 assert_equal(0, C2.SIslocked("C0.c1[0]"))
5078 assert_equal(1, C2.SIslocked("C0.c1[1]"))
5079 # static by bare name member expr from other class
5080 assert_equal(0, C2.SIslocked("c1[0]"))
5081 assert_equal(0, C2.SIslocked("c1[1]"))
5082
5083
5084 # static by bare name in same class
5085 unlockvar l0c0
5086 assert_equal(0, C0.SIslocked("c0"))
5087 lockvar l0c0
5088 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02005089 END
Ernie Rael4c8da022023-10-11 21:35:11 +02005090 v9.CheckSourceSuccess(lines)
5091
5092 # Check islocked class/object from various places.
5093 lines =<< trim END
5094 vim9script
5095
5096 class C
5097 def Islocked(arg: string): number
5098 return islocked(arg)
5099 enddef
5100 static def SIslocked(arg: string): number
5101 return islocked(arg)
5102 enddef
5103 endclass
5104 var obj = C.new()
5105
5106 # object method
5107 assert_equal(0, obj.Islocked("this"))
5108 assert_equal(0, obj.Islocked("C"))
5109
5110 # class method
5111 ### assert_equal(0, C.SIslocked("this"))
5112 assert_equal(0, C.SIslocked("C"))
5113
5114 #script level
5115 var v: number
5116 v = islocked("C")
5117 assert_equal(0, v)
5118 v = islocked("obj")
5119 assert_equal(0, v)
5120 END
5121 v9.CheckSourceSuccess(lines)
5122enddef
5123
5124def Test_lockvar_islocked_notfound()
5125 # Try non-existent things
5126 var lines =<< trim END
5127 vim9script
5128
5129 class C
5130 def Islocked(arg: string): number
5131 return islocked(arg)
5132 enddef
5133 static def SIslocked(arg: string): number
5134 return islocked(arg)
5135 enddef
5136 endclass
5137 var obj = C.new()
5138 assert_equal(-1, obj.Islocked("anywhere"))
5139 assert_equal(-1, C.SIslocked("notanywhere"))
5140 END
5141 v9.CheckSourceSuccess(lines)
5142
5143 # Something not found of the form "name1.name2" is an error
5144 lines =<< trim END
5145 vim9script
5146
5147 islocked("one.two")
5148 END
5149 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
5150
5151 lines =<< trim END
5152 vim9script
5153
5154 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005155 var val = { key: "value" }
Ernie Rael4c8da022023-10-11 21:35:11 +02005156 def Islocked(arg: string): number
5157 return islocked(arg)
5158 enddef
5159 endclass
5160 var obj = C.new()
5161 obj.Islocked("this.val.not_there"))
5162 END
5163 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
5164
5165 lines =<< trim END
5166 vim9script
5167
5168 class C
5169 def Islocked(arg: string): number
5170 return islocked(arg)
5171 enddef
5172 endclass
5173 var obj = C.new()
5174 obj.Islocked("this.notobjmember")
5175 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005176 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02005177
5178 # access a script variable through methods
5179 lines =<< trim END
5180 vim9script
5181
5182 var l = [1]
5183 class C
5184 def Islocked(arg: string): number
5185 return islocked(arg)
5186 enddef
5187 static def SIslocked(arg: string): number
5188 return islocked(arg)
5189 enddef
5190 endclass
5191 var obj = C.new()
5192 assert_equal(0, obj.Islocked("l"))
5193 assert_equal(0, C.SIslocked("l"))
5194 lockvar l
5195 assert_equal(1, obj.Islocked("l"))
5196 assert_equal(1, C.SIslocked("l"))
5197 END
5198 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02005199enddef
5200
Ernie Rael03042a22023-11-11 08:53:32 +01005201" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005202def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005203 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005204 var lines =<< trim END
5205 vim9script
5206
5207 class A
5208 def _Foo(): number
5209 return 1234
5210 enddef
5211 endclass
5212 var a = A.new()
5213 a._Foo()
5214 END
Ernie Rael03042a22023-11-11 08:53:32 +01005215 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005216
Ernie Rael03042a22023-11-11 08:53:32 +01005217 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005218 lines =<< trim END
5219 vim9script
5220
5221 class A
5222 def _Foo(): number
5223 return 1234
5224 enddef
5225 endclass
5226 def T()
5227 var a = A.new()
5228 a._Foo()
5229 enddef
5230 T()
5231 END
Ernie Rael03042a22023-11-11 08:53:32 +01005232 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005233
Ernie Rael03042a22023-11-11 08:53:32 +01005234 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005235 lines =<< trim END
5236 vim9script
5237
5238 class A
5239 def _Foo(): number
5240 return 1234
5241 enddef
5242 def Bar(): number
5243 return this._Foo()
5244 enddef
5245 endclass
5246 var a = A.new()
5247 assert_equal(1234, a.Bar())
5248 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005249 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005250
Ernie Rael03042a22023-11-11 08:53:32 +01005251 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005252 lines =<< trim END
5253 vim9script
5254
5255 class A
5256 def _Foo(): number
5257 return 1234
5258 enddef
5259 def Bar(): number
5260 return this._Foo()
5261 enddef
5262 endclass
5263 def T()
5264 var a = A.new()
5265 assert_equal(1234, a.Bar())
5266 enddef
5267 T()
5268 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005269 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005270
Ernie Rael03042a22023-11-11 08:53:32 +01005271 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005272 lines =<< trim END
5273 vim9script
5274
5275 class A
5276 def _Foo(): number
5277 return 1234
5278 enddef
5279 def Bar(): number
5280 return _Foo()
5281 enddef
5282 endclass
5283 var a = A.new()
5284 a.Bar()
5285 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005286 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005287
Ernie Rael03042a22023-11-11 08:53:32 +01005288 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005289 lines =<< trim END
5290 vim9script
5291
5292 class A
5293 def _Foo(): number
5294 return 1234
5295 enddef
5296 endclass
5297 A._Foo()
5298 END
Ernie Rael03042a22023-11-11 08:53:32 +01005299 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005300
Ernie Rael03042a22023-11-11 08:53:32 +01005301 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005302 lines =<< trim END
5303 vim9script
5304
5305 class A
5306 def _Foo()
5307 enddef
5308 def _Foo()
5309 enddef
5310 endclass
5311 var a = A.new()
5312 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005313 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005314
Ernie Rael03042a22023-11-11 08:53:32 +01005315 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005316 lines =<< trim END
5317 vim9script
5318
5319 class A
5320 def _Foo()
5321 enddef
5322 def Foo()
5323 enddef
5324 endclass
5325 var a = A.new()
5326 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005327 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005328
Ernie Rael03042a22023-11-11 08:53:32 +01005329 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005330 lines =<< trim END
5331 vim9script
5332
5333 class A
5334 def Foo()
5335 enddef
5336 def _Foo()
5337 enddef
5338 endclass
5339 var a = A.new()
5340 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005341 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005342
Ernie Rael03042a22023-11-11 08:53:32 +01005343 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005344 lines =<< trim END
5345 vim9script
5346
5347 class A
5348 def Foo(): number
5349 return 100
5350 enddef
5351 def _Bar(): number
5352 return 200
5353 enddef
5354 def _Baz()
5355 assert_equal(100, this.Foo())
5356 assert_equal(200, this._Bar())
5357 enddef
5358 def T()
5359 this._Baz()
5360 enddef
5361 endclass
5362 var a = A.new()
5363 a.T()
5364 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005365 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005366
Ernie Rael03042a22023-11-11 08:53:32 +01005367 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005368 lines =<< trim END
5369 vim9script
5370
5371 class A
5372 def _Foo(): number
5373 return 100
5374 enddef
5375 endclass
5376 class B
5377 def Foo(): number
5378 var a = A.new()
5379 a._Foo()
5380 enddef
5381 endclass
5382 var b = B.new()
5383 b.Foo()
5384 END
Ernie Rael03042a22023-11-11 08:53:32 +01005385 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005386
Ernie Rael03042a22023-11-11 08:53:32 +01005387 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005388 lines =<< trim END
5389 vim9script
5390 class A
5391 def _Foo(): number
5392 return 1234
5393 enddef
5394 endclass
5395 class B extends A
5396 def Bar()
5397 enddef
5398 endclass
5399 class C extends B
5400 def Baz(): number
5401 return this._Foo()
5402 enddef
5403 endclass
5404 var c = C.new()
5405 assert_equal(1234, c.Baz())
5406 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005407 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005408
Ernie Rael03042a22023-11-11 08:53:32 +01005409 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005410 lines =<< trim END
5411 vim9script
5412 class A
5413 def _Foo(): number
5414 return 1234
5415 enddef
5416 endclass
5417 class B extends A
5418 def Bar()
5419 enddef
5420 endclass
5421 class C extends B
5422 def Baz(): number
5423 enddef
5424 endclass
5425 var c = C.new()
5426 assert_equal(1234, c._Foo())
5427 END
Ernie Rael03042a22023-11-11 08:53:32 +01005428 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005429
5430 # Using "_" prefix in a method name should fail outside of a class
5431 lines =<< trim END
5432 vim9script
5433 def _Foo(): number
5434 return 1234
5435 enddef
5436 var a = _Foo()
5437 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005438 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005439enddef
5440
Ernie Rael03042a22023-11-11 08:53:32 +01005441" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005442def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005443 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005444 var lines =<< trim END
5445 vim9script
5446
5447 class A
5448 static def _Foo(): number
5449 return 1234
5450 enddef
5451 endclass
5452 A._Foo()
5453 END
Ernie Rael03042a22023-11-11 08:53:32 +01005454 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005455
Ernie Rael03042a22023-11-11 08:53:32 +01005456 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005457 lines =<< trim END
5458 vim9script
5459
5460 class A
5461 static def _Foo(): number
5462 return 1234
5463 enddef
5464 endclass
5465 def T()
5466 A._Foo()
5467 enddef
5468 T()
5469 END
Ernie Rael03042a22023-11-11 08:53:32 +01005470 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005471
Ernie Rael03042a22023-11-11 08:53:32 +01005472 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005473 lines =<< trim END
5474 vim9script
5475
5476 class A
5477 static def _Foo(): number
5478 return 1234
5479 enddef
5480 endclass
5481 var a = A.new()
5482 a._Foo()
5483 END
Ernie Rael03042a22023-11-11 08:53:32 +01005484 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005485
Ernie Rael03042a22023-11-11 08:53:32 +01005486 # Try calling a class protected method using an object (from a def function)
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 def T()
5496 var a = A.new()
5497 a._Foo()
5498 enddef
5499 T()
5500 END
Ernie Rael03042a22023-11-11 08:53:32 +01005501 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005502
Ernie Rael03042a22023-11-11 08:53:32 +01005503 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005504 lines =<< trim END
5505 vim9script
5506
5507 class A
5508 static def _Foo(): number
5509 return 1234
5510 enddef
5511 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005512 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005513 enddef
5514 endclass
5515 var a = A.new()
5516 a.Bar()
5517 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005518 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005519
Ernie Rael03042a22023-11-11 08:53:32 +01005520 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005521 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005522 lines =<< trim END
5523 vim9script
5524
5525 class A
5526 static def _Foo1(): number
5527 return 1234
5528 enddef
5529 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005530 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005531 enddef
5532 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005533 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005534 enddef
5535 endclass
5536 var a = A.new()
5537 a.Bar()
5538 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005539 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005540
Ernie Rael03042a22023-11-11 08:53:32 +01005541 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005542 lines =<< trim END
5543 vim9script
5544
5545 class A
5546 static def _Foo()
5547 enddef
5548 static def Foo()
5549 enddef
5550 endclass
5551 var a = A.new()
5552 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005553 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005554
Ernie Rael03042a22023-11-11 08:53:32 +01005555 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005556 lines =<< trim END
5557 vim9script
5558
5559 class A
5560 static def _Foo(): number
5561 return 1234
5562 enddef
5563 endclass
5564 class B
5565 def Foo(): number
5566 return A._Foo()
5567 enddef
5568 endclass
5569 var b = B.new()
5570 assert_equal(1234, b.Foo())
5571 END
Ernie Rael03042a22023-11-11 08:53:32 +01005572 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005573
Ernie Rael03042a22023-11-11 08:53:32 +01005574 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005575 lines =<< trim END
5576 vim9script
5577 class A
5578 static def _Foo(): number
5579 return 1234
5580 enddef
5581 endclass
5582 class B extends A
5583 def Bar()
5584 enddef
5585 endclass
5586 class C extends B
5587 def Baz(): number
5588 return A._Foo()
5589 enddef
5590 endclass
5591 var c = C.new()
5592 assert_equal(1234, c.Baz())
5593 END
Ernie Rael03042a22023-11-11 08:53:32 +01005594 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005595
Ernie Rael03042a22023-11-11 08:53:32 +01005596 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005597 lines =<< trim END
5598 vim9script
5599 class A
5600 static def _Foo(): number
5601 return 1234
5602 enddef
5603 endclass
5604 class B extends A
5605 def Bar()
5606 enddef
5607 endclass
5608 class C extends B
5609 static def Baz(): number
5610 return A._Foo()
5611 enddef
5612 endclass
5613 assert_equal(1234, C.Baz())
5614 END
Ernie Rael03042a22023-11-11 08:53:32 +01005615 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005616
Ernie Rael03042a22023-11-11 08:53:32 +01005617 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005618 lines =<< trim END
5619 vim9script
5620 class A
5621 static def _Foo(): number
5622 return 1234
5623 enddef
5624 endclass
5625 class B extends A
5626 def Bar()
5627 enddef
5628 endclass
5629 class C extends B
5630 def Baz(): number
5631 enddef
5632 endclass
5633 var c = C.new()
5634 assert_equal(1234, C._Foo())
5635 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005636 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005637enddef
5638
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005639" Test for using the return value of a class/object method as a function
5640" argument.
5641def Test_objmethod_funcarg()
5642 var lines =<< trim END
5643 vim9script
5644
5645 class C
5646 def Foo(): string
5647 return 'foo'
5648 enddef
5649 endclass
5650
5651 def Bar(a: number, s: string): string
5652 return s
5653 enddef
5654
5655 def Baz(c: C)
5656 assert_equal('foo', Bar(10, c.Foo()))
5657 enddef
5658
5659 var t = C.new()
5660 Baz(t)
5661 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005662 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005663
5664 lines =<< trim END
5665 vim9script
5666
5667 class C
5668 static def Foo(): string
5669 return 'foo'
5670 enddef
5671 endclass
5672
5673 def Bar(a: number, s: string): string
5674 return s
5675 enddef
5676
5677 def Baz()
5678 assert_equal('foo', Bar(10, C.Foo()))
5679 enddef
5680
5681 Baz()
5682 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005683 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005684enddef
5685
Ernie Raelcf138d42023-09-06 20:45:03 +02005686def Test_static_inheritence()
5687 # subclasses get their own static copy
5688 var lines =<< trim END
5689 vim9script
5690
5691 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005692 static var _svar: number
5693 var _mvar: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005694 def new()
5695 _svar = 1
5696 this._mvar = 101
5697 enddef
5698 def AccessObject(): number
5699 return this._mvar
5700 enddef
5701 def AccessStaticThroughObject(): number
5702 return _svar
5703 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005704 endclass
5705
5706 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005707 def new()
5708 this._mvar = 102
5709 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005710 endclass
5711
5712 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005713 def new()
5714 this._mvar = 103
5715 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005716
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005717 def AccessPrivateStaticThroughClassName(): number
5718 assert_equal(1, A._svar)
5719 return 444
5720 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005721 endclass
5722
5723 var oa = A.new()
5724 var ob = B.new()
5725 var oc = C.new()
5726 assert_equal(101, oa.AccessObject())
5727 assert_equal(102, ob.AccessObject())
5728 assert_equal(103, oc.AccessObject())
5729
Ernie Rael03042a22023-11-11 08:53:32 +01005730 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005731
5732 # verify object properly resolves to correct static
5733 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005734 assert_equal(1, ob.AccessStaticThroughObject())
5735 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005736 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005737 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005738enddef
5739
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005740" Test for declaring duplicate object and class members
5741def Test_dup_member_variable()
5742 # Duplicate member variable
5743 var lines =<< trim END
5744 vim9script
5745 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005746 var val = 10
5747 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005748 endclass
5749 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005750 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005751
Ernie Rael03042a22023-11-11 08:53:32 +01005752 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005753 lines =<< trim END
5754 vim9script
5755 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005756 var _val = 10
5757 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005758 endclass
5759 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005760 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005761
5762 # Duplicate public member variable
5763 lines =<< trim END
5764 vim9script
5765 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005766 public var val = 10
5767 public var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005768 endclass
5769 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005770 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005771
Ernie Rael03042a22023-11-11 08:53:32 +01005772 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005773 lines =<< trim END
5774 vim9script
5775 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005776 var val = 10
5777 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005778 endclass
5779 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005780 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005781
Ernie Rael03042a22023-11-11 08:53:32 +01005782 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005783 lines =<< trim END
5784 vim9script
5785 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005786 var _val = 20
5787 public var val = 10
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005788 endclass
5789 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005790 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005791
5792 # Duplicate class member variable
5793 lines =<< trim END
5794 vim9script
5795 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005796 static var s: string = "abc"
5797 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005798 endclass
5799 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005800 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005801
Ernie Rael03042a22023-11-11 08:53:32 +01005802 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005803 lines =<< trim END
5804 vim9script
5805 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005806 public static var s: string = "abc"
5807 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005808 endclass
5809 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005810 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005811
5812 # Duplicate class and object member variable
5813 lines =<< trim END
5814 vim9script
5815 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005816 static var val = 10
5817 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005818 def new()
5819 enddef
5820 endclass
5821 var c = C.new()
5822 assert_equal(10, C.val)
5823 assert_equal(20, c.val)
5824 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005825 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005826
5827 # Duplicate object member variable in a derived class
5828 lines =<< trim END
5829 vim9script
5830 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005831 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005832 endclass
5833 class B extends A
5834 endclass
5835 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005836 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005837 endclass
5838 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005839 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005840
Ernie Rael03042a22023-11-11 08:53:32 +01005841 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005842 lines =<< trim END
5843 vim9script
5844 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005845 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005846 endclass
5847 class B extends A
5848 endclass
5849 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005850 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005851 endclass
5852 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005853 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005854
Ernie Rael03042a22023-11-11 08:53:32 +01005855 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005856 lines =<< trim END
5857 vim9script
5858 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005859 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005860 endclass
5861 class B extends A
5862 endclass
5863 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005864 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005865 endclass
5866 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005867 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005868
5869 # Duplicate object member variable in a derived class
5870 lines =<< trim END
5871 vim9script
5872 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005873 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005874 endclass
5875 class B extends A
5876 endclass
5877 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005878 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005879 endclass
5880 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005881 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005882
5883 # Two member variables with a common prefix
5884 lines =<< trim END
5885 vim9script
5886 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005887 public static var svar2: number
5888 public static var svar: number
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005889 endclass
5890 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005891 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005892enddef
5893
Ernie Rael03042a22023-11-11 08:53:32 +01005894" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005895def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01005896 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005897 var lines =<< trim END
5898 vim9script
5899 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005900 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005901 def GetVal(): number
5902 return this._val
5903 enddef
5904 endclass
5905 def T()
5906 var a = A.new()
5907 a._val = 20
5908 enddef
5909 T()
5910 END
Ernie Rael03042a22023-11-11 08:53:32 +01005911 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005912
Ernie Rael03042a22023-11-11 08:53:32 +01005913 # access a non-existing protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005914 lines =<< trim END
5915 vim9script
5916 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005917 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005918 endclass
5919 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005920 var a = A.new()
5921 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005922 enddef
5923 T()
5924 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005925 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005926
Ernie Rael03042a22023-11-11 08:53:32 +01005927 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005928 lines =<< trim END
5929 vim9script
5930 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005931 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005932 endclass
5933 def T()
5934 var a = A.new()
5935 var x = a._val
5936 enddef
5937 T()
5938 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005939 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005940
Ernie Rael03042a22023-11-11 08:53:32 +01005941 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005942 lines =<< trim END
5943 vim9script
5944 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005945 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005946 endclass
5947 def T()
5948 var a = A.new()
5949 a._val = 3
5950 enddef
5951 T()
5952 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005953 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005954
Ernie Rael03042a22023-11-11 08:53:32 +01005955 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005956 lines =<< trim END
5957 vim9script
5958 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005959 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005960 endclass
5961 def T()
5962 var x = A._val
5963 enddef
5964 T()
5965 END
Ernie Rael03042a22023-11-11 08:53:32 +01005966 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02005967
Ernie Rael03042a22023-11-11 08:53:32 +01005968 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005969 lines =<< trim END
5970 vim9script
5971 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005972 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005973 endclass
5974 def T()
5975 A._val = 3
5976 enddef
5977 T()
5978 END
Ernie Rael03042a22023-11-11 08:53:32 +01005979 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005980enddef
5981
5982" Test for changing the member access of an interface in a implementation class
5983def Test_change_interface_member_access()
5984 var lines =<< trim END
5985 vim9script
5986 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005987 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005988 endinterface
5989 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005990 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005991 endclass
5992 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005993 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005994
5995 lines =<< trim END
5996 vim9script
5997 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005998 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005999 endinterface
6000 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006001 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006002 endclass
6003 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006004 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006005enddef
6006
6007" Test for trying to change a readonly member from a def function
6008def Test_readonly_member_change_in_def_func()
6009 var lines =<< trim END
6010 vim9script
6011 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006012 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006013 endclass
6014 def T()
6015 var a = A.new()
6016 a.val = 20
6017 enddef
6018 T()
6019 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006020 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006021enddef
6022
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006023" Test for reading and writing a class member from a def function
6024def Test_modify_class_member_from_def_function()
6025 var lines =<< trim END
6026 vim9script
6027 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006028 var var1: number = 10
6029 public static var var2: list<number> = [1, 2]
6030 public static var var3: dict<number> = {a: 1, b: 2}
6031 static var _priv_var4: number = 40
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006032 endclass
6033 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02006034 assert_equal([1, 2], A.var2)
6035 assert_equal({a: 1, b: 2}, A.var3)
6036 A.var2 = [3, 4]
6037 A.var3 = {c: 3, d: 4}
6038 assert_equal([3, 4], A.var2)
6039 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael03042a22023-11-11 08:53:32 +01006040 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006041 enddef
6042 T()
6043 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006044 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006045enddef
6046
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006047" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006048def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006049 var lines =<< trim END
6050 vim9script
6051 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006052 public static var svar1: list<number> = [1]
6053 public static var svar2: list<number> = [2]
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006054 endclass
6055
6056 A.svar1->add(3)
6057 A.svar2->add(4)
6058 assert_equal([1, 3], A.svar1)
6059 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006060
6061 def Foo()
6062 A.svar1->add(7)
6063 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006064 assert_equal([1, 3, 7], A.svar1)
6065 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006066 enddef
6067 Foo()
6068 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006069 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006070
6071 # Cannot read from a class variable using an object in script context
6072 lines =<< trim END
6073 vim9script
6074 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006075 public var var1: number
6076 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006077 endclass
6078
6079 var a = A.new()
6080 echo a.svar2
6081 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006082 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006083
6084 # Cannot write to a class variable using an object in script context
6085 lines =<< trim END
6086 vim9script
6087 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006088 public var var1: number
6089 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006090 endclass
6091
6092 var a = A.new()
6093 a.svar2 = [2]
6094 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006095 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006096
6097 # Cannot read from a class variable using an object in def method context
6098 lines =<< trim END
6099 vim9script
6100 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006101 public var var1: number
6102 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006103 endclass
6104
6105 def T()
6106 var a = A.new()
6107 echo a.svar2
6108 enddef
6109 T()
6110 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006111 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006112
6113 # Cannot write to a class variable using an object in def method context
6114 lines =<< trim END
6115 vim9script
6116 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006117 public var var1: number
6118 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006119 endclass
6120
6121 def T()
6122 var a = A.new()
6123 a.svar2 = [2]
6124 enddef
6125 T()
6126 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006127 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006128enddef
6129
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006130" Test for using a interface method using a child object
6131def Test_interface_method_from_child()
6132 var lines =<< trim END
6133 vim9script
6134
6135 interface A
6136 def Foo(): string
6137 endinterface
6138
6139 class B implements A
6140 def Foo(): string
6141 return 'foo'
6142 enddef
6143 endclass
6144
6145 class C extends B
6146 def Bar(): string
6147 return 'bar'
6148 enddef
6149 endclass
6150
6151 def T1(a: A)
6152 assert_equal('foo', a.Foo())
6153 enddef
6154
6155 def T2(b: B)
6156 assert_equal('foo', b.Foo())
6157 enddef
6158
6159 var c = C.new()
6160 T1(c)
6161 T2(c)
6162 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006163 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006164enddef
6165
6166" Test for using an interface method using a child object when it is overridden
6167" by the child class.
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01006168def Test_interface_overridden_method_from_child()
6169 var lines =<< trim END
6170 vim9script
6171
6172 interface A
6173 def Foo(): string
6174 endinterface
6175
6176 class B implements A
6177 def Foo(): string
6178 return 'b-foo'
6179 enddef
6180 endclass
6181
6182 class C extends B
6183 def Bar(): string
6184 return 'bar'
6185 enddef
6186 def Foo(): string
6187 return 'c-foo'
6188 enddef
6189 endclass
6190
6191 def T1(a: A)
6192 assert_equal('c-foo', a.Foo())
6193 enddef
6194
6195 def T2(b: B)
6196 assert_equal('c-foo', b.Foo())
6197 enddef
6198
6199 var c = C.new()
6200 T1(c)
6201 T2(c)
6202 END
6203 v9.CheckSourceSuccess(lines)
6204enddef
6205
6206" Test for interface inheritance
6207def Test_interface_inheritance()
6208 var lines =<< trim END
6209 vim9script
6210
6211 interface A
6212 def A_Fn(): string
6213 endinterface
6214
6215 interface B
6216 def B_Fn(): string
6217 endinterface
6218
6219 interface C
6220 def C_Fn(): string
6221 endinterface
6222
6223 class C1 implements A
6224 def A_Fn(): string
6225 return 'c1-a'
6226 enddef
6227 endclass
6228
6229 class C2 extends C1 implements B
6230 def B_Fn(): string
6231 return 'c2-b'
6232 enddef
6233 def A_Fn(): string
6234 return 'c2-a'
6235 enddef
6236 endclass
6237
6238 class C3 extends C2 implements C
6239 def C_Fn(): string
6240 return 'c3-c'
6241 enddef
6242 def A_Fn(): string
6243 return 'c3-a'
6244 enddef
6245 def B_Fn(): string
6246 return 'c3-b'
6247 enddef
6248 endclass
6249
6250 def T1(a: A, s: string)
6251 assert_equal(s, a.A_Fn())
6252 enddef
6253
6254 def T2(b: B, s: string)
6255 assert_equal(s, b.B_Fn())
6256 enddef
6257
6258 def T3(c: C, s: string)
6259 assert_equal(s, c.C_Fn())
6260 enddef
6261
6262 def T4(c1: C1)
6263 T1(c1, 'c3-a')
6264 enddef
6265
6266 def T5(c2: C2)
6267 T1(c2, 'c3-a')
6268 T2(c2, 'c3-b')
6269 enddef
6270
6271 def T6(c3: C3)
6272 T1(c3, 'c3-a')
6273 T2(c3, 'c3-b')
6274 T3(c3, 'c3-c')
6275 enddef
6276
6277 var o3 = C3.new()
6278 T4(o3)
6279 T5(o3)
6280 T6(o3)
6281 END
6282 v9.CheckSourceSuccess(lines)
6283
6284 # Both the parent and child classes implement the same interface
6285 lines =<< trim END
6286 vim9script
6287
6288 interface I
6289 def Foo(): string
6290 endinterface
6291
6292 class A implements I
6293 def Foo(): string
6294 return 'A-foo'
6295 enddef
6296 endclass
6297
6298 class B implements I
6299 def Foo(): string
6300 return 'B-foo'
6301 enddef
6302 endclass
6303
6304 def Bar(i1: I): string
6305 return i1.Foo()
6306 enddef
6307
6308 var b = B.new()
6309 assert_equal('B-foo', Bar(b))
6310 END
6311 v9.CheckSourceSuccess(lines)
6312enddef
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006313
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006314" Test for abstract methods
6315def Test_abstract_method()
6316 # Use two abstract methods
6317 var lines =<< trim END
6318 vim9script
6319 abstract class A
6320 def M1(): number
6321 return 10
6322 enddef
6323 abstract def M2(): number
6324 abstract def M3(): number
6325 endclass
6326 class B extends A
6327 def M2(): number
6328 return 20
6329 enddef
6330 def M3(): number
6331 return 30
6332 enddef
6333 endclass
6334 var b = B.new()
6335 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6336 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006337 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006338
6339 # Don't define an abstract method
6340 lines =<< trim END
6341 vim9script
6342 abstract class A
6343 abstract def Foo()
6344 endclass
6345 class B extends A
6346 endclass
6347 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006348 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006349
6350 # Use abstract method in a concrete class
6351 lines =<< trim END
6352 vim9script
6353 class A
6354 abstract def Foo()
6355 endclass
6356 class B extends A
6357 endclass
6358 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006359 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006360
6361 # Use abstract method in an interface
6362 lines =<< trim END
6363 vim9script
6364 interface A
6365 abstract def Foo()
6366 endinterface
6367 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006368 def Foo()
6369 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006370 endclass
6371 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006372 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6373
6374 # Use abstract static method in an interface
6375 lines =<< trim END
6376 vim9script
6377 interface A
6378 abstract static def Foo()
6379 enddef
6380 endinterface
6381 END
6382 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6383
6384 # Use abstract static variable in an interface
6385 lines =<< trim END
6386 vim9script
6387 interface A
6388 abstract static foo: number = 10
6389 endinterface
6390 END
6391 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006392
6393 # Abbreviate the "abstract" keyword
6394 lines =<< trim END
6395 vim9script
6396 class A
6397 abs def Foo()
6398 endclass
6399 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006400 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006401
6402 # Use "abstract" with a member variable
6403 lines =<< trim END
6404 vim9script
6405 abstract class A
6406 abstract this.val = 10
6407 endclass
6408 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006409 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006410
6411 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006412 lines =<< trim END
6413 vim9script
6414 abstract class A
6415 abstract static def Foo(): number
6416 endclass
6417 END
6418 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006419
6420 # Type mismatch between abstract method and concrete method
6421 lines =<< trim END
6422 vim9script
6423 abstract class A
6424 abstract def Foo(a: string, b: number): list<number>
6425 endclass
6426 class B extends A
6427 def Foo(a: number, b: string): list<string>
6428 return []
6429 enddef
6430 endclass
6431 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006432 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 +02006433
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006434 # Invoke an abstract method from a def function
6435 lines =<< trim END
6436 vim9script
6437 abstract class A
6438 abstract def Foo(): list<number>
6439 endclass
6440 class B extends A
6441 def Foo(): list<number>
6442 return [3, 5]
6443 enddef
6444 endclass
6445 def Bar(c: B)
6446 assert_equal([3, 5], c.Foo())
6447 enddef
6448 var b = B.new()
6449 Bar(b)
6450 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006451 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006452
6453 # Use a static method in an abstract class
6454 lines =<< trim END
6455 vim9script
6456 abstract class A
6457 static def Foo(): string
6458 return 'foo'
6459 enddef
6460 endclass
6461 assert_equal('foo', A.Foo())
6462 END
6463 v9.CheckSourceSuccess(lines)
Ernie Rael7c92e882025-01-18 17:26:39 +01006464
6465 # Invoke method returning a value through the abstract class. See #15432.
6466 lines =<< trim END
6467 vim9script
6468
6469 abstract class A
6470 abstract def String(): string
6471 endclass
6472
6473 class B extends A
6474 def String(): string
6475 return 'B'
6476 enddef
6477 endclass
6478
6479 def F(o: A)
6480 assert_equal('B', o.String())
6481 enddef
6482 F(B.new())
6483 END
6484 v9.CheckSourceSuccess(lines)
6485
6486 # Invoke abstract method returning a value does not compile
6487 lines =<< trim END
6488 vim9script
6489
6490 abstract class A
6491 abstract def String(): string
6492 return 'X'
6493 enddef
6494 endclass
6495 END
6496 v9.CheckScriptFailure(lines, "E1318: Not a valid command in a class: return 'X'")
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006497enddef
6498
6499" Test for calling a class method from a subclass
6500def Test_class_method_call_from_subclass()
6501 # class method call from a subclass
6502 var lines =<< trim END
6503 vim9script
6504
6505 class A
6506 static def Foo()
6507 echo "foo"
6508 enddef
6509 endclass
6510
6511 class B extends A
6512 def Bar()
6513 Foo()
6514 enddef
6515 endclass
6516
6517 var b = B.new()
6518 b.Bar()
6519 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006520 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006521enddef
6522
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006523" Test for calling a class method using an object in a def function context and
6524" script context.
6525def Test_class_method_call_using_object()
6526 # script context
6527 var lines =<< trim END
6528 vim9script
6529 class A
6530 static def Foo(): list<string>
6531 return ['a', 'b']
6532 enddef
6533 def Bar()
6534 assert_equal(['a', 'b'], A.Foo())
6535 assert_equal(['a', 'b'], Foo())
6536 enddef
6537 endclass
6538
6539 def T()
6540 assert_equal(['a', 'b'], A.Foo())
6541 var t_a = A.new()
6542 t_a.Bar()
6543 enddef
6544
6545 assert_equal(['a', 'b'], A.Foo())
6546 var a = A.new()
6547 a.Bar()
6548 T()
6549 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006550 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006551
6552 # script context
6553 lines =<< trim END
6554 vim9script
6555 class A
6556 static def Foo(): string
6557 return 'foo'
6558 enddef
6559 endclass
6560
6561 var a = A.new()
6562 assert_equal('foo', a.Foo())
6563 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006564 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006565
6566 # def function context
6567 lines =<< trim END
6568 vim9script
6569 class A
6570 static def Foo(): string
6571 return 'foo'
6572 enddef
6573 endclass
6574
6575 def T()
6576 var a = A.new()
6577 assert_equal('foo', a.Foo())
6578 enddef
6579 T()
6580 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006581 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006582enddef
6583
6584def Test_class_variable()
6585 var lines =<< trim END
6586 vim9script
6587
6588 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006589 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006590 static def ClassFunc()
6591 assert_equal(10, val)
6592 enddef
6593 def ObjFunc()
6594 assert_equal(10, val)
6595 enddef
6596 endclass
6597
6598 class B extends A
6599 endclass
6600
6601 assert_equal(10, A.val)
6602 A.ClassFunc()
6603 var a = A.new()
6604 a.ObjFunc()
6605 var b = B.new()
6606 b.ObjFunc()
6607
6608 def T1(a1: A)
6609 a1.ObjFunc()
6610 A.ClassFunc()
6611 enddef
6612 T1(b)
6613
6614 A.val = 20
6615 assert_equal(20, A.val)
6616 END
6617 v9.CheckSourceSuccess(lines)
6618
6619 # Modifying a parent class variable from a child class method
6620 lines =<< trim END
6621 vim9script
6622
6623 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006624 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006625 endclass
6626
6627 class B extends A
6628 static def ClassFunc()
6629 val = 20
6630 enddef
6631 endclass
6632 B.ClassFunc()
6633 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006634 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006635
6636 # Reading a parent class variable from a child class method
6637 lines =<< trim END
6638 vim9script
6639
6640 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006641 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006642 endclass
6643
6644 class B extends A
6645 static def ClassFunc()
6646 var i = val
6647 enddef
6648 endclass
6649 B.ClassFunc()
6650 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006651 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006652
6653 # Modifying a parent class variable from a child object method
6654 lines =<< trim END
6655 vim9script
6656
6657 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006658 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006659 endclass
6660
6661 class B extends A
6662 def ObjFunc()
6663 val = 20
6664 enddef
6665 endclass
6666 var b = B.new()
6667 b.ObjFunc()
6668 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006669 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006670
6671 # Reading a parent class variable from a child object method
6672 lines =<< trim END
6673 vim9script
6674
6675 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006676 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006677 endclass
6678
6679 class B extends A
6680 def ObjFunc()
6681 var i = val
6682 enddef
6683 endclass
6684 var b = B.new()
6685 b.ObjFunc()
6686 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006687 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006688
6689 # Modifying a class variable using an object at script level
6690 lines =<< trim END
6691 vim9script
6692
6693 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006694 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006695 endclass
6696 var a = A.new()
6697 a.val = 20
6698 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006699 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006700
6701 # Reading a class variable using an object at script level
6702 lines =<< trim END
6703 vim9script
6704
6705 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006706 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006707 endclass
6708 var a = A.new()
6709 var i = a.val
6710 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006711 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006712
6713 # Modifying a class variable using an object at function level
6714 lines =<< trim END
6715 vim9script
6716
6717 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006718 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006719 endclass
6720
6721 def T()
6722 var a = A.new()
6723 a.val = 20
6724 enddef
6725 T()
6726 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006727 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006728
6729 # Reading a class variable using an object at function level
6730 lines =<< trim END
6731 vim9script
6732
6733 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006734 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006735 endclass
6736 def T()
6737 var a = A.new()
6738 var i = a.val
6739 enddef
6740 T()
6741 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006742 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006743
6744 # Use old implicit var declaration syntax (without initialization)
6745 lines =<< trim END
6746 vim9script
6747
6748 class A
6749 static val: number
6750 endclass
6751 END
6752 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6753
6754 # Use old implicit var declaration syntax (with initialization)
6755 lines =<< trim END
6756 vim9script
6757
6758 class A
6759 static val: number = 10
6760 endclass
6761 END
6762 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6763
6764 # Use old implicit var declaration syntax (type inferred)
6765 lines =<< trim END
6766 vim9script
6767
6768 class A
6769 static val = 10
6770 endclass
6771 END
6772 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6773
6774 # Missing ":var" in "var" class variable declaration (without initialization)
6775 lines =<< trim END
6776 vim9script
6777
6778 class A
6779 static var: number
6780 endclass
6781 END
6782 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6783
6784 # Missing ":var" in "var" class variable declaration (with initialization)
6785 lines =<< trim END
6786 vim9script
6787
6788 class A
6789 static var: number = 10
6790 endclass
6791 END
6792 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6793
6794 # Missing ":var" in "var" class variable declaration (type inferred)
6795 lines =<< trim END
6796 vim9script
6797
6798 class A
6799 static var = 10
6800 endclass
6801 END
6802 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6803
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006804enddef
6805
6806" Test for using a duplicate class method and class variable in a child class
6807def Test_dup_class_member()
6808 # duplicate class variable, class method and overridden object method
6809 var lines =<< trim END
6810 vim9script
6811 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006812 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006813 static def Check()
6814 assert_equal(100, sval)
6815 enddef
6816 def GetVal(): number
6817 return sval
6818 enddef
6819 endclass
6820
6821 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006822 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006823 static def Check()
6824 assert_equal(200, sval)
6825 enddef
6826 def GetVal(): number
6827 return sval
6828 enddef
6829 endclass
6830
6831 def T1(aa: A): number
6832 return aa.GetVal()
6833 enddef
6834
6835 def T2(bb: B): number
6836 return bb.GetVal()
6837 enddef
6838
6839 assert_equal(100, A.sval)
6840 assert_equal(200, B.sval)
6841 var a = A.new()
6842 assert_equal(100, a.GetVal())
6843 var b = B.new()
6844 assert_equal(200, b.GetVal())
6845 assert_equal(200, T1(b))
6846 assert_equal(200, T2(b))
6847 END
6848 v9.CheckSourceSuccess(lines)
6849
6850 # duplicate class variable and class method
6851 lines =<< trim END
6852 vim9script
6853 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006854 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006855 static def Check()
6856 assert_equal(100, sval)
6857 enddef
6858 def GetVal(): number
6859 return sval
6860 enddef
6861 endclass
6862
6863 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006864 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006865 static def Check()
6866 assert_equal(200, sval)
6867 enddef
6868 endclass
6869
6870 def T1(aa: A): number
6871 return aa.GetVal()
6872 enddef
6873
6874 def T2(bb: B): number
6875 return bb.GetVal()
6876 enddef
6877
6878 assert_equal(100, A.sval)
6879 assert_equal(200, B.sval)
6880 var a = A.new()
6881 assert_equal(100, a.GetVal())
6882 var b = B.new()
6883 assert_equal(100, b.GetVal())
6884 assert_equal(100, T1(b))
6885 assert_equal(100, T2(b))
6886 END
6887 v9.CheckSourceSuccess(lines)
6888enddef
6889
6890" Test for calling an instance method using the class
6891def Test_instance_method_call_using_class()
6892 # Invoke an object method using a class in script context
6893 var lines =<< trim END
6894 vim9script
6895 class A
6896 def Foo()
6897 echo "foo"
6898 enddef
6899 endclass
6900 A.Foo()
6901 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006902 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006903
6904 # Invoke an object method using a class in def function context
6905 lines =<< trim END
6906 vim9script
6907 class A
6908 def Foo()
6909 echo "foo"
6910 enddef
6911 endclass
6912 def T()
6913 A.Foo()
6914 enddef
6915 T()
6916 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006917 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006918enddef
6919
6920" Test for duplicate class method and instance method
6921def Test_dup_classmethod_objmethod()
6922 # Duplicate instance method
6923 var lines =<< trim END
6924 vim9script
6925 class A
6926 static def Foo()
6927 enddef
6928 def Foo()
6929 enddef
6930 endclass
6931 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006932 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006933
Ernie Rael03042a22023-11-11 08:53:32 +01006934 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006935 lines =<< trim END
6936 vim9script
6937 class A
6938 static def Foo()
6939 enddef
6940 def _Foo()
6941 enddef
6942 endclass
6943 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006944 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006945
6946 # Duplicate class method
6947 lines =<< trim END
6948 vim9script
6949 class A
6950 def Foo()
6951 enddef
6952 static def Foo()
6953 enddef
6954 endclass
6955 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006956 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006957
Ernie Rael03042a22023-11-11 08:53:32 +01006958 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006959 lines =<< trim END
6960 vim9script
6961 class A
6962 def Foo()
6963 enddef
6964 static def _Foo()
6965 enddef
6966 endclass
6967 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006968 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006969
Ernie Rael03042a22023-11-11 08:53:32 +01006970 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006971 lines =<< trim END
6972 vim9script
6973 class A
6974 def _Foo()
6975 enddef
6976 static def _Foo()
6977 enddef
6978 endclass
6979 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006980 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006981enddef
6982
6983" Test for an instance method access level comparison with parent instance
6984" methods.
6985def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01006986 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006987 var lines =<< trim END
6988 vim9script
6989 class A
6990 def Foo()
6991 enddef
6992 endclass
6993 class B extends A
6994 endclass
6995 class C extends B
6996 def _Foo()
6997 enddef
6998 endclass
6999 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007000 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007001
7002 # Public method in subclass
7003 lines =<< trim END
7004 vim9script
7005 class A
7006 def _Foo()
7007 enddef
7008 endclass
7009 class B extends A
7010 endclass
7011 class C extends B
7012 def Foo()
7013 enddef
7014 endclass
7015 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007016 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007017enddef
7018
7019def Test_extend_empty_class()
7020 var lines =<< trim END
7021 vim9script
7022 class A
7023 endclass
7024 class B extends A
7025 endclass
7026 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007027 public static var rw_class_var = 1
7028 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007029 static def ClassMethod(): number
7030 return 3
7031 enddef
7032 def ObjMethod(): number
7033 return 4
7034 enddef
7035 endclass
7036 assert_equal(1, C.rw_class_var)
7037 assert_equal(3, C.ClassMethod())
7038 var c = C.new()
7039 assert_equal(2, c.rw_obj_var)
7040 assert_equal(4, c.ObjMethod())
7041 END
7042 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02007043enddef
7044
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007045" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01007046" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007047def Test_interface_with_unsupported_members()
7048 var lines =<< trim END
7049 vim9script
7050 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007051 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007052 endinterface
7053 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007054 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007055
7056 lines =<< trim END
7057 vim9script
7058 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007059 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007060 endinterface
7061 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007062 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007063
7064 lines =<< trim END
7065 vim9script
7066 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007067 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007068 endinterface
7069 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007070 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007071
7072 lines =<< trim END
7073 vim9script
7074 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007075 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007076 endinterface
7077 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007078 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007079
7080 lines =<< trim END
7081 vim9script
7082 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007083 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007084 endinterface
7085 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007086 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007087
7088 lines =<< trim END
7089 vim9script
7090 interface A
7091 static def Foo(d: dict<any>): list<string>
7092 endinterface
7093 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007094 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007095
7096 lines =<< trim END
7097 vim9script
7098 interface A
7099 static def _Foo(d: dict<any>): list<string>
7100 endinterface
7101 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007102 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007103
7104 lines =<< trim END
7105 vim9script
7106 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007107 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007108 endinterface
7109 END
Ernie Rael03042a22023-11-11 08:53:32 +01007110 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007111
7112 lines =<< trim END
7113 vim9script
7114 interface A
7115 def _Foo(d: dict<any>): list<string>
7116 endinterface
7117 END
Ernie Rael03042a22023-11-11 08:53:32 +01007118 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007119enddef
7120
7121" Test for extending an interface
7122def Test_extend_interface()
7123 var lines =<< trim END
7124 vim9script
7125 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007126 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007127 def Foo()
7128 endinterface
7129 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007130 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007131 def Bar()
7132 endinterface
7133 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007134 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007135 def Foo()
7136 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007137 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007138 def Bar()
7139 enddef
7140 endclass
7141 END
7142 v9.CheckSourceSuccess(lines)
7143
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007144 # extending empty interface
7145 lines =<< trim END
7146 vim9script
7147 interface A
7148 endinterface
7149 interface B extends A
7150 endinterface
7151 class C implements B
7152 endclass
7153 END
7154 v9.CheckSourceSuccess(lines)
7155
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007156 lines =<< trim END
7157 vim9script
7158 interface A
7159 def Foo()
7160 endinterface
7161 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007162 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007163 endinterface
7164 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007165 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007166 endclass
7167 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007168 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007169
7170 lines =<< trim END
7171 vim9script
7172 interface A
7173 def Foo()
7174 endinterface
7175 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007176 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007177 endinterface
7178 class C implements A, B
7179 def Foo()
7180 enddef
7181 endclass
7182 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007183 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007184
7185 # interface cannot extend a class
7186 lines =<< trim END
7187 vim9script
7188 class A
7189 endclass
7190 interface B extends A
7191 endinterface
7192 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007193 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007194
7195 # class cannot extend an interface
7196 lines =<< trim END
7197 vim9script
7198 interface A
7199 endinterface
7200 class B extends A
7201 endclass
7202 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007203 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007204
7205 # interface cannot implement another interface
7206 lines =<< trim END
7207 vim9script
7208 interface A
7209 endinterface
7210 interface B implements A
7211 endinterface
7212 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007213 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007214
7215 # interface cannot extend multiple interfaces
7216 lines =<< trim END
7217 vim9script
7218 interface A
7219 endinterface
7220 interface B
7221 endinterface
7222 interface C extends A, B
7223 endinterface
7224 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007225 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007226
7227 # Variable type in an extended interface is of different type
7228 lines =<< trim END
7229 vim9script
7230 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007231 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007232 endinterface
7233 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007234 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007235 endinterface
7236 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007237 var val1: string
7238 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007239 endinterface
7240 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007241 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007242enddef
7243
7244" Test for a child class implementing an interface when some of the methods are
7245" defined in the parent class.
7246def Test_child_class_implements_interface()
7247 var lines =<< trim END
7248 vim9script
7249
7250 interface Intf
7251 def F1(): list<list<number>>
7252 def F2(): list<list<number>>
7253 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007254 var var1: list<dict<number>>
7255 var var2: list<dict<number>>
7256 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007257 endinterface
7258
7259 class A
7260 def A1()
7261 enddef
7262 def F3(): list<list<number>>
7263 return [[3]]
7264 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007265 var v1: list<list<number>> = [[0]]
7266 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007267 endclass
7268
7269 class B extends A
7270 def B1()
7271 enddef
7272 def F2(): list<list<number>>
7273 return [[2]]
7274 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007275 var v2: list<list<number>> = [[0]]
7276 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007277 endclass
7278
7279 class C extends B implements Intf
7280 def C1()
7281 enddef
7282 def F1(): list<list<number>>
7283 return [[1]]
7284 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007285 var v3: list<list<number>> = [[0]]
7286 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007287 endclass
7288
7289 def T(if: Intf)
7290 assert_equal([[1]], if.F1())
7291 assert_equal([[2]], if.F2())
7292 assert_equal([[3]], if.F3())
7293 assert_equal([{a: 10}], if.var1)
7294 assert_equal([{b: 20}], if.var2)
7295 assert_equal([{c: 30}], if.var3)
7296 enddef
7297
7298 var c = C.new()
7299 T(c)
7300 assert_equal([[1]], c.F1())
7301 assert_equal([[2]], c.F2())
7302 assert_equal([[3]], c.F3())
7303 assert_equal([{a: 10}], c.var1)
7304 assert_equal([{b: 20}], c.var2)
7305 assert_equal([{c: 30}], c.var3)
7306 END
7307 v9.CheckSourceSuccess(lines)
7308
7309 # One of the interface methods is not found
7310 lines =<< trim END
7311 vim9script
7312
7313 interface Intf
7314 def F1()
7315 def F2()
7316 def F3()
7317 endinterface
7318
7319 class A
7320 def A1()
7321 enddef
7322 endclass
7323
7324 class B extends A
7325 def B1()
7326 enddef
7327 def F2()
7328 enddef
7329 endclass
7330
7331 class C extends B implements Intf
7332 def C1()
7333 enddef
7334 def F1()
7335 enddef
7336 endclass
7337 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007338 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007339
7340 # One of the interface methods is of different type
7341 lines =<< trim END
7342 vim9script
7343
7344 interface Intf
7345 def F1()
7346 def F2()
7347 def F3()
7348 endinterface
7349
7350 class A
7351 def F3(): number
7352 return 0
7353 enddef
7354 def A1()
7355 enddef
7356 endclass
7357
7358 class B extends A
7359 def B1()
7360 enddef
7361 def F2()
7362 enddef
7363 endclass
7364
7365 class C extends B implements Intf
7366 def C1()
7367 enddef
7368 def F1()
7369 enddef
7370 endclass
7371 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007372 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007373
7374 # One of the interface variables is not present
7375 lines =<< trim END
7376 vim9script
7377
7378 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007379 var var1: list<dict<number>>
7380 var var2: list<dict<number>>
7381 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007382 endinterface
7383
7384 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007385 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007386 endclass
7387
7388 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007389 var v2: list<list<number>> = [[0]]
7390 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007391 endclass
7392
7393 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007394 var v3: list<list<number>> = [[0]]
7395 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007396 endclass
7397 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007398 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007399
7400 # One of the interface variables is of different type
7401 lines =<< trim END
7402 vim9script
7403
7404 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007405 var var1: list<dict<number>>
7406 var var2: list<dict<number>>
7407 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007408 endinterface
7409
7410 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007411 var v1: list<list<number>> = [[0]]
7412 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007413 endclass
7414
7415 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007416 var v2: list<list<number>> = [[0]]
7417 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007418 endclass
7419
7420 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007421 var v3: list<list<number>> = [[0]]
7422 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007423 endclass
7424 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007425 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 +02007426enddef
7427
7428" Test for extending an interface with duplicate variables and methods
7429def Test_interface_extends_with_dup_members()
7430 var lines =<< trim END
7431 vim9script
7432 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007433 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007434 def Foo1(): number
7435 endinterface
7436 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007437 var n2: number
7438 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007439 def Foo2(): number
7440 def Foo1(): number
7441 endinterface
7442 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007443 var n1 = 10
7444 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007445 def Foo1(): number
7446 return 30
7447 enddef
7448 def Foo2(): number
7449 return 40
7450 enddef
7451 endclass
7452 def T1(a: A)
7453 assert_equal(10, a.n1)
7454 assert_equal(30, a.Foo1())
7455 enddef
7456 def T2(b: B)
7457 assert_equal(10, b.n1)
7458 assert_equal(20, b.n2)
7459 assert_equal(30, b.Foo1())
7460 assert_equal(40, b.Foo2())
7461 enddef
7462 var c = C.new()
7463 T1(c)
7464 T2(c)
7465 END
7466 v9.CheckSourceSuccess(lines)
7467enddef
7468
Yegappan Lakshmananc10342d2025-01-11 09:39:01 +01007469" Test for implementing an interface with different ordering for the interface
7470" member variables.
7471def Test_implement_interface_with_different_variable_order()
7472 var lines =<< trim END
7473 vim9script
7474
7475 interface IX
7476 var F: func(): string
7477 endinterface
7478
7479 class X implements IX
7480 var x: number
7481 var F: func(): string = () => 'ok'
7482 endclass
7483
7484 def Foo(ix: IX): string
7485 return ix.F()
7486 enddef
7487
7488 var x0 = X.new(0)
7489 assert_equal('ok', Foo(x0))
7490 END
7491 v9.CheckSourceSuccess(lines)
7492enddef
7493
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01007494" Test for inheriting interfaces from an imported super class
7495def Test_interface_inheritance_with_imported_super()
7496 var lines =<< trim END
7497 vim9script
7498
7499 export interface I
7500 def F(): string
7501 endinterface
7502
7503 export class A implements I
7504 def F(): string
7505 return 'A'
7506 enddef
7507 endclass
7508 END
7509 writefile(lines, 'Xinheritintfimportclass.vim', 'D')
7510
7511 lines =<< trim END
7512 vim9script
7513
7514 import './Xinheritintfimportclass.vim' as i_imp
7515
7516 # class C extends i_imp.A
7517 class C extends i_imp.A implements i_imp.I
7518 def F(): string
7519 return 'C'
7520 enddef
7521 endclass
7522
7523 def TestI(i: i_imp.I): string
7524 return i.F()
7525 enddef
7526
7527 assert_equal('C', TestI(C.new()))
7528 END
7529 v9.CheckSourceSuccess(lines)
7530enddef
7531
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007532" Test for using "any" type for a variable in a sub-class while it has a
7533" concrete type in the interface
7534def Test_implements_using_var_type_any()
7535 var lines =<< trim END
7536 vim9script
7537 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007538 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007539 endinterface
7540 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007541 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007542 endclass
7543 var b = B.new()
7544 assert_equal([{a: '1'}, {b: '2'}], b.val)
7545 END
7546 v9.CheckSourceSuccess(lines)
7547
7548 # initialize instance variable using a different type
7549 lines =<< trim END
7550 vim9script
7551 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007552 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007553 endinterface
7554 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007555 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007556 endclass
7557 var b = B.new()
7558 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007559 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007560enddef
7561
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007562" Test for assigning to a member variable in a nested class
7563def Test_nested_object_assignment()
7564 var lines =<< trim END
7565 vim9script
7566
7567 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007568 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007569 endclass
7570
7571 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007572 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007573 endclass
7574
7575 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007576 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007577 endclass
7578
7579 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007580 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007581 endclass
7582
7583 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007584 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007585 enddef
7586
7587 var d = D.new()
7588 T(d)
7589 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007590 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007591enddef
7592
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007593" Test for calling methods using a null object
7594def Test_null_object_method_call()
7595 # Calling a object method using a null object in script context
7596 var lines =<< trim END
7597 vim9script
7598
7599 class C
7600 def Foo()
7601 assert_report('This method should not be executed')
7602 enddef
7603 endclass
7604
7605 var o: C
7606 o.Foo()
7607 END
7608 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7609
7610 # Calling a object method using a null object in def function context
7611 lines =<< trim END
7612 vim9script
7613
7614 class C
7615 def Foo()
7616 assert_report('This method should not be executed')
7617 enddef
7618 endclass
7619
7620 def T()
7621 var o: C
7622 o.Foo()
7623 enddef
7624 T()
7625 END
7626 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7627
7628 # Calling a object method through another class method using a null object in
7629 # script context
7630 lines =<< trim END
7631 vim9script
7632
7633 class C
7634 def Foo()
7635 assert_report('This method should not be executed')
7636 enddef
7637
7638 static def Bar(o_any: any)
7639 var o_typed: C = o_any
7640 o_typed.Foo()
7641 enddef
7642 endclass
7643
7644 var o: C
7645 C.Bar(o)
7646 END
7647 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7648
7649 # Calling a object method through another class method using a null object in
7650 # def function context
7651 lines =<< trim END
7652 vim9script
7653
7654 class C
7655 def Foo()
7656 assert_report('This method should not be executed')
7657 enddef
7658
7659 static def Bar(o_any: any)
7660 var o_typed: C = o_any
7661 o_typed.Foo()
7662 enddef
7663 endclass
7664
7665 def T()
7666 var o: C
7667 C.Bar(o)
7668 enddef
7669 T()
7670 END
7671 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007672
7673 # Calling an object method defined in a class that is extended. This differs
7674 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7675 lines =<< trim END
7676 vim9script
7677
7678 class C0
7679 def F()
7680 enddef
7681 endclass
7682
7683 class C extends C0
7684 endclass
7685
7686 def X()
7687 var o: C0 = null_object
7688 o.F()
7689 enddef
7690 X()
7691 END
7692 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7693
7694 # Getting a function ref an object method.
7695 lines =<< trim END
7696 vim9script
7697
7698 class C0
7699 def F()
7700 enddef
7701 endclass
7702
7703 class C extends C0
7704 endclass
7705
7706 def X()
7707 var o: C0 = null_object
7708 var XXX = o.F
7709 enddef
7710 X()
7711 END
7712 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007713enddef
7714
7715" Test for using a dict as an object member
7716def Test_dict_object_member()
7717 var lines =<< trim END
7718 vim9script
7719
7720 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007721 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007722 def GetState(): dict<number>
7723 return this.state
7724 enddef
7725 endclass
7726
7727 var ctx = Context.new()
7728 ctx.state->extend({a: 1})
7729 ctx.state['b'] = 2
7730 assert_equal({a: 1, b: 2}, ctx.GetState())
7731
7732 def F()
7733 ctx.state['c'] = 3
7734 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7735 enddef
7736 F()
7737 assert_equal(3, ctx.state.c)
7738 ctx.state.c = 4
7739 assert_equal(4, ctx.state.c)
7740 END
7741 v9.CheckSourceSuccess(lines)
7742enddef
7743
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007744" The following test was failing after 9.0.1914. This was caused by using a
7745" freed object from a previous method call.
7746def Test_freed_object_from_previous_method_call()
7747 var lines =<< trim END
7748 vim9script
7749
7750 class Context
7751 endclass
7752
7753 class Result
7754 endclass
7755
7756 def Failure(): Result
7757 return Result.new()
7758 enddef
7759
7760 def GetResult(ctx: Context): Result
7761 return Failure()
7762 enddef
7763
7764 def Test_GetResult()
7765 var ctx = Context.new()
7766 var result = GetResult(ctx)
7767 enddef
7768
7769 Test_GetResult()
7770 END
7771 v9.CheckSourceSuccess(lines)
7772enddef
7773
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007774" Test for duplicate object and class variable
7775def Test_duplicate_variable()
7776 # Object variable name is same as the class variable name
7777 var lines =<< trim END
7778 vim9script
7779 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007780 public static var sval: number
7781 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007782 endclass
7783 var a = A.new()
7784 END
7785 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7786
7787 # Duplicate variable name and calling a class method
7788 lines =<< trim END
7789 vim9script
7790 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007791 public static var sval: number
7792 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007793 def F1()
7794 echo this.sval
7795 enddef
7796 static def F2()
7797 echo sval
7798 enddef
7799 endclass
7800 A.F2()
7801 END
7802 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7803
7804 # Duplicate variable with an empty constructor
7805 lines =<< trim END
7806 vim9script
7807 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007808 public static var sval: number
7809 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007810 def new()
7811 enddef
7812 endclass
7813 var a = A.new()
7814 END
7815 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7816enddef
7817
7818" Test for using a reserved keyword as a variable name
7819def Test_reserved_varname()
7820 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7821 'null_function', 'null_list', 'null_partial', 'null_string',
7822 'null_channel', 'null_job', 'super', 'this']
7823
7824 var lines =<< trim eval END
7825 vim9script
7826 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007827 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007828 endclass
7829 var o = C.new()
7830 END
7831 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7832
7833 lines =<< trim eval END
7834 vim9script
7835 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007836 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007837 def new()
7838 enddef
7839 endclass
7840 var o = C.new()
7841 END
7842 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7843
7844 lines =<< trim eval END
7845 vim9script
7846 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007847 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007848 def new()
7849 enddef
7850 def F()
7851 echo this.{kword}
7852 enddef
7853 endclass
7854 var o = C.new()
7855 o.F()
7856 END
7857 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007858
7859 # class variable name
7860 if kword != 'this'
7861 lines =<< trim eval END
7862 vim9script
7863 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007864 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007865 endclass
7866 END
7867 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7868 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007869 endfor
7870enddef
7871
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007872" Test for checking the type of the arguments and the return value of a object
7873" method in an extended class.
7874def Test_extended_obj_method_type_check()
7875 var lines =<< trim END
7876 vim9script
7877
7878 class A
7879 endclass
7880 class B extends A
7881 endclass
7882 class C extends B
7883 endclass
7884
7885 class Foo
7886 def Doit(p: B): B
7887 return B.new()
7888 enddef
7889 endclass
7890
7891 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007892 def Doit(p: C): B
7893 return B.new()
7894 enddef
7895 endclass
7896 END
7897 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
7898
7899 lines =<< trim END
7900 vim9script
7901
7902 class A
7903 endclass
7904 class B extends A
7905 endclass
7906 class C extends B
7907 endclass
7908
7909 class Foo
7910 def Doit(p: B): B
7911 return B.new()
7912 enddef
7913 endclass
7914
7915 class Bar extends Foo
7916 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007917 return C.new()
7918 enddef
7919 endclass
7920 END
7921 v9.CheckSourceSuccess(lines)
7922
7923 lines =<< trim END
7924 vim9script
7925
7926 class A
7927 endclass
7928 class B extends A
7929 endclass
7930 class C extends B
7931 endclass
7932
7933 class Foo
7934 def Doit(p: B): B
7935 return B.new()
7936 enddef
7937 endclass
7938
7939 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007940 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007941 return B.new()
7942 enddef
7943 endclass
7944 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007945 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 +02007946
7947 lines =<< trim END
7948 vim9script
7949
7950 class A
7951 endclass
7952 class B extends A
7953 endclass
7954 class C extends B
7955 endclass
7956
7957 class Foo
7958 def Doit(p: B): B
7959 return B.new()
7960 enddef
7961 endclass
7962
7963 class Bar extends Foo
7964 def Doit(p: B): A
7965 return A.new()
7966 enddef
7967 endclass
7968 END
7969 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 +02007970
7971 # check varargs type mismatch
7972 lines =<< trim END
7973 vim9script
7974
7975 class B
7976 def F(...xxx: list<any>)
7977 enddef
7978 endclass
7979 class C extends B
7980 def F(xxx: list<any>)
7981 enddef
7982 endclass
7983 END
7984 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 +02007985enddef
7986
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007987" Test type checking for class variable in assignments
7988func Test_class_variable_complex_type_check()
7989 " class variable with a specific type. Try assigning a different type at
7990 " script level.
7991 let lines =<< trim END
7992 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007993 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007994 return {}
7995 enddef
7996 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007997 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007998 endclass
7999 test_garbagecollect_now()
8000 A.Fn = "abc"
8001 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008002 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 +02008003
8004 " class variable with a specific type. Try assigning a different type at
8005 " class def method level.
8006 let lines =<< trim END
8007 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008008 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008009 return {}
8010 enddef
8011 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008012 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008013 def Bar()
8014 Fn = "abc"
8015 enddef
8016 endclass
8017 var a = A.new()
8018 test_garbagecollect_now()
8019 a.Bar()
8020 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008021 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 +02008022
8023 " class variable with a specific type. Try assigning a different type at
8024 " script def method level.
8025 let lines =<< trim END
8026 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008027 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008028 return {}
8029 enddef
8030 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008031 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008032 endclass
8033 def Bar()
8034 A.Fn = "abc"
8035 enddef
8036 test_garbagecollect_now()
8037 Bar()
8038 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008039 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 +02008040
8041 " class variable without any type. Should be set to the initialization
8042 " expression type. Try assigning a different type from script level.
8043 let lines =<< trim END
8044 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008045 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008046 return {}
8047 enddef
8048 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008049 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008050 endclass
8051 test_garbagecollect_now()
8052 A.Fn = "abc"
8053 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008054 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 +02008055
8056 " class variable without any type. Should be set to the initialization
8057 " expression type. Try assigning a different type at class def level.
8058 let lines =<< trim END
8059 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008060 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008061 return {}
8062 enddef
8063 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008064 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008065 def Bar()
8066 Fn = "abc"
8067 enddef
8068 endclass
8069 var a = A.new()
8070 test_garbagecollect_now()
8071 a.Bar()
8072 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008073 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 +02008074
8075 " class variable without any type. Should be set to the initialization
8076 " expression type. Try assigning a different type at script def level.
8077 let lines =<< trim END
8078 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008079 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008080 return {}
8081 enddef
8082 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008083 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008084 endclass
8085 def Bar()
8086 A.Fn = "abc"
8087 enddef
8088 test_garbagecollect_now()
8089 Bar()
8090 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008091 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 +02008092
8093 " class variable with 'any" type. Can be assigned different types.
8094 let lines =<< trim END
8095 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008096 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008097 return {}
8098 enddef
8099 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008100 public static var Fn: any = Foo
8101 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008102 endclass
8103 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008104 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008105 A.Fn = "abc"
8106 test_garbagecollect_now()
8107 assert_equal('string', typename(A.Fn))
8108 A.Fn2 = Foo
8109 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008110 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008111 A.Fn2 = "xyz"
8112 test_garbagecollect_now()
8113 assert_equal('string', typename(A.Fn2))
8114 END
8115 call v9.CheckSourceSuccess(lines)
8116
8117 " class variable with 'any" type. Can be assigned different types.
8118 let lines =<< trim END
8119 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008120 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008121 return {}
8122 enddef
8123 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008124 public static var Fn: any = Foo
8125 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008126
8127 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008128 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008129 Fn = "abc"
8130 assert_equal('string', typename(Fn))
8131 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008132 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008133 Fn2 = "xyz"
8134 assert_equal('string', typename(Fn2))
8135 enddef
8136 endclass
8137 var a = A.new()
8138 test_garbagecollect_now()
8139 a.Bar()
8140 test_garbagecollect_now()
8141 A.Fn = Foo
8142 a.Bar()
8143 END
8144 call v9.CheckSourceSuccess(lines)
8145
8146 " class variable with 'any" type. Can be assigned different types.
8147 let lines =<< trim END
8148 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008149 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008150 return {}
8151 enddef
8152 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008153 public static var Fn: any = Foo
8154 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008155 endclass
8156
8157 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008158 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008159 A.Fn = "abc"
8160 assert_equal('string', typename(A.Fn))
8161 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008162 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008163 A.Fn2 = "xyz"
8164 assert_equal('string', typename(A.Fn2))
8165 enddef
8166 Bar()
8167 test_garbagecollect_now()
8168 A.Fn = Foo
8169 Bar()
8170 END
8171 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008172
8173 let lines =<< trim END
8174 vim9script
8175 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008176 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008177 endclass
8178 assert_equal([0z10, 0z20], A.foo)
8179 A.foo = [0z30]
8180 assert_equal([0z30], A.foo)
8181 var a = A.foo
8182 assert_equal([0z30], a)
8183 END
8184 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008185endfunc
8186
8187" Test type checking for object variable in assignments
8188func Test_object_variable_complex_type_check()
8189 " object variable with a specific type. Try assigning a different type at
8190 " script level.
8191 let lines =<< trim END
8192 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008193 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008194 return {}
8195 enddef
8196 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008197 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008198 endclass
8199 var a = A.new()
8200 test_garbagecollect_now()
8201 a.Fn = "abc"
8202 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008203 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 +02008204
8205 " object variable with a specific type. Try assigning a different type at
8206 " object def method level.
8207 let lines =<< trim END
8208 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008209 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008210 return {}
8211 enddef
8212 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008213 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008214 def Bar()
8215 this.Fn = "abc"
8216 this.Fn = Foo
8217 enddef
8218 endclass
8219 var a = A.new()
8220 test_garbagecollect_now()
8221 a.Bar()
8222 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008223 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 +02008224
8225 " object variable with a specific type. Try assigning a different type at
8226 " script def method level.
8227 let lines =<< trim END
8228 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008229 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008230 return {}
8231 enddef
8232 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008233 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008234 endclass
8235 def Bar()
8236 var a = A.new()
8237 a.Fn = "abc"
8238 a.Fn = Foo
8239 enddef
8240 test_garbagecollect_now()
8241 Bar()
8242 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008243 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 +02008244
8245 " object variable without any type. Should be set to the initialization
8246 " expression type. Try assigning a different type from script level.
8247 let lines =<< trim END
8248 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008249 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008250 return {}
8251 enddef
8252 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008253 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008254 endclass
8255 var a = A.new()
8256 test_garbagecollect_now()
8257 a.Fn = "abc"
8258 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008259 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 +02008260
8261 " object variable without any type. Should be set to the initialization
8262 " expression type. Try assigning a different type at object def level.
8263 let lines =<< trim END
8264 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008265 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008266 return {}
8267 enddef
8268 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008269 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008270 def Bar()
8271 this.Fn = "abc"
8272 this.Fn = Foo
8273 enddef
8274 endclass
8275 var a = A.new()
8276 test_garbagecollect_now()
8277 a.Bar()
8278 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008279 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 +02008280
8281 " object variable without any type. Should be set to the initialization
8282 " expression type. Try assigning a different type at script def level.
8283 let lines =<< trim END
8284 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008285 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008286 return {}
8287 enddef
8288 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008289 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008290 endclass
8291 def Bar()
8292 var a = A.new()
8293 a.Fn = "abc"
8294 a.Fn = Foo
8295 enddef
8296 test_garbagecollect_now()
8297 Bar()
8298 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008299 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 +02008300
8301 " object variable with 'any" type. Can be assigned different types.
8302 let lines =<< trim END
8303 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008304 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008305 return {}
8306 enddef
8307 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008308 public var Fn: any = Foo
8309 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008310 endclass
8311
8312 var a = A.new()
8313 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008314 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008315 a.Fn = "abc"
8316 test_garbagecollect_now()
8317 assert_equal('string', typename(a.Fn))
8318 a.Fn2 = Foo
8319 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008320 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008321 a.Fn2 = "xyz"
8322 test_garbagecollect_now()
8323 assert_equal('string', typename(a.Fn2))
8324 END
8325 call v9.CheckSourceSuccess(lines)
8326
8327 " object variable with 'any" type. Can be assigned different types.
8328 let lines =<< trim END
8329 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008330 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008331 return {}
8332 enddef
8333 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008334 public var Fn: any = Foo
8335 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008336
8337 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008338 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008339 this.Fn = "abc"
8340 assert_equal('string', typename(this.Fn))
8341 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008342 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008343 this.Fn2 = "xyz"
8344 assert_equal('string', typename(this.Fn2))
8345 enddef
8346 endclass
8347
8348 var a = A.new()
8349 test_garbagecollect_now()
8350 a.Bar()
8351 test_garbagecollect_now()
8352 a.Fn = Foo
8353 a.Bar()
8354 END
8355 call v9.CheckSourceSuccess(lines)
8356
8357 " object variable with 'any" type. Can be assigned different types.
8358 let lines =<< trim END
8359 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008360 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008361 return {}
8362 enddef
8363 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008364 public var Fn: any = Foo
8365 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008366 endclass
8367
8368 def Bar()
8369 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008370 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008371 a.Fn = "abc"
8372 assert_equal('string', typename(a.Fn))
8373 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008374 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008375 a.Fn2 = "xyz"
8376 assert_equal('string', typename(a.Fn2))
8377 enddef
8378 test_garbagecollect_now()
8379 Bar()
8380 test_garbagecollect_now()
8381 Bar()
8382 END
8383 call v9.CheckSourceSuccess(lines)
8384endfunc
8385
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008386" Test for recursively calling an object method. This used to cause an
8387" use-after-free error.
8388def Test_recursive_object_method_call()
8389 var lines =<< trim END
8390 vim9script
8391 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008392 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008393 def Foo(): number
8394 if this.val >= 90
8395 return this.val
8396 endif
8397 this.val += 1
8398 return this.Foo()
8399 enddef
8400 endclass
8401 var a = A.new()
8402 assert_equal(90, a.Foo())
8403 END
8404 v9.CheckSourceSuccess(lines)
8405enddef
8406
8407" Test for recursively calling a class method.
8408def Test_recursive_class_method_call()
8409 var lines =<< trim END
8410 vim9script
8411 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008412 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008413 static def Foo(): number
8414 if val >= 90
8415 return val
8416 endif
8417 val += 1
8418 return Foo()
8419 enddef
8420 endclass
8421 assert_equal(90, A.Foo())
8422 END
8423 v9.CheckSourceSuccess(lines)
8424enddef
8425
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008426" Test for checking the argument types and the return type when assigning a
8427" funcref to make sure the invariant class type is used.
8428def Test_funcref_argtype_returntype_check()
8429 var lines =<< trim END
8430 vim9script
8431 class A
8432 endclass
8433 class B extends A
8434 endclass
8435
8436 def Foo(p: B): B
8437 return B.new()
8438 enddef
8439
8440 var Bar: func(A): A = Foo
8441 END
8442 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8443
8444 lines =<< trim END
8445 vim9script
8446 class A
8447 endclass
8448 class B extends A
8449 endclass
8450
8451 def Foo(p: B): B
8452 return B.new()
8453 enddef
8454
8455 def Baz()
8456 var Bar: func(A): A = Foo
8457 enddef
8458 Baz()
8459 END
8460 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8461enddef
8462
Ernie Rael96952b22023-10-17 18:15:01 +02008463def Test_funcref_argtype_invariance_check()
8464 var lines =<< trim END
8465 vim9script
8466
8467 class A
8468 endclass
8469 class B extends A
8470 endclass
8471 class C extends B
8472 endclass
8473
8474 var Func: func(B): number
8475 Func = (o: B): number => 3
8476 assert_equal(3, Func(B.new()))
8477 END
8478 v9.CheckSourceSuccess(lines)
8479
8480 lines =<< trim END
8481 vim9script
8482
8483 class A
8484 endclass
8485 class B extends A
8486 endclass
8487 class C extends B
8488 endclass
8489
8490 var Func: func(B): number
8491 Func = (o: A): number => 3
8492 END
8493 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8494
8495 lines =<< trim END
8496 vim9script
8497
8498 class A
8499 endclass
8500 class B extends A
8501 endclass
8502 class C extends B
8503 endclass
8504
8505 var Func: func(B): number
8506 Func = (o: C): number => 3
8507 END
8508 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8509enddef
8510
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008511" Test for using an operator (e.g. +) with an assignment
8512def Test_op_and_assignment()
8513 # Using += with a class variable
8514 var lines =<< trim END
8515 vim9script
8516 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008517 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008518 static def Foo(): list<number>
8519 val += [1]
8520 return val
8521 enddef
8522 endclass
8523 def Bar(): list<number>
8524 A.val += [2]
8525 return A.val
8526 enddef
8527 assert_equal([1], A.Foo())
8528 assert_equal([1, 2], Bar())
8529 A.val += [3]
8530 assert_equal([1, 2, 3], A.val)
8531 END
8532 v9.CheckSourceSuccess(lines)
8533
8534 # Using += with an object variable
8535 lines =<< trim END
8536 vim9script
8537 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008538 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008539 def Foo(): list<number>
8540 this.val += [1]
8541 return this.val
8542 enddef
8543 endclass
8544 def Bar(bar_a: A): list<number>
8545 bar_a.val += [2]
8546 return bar_a.val
8547 enddef
8548 var a = A.new()
8549 assert_equal([1], a.Foo())
8550 assert_equal([1, 2], Bar(a))
8551 a.val += [3]
8552 assert_equal([1, 2, 3], a.val)
8553 END
8554 v9.CheckSourceSuccess(lines)
8555enddef
8556
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008557" Test for using an object method as a funcref
8558def Test_object_funcref()
8559 # Using object method funcref from a def function
8560 var lines =<< trim END
8561 vim9script
8562 class A
8563 def Foo(): list<number>
8564 return [3, 2, 1]
8565 enddef
8566 endclass
8567 def Bar()
8568 var a = A.new()
8569 var Fn = a.Foo
8570 assert_equal([3, 2, 1], Fn())
8571 enddef
8572 Bar()
8573 END
8574 v9.CheckSourceSuccess(lines)
8575
8576 # Using object method funcref at the script level
8577 lines =<< trim END
8578 vim9script
8579 class A
8580 def Foo(): dict<number>
8581 return {a: 1, b: 2}
8582 enddef
8583 endclass
8584 var a = A.new()
8585 var Fn = a.Foo
8586 assert_equal({a: 1, b: 2}, Fn())
8587 END
8588 v9.CheckSourceSuccess(lines)
8589
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008590 # Using object method funcref at the script level
8591 lines =<< trim END
8592 vim9script
8593 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008594 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008595 def Foo(): number
8596 return this.val
8597 enddef
8598 endclass
8599 var a = A.new(345)
8600 var Fn = a.Foo
8601 assert_equal(345, Fn())
8602 END
8603 v9.CheckSourceSuccess(lines)
8604
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008605 # Using object method funcref from another object method
8606 lines =<< trim END
8607 vim9script
8608 class A
8609 def Foo(): list<number>
8610 return [3, 2, 1]
8611 enddef
8612 def Bar()
8613 var Fn = this.Foo
8614 assert_equal([3, 2, 1], Fn())
8615 enddef
8616 endclass
8617 var a = A.new()
8618 a.Bar()
8619 END
8620 v9.CheckSourceSuccess(lines)
8621
8622 # Using function() to get a object method funcref
8623 lines =<< trim END
8624 vim9script
8625 class A
8626 def Foo(l: list<any>): list<any>
8627 return l
8628 enddef
8629 endclass
8630 var a = A.new()
8631 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8632 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8633 END
8634 v9.CheckSourceSuccess(lines)
8635
8636 # Use an object method with a function returning a funcref and then call the
8637 # funcref.
8638 lines =<< trim END
8639 vim9script
8640
8641 def Map(F: func(number): number): func(number): number
8642 return (n: number) => F(n)
8643 enddef
8644
8645 class Math
8646 def Double(n: number): number
8647 return 2 * n
8648 enddef
8649 endclass
8650
8651 const math = Math.new()
8652 assert_equal(48, Map(math.Double)(24))
8653 END
8654 v9.CheckSourceSuccess(lines)
8655
Ernie Rael03042a22023-11-11 08:53:32 +01008656 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008657 lines =<< trim END
8658 vim9script
8659 class A
8660 def _Foo()
8661 enddef
8662 endclass
8663 def Bar()
8664 var a = A.new()
8665 var Fn = a._Foo
8666 enddef
8667 Bar()
8668 END
Ernie Rael03042a22023-11-11 08:53:32 +01008669 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008670
Ernie Rael03042a22023-11-11 08:53:32 +01008671 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008672 lines =<< trim END
8673 vim9script
8674 class A
8675 def _Foo()
8676 enddef
8677 endclass
8678 var a = A.new()
8679 var Fn = a._Foo
8680 END
Ernie Rael03042a22023-11-11 08:53:32 +01008681 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008682
Ernie Rael03042a22023-11-11 08:53:32 +01008683 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008684 lines =<< trim END
8685 vim9script
8686 class A
8687 def _Foo(): list<number>
8688 return [3, 2, 1]
8689 enddef
8690 def Bar()
8691 var Fn = this._Foo
8692 assert_equal([3, 2, 1], Fn())
8693 enddef
8694 endclass
8695 var a = A.new()
8696 a.Bar()
8697 END
8698 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008699
8700 # Using object method funcref using call()
8701 lines =<< trim END
8702 vim9script
8703 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008704 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008705 def Foo(): number
8706 return this.val
8707 enddef
8708 endclass
8709
8710 def Bar(obj: A)
8711 assert_equal(123, call(obj.Foo, []))
8712 enddef
8713
8714 var a = A.new(123)
8715 Bar(a)
8716 assert_equal(123, call(a.Foo, []))
8717 END
8718 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008719enddef
8720
8721" Test for using a class method as a funcref
8722def Test_class_funcref()
8723 # Using class method funcref in a def function
8724 var lines =<< trim END
8725 vim9script
8726 class A
8727 static def Foo(): list<number>
8728 return [3, 2, 1]
8729 enddef
8730 endclass
8731 def Bar()
8732 var Fn = A.Foo
8733 assert_equal([3, 2, 1], Fn())
8734 enddef
8735 Bar()
8736 END
8737 v9.CheckSourceSuccess(lines)
8738
8739 # Using class method funcref at script level
8740 lines =<< trim END
8741 vim9script
8742 class A
8743 static def Foo(): dict<number>
8744 return {a: 1, b: 2}
8745 enddef
8746 endclass
8747 var Fn = A.Foo
8748 assert_equal({a: 1, b: 2}, Fn())
8749 END
8750 v9.CheckSourceSuccess(lines)
8751
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008752 # Using class method funcref at the script level
8753 lines =<< trim END
8754 vim9script
8755 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008756 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008757 static def Foo(): number
8758 return val
8759 enddef
8760 endclass
8761 A.val = 567
8762 var Fn = A.Foo
8763 assert_equal(567, Fn())
8764 END
8765 v9.CheckSourceSuccess(lines)
8766
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008767 # Using function() to get a class method funcref
8768 lines =<< trim END
8769 vim9script
8770 class A
8771 static def Foo(l: list<any>): list<any>
8772 return l
8773 enddef
8774 endclass
8775 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8776 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8777 END
8778 v9.CheckSourceSuccess(lines)
8779
8780 # Using a class method funcref from another class method
8781 lines =<< trim END
8782 vim9script
8783 class A
8784 static def Foo(): list<number>
8785 return [3, 2, 1]
8786 enddef
8787 static def Bar()
8788 var Fn = Foo
8789 assert_equal([3, 2, 1], Fn())
8790 enddef
8791 endclass
8792 A.Bar()
8793 END
8794 v9.CheckSourceSuccess(lines)
8795
8796 # Use a class method with a function returning a funcref and then call the
8797 # funcref.
8798 lines =<< trim END
8799 vim9script
8800
8801 def Map(F: func(number): number): func(number): number
8802 return (n: number) => F(n)
8803 enddef
8804
8805 class Math
8806 static def StaticDouble(n: number): number
8807 return 2 * n
8808 enddef
8809 endclass
8810
8811 assert_equal(48, Map(Math.StaticDouble)(24))
8812 END
8813 v9.CheckSourceSuccess(lines)
8814
Ernie Rael03042a22023-11-11 08:53:32 +01008815 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008816 lines =<< trim END
8817 vim9script
8818 class A
8819 static def _Foo()
8820 enddef
8821 endclass
8822 def Bar()
8823 var Fn = A._Foo
8824 enddef
8825 Bar()
8826 END
Ernie Rael03042a22023-11-11 08:53:32 +01008827 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008828
Ernie Rael03042a22023-11-11 08:53:32 +01008829 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008830 lines =<< trim END
8831 vim9script
8832 class A
8833 static def _Foo()
8834 enddef
8835 endclass
8836 var Fn = A._Foo
8837 END
Ernie Rael03042a22023-11-11 08:53:32 +01008838 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008839
Ernie Rael03042a22023-11-11 08:53:32 +01008840 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008841 lines =<< trim END
8842 vim9script
8843 class A
8844 static def _Foo(): list<number>
8845 return [3, 2, 1]
8846 enddef
8847 static def Bar()
8848 var Fn = _Foo
8849 assert_equal([3, 2, 1], Fn())
8850 enddef
8851 endclass
8852 A.Bar()
8853 END
8854 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008855
8856 # Using class method funcref using call()
8857 lines =<< trim END
8858 vim9script
8859 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008860 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008861 static def Foo(): number
8862 return val
8863 enddef
8864 endclass
8865
8866 def Bar()
8867 A.val = 468
8868 assert_equal(468, call(A.Foo, []))
8869 enddef
8870 Bar()
8871 assert_equal(468, call(A.Foo, []))
8872 END
8873 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008874enddef
8875
8876" Test for using an object member as a funcref
8877def Test_object_member_funcref()
8878 # Using a funcref object variable in an object method
8879 var lines =<< trim END
8880 vim9script
8881 def Foo(n: number): number
8882 return n * 10
8883 enddef
8884
8885 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008886 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008887 def Bar()
8888 assert_equal(200, this.Cb(20))
8889 enddef
8890 endclass
8891
8892 var a = A.new()
8893 a.Bar()
8894 END
8895 v9.CheckSourceSuccess(lines)
8896
8897 # Using a funcref object variable in a def method
8898 lines =<< trim END
8899 vim9script
8900 def Foo(n: number): number
8901 return n * 10
8902 enddef
8903
8904 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008905 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008906 endclass
8907
8908 def Bar()
8909 var a = A.new()
8910 assert_equal(200, a.Cb(20))
8911 enddef
8912 Bar()
8913 END
8914 v9.CheckSourceSuccess(lines)
8915
8916 # Using a funcref object variable at script level
8917 lines =<< trim END
8918 vim9script
8919 def Foo(n: number): number
8920 return n * 10
8921 enddef
8922
8923 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008924 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008925 endclass
8926
8927 var a = A.new()
8928 assert_equal(200, a.Cb(20))
8929 END
8930 v9.CheckSourceSuccess(lines)
8931
8932 # Using a funcref object variable pointing to an object method in an object
8933 # method.
8934 lines =<< trim END
8935 vim9script
8936 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008937 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008938 def Foo(n: number): number
8939 return n * 10
8940 enddef
8941 def Bar()
8942 assert_equal(200, this.Cb(20))
8943 enddef
8944 endclass
8945
8946 var a = A.new()
8947 a.Bar()
8948 END
8949 v9.CheckSourceSuccess(lines)
8950
8951 # Using a funcref object variable pointing to an object method in a def
8952 # method.
8953 lines =<< trim END
8954 vim9script
8955 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008956 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008957 def Foo(n: number): number
8958 return n * 10
8959 enddef
8960 endclass
8961
8962 def Bar()
8963 var a = A.new()
8964 assert_equal(200, a.Cb(20))
8965 enddef
8966 Bar()
8967 END
8968 v9.CheckSourceSuccess(lines)
8969
8970 # Using a funcref object variable pointing to an object method at script
8971 # level.
8972 lines =<< trim END
8973 vim9script
8974 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008975 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008976 def Foo(n: number): number
8977 return n * 10
8978 enddef
8979 endclass
8980
8981 var a = A.new()
8982 assert_equal(200, a.Cb(20))
8983 END
8984 v9.CheckSourceSuccess(lines)
8985enddef
8986
8987" Test for using a class member as a funcref
8988def Test_class_member_funcref()
8989 # Using a funcref class variable in a class method
8990 var lines =<< trim END
8991 vim9script
8992 def Foo(n: number): number
8993 return n * 10
8994 enddef
8995
8996 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008997 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008998 static def Bar()
8999 assert_equal(200, Cb(20))
9000 enddef
9001 endclass
9002
9003 A.Bar()
9004 END
9005 v9.CheckSourceSuccess(lines)
9006
9007 # Using a funcref class variable in a def method
9008 lines =<< trim END
9009 vim9script
9010 def Foo(n: number): number
9011 return n * 10
9012 enddef
9013
9014 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009015 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009016 endclass
9017
9018 def Bar()
9019 assert_equal(200, A.Cb(20))
9020 enddef
9021 Bar()
9022 END
9023 v9.CheckSourceSuccess(lines)
9024
9025 # Using a funcref class variable at script level
9026 lines =<< trim END
9027 vim9script
9028 def Foo(n: number): number
9029 return n * 10
9030 enddef
9031
9032 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009033 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009034 endclass
9035
9036 assert_equal(200, A.Cb(20))
9037 END
9038 v9.CheckSourceSuccess(lines)
9039
9040 # Using a funcref class variable pointing to a class method in a class
9041 # method.
9042 lines =<< trim END
9043 vim9script
9044 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009045 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009046 static def Foo(n: number): number
9047 return n * 10
9048 enddef
9049 static def Init()
9050 Cb = Foo
9051 enddef
9052 static def Bar()
9053 assert_equal(200, Cb(20))
9054 enddef
9055 endclass
9056
9057 A.Init()
9058 A.Bar()
9059 END
9060 v9.CheckSourceSuccess(lines)
9061
9062 # Using a funcref class variable pointing to a class method in a def method.
9063 lines =<< trim END
9064 vim9script
9065 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009066 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009067 static def Foo(n: number): number
9068 return n * 10
9069 enddef
9070 static def Init()
9071 Cb = Foo
9072 enddef
9073 endclass
9074
9075 def Bar()
9076 A.Init()
9077 assert_equal(200, A.Cb(20))
9078 enddef
9079 Bar()
9080 END
9081 v9.CheckSourceSuccess(lines)
9082
9083 # Using a funcref class variable pointing to a class method at script level.
9084 lines =<< trim END
9085 vim9script
9086 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009087 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009088 static def Foo(n: number): number
9089 return n * 10
9090 enddef
9091 static def Init()
9092 Cb = Foo
9093 enddef
9094 endclass
9095
9096 A.Init()
9097 assert_equal(200, A.Cb(20))
9098 END
9099 v9.CheckSourceSuccess(lines)
9100enddef
9101
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009102" Test for using object methods as popup callback functions
9103def Test_objmethod_popup_callback()
9104 # Use the popup from the script level
9105 var lines =<< trim END
9106 vim9script
9107
9108 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009109 var selection: number = -1
9110 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009111
9112 def PopupFilter(id: number, key: string): bool
9113 add(this.filterkeys, key)
9114 return popup_filter_yesno(id, key)
9115 enddef
9116
9117 def PopupCb(id: number, result: number)
9118 this.selection = result ? 100 : 200
9119 enddef
9120 endclass
9121
9122 var a = A.new()
9123 feedkeys('', 'xt')
9124 var winid = popup_create('Y/N?',
9125 {filter: a.PopupFilter, callback: a.PopupCb})
9126 feedkeys('y', 'xt')
9127 popup_close(winid)
9128 assert_equal(100, a.selection)
9129 assert_equal(['y'], a.filterkeys)
9130 feedkeys('', 'xt')
9131 winid = popup_create('Y/N?',
9132 {filter: a.PopupFilter, callback: a.PopupCb})
9133 feedkeys('n', 'xt')
9134 popup_close(winid)
9135 assert_equal(200, a.selection)
9136 assert_equal(['y', 'n'], a.filterkeys)
9137 END
9138 v9.CheckSourceSuccess(lines)
9139
9140 # Use the popup from a def function
9141 lines =<< trim END
9142 vim9script
9143
9144 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009145 var selection: number = -1
9146 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009147
9148 def PopupFilter(id: number, key: string): bool
9149 add(this.filterkeys, key)
9150 return popup_filter_yesno(id, key)
9151 enddef
9152
9153 def PopupCb(id: number, result: number)
9154 this.selection = result ? 100 : 200
9155 enddef
9156 endclass
9157
9158 def Foo()
9159 var a = A.new()
9160 feedkeys('', 'xt')
9161 var winid = popup_create('Y/N?',
9162 {filter: a.PopupFilter, callback: a.PopupCb})
9163 feedkeys('y', 'xt')
9164 popup_close(winid)
9165 assert_equal(100, a.selection)
9166 assert_equal(['y'], a.filterkeys)
9167 feedkeys('', 'xt')
9168 winid = popup_create('Y/N?',
9169 {filter: a.PopupFilter, callback: a.PopupCb})
9170 feedkeys('n', 'xt')
9171 popup_close(winid)
9172 assert_equal(200, a.selection)
9173 assert_equal(['y', 'n'], a.filterkeys)
9174 enddef
9175 Foo()
9176 END
9177 v9.CheckSourceSuccess(lines)
9178enddef
9179
9180" Test for using class methods as popup callback functions
9181def Test_classmethod_popup_callback()
9182 # Use the popup from the script level
9183 var lines =<< trim END
9184 vim9script
9185
9186 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009187 static var selection: number = -1
9188 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009189
9190 static def PopupFilter(id: number, key: string): bool
9191 add(filterkeys, key)
9192 return popup_filter_yesno(id, key)
9193 enddef
9194
9195 static def PopupCb(id: number, result: number)
9196 selection = result ? 100 : 200
9197 enddef
9198 endclass
9199
9200 feedkeys('', 'xt')
9201 var winid = popup_create('Y/N?',
9202 {filter: A.PopupFilter, callback: A.PopupCb})
9203 feedkeys('y', 'xt')
9204 popup_close(winid)
9205 assert_equal(100, A.selection)
9206 assert_equal(['y'], A.filterkeys)
9207 feedkeys('', 'xt')
9208 winid = popup_create('Y/N?',
9209 {filter: A.PopupFilter, callback: A.PopupCb})
9210 feedkeys('n', 'xt')
9211 popup_close(winid)
9212 assert_equal(200, A.selection)
9213 assert_equal(['y', 'n'], A.filterkeys)
9214 END
9215 v9.CheckSourceSuccess(lines)
9216
9217 # Use the popup from a def function
9218 lines =<< trim END
9219 vim9script
9220
9221 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009222 static var selection: number = -1
9223 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009224
9225 static def PopupFilter(id: number, key: string): bool
9226 add(filterkeys, key)
9227 return popup_filter_yesno(id, key)
9228 enddef
9229
9230 static def PopupCb(id: number, result: number)
9231 selection = result ? 100 : 200
9232 enddef
9233 endclass
9234
9235 def Foo()
9236 feedkeys('', 'xt')
9237 var winid = popup_create('Y/N?',
9238 {filter: A.PopupFilter, callback: A.PopupCb})
9239 feedkeys('y', 'xt')
9240 popup_close(winid)
9241 assert_equal(100, A.selection)
9242 assert_equal(['y'], A.filterkeys)
9243 feedkeys('', 'xt')
9244 winid = popup_create('Y/N?',
9245 {filter: A.PopupFilter, callback: A.PopupCb})
9246 feedkeys('n', 'xt')
9247 popup_close(winid)
9248 assert_equal(200, A.selection)
9249 assert_equal(['y', 'n'], A.filterkeys)
9250 enddef
9251 Foo()
9252 END
9253 v9.CheckSourceSuccess(lines)
9254enddef
9255
9256" Test for using an object method as a timer callback function
9257def Test_objmethod_timer_callback()
9258 # Use the timer callback from script level
9259 var lines =<< trim END
9260 vim9script
9261
9262 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009263 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009264 def TimerCb(timerID: number)
9265 this.timerTick = 6
9266 enddef
9267 endclass
9268
9269 var a = A.new()
9270 timer_start(0, a.TimerCb)
9271 var maxWait = 5
9272 while maxWait > 0 && a.timerTick == -1
9273 :sleep 10m
9274 maxWait -= 1
9275 endwhile
9276 assert_equal(6, a.timerTick)
9277 END
9278 v9.CheckSourceSuccess(lines)
9279
9280 # Use the timer callback from a def function
9281 lines =<< trim END
9282 vim9script
9283
9284 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009285 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009286 def TimerCb(timerID: number)
9287 this.timerTick = 6
9288 enddef
9289 endclass
9290
9291 def Foo()
9292 var a = A.new()
9293 timer_start(0, a.TimerCb)
9294 var maxWait = 5
9295 while maxWait > 0 && a.timerTick == -1
9296 :sleep 10m
9297 maxWait -= 1
9298 endwhile
9299 assert_equal(6, a.timerTick)
9300 enddef
9301 Foo()
9302 END
9303 v9.CheckSourceSuccess(lines)
9304enddef
9305
9306" Test for using a class method as a timer callback function
9307def Test_classmethod_timer_callback()
9308 # Use the timer callback from script level
9309 var lines =<< trim END
9310 vim9script
9311
9312 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009313 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009314 static def TimerCb(timerID: number)
9315 timerTick = 6
9316 enddef
9317 endclass
9318
9319 timer_start(0, A.TimerCb)
9320 var maxWait = 5
9321 while maxWait > 0 && A.timerTick == -1
9322 :sleep 10m
9323 maxWait -= 1
9324 endwhile
9325 assert_equal(6, A.timerTick)
9326 END
9327 v9.CheckSourceSuccess(lines)
9328
9329 # Use the timer callback from a def function
9330 lines =<< trim END
9331 vim9script
9332
9333 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009334 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009335 static def TimerCb(timerID: number)
9336 timerTick = 6
9337 enddef
9338 endclass
9339
9340 def Foo()
9341 timer_start(0, A.TimerCb)
9342 var maxWait = 5
9343 while maxWait > 0 && A.timerTick == -1
9344 :sleep 10m
9345 maxWait -= 1
9346 endwhile
9347 assert_equal(6, A.timerTick)
9348 enddef
9349 Foo()
9350 END
9351 v9.CheckSourceSuccess(lines)
9352enddef
9353
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009354" Test for using a class variable as the first and/or second operand of a binary
9355" operator.
9356def Test_class_variable_as_operands()
9357 var lines =<< trim END
9358 vim9script
9359 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009360 static var truthy: bool = true
9361 public static var TruthyFn: func
9362 static var list: list<any> = []
9363 static var four: number = 4
9364 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009365
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009366 static def Str(): string
9367 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009368 enddef
9369
9370 static def Four(): number
9371 return four
9372 enddef
9373
9374 static def List(): list<any>
9375 return list
9376 enddef
9377
9378 static def Truthy(): bool
9379 return truthy
9380 enddef
9381
9382 def TestOps()
9383 assert_true(Tests.truthy == truthy)
9384 assert_true(truthy == Tests.truthy)
9385 assert_true(Tests.list isnot [])
9386 assert_true([] isnot Tests.list)
9387 assert_equal(2, Tests.four >> 1)
9388 assert_equal(16, 1 << Tests.four)
9389 assert_equal(8, Tests.four + four)
9390 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009391 assert_equal('hellohello', Tests.str .. str)
9392 assert_equal('hellohello', str .. Tests.str)
9393
9394 # Using class variable for list indexing
9395 var l = range(10)
9396 assert_equal(4, l[Tests.four])
9397 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9398
9399 # Using class variable for Dict key
9400 var d = {hello: 'abc'}
9401 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009402 enddef
9403 endclass
9404
9405 def TestOps2()
9406 assert_true(Tests.truthy == Tests.Truthy())
9407 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009408 assert_true(Tests.truthy == Tests.TruthyFn())
9409 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009410 assert_true(Tests.list is Tests.List())
9411 assert_true(Tests.List() is Tests.list)
9412 assert_equal(2, Tests.four >> 1)
9413 assert_equal(16, 1 << Tests.four)
9414 assert_equal(8, Tests.four + Tests.Four())
9415 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009416 assert_equal('hellohello', Tests.str .. Tests.Str())
9417 assert_equal('hellohello', Tests.Str() .. Tests.str)
9418
9419 # Using class variable for list indexing
9420 var l = range(10)
9421 assert_equal(4, l[Tests.four])
9422 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9423
9424 # Using class variable for Dict key
9425 var d = {hello: 'abc'}
9426 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009427 enddef
9428
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009429 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009430 var t = Tests.new()
9431 t.TestOps()
9432 TestOps2()
9433
9434 assert_true(Tests.truthy == Tests.Truthy())
9435 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009436 assert_true(Tests.truthy == Tests.TruthyFn())
9437 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009438 assert_true(Tests.list is Tests.List())
9439 assert_true(Tests.List() is Tests.list)
9440 assert_equal(2, Tests.four >> 1)
9441 assert_equal(16, 1 << Tests.four)
9442 assert_equal(8, Tests.four + Tests.Four())
9443 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009444 assert_equal('hellohello', Tests.str .. Tests.Str())
9445 assert_equal('hellohello', Tests.Str() .. Tests.str)
9446
9447 # Using class variable for list indexing
9448 var l = range(10)
9449 assert_equal(4, l[Tests.four])
9450 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9451
9452 # Using class variable for Dict key
9453 var d = {hello: 'abc'}
9454 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009455 END
9456 v9.CheckSourceSuccess(lines)
9457enddef
9458
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009459" Test for checking the type of the key used to access an object dict member.
9460def Test_dict_member_key_type_check()
9461 var lines =<< trim END
9462 vim9script
9463
9464 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009465 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009466 endclass
9467
9468 class Test extends State
9469 def ObjMethodTests()
9470 var cursor: number = 0
9471 var z: number = 0
9472 [this.numbers[cursor]] = ['zero.1']
9473 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9474 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9475 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9476 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9477 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9478 [this.numbers[cursor], z] = ['zero.4', 1]
9479 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9480 [z, this.numbers[cursor]] = [1, 'zero.5']
9481 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9482 enddef
9483
9484 static def ClassMethodTests(that: State)
9485 var cursor: number = 0
9486 var z: number = 0
9487 [that.numbers[cursor]] = ['zero.1']
9488 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9489 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9490 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9491 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9492 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9493 [that.numbers[cursor], z] = ['zero.4', 1]
9494 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9495 [z, that.numbers[cursor]] = [1, 'zero.5']
9496 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9497 enddef
9498
9499 def new()
9500 enddef
9501
9502 def newMethodTests()
9503 var cursor: number = 0
9504 var z: number
9505 [this.numbers[cursor]] = ['zero.1']
9506 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9507 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9508 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9509 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9510 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9511 [this.numbers[cursor], z] = ['zero.4', 1]
9512 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9513 [z, this.numbers[cursor]] = [1, 'zero.5']
9514 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9515 enddef
9516 endclass
9517
9518 def DefFuncTests(that: Test)
9519 var cursor: number = 0
9520 var z: number
9521 [that.numbers[cursor]] = ['zero.1']
9522 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9523 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9524 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9525 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9526 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9527 [that.numbers[cursor], z] = ['zero.4', 1]
9528 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9529 [z, that.numbers[cursor]] = [1, 'zero.5']
9530 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9531 enddef
9532
9533 Test.newMethodTests()
9534 Test.new().ObjMethodTests()
9535 Test.ClassMethodTests(Test.new())
9536 DefFuncTests(Test.new())
9537
9538 const test: Test = Test.new()
9539 var cursor: number = 0
9540 [test.numbers[cursor], cursor] = ['zero', 1]
9541 [cursor, test.numbers[cursor]] = [1, 'one']
9542 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9543 END
9544 v9.CheckSourceSuccess(lines)
9545
9546 lines =<< trim END
9547 vim9script
9548
9549 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009550 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009551
9552 def new()
9553 enddef
9554
9555 def Foo()
9556 var z: number
9557 [this.numbers.a, z] = [{}, 10]
9558 enddef
9559 endclass
9560
9561 var a = A.new()
9562 a.Foo()
9563 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009564 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009565
9566 lines =<< trim END
9567 vim9script
9568
9569 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009570 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009571
9572 def new()
9573 enddef
9574
9575 def Foo()
9576 var x: string = 'a'
9577 var y: number
9578 [this.numbers[x], y] = [{}, 10]
9579 enddef
9580 endclass
9581
9582 var a = A.new()
9583 a.Foo()
9584 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009585 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009586enddef
9587
mityua5550692023-11-25 15:41:20 +01009588def Test_compile_many_def_functions_in_funcref_instr()
9589 # This used to crash Vim. This is reproducible only when run on new instance
9590 # of Vim.
9591 var lines =<< trim END
9592 vim9script
9593
9594 class A
9595 def new()
9596 this.TakeFunc(this.F00)
9597 enddef
9598
9599 def TakeFunc(F: func)
9600 enddef
9601
9602 def F00()
9603 this.F01()
9604 this.F02()
9605 this.F03()
9606 this.F04()
9607 this.F05()
9608 this.F06()
9609 this.F07()
9610 this.F08()
9611 this.F09()
9612 this.F10()
9613 this.F11()
9614 this.F12()
9615 this.F13()
9616 this.F14()
9617 this.F15()
9618 this.F16()
9619 this.F17()
9620 this.F18()
9621 this.F19()
9622 this.F20()
9623 this.F21()
9624 this.F22()
9625 this.F23()
9626 this.F24()
9627 this.F25()
9628 this.F26()
9629 this.F27()
9630 this.F28()
9631 this.F29()
9632 this.F30()
9633 this.F31()
9634 this.F32()
9635 this.F33()
9636 this.F34()
9637 this.F35()
9638 this.F36()
9639 this.F37()
9640 this.F38()
9641 this.F39()
9642 this.F40()
9643 this.F41()
9644 this.F42()
9645 this.F43()
9646 this.F44()
9647 this.F45()
9648 this.F46()
9649 this.F47()
9650 enddef
9651
9652 def F01()
9653 enddef
9654 def F02()
9655 enddef
9656 def F03()
9657 enddef
9658 def F04()
9659 enddef
9660 def F05()
9661 enddef
9662 def F06()
9663 enddef
9664 def F07()
9665 enddef
9666 def F08()
9667 enddef
9668 def F09()
9669 enddef
9670 def F10()
9671 enddef
9672 def F11()
9673 enddef
9674 def F12()
9675 enddef
9676 def F13()
9677 enddef
9678 def F14()
9679 enddef
9680 def F15()
9681 enddef
9682 def F16()
9683 enddef
9684 def F17()
9685 enddef
9686 def F18()
9687 enddef
9688 def F19()
9689 enddef
9690 def F20()
9691 enddef
9692 def F21()
9693 enddef
9694 def F22()
9695 enddef
9696 def F23()
9697 enddef
9698 def F24()
9699 enddef
9700 def F25()
9701 enddef
9702 def F26()
9703 enddef
9704 def F27()
9705 enddef
9706 def F28()
9707 enddef
9708 def F29()
9709 enddef
9710 def F30()
9711 enddef
9712 def F31()
9713 enddef
9714 def F32()
9715 enddef
9716 def F33()
9717 enddef
9718 def F34()
9719 enddef
9720 def F35()
9721 enddef
9722 def F36()
9723 enddef
9724 def F37()
9725 enddef
9726 def F38()
9727 enddef
9728 def F39()
9729 enddef
9730 def F40()
9731 enddef
9732 def F41()
9733 enddef
9734 def F42()
9735 enddef
9736 def F43()
9737 enddef
9738 def F44()
9739 enddef
9740 def F45()
9741 enddef
9742 def F46()
9743 enddef
9744 def F47()
9745 enddef
9746 endclass
9747
9748 A.new()
9749 END
9750 writefile(lines, 'Xscript', 'D')
9751 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9752 assert_equal(0, v:shell_error)
9753enddef
9754
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009755" Test for 'final' class and object variables
9756def Test_final_class_object_variable()
9757 # Test for changing a final object variable from an object function
9758 var lines =<< trim END
9759 vim9script
9760 class A
9761 final foo: string = "abc"
9762 def Foo()
9763 this.foo = "def"
9764 enddef
9765 endclass
9766 defcompile A.Foo
9767 END
9768 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9769
9770 # Test for changing a final object variable from the 'new' function
9771 lines =<< trim END
9772 vim9script
9773 class A
9774 final s1: string
9775 final s2: string
9776 def new(this.s1)
9777 this.s2 = 'def'
9778 enddef
9779 endclass
9780 var a = A.new('abc')
9781 assert_equal('abc', a.s1)
9782 assert_equal('def', a.s2)
9783 END
9784 v9.CheckSourceSuccess(lines)
9785
9786 # Test for a final class variable
9787 lines =<< trim END
9788 vim9script
9789 class A
9790 static final s1: string = "abc"
9791 endclass
9792 assert_equal('abc', A.s1)
9793 END
9794 v9.CheckSourceSuccess(lines)
9795
9796 # Test for changing a final class variable from a class function
9797 lines =<< trim END
9798 vim9script
9799 class A
9800 static final s1: string = "abc"
9801 static def Foo()
9802 s1 = "def"
9803 enddef
9804 endclass
9805 A.Foo()
9806 END
9807 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9808
9809 # Test for changing a public final class variable at script level
9810 lines =<< trim END
9811 vim9script
9812 class A
9813 public static final s1: string = "abc"
9814 endclass
9815 assert_equal('abc', A.s1)
9816 A.s1 = 'def'
9817 END
9818 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9819
9820 # Test for changing a public final class variable from a class function
9821 lines =<< trim END
9822 vim9script
9823 class A
9824 public static final s1: string = "abc"
9825 static def Foo()
9826 s1 = "def"
9827 enddef
9828 endclass
9829 A.Foo()
9830 END
9831 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9832
9833 # Test for changing a public final class variable from a function
9834 lines =<< trim END
9835 vim9script
9836 class A
9837 public static final s1: string = "abc"
9838 endclass
9839 def Foo()
9840 A.s1 = 'def'
9841 enddef
9842 defcompile
9843 END
9844 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9845
9846 # Test for using a final variable of composite type
9847 lines =<< trim END
9848 vim9script
9849 class A
9850 public final l: list<number>
9851 def new()
9852 this.l = [1, 2]
9853 enddef
9854 def Foo()
9855 this.l[0] = 3
9856 this.l->add(4)
9857 enddef
9858 endclass
9859 var a = A.new()
9860 assert_equal([1, 2], a.l)
9861 a.Foo()
9862 assert_equal([3, 2, 4], a.l)
9863 END
9864 v9.CheckSourceSuccess(lines)
9865
9866 # Test for changing a final variable of composite type from another object
9867 # function
9868 lines =<< trim END
9869 vim9script
9870 class A
9871 public final l: list<number> = [1, 2]
9872 def Foo()
9873 this.l = [3, 4]
9874 enddef
9875 endclass
9876 var a = A.new()
9877 a.Foo()
9878 END
9879 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9880
9881 # Test for modifying a final variable of composite type at script level
9882 lines =<< trim END
9883 vim9script
9884 class A
9885 public final l: list<number> = [1, 2]
9886 endclass
9887 var a = A.new()
9888 a.l[0] = 3
9889 a.l->add(4)
9890 assert_equal([3, 2, 4], a.l)
9891 END
9892 v9.CheckSourceSuccess(lines)
9893
9894 # Test for modifying a final variable of composite type from a function
9895 lines =<< trim END
9896 vim9script
9897 class A
9898 public final l: list<number> = [1, 2]
9899 endclass
9900 def Foo()
9901 var a = A.new()
9902 a.l[0] = 3
9903 a.l->add(4)
9904 assert_equal([3, 2, 4], a.l)
9905 enddef
9906 Foo()
9907 END
9908 v9.CheckSourceSuccess(lines)
9909
9910 # Test for modifying a final variable of composite type from another object
9911 # function
9912 lines =<< trim END
9913 vim9script
9914 class A
9915 public final l: list<number> = [1, 2]
9916 def Foo()
9917 this.l[0] = 3
9918 this.l->add(4)
9919 enddef
9920 endclass
9921 var a = A.new()
9922 a.Foo()
9923 assert_equal([3, 2, 4], a.l)
9924 END
9925 v9.CheckSourceSuccess(lines)
9926
9927 # Test for assigning a new value to a final variable of composite type at
9928 # script level
9929 lines =<< trim END
9930 vim9script
9931 class A
9932 public final l: list<number> = [1, 2]
9933 endclass
9934 var a = A.new()
9935 a.l = [3, 4]
9936 END
9937 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
9938
9939 # Test for assigning a new value to a final variable of composite type from
9940 # another object function
9941 lines =<< trim END
9942 vim9script
9943 class A
9944 public final l: list<number> = [1, 2]
9945 def Foo()
9946 this.l = [3, 4]
9947 enddef
9948 endclass
9949 var a = A.new()
9950 a.Foo()
9951 END
9952 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9953
9954 # Test for assigning a new value to a final variable of composite type from
9955 # another function
9956 lines =<< trim END
9957 vim9script
9958 class A
9959 public final l: list<number> = [1, 2]
9960 endclass
9961 def Foo()
9962 var a = A.new()
9963 a.l = [3, 4]
9964 enddef
9965 Foo()
9966 END
9967 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
9968
9969 # Error case: Use 'final' with just a variable name
9970 lines =<< trim END
9971 vim9script
9972 class A
9973 final foo
9974 endclass
9975 var a = A.new()
9976 END
9977 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9978
9979 # Error case: Use 'final' followed by 'public'
9980 lines =<< trim END
9981 vim9script
9982 class A
9983 final public foo: number
9984 endclass
9985 var a = A.new()
9986 END
9987 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9988
9989 # Error case: Use 'final' followed by 'static'
9990 lines =<< trim END
9991 vim9script
9992 class A
9993 final static foo: number
9994 endclass
9995 var a = A.new()
9996 END
9997 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9998
9999 # Error case: 'final' cannot be used in an interface
10000 lines =<< trim END
10001 vim9script
10002 interface A
10003 final foo: number = 10
10004 endinterface
10005 END
10006 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
10007
10008 # Error case: 'final' not supported for an object method
10009 lines =<< trim END
10010 vim9script
10011 class A
10012 final def Foo()
10013 enddef
10014 endclass
10015 END
10016 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10017
10018 # Error case: 'final' not supported for a class method
10019 lines =<< trim END
10020 vim9script
10021 class A
10022 static final def Foo()
10023 enddef
10024 endclass
10025 END
10026 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10027enddef
10028
10029" Test for 'const' class and object variables
10030def Test_const_class_object_variable()
10031 # Test for changing a const object variable from an object function
10032 var lines =<< trim END
10033 vim9script
10034 class A
10035 const foo: string = "abc"
10036 def Foo()
10037 this.foo = "def"
10038 enddef
10039 endclass
10040 defcompile A.Foo
10041 END
10042 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
10043
10044 # Test for changing a const object variable from the 'new' function
10045 lines =<< trim END
10046 vim9script
10047 class A
10048 const s1: string
10049 const s2: string
10050 def new(this.s1)
10051 this.s2 = 'def'
10052 enddef
10053 endclass
10054 var a = A.new('abc')
10055 assert_equal('abc', a.s1)
10056 assert_equal('def', a.s2)
10057 END
10058 v9.CheckSourceSuccess(lines)
10059
10060 # Test for changing a const object variable from an object method called from
10061 # the 'new' function
10062 lines =<< trim END
10063 vim9script
10064 class A
10065 const s1: string = 'abc'
10066 def new()
10067 this.ChangeStr()
10068 enddef
10069 def ChangeStr()
10070 this.s1 = 'def'
10071 enddef
10072 endclass
10073 var a = A.new()
10074 END
10075 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10076
10077 # Test for a const class variable
10078 lines =<< trim END
10079 vim9script
10080 class A
10081 static const s1: string = "abc"
10082 endclass
10083 assert_equal('abc', A.s1)
10084 END
10085 v9.CheckSourceSuccess(lines)
10086
10087 # Test for changing a const class variable from a class function
10088 lines =<< trim END
10089 vim9script
10090 class A
10091 static const s1: string = "abc"
10092 static def Foo()
10093 s1 = "def"
10094 enddef
10095 endclass
10096 A.Foo()
10097 END
10098 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10099
10100 # Test for changing a public const class variable at script level
10101 lines =<< trim END
10102 vim9script
10103 class A
10104 public static const s1: string = "abc"
10105 endclass
10106 assert_equal('abc', A.s1)
10107 A.s1 = 'def'
10108 END
10109 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
10110
10111 # Test for changing a public const class variable from a class function
10112 lines =<< trim END
10113 vim9script
10114 class A
10115 public static const s1: string = "abc"
10116 static def Foo()
10117 s1 = "def"
10118 enddef
10119 endclass
10120 A.Foo()
10121 END
10122 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10123
10124 # Test for changing a public const class variable from a function
10125 lines =<< trim END
10126 vim9script
10127 class A
10128 public static const s1: string = "abc"
10129 endclass
10130 def Foo()
10131 A.s1 = 'def'
10132 enddef
10133 defcompile
10134 END
10135 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10136
10137 # Test for changing a const List item from an object function
10138 lines =<< trim END
10139 vim9script
10140 class A
10141 public const l: list<number>
10142 def new()
10143 this.l = [1, 2]
10144 enddef
10145 def Foo()
10146 this.l[0] = 3
10147 enddef
10148 endclass
10149 var a = A.new()
10150 assert_equal([1, 2], a.l)
10151 a.Foo()
10152 END
10153 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10154
10155 # Test for adding a value to a const List from an object function
10156 lines =<< trim END
10157 vim9script
10158 class A
10159 public const l: list<number>
10160 def new()
10161 this.l = [1, 2]
10162 enddef
10163 def Foo()
10164 this.l->add(3)
10165 enddef
10166 endclass
10167 var a = A.new()
10168 a.Foo()
10169 END
10170 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10171
10172 # Test for reassigning a const List from an object function
10173 lines =<< trim END
10174 vim9script
10175 class A
10176 public const l: list<number> = [1, 2]
10177 def Foo()
10178 this.l = [3, 4]
10179 enddef
10180 endclass
10181 var a = A.new()
10182 a.Foo()
10183 END
10184 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10185
10186 # Test for changing a const List item at script level
10187 lines =<< trim END
10188 vim9script
10189 class A
10190 public const l: list<number> = [1, 2]
10191 endclass
10192 var a = A.new()
10193 a.l[0] = 3
10194 END
10195 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10196
10197 # Test for adding a value to a const List item at script level
10198 lines =<< trim END
10199 vim9script
10200 class A
10201 public const l: list<number> = [1, 2]
10202 endclass
10203 var a = A.new()
10204 a.l->add(4)
10205 END
10206 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10207
10208 # Test for changing a const List item from a function
10209 lines =<< trim END
10210 vim9script
10211 class A
10212 public const l: list<number> = [1, 2]
10213 endclass
10214 def Foo()
10215 var a = A.new()
10216 a.l[0] = 3
10217 enddef
10218 Foo()
10219 END
10220 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
10221
10222 # Test for adding a value to a const List item from a function
10223 lines =<< trim END
10224 vim9script
10225 class A
10226 public const l: list<number> = [1, 2]
10227 endclass
10228 def Foo()
10229 var a = A.new()
10230 a.l->add(4)
10231 enddef
10232 Foo()
10233 END
10234 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
10235
10236 # Test for changing a const List item from an object method
10237 lines =<< trim END
10238 vim9script
10239 class A
10240 public const l: list<number> = [1, 2]
10241 def Foo()
10242 this.l[0] = 3
10243 enddef
10244 endclass
10245 var a = A.new()
10246 a.Foo()
10247 END
10248 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10249
10250 # Test for adding a value to a const List item from an object method
10251 lines =<< trim END
10252 vim9script
10253 class A
10254 public const l: list<number> = [1, 2]
10255 def Foo()
10256 this.l->add(4)
10257 enddef
10258 endclass
10259 var a = A.new()
10260 a.Foo()
10261 END
10262 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10263
10264 # Test for reassigning a const List object variable at script level
10265 lines =<< trim END
10266 vim9script
10267 class A
10268 public const l: list<number> = [1, 2]
10269 endclass
10270 var a = A.new()
10271 a.l = [3, 4]
10272 END
10273 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10274
10275 # Test for reassigning a const List object variable from an object method
10276 lines =<< trim END
10277 vim9script
10278 class A
10279 public const l: list<number> = [1, 2]
10280 def Foo()
10281 this.l = [3, 4]
10282 enddef
10283 endclass
10284 var a = A.new()
10285 a.Foo()
10286 END
10287 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10288
10289 # Test for reassigning a const List object variable from another function
10290 lines =<< trim END
10291 vim9script
10292 class A
10293 public const l: list<number> = [1, 2]
10294 endclass
10295 def Foo()
10296 var a = A.new()
10297 a.l = [3, 4]
10298 enddef
10299 Foo()
10300 END
10301 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10302
10303 # Error case: Use 'const' with just a variable name
10304 lines =<< trim END
10305 vim9script
10306 class A
10307 const foo
10308 endclass
10309 var a = A.new()
10310 END
10311 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10312
10313 # Error case: Use 'const' followed by 'public'
10314 lines =<< trim END
10315 vim9script
10316 class A
10317 const public foo: number
10318 endclass
10319 var a = A.new()
10320 END
10321 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10322
10323 # Error case: Use 'const' followed by 'static'
10324 lines =<< trim END
10325 vim9script
10326 class A
10327 const static foo: number
10328 endclass
10329 var a = A.new()
10330 END
10331 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10332
10333 # Error case: 'const' cannot be used in an interface
10334 lines =<< trim END
10335 vim9script
10336 interface A
10337 const foo: number = 10
10338 endinterface
10339 END
10340 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10341
10342 # Error case: 'const' not supported for an object method
10343 lines =<< trim END
10344 vim9script
10345 class A
10346 const def Foo()
10347 enddef
10348 endclass
10349 END
10350 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10351
10352 # Error case: 'const' not supported for a class method
10353 lines =<< trim END
10354 vim9script
10355 class A
10356 static const def Foo()
10357 enddef
10358 endclass
10359 END
10360 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10361enddef
10362
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010363" Test for compiling class/object methods using :defcompile
10364def Test_defcompile_class()
10365 # defcompile all the classes in the current script
10366 var lines =<< trim END
10367 vim9script
10368 class A
10369 def Foo()
10370 var i = 10
10371 enddef
10372 endclass
10373 class B
10374 def Bar()
10375 var i = 20
10376 xxx
10377 enddef
10378 endclass
10379 defcompile
10380 END
10381 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10382
10383 # defcompile a specific class
10384 lines =<< trim END
10385 vim9script
10386 class A
10387 def Foo()
10388 xxx
10389 enddef
10390 endclass
10391 class B
10392 def Bar()
10393 yyy
10394 enddef
10395 endclass
10396 defcompile B
10397 END
10398 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10399
10400 # defcompile a non-class
10401 lines =<< trim END
10402 vim9script
10403 class A
10404 def Foo()
10405 enddef
10406 endclass
10407 var X: list<number> = []
10408 defcompile X
10409 END
10410 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10411
10412 # defcompile a class twice
10413 lines =<< trim END
10414 vim9script
10415 class A
10416 def new()
10417 enddef
10418 endclass
10419 defcompile A
10420 defcompile A
10421 assert_equal('Function A.new does not need compiling', v:statusmsg)
10422 END
10423 v9.CheckSourceSuccess(lines)
10424
10425 # defcompile should not compile an imported class
10426 lines =<< trim END
10427 vim9script
10428 export class A
10429 def Foo()
10430 xxx
10431 enddef
10432 endclass
10433 END
10434 writefile(lines, 'Xdefcompileimport.vim', 'D')
10435 lines =<< trim END
10436 vim9script
10437
10438 import './Xdefcompileimport.vim'
10439 class B
10440 endclass
10441 defcompile
10442 END
10443 v9.CheckScriptSuccess(lines)
10444enddef
10445
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010446" Test for cases common to all the object builtin methods
10447def Test_object_builtin_method()
10448 var lines =<< trim END
10449 vim9script
10450 class A
10451 def abc()
10452 enddef
10453 endclass
10454 END
10455 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10456
10457 for funcname in ["len", "string", "empty"]
10458 lines =<< trim eval END
10459 vim9script
10460 class A
10461 static def {funcname}(): number
10462 enddef
10463 endclass
10464 END
10465 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10466 endfor
10467enddef
10468
10469" Test for using the empty() builtin method with an object
10470" This is a legacy function to use the test_garbagecollect_now() function.
10471func Test_object_empty()
10472 let lines =<< trim END
10473 vim9script
10474 class A
10475 def empty(): bool
10476 return true
10477 enddef
10478 endclass
10479
10480 def Foo()
10481 var afoo = A.new()
10482 assert_equal(true, empty(afoo))
10483 assert_equal(true, afoo->empty())
10484 enddef
10485
10486 var a = A.new()
10487 assert_equal(1, empty(a))
10488 assert_equal(1, a->empty())
10489 test_garbagecollect_now()
10490 assert_equal(1, empty(a))
10491 Foo()
10492 test_garbagecollect_now()
10493 Foo()
10494 END
10495 call v9.CheckSourceSuccess(lines)
10496
10497 " empty() should return 1 without a builtin method
10498 let lines =<< trim END
10499 vim9script
10500 class A
10501 endclass
10502
10503 def Foo()
10504 var afoo = A.new()
10505 assert_equal(1, empty(afoo))
10506 enddef
10507
10508 var a = A.new()
10509 assert_equal(1, empty(a))
10510 Foo()
10511 END
10512 call v9.CheckSourceSuccess(lines)
10513
10514 " Unsupported signature for the empty() method
10515 let lines =<< trim END
10516 vim9script
10517 class A
10518 def empty()
10519 enddef
10520 endclass
10521 END
10522 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10523
10524 " Error when calling the empty() method
10525 let lines =<< trim END
10526 vim9script
10527 class A
10528 def empty(): bool
10529 throw "Failed to check emptiness"
10530 enddef
10531 endclass
10532
10533 def Foo()
10534 var afoo = A.new()
10535 var i = empty(afoo)
10536 enddef
10537
10538 var a = A.new()
10539 assert_fails('empty(a)', 'Failed to check emptiness')
10540 assert_fails('Foo()', 'Failed to check emptiness')
10541 END
10542 call v9.CheckSourceSuccess(lines)
10543
10544 " call empty() using an object from a script
10545 let lines =<< trim END
10546 vim9script
10547 class A
10548 def empty(): bool
10549 return true
10550 enddef
10551 endclass
10552 var afoo = A.new()
10553 assert_equal(true, afoo.empty())
10554 END
10555 call v9.CheckSourceSuccess(lines)
10556
10557 " call empty() using an object from a method
10558 let lines =<< trim END
10559 vim9script
10560 class A
10561 def empty(): bool
10562 return true
10563 enddef
10564 endclass
10565 def Foo()
10566 var afoo = A.new()
10567 assert_equal(true, afoo.empty())
10568 enddef
10569 Foo()
10570 END
10571 call v9.CheckSourceSuccess(lines)
10572
10573 " call empty() using "this" from an object method
10574 let lines =<< trim END
10575 vim9script
10576 class A
10577 def empty(): bool
10578 return true
10579 enddef
10580 def Foo(): bool
10581 return this.empty()
10582 enddef
10583 endclass
10584 def Bar()
10585 var abar = A.new()
10586 assert_equal(true, abar.Foo())
10587 enddef
10588 Bar()
10589 END
10590 call v9.CheckSourceSuccess(lines)
10591
10592 " Call empty() from a derived object
10593 let lines =<< trim END
10594 vim9script
10595 class A
10596 def empty(): bool
10597 return false
10598 enddef
10599 endclass
10600 class B extends A
10601 def empty(): bool
10602 return true
10603 enddef
10604 endclass
10605 def Foo(afoo: A)
10606 assert_equal(true, empty(afoo))
10607 var bfoo = B.new()
10608 assert_equal(true, empty(bfoo))
10609 enddef
10610 var b = B.new()
10611 assert_equal(1, empty(b))
10612 Foo(b)
10613 END
10614 call v9.CheckSourceSuccess(lines)
10615
10616 " Invoking empty method using an interface
10617 let lines =<< trim END
10618 vim9script
10619 interface A
10620 def empty(): bool
10621 endinterface
10622 class B implements A
10623 def empty(): bool
10624 return false
10625 enddef
10626 endclass
10627 def Foo(a: A)
10628 assert_equal(false, empty(a))
10629 enddef
10630 var b = B.new()
10631 Foo(b)
10632 END
10633 call v9.CheckSourceSuccess(lines)
10634endfunc
10635
10636" Test for using the len() builtin method with an object
10637" This is a legacy function to use the test_garbagecollect_now() function.
10638func Test_object_length()
10639 let lines =<< trim END
10640 vim9script
10641 class A
10642 var mylen: number = 0
10643 def new(n: number)
10644 this.mylen = n
10645 enddef
10646 def len(): number
10647 return this.mylen
10648 enddef
10649 endclass
10650
10651 def Foo()
10652 var afoo = A.new(12)
10653 assert_equal(12, len(afoo))
10654 assert_equal(12, afoo->len())
10655 enddef
10656
10657 var a = A.new(22)
10658 assert_equal(22, len(a))
10659 assert_equal(22, a->len())
10660 test_garbagecollect_now()
10661 assert_equal(22, len(a))
10662 Foo()
10663 test_garbagecollect_now()
10664 Foo()
10665 END
10666 call v9.CheckSourceSuccess(lines)
10667
10668 " len() should return 0 without a builtin method
10669 let lines =<< trim END
10670 vim9script
10671 class A
10672 endclass
10673
10674 def Foo()
10675 var afoo = A.new()
10676 assert_equal(0, len(afoo))
10677 enddef
10678
10679 var a = A.new()
10680 assert_equal(0, len(a))
10681 Foo()
10682 END
10683 call v9.CheckSourceSuccess(lines)
10684
10685 " Unsupported signature for the len() method
10686 let lines =<< trim END
10687 vim9script
10688 class A
10689 def len()
10690 enddef
10691 endclass
10692 END
10693 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10694
10695 " Error when calling the len() method
10696 let lines =<< trim END
10697 vim9script
10698 class A
10699 def len(): number
10700 throw "Failed to compute length"
10701 enddef
10702 endclass
10703
10704 def Foo()
10705 var afoo = A.new()
10706 var i = len(afoo)
10707 enddef
10708
10709 var a = A.new()
10710 assert_fails('len(a)', 'Failed to compute length')
10711 assert_fails('Foo()', 'Failed to compute length')
10712 END
10713 call v9.CheckSourceSuccess(lines)
10714
10715 " call len() using an object from a script
10716 let lines =<< trim END
10717 vim9script
10718 class A
10719 def len(): number
10720 return 5
10721 enddef
10722 endclass
10723 var afoo = A.new()
10724 assert_equal(5, afoo.len())
10725 END
10726 call v9.CheckSourceSuccess(lines)
10727
10728 " call len() using an object from a method
10729 let lines =<< trim END
10730 vim9script
10731 class A
10732 def len(): number
10733 return 5
10734 enddef
10735 endclass
10736 def Foo()
10737 var afoo = A.new()
10738 assert_equal(5, afoo.len())
10739 enddef
10740 Foo()
10741 END
10742 call v9.CheckSourceSuccess(lines)
10743
10744 " call len() using "this" from an object method
10745 let lines =<< trim END
10746 vim9script
10747 class A
10748 def len(): number
10749 return 8
10750 enddef
10751 def Foo(): number
10752 return this.len()
10753 enddef
10754 endclass
10755 def Bar()
10756 var abar = A.new()
10757 assert_equal(8, abar.Foo())
10758 enddef
10759 Bar()
10760 END
10761 call v9.CheckSourceSuccess(lines)
10762
10763 " Call len() from a derived object
10764 let lines =<< trim END
10765 vim9script
10766 class A
10767 def len(): number
10768 return 10
10769 enddef
10770 endclass
10771 class B extends A
10772 def len(): number
10773 return 20
10774 enddef
10775 endclass
10776 def Foo(afoo: A)
10777 assert_equal(20, len(afoo))
10778 var bfoo = B.new()
10779 assert_equal(20, len(bfoo))
10780 enddef
10781 var b = B.new()
10782 assert_equal(20, len(b))
10783 Foo(b)
10784 END
10785 call v9.CheckSourceSuccess(lines)
10786
10787 " Invoking len method using an interface
10788 let lines =<< trim END
10789 vim9script
10790 interface A
10791 def len(): number
10792 endinterface
10793 class B implements A
10794 def len(): number
10795 return 123
10796 enddef
10797 endclass
10798 def Foo(a: A)
10799 assert_equal(123, len(a))
10800 enddef
10801 var b = B.new()
10802 Foo(b)
10803 END
10804 call v9.CheckSourceSuccess(lines)
10805endfunc
10806
10807" Test for using the string() builtin method with an object
10808" This is a legacy function to use the test_garbagecollect_now() function.
10809func Test_object_string()
10810 let lines =<< trim END
10811 vim9script
10812 class A
10813 var name: string
10814 def string(): string
10815 return this.name
10816 enddef
10817 endclass
10818
10819 def Foo()
10820 var afoo = A.new("foo-A")
10821 assert_equal('foo-A', string(afoo))
10822 assert_equal('foo-A', afoo->string())
10823 enddef
10824
10825 var a = A.new("script-A")
10826 assert_equal('script-A', string(a))
10827 assert_equal('script-A', a->string())
10828 assert_equal(['script-A'], execute('echo a')->split("\n"))
10829 test_garbagecollect_now()
10830 assert_equal('script-A', string(a))
10831 Foo()
10832 test_garbagecollect_now()
10833 Foo()
10834 END
10835 call v9.CheckSourceSuccess(lines)
10836
10837 " string() should return "object of A {}" without a builtin method
10838 let lines =<< trim END
10839 vim9script
10840 class A
10841 endclass
10842
10843 def Foo()
10844 var afoo = A.new()
10845 assert_equal('object of A {}', string(afoo))
10846 enddef
10847
10848 var a = A.new()
10849 assert_equal('object of A {}', string(a))
10850 Foo()
10851 END
10852 call v9.CheckSourceSuccess(lines)
10853
10854 " Unsupported signature for the string() method
10855 let lines =<< trim END
10856 vim9script
10857 class A
10858 def string()
10859 enddef
10860 endclass
10861 END
10862 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
10863
10864 " Error when calling the string() method
10865 let lines =<< trim END
10866 vim9script
10867 class A
10868 def string(): string
10869 throw "Failed to get text"
10870 enddef
10871 endclass
10872
10873 def Foo()
10874 var afoo = A.new()
10875 var i = string(afoo)
10876 enddef
10877
10878 var a = A.new()
10879 assert_fails('string(a)', 'Failed to get text')
10880 assert_fails('Foo()', 'Failed to get text')
10881 END
10882 call v9.CheckSourceSuccess(lines)
10883
10884 " call string() using an object from a script
10885 let lines =<< trim END
10886 vim9script
10887 class A
10888 def string(): string
10889 return 'A'
10890 enddef
10891 endclass
10892 var afoo = A.new()
10893 assert_equal('A', afoo.string())
10894 END
10895 call v9.CheckSourceSuccess(lines)
10896
10897 " call string() using an object from a method
10898 let lines =<< trim END
10899 vim9script
10900 class A
10901 def string(): string
10902 return 'A'
10903 enddef
10904 endclass
10905 def Foo()
10906 var afoo = A.new()
10907 assert_equal('A', afoo.string())
10908 enddef
10909 Foo()
10910 END
10911 call v9.CheckSourceSuccess(lines)
10912
10913 " call string() using "this" from an object method
10914 let lines =<< trim END
10915 vim9script
10916 class A
10917 def string(): string
10918 return 'A'
10919 enddef
10920 def Foo(): string
10921 return this.string()
10922 enddef
10923 endclass
10924 def Bar()
10925 var abar = A.new()
10926 assert_equal('A', abar.string())
10927 enddef
10928 Bar()
10929 END
10930 call v9.CheckSourceSuccess(lines)
10931
10932 " Call string() from a derived object
10933 let lines =<< trim END
10934 vim9script
10935 class A
10936 def string(): string
10937 return 'A'
10938 enddef
10939 endclass
10940 class B extends A
10941 def string(): string
10942 return 'B'
10943 enddef
10944 endclass
10945 def Foo(afoo: A)
10946 assert_equal('B', string(afoo))
10947 var bfoo = B.new()
10948 assert_equal('B', string(bfoo))
10949 enddef
10950 var b = B.new()
10951 assert_equal('B', string(b))
10952 Foo(b)
10953 END
10954 call v9.CheckSourceSuccess(lines)
10955
10956 " Invoking string method using an interface
10957 let lines =<< trim END
10958 vim9script
10959 interface A
10960 def string(): string
10961 endinterface
10962 class B implements A
10963 def string(): string
10964 return 'B'
10965 enddef
10966 endclass
10967 def Foo(a: A)
10968 assert_equal('B', string(a))
10969 enddef
10970 var b = B.new()
10971 Foo(b)
10972 END
10973 call v9.CheckSourceSuccess(lines)
10974endfunc
10975
Ernie Rael9d779c52024-07-07 20:41:44 +020010976" Test for using the string() builtin method with an object's method
10977def Test_method_string()
10978 var lines =<< trim END
10979 vim9script
10980 class A
10981 def F()
10982 enddef
10983 endclass
10984 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
10985 END
10986 v9.CheckScriptSuccess(lines)
10987enddef
10988
10989
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010010990" Test for using a class in the class definition
10991def Test_Ref_Class_Within_Same_Class()
10992 var lines =<< trim END
10993 vim9script
10994 class A
10995 var n: number = 0
10996 def Equals(other: A): bool
10997 return this.n == other.n
10998 enddef
10999 endclass
11000
11001 var a1 = A.new(10)
11002 var a2 = A.new(10)
11003 var a3 = A.new(20)
11004 assert_equal(true, a1.Equals(a2))
11005 assert_equal(false, a2.Equals(a3))
11006 END
11007 v9.CheckScriptSuccess(lines)
11008
11009 lines =<< trim END
11010 vim9script
11011
11012 class Foo
11013 var num: number
11014 def Clone(): Foo
11015 return Foo.new(this.num)
11016 enddef
11017 endclass
11018
11019 var f1 = Foo.new(1)
11020
11021 def F()
11022 var f2: Foo = f1.Clone()
11023 assert_equal(false, f2 is f1)
11024 assert_equal(true, f2.num == f1.num)
11025 enddef
11026 F()
11027
11028 var f3: Foo = f1.Clone()
11029 assert_equal(false, f3 is f1)
11030 assert_equal(true, f3.num == f1.num)
11031 END
11032 v9.CheckScriptSuccess(lines)
11033
11034 # Test for trying to use a class to extend when defining the same class
11035 lines =<< trim END
11036 vim9script
11037 class A extends A
11038 endclass
11039 END
11040 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
11041
11042 # Test for trying to use a class to implement when defining the same class
11043 lines =<< trim END
11044 vim9script
11045 class A implements A
11046 endclass
11047 END
11048 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
11049enddef
11050
Ernie Raelf0e69142024-06-22 11:12:00 +020011051" Test for comparing a class referencing itself
11052def Test_Object_Compare_With_Recursive_Class_Ref()
11053 var lines =<< trim END
11054 vim9script
11055
11056 class C
11057 public var nest: C
11058 endclass
11059
11060 var o1 = C.new()
11061 o1.nest = o1
11062
11063 var result = o1 == o1
11064 assert_equal(true, result)
11065 END
11066 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020011067
11068 lines =<< trim END
11069 vim9script
11070
11071 class C
11072 public var nest: C
11073 endclass
11074 var o1 = C.new()
11075 var o2 = C.new(C.new())
11076
11077 var result = o1 == o2
11078 assert_equal(false, result)
11079 END
11080 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020011081
11082 lines =<< trim END
11083 vim9script
11084 class C
11085 var nest1: C
11086 var nest2: C
11087 def Init(n1: C, n2: C)
11088 this.nest1 = n1
11089 this.nest2 = n2
11090 enddef
11091 endclass
11092
11093 var o1 = C.new()
11094 var o2 = C.new()
11095 o1.Init(o1, o2)
11096 o2.Init(o2, o1)
11097
11098 var result = o1 == o2
11099 assert_equal(true, result)
11100 END
11101 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020011102enddef
11103
Ernie Raelf3975492024-07-06 11:44:37 +020011104" Test for comparing a class with nesting objects
11105def Test_Object_Compare_With_Nesting_Objects()
11106 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
11107 # return the compare is equal.
11108 # Test that limit
11109
11110 var lines =<< trim END
11111 vim9script
11112 class C
11113 public var n: number
11114 public var nest: C
11115
11116 # Create a "C" that chains/nests to indicated depth.
11117 # return {head: firstC, tail: lastC}
11118 static def CreateNested(depth: number): dict<C>
11119 var first = C.new(1, null_object)
11120 var last = first
11121 for i in range(2, depth)
11122 last.nest = C.new(i, null_object)
11123 last = last.nest
11124 endfor
11125 return {head: first, tail: last}
11126 enddef
11127
11128 # Return pointer to nth item in chain.
11129 def GetLink(depth: number): C
11130 var count = 1
11131 var p: C = this
11132 while count < depth
11133 p = p.nest
11134 if p == null
11135 throw "too deep"
11136 endif
11137 count += 1
11138 endwhile
11139 return p
11140 enddef
11141
11142 # Return the length of the chain
11143 def len(): number
11144 var count = 1
11145 var p: C = this
11146 while p.nest != null
11147 p = p.nest
11148 count += 1
11149 endwhile
11150 return count
11151 enddef
11152 endclass
11153
11154 var chain = C.CreateNested(3)
11155 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
11156 assert_equal(s, string(chain.head))
11157 assert_equal(3, chain.head->len())
11158
11159 var chain1 = C.CreateNested(100)
11160 var chain2 = C.CreateNested(100)
11161 assert_true(chain1.head == chain2.head)
11162
11163 # modify the tail of chain2, compare not equal
11164 chain2.tail.n = 123456
11165 assert_true(chain1.head != chain2.head)
11166
11167 # a tail of a different length compares not equal
11168 chain2 = C.CreateNested(101)
11169 assert_true(chain1.head != chain2.head)
11170
11171 chain1 = C.CreateNested(1000)
11172 chain2 = C.CreateNested(1000)
11173 assert_true(chain1.head == chain2.head)
11174
11175 # modify the tail of chain2, compare not equal
11176 chain2.tail.n = 123456
11177 assert_true(chain1.head != chain2.head)
11178
11179 # try a chain longer that the limit
11180 chain1 = C.CreateNested(1001)
11181 chain2 = C.CreateNested(1001)
11182 assert_true(chain1.head == chain2.head)
11183
11184 # modify the tail, but still equal
11185 chain2.tail.n = 123456
11186 assert_true(chain1.head == chain2.head)
11187
11188 # remove 2 items from front, shorten the chain by two.
11189 chain1.head = chain1.head.GetLink(3)
11190 chain2.head = chain2.head.GetLink(3)
11191 assert_equal(3, chain1.head.n)
11192 assert_equal(3, chain2.head.n)
11193 assert_equal(999, chain1.head->len())
11194 assert_equal(999, chain2.head->len())
11195 # Now less than the limit, compare not equal
11196 assert_true(chain1.head != chain2.head)
11197 END
11198 v9.CheckScriptSuccess(lines)
11199enddef
11200
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011201" Test for using a compound operator from a lambda function in an object method
11202def Test_compound_op_in_objmethod_lambda()
11203 # Test using the "+=" operator
11204 var lines =<< trim END
11205 vim9script
11206 class A
11207 var n: number = 10
11208 def Foo()
11209 var Fn = () => {
11210 this.n += 1
11211 }
11212 Fn()
11213 enddef
11214 endclass
11215
11216 var a = A.new()
11217 a.Foo()
11218 assert_equal(11, a.n)
11219 END
11220 v9.CheckScriptSuccess(lines)
11221
11222 # Test using the "..=" operator
11223 lines =<< trim END
11224 vim9script
11225 class A
11226 var s: string = "a"
11227 def Foo()
11228 var Fn = () => {
11229 this.s ..= "a"
11230 }
11231 Fn()
11232 enddef
11233 endclass
11234
11235 var a = A.new()
11236 a.Foo()
11237 a.Foo()
11238 assert_equal("aaa", a.s)
11239 END
11240 v9.CheckScriptSuccess(lines)
11241enddef
11242
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011243" Test for using test_refcount() with a class and an object
11244def Test_class_object_refcount()
11245 var lines =<< trim END
11246 vim9script
11247 class A
11248 endclass
11249 var a: A = A.new()
11250 assert_equal(2, test_refcount(A))
11251 assert_equal(1, test_refcount(a))
11252 var b = a
11253 assert_equal(2, test_refcount(A))
11254 assert_equal(2, test_refcount(a))
11255 assert_equal(2, test_refcount(b))
11256 END
11257 v9.CheckScriptSuccess(lines)
11258enddef
11259
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011260" call a lambda function in one object from another object
11261def Test_lambda_invocation_across_classes()
11262 var lines =<< trim END
11263 vim9script
11264 class A
11265 var s: string = "foo"
11266 def GetFn(): func
11267 var Fn = (): string => {
11268 return this.s
11269 }
11270 return Fn
11271 enddef
11272 endclass
11273
11274 class B
11275 var s: string = "bar"
11276 def GetFn(): func
11277 var a = A.new()
11278 return a.GetFn()
11279 enddef
11280 endclass
11281
11282 var b = B.new()
11283 var Fn = b.GetFn()
11284 assert_equal("foo", Fn())
11285 END
11286 v9.CheckScriptSuccess(lines)
11287enddef
11288
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011289" Test for using a class member which is an object of the current class
11290def Test_current_class_object_class_member()
11291 var lines =<< trim END
11292 vim9script
11293 class A
11294 public static var obj1: A = A.new(10)
11295 var n: number
11296 endclass
11297 defcompile
11298 assert_equal(10, A.obj1.n)
11299 END
11300 v9.CheckScriptSuccess(lines)
11301enddef
11302
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011303" Test for updating a base class variable from a base class method without the
11304" class name. This used to crash Vim (Github issue #14352).
11305def Test_use_base_class_variable_from_base_class_method()
11306 var lines =<< trim END
11307 vim9script
11308
11309 class DictKeyClass
11310 static var _obj_id_count = 1
11311 def _GenerateKey()
11312 _obj_id_count += 1
11313 enddef
11314 static def GetIdCount(): number
11315 return _obj_id_count
11316 enddef
11317 endclass
11318
11319 class C extends DictKeyClass
11320 def F()
11321 this._GenerateKey()
11322 enddef
11323 endclass
11324
11325 C.new().F()
11326 assert_equal(2, DictKeyClass.GetIdCount())
11327 END
11328 v9.CheckScriptSuccess(lines)
11329enddef
11330
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011331" Test for accessing protected funcref object and class variables
11332def Test_protected_funcref()
11333 # protected funcref object variable
11334 var lines =<< trim END
11335 vim9script
11336 class Test1
11337 const _Id: func(any): any = (v) => v
11338 endclass
11339 var n = Test1.new()._Id(1)
11340 END
11341 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11342
11343 # protected funcref class variable
11344 lines =<< trim END
11345 vim9script
11346 class Test2
11347 static const _Id: func(any): any = (v) => v
11348 endclass
11349 var n = Test2._Id(2)
11350 END
11351 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11352enddef
11353
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011354" Test for using lambda block in classes
11355def Test_lambda_block_in_class()
11356 # This used to crash Vim
11357 var lines =<< trim END
11358 vim9script
11359 class IdClass1
11360 const Id: func(number): number = (num: number): number => {
11361 # Return a ID
11362 return num * 10
11363 }
11364 endclass
11365 var id = IdClass1.new()
11366 assert_equal(20, id.Id(2))
11367 END
11368 v9.CheckScriptSuccess(lines)
11369
11370 # This used to crash Vim
11371 lines =<< trim END
11372 vim9script
11373 class IdClass2
11374 static const Id: func(number): number = (num: number): number => {
11375 # Return a ID
11376 return num * 2
11377 }
11378 endclass
11379 assert_equal(16, IdClass2.Id(8))
11380 END
11381 v9.CheckScriptSuccess(lines)
11382enddef
11383
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011384" Test for defcompiling an abstract method
11385def Test_abstract_method_defcompile()
11386 # Compile an abstract class with abstract object methods
11387 var lines =<< trim END
11388 vim9script
11389 abstract class A
11390 abstract def Foo(): string
11391 abstract def Bar(): list<string>
11392 endclass
11393 defcompile
11394 END
11395 v9.CheckScriptSuccess(lines)
11396
11397 # Compile a concrete object method in an abstract class
11398 lines =<< trim END
11399 vim9script
11400 abstract class A
11401 abstract def Foo(): string
11402 abstract def Bar(): list<string>
11403 def Baz(): string
11404 pass
11405 enddef
11406 endclass
11407 defcompile
11408 END
11409 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11410
11411 # Compile a concrete class method in an abstract class
11412 lines =<< trim END
11413 vim9script
11414 abstract class A
11415 abstract def Foo(): string
11416 abstract def Bar(): list<string>
11417 static def Baz(): string
11418 pass
11419 enddef
11420 endclass
11421 defcompile
11422 END
11423 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11424enddef
11425
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011426" Test for defining a class in a function
11427def Test_class_definition_in_a_function()
11428 var lines =<< trim END
11429 vim9script
11430 def Foo()
11431 class A
11432 endclass
11433 enddef
11434 defcompile
11435 END
11436 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11437enddef
11438
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011439" Test for using [] with a class and an object
11440def Test_class_object_index()
11441 var lines =<< trim END
11442 vim9script
11443 class A
11444 endclass
11445 A[10] = 1
11446 END
11447 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11448
11449 lines =<< trim END
11450 vim9script
11451 class A
11452 endclass
11453 var a = A.new()
11454 a[10] = 1
11455 END
11456 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11457enddef
11458
LemonBoyf4af3312024-07-04 13:43:12 +020011459def Test_class_member_init_typecheck()
11460 # Ensure the class member is assigned its declared type.
11461 var lines =<< trim END
11462 vim9script
11463 class S
11464 static var l: list<string> = []
11465 endclass
11466 S.l->add(123)
11467 END
11468 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11469
11470 # Ensure the initializer value and the declared type match.
11471 lines =<< trim END
11472 vim9script
11473 class S
11474 var l: list<string> = [1, 2, 3]
11475 endclass
11476 var o = S.new()
11477 END
11478 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11479
11480 # Ensure the class member is assigned its declared type.
11481 lines =<< trim END
11482 vim9script
11483 class S
11484 var l: list<string> = []
11485 endclass
11486 var o = S.new()
11487 o.l->add(123)
11488 END
11489 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11490enddef
11491
LemonBoy50d48542024-07-04 17:03:17 +020011492def Test_class_cast()
11493 var lines =<< trim END
11494 vim9script
11495 class A
11496 endclass
11497 class B extends A
11498 var mylen: number
11499 endclass
11500 def F(o: A): number
11501 return (<B>o).mylen
11502 enddef
11503
11504 defcompile F
11505 END
11506 v9.CheckScriptSuccess(lines)
11507enddef
11508
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011509" Test for using a variable of type "any" with an object
11510def Test_any_obj_var_type()
11511 var lines =<< trim END
11512 vim9script
11513 class A
11514 var name: string = "foobar"
11515 def Foo(): string
11516 return "func foo"
11517 enddef
11518 endclass
11519
11520 def CheckVals(x: any)
11521 assert_equal("foobar", x.name)
11522 assert_equal("func foo", x.Foo())
11523 enddef
11524
11525 var a = A.new()
11526 CheckVals(a)
11527 END
11528 v9.CheckScriptSuccess(lines)
11529
11530 # Try to set a non-existing variable
11531 lines =<< trim END
11532 vim9script
11533 class A
11534 var name: string = "foobar"
11535 endclass
11536
11537 def SetNonExistingVar(x: any)
11538 x.bar = [1, 2, 3]
11539 enddef
11540
11541 var a = A.new()
11542 SetNonExistingVar(a)
11543 END
11544 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11545
11546 # Try to read a non-existing variable
11547 lines =<< trim END
11548 vim9script
11549 class A
11550 var name: string = "foobar"
11551 endclass
11552
11553 def GetNonExistingVar(x: any)
11554 var i: dict<any> = x.bar
11555 enddef
11556
11557 var a = A.new()
11558 GetNonExistingVar(a)
11559 END
11560 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11561
11562 # Try to invoke a non-existing method
11563 lines =<< trim END
11564 vim9script
11565 class A
11566 def Foo(): number
11567 return 10
11568 enddef
11569 endclass
11570
11571 def CallNonExistingMethod(x: any)
11572 var i: number = x.Bar()
11573 enddef
11574
11575 var a = A.new()
11576 CallNonExistingMethod(a)
11577 END
11578 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11579
11580 # Use an object which is a Dict value
11581 lines =<< trim END
11582 vim9script
11583 class Foo
11584 def Bar(): number
11585 return 369
11586 enddef
11587 endclass
11588
11589 def GetValue(FooDict: dict<any>): number
11590 var n: number = 0
11591 for foo in values(FooDict)
11592 n += foo.Bar()
11593 endfor
11594 return n
11595 enddef
11596
11597 var d = {'x': Foo.new()}
11598 assert_equal(369, GetValue(d))
11599 END
11600 v9.CheckScriptSuccess(lines)
11601
zeertzjqd32bf0a2024-12-17 20:55:13 +010011602 # Nested data. Object containing a Dict containing another Object.
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011603 lines =<< trim END
11604 vim9script
11605 class Context
11606 public var state: dict<any> = {}
11607 endclass
11608
11609 class Metadata
11610 public var value = 0
11611 endclass
11612
11613 var ctx = Context.new()
11614 ctx.state["meta"] = Metadata.new(2468)
11615
11616 const foo = ctx.state.meta.value
11617
11618 def F(): number
11619 const bar = ctx.state.meta.value
11620 return bar
11621 enddef
11622
11623 assert_equal(2468, F())
11624 END
11625 v9.CheckScriptSuccess(lines)
11626
11627 # Accessing an object from a method inside the class using any type
11628 lines =<< trim END
11629 vim9script
11630 class C
11631 def _G(): string
11632 return '_G'
11633 enddef
11634 static def S(o_any: any): string
11635 return o_any._G()
11636 enddef
11637 endclass
11638
11639 var o1 = C.new()
11640 assert_equal('_G', C.S(o1))
11641 END
11642 v9.CheckScriptSuccess(lines)
11643
11644 # Modifying an object private variable from a method in another class using
11645 # any type
11646 lines =<< trim END
11647 vim9script
11648
11649 class A
11650 var num = 10
11651 endclass
11652
11653 class B
11654 def SetVal(x: any)
11655 x.num = 20
11656 enddef
11657 endclass
11658
11659 var a = A.new()
11660 var b = B.new()
11661 b.SetVal(a)
11662 END
11663 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11664
11665 # Accessing a object protected variable from a method in another class using
11666 # any type
11667 lines =<< trim END
11668 vim9script
11669
11670 class A
11671 var _num = 10
11672 endclass
11673
11674 class B
11675 def GetVal(x: any): number
11676 return x._num
11677 enddef
11678 endclass
11679
11680 var a = A.new()
11681 var b = B.new()
11682 var i = b.GetVal(a)
11683 END
11684 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11685
11686 # Accessing an object returned from an imported function and class
11687 lines =<< trim END
11688 vim9script
11689 export class Foo
11690 public var name: string
11691 endclass
11692
11693 export def ReturnFooObject(): Foo
11694 var r = Foo.new('star')
11695 return r
11696 enddef
11697 END
11698 writefile(lines, 'Xanyvar1.vim', 'D')
11699
11700 lines =<< trim END
11701 vim9script
11702
11703 import './Xanyvar1.vim'
11704
11705 def GetName(): string
11706 var whatever = Xanyvar1.ReturnFooObject()
11707 return whatever.name
11708 enddef
11709
11710 assert_equal('star', GetName())
11711 END
11712 v9.CheckScriptSuccess(lines)
11713
11714 # Try to modify a private object variable using a variable of type "any"
11715 lines =<< trim END
11716 vim9script
11717
11718 class Foo
11719 var n: number = 10
11720 endclass
11721 def Fn(x: any)
11722 x.n = 20
11723 enddef
11724 var a = Foo.new()
11725 Fn(a)
11726 END
11727 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11728
11729 # Try to read a protected object variable using a variable of type "any"
11730 lines =<< trim END
11731 vim9script
11732
11733 class Foo
11734 var _n: number = 10
11735 endclass
11736 def Fn(x: any): number
11737 return x._n
11738 enddef
11739
11740 var a = Foo.new()
11741 Fn(a)
11742 END
11743 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11744
11745 # Read a protected object variable using a variable of type "any" in an object
11746 # method
11747 lines =<< trim END
11748 vim9script
11749
11750 class Foo
11751 var _n: number = 10
11752 def Fn(x: any): number
11753 return x._n
11754 enddef
11755 endclass
11756
11757 var a = Foo.new()
11758 assert_equal(10, a.Fn(a))
11759 END
11760 v9.CheckScriptSuccess(lines)
11761
11762 # Try to call a protected object method using a "any" type variable
11763 lines =<< trim END
11764 vim9script
11765
11766 class Foo
11767 def _GetVal(): number
11768 return 234
11769 enddef
11770 endclass
11771 def Fn(x: any): number
11772 return x._GetVal()
11773 enddef
11774
11775 var a = Foo.new()
11776 Fn(a)
11777 END
11778 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11779
11780 # Call a protected object method using a "any" type variable from another
11781 # object method
11782 lines =<< trim END
11783 vim9script
11784
11785 class Foo
11786 def _GetVal(): number
11787 return 234
11788 enddef
11789 def FooVal(x: any): number
11790 return x._GetVal()
11791 enddef
11792 endclass
11793
11794 var a = Foo.new()
11795 assert_equal(234, a.FooVal(a))
11796 END
11797 v9.CheckScriptSuccess(lines)
11798
11799 # Method chaining
11800 lines =<< trim END
11801 vim9script
11802
11803 export class T
11804 var id: number = 268
11805 def F(): any
11806 return this
11807 enddef
11808 endclass
11809
11810 def H()
11811 var a = T.new().F().F()
11812 assert_equal(268, a.id)
11813 enddef
11814 H()
11815
11816 var b: T = T.new().F().F()
11817 assert_equal(268, b.id)
11818 END
11819 v9.CheckScriptSuccess(lines)
11820
11821 # Using a null object to access a member variable
11822 lines =<< trim END
11823 vim9script
11824 def Fn(x: any): number
11825 return x.num
11826 enddef
11827
11828 Fn(null_object)
11829 END
11830 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11831
11832 # Using a null object to invoke a method
11833 lines =<< trim END
11834 vim9script
11835 def Fn(x: any)
11836 x.Foo()
11837 enddef
11838
11839 Fn(null_object)
11840 END
11841 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
Yegappan Lakshmanane7984462024-11-12 21:03:00 +010011842
11843 # Try to change a const object variable using a "any" variable
11844 lines =<< trim END
11845 vim9script
11846 class A
11847 public const v1: number = 123
11848 endclass
11849
11850 def Fn(o: any)
11851 o.v1 = 321
11852 enddef
11853
11854 var a = A.new()
11855 Fn(a)
11856 END
11857 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11858
11859 # Try to change a final object variable using a "any" variable
11860 lines =<< trim END
11861 vim9script
11862 class A
11863 public final v1: number = 123
11864 endclass
11865
11866 def Fn(o: any)
11867 o.v1 = 321
11868 enddef
11869
11870 var a = A.new()
11871 Fn(a)
11872 END
11873 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11874
11875 # Assign a different type of value to an "any" type object variable
11876 lines =<< trim END
11877 vim9script
11878 class A
11879 public var v1: list<any> = [1, 2]
11880 endclass
11881
11882 def Fn(o: A)
11883 o.v1 = 'abc'
11884 enddef
11885
11886 var a = A.new()
11887 Fn(a)
11888 END
11889 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 1)
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011890enddef
11891
Yegappan Lakshmanan481992c2024-12-06 18:35:12 +010011892" Test for using an object method with mapnew()
11893def Test_mapnew_with_instance_method()
11894 var lines =<< trim END
11895 vim9script
11896
11897 class Foo
11898 var str: string
11899 var nums: list<number> = [1, 2, 3]
11900
11901 def InstanceMethod(n: number): string
11902 return this.str .. n
11903 enddef
11904
11905 def MapperMethod(idx: number, elem: number): string
11906 return elem->this.InstanceMethod()
11907 enddef
11908
11909 def MapTest()
11910 this.str = "foo"
11911 var l = ['foo1', 'foo2', 'foo3']
11912 assert_equal(l, this.nums->mapnew(this.MapperMethod))
11913 enddef
11914 endclass
11915
11916 Foo.new().MapTest()
11917 END
11918 v9.CheckSourceSuccess(lines)
11919
11920 # Error in the mapnew() function
11921 lines =<< trim END
11922 vim9script
11923
11924 class Foo
11925 var str: string
11926 var nums: list<number> = [1, 2, 3]
11927
11928 def InstanceMethod(n: number): string
11929 throw "InstanceMethod failed"
11930 enddef
11931
11932 def MapperMethod(idx: number, elem: number): string
11933 return elem->this.InstanceMethod()
11934 enddef
11935
11936 def MapTest()
11937 this.str = "foo"
11938 var caught_exception: bool = false
11939 try
11940 this.nums->mapnew(this.MapperMethod)
11941 catch /InstanceMethod failed/
11942 caught_exception = true
11943 endtry
11944 assert_true(caught_exception)
11945 enddef
11946 endclass
11947
11948 Foo.new().MapTest()
11949 END
11950 v9.CheckSourceSuccess(lines)
11951enddef
11952
Yegappan Lakshmananb0206e92024-12-30 09:52:16 +010011953" Test for using an object method in a method call.
11954def Test_use_object_method_in_a_method_call()
11955 var lines =<< trim END
11956 vim9script
11957
11958 class Foo
11959 def Cost(nums: list<number>): number
11960 return nums[0] * nums[1]
11961 enddef
11962
11963 def ShowCost(): string
11964 var g = [4, 5]
11965 return $"Cost is: {g->this.Cost()}"
11966 enddef
11967 endclass
11968
11969 var d = Foo.new()
11970 assert_equal('Cost is: 20', d.ShowCost())
11971 END
11972 v9.CheckSourceSuccess(lines)
11973
11974 # Test for using a non-existing object method in string interpolation
11975 lines =<< trim END
11976 vim9script
11977
11978 class Foo
11979 def Cost(nums: list<number>): number
11980 return nums[0] * nums[1]
11981 enddef
11982
11983 def ShowCost(): string
11984 var g = [4, 5]
11985 echo $"Cost is: {g->this.NewCost()}"
11986 enddef
11987 endclass
11988
11989 var d = Foo.new()
11990 d.ShowCost()
11991 END
11992 v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
11993enddef
11994
Yegappan Lakshmananb04af4c2025-01-03 10:50:08 +010011995" Test for referencing an object variable which is not yet initialized
11996def Test_uninitialized_object_var()
11997 var lines =<< trim END
11998 vim9script
11999 class Foo
12000 const two: number = Foo.Two(this)
12001 const one: number = 1
12002
12003 static def Two(that: Foo): number
12004 return that.one + 2
12005 enddef
12006 endclass
12007
12008 echo Foo.Two(Foo.new())
12009 END
12010 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
12011
12012 lines =<< trim END
12013 vim9script
12014 class Foo
12015 const one: number = Foo.One(this)
12016
12017 static def One(that: Foo): number
12018 return 1
12019 enddef
12020 endclass
12021
12022 assert_equal(1, Foo.One(Foo.new()))
12023 END
12024 v9.CheckSourceSuccess(lines)
12025
12026 lines =<< trim END
12027 vim9script
12028 class Foo
12029 const one: number = 1
12030 const two: number = Foo.Two(this)
12031
12032 static def Two(that: Foo): number
12033 return that.one + 1
12034 enddef
12035 endclass
12036
12037 assert_equal(2, Foo.Two(Foo.new()))
12038 END
12039 v9.CheckSourceSuccess(lines)
12040
12041 lines =<< trim END
12042 vim9script
12043 class Foo
12044 const Id: func(any): any = ((_) => (v) => v)(this)
12045
12046 static def Id(that: Foo): func(any): any
12047 return that.Id
12048 enddef
12049 endclass
12050
12051 assert_equal(5, Foo.Id(Foo.new())(5))
12052 assert_equal(7, Foo.new().Id(7))
12053 END
12054 v9.CheckSourceSuccess(lines)
12055
12056 lines =<< trim END
12057 vim9script
12058 class Foo
12059 const Id: func(any): any = ((that) => (_) => that)(this)
12060
12061 static def Id(that: Foo): func(any): any
12062 return that.Id
12063 enddef
12064 endclass
12065
12066 const Id0: func(any): any = Foo.Id(Foo.new())
12067 const Id1: func(any): any = Foo.new().Id
12068 END
12069 v9.CheckSourceSuccess(lines)
12070
12071 lines =<< trim END
12072 vim9script
12073 class Foo
12074 const Id: any = Foo.Id(this)
12075
12076 static def Id(that: Foo): any
12077 return that.Id
12078 enddef
12079 endclass
12080
12081 const Id2: any = Foo.Id(Foo.new())
12082 const Id3: any = Foo.new().Id
12083 END
12084 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
12085
12086 lines =<< trim END
12087 vim9script
12088
12089 class Foo
12090 var x: string = ''
12091 var Y: func(): string = () => this.x
12092 endclass
12093
12094 var foo = Foo.new('ok')
12095 assert_equal('ok', foo.Y())
12096 END
12097 v9.CheckSourceSuccess(lines)
12098
12099 lines =<< trim END
12100 vim9script
12101
12102 class Foo
12103 var x: string = this.x
12104 endclass
12105
12106 var foo = Foo.new('ok')
12107 END
12108 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
12109enddef
12110
Yegappan Lakshmanan2050dcc2025-01-06 18:34:49 +010012111" Test for initializing member variables of compound type in the constructor
12112def Test_constructor_init_compound_member_var()
12113 var lines =<< trim END
12114 vim9script
12115
12116 class Foo
12117 var v1: string = "aaa"
12118 var v2: list<number> = [1, 2]
12119 var v3: dict<string> = {a: 'a', b: 'b'}
12120 endclass
12121
12122 class Bar
12123 var v4: string = "bbb"
12124 var v5: Foo = Foo.new()
12125 var v6: list<number> = [1, 2]
12126 endclass
12127
12128 var b: Bar = Bar.new()
12129 assert_equal("aaa", b.v5.v1)
12130 assert_equal([1, 2], b.v5.v2)
12131 assert_equal({a: 'a', b: 'b'}, b.v5.v3)
12132 assert_equal("bbb", b.v4)
12133 assert_equal([1, 2], b.v6)
12134 END
12135 v9.CheckSourceSuccess(lines)
12136enddef
12137
Yegappan Lakshmanan68d08582025-02-09 19:39:52 +010012138" Test for using a concrete method in an abstract extended class which is
12139" further extended
12140def Test_abstract_method_across_hierarchy()
12141 var lines =<< trim END
12142 vim9script
12143
12144 abstract class A
12145 abstract def Foo(): string
12146 endclass
12147
12148 abstract class B extends A
12149 abstract def Bar(): string
12150 endclass
12151
12152 class C extends B
12153 def Foo(): string
12154 return 'foo'
12155 enddef
12156
12157 def Bar(): string
12158 return 'bar'
12159 enddef
12160 endclass
12161
12162 def Fn1(a: A): string
12163 return a.Foo()
12164 enddef
12165
12166 def Fn2(b: B): string
12167 return b.Bar()
12168 enddef
12169
12170 var c = C.new()
12171 assert_equal('foo', Fn1(c))
12172 assert_equal('bar', Fn2(c))
12173 END
12174 v9.CheckSourceSuccess(lines)
12175
12176 lines =<< trim END
12177 vim9script
12178
12179 abstract class A
12180 abstract def Foo(): string
12181 endclass
12182
12183 abstract class B extends A
12184 abstract def Bar(): string
12185 endclass
12186
12187 class C extends B
12188 def Bar(): string
12189 return 'bar'
12190 enddef
12191 endclass
12192
12193 defcompile
12194 END
12195 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
12196
12197 lines =<< trim END
12198 vim9script
12199
12200 abstract class A
12201 abstract def M1(): string
12202 abstract def M2(): string
12203 endclass
12204
12205 abstract class B extends A
12206 def M1(): string
12207 return 'B: M1'
12208 enddef
12209
12210 def M2(): string
12211 return 'B: M2'
12212 enddef
12213 endclass
12214
12215 class C1 extends B
12216 def M1(): string
12217 return 'C1: M1'
12218 enddef
12219 endclass
12220
12221 class C2 extends B
12222 def M2(): string
12223 return 'C2: M2'
12224 enddef
12225 endclass
12226
12227 class D1 extends C1
12228 endclass
12229
12230 class D2 extends C2
12231 endclass
12232
12233 var l: list<string> = []
12234 for Type in ['C1', 'C2', 'D1', 'D2']
12235 l->add(eval($'{Type}.new().M1()'))
12236 l->add(eval($'{Type}.new().M2()'))
12237 endfor
12238 assert_equal(['C1: M1', 'B: M2', 'B: M1', 'C2: M2', 'C1: M1', 'B: M2', 'B: M1', 'C2: M2'], l)
12239 END
12240 v9.CheckSourceSuccess(lines)
12241
12242 lines =<< trim END
12243 vim9script
12244
12245 abstract class A
12246 abstract def M1(): string
12247 abstract def M2(): string
12248 endclass
12249
12250 class B extends A
12251 def M1(): string
12252 return 'B: M1'
12253 enddef
12254
12255 def M2(): string
12256 return 'B: M2'
12257 enddef
12258 endclass
12259
12260 abstract class C extends B
12261 endclass
12262
12263 class D1 extends C
12264 def M1(): string
12265 return 'D1: M1'
12266 enddef
12267 endclass
12268
12269 class D2 extends C
12270 def M2(): string
12271 return 'D2: M2'
12272 enddef
12273 endclass
12274
12275 class E1 extends D1
12276 endclass
12277
12278 class E2 extends D2
12279 endclass
12280
12281 var l: list<string> = []
12282 for Type in ['B', 'D1', 'D2', 'E1', 'E2']
12283 l->add(eval($'{Type}.new().M1()'))
12284 l->add( eval($'{Type}.new().M2()'))
12285 endfor
12286 assert_equal(['B: M1', 'B: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2'], l)
12287 END
12288 v9.CheckSourceSuccess(lines)
12289enddef
12290
Yegappan Lakshmanan7e898002025-02-11 22:07:05 +010012291" Test for using a protected new() method (singleton design pattern)
12292def Test_protected_new_method()
12293 var lines =<< trim END
12294 vim9script
12295 class A
12296 def _new()
12297 enddef
12298 endclass
12299 var a = A.new()
12300 END
12301 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "A"', 6)
12302
12303 lines =<< trim END
12304 vim9script
12305 class A
12306 static var _instance: A
12307 var str: string
12308 def _new(str: string)
12309 this.str = str
12310 enddef
12311 static def GetInstance(str: string): A
12312 if _instance == null
12313 _instance = A._new(str)
12314 endif
12315 return _instance
12316 enddef
12317 endclass
12318 var a: A = A.GetInstance('foo')
12319 var b: A = A.GetInstance('bar')
12320 assert_equal('foo', a.str)
12321 assert_equal('foo', b.str)
12322 END
12323 v9.CheckSourceSuccess(lines)
12324enddef
12325
Yegappan Lakshmananb5f463c2025-02-16 16:25:24 +010012326" Test for using 'super' in a closure function inside an object method
12327def Test_super_in_closure()
12328 var lines =<< trim END
12329 vim9script
12330
12331 class A
12332 const _value: number
12333
12334 def Fn(): func(any): number
12335 return (_: any) => this._value
12336 enddef
12337 endclass
12338
12339 class B extends A
12340 def Fn(): func(any): number
12341 return (_: any) => super._value
12342 enddef
12343 endclass
12344
12345 assert_equal(100, A.new(100).Fn()(null))
12346 assert_equal(200, B.new(200).Fn()(null))
12347 END
12348 v9.CheckSourceSuccess(lines)
12349enddef
12350
12351" Test for using 'super' to access methods and variables
12352def Test_super_keyword()
12353 var lines =<< trim END
12354 vim9script
12355 class Base
12356 var name: string
12357 def ToString(): string
12358 return this.name
12359 enddef
12360 endclass
12361
12362 class Child extends Base
12363 var age: number
12364 def ToString(): string
12365 return super.ToString() .. ': ' .. this.age
12366 enddef
12367 endclass
12368
12369 var o = Child.new('John', 42)
12370 assert_equal('John: 42', o.ToString())
12371 END
12372 v9.CheckSourceSuccess(lines)
12373
12374 lines =<< trim END
12375 vim9script
12376 class Child
12377 var age: number
12378 def ToString(): string
12379 return super .ToString() .. ': ' .. this.age
12380 enddef
12381 endclass
12382 var o = Child.new(42)
12383 echo o.ToString()
12384 END
12385 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
12386
12387 lines =<< trim END
12388 vim9script
12389 class Base
12390 var name: string
12391 def ToString(): string
12392 return this.name
12393 enddef
12394 endclass
12395
12396 var age = 42
12397 def ToString(): string
12398 return super.ToString() .. ': ' .. age
12399 enddef
12400 echo ToString()
12401 END
12402 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
12403
12404 lines =<< trim END
12405 vim9script
12406 class Child
12407 var age: number
12408 def ToString(): string
12409 return super.ToString() .. ': ' .. this.age
12410 enddef
12411 endclass
12412 var o = Child.new(42)
12413 echo o.ToString()
12414 END
12415 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
12416
12417 # Using super, Child invokes Base method which has optional arg. #12471
12418 lines =<< trim END
12419 vim9script
12420
12421 class Base
12422 var success: bool = false
12423 def Method(arg = 0)
12424 this.success = true
12425 enddef
12426 endclass
12427
12428 class Child extends Base
12429 def new()
12430 super.Method()
12431 enddef
12432 endclass
12433
12434 var obj = Child.new()
12435 assert_equal(true, obj.success)
12436 END
12437 v9.CheckSourceSuccess(lines)
12438
12439 # Using 'super' to access an object variable in the parent
12440 lines =<< trim END
12441 vim9script
12442
12443 class A
12444 var foo: string = 'xxx'
12445 endclass
12446
12447 class B extends A
12448 def GetString(): string
12449 return super.foo
12450 enddef
12451 endclass
12452
12453 var b: B = B.new()
12454 echo b.GetString()
12455 END
12456 v9.CheckSourceSuccess(lines)
12457
12458 # Using super to access an overriden method in the parent class
12459 lines =<< trim END
12460 vim9script
12461
12462 class A
12463 def Foo(): string
12464 return 'A.Foo'
12465 enddef
12466 endclass
12467
12468 class B extends A
12469 def Foo(): string
12470 return 'B.Foo'
12471 enddef
12472
12473 def Bar(): string
12474 return $'{super.Foo()} {this.Foo()}'
12475 enddef
12476 endclass
12477
12478 var b = B.new()
12479 assert_equal('A.Foo B.Foo', b.Bar())
12480 END
12481 v9.CheckSourceSuccess(lines)
12482enddef
12483
Bram Moolenaar00b28d62022-12-08 15:32:33 +000012484" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker