blob: 3b3ea2015f6c9c3d7d7729cc0b272160d67dd6ad [file] [log] [blame]
Bram Moolenaar00b28d62022-12-08 15:32:33 +00001" Test Vim9 classes
2
3source check.vim
4import './vim9.vim' as v9
5
6def Test_class_basic()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007 # Class supported only in "vim9script"
Bram Moolenaar00b28d62022-12-08 15:32:33 +00008 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02009 class NotWorking
10 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000011 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020012 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000013
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020014 # First character in a class name should be capitalized.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000015 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020016 vim9script
17 class notWorking
18 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000019 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020020 v9.CheckSourceFailure(lines, 'E1314: Class name must start with an uppercase letter: notWorking', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000021
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020022 # Only alphanumeric characters are supported in a class name
Bram Moolenaar00b28d62022-12-08 15:32:33 +000023 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020024 vim9script
25 class Not@working
26 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000027 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020028 v9.CheckSourceFailure(lines, 'E1315: White space required after name: Not@working', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000029
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020030 # Unsupported keyword (instead of class)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000031 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020032 vim9script
33 abstract noclass Something
34 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000035 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020036 v9.CheckSourceFailure(lines, 'E475: Invalid argument: noclass Something', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000037
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +010038 # Only the complete word "class" should be recognized
Bram Moolenaar00b28d62022-12-08 15:32:33 +000039 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020040 vim9script
41 abstract classy Something
42 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +000043 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020044 v9.CheckSourceFailure(lines, 'E475: Invalid argument: classy Something', 2)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000045
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020046 # The complete "endclass" should be specified.
Bram Moolenaar00b28d62022-12-08 15:32:33 +000047 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020048 vim9script
49 class Something
50 endcl
Bram Moolenaar00b28d62022-12-08 15:32:33 +000051 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020052 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endcl', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000053
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020054 # Additional words after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000055 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020056 vim9script
57 class Something
58 endclass school's out
Bram Moolenaar00b28d62022-12-08 15:32:33 +000059 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020060 v9.CheckSourceFailure(lines, "E488: Trailing characters: school's out", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000061
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +020062 # Additional commands after "endclass"
Bram Moolenaar00b28d62022-12-08 15:32:33 +000063 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020064 vim9script
65 class Something
66 endclass | echo 'done'
Bram Moolenaar00b28d62022-12-08 15:32:33 +000067 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +020068 v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +000069
Yegappan Lakshmananac773182024-04-27 11:36:12 +020070 # Additional command after "class name"
71 lines =<< trim END
72 vim9script
73 class Something | var x = 10
74 endclass
75 END
76 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
77
78 # Additional command after "object variable"
79 lines =<< trim END
80 vim9script
81 class Something
82 var l: list<number> = [] | var y = 10
83 endclass
84 END
85 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
86
87 # Additional command after "class variable"
88 lines =<< trim END
89 vim9script
90 class Something
91 static var d = {a: 10} | var y = 10
92 endclass
93 END
94 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
95
96 # Additional command after "object method"
97 lines =<< trim END
98 vim9script
99 class Something
100 def Foo() | var y = 10
101 enddef
102 endclass
103 END
104 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var y = 10", 3)
105
Yegappan Lakshmananfe55c312024-04-28 09:54:09 +0200106 # Comments are allowed after an inline block
107 lines =<< trim END
108 vim9script
109 class Foo
110 static const bar = { # {{{
111 baz: 'qux'
112 } # }}}
113 endclass
114 assert_equal({baz: 'qux'}, Foo.bar)
115 END
116 v9.CheckSourceSuccess(lines)
117
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +0100118 # Try to define a class with the same name as an existing variable
119 lines =<< trim END
120 vim9script
121 var Something: list<number> = [1]
122 class Thing
123 endclass
124 interface Api
125 endinterface
126 class Something extends Thing implements Api
127 var v1: string = ''
128 def Foo()
129 enddef
130 endclass
131 END
132 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 7)
133
zeertzjqe7102202024-02-13 20:32:04 +0100134 # Use old "this." prefixed member variable declaration syntax (without initialization)
Doug Kearns74da0ee2023-12-14 20:26:26 +0100135 lines =<< trim END
136 vim9script
137 class Something
138 this.count: number
139 endclass
140 END
141 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number', 3)
142
zeertzjqe7102202024-02-13 20:32:04 +0100143 # Use old "this." prefixed member variable declaration syntax (with initialization)
Doug Kearns74da0ee2023-12-14 20:26:26 +0100144 lines =<< trim END
145 vim9script
146 class Something
147 this.count: number = 42
148 endclass
149 END
150 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number = 42', 3)
151
152 # Use old "this." prefixed member variable declaration syntax (type inferred)
153 lines =<< trim END
154 vim9script
155 class Something
156 this.count = 42
157 endclass
158 END
159 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count = 42', 3)
160
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200161 # Use "this" without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000162 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200163 vim9script
164 class Something
165 this
166 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000167 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100168 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000169
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200170 # Use "this." without any member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000171 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200172 vim9script
173 class Something
174 this.
175 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000176 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100177 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000178
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200179 # Space between "this" and ".<variable>"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000180 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200181 vim9script
182 class Something
183 this .count
184 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000185 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100186 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this .count', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000187
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200188 # Space between "this." and the member variable name
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000189 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200190 vim9script
191 class Something
192 this. count
193 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000194 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100195 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this. count', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000196
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200197 # Use "that" instead of "this"
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000198 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200199 vim9script
200 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100201 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200202 that.count
203 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000204 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200205 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count', 4)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000206
Doug Kearns74da0ee2023-12-14 20:26:26 +0100207 # Use "variable" instead of "var" for member variable declaration (without initialization)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000208 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200209 vim9script
210 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100211 variable count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200212 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000213 END
Doug Kearns74da0ee2023-12-14 20:26:26 +0100214 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count: number', 3)
215
216 # Use "variable" instead of "var" for member variable declaration (with initialization)
217 lines =<< trim END
218 vim9script
219 class Something
220 variable count: number = 42
221 endclass
222 END
223 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count: number = 42', 3)
224
225 # Use "variable" instead of "var" for member variable declaration (type inferred)
226 lines =<< trim END
227 vim9script
228 class Something
229 variable count = 42
230 endclass
231 END
232 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: variable count = 42', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000233
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200234 # Use a non-existing member variable in new()
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000235 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200236 vim9script
237 class Something
238 def new()
239 this.state = 0
240 enddef
241 endclass
242 var obj = Something.new()
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000243 END
Ernie Raeld4802ec2023-10-20 11:59:00 +0200244 v9.CheckSourceFailure(lines, 'E1326: Variable "state" not found in object "Something"', 1)
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000245
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200246 # Space before ":" in a member variable declaration
Bram Moolenaarf54cedd2022-12-23 17:56:27 +0000247 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200248 vim9script
249 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100250 var count : number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200251 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000252 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200253 v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: count : number', 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000254
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200255 # No space after ":" in a member variable declaration
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000256 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200257 vim9script
258 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100259 var count:number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200260 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000261 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200262 v9.CheckSourceFailure(lines, "E1069: White space required after ':'", 3)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000263
Doug Kearns74da0ee2023-12-14 20:26:26 +0100264 # Missing ":var" in a "var" member variable declaration (without initialization)
265 lines =<< trim END
266 vim9script
267 class Something
268 var: number
269 endclass
270 END
271 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var: number', 3)
272
273 # Missing ":var" in a "var" member variable declaration (with initialization)
274 lines =<< trim END
275 vim9script
276 class Something
277 var: number = 42
278 endclass
279 END
280 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var: number = 42', 3)
281
282 # Missing ":var" in a "var" member variable declaration (type inferred)
283 lines =<< trim END
284 vim9script
285 class Something
286 var = 42
287 endclass
288 END
289 v9.CheckSourceFailure(lines, 'E1317: Invalid object variable declaration: var = 42', 3)
290
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200291 # Test for unsupported comment specifier
292 lines =<< trim END
293 vim9script
294 class Something
295 # comment
296 #{
297 endclass
298 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200299 v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200300
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200301 # Test for using class as a bool
302 lines =<< trim END
303 vim9script
304 class A
305 endclass
306 if A
307 endif
308 END
Ernie Raele75fde62023-12-21 17:18:54 +0100309 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200310
311 # Test for using object as a bool
312 lines =<< trim END
313 vim9script
314 class A
315 endclass
316 var a = A.new()
317 if a
318 endif
319 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200320 v9.CheckSourceFailure(lines, 'E1320: Using an Object as a Number', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200321
322 # Test for using class as a float
323 lines =<< trim END
324 vim9script
325 class A
326 endclass
327 sort([1.1, A], 'f')
328 END
Ernie Raelfa831102023-12-14 20:06:39 +0100329 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200330
331 # Test for using object as a float
332 lines =<< trim END
333 vim9script
334 class A
335 endclass
336 var a = A.new()
337 sort([1.1, a], 'f')
338 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200339 v9.CheckSourceFailure(lines, 'E1322: Using an Object as a Float', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200340
341 # Test for using class as a string
342 lines =<< trim END
343 vim9script
344 class A
345 endclass
346 :exe 'call ' .. A
347 END
Ernie Raele75fde62023-12-21 17:18:54 +0100348 v9.CheckSourceFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200349
350 # Test for using object as a string
351 lines =<< trim END
352 vim9script
353 class A
354 endclass
355 var a = A.new()
356 :exe 'call ' .. a
357 END
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +0200358 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +0200359
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200360 # Test creating a class with member variables and methods, calling a object
361 # method. Check for using type() and typename() with a class and an object.
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000362 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200363 vim9script
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000364
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200365 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100366 var lnum: number
367 var col: number
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000368
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200369 # make a nicely formatted string
370 def ToString(): string
371 return $'({this.lnum}, {this.col})'
372 enddef
373 endclass
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000374
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200375 # use the automatically generated new() method
376 var pos = TextPosition.new(2, 12)
377 assert_equal(2, pos.lnum)
378 assert_equal(12, pos.col)
Bram Moolenaarffdaca92022-12-09 21:41:48 +0000379
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200380 # call an object method
381 assert_equal('(2, 12)', pos.ToString())
Bram Moolenaarc0c2c262023-01-12 21:08:53 +0000382
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200383 assert_equal(v:t_class, type(TextPosition))
384 assert_equal(v:t_object, type(pos))
385 assert_equal('class<TextPosition>', typename(TextPosition))
386 assert_equal('object<TextPosition>', typename(pos))
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000387 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200388 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200389
390 # When referencing object methods, space cannot be used after a "."
391 lines =<< trim END
392 vim9script
393 class A
394 def Foo(): number
395 return 10
396 enddef
397 endclass
398 var a = A.new()
399 var v = a. Foo()
400 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200401 v9.CheckSourceFailure(lines, "E1202: No white space allowed after '.'", 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200402
403 # Using an object without specifying a method or a member variable
404 lines =<< trim END
405 vim9script
406 class A
407 def Foo(): number
408 return 10
409 enddef
410 endclass
411 var a = A.new()
412 var v = a.
413 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200414 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a."', 8)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +0200415
416 # Error when parsing the arguments of an object method.
417 lines =<< trim END
418 vim9script
419 class A
420 def Foo()
421 enddef
422 endclass
423 var a = A.new()
424 var v = a.Foo(,)
425 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200426 v9.CheckSourceFailure(lines, 'E15: Invalid expression: "a.Foo(,)"', 7)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200427
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200428 # Use a multi-line initialization for a member variable
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200429 lines =<< trim END
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200430 vim9script
431 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +0100432 var y = {
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200433 X: 1
434 }
435 endclass
436 var a = A.new()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200437 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200438 v9.CheckSourceSuccess(lines)
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000439enddef
440
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200441" Tests for object/class methods in a class
442def Test_class_def_method()
443 # Using the "public" keyword when defining an object method
444 var lines =<< trim END
445 vim9script
446 class A
447 public def Foo()
448 enddef
449 endclass
450 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200451 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200452
453 # Using the "public" keyword when defining a class method
454 lines =<< trim END
455 vim9script
456 class A
457 public static def Foo()
458 enddef
459 endclass
460 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200461 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200462
Ernie Rael03042a22023-11-11 08:53:32 +0100463 # Using the "public" keyword when defining an object protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200464 lines =<< trim END
465 vim9script
466 class A
467 public def _Foo()
468 enddef
469 endclass
470 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200471 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200472
Ernie Rael03042a22023-11-11 08:53:32 +0100473 # Using the "public" keyword when defining a class protected method
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200474 lines =<< trim END
475 vim9script
476 class A
477 public static def _Foo()
478 enddef
479 endclass
480 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200481 v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200482
483 # Using a "def" keyword without an object method name
484 lines =<< trim END
485 vim9script
486 class A
487 def
488 enddef
489 endclass
490 END
491 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: def', 3)
492
493 # Using a "def" keyword without a class method name
494 lines =<< trim END
495 vim9script
496 class A
497 static def
498 enddef
499 endclass
500 END
501 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: static def', 3)
502enddef
503
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000504def Test_class_defined_twice()
505 # class defined twice should fail
506 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200507 vim9script
508 class There
509 endclass
510 class There
511 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000512 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200513 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"', 4)
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000514
515 # one class, reload same script twice is OK
516 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200517 vim9script
518 class There
519 endclass
Bram Moolenaar83ae6152023-02-25 19:59:31 +0000520 END
521 writefile(lines, 'XclassTwice.vim', 'D')
522 source XclassTwice.vim
523 source XclassTwice.vim
524enddef
525
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000526def Test_returning_null_object()
527 # this was causing an internal error
528 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200529 vim9script
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000530
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200531 class BufferList
532 def Current(): any
533 return null_object
534 enddef
535 endclass
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000536
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200537 var buffers = BufferList.new()
538 echo buffers.Current()
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000539 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200540 v9.CheckSourceSuccess(lines)
Bram Moolenaarc4e1b862023-02-26 18:58:23 +0000541enddef
542
Bram Moolenaard13dd302023-03-11 20:56:35 +0000543def Test_using_null_class()
544 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200545 @_ = null_class.member
Bram Moolenaard13dd302023-03-11 20:56:35 +0000546 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200547 v9.CheckDefExecAndScriptFailure(lines, ['E715: Dictionary required', 'E1363: Incomplete type'])
Yegappan Lakshmananb2e42b92024-05-01 11:44:17 +0200548
549 # Test for using a null class as a value
550 lines =<< trim END
551 vim9script
552 echo empty(null_class)
553 END
554 v9.CheckSourceFailure(lines, 'E1405: Class "" cannot be used as a value', 2)
555
556 # Test for using a null class with string()
557 lines =<< trim END
558 vim9script
559 assert_equal('class [unknown]', string(null_class))
560 END
561 v9.CheckSourceSuccess(lines)
562
Yegappan Lakshmananda9d3452024-05-02 13:02:36 +0200563 # Test for using a null class with type() and typename()
Yegappan Lakshmananb2e42b92024-05-01 11:44:17 +0200564 lines =<< trim END
565 vim9script
566 assert_equal(12, type(null_class))
567 assert_equal('class<Unknown>', typename(null_class))
568 END
569 v9.CheckSourceSuccess(lines)
570enddef
571
Bram Moolenaar657aea72023-01-27 13:16:19 +0000572def Test_class_interface_wrong_end()
573 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200574 vim9script
575 abstract class SomeName
Doug Kearns74da0ee2023-12-14 20:26:26 +0100576 var member = 'text'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200577 endinterface
Bram Moolenaar657aea72023-01-27 13:16:19 +0000578 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200579 v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass', 4)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000580
581 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200582 vim9script
583 export interface AnotherName
Doug Kearns74da0ee2023-12-14 20:26:26 +0100584 var member: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200585 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +0000586 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200587 v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface', 4)
Bram Moolenaar657aea72023-01-27 13:16:19 +0000588enddef
589
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000590def Test_object_not_set()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200591 # Use an uninitialized object in script context
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000592 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200593 vim9script
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000594
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200595 class State
Doug Kearns74da0ee2023-12-14 20:26:26 +0100596 var value = 'xyz'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200597 endclass
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000598
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200599 var state: State
600 var db = {'xyz': 789}
601 echo db[state.value]
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000602 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200603 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 9)
Bram Moolenaar0917e862023-02-18 14:42:44 +0000604
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200605 # Use an uninitialized object from a def function
Bram Moolenaar0917e862023-02-18 14:42:44 +0000606 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200607 vim9script
Bram Moolenaar0917e862023-02-18 14:42:44 +0000608
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200609 class Class
Doug Kearns74da0ee2023-12-14 20:26:26 +0100610 var id: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200611 def Method1()
612 echo 'Method1' .. this.id
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000613 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200614 endclass
615
616 var obj: Class
617 def Func()
618 obj.Method1()
619 enddef
620 Func()
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000621 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200622 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000623
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200624 # Pass an uninitialized object variable to a "new" function and try to call an
625 # object method.
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000626 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200627 vim9script
Bram Moolenaarc3f971f2023-03-02 17:38:33 +0000628
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200629 class Background
Doug Kearns74da0ee2023-12-14 20:26:26 +0100630 var background = 'dark'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200631 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000632
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200633 class Colorscheme
Doug Kearns74da0ee2023-12-14 20:26:26 +0100634 var _bg: Background
Bram Moolenaar0917e862023-02-18 14:42:44 +0000635
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200636 def GetBackground(): string
637 return this._bg.background
638 enddef
639 endclass
Bram Moolenaar0917e862023-02-18 14:42:44 +0000640
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200641 var bg: Background # UNINITIALIZED
642 echo Colorscheme.new(bg).GetBackground()
Bram Moolenaar0917e862023-02-18 14:42:44 +0000643 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200644 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 1)
Ernie Raelf77a7f72023-03-03 15:05:30 +0000645
646 # TODO: this should not give an error but be handled at runtime
647 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200648 vim9script
Ernie Raelf77a7f72023-03-03 15:05:30 +0000649
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200650 class Class
Doug Kearns74da0ee2023-12-14 20:26:26 +0100651 var id: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200652 def Method1()
653 echo 'Method1' .. this.id
Ernie Raelf77a7f72023-03-03 15:05:30 +0000654 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200655 endclass
656
657 var obj = null_object
658 def Func()
659 obj.Method1()
660 enddef
661 Func()
Ernie Raelf77a7f72023-03-03 15:05:30 +0000662 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200663 v9.CheckSourceFailure(lines, 'E1363: Incomplete type', 1)
Ernie Raelbe828252024-07-26 18:37:02 +0200664
665 # Reference a object variable through a null class object which is stored in a
666 # variable of type "any".
667 lines =<< trim END
668 vim9script
669
670 def Z()
671 var o: any = null_object
672 o.v = 4
673 enddef
674 Z()
675 END
676 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
677
678 # Do "echom" of a null object variable.
679 lines =<< trim END
680 vim9script
681
682 def X()
683 var x = null_object
684 echom x
685 enddef
686 X()
687 END
688 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 2)
Ernie Rael94082b62024-07-26 19:40:29 +0200689
690 # Use a null object variable that vim wants to force to number.
691 lines =<< trim END
692 vim9script
693
694 def X()
695 var o = null_object
696 var l = [ 1, o]
697 sort(l, 'N')
698 enddef
699 X()
700 END
701 v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 3)
Bram Moolenaar552bdca2023-02-17 21:08:50 +0000702enddef
703
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200704" Null object assignment and comparison
Ernie Rael5c018be2023-08-27 18:40:26 +0200705def Test_null_object_assign_compare()
706 var lines =<< trim END
707 vim9script
708
709 var nullo = null_object
710 def F(): any
711 return nullo
712 enddef
713 assert_equal('object<Unknown>', typename(F()))
714
715 var o0 = F()
716 assert_true(o0 == null_object)
717 assert_true(o0 == null)
718
719 var o1: any = nullo
720 assert_true(o1 == null_object)
721 assert_true(o1 == null)
722
723 def G()
724 var x = null_object
725 enddef
726
727 class C
728 endclass
729 var o2: C
730 assert_true(o2 == null_object)
731 assert_true(o2 == null)
732
733 o2 = null_object
734 assert_true(o2 == null)
735
736 o2 = C.new()
737 assert_true(o2 != null)
738
739 o2 = null_object
740 assert_true(o2 == null)
741 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200742 v9.CheckSourceSuccess(lines)
Ernie Rael5c018be2023-08-27 18:40:26 +0200743enddef
744
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200745" Test for object member initialization and disassembly
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000746def Test_class_member_initializer()
747 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200748 vim9script
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000749
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200750 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100751 var lnum: number = 1
752 var col: number = 1
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000753
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200754 # constructor with only the line number
755 def new(lnum: number)
756 this.lnum = lnum
757 enddef
758 endclass
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000759
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200760 var pos = TextPosition.new(3)
761 assert_equal(3, pos.lnum)
762 assert_equal(1, pos.col)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000763
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200764 var instr = execute('disassemble TextPosition.new')
765 assert_match('new\_s*' ..
766 '0 NEW TextPosition size \d\+\_s*' ..
767 '\d PUSHNR 1\_s*' ..
768 '\d STORE_THIS 0\_s*' ..
769 '\d PUSHNR 1\_s*' ..
770 '\d STORE_THIS 1\_s*' ..
771 'this.lnum = lnum\_s*' ..
772 '\d LOAD arg\[-1]\_s*' ..
773 '\d PUSHNR 0\_s*' ..
774 '\d LOAD $0\_s*' ..
775 '\d\+ STOREINDEX object\_s*' ..
776 '\d\+ RETURN object.*',
777 instr)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000778 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200779 v9.CheckSourceSuccess(lines)
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +0000780enddef
781
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000782def Test_member_any_used_as_object()
783 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200784 vim9script
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000785
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200786 class Inner
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +0100787 public var value: number = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200788 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000789
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200790 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100791 var inner: any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200792 endclass
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000793
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200794 def F(outer: Outer)
795 outer.inner.value = 1
796 enddef
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000797
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200798 var inner_obj = Inner.new(0)
799 var outer_obj = Outer.new(inner_obj)
800 F(outer_obj)
801 assert_equal(1, inner_obj.value)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000802 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200803 v9.CheckSourceSuccess(lines)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000804
Ernie Rael03042a22023-11-11 08:53:32 +0100805 # Try modifying a protected variable using an "any" object
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200806 lines =<< trim END
807 vim9script
808
809 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100810 var _value: string = ''
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200811 endclass
812
813 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100814 var inner: any
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200815 endclass
816
817 def F(outer: Outer)
818 outer.inner._value = 'b'
819 enddef
820
821 var inner_obj = Inner.new('a')
822 var outer_obj = Outer.new(inner_obj)
823 F(outer_obj)
824 END
Ernie Rael03042a22023-11-11 08:53:32 +0100825 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_value" in class "Inner"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200826
827 # Try modifying a non-existing variable using an "any" object
828 lines =<< trim END
829 vim9script
830
831 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100832 var value: string = ''
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200833 endclass
834
835 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100836 var inner: any
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200837 endclass
838
839 def F(outer: Outer)
840 outer.inner.someval = 'b'
841 enddef
842
843 var inner_obj = Inner.new('a')
844 var outer_obj = Outer.new(inner_obj)
845 F(outer_obj)
846 END
Ernie Raeld4802ec2023-10-20 11:59:00 +0200847 v9.CheckSourceFailure(lines, 'E1326: Variable "someval" not found in object "Inner"', 1)
Bram Moolenaar2c1c8032023-02-18 18:38:37 +0000848enddef
849
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200850" Nested assignment to a object variable which is of another class type
851def Test_assignment_nested_type()
852 var lines =<< trim END
853 vim9script
854
855 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100856 public var value: number = 0
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200857 endclass
858
859 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100860 var inner: Inner
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200861 endclass
862
863 def F(outer: Outer)
864 outer.inner.value = 1
865 enddef
866
867 def Test_assign_to_nested_typed_member()
868 var inner = Inner.new(0)
869 var outer = Outer.new(inner)
870 F(outer)
871 assert_equal(1, inner.value)
872 enddef
873
874 Test_assign_to_nested_typed_member()
Ernie Rael98e68c02023-09-20 20:13:06 +0200875
876 var script_inner = Inner.new(0)
877 var script_outer = Outer.new(script_inner)
878 script_outer.inner.value = 1
879 assert_equal(1, script_inner.value)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200880 END
881 v9.CheckSourceSuccess(lines)
Ernie Rael98e68c02023-09-20 20:13:06 +0200882
883 # Assignment where target item is read only in :def
884 lines =<< trim END
885 vim9script
886
887 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100888 var value: number = 0
Ernie Rael98e68c02023-09-20 20:13:06 +0200889 endclass
890
891 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100892 var inner: Inner
Ernie Rael98e68c02023-09-20 20:13:06 +0200893 endclass
894
895 def F(outer: Outer)
896 outer.inner.value = 1
897 enddef
898
899 def Test_assign_to_nested_typed_member()
900 var inner = Inner.new(0)
901 var outer = Outer.new(inner)
902 F(outer)
903 assert_equal(1, inner.value)
904 enddef
905
906 Test_assign_to_nested_typed_member()
907 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200908 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 1)
Ernie Rael98e68c02023-09-20 20:13:06 +0200909
910 # Assignment where target item is read only script level
911 lines =<< trim END
912 vim9script
913
914 class Inner
Doug Kearns74da0ee2023-12-14 20:26:26 +0100915 var value: number = 0
Ernie Rael98e68c02023-09-20 20:13:06 +0200916 endclass
917
918 class Outer
Doug Kearns74da0ee2023-12-14 20:26:26 +0100919 var inner: Inner
Ernie Rael98e68c02023-09-20 20:13:06 +0200920 endclass
921
922 def F(outer: Outer)
923 outer.inner.value = 1
924 enddef
925
926 var script_inner = Inner.new(0)
927 var script_outer = Outer.new(script_inner)
928 script_outer.inner.value = 1
929 assert_equal(1, script_inner.value)
930 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200931 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "Inner" is not writable', 17)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200932enddef
933
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000934def Test_assignment_with_operator()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200935 # Use "+=" to assign to a object variable
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000936 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200937 vim9script
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000938
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200939 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +0100940 public var x: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000941
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200942 def Add(n: number)
943 this.x += n
Bram Moolenaar22363c62023-04-24 17:15:25 +0100944 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200945 endclass
Bram Moolenaar22363c62023-04-24 17:15:25 +0100946
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200947 var f = Foo.new(3)
948 f.Add(17)
949 assert_equal(20, f.x)
950
951 def AddToFoo(obj: Foo)
952 obj.x += 3
953 enddef
954
955 AddToFoo(f)
956 assert_equal(23, f.x)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000957 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200958 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +0000959enddef
960
Bram Moolenaarf4508042023-01-15 16:54:57 +0000961def Test_list_of_objects()
962 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200963 vim9script
Bram Moolenaarf4508042023-01-15 16:54:57 +0000964
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200965 class Foo
966 def Add()
Bram Moolenaarf4508042023-01-15 16:54:57 +0000967 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200968 endclass
Bram Moolenaarf4508042023-01-15 16:54:57 +0000969
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200970 def ProcessList(fooList: list<Foo>)
971 for foo in fooList
972 foo.Add()
973 endfor
974 enddef
975
976 var l: list<Foo> = [Foo.new()]
977 ProcessList(l)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000978 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200979 v9.CheckSourceSuccess(lines)
Bram Moolenaarf4508042023-01-15 16:54:57 +0000980enddef
981
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000982def Test_expr_after_using_object()
983 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200984 vim9script
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000985
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200986 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +0100987 var label: string = ''
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200988 endclass
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000989
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200990 def Foo(): Something
991 var v = Something.new()
992 echo 'in Foo(): ' .. typename(v)
993 return v
994 enddef
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000995
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200996 Foo()
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000997 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +0200998 v9.CheckSourceSuccess(lines)
Bram Moolenaar912bfee2023-01-15 20:18:55 +0000999enddef
1000
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001001def Test_class_default_new()
1002 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001003 vim9script
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001004
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001005 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001006 var lnum: number = 1
1007 var col: number = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001008 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001009
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001010 var pos = TextPosition.new()
1011 assert_equal(1, pos.lnum)
1012 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001013
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001014 pos = TextPosition.new(v:none, v:none)
1015 assert_equal(1, pos.lnum)
1016 assert_equal(1, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001017
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001018 pos = TextPosition.new(3, 22)
1019 assert_equal(3, pos.lnum)
1020 assert_equal(22, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001021
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001022 pos = TextPosition.new(v:none, 33)
1023 assert_equal(1, pos.lnum)
1024 assert_equal(33, pos.col)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001025 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001026 v9.CheckSourceSuccess(lines)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001027
1028 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001029 vim9script
1030 class Person
Doug Kearns74da0ee2023-12-14 20:26:26 +01001031 var name: string
1032 var age: number = 42
1033 var education: string = "unknown"
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001034
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001035 def new(this.name, this.age = v:none, this.education = v:none)
1036 enddef
1037 endclass
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001038
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001039 var piet = Person.new("Piet")
1040 assert_equal("Piet", piet.name)
1041 assert_equal(42, piet.age)
1042 assert_equal("unknown", piet.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001043
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001044 var chris = Person.new("Chris", 4, "none")
1045 assert_equal("Chris", chris.name)
1046 assert_equal(4, chris.age)
1047 assert_equal("none", chris.education)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001048 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001049 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001050
1051 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001052 vim9script
1053 class Person
Doug Kearns74da0ee2023-12-14 20:26:26 +01001054 var name: string
1055 var age: number = 42
1056 var education: string = "unknown"
Bram Moolenaar74e12742022-12-13 21:14:28 +00001057
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001058 def new(this.name, this.age = v:none, this.education = v:none)
1059 enddef
1060 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001061
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001062 var missing = Person.new()
Bram Moolenaar74e12742022-12-13 21:14:28 +00001063 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001064 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001065
1066 # Using a specific value to initialize an instance variable in the new()
1067 # method.
1068 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001069 vim9script
1070 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001071 var val: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001072 def new(this.val = 'a')
1073 enddef
1074 endclass
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001075 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001076 v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'", 4)
Bram Moolenaar65b0d162022-12-13 18:43:22 +00001077enddef
1078
h-east2261c892023-08-16 21:49:54 +09001079def Test_class_new_with_object_member()
1080 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001081 vim9script
h-east2261c892023-08-16 21:49:54 +09001082
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001083 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001084 var str: string
1085 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001086 def new(this.str, this.num)
h-east2261c892023-08-16 21:49:54 +09001087 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001088 def newVals(this.str, this.num)
1089 enddef
1090 endclass
h-east2261c892023-08-16 21:49:54 +09001091
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001092 def Check()
1093 try
1094 var c = C.new('cats', 2)
1095 assert_equal('cats', c.str)
1096 assert_equal(2, c.num)
1097
1098 c = C.newVals('dogs', 4)
1099 assert_equal('dogs', c.str)
1100 assert_equal(4, c.num)
1101 catch
1102 assert_report($'Unexpected exception was caught: {v:exception}')
1103 endtry
1104 enddef
1105
1106 Check()
h-east2261c892023-08-16 21:49:54 +09001107 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001108 v9.CheckSourceSuccess(lines)
h-east2261c892023-08-16 21:49:54 +09001109
1110 lines =<< trim END
h-eastdb385522023-09-28 22:18:19 +02001111 vim9script
1112
1113 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001114 var str: string
1115 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001116 def new(this.str, this.num)
h-eastdb385522023-09-28 22:18:19 +02001117 enddef
1118 endclass
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001119
1120 def Check()
1121 try
1122 var c = C.new(1, 2)
1123 catch
1124 assert_report($'Unexpected exception was caught: {v:exception}')
1125 endtry
1126 enddef
1127
1128 Check()
h-eastdb385522023-09-28 22:18:19 +02001129 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001130 v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 2)
h-eastdb385522023-09-28 22:18:19 +02001131
1132 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001133 vim9script
h-eastb895b0f2023-09-24 15:46:31 +02001134
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001135 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001136 var str: string
1137 var num: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001138 def newVals(this.str, this.num)
h-eastb895b0f2023-09-24 15:46:31 +02001139 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001140 endclass
h-eastb895b0f2023-09-24 15:46:31 +02001141
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001142 def Check()
1143 try
1144 var c = C.newVals('dogs', 'apes')
1145 catch
1146 assert_report($'Unexpected exception was caught: {v:exception}')
1147 endtry
1148 enddef
1149
1150 Check()
1151 END
1152 v9.CheckSourceFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string', 2)
1153
1154 lines =<< trim END
1155 vim9script
1156
1157 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01001158 var str: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001159 def new(str: any)
1160 enddef
1161 endclass
1162
1163 def Check()
1164 try
1165 var c = C.new(1)
1166 catch
1167 assert_report($'Unexpected exception was caught: {v:exception}')
1168 endtry
1169 enddef
1170
1171 Check()
h-eastb895b0f2023-09-24 15:46:31 +02001172 END
1173 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001174
1175 # Try using "this." argument in a class method
1176 lines =<< trim END
1177 vim9script
1178 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001179 var val = 10
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001180 static def Foo(this.val: number)
1181 enddef
1182 endclass
1183 END
1184 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
1185
1186 # Try using "this." argument in an object method
1187 lines =<< trim END
1188 vim9script
1189 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001190 var val = 10
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02001191 def Foo(this.val: number)
1192 enddef
1193 endclass
1194 END
1195 v9.CheckSourceFailure(lines, 'E1390: Cannot use an object variable "this.val" except with the "new" method', 4)
h-east2261c892023-08-16 21:49:54 +09001196enddef
1197
Bram Moolenaar74e12742022-12-13 21:14:28 +00001198def Test_class_object_member_inits()
1199 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001200 vim9script
1201 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001202 var lnum: number
1203 var col = 1
1204 var addcol: number = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001205 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001206
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001207 var pos = TextPosition.new()
1208 assert_equal(0, pos.lnum)
1209 assert_equal(1, pos.col)
1210 assert_equal(2, pos.addcol)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001211 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001212 v9.CheckSourceSuccess(lines)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001213
1214 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001215 vim9script
1216 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01001217 var lnum
1218 var col = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001219 endclass
Bram Moolenaar74e12742022-12-13 21:14:28 +00001220 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001221 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001222
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001223 # If the type is not specified for a member, then it should be set during
1224 # object creation and not when defining the class.
Bram Moolenaar74e12742022-12-13 21:14:28 +00001225 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001226 vim9script
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001227
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001228 var init_count = 0
1229 def Init(): string
1230 init_count += 1
1231 return 'foo'
1232 enddef
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001233
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001234 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001235 var str1 = Init()
1236 var str2: string = Init()
1237 var col = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001238 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001239
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001240 assert_equal(init_count, 0)
1241 var a = A.new()
1242 assert_equal(init_count, 2)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001243 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001244 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001245
1246 # Test for initializing an object member with an unknown variable/type
1247 lines =<< trim END
1248 vim9script
1249 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001250 var value = init_val
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001251 endclass
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02001252 var a = A.new()
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001253 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001254 v9.CheckSourceFailure(lines, 'E1001: Variable not found: init_val', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001255
1256 # Test for initializing an object member with an special type
1257 lines =<< trim END
1258 vim9script
1259 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001260 var value: void
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02001261 endclass
1262 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001263 v9.CheckSourceFailure(lines, 'E1330: Invalid type for object variable: void', 3)
Bram Moolenaar74e12742022-12-13 21:14:28 +00001264enddef
1265
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001266" Test for instance variable access
1267def Test_instance_variable_access()
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001268 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001269 vim9script
1270 class Triple
Doug Kearns74da0ee2023-12-14 20:26:26 +01001271 var _one = 1
1272 var two = 2
1273 public var three = 3
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001274
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001275 def GetOne(): number
1276 return this._one
1277 enddef
1278 endclass
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001279
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001280 var trip = Triple.new()
1281 assert_equal(1, trip.GetOne())
1282 assert_equal(2, trip.two)
1283 assert_equal(3, trip.three)
Ernie Rael03042a22023-11-11 08:53:32 +01001284 assert_fails('echo trip._one', 'E1333: Cannot access protected variable "_one" in class "Triple"')
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001285
Ernie Rael03042a22023-11-11 08:53:32 +01001286 assert_fails('trip._one = 11', 'E1333: Cannot access protected variable "_one" in class "Triple"')
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001287 assert_fails('trip.two = 22', 'E1335: Variable "two" in class "Triple" is not writable')
1288 trip.three = 33
1289 assert_equal(33, trip.three)
Bram Moolenaard505d172022-12-18 21:42:55 +00001290
Ernie Raeld4802ec2023-10-20 11:59:00 +02001291 assert_fails('trip.four = 4', 'E1326: Variable "four" not found in object "Triple"')
Bram Moolenaard505d172022-12-18 21:42:55 +00001292 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001293 v9.CheckSourceSuccess(lines)
Bram Moolenaar590162c2022-12-24 21:24:06 +00001294
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001295 # Test for a public member variable name beginning with an underscore
1296 lines =<< trim END
1297 vim9script
1298 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001299 public var _val = 10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001300 endclass
1301 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02001302 v9.CheckSourceFailure(lines, 'E1332: public variable name cannot start with underscore: public var _val = 10', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001303
Bram Moolenaar590162c2022-12-24 21:24:06 +00001304 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001305 vim9script
Bram Moolenaar590162c2022-12-24 21:24:06 +00001306
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001307 class MyCar
Doug Kearns74da0ee2023-12-14 20:26:26 +01001308 var make: string
1309 var age = 5
Bram Moolenaar590162c2022-12-24 21:24:06 +00001310
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001311 def new(make_arg: string)
1312 this.make = make_arg
Bram Moolenaar574950d2023-01-03 19:08:50 +00001313 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001314
1315 def GetMake(): string
1316 return $"make = {this.make}"
1317 enddef
1318 def GetAge(): number
1319 return this.age
1320 enddef
1321 endclass
1322
1323 var c = MyCar.new("abc")
1324 assert_equal('make = abc', c.GetMake())
1325
1326 c = MyCar.new("def")
1327 assert_equal('make = def', c.GetMake())
1328
1329 var c2 = MyCar.new("123")
1330 assert_equal('make = 123', c2.GetMake())
1331
1332 def CheckCar()
1333 assert_equal("make = def", c.GetMake())
1334 assert_equal(5, c.GetAge())
1335 enddef
1336 CheckCar()
Bram Moolenaar590162c2022-12-24 21:24:06 +00001337 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001338 v9.CheckSourceSuccess(lines)
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001339
1340 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001341 vim9script
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001342
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001343 class MyCar
Doug Kearns74da0ee2023-12-14 20:26:26 +01001344 var make: string
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001345
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001346 def new(make_arg: string)
1347 this.make = make_arg
1348 enddef
1349 endclass
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001350
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001351 var c = MyCar.new("abc")
1352 var c = MyCar.new("def")
Bram Moolenaar6ef54712022-12-25 19:31:36 +00001353 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001354 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "c"', 12)
Bram Moolenaarb149d222023-01-24 13:03:37 +00001355
1356 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001357 vim9script
Bram Moolenaarb149d222023-01-24 13:03:37 +00001358
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001359 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001360 var x: list<number> = []
Bram Moolenaarb149d222023-01-24 13:03:37 +00001361
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001362 def Add(n: number): any
1363 this.x->add(n)
1364 return this
1365 enddef
1366 endclass
Bram Moolenaarb149d222023-01-24 13:03:37 +00001367
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001368 echo Foo.new().Add(1).Add(2).x
1369 echo Foo.new().Add(1).Add(2)
1370 .x
1371 echo Foo.new().Add(1)
1372 .Add(2).x
1373 echo Foo.new()
1374 .Add(1).Add(2).x
1375 echo Foo.new()
1376 .Add(1)
1377 .Add(2)
1378 .x
Bram Moolenaarb149d222023-01-24 13:03:37 +00001379 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001380 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001381
1382 # Test for "public" cannot be abbreviated
1383 lines =<< trim END
1384 vim9script
1385 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001386 pub var val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001387 endclass
1388 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001389 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: pub var val = 1', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001390
Doug Kearns74da0ee2023-12-14 20:26:26 +01001391 # Test for "public" keyword must be followed by "var" or "static".
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001392 lines =<< trim END
1393 vim9script
1394 class Something
1395 public val = 1
1396 endclass
1397 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02001398 v9.CheckSourceFailure(lines, 'E1331: public must be followed by "var" or "static"', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001399
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001400 # Modify a instance variable using the class name in the script context
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001401 lines =<< trim END
1402 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001403 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001404 public var val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001405 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001406 A.val = 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001407 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001408 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001409
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001410 # Read a instance variable using the class name in the script context
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001411 lines =<< trim END
1412 vim9script
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001413 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001414 public var val = 1
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001415 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001416 var i = A.val
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02001417 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001418 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 5)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001419
1420 # Modify a instance variable using the class name in a def function
1421 lines =<< trim END
1422 vim9script
1423 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001424 public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001425 endclass
1426 def T()
1427 A.val = 1
1428 enddef
1429 T()
1430 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001431 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001432
1433 # Read a instance variable using the class name in a def function
1434 lines =<< trim END
1435 vim9script
1436 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001437 public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001438 endclass
1439 def T()
1440 var i = A.val
1441 enddef
1442 T()
1443 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001444 v9.CheckSourceFailure(lines, 'E1376: Object variable "val" accessible only using class "A" object', 1)
Ernie Raelcf138d42023-09-06 20:45:03 +02001445
1446 # Access from child class extending a class:
1447 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001448 vim9script
1449 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001450 var ro_obj_var = 10
1451 public var rw_obj_var = 20
1452 var _priv_obj_var = 30
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001453 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001454
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001455 class B extends A
1456 def Foo()
1457 var x: number
1458 x = this.ro_obj_var
1459 this.ro_obj_var = 0
1460 x = this.rw_obj_var
1461 this.rw_obj_var = 0
1462 x = this._priv_obj_var
1463 this._priv_obj_var = 0
1464 enddef
1465 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001466
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001467 var b = B.new()
1468 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001469 END
1470 v9.CheckSourceSuccess(lines)
1471enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02001472
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001473" Test for class variable access
1474def Test_class_variable_access()
1475 # Test for "static" cannot be abbreviated
1476 var lines =<< trim END
1477 vim9script
1478 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001479 stat var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001480 endclass
1481 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001482 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: stat var val = 1', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001483
1484 # Test for "static" cannot be followed by "public".
1485 lines =<< trim END
1486 vim9script
1487 class Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01001488 static public var val = 1
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001489 endclass
1490 END
Doug Kearns74da0ee2023-12-14 20:26:26 +01001491 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 3)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001492
1493 # A readonly class variable cannot be modified from a child class
1494 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001495 vim9script
1496 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001497 static var ro_class_var = 40
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001498 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001499
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001500 class B extends A
1501 def Foo()
1502 A.ro_class_var = 50
1503 enddef
1504 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001505
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001506 var b = B.new()
1507 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001508 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001509 v9.CheckSourceFailure(lines, 'E1335: Variable "ro_class_var" in class "A" is not writable', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001510
Ernie Rael03042a22023-11-11 08:53:32 +01001511 # A protected class variable cannot be accessed from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001512 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001513 vim9script
1514 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001515 static var _priv_class_var = 60
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001516 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001517
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001518 class B extends A
1519 def Foo()
1520 var i = A._priv_class_var
1521 enddef
1522 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001523
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001524 var b = B.new()
1525 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001526 END
Ernie Rael03042a22023-11-11 08:53:32 +01001527 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001528
Ernie Rael03042a22023-11-11 08:53:32 +01001529 # A protected class variable cannot be modified from a child class
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001530 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001531 vim9script
1532 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001533 static var _priv_class_var = 60
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001534 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001535
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001536 class B extends A
1537 def Foo()
1538 A._priv_class_var = 0
1539 enddef
1540 endclass
Ernie Raelcf138d42023-09-06 20:45:03 +02001541
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001542 var b = B.new()
1543 b.Foo()
Ernie Raelcf138d42023-09-06 20:45:03 +02001544 END
Ernie Rael03042a22023-11-11 08:53:32 +01001545 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_priv_class_var" in class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001546
1547 # Access from child class extending a class and from script context
1548 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001549 vim9script
1550 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001551 static var ro_class_var = 10
1552 public static var rw_class_var = 20
1553 static var _priv_class_var = 30
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001554 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001555
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001556 class B extends A
1557 def Foo()
1558 var x: number
1559 x = A.ro_class_var
1560 assert_equal(10, x)
1561 x = A.rw_class_var
1562 assert_equal(25, x)
1563 A.rw_class_var = 20
1564 assert_equal(20, A.rw_class_var)
1565 enddef
1566 endclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001567
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001568 assert_equal(10, A.ro_class_var)
1569 assert_equal(20, A.rw_class_var)
1570 A.rw_class_var = 25
1571 assert_equal(25, A.rw_class_var)
1572 var b = B.new()
1573 b.Foo()
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001574 END
1575 v9.CheckSourceSuccess(lines)
Bram Moolenaard505d172022-12-18 21:42:55 +00001576enddef
1577
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001578def Test_class_object_compare()
1579 var class_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001580 vim9script
1581 class Item
Doug Kearns74da0ee2023-12-14 20:26:26 +01001582 var nr = 0
1583 var name = 'xx'
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001584 endclass
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001585 END
1586
1587 # used at the script level and in a compiled function
1588 var test_lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001589 var i1 = Item.new()
1590 assert_equal(i1, i1)
1591 assert_true(i1 is i1)
1592 var i2 = Item.new()
1593 assert_equal(i1, i2)
1594 assert_false(i1 is i2)
1595 var i3 = Item.new(0, 'xx')
1596 assert_equal(i1, i3)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001597
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001598 var io1 = Item.new(1, 'xx')
1599 assert_notequal(i1, io1)
1600 var io2 = Item.new(0, 'yy')
1601 assert_notequal(i1, io2)
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001602 END
1603
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001604 v9.CheckSourceSuccess(class_lines + test_lines)
1605 v9.CheckSourceSuccess(
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001606 class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001607
1608 for op in ['>', '>=', '<', '<=', '=~', '!~']
1609 var op_lines = [
1610 'var i1 = Item.new()',
1611 'var i2 = Item.new()',
1612 'echo i1 ' .. op .. ' i2',
1613 ]
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001614 v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object', 8)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001615 v9.CheckSourceFailure(class_lines
Bram Moolenaar46ab9252023-01-03 14:01:21 +00001616 + ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
Bram Moolenaarbcf31ec2023-01-02 20:32:24 +00001617 endfor
1618enddef
1619
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001620def Test_object_type()
1621 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001622 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001623
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001624 class One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001625 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001626 endclass
1627 class Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001628 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001629 endclass
1630 class TwoMore extends Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001631 var more = 9
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001632 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001633
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001634 var o: One = One.new()
1635 var t: Two = Two.new()
1636 var m: TwoMore = TwoMore.new()
1637 var tm: Two = TwoMore.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001638
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001639 t = m
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001640 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001641 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001642
1643 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001644 vim9script
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001645
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001646 class One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001647 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001648 endclass
1649 class Two
Doug Kearns74da0ee2023-12-14 20:26:26 +01001650 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001651 endclass
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001652
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001653 var o: One = Two.new()
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001654 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001655 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>', 10)
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001656
1657 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001658 vim9script
Bram Moolenaara94bd9d2023-01-12 15:01:32 +00001659
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001660 interface One
1661 def GetMember(): number
1662 endinterface
1663 class Two implements One
Doug Kearns74da0ee2023-12-14 20:26:26 +01001664 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001665 def GetMember(): number
1666 return this.one
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001667 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001668 endclass
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001669
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001670 var o: One = Two.new(5)
1671 assert_equal(5, o.GetMember())
1672 END
1673 v9.CheckSourceSuccess(lines)
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001674
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001675 lines =<< trim END
1676 vim9script
1677
1678 class Num
Doug Kearns74da0ee2023-12-14 20:26:26 +01001679 var n: number = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001680 endclass
1681
1682 def Ref(name: string): func(Num): Num
1683 return (arg: Num): Num => {
1684 return eval(name)(arg)
1685 }
1686 enddef
1687
1688 const Fn = Ref('Double')
1689 var Double = (m: Num): Num => Num.new(m.n * 2)
1690
1691 echo Fn(Num.new(4))
Bram Moolenaar450c7a92023-01-16 16:39:37 +00001692 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001693 v9.CheckSourceSuccess(lines)
Bram Moolenaar6481acc2023-01-11 21:14:17 +00001694enddef
1695
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001696def Test_class_member()
1697 # check access rules
Bram Moolenaard505d172022-12-18 21:42:55 +00001698 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001699 vim9script
1700 class TextPos
Doug Kearns74da0ee2023-12-14 20:26:26 +01001701 var lnum = 1
1702 var col = 1
1703 static var counter = 0
1704 static var _secret = 7
1705 public static var anybody = 42
Bram Moolenaard505d172022-12-18 21:42:55 +00001706
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001707 static def AddToCounter(nr: number)
1708 counter += nr
1709 enddef
1710 endclass
Bram Moolenaard505d172022-12-18 21:42:55 +00001711
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001712 assert_equal(0, TextPos.counter)
1713 TextPos.AddToCounter(3)
1714 assert_equal(3, TextPos.counter)
1715 assert_fails('echo TextPos.noSuchMember', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
Bram Moolenaar94722c52023-01-28 19:19:03 +00001716
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001717 def GetCounter(): number
1718 return TextPos.counter
1719 enddef
1720 assert_equal(3, GetCounter())
Bram Moolenaard505d172022-12-18 21:42:55 +00001721
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001722 assert_fails('TextPos.noSuchMember = 2', 'E1337: Class variable "noSuchMember" not found in class "TextPos"')
1723 assert_fails('TextPos.counter = 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
1724 assert_fails('TextPos.counter += 5', 'E1335: Variable "counter" in class "TextPos" is not writable')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001725
Ernie Rael03042a22023-11-11 08:53:32 +01001726 assert_fails('echo TextPos._secret', 'E1333: Cannot access protected variable "_secret" in class "TextPos"')
1727 assert_fails('TextPos._secret = 8', 'E1333: Cannot access protected variable "_secret" in class "TextPos"')
Bram Moolenaar9f2d97e2022-12-31 19:01:02 +00001728
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001729 assert_equal(42, TextPos.anybody)
1730 TextPos.anybody = 12
1731 assert_equal(12, TextPos.anybody)
1732 TextPos.anybody += 5
1733 assert_equal(17, TextPos.anybody)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001734 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001735 v9.CheckSourceSuccess(lines)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001736
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001737 # example in the help
1738 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001739 vim9script
1740 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +01001741 var size: number
1742 static var totalSize: number
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001743
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001744 def new(this.size)
1745 totalSize += this.size
1746 enddef
1747 endclass
1748 assert_equal(0, OtherThing.totalSize)
1749 var to3 = OtherThing.new(3)
1750 assert_equal(3, OtherThing.totalSize)
1751 var to7 = OtherThing.new(7)
1752 assert_equal(10, OtherThing.totalSize)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001753 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001754 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00001755
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001756 # using static class member twice
1757 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001758 vim9script
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001759
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001760 class HTML
Doug Kearns74da0ee2023-12-14 20:26:26 +01001761 static var author: string = 'John Doe'
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001762
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001763 static def MacroSubstitute(s: string): string
1764 return substitute(s, '{{author}}', author, 'gi')
1765 enddef
1766 endclass
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001767
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001768 assert_equal('some text', HTML.MacroSubstitute('some text'))
1769 assert_equal('some text', HTML.MacroSubstitute('some text'))
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001770 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001771 v9.CheckSourceSuccess(lines)
Bram Moolenaar4e2406c2023-06-24 19:22:21 +01001772
Ernie Rael03042a22023-11-11 08:53:32 +01001773 # access protected member in lambda
Bram Moolenaar62a69232023-01-24 15:07:04 +00001774 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001775 vim9script
Bram Moolenaar62a69232023-01-24 15:07:04 +00001776
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001777 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001778 var _x: number = 0
Bram Moolenaar62a69232023-01-24 15:07:04 +00001779
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001780 def Add(n: number): number
1781 const F = (): number => this._x + n
1782 return F()
1783 enddef
1784 endclass
Bram Moolenaar62a69232023-01-24 15:07:04 +00001785
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001786 var foo = Foo.new()
1787 assert_equal(5, foo.Add(5))
Bram Moolenaar62a69232023-01-24 15:07:04 +00001788 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001789 v9.CheckSourceSuccess(lines)
Bram Moolenaar62a69232023-01-24 15:07:04 +00001790
Ernie Rael03042a22023-11-11 08:53:32 +01001791 # access protected member in lambda body
h-east2bd6a092023-05-19 19:01:17 +01001792 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001793 vim9script
h-east2bd6a092023-05-19 19:01:17 +01001794
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001795 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01001796 var _x: number = 6
h-east2bd6a092023-05-19 19:01:17 +01001797
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001798 def Add(n: number): number
1799 var Lam = () => {
1800 this._x = this._x + n
1801 }
1802 Lam()
1803 return this._x
1804 enddef
1805 endclass
h-east2bd6a092023-05-19 19:01:17 +01001806
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001807 var foo = Foo.new()
1808 assert_equal(13, foo.Add(7))
h-east2bd6a092023-05-19 19:01:17 +01001809 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02001810 v9.CheckSourceSuccess(lines)
h-east2bd6a092023-05-19 19:01:17 +01001811
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001812 # check shadowing
1813 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001814 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001815
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001816 class Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01001817 static var count = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001818 def Method(count: number)
1819 echo count
1820 enddef
1821 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001822
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001823 var s = Some.new()
1824 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001825 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001826 v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count', 5)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001827
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02001828 # Use a local variable in a method with the same name as a class variable
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001829 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001830 vim9script
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001831
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001832 class Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01001833 static var count = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001834 def Method(arg: number)
1835 var count = 3
1836 echo arg count
1837 enddef
1838 endclass
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001839
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001840 var s = Some.new()
1841 s.Method(7)
Bram Moolenaar6acf7572023-01-01 19:53:30 +00001842 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001843 v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001844
1845 # Test for using an invalid type for a member variable
1846 lines =<< trim END
1847 vim9script
1848 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001849 var val: xxx
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001850 endclass
1851 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001852 v9.CheckSourceFailure(lines, 'E1010: Type not recognized: xxx', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001853
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001854 # Test for setting a member on a null object
1855 lines =<< trim END
1856 vim9script
1857 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001858 public var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001859 endclass
1860
1861 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001862 var obj: A
1863 obj.val = ""
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001864 enddef
1865 F()
1866 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001867 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001868
1869 # Test for accessing a member on a null object
1870 lines =<< trim END
1871 vim9script
1872 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001873 var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001874 endclass
1875
1876 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001877 var obj: A
1878 echo obj.val
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001879 enddef
1880 F()
1881 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001882 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001883
1884 # Test for setting a member on a null object, at script level
1885 lines =<< trim END
1886 vim9script
1887 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001888 public var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001889 endclass
1890
1891 var obj: A
1892 obj.val = ""
1893 END
Ernie Rael4c8da022023-10-11 21:35:11 +02001894 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001895
1896 # Test for accessing a member on a null object, at script level
1897 lines =<< trim END
1898 vim9script
1899 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001900 var val: string
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001901 endclass
1902
1903 var obj: A
1904 echo obj.val
1905 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001906 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 7)
Gianmaria Bajod7085a02023-08-31 18:15:26 +02001907
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001908 # Test for no space before or after the '=' when initializing a member
1909 # variable
1910 lines =<< trim END
1911 vim9script
1912 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001913 var val: number= 10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001914 endclass
1915 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001916 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001917 lines =<< trim END
1918 vim9script
1919 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01001920 var val: number =10
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001921 endclass
1922 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02001923 v9.CheckSourceFailure(lines, "E1004: White space required before and after '='", 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02001924
1925 # Access a non-existing member
1926 lines =<< trim END
1927 vim9script
1928 class A
1929 endclass
1930 var a = A.new()
1931 var v = a.bar
1932 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02001933 v9.CheckSourceFailure(lines, 'E1326: Variable "bar" not found in object "A"', 5)
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00001934enddef
1935
Ernie Raele6c9aa52023-10-06 19:55:52 +02001936" These messages should show the defining class of the variable (base class),
1937" not the class that did the reference (super class)
1938def Test_defining_class_message()
1939 var lines =<< trim END
1940 vim9script
1941
1942 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001943 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001944 endclass
1945
1946 class Child extends Base
1947 endclass
1948
1949 var o = Child.new()
1950 var x = o._v1
1951 END
Ernie Rael03042a22023-11-11 08:53:32 +01001952 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 11)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001953 lines =<< trim END
1954 vim9script
1955
1956 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001957 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001958 endclass
1959
1960 class Child extends Base
1961 endclass
1962
1963 def F()
1964 var o = Child.new()
1965 var x = o._v1
1966 enddef
1967 F()
1968 END
Ernie Rael03042a22023-11-11 08:53:32 +01001969 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02001970 lines =<< trim END
1971 vim9script
1972
1973 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001974 var v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001975 endclass
1976
1977 class Child extends Base
1978 endclass
1979
1980 var o = Child.new()
1981 o.v1 = []
1982 END
1983 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 11)
1984 lines =<< trim END
1985 vim9script
1986
1987 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01001988 var v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02001989 endclass
1990
1991 class Child extends Base
1992 endclass
1993
1994 def F()
1995 var o = Child.new()
1996 o.v1 = []
1997 enddef
1998 F()
1999 END
2000
Ernie Rael03042a22023-11-11 08:53:32 +01002001 # Attempt to read a protected variable that is in the middle
Ernie Raele6c9aa52023-10-06 19:55:52 +02002002 # of the class hierarchy.
2003 v9.CheckSourceFailure(lines, 'E1335: Variable "v1" in class "Base" is not writable', 2)
2004 lines =<< trim END
2005 vim9script
2006
2007 class Base0
2008 endclass
2009
2010 class Base extends Base0
Doug Kearns74da0ee2023-12-14 20:26:26 +01002011 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002012 endclass
2013
2014 class Child extends Base
2015 endclass
2016
2017 def F()
2018 var o = Child.new()
2019 var x = o._v1
2020 enddef
2021 F()
2022 END
Ernie Rael03042a22023-11-11 08:53:32 +01002023 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Base"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002024
Ernie Rael03042a22023-11-11 08:53:32 +01002025 # Attempt to read a protected variable that is at the start
Ernie Raele6c9aa52023-10-06 19:55:52 +02002026 # of the class hierarchy.
2027 lines =<< trim END
2028 vim9script
2029
2030 class Base0
2031 endclass
2032
2033 class Base extends Base0
2034 endclass
2035
2036 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01002037 var _v1: list<list<number>>
Ernie Raele6c9aa52023-10-06 19:55:52 +02002038 endclass
2039
2040 def F()
2041 var o = Child.new()
2042 var x = o._v1
2043 enddef
2044 F()
2045 END
Ernie Rael03042a22023-11-11 08:53:32 +01002046 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "Child"', 2)
Ernie Raele6c9aa52023-10-06 19:55:52 +02002047enddef
2048
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002049func Test_class_garbagecollect()
2050 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002051 vim9script
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002052
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002053 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002054 var p = [2, 3]
2055 static var pl = ['a', 'b']
2056 static var pd = {a: 'a', b: 'b'}
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002057 endclass
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002058
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002059 echo Point.pl Point.pd
2060 call test_garbagecollect_now()
2061 echo Point.pl Point.pd
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002062 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002063 call v9.CheckSourceSuccess(lines)
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002064
2065 let lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002066 vim9script
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002067
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002068 interface View
2069 endinterface
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002070
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002071 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01002072 var view: View
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002073 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002074
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002075 class MyView implements View
Doug Kearns74da0ee2023-12-14 20:26:26 +01002076 var widget: Widget
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002077
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002078 def new()
2079 # this will result in a circular reference to this object
Doug Kearns74da0ee2023-12-14 20:26:26 +01002080 var widget = Widget.new(this)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002081 enddef
2082 endclass
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002083
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002084 var view = MyView.new()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002085
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002086 # overwrite "view", will be garbage-collected next
2087 view = MyView.new()
2088 test_garbagecollect_now()
Bram Moolenaarf7ca56f2023-06-05 16:53:25 +01002089 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002090 call v9.CheckSourceSuccess(lines)
Bram Moolenaarcf760d52023-01-05 13:16:04 +00002091endfunc
2092
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002093" Test interface garbage collection
2094func Test_interface_garbagecollect()
2095 let lines =<< trim END
2096 vim9script
2097
2098 interface I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002099 var ro_obj_var: number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002100
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002101 def ObjFoo(): number
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002102 endinterface
2103
2104 class A implements I
Doug Kearns74da0ee2023-12-14 20:26:26 +01002105 static var ro_class_var: number = 10
2106 public static var rw_class_var: number = 20
2107 static var _priv_class_var: number = 30
2108 var ro_obj_var: number = 40
2109 var _priv_obj_var: number = 60
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002110
2111 static def _ClassBar(): number
2112 return _priv_class_var
2113 enddef
2114
2115 static def ClassFoo(): number
2116 return ro_class_var + rw_class_var + A._ClassBar()
2117 enddef
2118
2119 def _ObjBar(): number
2120 return this._priv_obj_var
2121 enddef
2122
2123 def ObjFoo(): number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002124 return this.ro_obj_var + this._ObjBar()
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002125 enddef
2126 endclass
2127
2128 assert_equal(60, A.ClassFoo())
2129 var o = A.new()
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002130 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002131 test_garbagecollect_now()
2132 assert_equal(60, A.ClassFoo())
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002133 assert_equal(100, o.ObjFoo())
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002134 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002135 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan544be0d2023-09-04 22:14:28 +02002136endfunc
2137
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002138def Test_class_method()
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002139 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002140 vim9script
2141 class Value
Doug Kearns74da0ee2023-12-14 20:26:26 +01002142 var value = 0
2143 static var objects = 0
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002144
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002145 def new(v: number)
2146 this.value = v
2147 ++objects
2148 enddef
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002149
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002150 static def GetCount(): number
2151 return objects
2152 enddef
2153 endclass
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002154
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002155 assert_equal(0, Value.GetCount())
2156 var v1 = Value.new(2)
2157 assert_equal(1, Value.GetCount())
2158 var v2 = Value.new(7)
2159 assert_equal(2, Value.GetCount())
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002160 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002161 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002162
2163 # Test for cleaning up after a class definition failure when using class
2164 # functions.
2165 lines =<< trim END
2166 vim9script
2167 class A
2168 static def Foo()
2169 enddef
2170 aaa
2171 endclass
2172 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002173 v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: aaa', 5)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002174
2175 # Test for calling a class method from another class method without the class
2176 # name prefix.
2177 lines =<< trim END
2178 vim9script
2179 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01002180 static var myList: list<number> = [1]
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002181 static def Foo(n: number)
2182 myList->add(n)
2183 enddef
2184 static def Bar()
2185 Foo(2)
2186 enddef
2187 def Baz()
2188 Foo(3)
2189 enddef
2190 endclass
2191 A.Bar()
2192 var a = A.new()
2193 a.Baz()
2194 assert_equal([1, 2, 3], A.myList)
2195 END
2196 v9.CheckSourceSuccess(lines)
Bram Moolenaar6bafdd42023-01-01 12:58:33 +00002197enddef
2198
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002199def Test_class_defcompile()
2200 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002201 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002202
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002203 class C
2204 def Fo(i: number): string
2205 return i
2206 enddef
2207 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002208
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002209 defcompile C.Fo
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002210 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002211 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number', 1)
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002212
2213 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002214 vim9script
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002215
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002216 class C
2217 static def Fc(): number
2218 return 'x'
2219 enddef
2220 endclass
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002221
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002222 defcompile C.Fc
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002223 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002224 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002225
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002226 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002227 vim9script
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002228
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002229 class C
2230 static def new()
2231 enddef
2232 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002233
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002234 defcompile C.new
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002235 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002236 v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" method as static', 5)
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +02002237
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002238 # Trying to compile a function using a non-existing class variable
2239 lines =<< trim END
2240 vim9script
2241 defcompile x.Foo()
2242 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002243 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002244
2245 # Trying to compile a function using a variable which is not a class
2246 lines =<< trim END
2247 vim9script
2248 var x: number
2249 defcompile x.Foo()
2250 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002251 v9.CheckSourceFailure(lines, 'E475: Invalid argument: x.Foo()', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002252
2253 # Trying to compile a function without specifying the name
2254 lines =<< trim END
2255 vim9script
2256 class A
2257 endclass
2258 defcompile A.
2259 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002260 v9.CheckSourceFailure(lines, 'E475: Invalid argument: A.', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002261
2262 # Trying to compile a non-existing class object member function
2263 lines =<< trim END
2264 vim9script
2265 class A
2266 endclass
2267 var a = A.new()
2268 defcompile a.Foo()
2269 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02002270 v9.CheckSourceFailureList(lines, ['E1326: Variable "Foo" not found in object "A"', 'E475: Invalid argument: a.Foo()'])
Bram Moolenaar99a7c0d2023-02-21 19:55:14 +00002271enddef
2272
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002273def Test_class_object_to_string()
2274 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002275 vim9script
2276 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +01002277 var lnum = 1
2278 var col = 22
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002279 endclass
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002280
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002281 assert_equal("class TextPosition", string(TextPosition))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002282
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002283 var pos = TextPosition.new()
2284 assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002285 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002286 v9.CheckSourceSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +02002287
2288 # check string() with object nesting
2289 lines =<< trim END
2290 vim9script
2291 class C
2292 var nest1: C
2293 var nest2: C
2294 def Init(n1: C, n2: C)
2295 this.nest1 = n1
2296 this.nest2 = n2
2297 enddef
2298 endclass
2299
2300 var o1 = C.new()
2301 var o2 = C.new()
2302 o1.Init(o1, o2)
2303 o2.Init(o2, o1)
2304
2305 # The following previously put's vim into an infinite loop.
2306
2307 var expect = "object of C {nest1: object of C {...}, nest2: object of C {nest1: object of C {...}, nest2: object of C {...}}}"
2308 assert_equal(expect, string(o1))
2309 END
2310 v9.CheckSourceSuccess(lines)
2311
2312 lines =<< trim END
2313 vim9script
2314
2315 class B
2316 endclass
2317
2318 class C
2319 var b: B
2320 var c: C
2321 endclass
2322
2323 var o1 = C.new(B.new(), C.new(B.new()))
2324 var expect = "object of C {b: object of B {}, c: object of C {b: object of B {}, c: object of [unknown]}}"
2325 assert_equal(expect, string(o1))
2326 END
2327 v9.CheckSourceSuccess(lines)
Bram Moolenaar91c9d6d2022-12-14 17:30:37 +00002328enddef
Bram Moolenaar74e12742022-12-13 21:14:28 +00002329
Bram Moolenaar554d0312023-01-05 19:59:18 +00002330def Test_interface_basics()
2331 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002332 vim9script
2333 interface Something
Doug Kearns74da0ee2023-12-14 20:26:26 +01002334 var ro_var: list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002335 def GetCount(): number
2336 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002337 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002338 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002339
2340 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002341 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002342 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002343 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002344 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002345 v9.CheckSourceFailure(lines, 'E1342: Interface can only be defined in Vim9 script', 1)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002346
2347 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002348 vim9script
Bram Moolenaar554d0312023-01-05 19:59:18 +00002349
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002350 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002351 var value: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002352 def Method(value: number)
2353 endinterface
Bram Moolenaard40f00c2023-01-13 17:36:49 +00002354 END
h-east61378a12023-04-18 19:07:29 +01002355 # The argument name and the object member name are the same, but this is not a
2356 # problem because object members are always accessed with the "this." prefix.
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002357 v9.CheckSourceSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002358
2359 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002360 vim9script
2361 interface somethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002362 static var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002363 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002364 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002365 v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong', 2)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002366
2367 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002368 vim9script
2369 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002370 var value: string
2371 var count = 7
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002372 def GetCount(): number
2373 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002374 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002375 v9.CheckSourceFailure(lines, 'E1344: Cannot initialize a variable in an interface', 4)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002376
2377 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002378 vim9script
2379 interface SomethingWrong
Doug Kearns74da0ee2023-12-14 20:26:26 +01002380 var value: string
2381 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002382 def GetCount(): number
2383 return 5
2384 enddef
2385 endinterface
Bram Moolenaar554d0312023-01-05 19:59:18 +00002386 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002387 v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5', 6)
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002388
h-eastaa979c72025-01-03 10:19:45 +01002389 # Test for "interface" cannot be abbreviated
2390 lines =<< trim END
2391 vim9script
2392 inte Something
2393 endinterface
2394 END
2395 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: inte Something', 2)
2396
2397 # Test for "endinterface" cannot be abbreviated
2398 lines =<< trim END
2399 vim9script
2400 interface Something
2401 endin
2402 END
2403 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endin', 3)
2404
Yegappan Lakshmananac773182024-04-27 11:36:12 +02002405 # Additional commands after "interface name"
2406 lines =<< trim END
2407 vim9script
2408 interface Something | var x = 10 | var y = 20
2409 endinterface
2410 END
2411 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
2412
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002413 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002414 vim9script
2415 export interface EnterExit
2416 def Enter(): void
2417 def Exit(): void
2418 endinterface
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002419 END
2420 writefile(lines, 'XdefIntf.vim', 'D')
2421
2422 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002423 vim9script
2424 import './XdefIntf.vim' as defIntf
2425 export def With(ee: defIntf.EnterExit, F: func)
2426 ee.Enter()
2427 try
2428 F()
2429 finally
2430 ee.Exit()
2431 endtry
2432 enddef
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002433 END
2434 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002435
2436 var imported =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002437 vim9script
2438 export abstract class EnterExit
2439 def Enter(): void
2440 enddef
2441 def Exit(): void
2442 enddef
2443 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +00002444 END
2445 writefile(imported, 'XdefIntf2.vim', 'D')
2446
2447 lines[1] = " import './XdefIntf2.vim' as defIntf"
2448 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002449enddef
2450
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01002451" Test for using string() with an interface
2452def Test_interface_to_string()
2453 var lines =<< trim END
2454 vim9script
2455 interface Intf
2456 def Method(nr: number)
2457 endinterface
2458 assert_equal("interface Intf", string(Intf))
2459 END
2460 v9.CheckSourceSuccess(lines)
2461enddef
2462
Bram Moolenaar94674f22023-01-06 18:42:20 +00002463def Test_class_implements_interface()
2464 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002465 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002466
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002467 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002468 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002469 def Method(nr: number)
2470 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002471
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002472 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002473 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002474 def Method(nr: number)
2475 echo nr
2476 enddef
2477 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002478
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002479 interface Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002480 var member: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002481 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002482
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002483 class AnotherImpl implements Some, Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002484 var member = 'abc'
2485 var count = 20
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002486 def Method(nr: number)
2487 echo nr
2488 enddef
2489 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002490 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002491 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002492
2493 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002494 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002495
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002496 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002497 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002498 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002499
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002500 class SomeImpl implements Some implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002501 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002502 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002503 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002504 v9.CheckSourceFailure(lines, 'E1350: Duplicate "implements"', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002505
2506 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002507 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002508
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002509 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002510 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002511 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002512
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002513 class SomeImpl implements Some, Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002514 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002515 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002516 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002517 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002518
2519 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002520 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002521
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002522 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002523 var counter: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002524 def Method(nr: number)
2525 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002526
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002527 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002528 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002529 def Method(nr: number)
2530 echo nr
2531 enddef
2532 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002533 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002534 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented', 13)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002535
2536 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002537 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002538
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002539 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002540 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002541 def Methods(nr: number)
2542 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002543
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002544 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002545 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002546 def Method(nr: number)
2547 echo nr
2548 enddef
2549 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002550 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002551 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented', 13)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002552
2553 # Check different order of members in class and interface works.
2554 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002555 vim9script
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002556
2557 interface Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002558 var label: string
2559 var errpos: number
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002560 endinterface
2561
2562 # order of members is opposite of interface
2563 class Failure implements Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002564 public var lnum: number = 5
2565 var errpos: number = 42
2566 var label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002567 endclass
2568
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002569 def Test()
2570 var result: Result = Failure.new()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002571
2572 assert_equal('label', result.label)
2573 assert_equal(42, result.errpos)
2574 enddef
2575
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002576 Test()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002577 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002578 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002579
2580 # Interface name after "extends" doesn't end in a space or NUL character
2581 lines =<< trim END
2582 vim9script
2583 interface A
2584 endinterface
2585 class B extends A"
2586 endclass
2587 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002588 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002589
2590 # Trailing characters after a class name
2591 lines =<< trim END
2592 vim9script
2593 class A bbb
2594 endclass
2595 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002596 v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002597
2598 # using "implements" with a non-existing class
2599 lines =<< trim END
2600 vim9script
2601 class A implements B
2602 endclass
2603 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002604 v9.CheckSourceFailure(lines, 'E1346: Interface name not found: B', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002605
2606 # using "implements" with a regular class
2607 lines =<< trim END
2608 vim9script
2609 class A
2610 endclass
2611 class B implements A
2612 endclass
2613 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002614 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: A', 5)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002615
2616 # using "implements" with a variable
2617 lines =<< trim END
2618 vim9script
2619 var T: number = 10
2620 class A implements T
2621 endclass
2622 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002623 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: T', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002624
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002625 # implements should be followed by a white space
2626 lines =<< trim END
2627 vim9script
2628 interface A
2629 endinterface
2630 class B implements A;
2631 endclass
2632 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002633 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A;', 4)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002634
LemonBoyc5d27442023-08-19 13:02:35 +02002635 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002636 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002637
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002638 interface One
2639 def IsEven(nr: number): bool
2640 endinterface
2641 class Two implements One
2642 def IsEven(nr: number): string
2643 enddef
2644 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002645 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002646 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002647
2648 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002649 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002650
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002651 interface One
2652 def IsEven(nr: number): bool
2653 endinterface
2654 class Two implements One
2655 def IsEven(nr: bool): bool
2656 enddef
2657 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002658 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002659 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002660
2661 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002662 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002663
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002664 interface One
2665 def IsEven(nr: number): bool
2666 endinterface
2667 class Two implements One
2668 def IsEven(nr: number, ...extra: list<number>): bool
2669 enddef
2670 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002671 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002672 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool', 9)
Ernie Raelcf138d42023-09-06 20:45:03 +02002673
2674 # access superclass interface members from subclass, mix variable order
2675 lines =<< trim END
2676 vim9script
2677
2678 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002679 var mvar1: number
2680 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002681 endinterface
2682
2683 # NOTE: the order is swapped
2684 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002685 var mvar2: number
2686 var mvar1: number
2687 public static var svar2: number
2688 public static var svar1: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002689 def new()
2690 svar1 = 11
2691 svar2 = 12
2692 this.mvar1 = 111
2693 this.mvar2 = 112
2694 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002695 endclass
2696
2697 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002698 def new()
2699 this.mvar1 = 121
2700 this.mvar2 = 122
2701 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002702 endclass
2703
2704 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002705 def new()
2706 this.mvar1 = 131
2707 this.mvar2 = 132
2708 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002709 endclass
2710
Ernie Raelcf138d42023-09-06 20:45:03 +02002711 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002712 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002713 enddef
2714
2715 var oa = A.new()
2716 var ob = B.new()
2717 var oc = C.new()
2718
Ernie Raelcf138d42023-09-06 20:45:03 +02002719 assert_equal([111, 112], F2(oa))
2720 assert_equal([121, 122], F2(ob))
2721 assert_equal([131, 132], F2(oc))
2722 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002723 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002724
2725 # Access superclass interface members from subclass, mix variable order.
2726 # Two interfaces, one on A, one on B; each has both kinds of variables
2727 lines =<< trim END
2728 vim9script
2729
2730 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002731 var mvar1: number
2732 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002733 endinterface
2734
2735 interface I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002736 var mvar3: number
2737 var mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002738 endinterface
2739
2740 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002741 public static var svar1: number
2742 public static var svar2: number
2743 var mvar1: number
2744 var mvar2: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002745 def new()
2746 svar1 = 11
2747 svar2 = 12
2748 this.mvar1 = 111
2749 this.mvar2 = 112
2750 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002751 endclass
2752
2753 class B extends A implements I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002754 static var svar3: number
2755 static var svar4: number
2756 var mvar3: number
2757 var mvar4: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002758 def new()
2759 svar3 = 23
2760 svar4 = 24
2761 this.mvar1 = 121
2762 this.mvar2 = 122
2763 this.mvar3 = 123
2764 this.mvar4 = 124
2765 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002766 endclass
2767
2768 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01002769 public static var svar5: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002770 def new()
2771 svar5 = 1001
2772 this.mvar1 = 131
2773 this.mvar2 = 132
2774 this.mvar3 = 133
2775 this.mvar4 = 134
2776 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002777 endclass
2778
Ernie Raelcf138d42023-09-06 20:45:03 +02002779 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002780 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002781 enddef
2782
Ernie Raelcf138d42023-09-06 20:45:03 +02002783 def F4(i: I2): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002784 return [ i.mvar3, i.mvar4 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002785 enddef
2786
Ernie Raelcf138d42023-09-06 20:45:03 +02002787 var oa = A.new()
2788 var ob = B.new()
2789 var oc = C.new()
2790
Ernie Raelcf138d42023-09-06 20:45:03 +02002791 assert_equal([[111, 112]], [F2(oa)])
2792 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2793 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002794 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002795 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002796
2797 # Using two interface names without a space after the ","
2798 lines =<< trim END
2799 vim9script
2800 interface A
2801 endinterface
2802 interface B
2803 endinterface
2804 class C implements A,B
2805 endclass
2806 END
2807 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2808
2809 # No interface name after a comma
2810 lines =<< trim END
2811 vim9script
2812 interface A
2813 endinterface
2814 class B implements A,
2815 endclass
2816 END
2817 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2818
2819 # No interface name after implements
2820 lines =<< trim END
2821 vim9script
2822 class A implements
2823 endclass
2824 END
2825 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002826enddef
2827
Bram Moolenaard0200c82023-01-28 15:19:40 +00002828def Test_call_interface_method()
2829 var lines =<< trim END
2830 vim9script
2831 interface Base
2832 def Enter(): void
2833 endinterface
2834
2835 class Child implements Base
2836 def Enter(): void
2837 g:result ..= 'child'
2838 enddef
2839 endclass
2840
2841 def F(obj: Base)
2842 obj.Enter()
2843 enddef
2844
2845 g:result = ''
2846 F(Child.new())
2847 assert_equal('child', g:result)
2848 unlet g:result
2849 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002850 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002851
2852 lines =<< trim END
2853 vim9script
2854 class Base
2855 def Enter(): void
2856 g:result ..= 'base'
2857 enddef
2858 endclass
2859
2860 class Child extends Base
2861 def Enter(): void
2862 g:result ..= 'child'
2863 enddef
2864 endclass
2865
2866 def F(obj: Base)
2867 obj.Enter()
2868 enddef
2869
2870 g:result = ''
2871 F(Child.new())
2872 assert_equal('child', g:result)
2873 unlet g:result
2874 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002875 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002876
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002877 # method of interface returns a value
2878 lines =<< trim END
2879 vim9script
2880 interface Base
2881 def Enter(): string
2882 endinterface
2883
2884 class Child implements Base
2885 def Enter(): string
2886 g:result ..= 'child'
2887 return "/resource"
2888 enddef
2889 endclass
2890
2891 def F(obj: Base)
2892 var r = obj.Enter()
2893 g:result ..= r
2894 enddef
2895
2896 g:result = ''
2897 F(Child.new())
2898 assert_equal('child/resource', g:result)
2899 unlet g:result
2900 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002901 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002902
2903 lines =<< trim END
2904 vim9script
2905 class Base
2906 def Enter(): string
2907 return null_string
2908 enddef
2909 endclass
2910
2911 class Child extends Base
2912 def Enter(): string
2913 g:result ..= 'child'
2914 return "/resource"
2915 enddef
2916 endclass
2917
2918 def F(obj: Base)
2919 var r = obj.Enter()
2920 g:result ..= r
2921 enddef
2922
2923 g:result = ''
2924 F(Child.new())
2925 assert_equal('child/resource', g:result)
2926 unlet g:result
2927 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002928 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002929
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002930 # No class that implements the interface.
2931 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002932 vim9script
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002933
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002934 interface IWithEE
2935 def Enter(): any
2936 def Exit(): void
2937 endinterface
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002938
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002939 def With1(ee: IWithEE, F: func)
2940 var r = ee.Enter()
2941 enddef
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002942
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002943 defcompile
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002944 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002945 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002946enddef
2947
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002948def Test_class_used_as_type()
2949 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002950 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002951
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002952 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002953 var x = 0
2954 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002955 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002956
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002957 var p: Point
2958 p = Point.new(2, 33)
2959 assert_equal(2, p.x)
2960 assert_equal(33, p.y)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002961 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002962 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002963
2964 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002965 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002966
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002967 interface HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002968 var x: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002969 endinterface
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002970
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002971 class Point implements HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002972 var x = 0
2973 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002974 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002975
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002976 var p: Point
2977 p = Point.new(2, 33)
2978 var hx = p
2979 assert_equal(2, hx.x)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002980 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002981 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002982
2983 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002984 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002985
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002986 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002987 var x = 0
2988 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002989 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002990
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002991 var p: Point
2992 p = 'text'
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002993 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002994 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string', 9)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002995enddef
2996
Bram Moolenaar83677162023-01-08 19:54:10 +00002997def Test_class_extends()
2998 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002999 vim9script
3000 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003001 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003002 def GetOne(): number
3003 return this.one
Bram Moolenaar6aa09372023-01-11 17:59:38 +00003004 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003005 endclass
3006 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003007 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003008 def GetTotal(): number
3009 return this.one + this.two
3010 enddef
3011 endclass
3012 var o = Child.new()
3013 assert_equal(1, o.one)
3014 assert_equal(2, o.two)
3015 assert_equal(1, o.GetOne())
3016 assert_equal(3, o.GetTotal())
Bram Moolenaar6481acc2023-01-11 21:14:17 +00003017 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003018 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003019
3020 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003021 vim9script
3022 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003023 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003024 endclass
3025 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003026 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003027 endclass
3028 var o = Child.new(3, 44)
3029 assert_equal(3, o.one)
3030 assert_equal(44, o.two)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003031 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003032 v9.CheckSourceSuccess(lines)
3033
3034 lines =<< trim END
3035 vim9script
3036 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003037 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003038 endclass
3039 class Child extends Base extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003040 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003041 endclass
3042 END
3043 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"', 5)
3044
3045 lines =<< trim END
3046 vim9script
3047 class Child extends BaseClass
Doug Kearns74da0ee2023-12-14 20:26:26 +01003048 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003049 endclass
3050 END
3051 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass', 4)
3052
3053 lines =<< trim END
3054 vim9script
3055 var SomeVar = 99
3056 class Child extends SomeVar
Doug Kearns74da0ee2023-12-14 20:26:26 +01003057 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003058 endclass
3059 END
3060 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar', 5)
3061
3062 lines =<< trim END
3063 vim9script
3064 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003065 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003066 def ToString(): string
3067 return this.name
3068 enddef
3069 endclass
3070
3071 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003072 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003073 def ToString(): string
3074 return super.ToString() .. ': ' .. this.age
3075 enddef
3076 endclass
3077
3078 var o = Child.new('John', 42)
3079 assert_equal('John: 42', o.ToString())
3080 END
3081 v9.CheckSourceSuccess(lines)
3082
3083 lines =<< trim END
3084 vim9script
3085 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003086 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003087 def ToString(): number
3088 return this.age
3089 enddef
3090 def ToString(): string
3091 return this.age
3092 enddef
3093 endclass
3094 END
3095 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
3096
3097 lines =<< trim END
3098 vim9script
3099 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003100 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003101 def ToString(): string
3102 return super .ToString() .. ': ' .. this.age
3103 enddef
3104 endclass
3105 var o = Child.new(42)
3106 echo o.ToString()
3107 END
3108 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
3109
3110 lines =<< trim END
3111 vim9script
3112 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003113 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003114 def ToString(): string
3115 return this.name
3116 enddef
3117 endclass
3118
3119 var age = 42
3120 def ToString(): string
3121 return super.ToString() .. ': ' .. age
3122 enddef
3123 echo ToString()
3124 END
3125 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
3126
3127 lines =<< trim END
3128 vim9script
3129 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003130 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003131 def ToString(): string
3132 return super.ToString() .. ': ' .. this.age
3133 enddef
3134 endclass
3135 var o = Child.new(42)
3136 echo o.ToString()
3137 END
3138 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
3139
3140 lines =<< trim END
3141 vim9script
3142 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003143 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003144 static def ToString(): string
3145 return 'Base class'
3146 enddef
3147 endclass
3148
3149 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003150 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003151 def ToString(): string
3152 return Base.ToString() .. ': ' .. this.age
3153 enddef
3154 endclass
3155
3156 var o = Child.new('John', 42)
3157 assert_equal('Base class: 42', o.ToString())
3158 END
3159 v9.CheckSourceSuccess(lines)
3160
3161 lines =<< trim END
3162 vim9script
3163 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003164 var value = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003165 def new(init: number)
3166 this.value = number + 1
3167 enddef
3168 endclass
3169 class Child extends Base
3170 def new()
3171 this.new(3)
3172 enddef
3173 endclass
3174 var c = Child.new()
3175 END
3176 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003177
3178 # base class with more than one object member
3179 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003180 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003181
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003182 class Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01003183 var success: bool
3184 var value: any = null
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003185 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003186
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003187 class Success extends Result
3188 def new(this.value = v:none)
3189 this.success = true
3190 enddef
3191 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003192
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003193 var v = Success.new('asdf')
3194 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003195 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003196 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003197
3198 # class name after "extends" doesn't end in a space or NUL character
3199 lines =<< trim END
3200 vim9script
3201 class A
3202 endclass
3203 class B extends A"
3204 endclass
3205 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003206 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00003207enddef
3208
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003209def Test_using_base_class()
3210 var lines =<< trim END
3211 vim9script
3212
3213 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003214 def Enter(): any
3215 return null
3216 enddef
3217 def Exit(resource: any): void
3218 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003219 endclass
3220
3221 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003222 def Enter(): any
3223 return 42
3224 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003225
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003226 def Exit(resource: number): void
3227 g:result ..= '/exit'
3228 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003229 endclass
3230
3231 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003232 var r = ee.Enter()
3233 try
3234 g:result ..= r
3235 finally
3236 g:result ..= '/finally'
3237 ee.Exit(r)
3238 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003239 enddef
3240
3241 g:result = ''
3242 With(ChildEE.new())
3243 assert_equal('42/finally/exit', g:result)
3244 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003245 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003246 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01003247
3248 # Using super, Child invokes Base method which has optional arg. #12471
3249 lines =<< trim END
3250 vim9script
3251
3252 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003253 var success: bool = false
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003254 def Method(arg = 0)
3255 this.success = true
3256 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01003257 endclass
3258
3259 class Child extends Base
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003260 def new()
3261 super.Method()
3262 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01003263 endclass
3264
3265 var obj = Child.new()
3266 assert_equal(true, obj.success)
3267 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003268 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003269enddef
3270
Ernie Raelbce60c42025-01-19 10:03:00 +01003271" Test for using a method from the super class
Ernie Rael58c95792024-08-13 23:27:22 +02003272def Test_super_dispatch()
3273 # See #15448 and #15463
3274 var lines =<< trim END
3275 vim9script
3276
3277 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003278 def String(): string
3279 return 'A'
3280 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003281 endclass
3282
3283 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003284 def String(): string
3285 return super.String()
3286 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003287 endclass
3288
3289 class C extends B
3290 endclass
3291
3292 assert_equal('A', C.new().String())
3293 END
3294 v9.CheckSourceSuccess(lines)
3295
3296 lines =<< trim END
3297 vim9script
3298
3299 class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003300 def F(): string
3301 return 'AA'
3302 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003303 endclass
3304
3305 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003306 def F(): string
3307 return 'BB'
3308 enddef
3309 def S(): string
3310 return super.F()
3311 enddef
3312 def S0(): string
3313 return this.S()
3314 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003315 endclass
3316
3317 class C extends B
Ernie Raelbce60c42025-01-19 10:03:00 +01003318 def F(): string
3319 return 'CC'
3320 enddef
3321 def ToB(): string
3322 return super.F()
3323 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003324 endclass
3325
3326 assert_equal('AA', B.new().S())
3327 assert_equal('AA', C.new().S())
3328 assert_equal('AA', B.new().S0())
3329 assert_equal('AA', C.new().S0())
3330
3331 assert_equal('BB', C.new().ToB())
3332
3333 assert_equal('CC', C.new().F())
3334 assert_equal('BB', B.new().F())
3335 assert_equal('AA', A.new().F())
3336 END
3337 v9.CheckSourceSuccess(lines)
3338
3339 lines =<< trim END
3340 vim9script
3341
3342 var call_chain: list<string>
3343
3344 abstract class A
Ernie Raelbce60c42025-01-19 10:03:00 +01003345 abstract def _G(): string
Ernie Rael58c95792024-08-13 23:27:22 +02003346
Ernie Raelbce60c42025-01-19 10:03:00 +01003347 def F(): string
3348 call_chain->add('A.F()')
3349 return this._G()
3350 enddef
3351 def _H(): string
3352 call_chain->add('A._H()')
3353 return this.F()
3354 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003355 endclass
3356
3357 class B extends A
Ernie Raelbce60c42025-01-19 10:03:00 +01003358 def _G(): string
3359 call_chain->add('B.G()')
3360 return 'BBB'
3361 enddef
3362 def SF(): string
3363 call_chain->add('B.SF()')
3364 return super._H()
3365 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003366 endclass
3367
3368 class C extends B
3369 endclass
3370
3371 class D extends C
Ernie Raelbce60c42025-01-19 10:03:00 +01003372 def SF(): string
3373 call_chain->add('D.SF()')
3374 return super.SF()
3375 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003376 endclass
3377
3378 class E extends D
Ernie Raelbce60c42025-01-19 10:03:00 +01003379 def SF(): string
3380 call_chain->add('E.SF()')
3381 return super.SF()
3382 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003383 endclass
3384
3385 class F extends E
Ernie Raelbce60c42025-01-19 10:03:00 +01003386 def _G(): string
3387 call_chain->add('F._G()')
3388 return 'FFF'
3389 enddef
Ernie Rael58c95792024-08-13 23:27:22 +02003390 endclass
3391
3392 # E.new() -> A.F() -> B._G()
3393 call_chain = []
3394 var o1 = E.new()
3395 assert_equal('BBB', o1.F())
3396 assert_equal(['A.F()', 'B.G()'], call_chain)
3397
3398 # F.new() -> E.SF() -> D.SF() -> B.SF() -> A._H() -> A.F() -> F._G()
3399 call_chain = []
3400 var o2 = F.new()
3401 assert_equal('FFF', o2.SF())
3402 assert_equal(['E.SF()', 'D.SF()', 'B.SF()', 'A._H()', 'A.F()', 'F._G()'], call_chain)
3403 END
3404 v9.CheckSourceSuccess(lines)
Ernie Raelbce60c42025-01-19 10:03:00 +01003405
3406 # problems with method dispatch: super -> abstract
3407 # https://github.com/vim/vim/issues/15514
3408 lines =<< trim END
3409 vim9script
3410 abstract class B
3411 abstract def ToString(): string
3412 endclass
3413
3414 class C extends B
3415 def ToString(): string
3416 return super.ToString()
3417 enddef
3418 endclass
3419
3420 try
3421 defcompile C.ToString
3422 call assert_false(1, 'command should have failed')
3423 catch
3424 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3425 endtry
3426 END
3427 v9.CheckSourceSuccess(lines)
3428
3429 # problems with method dispatch: super -> abstract -> concrete
3430 lines =<< trim END
3431 vim9script
3432
3433 class A
3434 def ToString()
3435 echo 'A'
3436 enddef
3437 endclass
3438
3439 abstract class B extends A
3440 abstract def ToString()
3441 endclass
3442
3443 class C extends B
3444 def ToString()
3445 super.ToString()
3446 enddef
3447 endclass
3448
3449 try
3450 defcompile C.ToString
3451 call assert_false(1, 'command should have failed')
3452 catch
3453 call assert_exception('E1431: Abstract method "ToString" in class "B" cannot be accessed directly')
3454 endtry
3455 END
3456 v9.CheckSourceSuccess(lines)
3457
3458 # Invoking a super method and an interface method which have the same name.
3459 lines =<< trim END
3460 vim9script
3461
3462 interface I
3463 def ToString(): string
3464 endinterface
3465
3466 # Note that A does not implement I.
3467 class A
3468 def ToString(): string
3469 return 'A'
3470 enddef
3471 endclass
3472
3473 class B extends A implements I
3474 def ToString(): string
3475 return super.ToString()
3476 enddef
3477 endclass
3478
3479 def TestI(i: I): string
3480 return i.ToString()
3481 enddef
3482
3483 assert_equal('A', B.new().ToString())
3484 assert_equal('A', TestI(B.new()))
3485 END
3486 v9.CheckSourceSuccess(lines)
3487
3488 # super and an abstract class with no abstract methods
3489 lines =<< trim END
3490 vim9script
3491
3492 class A
3493 def ToString(): string
3494 return 'A'
3495 enddef
3496 endclass
3497
3498 # An abstract class with no abstract methods.
3499 abstract class B extends A
3500 endclass
3501
3502 class C extends B
3503 def ToString(): string
3504 return super.ToString()
3505 enddef
3506 endclass
3507
3508 def TestA(a: A): string
3509 return a.ToString()
3510 enddef
3511
3512 def TestB(b: B): string
3513 return b.ToString()
3514 enddef
3515
3516 assert_equal('A', C.new().ToString())
3517 assert_equal('A', TestA(A.new()))
3518 assert_equal('A', TestA(C.new()))
3519 assert_equal('A', TestB(C.new()))
3520 END
3521 v9.CheckSourceSuccess(lines)
3522
3523 # super and an abstract class with no abstract methods and the initial
3524 # implements clause
3525 lines =<< trim END
3526 vim9script
3527
3528 interface I
3529 def ToString(): string
3530 endinterface
3531
3532 # Note that A does not implement I.
3533 class A
3534 def ToString(): string
3535 return 'A'
3536 enddef
3537 endclass
3538
3539 # An abstract class with no abstract methods.
3540 abstract class B extends A implements I
3541 endclass
3542
3543 class C extends B implements I
3544 def ToString(): string
3545 return super.ToString()
3546 enddef
3547 endclass
3548
3549 # Note that A.ToString() is different from I.ToString().
3550 def TestA(a: A): string
3551 return a.ToString()
3552 enddef
3553
3554 assert_equal('A', C.new().ToString())
3555 assert_equal('A', TestA(A.new()))
3556 assert_equal('A', TestA(C.new()))
3557 END
3558 v9.CheckSourceSuccess(lines)
Ernie Rael58c95792024-08-13 23:27:22 +02003559enddef
3560
Bram Moolenaara86655a2023-01-12 17:06:27 +00003561def Test_class_import()
3562 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003563 vim9script
3564 export class Animal
Doug Kearns74da0ee2023-12-14 20:26:26 +01003565 var kind: string
3566 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003567 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003568 END
3569 writefile(lines, 'Xanimal.vim', 'D')
3570
3571 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003572 vim9script
3573 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003574
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003575 var a: animal.Animal
3576 a = animal.Animal.new('fish', 'Eric')
3577 assert_equal('fish', a.kind)
3578 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003579
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003580 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3581 assert_equal('cat', b.kind)
3582 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003583 END
3584 v9.CheckScriptSuccess(lines)
3585enddef
3586
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003587" Test for importing a class into a legacy script and calling the class method
3588def Test_class_method_from_legacy_script()
3589 var lines =<< trim END
3590 vim9script
3591 export class A
3592 static var name: string = 'a'
3593 static def SetName(n: string)
3594 name = n
3595 enddef
3596 endclass
3597 END
3598 writefile(lines, 'Xvim9export.vim', 'D')
3599
3600 lines =<< trim END
3601 import './Xvim9export.vim' as vim9
3602
3603 call s:vim9.A.SetName('b')
3604 call assert_equal('b', s:vim9.A.name)
3605 END
3606 v9.CheckScriptSuccess(lines)
3607enddef
3608
Yegappan Lakshmanand2e1c832023-12-14 19:59:45 +01003609" Test for implementing an imported interface
3610def Test_implement_imported_interface()
3611 var lines =<< trim END
3612 vim9script
3613 export interface Imp_Intf1
3614 def Fn1(): number
3615 endinterface
3616 export interface Imp_Intf2
3617 def Fn2(): number
3618 endinterface
3619 END
3620 writefile(lines, 'Ximportinterface.vim', 'D')
3621
3622 lines =<< trim END
3623 vim9script
3624 import './Ximportinterface.vim' as Xintf
3625
3626 class A implements Xintf.Imp_Intf1, Xintf.Imp_Intf2
3627 def Fn1(): number
3628 return 10
3629 enddef
3630 def Fn2(): number
3631 return 20
3632 enddef
3633 endclass
3634 var a = A.new()
3635 assert_equal(10, a.Fn1())
3636 assert_equal(20, a.Fn2())
3637 END
3638 v9.CheckScriptSuccess(lines)
3639enddef
3640
3641" Test for extending an imported class
3642def Test_extend_imported_class()
3643 var lines =<< trim END
3644 vim9script
3645 export class Imp_C1
3646 def Fn1(): number
3647 return 5
3648 enddef
3649 endclass
3650 END
3651 writefile(lines, 'Xextendimportclass.vim', 'D')
3652
3653 lines =<< trim END
3654 vim9script
3655 import './Xextendimportclass.vim' as XClass
3656
3657 class A extends XClass.Imp_C1
3658 endclass
3659 var a = A.new()
3660 assert_equal(5, a.Fn1())
3661 END
3662 v9.CheckScriptSuccess(lines)
3663enddef
3664
Hirohito Higashi57f01192025-01-14 17:21:42 +01003665" Test for multi level import
3666def Test_multi_level_import_normal()
3667 var lines =<< trim END
3668 vim9script
3669 export class Property
3670 public var value: string
3671 endclass
3672 END
3673 writefile(lines, 'aa.vim', 'D')
3674
3675 lines =<< trim END
3676 vim9script
3677 import './aa.vim'
3678 export class View
3679 var content = aa.Property.new('')
3680 endclass
3681 END
3682 writefile(lines, 'bb.vim', 'D')
3683
3684 lines =<< trim END
3685 vim9script
3686 import './bb.vim'
3687 class MyView extends bb.View
3688 def new(value: string)
3689 this.content.value = value
3690 enddef
3691 endclass
3692 var myView = MyView.new('This should be ok')
3693 END
3694 v9.CheckScriptSuccess(lines)
3695enddef
3696
3697" Test for multi level import
3698def Test_multi_level_import_nest_over()
3699 var lines =<< trim END
3700 vim9script
3701 import './xbb.vim'
3702 export class Property
3703 public var value: string
3704 endclass
3705 END
3706 writefile(lines, 'xaa.vim', 'D')
3707
3708 lines =<< trim END
3709 vim9script
3710 import './xaa.vim'
3711 export class View
3712 var content = aa.Property.new('')
3713 endclass
3714 END
3715 writefile(lines, 'xbb.vim', 'D')
3716
3717 lines =<< trim END
3718 vim9script
3719 set maxfuncdepth=100
3720 import './xbb.vim'
3721 class MyView extends bb.View
3722 def new(value: string)
3723 this.content.value = value
3724 enddef
3725 endclass
3726 var myView = MyView.new('This should be ok')
3727 END
3728 v9.CheckSourceFailure(lines, 'E1045: Import nesting too deep', 3)
3729enddef
3730
3731def Test_abtstract_class()
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003732 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003733 vim9script
3734 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003735 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003736 endclass
3737 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003738 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003739 endclass
3740 var p: Base = Person.new('Peter', 42)
3741 assert_equal('Peter', p.name)
3742 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003743 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003744 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003745
3746 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003747 vim9script
3748 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003749 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003750 endclass
3751 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003752 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003753 endclass
3754 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003755 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003756 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003757
3758 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003759 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003760 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003761 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003762 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003763 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003764
h-eastaa979c72025-01-03 10:19:45 +01003765 # Test for "abstract" cannot be abbreviated
3766 lines =<< trim END
3767 vim9script
3768 abs class A
3769 endclass
3770 END
3771 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs class A', 2)
3772
Yegappan Lakshmananac773182024-04-27 11:36:12 +02003773 # Additional commands after "abstract class"
3774 lines =<< trim END
3775 vim9script
3776 abstract class Something | var x = []
3777 endclass
3778 END
3779 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = []", 2)
3780
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003781 # Abstract class cannot have a "new" function
3782 lines =<< trim END
3783 vim9script
3784 abstract class Base
3785 def new()
3786 enddef
3787 endclass
3788 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003789 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003790
3791 # extending an abstract class with class methods and variables
3792 lines =<< trim END
3793 vim9script
3794 abstract class A
3795 static var s: string = 'vim'
3796 static def Fn(): list<number>
3797 return [10]
3798 enddef
3799 endclass
3800 class B extends A
3801 endclass
3802 var b = B.new()
3803 assert_equal('vim', A.s)
3804 assert_equal([10], A.Fn())
3805 END
3806 v9.CheckScriptSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003807enddef
3808
Bram Moolenaar486fc252023-01-18 14:51:07 +00003809def Test_closure_in_class()
3810 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003811 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003812
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003813 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01003814 var y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003815
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003816 def new()
3817 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3818 enddef
3819 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003820
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003821 Foo.new()
3822 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003823 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003824 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003825enddef
3826
Ernie Rael9ed53752023-12-11 17:40:46 +01003827def Test_construct_object_from_legacy()
3828 # Cannot directly invoke constructor from legacy
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003829 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003830 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003831
Ernie Rael9ed53752023-12-11 17:40:46 +01003832 var newCalled = false
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003833
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003834 class A
Ernie Rael9ed53752023-12-11 17:40:46 +01003835 def new(arg: string)
3836 newCalled = true
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003837 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003838 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003839
Ernie Rael9ed53752023-12-11 17:40:46 +01003840 export def CreateA(...args: list<any>): A
3841 return call(A.new, args)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003842 enddef
3843
Ernie Rael9ed53752023-12-11 17:40:46 +01003844 g:P = CreateA
3845 legacy call g:P('some_arg')
3846 assert_equal(true, newCalled)
3847 unlet g:P
3848 END
3849 v9.CheckSourceSuccess(lines)
3850
3851 lines =<< trim END
3852 vim9script
3853
3854 var newCalled = false
3855
3856 class A
3857 static def CreateA(options = {}): any
3858 return A.new()
3859 enddef
3860 def new()
3861 newCalled = true
3862 enddef
3863 endclass
3864
3865 g:P = A.CreateA
3866 legacy call g:P()
3867 assert_equal(true, newCalled)
3868 unlet g:P
3869 END
3870 v9.CheckSourceSuccess(lines)
3871
3872 # This also tests invoking "new()" with "call"
3873 lines =<< trim END
3874 vim9script
3875
3876 var createdObject: any
3877
3878 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01003879 var val1: number
3880 var val2: number
Ernie Rael9ed53752023-12-11 17:40:46 +01003881 static def CreateA(...args: list<any>): any
3882 createdObject = call(A.new, args)
3883 return createdObject
3884 enddef
3885 endclass
3886
3887 g:P = A.CreateA
3888 legacy call g:P(3, 5)
3889 assert_equal(3, createdObject.val1)
3890 assert_equal(5, createdObject.val2)
3891 legacy call g:P()
3892 assert_equal(0, createdObject.val1)
3893 assert_equal(0, createdObject.val2)
3894 legacy call g:P(7)
3895 assert_equal(7, createdObject.val1)
3896 assert_equal(0, createdObject.val2)
3897 unlet g:P
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003898 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003899 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003900enddef
3901
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003902def Test_defer_with_object()
3903 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003904 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003905
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003906 class CWithEE
3907 def Enter()
3908 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003909 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003910 def Exit()
3911 g:result ..= "exited"
3912 enddef
3913 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003914
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003915 def With(ee: CWithEE, F: func)
3916 ee.Enter()
3917 defer ee.Exit()
3918 F()
3919 enddef
3920
3921 g:result = ''
3922 var obj = CWithEE.new()
3923 obj->With(() => {
3924 g:result ..= "called/"
3925 })
3926 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003927 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003928 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003929 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003930
3931 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003932 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003933
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003934 class BaseWithEE
3935 def Enter()
3936 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003937 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003938 def Exit()
3939 g:result ..= "exited-base"
3940 enddef
3941 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003942
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003943 class CWithEE extends BaseWithEE
3944 def Enter()
3945 g:result ..= "entered-child/"
3946 enddef
3947 def Exit()
3948 g:result ..= "exited-child"
3949 enddef
3950 endclass
3951
3952 def With(ee: BaseWithEE, F: func)
3953 ee.Enter()
3954 defer ee.Exit()
3955 F()
3956 enddef
3957
3958 g:result = ''
3959 var obj = CWithEE.new()
3960 obj->With(() => {
3961 g:result ..= "called/"
3962 })
3963 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003964 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003965 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003966 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003967enddef
3968
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003969" The following test used to crash Vim (Github issue #12676)
3970def Test_extends_method_crashes_vim()
3971 var lines =<< trim END
3972 vim9script
3973
3974 class Observer
3975 endclass
3976
3977 class Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003978 var value: any
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003979
3980 def Set(v: any)
3981 if v != this.value
3982 this.value = v
3983 endif
3984 enddef
3985
3986 def Register(observer: Observer)
3987 enddef
3988 endclass
3989
3990 class Bool extends Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003991 var value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003992 endclass
3993
3994 def Observe(obj: Property, who: Observer)
3995 obj.Register(who)
3996 enddef
3997
3998 var p = Bool.new(false)
3999 var myObserver = Observer.new()
4000
4001 Observe(p, myObserver)
4002
4003 p.Set(true)
4004 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004005 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02004006enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004007
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02004008" Test for calling a method in a class that is extended
4009def Test_call_method_in_extended_class()
4010 var lines =<< trim END
4011 vim9script
4012
4013 var prop_init_called = false
4014 var prop_register_called = false
4015
4016 class Property
4017 def Init()
4018 prop_init_called = true
4019 enddef
4020
4021 def Register()
4022 prop_register_called = true
4023 enddef
4024 endclass
4025
4026 class Bool extends Property
4027 endclass
4028
4029 def Observe(obj: Property)
4030 obj.Register()
4031 enddef
4032
4033 var p = Property.new()
4034 Observe(p)
4035
4036 p.Init()
4037 assert_true(prop_init_called)
4038 assert_true(prop_register_called)
4039 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004040 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02004041enddef
4042
LemonBoyafe04662023-08-23 21:08:11 +02004043def Test_instanceof()
4044 var lines =<< trim END
4045 vim9script
4046
4047 class Base1
4048 endclass
4049
4050 class Base2 extends Base1
4051 endclass
4052
4053 interface Intf1
4054 endinterface
4055
4056 class Mix1 implements Intf1
4057 endclass
4058
4059 class Base3 extends Mix1
4060 endclass
4061
Ernie Rael2025af12023-12-12 16:58:00 +01004062 type AliasBase1 = Base1
4063 type AliasBase2 = Base2
4064 type AliasIntf1 = Intf1
4065 type AliasMix1 = Mix1
4066
LemonBoyafe04662023-08-23 21:08:11 +02004067 var b1 = Base1.new()
4068 var b2 = Base2.new()
4069 var b3 = Base3.new()
4070
4071 assert_true(instanceof(b1, Base1))
4072 assert_true(instanceof(b2, Base1))
4073 assert_false(instanceof(b1, Base2))
4074 assert_true(instanceof(b3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01004075 assert_true(instanceof(b3, Base1, Base2, Intf1))
4076
4077 assert_true(instanceof(b1, AliasBase1))
4078 assert_true(instanceof(b2, AliasBase1))
4079 assert_false(instanceof(b1, AliasBase2))
4080 assert_true(instanceof(b3, AliasMix1))
4081 assert_true(instanceof(b3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02004082
4083 def Foo()
4084 var a1 = Base1.new()
4085 var a2 = Base2.new()
4086 var a3 = Base3.new()
4087
4088 assert_true(instanceof(a1, Base1))
4089 assert_true(instanceof(a2, Base1))
4090 assert_false(instanceof(a1, Base2))
4091 assert_true(instanceof(a3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01004092 assert_true(instanceof(a3, Base1, Base2, Intf1))
4093
4094 assert_true(instanceof(a1, AliasBase1))
4095 assert_true(instanceof(a2, AliasBase1))
4096 assert_false(instanceof(a1, AliasBase2))
4097 assert_true(instanceof(a3, AliasMix1))
4098 assert_true(instanceof(a3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02004099 enddef
4100 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02004101
4102 var o_null: Base1
4103 assert_false(instanceof(o_null, Base1))
4104
LemonBoyafe04662023-08-23 21:08:11 +02004105 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004106 v9.CheckSourceSuccess(lines)
Ernie Rael2025af12023-12-12 16:58:00 +01004107
4108 lines =<< trim END
4109 vim9script
4110
4111 class Base1
4112 endclass
4113 instanceof(Base1.new())
4114 END
4115 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
4116
4117 lines =<< trim END
4118 vim9script
4119
4120 class Base1
4121 endclass
4122 def F()
4123 instanceof(Base1.new())
4124 enddef
4125 F()
4126 END
4127 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
4128
4129 lines =<< trim END
4130 vim9script
4131
4132 class Base1
4133 endclass
4134
4135 class Base2
4136 endclass
4137
4138 var o = Base2.new()
4139 instanceof(o, Base1, Base2, 3)
4140 END
4141 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4', 10)
4142
4143 lines =<< trim END
4144 vim9script
4145
4146 class Base1
4147 endclass
4148
4149 class Base2
4150 endclass
4151
4152 def F()
4153 var o = Base2.new()
4154 instanceof(o, Base1, Base2, 3)
4155 enddef
4156 F()
4157 END
4158 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4')
LemonBoyafe04662023-08-23 21:08:11 +02004159enddef
4160
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004161" Test for calling a method in the parent class that is extended partially.
4162" This used to fail with the 'E118: Too many arguments for function: Text' error
4163" message (Github issue #12524).
4164def Test_call_method_in_parent_class()
4165 var lines =<< trim END
4166 vim9script
4167
4168 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01004169 var _lnum: number = 1
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004170
4171 def SetY(lnum: number)
4172 this._lnum = lnum
4173 enddef
4174
4175 def Text(): string
4176 return ''
4177 enddef
4178 endclass
4179
4180 class Foo extends Widget
4181 def Text(): string
4182 return '<Foo>'
4183 enddef
4184 endclass
4185
4186 def Stack(w1: Widget, w2: Widget): list<Widget>
4187 w1.SetY(1)
4188 w2.SetY(2)
4189 return [w1, w2]
4190 enddef
4191
4192 var foo1 = Foo.new()
4193 var foo2 = Foo.new()
4194 var l = Stack(foo1, foo2)
4195 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004196 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004197enddef
4198
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004199" Test for calling methods from three levels of classes
4200def Test_multi_level_method_call()
4201 var lines =<< trim END
4202 vim9script
4203
4204 var A_func1: number = 0
4205 var A_func2: number = 0
4206 var A_func3: number = 0
4207 var B_func2: number = 0
4208 var B_func3: number = 0
4209 var C_func3: number = 0
4210
4211 class A
4212 def Func1()
4213 A_func1 += 1
4214 enddef
4215
4216 def Func2()
4217 A_func2 += 1
4218 enddef
4219
4220 def Func3()
4221 A_func3 += 1
4222 enddef
4223 endclass
4224
4225 class B extends A
4226 def Func2()
4227 B_func2 += 1
4228 enddef
4229
4230 def Func3()
4231 B_func3 += 1
4232 enddef
4233 endclass
4234
4235 class C extends B
4236 def Func3()
4237 C_func3 += 1
4238 enddef
4239 endclass
4240
4241 def A_CallFuncs(a: A)
4242 a.Func1()
4243 a.Func2()
4244 a.Func3()
4245 enddef
4246
4247 def B_CallFuncs(b: B)
4248 b.Func1()
4249 b.Func2()
4250 b.Func3()
4251 enddef
4252
4253 def C_CallFuncs(c: C)
4254 c.Func1()
4255 c.Func2()
4256 c.Func3()
4257 enddef
4258
4259 var cobj = C.new()
4260 A_CallFuncs(cobj)
4261 B_CallFuncs(cobj)
4262 C_CallFuncs(cobj)
4263 assert_equal(3, A_func1)
4264 assert_equal(0, A_func2)
4265 assert_equal(0, A_func3)
4266 assert_equal(3, B_func2)
4267 assert_equal(0, B_func3)
4268 assert_equal(3, C_func3)
4269 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004270 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004271enddef
4272
4273" Test for using members from three levels of classes
4274def Test_multi_level_member_access()
4275 var lines =<< trim END
4276 vim9script
4277
4278 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004279 public var val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004280 endclass
4281
4282 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004283 public var val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004284 endclass
4285
4286 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01004287 public var val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004288 endclass
4289
4290 def A_members(a: A)
4291 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004292 enddef
4293
4294 def B_members(b: B)
4295 b.val1 += 1
4296 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004297 enddef
4298
4299 def C_members(c: C)
4300 c.val1 += 1
4301 c.val2 += 1
4302 c.val3 += 1
4303 enddef
4304
4305 var cobj = C.new()
4306 A_members(cobj)
4307 B_members(cobj)
4308 C_members(cobj)
4309 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004310 assert_equal(2, cobj.val2)
4311 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004312 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004313 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004314enddef
4315
LemonBoy0ffc17a2023-08-20 18:09:11 +02004316" Test expansion of <stack> with class methods.
4317def Test_stack_expansion_with_methods()
4318 var lines =<< trim END
4319 vim9script
4320
4321 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004322 def M1()
4323 F0()
4324 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02004325 endclass
4326
4327 def F0()
Ernie Rael16cdfa62024-04-02 19:05:39 +02004328 assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
LemonBoy0ffc17a2023-08-20 18:09:11 +02004329 enddef
4330
4331 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004332 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02004333 enddef
4334
4335 F()
4336 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004337 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02004338enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004339
4340" Test the return type of the new() constructor
4341def Test_new_return_type()
4342 # new() uses the default return type and there is no return statement
4343 var lines =<< trim END
4344 vim9script
4345
4346 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004347 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004348
4349 def new(this._bufnr)
4350 if !bufexists(this._bufnr)
4351 this._bufnr = -1
4352 endif
4353 enddef
4354 endclass
4355
4356 var c = C.new(12345)
4357 assert_equal('object<C>', typename(c))
4358
4359 var v1: C
4360 v1 = C.new(12345)
4361 assert_equal('object<C>', typename(v1))
4362
4363 def F()
4364 var v2: C
4365 v2 = C.new(12345)
4366 assert_equal('object<C>', typename(v2))
4367 enddef
4368 F()
4369 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004370 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004371
4372 # new() uses the default return type and an empty 'return' statement
4373 lines =<< trim END
4374 vim9script
4375
4376 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004377 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004378
4379 def new(this._bufnr)
4380 if !bufexists(this._bufnr)
4381 this._bufnr = -1
4382 return
4383 endif
4384 enddef
4385 endclass
4386
4387 var c = C.new(12345)
4388 assert_equal('object<C>', typename(c))
4389
4390 var v1: C
4391 v1 = C.new(12345)
4392 assert_equal('object<C>', typename(v1))
4393
4394 def F()
4395 var v2: C
4396 v2 = C.new(12345)
4397 assert_equal('object<C>', typename(v2))
4398 enddef
4399 F()
4400 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004401 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004402
4403 # new() uses "any" return type and returns "this"
4404 lines =<< trim END
4405 vim9script
4406
4407 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004408 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004409
4410 def new(this._bufnr): any
4411 if !bufexists(this._bufnr)
4412 this._bufnr = -1
4413 return this
4414 endif
4415 enddef
4416 endclass
4417 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004418 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004419
4420 # new() uses 'Dict' return type and returns a Dict
4421 lines =<< trim END
4422 vim9script
4423
4424 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004425 var _state: dict<any>
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004426
4427 def new(): dict<any>
4428 this._state = {}
4429 return this._state
4430 enddef
4431 endclass
4432
4433 var c = C.new()
4434 assert_equal('object<C>', typename(c))
4435 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004436 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004437enddef
4438
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004439" Test for checking a member initialization type at run time.
4440def Test_runtime_type_check_for_member_init()
4441 var lines =<< trim END
4442 vim9script
4443
4444 var retnum: bool = false
4445
4446 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004447 retnum = !retnum
4448 if retnum
4449 return 1
4450 else
4451 return "hello"
4452 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004453 enddef
4454
4455 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004456 var _foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004457 endclass
4458
4459 var c1 = C.new()
4460 var c2 = C.new()
4461 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004462 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004463enddef
4464
4465" Test for locking a variable referring to an object and reassigning to another
4466" object.
Ernie Raelee865f32023-09-29 19:53:55 +02004467def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004468 var lines =<< trim END
4469 vim9script
4470
4471 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004472 var val: number
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004473 def new(this.val)
4474 enddef
4475 endclass
4476
4477 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
4478 lockvar 2 some_dict
4479
4480 var current: C
4481 current = some_dict['c']
4482 assert_equal(3, current.val)
4483 current = some_dict['b']
4484 assert_equal(2, current.val)
4485
4486 def F()
4487 current = some_dict['c']
4488 enddef
4489
4490 def G()
4491 current = some_dict['b']
4492 enddef
4493
4494 F()
4495 assert_equal(3, current.val)
4496 G()
4497 assert_equal(2, current.val)
4498 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004499 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004500enddef
4501
Ernie Raelee865f32023-09-29 19:53:55 +02004502" Test trying to lock an object variable from various places
4503def Test_lockvar_object_variable()
4504 # An object variable lockvar has several cases:
4505 # object method, scriptlevel, scriplevel from :def, :def arg
4506 # method arg, static method arg.
4507 # Also different depths
4508
Ernie Raelee865f32023-09-29 19:53:55 +02004509 #
4510 # lockvar of read-only object variable
4511 #
4512
4513 # read-only lockvar from object method
4514 var lines =<< trim END
4515 vim9script
4516
4517 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004518 var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004519 def Lock()
4520 lockvar this.val1
4521 enddef
4522 endclass
4523 var o = C.new(3)
4524 o.Lock()
4525 END
Ernie Rael64885642023-10-04 20:16:22 +02004526 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004527
4528 # read-only lockvar from scriptlevel
4529 lines =<< trim END
4530 vim9script
4531
4532 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004533 var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004534 endclass
4535 var o = C.new(3)
4536 lockvar o.val2
4537 END
4538 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
4539
4540 # read-only lockvar of scriptlevel variable from def
4541 lines =<< trim END
4542 vim9script
4543
4544 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004545 var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004546 endclass
4547 var o = C.new(3)
4548 def Lock()
4549 lockvar o.val3
4550 enddef
4551 Lock()
4552 END
4553 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
4554
4555 # read-only lockvar of def argument variable
4556 lines =<< trim END
4557 vim9script
4558
4559 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004560 var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004561 endclass
4562 def Lock(o: C)
4563 lockvar o.val4
4564 enddef
4565 Lock(C.new(3))
4566 END
4567 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
4568
Ernie Raelee865f32023-09-29 19:53:55 +02004569 # read-only lockvar from object method arg
4570 lines =<< trim END
4571 vim9script
4572
4573 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004574 var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004575 def Lock(c: C)
4576 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004577 enddef
4578 endclass
4579 var o = C.new(3)
4580 o.Lock(C.new(5))
4581 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004582 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004583
4584 # read-only lockvar from class method arg
4585 lines =<< trim END
4586 vim9script
4587
4588 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004589 var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004590 static def Lock(c: C)
4591 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004592 enddef
4593 endclass
4594 var o = C.new(3)
4595 C.Lock(o)
4596 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004597 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004598
4599 #
4600 # lockvar of public object variable
4601 #
4602
4603 # lockvar from object method
4604 lines =<< trim END
4605 vim9script
4606
4607 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004608 public var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004609 def Lock()
4610 lockvar this.val1
4611 enddef
4612 endclass
4613 var o = C.new(3)
4614 o.Lock()
4615 END
4616 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
4617
4618 # lockvar from scriptlevel
4619 lines =<< trim END
4620 vim9script
4621
4622 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004623 public var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004624 endclass
4625 var o = C.new(3)
4626 lockvar o.val2
4627 END
4628 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
4629
4630 # lockvar of scriptlevel variable from def
4631 lines =<< trim END
4632 vim9script
4633
4634 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004635 public var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004636 endclass
4637 var o = C.new(3)
4638 def Lock()
4639 lockvar o.val3
4640 enddef
4641 Lock()
4642 END
4643 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
4644
4645 # lockvar of def argument variable
4646 lines =<< trim END
4647 vim9script
4648
4649 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004650 public var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004651 endclass
4652 def Lock(o: C)
4653 lockvar o.val4
4654 enddef
4655 Lock(C.new(3))
4656 END
4657 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
4658
4659 # lockvar from object method arg
4660 lines =<< trim END
4661 vim9script
4662
4663 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004664 public var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004665 def Lock(c: C)
4666 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004667 enddef
4668 endclass
4669 var o = C.new(3)
4670 o.Lock(C.new(5))
4671 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004672 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004673
4674 # lockvar from class method arg
4675 lines =<< trim END
4676 vim9script
4677
4678 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004679 public var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004680 static def Lock(c: C)
4681 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004682 enddef
4683 endclass
4684 var o = C.new(3)
4685 C.Lock(o)
4686 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004687 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004688enddef
4689
4690" Test trying to lock a class variable from various places
4691def Test_lockvar_class_variable()
4692
4693 # lockvar bare static from object method
4694 var lines =<< trim END
4695 vim9script
4696
4697 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004698 public static var sval1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004699 def Lock()
4700 lockvar sval1
4701 enddef
4702 endclass
4703 var o = C.new()
4704 o.Lock()
4705 END
4706 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
4707
4708 # lockvar C.static from object method
4709 lines =<< trim END
4710 vim9script
4711
4712 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004713 public static var sval2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004714 def Lock()
4715 lockvar C.sval2
4716 enddef
4717 endclass
4718 var o = C.new()
4719 o.Lock()
4720 END
4721 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
4722
4723 # lockvar bare static from class method
4724 lines =<< trim END
4725 vim9script
4726
4727 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004728 public static var sval3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004729 static def Lock()
4730 lockvar sval3
4731 enddef
4732 endclass
4733 C.Lock()
4734 END
4735 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
4736
4737 # lockvar C.static from class method
4738 lines =<< trim END
4739 vim9script
4740
4741 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004742 public static var sval4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004743 static def Lock()
4744 lockvar C.sval4
4745 enddef
4746 endclass
4747 C.Lock()
4748 END
4749 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
4750
4751 # lockvar C.static from script level
4752 lines =<< trim END
4753 vim9script
4754
4755 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004756 public static var sval5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004757 endclass
4758 lockvar C.sval5
4759 END
4760 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
4761
4762 # lockvar o.static from script level
4763 lines =<< trim END
4764 vim9script
4765
4766 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004767 public static var sval6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004768 endclass
4769 var o = C.new()
4770 lockvar o.sval6
4771 END
4772 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
4773enddef
4774
4775" Test locking an argument to :def
4776def Test_lockvar_argument()
4777 # Lockvar a function arg
4778 var lines =<< trim END
4779 vim9script
4780
4781 def Lock(val: any)
4782 lockvar val
4783 enddef
4784
4785 var d = {a: 1, b: 2}
4786 Lock(d)
4787
4788 d->extend({c: 3})
4789 END
4790 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
4791
4792 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
4793 # class member in "C". This tests lval_root_is_arg.
4794 lines =<< trim END
4795 vim9script
4796
4797 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004798 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004799 endclass
4800
4801 def Lock2(sval: any)
4802 lockvar sval
4803 enddef
4804
4805 var o = C.new()
4806 Lock2(o)
4807 END
4808 v9.CheckSourceSuccess(lines)
4809
4810 # Lock a class.
4811 lines =<< trim END
4812 vim9script
4813
4814 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004815 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004816 endclass
4817
4818 def Lock2(sval: any)
4819 lockvar sval
4820 enddef
4821
4822 Lock2(C)
4823 END
Ernie Raelb077b582023-12-14 20:11:44 +01004824 v9.CheckSourceFailure(lines, 'E1405: Class "C" cannot be used as a value')
Ernie Raelee865f32023-09-29 19:53:55 +02004825
4826 # Lock an object.
4827 lines =<< trim END
4828 vim9script
4829
4830 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004831 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004832 endclass
4833
4834 def Lock2(sval: any)
4835 lockvar sval
4836 enddef
4837
4838 Lock2(C.new())
4839 END
4840 v9.CheckSourceSuccess(lines)
4841
4842 # In this case (unlike previous) "lockvar sval" is a class member.
4843 lines =<< trim END
4844 vim9script
4845
4846 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004847 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004848 def Lock2()
4849 lockvar sval
4850 enddef
4851 endclass
4852
4853
4854 var o = C.new()
4855 o.Lock2()
4856 END
4857 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4858enddef
4859
4860" Test that this can be locked without error
4861def Test_lockvar_this()
4862 # lockvar this
4863 var lines =<< trim END
4864 vim9script
4865 class C
4866 def TLock()
4867 lockvar this
4868 enddef
4869 endclass
4870 var o = C.new()
4871 o.TLock()
4872 END
4873 v9.CheckSourceSuccess(lines)
4874
4875 # lockvar four (four letter word, but not this)
4876 lines =<< trim END
4877 vim9script
4878 class C
4879 def TLock4()
4880 var four: number
4881 lockvar four
4882 enddef
4883 endclass
4884 var o = C.new()
4885 o.TLock4()
4886 END
4887 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4888
4889 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4890 lines =<< trim END
4891 vim9script
4892 class C
4893 def TLock5()
4894 var this5: number
4895 lockvar this5
4896 enddef
4897 endclass
4898 var o = C.new()
4899 o.TLock5()
4900 END
4901 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4902enddef
4903
4904" Test some general lockvar cases
4905def Test_lockvar_general()
4906 # lockvar an object and a class. It does nothing
4907 var lines =<< trim END
4908 vim9script
4909 class C
4910 endclass
4911 var o = C.new()
4912 lockvar o
4913 lockvar C
4914 END
4915 v9.CheckSourceSuccess(lines)
4916
4917 # Lock a list element that's nested in an object variable from a :def
4918 lines =<< trim END
4919 vim9script
4920
4921 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004922 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004923 endclass
4924 def Lock2(obj: any)
4925 lockvar obj.val[1]
4926 enddef
4927
4928 var o = C.new()
4929 Lock2(o)
4930 o.val[0] = [9]
4931 assert_equal([ [9], [2], [3] ], o.val)
4932 try
4933 o.val[1] = [999]
4934 call assert_false(true, 'assign should have failed')
4935 catch
4936 assert_exception('E741:')
4937 endtry
4938 o.val[2] = [8]
4939 assert_equal([ [9], [2], [8] ], o.val)
4940 END
4941 v9.CheckSourceSuccess(lines)
4942
4943 # Lock a list element that's nested in an object variable from scriptlevel
4944 lines =<< trim END
4945 vim9script
4946
4947 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004948 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004949 endclass
4950
4951 var o = C.new()
4952 lockvar o.val[1]
4953 o.val[0] = [9]
4954 assert_equal([ [9], [2], [3] ], o.val)
4955 try
4956 o.val[1] = [999]
4957 call assert_false(true, 'assign should have failed')
4958 catch
4959 assert_exception('E741:')
4960 endtry
4961 o.val[2] = [8]
4962 assert_equal([ [9], [2], [8] ], o.val)
4963 END
4964 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004965
4966 # lock a script level variable from an object method
4967 lines =<< trim END
4968 vim9script
4969
4970 class C
4971 def Lock()
4972 lockvar l
4973 enddef
4974 endclass
4975
4976 var l = [1]
4977 C.new().Lock()
4978 l[0] = 11
4979 END
4980 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4981
Ernie Rael03042a22023-11-11 08:53:32 +01004982 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004983 # in an object fetched via a script level list
4984 lines =<< trim END
4985 vim9script
4986
4987 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004988 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004989 def Lock()
4990 lockvar lc[0]._v1[1]
4991 enddef
4992 endclass
4993
4994 var l = [[1], [2], [3]]
4995 var o = C.new(l)
4996 var lc: list<C> = [ o ]
4997
4998 o.Lock()
4999 l[0] = [22]
5000 l[1] = [33]
5001 END
5002 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
5003
5004 # similar to the previous test, except the locking code is executing
Ernie Rael03042a22023-11-11 08:53:32 +01005005 # in a class that does not own the protected variable.
5006 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02005007 # the same name.
5008 lines =<< trim END
5009 vim9script
5010
5011 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01005012 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02005013 def Lock(obj: any)
5014 lockvar lc[0]._v1[1]
5015 enddef
5016 endclass
5017
5018 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005019 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02005020 endclass
5021
5022 var l = [[1], [2], [3]]
5023 var o = C.new(l)
5024 var lc: list<C> = [ o ]
5025
5026 var o2 = C2.new()
5027 o2.Lock(o)
5028 END
Ernie Rael03042a22023-11-11 08:53:32 +01005029 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02005030enddef
5031
Ernie Rael9771b2a2023-10-07 22:05:40 +02005032" Test builtin islocked()
5033def Test_lockvar_islocked()
5034 # Can't lock class/object variable
5035 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01005036 # Lock item of variable's value (a list item)
5037 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02005038 var lines =<< trim END
5039 vim9script
5040
5041 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005042 var o0: list<list<number>> = [ [0], [1], [2]]
5043 var o1: list<list<number>> = [[10], [11], [12]]
5044 static var c0: list<list<number>> = [[20], [21], [22]]
5045 static var c1: list<list<number>> = [[30], [31], [32]]
Ernie Rael9771b2a2023-10-07 22:05:40 +02005046 endclass
5047
5048 def LockIt(arg: any)
5049 lockvar arg
5050 enddef
5051
5052 def UnlockIt(arg: any)
5053 unlockvar arg
5054 enddef
5055
5056 var obj = C.new()
5057 #lockvar obj.o1 # can't lock something you can't write to
5058
5059 try
5060 lockvar obj.o1 # can't lock something you can't write to
5061 call assert_false(1, '"lockvar obj.o1" should have failed')
5062 catch
5063 call assert_exception('E1335:')
5064 endtry
5065
5066 LockIt(obj.o1) # but can lock it's value
5067 assert_equal(1, islocked("obj.o1"))
5068 assert_equal(1, islocked("obj.o1[0]"))
5069 assert_equal(1, islocked("obj.o1[1]"))
5070 UnlockIt(obj.o1)
5071 assert_equal(0, islocked("obj.o1"))
5072 assert_equal(0, islocked("obj.o1[0]"))
5073
5074 lockvar obj.o1[0]
5075 assert_equal(0, islocked("obj.o1"))
5076 assert_equal(1, islocked("obj.o1[0]"))
5077 assert_equal(0, islocked("obj.o1[1]"))
5078 unlockvar obj.o1[0]
5079 assert_equal(0, islocked("obj.o1"))
5080 assert_equal(0, islocked("obj.o1[0]"))
5081
5082 # Same thing, but with a static
5083
5084 try
5085 lockvar C.c1 # can't lock something you can't write to
5086 call assert_false(1, '"lockvar C.c1" should have failed')
5087 catch
5088 call assert_exception('E1335:')
5089 endtry
5090
5091 LockIt(C.c1) # but can lock it's value
5092 assert_equal(1, islocked("C.c1"))
5093 assert_equal(1, islocked("C.c1[0]"))
5094 assert_equal(1, islocked("C.c1[1]"))
5095 UnlockIt(C.c1)
5096 assert_equal(0, islocked("C.c1"))
5097 assert_equal(0, islocked("C.c1[0]"))
5098
5099 lockvar C.c1[0]
5100 assert_equal(0, islocked("C.c1"))
5101 assert_equal(1, islocked("C.c1[0]"))
5102 assert_equal(0, islocked("C.c1[1]"))
5103 unlockvar C.c1[0]
5104 assert_equal(0, islocked("C.c1"))
5105 assert_equal(0, islocked("C.c1[0]"))
5106 END
5107 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02005108
5109 # Do islocked() from an object method
5110 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02005111 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02005112 vim9script
5113
5114 var l0o0 = [ [0], [1], [2]]
5115 var l0o1 = [ [10], [11], [12]]
5116 var l0c0 = [[120], [121], [122]]
5117 var l0c1 = [[130], [131], [132]]
5118
5119 class C0
Doug Kearns74da0ee2023-12-14 20:26:26 +01005120 var o0: list<list<number>> = l0o0
5121 var o1: list<list<number>> = l0o1
5122 static var c0: list<list<number>> = l0c0
5123 static var c1: list<list<number>> = l0c1
Ernie Rael4c8da022023-10-11 21:35:11 +02005124 def Islocked(arg: string): number
5125 return islocked(arg)
5126 enddef
5127 static def SIslocked(arg: string): number
5128 return islocked(arg)
5129 enddef
5130 endclass
5131
5132 var l2o0 = [[20000], [20001], [20002]]
5133 var l2o1 = [[20010], [20011], [20012]]
5134 var l2c0 = [[20120], [20121], [20122]]
5135 var l2c1 = [[20130], [20131], [20132]]
5136
5137 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01005138 var o0: list<list<number>> = l2o0
5139 var o1: list<list<number>> = l2o1
5140 static var c0: list<list<number>> = l2c0
5141 static var c1: list<list<number>> = l2c1
Ernie Rael4c8da022023-10-11 21:35:11 +02005142 def Islocked(arg: string): number
5143 return islocked(arg)
5144 enddef
5145 static def SIslocked(arg: string): number
5146 return islocked(arg)
5147 enddef
5148 endclass
5149
5150 var obj0 = C0.new()
5151 var obj2 = C2.new()
5152
5153 var l = [ obj0, null_object, obj2 ]
5154
5155 # lock list, object func access through script var expr
5156 assert_equal(0, obj0.Islocked("l[0].o0"))
5157 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
5158 lockvar l0o0
5159 assert_equal(1, obj0.Islocked("l[0].o0"))
5160 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
5161
5162 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
5163
5164 # lock list element, object func access through script var expr
5165 lockvar l0o1[1]
5166 assert_equal(0, obj0.Islocked("this.o1[0]"))
5167 assert_equal(1, obj0.Islocked("this.o1[1]"))
5168
5169 assert_equal(0, obj0.Islocked("this.o1"))
5170 lockvar l0o1
5171 assert_equal(1, obj0.Islocked("this.o1"))
5172 unlockvar l0o1
5173
5174 lockvar l0c1[1]
5175
5176 # static by class name member expr from same class
5177 assert_equal(0, obj0.Islocked("C0.c1[0]"))
5178 assert_equal(1, obj0.Islocked("C0.c1[1]"))
5179 # static by bare name member expr from same class
5180 assert_equal(0, obj0.Islocked("c1[0]"))
5181 assert_equal(1, obj0.Islocked("c1[1]"))
5182
5183 # static by class name member expr from other class
5184 assert_equal(0, obj2.Islocked("C0.c1[0]"))
5185 assert_equal(1, obj2.Islocked("C0.c1[1]"))
5186 # static by bare name member expr from other class
5187 assert_equal(0, obj2.Islocked("c1[0]"))
5188 assert_equal(0, obj2.Islocked("c1[1]"))
5189
5190
5191 # static by bare name in same class
5192 assert_equal(0, obj0.Islocked("c0"))
5193 lockvar l0c0
5194 assert_equal(1, obj0.Islocked("c0"))
5195
5196 #
5197 # similar stuff, but use static method
5198 #
5199
5200 unlockvar l0o0
5201
5202 # lock list, object func access through script var expr
5203 assert_equal(0, C0.SIslocked("l[0].o0"))
5204 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
5205 lockvar l0o0
5206 assert_equal(1, C0.SIslocked("l[0].o0"))
5207 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
5208
5209 unlockvar l0o1
5210
5211 # can't access "this" from class method
5212 try
5213 C0.SIslocked("this.o1[0]")
5214 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
5215 catch
5216 call assert_exception('E121: Undefined variable: this')
5217 endtry
5218
5219 lockvar l0c1[1]
5220
5221 # static by class name member expr from same class
5222 assert_equal(0, C0.SIslocked("C0.c1[0]"))
5223 assert_equal(1, C0.SIslocked("C0.c1[1]"))
5224 # static by bare name member expr from same class
5225 assert_equal(0, C0.SIslocked("c1[0]"))
5226 assert_equal(1, C0.SIslocked("c1[1]"))
5227
5228 # static by class name member expr from other class
5229 assert_equal(0, C2.SIslocked("C0.c1[0]"))
5230 assert_equal(1, C2.SIslocked("C0.c1[1]"))
5231 # static by bare name member expr from other class
5232 assert_equal(0, C2.SIslocked("c1[0]"))
5233 assert_equal(0, C2.SIslocked("c1[1]"))
5234
5235
5236 # static by bare name in same class
5237 unlockvar l0c0
5238 assert_equal(0, C0.SIslocked("c0"))
5239 lockvar l0c0
5240 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02005241 END
Ernie Rael4c8da022023-10-11 21:35:11 +02005242 v9.CheckSourceSuccess(lines)
5243
5244 # Check islocked class/object from various places.
5245 lines =<< trim END
5246 vim9script
5247
5248 class C
5249 def Islocked(arg: string): number
5250 return islocked(arg)
5251 enddef
5252 static def SIslocked(arg: string): number
5253 return islocked(arg)
5254 enddef
5255 endclass
5256 var obj = C.new()
5257
5258 # object method
5259 assert_equal(0, obj.Islocked("this"))
5260 assert_equal(0, obj.Islocked("C"))
5261
5262 # class method
5263 ### assert_equal(0, C.SIslocked("this"))
5264 assert_equal(0, C.SIslocked("C"))
5265
5266 #script level
5267 var v: number
5268 v = islocked("C")
5269 assert_equal(0, v)
5270 v = islocked("obj")
5271 assert_equal(0, v)
5272 END
5273 v9.CheckSourceSuccess(lines)
5274enddef
5275
5276def Test_lockvar_islocked_notfound()
5277 # Try non-existent things
5278 var lines =<< trim END
5279 vim9script
5280
5281 class C
5282 def Islocked(arg: string): number
5283 return islocked(arg)
5284 enddef
5285 static def SIslocked(arg: string): number
5286 return islocked(arg)
5287 enddef
5288 endclass
5289 var obj = C.new()
5290 assert_equal(-1, obj.Islocked("anywhere"))
5291 assert_equal(-1, C.SIslocked("notanywhere"))
5292 END
5293 v9.CheckSourceSuccess(lines)
5294
5295 # Something not found of the form "name1.name2" is an error
5296 lines =<< trim END
5297 vim9script
5298
5299 islocked("one.two")
5300 END
5301 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
5302
5303 lines =<< trim END
5304 vim9script
5305
5306 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005307 var val = { key: "value" }
Ernie Rael4c8da022023-10-11 21:35:11 +02005308 def Islocked(arg: string): number
5309 return islocked(arg)
5310 enddef
5311 endclass
5312 var obj = C.new()
5313 obj.Islocked("this.val.not_there"))
5314 END
5315 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
5316
5317 lines =<< trim END
5318 vim9script
5319
5320 class C
5321 def Islocked(arg: string): number
5322 return islocked(arg)
5323 enddef
5324 endclass
5325 var obj = C.new()
5326 obj.Islocked("this.notobjmember")
5327 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005328 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02005329
5330 # access a script variable through methods
5331 lines =<< trim END
5332 vim9script
5333
5334 var l = [1]
5335 class C
5336 def Islocked(arg: string): number
5337 return islocked(arg)
5338 enddef
5339 static def SIslocked(arg: string): number
5340 return islocked(arg)
5341 enddef
5342 endclass
5343 var obj = C.new()
5344 assert_equal(0, obj.Islocked("l"))
5345 assert_equal(0, C.SIslocked("l"))
5346 lockvar l
5347 assert_equal(1, obj.Islocked("l"))
5348 assert_equal(1, C.SIslocked("l"))
5349 END
5350 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02005351enddef
5352
Ernie Rael03042a22023-11-11 08:53:32 +01005353" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005354def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005355 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005356 var lines =<< trim END
5357 vim9script
5358
5359 class A
5360 def _Foo(): number
5361 return 1234
5362 enddef
5363 endclass
5364 var a = A.new()
5365 a._Foo()
5366 END
Ernie Rael03042a22023-11-11 08:53:32 +01005367 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005368
Ernie Rael03042a22023-11-11 08:53:32 +01005369 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005370 lines =<< trim END
5371 vim9script
5372
5373 class A
5374 def _Foo(): number
5375 return 1234
5376 enddef
5377 endclass
5378 def T()
5379 var a = A.new()
5380 a._Foo()
5381 enddef
5382 T()
5383 END
Ernie Rael03042a22023-11-11 08:53:32 +01005384 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005385
Ernie Rael03042a22023-11-11 08:53:32 +01005386 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005387 lines =<< trim END
5388 vim9script
5389
5390 class A
5391 def _Foo(): number
5392 return 1234
5393 enddef
5394 def Bar(): number
5395 return this._Foo()
5396 enddef
5397 endclass
5398 var a = A.new()
5399 assert_equal(1234, a.Bar())
5400 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005401 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005402
Ernie Rael03042a22023-11-11 08:53:32 +01005403 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005404 lines =<< trim END
5405 vim9script
5406
5407 class A
5408 def _Foo(): number
5409 return 1234
5410 enddef
5411 def Bar(): number
5412 return this._Foo()
5413 enddef
5414 endclass
5415 def T()
5416 var a = A.new()
5417 assert_equal(1234, a.Bar())
5418 enddef
5419 T()
5420 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005421 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005422
Ernie Rael03042a22023-11-11 08:53:32 +01005423 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005424 lines =<< trim END
5425 vim9script
5426
5427 class A
5428 def _Foo(): number
5429 return 1234
5430 enddef
5431 def Bar(): number
5432 return _Foo()
5433 enddef
5434 endclass
5435 var a = A.new()
5436 a.Bar()
5437 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005438 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005439
Ernie Rael03042a22023-11-11 08:53:32 +01005440 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005441 lines =<< trim END
5442 vim9script
5443
5444 class A
5445 def _Foo(): number
5446 return 1234
5447 enddef
5448 endclass
5449 A._Foo()
5450 END
Ernie Rael03042a22023-11-11 08:53:32 +01005451 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005452
Ernie Rael03042a22023-11-11 08:53:32 +01005453 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005454 lines =<< trim END
5455 vim9script
5456
5457 class A
5458 def _Foo()
5459 enddef
5460 def _Foo()
5461 enddef
5462 endclass
5463 var a = A.new()
5464 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005465 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005466
Ernie Rael03042a22023-11-11 08:53:32 +01005467 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005468 lines =<< trim END
5469 vim9script
5470
5471 class A
5472 def _Foo()
5473 enddef
5474 def Foo()
5475 enddef
5476 endclass
5477 var a = A.new()
5478 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005479 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005480
Ernie Rael03042a22023-11-11 08:53:32 +01005481 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005482 lines =<< trim END
5483 vim9script
5484
5485 class A
5486 def Foo()
5487 enddef
5488 def _Foo()
5489 enddef
5490 endclass
5491 var a = A.new()
5492 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005493 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005494
Ernie Rael03042a22023-11-11 08:53:32 +01005495 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005496 lines =<< trim END
5497 vim9script
5498
5499 class A
5500 def Foo(): number
5501 return 100
5502 enddef
5503 def _Bar(): number
5504 return 200
5505 enddef
5506 def _Baz()
5507 assert_equal(100, this.Foo())
5508 assert_equal(200, this._Bar())
5509 enddef
5510 def T()
5511 this._Baz()
5512 enddef
5513 endclass
5514 var a = A.new()
5515 a.T()
5516 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005517 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005518
Ernie Rael03042a22023-11-11 08:53:32 +01005519 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005520 lines =<< trim END
5521 vim9script
5522
5523 class A
5524 def _Foo(): number
5525 return 100
5526 enddef
5527 endclass
5528 class B
5529 def Foo(): number
5530 var a = A.new()
5531 a._Foo()
5532 enddef
5533 endclass
5534 var b = B.new()
5535 b.Foo()
5536 END
Ernie Rael03042a22023-11-11 08:53:32 +01005537 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005538
Ernie Rael03042a22023-11-11 08:53:32 +01005539 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005540 lines =<< trim END
5541 vim9script
5542 class A
5543 def _Foo(): number
5544 return 1234
5545 enddef
5546 endclass
5547 class B extends A
5548 def Bar()
5549 enddef
5550 endclass
5551 class C extends B
5552 def Baz(): number
5553 return this._Foo()
5554 enddef
5555 endclass
5556 var c = C.new()
5557 assert_equal(1234, c.Baz())
5558 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005559 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005560
Ernie Rael03042a22023-11-11 08:53:32 +01005561 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005562 lines =<< trim END
5563 vim9script
5564 class A
5565 def _Foo(): number
5566 return 1234
5567 enddef
5568 endclass
5569 class B extends A
5570 def Bar()
5571 enddef
5572 endclass
5573 class C extends B
5574 def Baz(): number
5575 enddef
5576 endclass
5577 var c = C.new()
5578 assert_equal(1234, c._Foo())
5579 END
Ernie Rael03042a22023-11-11 08:53:32 +01005580 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005581
5582 # Using "_" prefix in a method name should fail outside of a class
5583 lines =<< trim END
5584 vim9script
5585 def _Foo(): number
5586 return 1234
5587 enddef
5588 var a = _Foo()
5589 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005590 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005591enddef
5592
Ernie Rael03042a22023-11-11 08:53:32 +01005593" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005594def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005595 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005596 var lines =<< trim END
5597 vim9script
5598
5599 class A
5600 static def _Foo(): number
5601 return 1234
5602 enddef
5603 endclass
5604 A._Foo()
5605 END
Ernie Rael03042a22023-11-11 08:53:32 +01005606 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005607
Ernie Rael03042a22023-11-11 08:53:32 +01005608 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005609 lines =<< trim END
5610 vim9script
5611
5612 class A
5613 static def _Foo(): number
5614 return 1234
5615 enddef
5616 endclass
5617 def T()
5618 A._Foo()
5619 enddef
5620 T()
5621 END
Ernie Rael03042a22023-11-11 08:53:32 +01005622 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005623
Ernie Rael03042a22023-11-11 08:53:32 +01005624 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005625 lines =<< trim END
5626 vim9script
5627
5628 class A
5629 static def _Foo(): number
5630 return 1234
5631 enddef
5632 endclass
5633 var a = A.new()
5634 a._Foo()
5635 END
Ernie Rael03042a22023-11-11 08:53:32 +01005636 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005637
Ernie Rael03042a22023-11-11 08:53:32 +01005638 # Try calling a class protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005639 lines =<< trim END
5640 vim9script
5641
5642 class A
5643 static def _Foo(): number
5644 return 1234
5645 enddef
5646 endclass
5647 def T()
5648 var a = A.new()
5649 a._Foo()
5650 enddef
5651 T()
5652 END
Ernie Rael03042a22023-11-11 08:53:32 +01005653 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005654
Ernie Rael03042a22023-11-11 08:53:32 +01005655 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005656 lines =<< trim END
5657 vim9script
5658
5659 class A
5660 static def _Foo(): number
5661 return 1234
5662 enddef
5663 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005664 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005665 enddef
5666 endclass
5667 var a = A.new()
5668 a.Bar()
5669 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005670 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005671
Ernie Rael03042a22023-11-11 08:53:32 +01005672 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005673 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005674 lines =<< trim END
5675 vim9script
5676
5677 class A
5678 static def _Foo1(): number
5679 return 1234
5680 enddef
5681 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005682 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005683 enddef
5684 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005685 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005686 enddef
5687 endclass
5688 var a = A.new()
5689 a.Bar()
5690 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005691 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005692
Ernie Rael03042a22023-11-11 08:53:32 +01005693 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005694 lines =<< trim END
5695 vim9script
5696
5697 class A
5698 static def _Foo()
5699 enddef
5700 static def Foo()
5701 enddef
5702 endclass
5703 var a = A.new()
5704 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005705 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005706
Ernie Rael03042a22023-11-11 08:53:32 +01005707 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005708 lines =<< trim END
5709 vim9script
5710
5711 class A
5712 static def _Foo(): number
5713 return 1234
5714 enddef
5715 endclass
5716 class B
5717 def Foo(): number
5718 return A._Foo()
5719 enddef
5720 endclass
5721 var b = B.new()
5722 assert_equal(1234, b.Foo())
5723 END
Ernie Rael03042a22023-11-11 08:53:32 +01005724 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005725
Ernie Rael03042a22023-11-11 08:53:32 +01005726 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005727 lines =<< trim END
5728 vim9script
5729 class A
5730 static def _Foo(): number
5731 return 1234
5732 enddef
5733 endclass
5734 class B extends A
5735 def Bar()
5736 enddef
5737 endclass
5738 class C extends B
5739 def Baz(): number
5740 return A._Foo()
5741 enddef
5742 endclass
5743 var c = C.new()
5744 assert_equal(1234, c.Baz())
5745 END
Ernie Rael03042a22023-11-11 08:53:32 +01005746 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005747
Ernie Rael03042a22023-11-11 08:53:32 +01005748 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005749 lines =<< trim END
5750 vim9script
5751 class A
5752 static def _Foo(): number
5753 return 1234
5754 enddef
5755 endclass
5756 class B extends A
5757 def Bar()
5758 enddef
5759 endclass
5760 class C extends B
5761 static def Baz(): number
5762 return A._Foo()
5763 enddef
5764 endclass
5765 assert_equal(1234, C.Baz())
5766 END
Ernie Rael03042a22023-11-11 08:53:32 +01005767 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005768
Ernie Rael03042a22023-11-11 08:53:32 +01005769 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005770 lines =<< trim END
5771 vim9script
5772 class A
5773 static def _Foo(): number
5774 return 1234
5775 enddef
5776 endclass
5777 class B extends A
5778 def Bar()
5779 enddef
5780 endclass
5781 class C extends B
5782 def Baz(): number
5783 enddef
5784 endclass
5785 var c = C.new()
5786 assert_equal(1234, C._Foo())
5787 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005788 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005789enddef
5790
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005791" Test for using the return value of a class/object method as a function
5792" argument.
5793def Test_objmethod_funcarg()
5794 var lines =<< trim END
5795 vim9script
5796
5797 class C
5798 def Foo(): string
5799 return 'foo'
5800 enddef
5801 endclass
5802
5803 def Bar(a: number, s: string): string
5804 return s
5805 enddef
5806
5807 def Baz(c: C)
5808 assert_equal('foo', Bar(10, c.Foo()))
5809 enddef
5810
5811 var t = C.new()
5812 Baz(t)
5813 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005814 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005815
5816 lines =<< trim END
5817 vim9script
5818
5819 class C
5820 static def Foo(): string
5821 return 'foo'
5822 enddef
5823 endclass
5824
5825 def Bar(a: number, s: string): string
5826 return s
5827 enddef
5828
5829 def Baz()
5830 assert_equal('foo', Bar(10, C.Foo()))
5831 enddef
5832
5833 Baz()
5834 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005835 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005836enddef
5837
Ernie Raelcf138d42023-09-06 20:45:03 +02005838def Test_static_inheritence()
5839 # subclasses get their own static copy
5840 var lines =<< trim END
5841 vim9script
5842
5843 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005844 static var _svar: number
5845 var _mvar: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005846 def new()
5847 _svar = 1
5848 this._mvar = 101
5849 enddef
5850 def AccessObject(): number
5851 return this._mvar
5852 enddef
5853 def AccessStaticThroughObject(): number
5854 return _svar
5855 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005856 endclass
5857
5858 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005859 def new()
5860 this._mvar = 102
5861 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005862 endclass
5863
5864 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005865 def new()
5866 this._mvar = 103
5867 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005868
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005869 def AccessPrivateStaticThroughClassName(): number
5870 assert_equal(1, A._svar)
5871 return 444
5872 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005873 endclass
5874
5875 var oa = A.new()
5876 var ob = B.new()
5877 var oc = C.new()
5878 assert_equal(101, oa.AccessObject())
5879 assert_equal(102, ob.AccessObject())
5880 assert_equal(103, oc.AccessObject())
5881
Ernie Rael03042a22023-11-11 08:53:32 +01005882 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005883
5884 # verify object properly resolves to correct static
5885 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005886 assert_equal(1, ob.AccessStaticThroughObject())
5887 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005888 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005889 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005890enddef
5891
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005892" Test for declaring duplicate object and class members
5893def Test_dup_member_variable()
5894 # Duplicate member variable
5895 var lines =<< trim END
5896 vim9script
5897 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005898 var val = 10
5899 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005900 endclass
5901 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005902 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005903
Ernie Rael03042a22023-11-11 08:53:32 +01005904 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005905 lines =<< trim END
5906 vim9script
5907 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005908 var _val = 10
5909 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005910 endclass
5911 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005912 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005913
5914 # Duplicate public member variable
5915 lines =<< trim END
5916 vim9script
5917 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005918 public var val = 10
5919 public var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005920 endclass
5921 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005922 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005923
Ernie Rael03042a22023-11-11 08:53:32 +01005924 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005925 lines =<< trim END
5926 vim9script
5927 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005928 var val = 10
5929 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005930 endclass
5931 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005932 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005933
Ernie Rael03042a22023-11-11 08:53:32 +01005934 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005935 lines =<< trim END
5936 vim9script
5937 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005938 var _val = 20
5939 public var val = 10
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005940 endclass
5941 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005942 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005943
5944 # Duplicate class member variable
5945 lines =<< trim END
5946 vim9script
5947 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005948 static var s: string = "abc"
5949 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005950 endclass
5951 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005952 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005953
Ernie Rael03042a22023-11-11 08:53:32 +01005954 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005955 lines =<< trim END
5956 vim9script
5957 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005958 public static var s: string = "abc"
5959 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005960 endclass
5961 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005962 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005963
5964 # Duplicate class and object member variable
5965 lines =<< trim END
5966 vim9script
5967 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005968 static var val = 10
5969 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005970 def new()
5971 enddef
5972 endclass
5973 var c = C.new()
5974 assert_equal(10, C.val)
5975 assert_equal(20, c.val)
5976 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005977 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005978
5979 # Duplicate object member variable in a derived class
5980 lines =<< trim END
5981 vim9script
5982 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005983 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005984 endclass
5985 class B extends A
5986 endclass
5987 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005988 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005989 endclass
5990 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005991 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005992
Ernie Rael03042a22023-11-11 08:53:32 +01005993 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005994 lines =<< trim END
5995 vim9script
5996 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005997 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005998 endclass
5999 class B extends A
6000 endclass
6001 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006002 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006003 endclass
6004 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006005 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006006
Ernie Rael03042a22023-11-11 08:53:32 +01006007 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006008 lines =<< trim END
6009 vim9script
6010 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006011 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006012 endclass
6013 class B extends A
6014 endclass
6015 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006016 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006017 endclass
6018 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006019 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006020
6021 # Duplicate object member variable in a derived class
6022 lines =<< trim END
6023 vim9script
6024 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006025 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006026 endclass
6027 class B extends A
6028 endclass
6029 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006030 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02006031 endclass
6032 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006033 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006034
6035 # Two member variables with a common prefix
6036 lines =<< trim END
6037 vim9script
6038 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006039 public static var svar2: number
6040 public static var svar: number
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006041 endclass
6042 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006043 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02006044enddef
6045
Ernie Rael03042a22023-11-11 08:53:32 +01006046" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006047def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01006048 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006049 var lines =<< trim END
6050 vim9script
6051 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006052 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006053 def GetVal(): number
6054 return this._val
6055 enddef
6056 endclass
6057 def T()
6058 var a = A.new()
6059 a._val = 20
6060 enddef
6061 T()
6062 END
Ernie Rael03042a22023-11-11 08:53:32 +01006063 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006064
Ernie Rael03042a22023-11-11 08:53:32 +01006065 # access a non-existing protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006066 lines =<< trim END
6067 vim9script
6068 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006069 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006070 endclass
6071 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006072 var a = A.new()
6073 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006074 enddef
6075 T()
6076 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02006077 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02006078
Ernie Rael03042a22023-11-11 08:53:32 +01006079 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02006080 lines =<< trim END
6081 vim9script
6082 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006083 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006084 endclass
6085 def T()
6086 var a = A.new()
6087 var x = a._val
6088 enddef
6089 T()
6090 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006091 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02006092
Ernie Rael03042a22023-11-11 08:53:32 +01006093 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02006094 lines =<< trim END
6095 vim9script
6096 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006097 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006098 endclass
6099 def T()
6100 var a = A.new()
6101 a._val = 3
6102 enddef
6103 T()
6104 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006105 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02006106
Ernie Rael03042a22023-11-11 08:53:32 +01006107 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02006108 lines =<< trim END
6109 vim9script
6110 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006111 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006112 endclass
6113 def T()
6114 var x = A._val
6115 enddef
6116 T()
6117 END
Ernie Rael03042a22023-11-11 08:53:32 +01006118 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02006119
Ernie Rael03042a22023-11-11 08:53:32 +01006120 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02006121 lines =<< trim END
6122 vim9script
6123 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006124 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006125 endclass
6126 def T()
6127 A._val = 3
6128 enddef
6129 T()
6130 END
Ernie Rael03042a22023-11-11 08:53:32 +01006131 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006132enddef
6133
6134" Test for changing the member access of an interface in a implementation class
6135def Test_change_interface_member_access()
6136 var lines =<< trim END
6137 vim9script
6138 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006139 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006140 endinterface
6141 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006142 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006143 endclass
6144 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006145 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006146
6147 lines =<< trim END
6148 vim9script
6149 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006150 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006151 endinterface
6152 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006153 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006154 endclass
6155 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006156 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006157enddef
6158
6159" Test for trying to change a readonly member from a def function
6160def Test_readonly_member_change_in_def_func()
6161 var lines =<< trim END
6162 vim9script
6163 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006164 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006165 endclass
6166 def T()
6167 var a = A.new()
6168 a.val = 20
6169 enddef
6170 T()
6171 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006172 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006173enddef
6174
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006175" Test for reading and writing a class member from a def function
6176def Test_modify_class_member_from_def_function()
6177 var lines =<< trim END
6178 vim9script
6179 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006180 var var1: number = 10
6181 public static var var2: list<number> = [1, 2]
6182 public static var var3: dict<number> = {a: 1, b: 2}
6183 static var _priv_var4: number = 40
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006184 endclass
6185 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02006186 assert_equal([1, 2], A.var2)
6187 assert_equal({a: 1, b: 2}, A.var3)
6188 A.var2 = [3, 4]
6189 A.var3 = {c: 3, d: 4}
6190 assert_equal([3, 4], A.var2)
6191 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael03042a22023-11-11 08:53:32 +01006192 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006193 enddef
6194 T()
6195 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006196 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006197enddef
6198
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006199" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006200def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006201 var lines =<< trim END
6202 vim9script
6203 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006204 public static var svar1: list<number> = [1]
6205 public static var svar2: list<number> = [2]
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006206 endclass
6207
6208 A.svar1->add(3)
6209 A.svar2->add(4)
6210 assert_equal([1, 3], A.svar1)
6211 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006212
6213 def Foo()
6214 A.svar1->add(7)
6215 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006216 assert_equal([1, 3, 7], A.svar1)
6217 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006218 enddef
6219 Foo()
6220 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006221 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006222
6223 # Cannot read from a class variable using an object in script context
6224 lines =<< trim END
6225 vim9script
6226 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006227 public var var1: number
6228 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006229 endclass
6230
6231 var a = A.new()
6232 echo a.svar2
6233 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006234 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006235
6236 # Cannot write to a class variable using an object in script context
6237 lines =<< trim END
6238 vim9script
6239 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006240 public var var1: number
6241 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006242 endclass
6243
6244 var a = A.new()
6245 a.svar2 = [2]
6246 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006247 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006248
6249 # Cannot read from a class variable using an object in def method context
6250 lines =<< trim END
6251 vim9script
6252 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006253 public var var1: number
6254 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006255 endclass
6256
6257 def T()
6258 var a = A.new()
6259 echo a.svar2
6260 enddef
6261 T()
6262 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006263 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006264
6265 # Cannot write to a class variable using an object in def method context
6266 lines =<< trim END
6267 vim9script
6268 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006269 public var var1: number
6270 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006271 endclass
6272
6273 def T()
6274 var a = A.new()
6275 a.svar2 = [2]
6276 enddef
6277 T()
6278 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006279 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006280enddef
6281
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006282" Test for using a interface method using a child object
6283def Test_interface_method_from_child()
6284 var lines =<< trim END
6285 vim9script
6286
6287 interface A
6288 def Foo(): string
6289 endinterface
6290
6291 class B implements A
6292 def Foo(): string
6293 return 'foo'
6294 enddef
6295 endclass
6296
6297 class C extends B
6298 def Bar(): string
6299 return 'bar'
6300 enddef
6301 endclass
6302
6303 def T1(a: A)
6304 assert_equal('foo', a.Foo())
6305 enddef
6306
6307 def T2(b: B)
6308 assert_equal('foo', b.Foo())
6309 enddef
6310
6311 var c = C.new()
6312 T1(c)
6313 T2(c)
6314 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006315 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006316enddef
6317
6318" Test for using an interface method using a child object when it is overridden
6319" by the child class.
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01006320def Test_interface_overridden_method_from_child()
6321 var lines =<< trim END
6322 vim9script
6323
6324 interface A
6325 def Foo(): string
6326 endinterface
6327
6328 class B implements A
6329 def Foo(): string
6330 return 'b-foo'
6331 enddef
6332 endclass
6333
6334 class C extends B
6335 def Bar(): string
6336 return 'bar'
6337 enddef
6338 def Foo(): string
6339 return 'c-foo'
6340 enddef
6341 endclass
6342
6343 def T1(a: A)
6344 assert_equal('c-foo', a.Foo())
6345 enddef
6346
6347 def T2(b: B)
6348 assert_equal('c-foo', b.Foo())
6349 enddef
6350
6351 var c = C.new()
6352 T1(c)
6353 T2(c)
6354 END
6355 v9.CheckSourceSuccess(lines)
6356enddef
6357
6358" Test for interface inheritance
6359def Test_interface_inheritance()
6360 var lines =<< trim END
6361 vim9script
6362
6363 interface A
6364 def A_Fn(): string
6365 endinterface
6366
6367 interface B
6368 def B_Fn(): string
6369 endinterface
6370
6371 interface C
6372 def C_Fn(): string
6373 endinterface
6374
6375 class C1 implements A
6376 def A_Fn(): string
6377 return 'c1-a'
6378 enddef
6379 endclass
6380
6381 class C2 extends C1 implements B
6382 def B_Fn(): string
6383 return 'c2-b'
6384 enddef
6385 def A_Fn(): string
6386 return 'c2-a'
6387 enddef
6388 endclass
6389
6390 class C3 extends C2 implements C
6391 def C_Fn(): string
6392 return 'c3-c'
6393 enddef
6394 def A_Fn(): string
6395 return 'c3-a'
6396 enddef
6397 def B_Fn(): string
6398 return 'c3-b'
6399 enddef
6400 endclass
6401
6402 def T1(a: A, s: string)
6403 assert_equal(s, a.A_Fn())
6404 enddef
6405
6406 def T2(b: B, s: string)
6407 assert_equal(s, b.B_Fn())
6408 enddef
6409
6410 def T3(c: C, s: string)
6411 assert_equal(s, c.C_Fn())
6412 enddef
6413
6414 def T4(c1: C1)
6415 T1(c1, 'c3-a')
6416 enddef
6417
6418 def T5(c2: C2)
6419 T1(c2, 'c3-a')
6420 T2(c2, 'c3-b')
6421 enddef
6422
6423 def T6(c3: C3)
6424 T1(c3, 'c3-a')
6425 T2(c3, 'c3-b')
6426 T3(c3, 'c3-c')
6427 enddef
6428
6429 var o3 = C3.new()
6430 T4(o3)
6431 T5(o3)
6432 T6(o3)
6433 END
6434 v9.CheckSourceSuccess(lines)
6435
6436 # Both the parent and child classes implement the same interface
6437 lines =<< trim END
6438 vim9script
6439
6440 interface I
6441 def Foo(): string
6442 endinterface
6443
6444 class A implements I
6445 def Foo(): string
6446 return 'A-foo'
6447 enddef
6448 endclass
6449
6450 class B implements I
6451 def Foo(): string
6452 return 'B-foo'
6453 enddef
6454 endclass
6455
6456 def Bar(i1: I): string
6457 return i1.Foo()
6458 enddef
6459
6460 var b = B.new()
6461 assert_equal('B-foo', Bar(b))
6462 END
6463 v9.CheckSourceSuccess(lines)
6464enddef
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006465
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006466" Test for abstract methods
6467def Test_abstract_method()
6468 # Use two abstract methods
6469 var lines =<< trim END
6470 vim9script
6471 abstract class A
6472 def M1(): number
6473 return 10
6474 enddef
6475 abstract def M2(): number
6476 abstract def M3(): number
6477 endclass
6478 class B extends A
6479 def M2(): number
6480 return 20
6481 enddef
6482 def M3(): number
6483 return 30
6484 enddef
6485 endclass
6486 var b = B.new()
6487 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6488 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006489 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006490
6491 # Don't define an abstract method
6492 lines =<< trim END
6493 vim9script
6494 abstract class A
6495 abstract def Foo()
6496 endclass
6497 class B extends A
6498 endclass
6499 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006500 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006501
6502 # Use abstract method in a concrete class
6503 lines =<< trim END
6504 vim9script
6505 class A
6506 abstract def Foo()
6507 endclass
6508 class B extends A
6509 endclass
6510 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006511 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006512
6513 # Use abstract method in an interface
6514 lines =<< trim END
6515 vim9script
6516 interface A
6517 abstract def Foo()
6518 endinterface
6519 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006520 def Foo()
6521 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006522 endclass
6523 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006524 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6525
6526 # Use abstract static method in an interface
6527 lines =<< trim END
6528 vim9script
6529 interface A
6530 abstract static def Foo()
6531 enddef
6532 endinterface
6533 END
6534 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6535
6536 # Use abstract static variable in an interface
6537 lines =<< trim END
6538 vim9script
6539 interface A
6540 abstract static foo: number = 10
6541 endinterface
6542 END
6543 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006544
6545 # Abbreviate the "abstract" keyword
6546 lines =<< trim END
6547 vim9script
6548 class A
6549 abs def Foo()
6550 endclass
6551 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006552 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006553
6554 # Use "abstract" with a member variable
6555 lines =<< trim END
6556 vim9script
6557 abstract class A
6558 abstract this.val = 10
6559 endclass
6560 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006561 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006562
6563 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006564 lines =<< trim END
6565 vim9script
6566 abstract class A
6567 abstract static def Foo(): number
6568 endclass
6569 END
6570 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006571
6572 # Type mismatch between abstract method and concrete method
6573 lines =<< trim END
6574 vim9script
6575 abstract class A
6576 abstract def Foo(a: string, b: number): list<number>
6577 endclass
6578 class B extends A
6579 def Foo(a: number, b: string): list<string>
6580 return []
6581 enddef
6582 endclass
6583 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006584 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 +02006585
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006586 # Invoke an abstract method from a def function
6587 lines =<< trim END
6588 vim9script
6589 abstract class A
6590 abstract def Foo(): list<number>
6591 endclass
6592 class B extends A
6593 def Foo(): list<number>
6594 return [3, 5]
6595 enddef
6596 endclass
6597 def Bar(c: B)
6598 assert_equal([3, 5], c.Foo())
6599 enddef
6600 var b = B.new()
6601 Bar(b)
6602 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006603 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006604
6605 # Use a static method in an abstract class
6606 lines =<< trim END
6607 vim9script
6608 abstract class A
6609 static def Foo(): string
6610 return 'foo'
6611 enddef
6612 endclass
6613 assert_equal('foo', A.Foo())
6614 END
6615 v9.CheckSourceSuccess(lines)
Ernie Rael7c92e882025-01-18 17:26:39 +01006616
6617 # Invoke method returning a value through the abstract class. See #15432.
6618 lines =<< trim END
6619 vim9script
6620
6621 abstract class A
6622 abstract def String(): string
6623 endclass
6624
6625 class B extends A
6626 def String(): string
6627 return 'B'
6628 enddef
6629 endclass
6630
6631 def F(o: A)
6632 assert_equal('B', o.String())
6633 enddef
6634 F(B.new())
6635 END
6636 v9.CheckSourceSuccess(lines)
6637
6638 # Invoke abstract method returning a value does not compile
6639 lines =<< trim END
6640 vim9script
6641
6642 abstract class A
6643 abstract def String(): string
6644 return 'X'
6645 enddef
6646 endclass
6647 END
6648 v9.CheckScriptFailure(lines, "E1318: Not a valid command in a class: return 'X'")
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006649enddef
6650
6651" Test for calling a class method from a subclass
6652def Test_class_method_call_from_subclass()
6653 # class method call from a subclass
6654 var lines =<< trim END
6655 vim9script
6656
6657 class A
6658 static def Foo()
6659 echo "foo"
6660 enddef
6661 endclass
6662
6663 class B extends A
6664 def Bar()
6665 Foo()
6666 enddef
6667 endclass
6668
6669 var b = B.new()
6670 b.Bar()
6671 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006672 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006673enddef
6674
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006675" Test for calling a class method using an object in a def function context and
6676" script context.
6677def Test_class_method_call_using_object()
6678 # script context
6679 var lines =<< trim END
6680 vim9script
6681 class A
6682 static def Foo(): list<string>
6683 return ['a', 'b']
6684 enddef
6685 def Bar()
6686 assert_equal(['a', 'b'], A.Foo())
6687 assert_equal(['a', 'b'], Foo())
6688 enddef
6689 endclass
6690
6691 def T()
6692 assert_equal(['a', 'b'], A.Foo())
6693 var t_a = A.new()
6694 t_a.Bar()
6695 enddef
6696
6697 assert_equal(['a', 'b'], A.Foo())
6698 var a = A.new()
6699 a.Bar()
6700 T()
6701 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006702 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006703
6704 # script context
6705 lines =<< trim END
6706 vim9script
6707 class A
6708 static def Foo(): string
6709 return 'foo'
6710 enddef
6711 endclass
6712
6713 var a = A.new()
6714 assert_equal('foo', a.Foo())
6715 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006716 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006717
6718 # def function context
6719 lines =<< trim END
6720 vim9script
6721 class A
6722 static def Foo(): string
6723 return 'foo'
6724 enddef
6725 endclass
6726
6727 def T()
6728 var a = A.new()
6729 assert_equal('foo', a.Foo())
6730 enddef
6731 T()
6732 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006733 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006734enddef
6735
6736def Test_class_variable()
6737 var lines =<< trim END
6738 vim9script
6739
6740 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006741 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006742 static def ClassFunc()
6743 assert_equal(10, val)
6744 enddef
6745 def ObjFunc()
6746 assert_equal(10, val)
6747 enddef
6748 endclass
6749
6750 class B extends A
6751 endclass
6752
6753 assert_equal(10, A.val)
6754 A.ClassFunc()
6755 var a = A.new()
6756 a.ObjFunc()
6757 var b = B.new()
6758 b.ObjFunc()
6759
6760 def T1(a1: A)
6761 a1.ObjFunc()
6762 A.ClassFunc()
6763 enddef
6764 T1(b)
6765
6766 A.val = 20
6767 assert_equal(20, A.val)
6768 END
6769 v9.CheckSourceSuccess(lines)
6770
6771 # Modifying a parent class variable from a child class method
6772 lines =<< trim END
6773 vim9script
6774
6775 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006776 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006777 endclass
6778
6779 class B extends A
6780 static def ClassFunc()
6781 val = 20
6782 enddef
6783 endclass
6784 B.ClassFunc()
6785 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006786 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006787
6788 # Reading a parent class variable from a child class method
6789 lines =<< trim END
6790 vim9script
6791
6792 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006793 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006794 endclass
6795
6796 class B extends A
6797 static def ClassFunc()
6798 var i = val
6799 enddef
6800 endclass
6801 B.ClassFunc()
6802 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006803 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006804
6805 # Modifying a parent class variable from a child object method
6806 lines =<< trim END
6807 vim9script
6808
6809 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006810 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006811 endclass
6812
6813 class B extends A
6814 def ObjFunc()
6815 val = 20
6816 enddef
6817 endclass
6818 var b = B.new()
6819 b.ObjFunc()
6820 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006821 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006822
6823 # Reading a parent class variable from a child object method
6824 lines =<< trim END
6825 vim9script
6826
6827 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006828 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006829 endclass
6830
6831 class B extends A
6832 def ObjFunc()
6833 var i = val
6834 enddef
6835 endclass
6836 var b = B.new()
6837 b.ObjFunc()
6838 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006839 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006840
6841 # Modifying a class variable using an object at script level
6842 lines =<< trim END
6843 vim9script
6844
6845 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006846 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006847 endclass
6848 var a = A.new()
6849 a.val = 20
6850 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006851 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006852
6853 # Reading a class variable using an object at script level
6854 lines =<< trim END
6855 vim9script
6856
6857 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006858 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006859 endclass
6860 var a = A.new()
6861 var i = a.val
6862 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006863 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006864
6865 # Modifying a class variable using an object at function level
6866 lines =<< trim END
6867 vim9script
6868
6869 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006870 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006871 endclass
6872
6873 def T()
6874 var a = A.new()
6875 a.val = 20
6876 enddef
6877 T()
6878 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006879 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006880
6881 # Reading a class variable using an object at function level
6882 lines =<< trim END
6883 vim9script
6884
6885 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006886 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006887 endclass
6888 def T()
6889 var a = A.new()
6890 var i = a.val
6891 enddef
6892 T()
6893 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006894 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006895
6896 # Use old implicit var declaration syntax (without initialization)
6897 lines =<< trim END
6898 vim9script
6899
6900 class A
6901 static val: number
6902 endclass
6903 END
6904 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6905
6906 # Use old implicit var declaration syntax (with initialization)
6907 lines =<< trim END
6908 vim9script
6909
6910 class A
6911 static val: number = 10
6912 endclass
6913 END
6914 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6915
6916 # Use old implicit var declaration syntax (type inferred)
6917 lines =<< trim END
6918 vim9script
6919
6920 class A
6921 static val = 10
6922 endclass
6923 END
6924 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6925
6926 # Missing ":var" in "var" class variable declaration (without initialization)
6927 lines =<< trim END
6928 vim9script
6929
6930 class A
6931 static var: number
6932 endclass
6933 END
6934 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6935
6936 # Missing ":var" in "var" class variable declaration (with initialization)
6937 lines =<< trim END
6938 vim9script
6939
6940 class A
6941 static var: number = 10
6942 endclass
6943 END
6944 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6945
6946 # Missing ":var" in "var" class variable declaration (type inferred)
6947 lines =<< trim END
6948 vim9script
6949
6950 class A
6951 static var = 10
6952 endclass
6953 END
6954 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6955
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006956enddef
6957
6958" Test for using a duplicate class method and class variable in a child class
6959def Test_dup_class_member()
6960 # duplicate class variable, class method and overridden object method
6961 var lines =<< trim END
6962 vim9script
6963 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006964 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006965 static def Check()
6966 assert_equal(100, sval)
6967 enddef
6968 def GetVal(): number
6969 return sval
6970 enddef
6971 endclass
6972
6973 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006974 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006975 static def Check()
6976 assert_equal(200, sval)
6977 enddef
6978 def GetVal(): number
6979 return sval
6980 enddef
6981 endclass
6982
6983 def T1(aa: A): number
6984 return aa.GetVal()
6985 enddef
6986
6987 def T2(bb: B): number
6988 return bb.GetVal()
6989 enddef
6990
6991 assert_equal(100, A.sval)
6992 assert_equal(200, B.sval)
6993 var a = A.new()
6994 assert_equal(100, a.GetVal())
6995 var b = B.new()
6996 assert_equal(200, b.GetVal())
6997 assert_equal(200, T1(b))
6998 assert_equal(200, T2(b))
6999 END
7000 v9.CheckSourceSuccess(lines)
7001
7002 # duplicate class variable and class method
7003 lines =<< trim END
7004 vim9script
7005 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007006 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007007 static def Check()
7008 assert_equal(100, sval)
7009 enddef
7010 def GetVal(): number
7011 return sval
7012 enddef
7013 endclass
7014
7015 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007016 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007017 static def Check()
7018 assert_equal(200, sval)
7019 enddef
7020 endclass
7021
7022 def T1(aa: A): number
7023 return aa.GetVal()
7024 enddef
7025
7026 def T2(bb: B): number
7027 return bb.GetVal()
7028 enddef
7029
7030 assert_equal(100, A.sval)
7031 assert_equal(200, B.sval)
7032 var a = A.new()
7033 assert_equal(100, a.GetVal())
7034 var b = B.new()
7035 assert_equal(100, b.GetVal())
7036 assert_equal(100, T1(b))
7037 assert_equal(100, T2(b))
7038 END
7039 v9.CheckSourceSuccess(lines)
7040enddef
7041
7042" Test for calling an instance method using the class
7043def Test_instance_method_call_using_class()
7044 # Invoke an object method using a class in script context
7045 var lines =<< trim END
7046 vim9script
7047 class A
7048 def Foo()
7049 echo "foo"
7050 enddef
7051 endclass
7052 A.Foo()
7053 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007054 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007055
7056 # Invoke an object method using a class in def function context
7057 lines =<< trim END
7058 vim9script
7059 class A
7060 def Foo()
7061 echo "foo"
7062 enddef
7063 endclass
7064 def T()
7065 A.Foo()
7066 enddef
7067 T()
7068 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007069 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007070enddef
7071
7072" Test for duplicate class method and instance method
7073def Test_dup_classmethod_objmethod()
7074 # Duplicate instance method
7075 var lines =<< trim END
7076 vim9script
7077 class A
7078 static def Foo()
7079 enddef
7080 def Foo()
7081 enddef
7082 endclass
7083 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007084 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007085
Ernie Rael03042a22023-11-11 08:53:32 +01007086 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007087 lines =<< trim END
7088 vim9script
7089 class A
7090 static def Foo()
7091 enddef
7092 def _Foo()
7093 enddef
7094 endclass
7095 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007096 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007097
7098 # Duplicate class method
7099 lines =<< trim END
7100 vim9script
7101 class A
7102 def Foo()
7103 enddef
7104 static def Foo()
7105 enddef
7106 endclass
7107 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007108 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007109
Ernie Rael03042a22023-11-11 08:53:32 +01007110 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007111 lines =<< trim END
7112 vim9script
7113 class A
7114 def Foo()
7115 enddef
7116 static def _Foo()
7117 enddef
7118 endclass
7119 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007120 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007121
Ernie Rael03042a22023-11-11 08:53:32 +01007122 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007123 lines =<< trim END
7124 vim9script
7125 class A
7126 def _Foo()
7127 enddef
7128 static def _Foo()
7129 enddef
7130 endclass
7131 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007132 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007133enddef
7134
7135" Test for an instance method access level comparison with parent instance
7136" methods.
7137def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01007138 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007139 var lines =<< trim END
7140 vim9script
7141 class A
7142 def Foo()
7143 enddef
7144 endclass
7145 class B extends A
7146 endclass
7147 class C extends B
7148 def _Foo()
7149 enddef
7150 endclass
7151 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007152 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007153
7154 # Public method in subclass
7155 lines =<< trim END
7156 vim9script
7157 class A
7158 def _Foo()
7159 enddef
7160 endclass
7161 class B extends A
7162 endclass
7163 class C extends B
7164 def Foo()
7165 enddef
7166 endclass
7167 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007168 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007169enddef
7170
7171def Test_extend_empty_class()
7172 var lines =<< trim END
7173 vim9script
7174 class A
7175 endclass
7176 class B extends A
7177 endclass
7178 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007179 public static var rw_class_var = 1
7180 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007181 static def ClassMethod(): number
7182 return 3
7183 enddef
7184 def ObjMethod(): number
7185 return 4
7186 enddef
7187 endclass
7188 assert_equal(1, C.rw_class_var)
7189 assert_equal(3, C.ClassMethod())
7190 var c = C.new()
7191 assert_equal(2, c.rw_obj_var)
7192 assert_equal(4, c.ObjMethod())
7193 END
7194 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02007195enddef
7196
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007197" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01007198" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007199def Test_interface_with_unsupported_members()
7200 var lines =<< trim END
7201 vim9script
7202 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007203 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007204 endinterface
7205 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007206 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007207
7208 lines =<< trim END
7209 vim9script
7210 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007211 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007212 endinterface
7213 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007214 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007215
7216 lines =<< trim END
7217 vim9script
7218 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007219 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007220 endinterface
7221 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007222 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007223
7224 lines =<< trim END
7225 vim9script
7226 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007227 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007228 endinterface
7229 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007230 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007231
7232 lines =<< trim END
7233 vim9script
7234 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007235 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007236 endinterface
7237 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007238 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007239
7240 lines =<< trim END
7241 vim9script
7242 interface A
7243 static def Foo(d: dict<any>): list<string>
7244 endinterface
7245 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007246 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007247
7248 lines =<< trim END
7249 vim9script
7250 interface A
7251 static def _Foo(d: dict<any>): list<string>
7252 endinterface
7253 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007254 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007255
7256 lines =<< trim END
7257 vim9script
7258 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007259 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007260 endinterface
7261 END
Ernie Rael03042a22023-11-11 08:53:32 +01007262 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007263
7264 lines =<< trim END
7265 vim9script
7266 interface A
7267 def _Foo(d: dict<any>): list<string>
7268 endinterface
7269 END
Ernie Rael03042a22023-11-11 08:53:32 +01007270 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007271enddef
7272
7273" Test for extending an interface
7274def Test_extend_interface()
7275 var lines =<< trim END
7276 vim9script
7277 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007278 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007279 def Foo()
7280 endinterface
7281 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007282 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007283 def Bar()
7284 endinterface
7285 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007286 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007287 def Foo()
7288 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007289 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007290 def Bar()
7291 enddef
7292 endclass
7293 END
7294 v9.CheckSourceSuccess(lines)
7295
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007296 # extending empty interface
7297 lines =<< trim END
7298 vim9script
7299 interface A
7300 endinterface
7301 interface B extends A
7302 endinterface
7303 class C implements B
7304 endclass
7305 END
7306 v9.CheckSourceSuccess(lines)
7307
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007308 lines =<< trim END
7309 vim9script
7310 interface A
7311 def Foo()
7312 endinterface
7313 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007314 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007315 endinterface
7316 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007317 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007318 endclass
7319 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007320 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007321
7322 lines =<< trim END
7323 vim9script
7324 interface A
7325 def Foo()
7326 endinterface
7327 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007328 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007329 endinterface
7330 class C implements A, B
7331 def Foo()
7332 enddef
7333 endclass
7334 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007335 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007336
7337 # interface cannot extend a class
7338 lines =<< trim END
7339 vim9script
7340 class A
7341 endclass
7342 interface B extends A
7343 endinterface
7344 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007345 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007346
7347 # class cannot extend an interface
7348 lines =<< trim END
7349 vim9script
7350 interface A
7351 endinterface
7352 class B extends A
7353 endclass
7354 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007355 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007356
7357 # interface cannot implement another interface
7358 lines =<< trim END
7359 vim9script
7360 interface A
7361 endinterface
7362 interface B implements A
7363 endinterface
7364 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007365 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007366
7367 # interface cannot extend multiple interfaces
7368 lines =<< trim END
7369 vim9script
7370 interface A
7371 endinterface
7372 interface B
7373 endinterface
7374 interface C extends A, B
7375 endinterface
7376 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007377 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007378
7379 # Variable type in an extended interface is of different type
7380 lines =<< trim END
7381 vim9script
7382 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007383 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007384 endinterface
7385 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007386 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007387 endinterface
7388 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007389 var val1: string
7390 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007391 endinterface
7392 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007393 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007394enddef
7395
7396" Test for a child class implementing an interface when some of the methods are
7397" defined in the parent class.
7398def Test_child_class_implements_interface()
7399 var lines =<< trim END
7400 vim9script
7401
7402 interface Intf
7403 def F1(): list<list<number>>
7404 def F2(): list<list<number>>
7405 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007406 var var1: list<dict<number>>
7407 var var2: list<dict<number>>
7408 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007409 endinterface
7410
7411 class A
7412 def A1()
7413 enddef
7414 def F3(): list<list<number>>
7415 return [[3]]
7416 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007417 var v1: list<list<number>> = [[0]]
7418 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007419 endclass
7420
7421 class B extends A
7422 def B1()
7423 enddef
7424 def F2(): list<list<number>>
7425 return [[2]]
7426 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007427 var v2: list<list<number>> = [[0]]
7428 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007429 endclass
7430
7431 class C extends B implements Intf
7432 def C1()
7433 enddef
7434 def F1(): list<list<number>>
7435 return [[1]]
7436 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007437 var v3: list<list<number>> = [[0]]
7438 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007439 endclass
7440
7441 def T(if: Intf)
7442 assert_equal([[1]], if.F1())
7443 assert_equal([[2]], if.F2())
7444 assert_equal([[3]], if.F3())
7445 assert_equal([{a: 10}], if.var1)
7446 assert_equal([{b: 20}], if.var2)
7447 assert_equal([{c: 30}], if.var3)
7448 enddef
7449
7450 var c = C.new()
7451 T(c)
7452 assert_equal([[1]], c.F1())
7453 assert_equal([[2]], c.F2())
7454 assert_equal([[3]], c.F3())
7455 assert_equal([{a: 10}], c.var1)
7456 assert_equal([{b: 20}], c.var2)
7457 assert_equal([{c: 30}], c.var3)
7458 END
7459 v9.CheckSourceSuccess(lines)
7460
7461 # One of the interface methods is not found
7462 lines =<< trim END
7463 vim9script
7464
7465 interface Intf
7466 def F1()
7467 def F2()
7468 def F3()
7469 endinterface
7470
7471 class A
7472 def A1()
7473 enddef
7474 endclass
7475
7476 class B extends A
7477 def B1()
7478 enddef
7479 def F2()
7480 enddef
7481 endclass
7482
7483 class C extends B implements Intf
7484 def C1()
7485 enddef
7486 def F1()
7487 enddef
7488 endclass
7489 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007490 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007491
7492 # One of the interface methods is of different type
7493 lines =<< trim END
7494 vim9script
7495
7496 interface Intf
7497 def F1()
7498 def F2()
7499 def F3()
7500 endinterface
7501
7502 class A
7503 def F3(): number
7504 return 0
7505 enddef
7506 def A1()
7507 enddef
7508 endclass
7509
7510 class B extends A
7511 def B1()
7512 enddef
7513 def F2()
7514 enddef
7515 endclass
7516
7517 class C extends B implements Intf
7518 def C1()
7519 enddef
7520 def F1()
7521 enddef
7522 endclass
7523 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007524 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007525
7526 # One of the interface variables is not present
7527 lines =<< trim END
7528 vim9script
7529
7530 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007531 var var1: list<dict<number>>
7532 var var2: list<dict<number>>
7533 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007534 endinterface
7535
7536 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007537 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007538 endclass
7539
7540 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007541 var v2: list<list<number>> = [[0]]
7542 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007543 endclass
7544
7545 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007546 var v3: list<list<number>> = [[0]]
7547 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007548 endclass
7549 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007550 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007551
7552 # One of the interface variables is of different type
7553 lines =<< trim END
7554 vim9script
7555
7556 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007557 var var1: list<dict<number>>
7558 var var2: list<dict<number>>
7559 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007560 endinterface
7561
7562 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007563 var v1: list<list<number>> = [[0]]
7564 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007565 endclass
7566
7567 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007568 var v2: list<list<number>> = [[0]]
7569 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007570 endclass
7571
7572 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007573 var v3: list<list<number>> = [[0]]
7574 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007575 endclass
7576 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007577 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 +02007578enddef
7579
7580" Test for extending an interface with duplicate variables and methods
7581def Test_interface_extends_with_dup_members()
7582 var lines =<< trim END
7583 vim9script
7584 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007585 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007586 def Foo1(): number
7587 endinterface
7588 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007589 var n2: number
7590 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007591 def Foo2(): number
7592 def Foo1(): number
7593 endinterface
7594 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007595 var n1 = 10
7596 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007597 def Foo1(): number
7598 return 30
7599 enddef
7600 def Foo2(): number
7601 return 40
7602 enddef
7603 endclass
7604 def T1(a: A)
7605 assert_equal(10, a.n1)
7606 assert_equal(30, a.Foo1())
7607 enddef
7608 def T2(b: B)
7609 assert_equal(10, b.n1)
7610 assert_equal(20, b.n2)
7611 assert_equal(30, b.Foo1())
7612 assert_equal(40, b.Foo2())
7613 enddef
7614 var c = C.new()
7615 T1(c)
7616 T2(c)
7617 END
7618 v9.CheckSourceSuccess(lines)
7619enddef
7620
Yegappan Lakshmananc10342d2025-01-11 09:39:01 +01007621" Test for implementing an interface with different ordering for the interface
7622" member variables.
7623def Test_implement_interface_with_different_variable_order()
7624 var lines =<< trim END
7625 vim9script
7626
7627 interface IX
7628 var F: func(): string
7629 endinterface
7630
7631 class X implements IX
7632 var x: number
7633 var F: func(): string = () => 'ok'
7634 endclass
7635
7636 def Foo(ix: IX): string
7637 return ix.F()
7638 enddef
7639
7640 var x0 = X.new(0)
7641 assert_equal('ok', Foo(x0))
7642 END
7643 v9.CheckSourceSuccess(lines)
7644enddef
7645
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01007646" Test for inheriting interfaces from an imported super class
7647def Test_interface_inheritance_with_imported_super()
7648 var lines =<< trim END
7649 vim9script
7650
7651 export interface I
7652 def F(): string
7653 endinterface
7654
7655 export class A implements I
7656 def F(): string
7657 return 'A'
7658 enddef
7659 endclass
7660 END
7661 writefile(lines, 'Xinheritintfimportclass.vim', 'D')
7662
7663 lines =<< trim END
7664 vim9script
7665
7666 import './Xinheritintfimportclass.vim' as i_imp
7667
7668 # class C extends i_imp.A
7669 class C extends i_imp.A implements i_imp.I
7670 def F(): string
7671 return 'C'
7672 enddef
7673 endclass
7674
7675 def TestI(i: i_imp.I): string
7676 return i.F()
7677 enddef
7678
7679 assert_equal('C', TestI(C.new()))
7680 END
7681 v9.CheckSourceSuccess(lines)
7682enddef
7683
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007684" Test for using "any" type for a variable in a sub-class while it has a
7685" concrete type in the interface
7686def Test_implements_using_var_type_any()
7687 var lines =<< trim END
7688 vim9script
7689 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007690 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007691 endinterface
7692 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007693 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007694 endclass
7695 var b = B.new()
7696 assert_equal([{a: '1'}, {b: '2'}], b.val)
7697 END
7698 v9.CheckSourceSuccess(lines)
7699
7700 # initialize instance variable using a different type
7701 lines =<< trim END
7702 vim9script
7703 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007704 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007705 endinterface
7706 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007707 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007708 endclass
7709 var b = B.new()
7710 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007711 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007712enddef
7713
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007714" Test for assigning to a member variable in a nested class
7715def Test_nested_object_assignment()
7716 var lines =<< trim END
7717 vim9script
7718
7719 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007720 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007721 endclass
7722
7723 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007724 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007725 endclass
7726
7727 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007728 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007729 endclass
7730
7731 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007732 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007733 endclass
7734
7735 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007736 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007737 enddef
7738
7739 var d = D.new()
7740 T(d)
7741 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007742 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007743enddef
7744
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007745" Test for calling methods using a null object
7746def Test_null_object_method_call()
7747 # Calling a object method using a null object in script context
7748 var lines =<< trim END
7749 vim9script
7750
7751 class C
7752 def Foo()
7753 assert_report('This method should not be executed')
7754 enddef
7755 endclass
7756
7757 var o: C
7758 o.Foo()
7759 END
7760 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7761
7762 # Calling a object method using a null object in def function context
7763 lines =<< trim END
7764 vim9script
7765
7766 class C
7767 def Foo()
7768 assert_report('This method should not be executed')
7769 enddef
7770 endclass
7771
7772 def T()
7773 var o: C
7774 o.Foo()
7775 enddef
7776 T()
7777 END
7778 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7779
7780 # Calling a object method through another class method using a null object in
7781 # script context
7782 lines =<< trim END
7783 vim9script
7784
7785 class C
7786 def Foo()
7787 assert_report('This method should not be executed')
7788 enddef
7789
7790 static def Bar(o_any: any)
7791 var o_typed: C = o_any
7792 o_typed.Foo()
7793 enddef
7794 endclass
7795
7796 var o: C
7797 C.Bar(o)
7798 END
7799 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7800
7801 # Calling a object method through another class method using a null object in
7802 # def function context
7803 lines =<< trim END
7804 vim9script
7805
7806 class C
7807 def Foo()
7808 assert_report('This method should not be executed')
7809 enddef
7810
7811 static def Bar(o_any: any)
7812 var o_typed: C = o_any
7813 o_typed.Foo()
7814 enddef
7815 endclass
7816
7817 def T()
7818 var o: C
7819 C.Bar(o)
7820 enddef
7821 T()
7822 END
7823 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007824
7825 # Calling an object method defined in a class that is extended. This differs
7826 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7827 lines =<< trim END
7828 vim9script
7829
7830 class C0
7831 def F()
7832 enddef
7833 endclass
7834
7835 class C extends C0
7836 endclass
7837
7838 def X()
7839 var o: C0 = null_object
7840 o.F()
7841 enddef
7842 X()
7843 END
7844 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7845
7846 # Getting a function ref an object method.
7847 lines =<< trim END
7848 vim9script
7849
7850 class C0
7851 def F()
7852 enddef
7853 endclass
7854
7855 class C extends C0
7856 endclass
7857
7858 def X()
7859 var o: C0 = null_object
7860 var XXX = o.F
7861 enddef
7862 X()
7863 END
7864 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007865enddef
7866
7867" Test for using a dict as an object member
7868def Test_dict_object_member()
7869 var lines =<< trim END
7870 vim9script
7871
7872 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007873 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007874 def GetState(): dict<number>
7875 return this.state
7876 enddef
7877 endclass
7878
7879 var ctx = Context.new()
7880 ctx.state->extend({a: 1})
7881 ctx.state['b'] = 2
7882 assert_equal({a: 1, b: 2}, ctx.GetState())
7883
7884 def F()
7885 ctx.state['c'] = 3
7886 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7887 enddef
7888 F()
7889 assert_equal(3, ctx.state.c)
7890 ctx.state.c = 4
7891 assert_equal(4, ctx.state.c)
7892 END
7893 v9.CheckSourceSuccess(lines)
7894enddef
7895
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007896" The following test was failing after 9.0.1914. This was caused by using a
7897" freed object from a previous method call.
7898def Test_freed_object_from_previous_method_call()
7899 var lines =<< trim END
7900 vim9script
7901
7902 class Context
7903 endclass
7904
7905 class Result
7906 endclass
7907
7908 def Failure(): Result
7909 return Result.new()
7910 enddef
7911
7912 def GetResult(ctx: Context): Result
7913 return Failure()
7914 enddef
7915
7916 def Test_GetResult()
7917 var ctx = Context.new()
7918 var result = GetResult(ctx)
7919 enddef
7920
7921 Test_GetResult()
7922 END
7923 v9.CheckSourceSuccess(lines)
7924enddef
7925
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007926" Test for duplicate object and class variable
7927def Test_duplicate_variable()
7928 # Object variable name is same as the class variable name
7929 var lines =<< trim END
7930 vim9script
7931 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007932 public static var sval: number
7933 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007934 endclass
7935 var a = A.new()
7936 END
7937 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7938
7939 # Duplicate variable name and calling a class method
7940 lines =<< trim END
7941 vim9script
7942 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007943 public static var sval: number
7944 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007945 def F1()
7946 echo this.sval
7947 enddef
7948 static def F2()
7949 echo sval
7950 enddef
7951 endclass
7952 A.F2()
7953 END
7954 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7955
7956 # Duplicate variable with an empty constructor
7957 lines =<< trim END
7958 vim9script
7959 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007960 public static var sval: number
7961 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007962 def new()
7963 enddef
7964 endclass
7965 var a = A.new()
7966 END
7967 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7968enddef
7969
7970" Test for using a reserved keyword as a variable name
7971def Test_reserved_varname()
7972 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7973 'null_function', 'null_list', 'null_partial', 'null_string',
7974 'null_channel', 'null_job', 'super', 'this']
7975
7976 var lines =<< trim eval END
7977 vim9script
7978 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007979 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007980 endclass
7981 var o = C.new()
7982 END
7983 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7984
7985 lines =<< trim eval END
7986 vim9script
7987 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007988 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007989 def new()
7990 enddef
7991 endclass
7992 var o = C.new()
7993 END
7994 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7995
7996 lines =<< trim eval END
7997 vim9script
7998 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007999 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02008000 def new()
8001 enddef
8002 def F()
8003 echo this.{kword}
8004 enddef
8005 endclass
8006 var o = C.new()
8007 o.F()
8008 END
8009 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02008010
8011 # class variable name
8012 if kword != 'this'
8013 lines =<< trim eval END
8014 vim9script
8015 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01008016 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02008017 endclass
8018 END
8019 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
8020 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02008021 endfor
8022enddef
8023
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02008024" Test for checking the type of the arguments and the return value of a object
8025" method in an extended class.
8026def Test_extended_obj_method_type_check()
8027 var lines =<< trim END
8028 vim9script
8029
8030 class A
8031 endclass
8032 class B extends A
8033 endclass
8034 class C extends B
8035 endclass
8036
8037 class Foo
8038 def Doit(p: B): B
8039 return B.new()
8040 enddef
8041 endclass
8042
8043 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02008044 def Doit(p: C): B
8045 return B.new()
8046 enddef
8047 endclass
8048 END
8049 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
8050
8051 lines =<< trim END
8052 vim9script
8053
8054 class A
8055 endclass
8056 class B extends A
8057 endclass
8058 class C extends B
8059 endclass
8060
8061 class Foo
8062 def Doit(p: B): B
8063 return B.new()
8064 enddef
8065 endclass
8066
8067 class Bar extends Foo
8068 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02008069 return C.new()
8070 enddef
8071 endclass
8072 END
8073 v9.CheckSourceSuccess(lines)
8074
8075 lines =<< trim END
8076 vim9script
8077
8078 class A
8079 endclass
8080 class B extends A
8081 endclass
8082 class C extends B
8083 endclass
8084
8085 class Foo
8086 def Doit(p: B): B
8087 return B.new()
8088 enddef
8089 endclass
8090
8091 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02008092 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02008093 return B.new()
8094 enddef
8095 endclass
8096 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02008097 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 +02008098
8099 lines =<< trim END
8100 vim9script
8101
8102 class A
8103 endclass
8104 class B extends A
8105 endclass
8106 class C extends B
8107 endclass
8108
8109 class Foo
8110 def Doit(p: B): B
8111 return B.new()
8112 enddef
8113 endclass
8114
8115 class Bar extends Foo
8116 def Doit(p: B): A
8117 return A.new()
8118 enddef
8119 endclass
8120 END
8121 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 +02008122
8123 # check varargs type mismatch
8124 lines =<< trim END
8125 vim9script
8126
8127 class B
8128 def F(...xxx: list<any>)
8129 enddef
8130 endclass
8131 class C extends B
8132 def F(xxx: list<any>)
8133 enddef
8134 endclass
8135 END
8136 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 +02008137enddef
8138
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008139" Test type checking for class variable in assignments
8140func Test_class_variable_complex_type_check()
8141 " class variable with a specific type. Try assigning a different type at
8142 " script level.
8143 let lines =<< trim END
8144 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008145 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008146 return {}
8147 enddef
8148 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008149 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008150 endclass
8151 test_garbagecollect_now()
8152 A.Fn = "abc"
8153 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008154 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 +02008155
8156 " class variable with a specific type. Try assigning a different type at
8157 " class def method level.
8158 let lines =<< trim END
8159 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008160 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008161 return {}
8162 enddef
8163 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008164 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008165 def Bar()
8166 Fn = "abc"
8167 enddef
8168 endclass
8169 var a = A.new()
8170 test_garbagecollect_now()
8171 a.Bar()
8172 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008173 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 +02008174
8175 " class variable with a specific type. Try assigning a different type at
8176 " script def method level.
8177 let lines =<< trim END
8178 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008179 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008180 return {}
8181 enddef
8182 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008183 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008184 endclass
8185 def Bar()
8186 A.Fn = "abc"
8187 enddef
8188 test_garbagecollect_now()
8189 Bar()
8190 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008191 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 +02008192
8193 " class variable without any type. Should be set to the initialization
8194 " expression type. Try assigning a different type from script level.
8195 let lines =<< trim END
8196 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008197 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008198 return {}
8199 enddef
8200 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008201 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008202 endclass
8203 test_garbagecollect_now()
8204 A.Fn = "abc"
8205 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008206 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 +02008207
8208 " class variable without any type. Should be set to the initialization
8209 " expression type. Try assigning a different type at class def level.
8210 let lines =<< trim END
8211 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008212 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008213 return {}
8214 enddef
8215 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008216 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008217 def Bar()
8218 Fn = "abc"
8219 enddef
8220 endclass
8221 var a = A.new()
8222 test_garbagecollect_now()
8223 a.Bar()
8224 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008225 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 +02008226
8227 " class variable without any type. Should be set to the initialization
8228 " expression type. Try assigning a different type at script def level.
8229 let lines =<< trim END
8230 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008231 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008232 return {}
8233 enddef
8234 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008235 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008236 endclass
8237 def Bar()
8238 A.Fn = "abc"
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', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008244
8245 " class variable with 'any" type. Can be assigned different types.
8246 let lines =<< trim END
8247 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008248 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008249 return {}
8250 enddef
8251 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008252 public static var Fn: any = Foo
8253 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008254 endclass
8255 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008256 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008257 A.Fn = "abc"
8258 test_garbagecollect_now()
8259 assert_equal('string', typename(A.Fn))
8260 A.Fn2 = Foo
8261 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008262 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008263 A.Fn2 = "xyz"
8264 test_garbagecollect_now()
8265 assert_equal('string', typename(A.Fn2))
8266 END
8267 call v9.CheckSourceSuccess(lines)
8268
8269 " class variable with 'any" type. Can be assigned different types.
8270 let lines =<< trim END
8271 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008272 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008273 return {}
8274 enddef
8275 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008276 public static var Fn: any = Foo
8277 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008278
8279 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008280 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008281 Fn = "abc"
8282 assert_equal('string', typename(Fn))
8283 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008284 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008285 Fn2 = "xyz"
8286 assert_equal('string', typename(Fn2))
8287 enddef
8288 endclass
8289 var a = A.new()
8290 test_garbagecollect_now()
8291 a.Bar()
8292 test_garbagecollect_now()
8293 A.Fn = Foo
8294 a.Bar()
8295 END
8296 call v9.CheckSourceSuccess(lines)
8297
8298 " class variable with 'any" type. Can be assigned different types.
8299 let lines =<< trim END
8300 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008301 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008302 return {}
8303 enddef
8304 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008305 public static var Fn: any = Foo
8306 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008307 endclass
8308
8309 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008310 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008311 A.Fn = "abc"
8312 assert_equal('string', typename(A.Fn))
8313 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008314 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008315 A.Fn2 = "xyz"
8316 assert_equal('string', typename(A.Fn2))
8317 enddef
8318 Bar()
8319 test_garbagecollect_now()
8320 A.Fn = Foo
8321 Bar()
8322 END
8323 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008324
8325 let lines =<< trim END
8326 vim9script
8327 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008328 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008329 endclass
8330 assert_equal([0z10, 0z20], A.foo)
8331 A.foo = [0z30]
8332 assert_equal([0z30], A.foo)
8333 var a = A.foo
8334 assert_equal([0z30], a)
8335 END
8336 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008337endfunc
8338
8339" Test type checking for object variable in assignments
8340func Test_object_variable_complex_type_check()
8341 " object variable with a specific type. Try assigning a different type at
8342 " script level.
8343 let lines =<< trim END
8344 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008345 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008346 return {}
8347 enddef
8348 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008349 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008350 endclass
8351 var a = A.new()
8352 test_garbagecollect_now()
8353 a.Fn = "abc"
8354 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008355 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 +02008356
8357 " object variable with a specific type. Try assigning a different type at
8358 " object def method level.
8359 let lines =<< trim END
8360 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008361 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008362 return {}
8363 enddef
8364 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008365 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008366 def Bar()
8367 this.Fn = "abc"
8368 this.Fn = Foo
8369 enddef
8370 endclass
8371 var a = A.new()
8372 test_garbagecollect_now()
8373 a.Bar()
8374 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008375 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 +02008376
8377 " object variable with a specific type. Try assigning a different type at
8378 " script def method level.
8379 let lines =<< trim END
8380 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008381 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008382 return {}
8383 enddef
8384 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008385 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008386 endclass
8387 def Bar()
8388 var a = A.new()
8389 a.Fn = "abc"
8390 a.Fn = Foo
8391 enddef
8392 test_garbagecollect_now()
8393 Bar()
8394 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008395 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 +02008396
8397 " object variable without any type. Should be set to the initialization
8398 " expression type. Try assigning a different type from script level.
8399 let lines =<< trim END
8400 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008401 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008402 return {}
8403 enddef
8404 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008405 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008406 endclass
8407 var a = A.new()
8408 test_garbagecollect_now()
8409 a.Fn = "abc"
8410 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008411 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 +02008412
8413 " object variable without any type. Should be set to the initialization
8414 " expression type. Try assigning a different type at object def level.
8415 let lines =<< trim END
8416 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008417 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008418 return {}
8419 enddef
8420 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008421 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008422 def Bar()
8423 this.Fn = "abc"
8424 this.Fn = Foo
8425 enddef
8426 endclass
8427 var a = A.new()
8428 test_garbagecollect_now()
8429 a.Bar()
8430 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008431 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 +02008432
8433 " object variable without any type. Should be set to the initialization
8434 " expression type. Try assigning a different type at script def level.
8435 let lines =<< trim END
8436 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008437 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008438 return {}
8439 enddef
8440 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008441 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008442 endclass
8443 def Bar()
8444 var a = A.new()
8445 a.Fn = "abc"
8446 a.Fn = Foo
8447 enddef
8448 test_garbagecollect_now()
8449 Bar()
8450 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008451 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 +02008452
8453 " object variable with 'any" type. Can be assigned different types.
8454 let lines =<< trim END
8455 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008456 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008457 return {}
8458 enddef
8459 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008460 public var Fn: any = Foo
8461 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008462 endclass
8463
8464 var a = A.new()
8465 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008466 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008467 a.Fn = "abc"
8468 test_garbagecollect_now()
8469 assert_equal('string', typename(a.Fn))
8470 a.Fn2 = Foo
8471 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008472 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008473 a.Fn2 = "xyz"
8474 test_garbagecollect_now()
8475 assert_equal('string', typename(a.Fn2))
8476 END
8477 call v9.CheckSourceSuccess(lines)
8478
8479 " object variable with 'any" type. Can be assigned different types.
8480 let lines =<< trim END
8481 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008482 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008483 return {}
8484 enddef
8485 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008486 public var Fn: any = Foo
8487 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008488
8489 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008490 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008491 this.Fn = "abc"
8492 assert_equal('string', typename(this.Fn))
8493 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008494 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008495 this.Fn2 = "xyz"
8496 assert_equal('string', typename(this.Fn2))
8497 enddef
8498 endclass
8499
8500 var a = A.new()
8501 test_garbagecollect_now()
8502 a.Bar()
8503 test_garbagecollect_now()
8504 a.Fn = Foo
8505 a.Bar()
8506 END
8507 call v9.CheckSourceSuccess(lines)
8508
8509 " object variable with 'any" type. Can be assigned different types.
8510 let lines =<< trim END
8511 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008512 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008513 return {}
8514 enddef
8515 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008516 public var Fn: any = Foo
8517 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008518 endclass
8519
8520 def Bar()
8521 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008522 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008523 a.Fn = "abc"
8524 assert_equal('string', typename(a.Fn))
8525 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008526 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008527 a.Fn2 = "xyz"
8528 assert_equal('string', typename(a.Fn2))
8529 enddef
8530 test_garbagecollect_now()
8531 Bar()
8532 test_garbagecollect_now()
8533 Bar()
8534 END
8535 call v9.CheckSourceSuccess(lines)
8536endfunc
8537
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008538" Test for recursively calling an object method. This used to cause an
8539" use-after-free error.
8540def Test_recursive_object_method_call()
8541 var lines =<< trim END
8542 vim9script
8543 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008544 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008545 def Foo(): number
8546 if this.val >= 90
8547 return this.val
8548 endif
8549 this.val += 1
8550 return this.Foo()
8551 enddef
8552 endclass
8553 var a = A.new()
8554 assert_equal(90, a.Foo())
8555 END
8556 v9.CheckSourceSuccess(lines)
8557enddef
8558
8559" Test for recursively calling a class method.
8560def Test_recursive_class_method_call()
8561 var lines =<< trim END
8562 vim9script
8563 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008564 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008565 static def Foo(): number
8566 if val >= 90
8567 return val
8568 endif
8569 val += 1
8570 return Foo()
8571 enddef
8572 endclass
8573 assert_equal(90, A.Foo())
8574 END
8575 v9.CheckSourceSuccess(lines)
8576enddef
8577
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008578" Test for checking the argument types and the return type when assigning a
8579" funcref to make sure the invariant class type is used.
8580def Test_funcref_argtype_returntype_check()
8581 var lines =<< trim END
8582 vim9script
8583 class A
8584 endclass
8585 class B extends A
8586 endclass
8587
8588 def Foo(p: B): B
8589 return B.new()
8590 enddef
8591
8592 var Bar: func(A): A = Foo
8593 END
8594 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8595
8596 lines =<< trim END
8597 vim9script
8598 class A
8599 endclass
8600 class B extends A
8601 endclass
8602
8603 def Foo(p: B): B
8604 return B.new()
8605 enddef
8606
8607 def Baz()
8608 var Bar: func(A): A = Foo
8609 enddef
8610 Baz()
8611 END
8612 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8613enddef
8614
Ernie Rael96952b22023-10-17 18:15:01 +02008615def Test_funcref_argtype_invariance_check()
8616 var lines =<< trim END
8617 vim9script
8618
8619 class A
8620 endclass
8621 class B extends A
8622 endclass
8623 class C extends B
8624 endclass
8625
8626 var Func: func(B): number
8627 Func = (o: B): number => 3
8628 assert_equal(3, Func(B.new()))
8629 END
8630 v9.CheckSourceSuccess(lines)
8631
8632 lines =<< trim END
8633 vim9script
8634
8635 class A
8636 endclass
8637 class B extends A
8638 endclass
8639 class C extends B
8640 endclass
8641
8642 var Func: func(B): number
8643 Func = (o: A): number => 3
8644 END
8645 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8646
8647 lines =<< trim END
8648 vim9script
8649
8650 class A
8651 endclass
8652 class B extends A
8653 endclass
8654 class C extends B
8655 endclass
8656
8657 var Func: func(B): number
8658 Func = (o: C): number => 3
8659 END
8660 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8661enddef
8662
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008663" Test for using an operator (e.g. +) with an assignment
8664def Test_op_and_assignment()
8665 # Using += with a class variable
8666 var lines =<< trim END
8667 vim9script
8668 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008669 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008670 static def Foo(): list<number>
8671 val += [1]
8672 return val
8673 enddef
8674 endclass
8675 def Bar(): list<number>
8676 A.val += [2]
8677 return A.val
8678 enddef
8679 assert_equal([1], A.Foo())
8680 assert_equal([1, 2], Bar())
8681 A.val += [3]
8682 assert_equal([1, 2, 3], A.val)
8683 END
8684 v9.CheckSourceSuccess(lines)
8685
8686 # Using += with an object variable
8687 lines =<< trim END
8688 vim9script
8689 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008690 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008691 def Foo(): list<number>
8692 this.val += [1]
8693 return this.val
8694 enddef
8695 endclass
8696 def Bar(bar_a: A): list<number>
8697 bar_a.val += [2]
8698 return bar_a.val
8699 enddef
8700 var a = A.new()
8701 assert_equal([1], a.Foo())
8702 assert_equal([1, 2], Bar(a))
8703 a.val += [3]
8704 assert_equal([1, 2, 3], a.val)
8705 END
8706 v9.CheckSourceSuccess(lines)
8707enddef
8708
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008709" Test for using an object method as a funcref
8710def Test_object_funcref()
8711 # Using object method funcref from a def function
8712 var lines =<< trim END
8713 vim9script
8714 class A
8715 def Foo(): list<number>
8716 return [3, 2, 1]
8717 enddef
8718 endclass
8719 def Bar()
8720 var a = A.new()
8721 var Fn = a.Foo
8722 assert_equal([3, 2, 1], Fn())
8723 enddef
8724 Bar()
8725 END
8726 v9.CheckSourceSuccess(lines)
8727
8728 # Using object method funcref at the script level
8729 lines =<< trim END
8730 vim9script
8731 class A
8732 def Foo(): dict<number>
8733 return {a: 1, b: 2}
8734 enddef
8735 endclass
8736 var a = A.new()
8737 var Fn = a.Foo
8738 assert_equal({a: 1, b: 2}, Fn())
8739 END
8740 v9.CheckSourceSuccess(lines)
8741
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008742 # Using object method funcref at the script level
8743 lines =<< trim END
8744 vim9script
8745 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008746 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008747 def Foo(): number
8748 return this.val
8749 enddef
8750 endclass
8751 var a = A.new(345)
8752 var Fn = a.Foo
8753 assert_equal(345, Fn())
8754 END
8755 v9.CheckSourceSuccess(lines)
8756
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008757 # Using object method funcref from another object method
8758 lines =<< trim END
8759 vim9script
8760 class A
8761 def Foo(): list<number>
8762 return [3, 2, 1]
8763 enddef
8764 def Bar()
8765 var Fn = this.Foo
8766 assert_equal([3, 2, 1], Fn())
8767 enddef
8768 endclass
8769 var a = A.new()
8770 a.Bar()
8771 END
8772 v9.CheckSourceSuccess(lines)
8773
8774 # Using function() to get a object method funcref
8775 lines =<< trim END
8776 vim9script
8777 class A
8778 def Foo(l: list<any>): list<any>
8779 return l
8780 enddef
8781 endclass
8782 var a = A.new()
8783 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8784 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8785 END
8786 v9.CheckSourceSuccess(lines)
8787
8788 # Use an object method with a function returning a funcref and then call the
8789 # funcref.
8790 lines =<< trim END
8791 vim9script
8792
8793 def Map(F: func(number): number): func(number): number
8794 return (n: number) => F(n)
8795 enddef
8796
8797 class Math
8798 def Double(n: number): number
8799 return 2 * n
8800 enddef
8801 endclass
8802
8803 const math = Math.new()
8804 assert_equal(48, Map(math.Double)(24))
8805 END
8806 v9.CheckSourceSuccess(lines)
8807
Ernie Rael03042a22023-11-11 08:53:32 +01008808 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008809 lines =<< trim END
8810 vim9script
8811 class A
8812 def _Foo()
8813 enddef
8814 endclass
8815 def Bar()
8816 var a = A.new()
8817 var Fn = a._Foo
8818 enddef
8819 Bar()
8820 END
Ernie Rael03042a22023-11-11 08:53:32 +01008821 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008822
Ernie Rael03042a22023-11-11 08:53:32 +01008823 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008824 lines =<< trim END
8825 vim9script
8826 class A
8827 def _Foo()
8828 enddef
8829 endclass
8830 var a = A.new()
8831 var Fn = a._Foo
8832 END
Ernie Rael03042a22023-11-11 08:53:32 +01008833 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008834
Ernie Rael03042a22023-11-11 08:53:32 +01008835 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008836 lines =<< trim END
8837 vim9script
8838 class A
8839 def _Foo(): list<number>
8840 return [3, 2, 1]
8841 enddef
8842 def Bar()
8843 var Fn = this._Foo
8844 assert_equal([3, 2, 1], Fn())
8845 enddef
8846 endclass
8847 var a = A.new()
8848 a.Bar()
8849 END
8850 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008851
8852 # Using object method funcref using call()
8853 lines =<< trim END
8854 vim9script
8855 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008856 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008857 def Foo(): number
8858 return this.val
8859 enddef
8860 endclass
8861
8862 def Bar(obj: A)
8863 assert_equal(123, call(obj.Foo, []))
8864 enddef
8865
8866 var a = A.new(123)
8867 Bar(a)
8868 assert_equal(123, call(a.Foo, []))
8869 END
8870 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008871enddef
8872
8873" Test for using a class method as a funcref
8874def Test_class_funcref()
8875 # Using class method funcref in a def function
8876 var lines =<< trim END
8877 vim9script
8878 class A
8879 static def Foo(): list<number>
8880 return [3, 2, 1]
8881 enddef
8882 endclass
8883 def Bar()
8884 var Fn = A.Foo
8885 assert_equal([3, 2, 1], Fn())
8886 enddef
8887 Bar()
8888 END
8889 v9.CheckSourceSuccess(lines)
8890
8891 # Using class method funcref at script level
8892 lines =<< trim END
8893 vim9script
8894 class A
8895 static def Foo(): dict<number>
8896 return {a: 1, b: 2}
8897 enddef
8898 endclass
8899 var Fn = A.Foo
8900 assert_equal({a: 1, b: 2}, Fn())
8901 END
8902 v9.CheckSourceSuccess(lines)
8903
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008904 # Using class method funcref at the script level
8905 lines =<< trim END
8906 vim9script
8907 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008908 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008909 static def Foo(): number
8910 return val
8911 enddef
8912 endclass
8913 A.val = 567
8914 var Fn = A.Foo
8915 assert_equal(567, Fn())
8916 END
8917 v9.CheckSourceSuccess(lines)
8918
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008919 # Using function() to get a class method funcref
8920 lines =<< trim END
8921 vim9script
8922 class A
8923 static def Foo(l: list<any>): list<any>
8924 return l
8925 enddef
8926 endclass
8927 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8928 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8929 END
8930 v9.CheckSourceSuccess(lines)
8931
8932 # Using a class method funcref from another class method
8933 lines =<< trim END
8934 vim9script
8935 class A
8936 static def Foo(): list<number>
8937 return [3, 2, 1]
8938 enddef
8939 static def Bar()
8940 var Fn = Foo
8941 assert_equal([3, 2, 1], Fn())
8942 enddef
8943 endclass
8944 A.Bar()
8945 END
8946 v9.CheckSourceSuccess(lines)
8947
8948 # Use a class method with a function returning a funcref and then call the
8949 # funcref.
8950 lines =<< trim END
8951 vim9script
8952
8953 def Map(F: func(number): number): func(number): number
8954 return (n: number) => F(n)
8955 enddef
8956
8957 class Math
8958 static def StaticDouble(n: number): number
8959 return 2 * n
8960 enddef
8961 endclass
8962
8963 assert_equal(48, Map(Math.StaticDouble)(24))
8964 END
8965 v9.CheckSourceSuccess(lines)
8966
Ernie Rael03042a22023-11-11 08:53:32 +01008967 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008968 lines =<< trim END
8969 vim9script
8970 class A
8971 static def _Foo()
8972 enddef
8973 endclass
8974 def Bar()
8975 var Fn = A._Foo
8976 enddef
8977 Bar()
8978 END
Ernie Rael03042a22023-11-11 08:53:32 +01008979 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008980
Ernie Rael03042a22023-11-11 08:53:32 +01008981 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008982 lines =<< trim END
8983 vim9script
8984 class A
8985 static def _Foo()
8986 enddef
8987 endclass
8988 var Fn = A._Foo
8989 END
Ernie Rael03042a22023-11-11 08:53:32 +01008990 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008991
Ernie Rael03042a22023-11-11 08:53:32 +01008992 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008993 lines =<< trim END
8994 vim9script
8995 class A
8996 static def _Foo(): list<number>
8997 return [3, 2, 1]
8998 enddef
8999 static def Bar()
9000 var Fn = _Foo
9001 assert_equal([3, 2, 1], Fn())
9002 enddef
9003 endclass
9004 A.Bar()
9005 END
9006 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02009007
9008 # Using class method funcref using call()
9009 lines =<< trim END
9010 vim9script
9011 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009012 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02009013 static def Foo(): number
9014 return val
9015 enddef
9016 endclass
9017
9018 def Bar()
9019 A.val = 468
9020 assert_equal(468, call(A.Foo, []))
9021 enddef
9022 Bar()
9023 assert_equal(468, call(A.Foo, []))
9024 END
9025 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009026enddef
9027
9028" Test for using an object member as a funcref
9029def Test_object_member_funcref()
9030 # Using a funcref object variable in an object method
9031 var lines =<< trim END
9032 vim9script
9033 def Foo(n: number): number
9034 return n * 10
9035 enddef
9036
9037 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009038 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009039 def Bar()
9040 assert_equal(200, this.Cb(20))
9041 enddef
9042 endclass
9043
9044 var a = A.new()
9045 a.Bar()
9046 END
9047 v9.CheckSourceSuccess(lines)
9048
9049 # Using a funcref object variable in a def method
9050 lines =<< trim END
9051 vim9script
9052 def Foo(n: number): number
9053 return n * 10
9054 enddef
9055
9056 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009057 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009058 endclass
9059
9060 def Bar()
9061 var a = A.new()
9062 assert_equal(200, a.Cb(20))
9063 enddef
9064 Bar()
9065 END
9066 v9.CheckSourceSuccess(lines)
9067
9068 # Using a funcref object variable at script level
9069 lines =<< trim END
9070 vim9script
9071 def Foo(n: number): number
9072 return n * 10
9073 enddef
9074
9075 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009076 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009077 endclass
9078
9079 var a = A.new()
9080 assert_equal(200, a.Cb(20))
9081 END
9082 v9.CheckSourceSuccess(lines)
9083
9084 # Using a funcref object variable pointing to an object method in an object
9085 # method.
9086 lines =<< trim END
9087 vim9script
9088 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009089 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009090 def Foo(n: number): number
9091 return n * 10
9092 enddef
9093 def Bar()
9094 assert_equal(200, this.Cb(20))
9095 enddef
9096 endclass
9097
9098 var a = A.new()
9099 a.Bar()
9100 END
9101 v9.CheckSourceSuccess(lines)
9102
9103 # Using a funcref object variable pointing to an object method in a def
9104 # method.
9105 lines =<< trim END
9106 vim9script
9107 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009108 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009109 def Foo(n: number): number
9110 return n * 10
9111 enddef
9112 endclass
9113
9114 def Bar()
9115 var a = A.new()
9116 assert_equal(200, a.Cb(20))
9117 enddef
9118 Bar()
9119 END
9120 v9.CheckSourceSuccess(lines)
9121
9122 # Using a funcref object variable pointing to an object method at script
9123 # level.
9124 lines =<< trim END
9125 vim9script
9126 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009127 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009128 def Foo(n: number): number
9129 return n * 10
9130 enddef
9131 endclass
9132
9133 var a = A.new()
9134 assert_equal(200, a.Cb(20))
9135 END
9136 v9.CheckSourceSuccess(lines)
9137enddef
9138
9139" Test for using a class member as a funcref
9140def Test_class_member_funcref()
9141 # Using a funcref class variable in a class method
9142 var lines =<< trim END
9143 vim9script
9144 def Foo(n: number): number
9145 return n * 10
9146 enddef
9147
9148 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009149 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009150 static def Bar()
9151 assert_equal(200, Cb(20))
9152 enddef
9153 endclass
9154
9155 A.Bar()
9156 END
9157 v9.CheckSourceSuccess(lines)
9158
9159 # Using a funcref class variable in a def method
9160 lines =<< trim END
9161 vim9script
9162 def Foo(n: number): number
9163 return n * 10
9164 enddef
9165
9166 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009167 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009168 endclass
9169
9170 def Bar()
9171 assert_equal(200, A.Cb(20))
9172 enddef
9173 Bar()
9174 END
9175 v9.CheckSourceSuccess(lines)
9176
9177 # Using a funcref class variable at script level
9178 lines =<< trim END
9179 vim9script
9180 def Foo(n: number): number
9181 return n * 10
9182 enddef
9183
9184 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009185 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009186 endclass
9187
9188 assert_equal(200, A.Cb(20))
9189 END
9190 v9.CheckSourceSuccess(lines)
9191
9192 # Using a funcref class variable pointing to a class method in a class
9193 # method.
9194 lines =<< trim END
9195 vim9script
9196 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009197 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009198 static def Foo(n: number): number
9199 return n * 10
9200 enddef
9201 static def Init()
9202 Cb = Foo
9203 enddef
9204 static def Bar()
9205 assert_equal(200, Cb(20))
9206 enddef
9207 endclass
9208
9209 A.Init()
9210 A.Bar()
9211 END
9212 v9.CheckSourceSuccess(lines)
9213
9214 # Using a funcref class variable pointing to a class method in a def method.
9215 lines =<< trim END
9216 vim9script
9217 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009218 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009219 static def Foo(n: number): number
9220 return n * 10
9221 enddef
9222 static def Init()
9223 Cb = Foo
9224 enddef
9225 endclass
9226
9227 def Bar()
9228 A.Init()
9229 assert_equal(200, A.Cb(20))
9230 enddef
9231 Bar()
9232 END
9233 v9.CheckSourceSuccess(lines)
9234
9235 # Using a funcref class variable pointing to a class method at script level.
9236 lines =<< trim END
9237 vim9script
9238 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009239 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009240 static def Foo(n: number): number
9241 return n * 10
9242 enddef
9243 static def Init()
9244 Cb = Foo
9245 enddef
9246 endclass
9247
9248 A.Init()
9249 assert_equal(200, A.Cb(20))
9250 END
9251 v9.CheckSourceSuccess(lines)
9252enddef
9253
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009254" Test for using object methods as popup callback functions
9255def Test_objmethod_popup_callback()
9256 # Use the popup from the script level
9257 var lines =<< trim END
9258 vim9script
9259
9260 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009261 var selection: number = -1
9262 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009263
9264 def PopupFilter(id: number, key: string): bool
9265 add(this.filterkeys, key)
9266 return popup_filter_yesno(id, key)
9267 enddef
9268
9269 def PopupCb(id: number, result: number)
9270 this.selection = result ? 100 : 200
9271 enddef
9272 endclass
9273
9274 var a = A.new()
9275 feedkeys('', 'xt')
9276 var winid = popup_create('Y/N?',
9277 {filter: a.PopupFilter, callback: a.PopupCb})
9278 feedkeys('y', 'xt')
9279 popup_close(winid)
9280 assert_equal(100, a.selection)
9281 assert_equal(['y'], a.filterkeys)
9282 feedkeys('', 'xt')
9283 winid = popup_create('Y/N?',
9284 {filter: a.PopupFilter, callback: a.PopupCb})
9285 feedkeys('n', 'xt')
9286 popup_close(winid)
9287 assert_equal(200, a.selection)
9288 assert_equal(['y', 'n'], a.filterkeys)
9289 END
9290 v9.CheckSourceSuccess(lines)
9291
9292 # Use the popup from a def function
9293 lines =<< trim END
9294 vim9script
9295
9296 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009297 var selection: number = -1
9298 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009299
9300 def PopupFilter(id: number, key: string): bool
9301 add(this.filterkeys, key)
9302 return popup_filter_yesno(id, key)
9303 enddef
9304
9305 def PopupCb(id: number, result: number)
9306 this.selection = result ? 100 : 200
9307 enddef
9308 endclass
9309
9310 def Foo()
9311 var a = A.new()
9312 feedkeys('', 'xt')
9313 var winid = popup_create('Y/N?',
9314 {filter: a.PopupFilter, callback: a.PopupCb})
9315 feedkeys('y', 'xt')
9316 popup_close(winid)
9317 assert_equal(100, a.selection)
9318 assert_equal(['y'], a.filterkeys)
9319 feedkeys('', 'xt')
9320 winid = popup_create('Y/N?',
9321 {filter: a.PopupFilter, callback: a.PopupCb})
9322 feedkeys('n', 'xt')
9323 popup_close(winid)
9324 assert_equal(200, a.selection)
9325 assert_equal(['y', 'n'], a.filterkeys)
9326 enddef
9327 Foo()
9328 END
9329 v9.CheckSourceSuccess(lines)
9330enddef
9331
9332" Test for using class methods as popup callback functions
9333def Test_classmethod_popup_callback()
9334 # Use the popup from the script level
9335 var lines =<< trim END
9336 vim9script
9337
9338 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009339 static var selection: number = -1
9340 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009341
9342 static def PopupFilter(id: number, key: string): bool
9343 add(filterkeys, key)
9344 return popup_filter_yesno(id, key)
9345 enddef
9346
9347 static def PopupCb(id: number, result: number)
9348 selection = result ? 100 : 200
9349 enddef
9350 endclass
9351
9352 feedkeys('', 'xt')
9353 var winid = popup_create('Y/N?',
9354 {filter: A.PopupFilter, callback: A.PopupCb})
9355 feedkeys('y', 'xt')
9356 popup_close(winid)
9357 assert_equal(100, A.selection)
9358 assert_equal(['y'], A.filterkeys)
9359 feedkeys('', 'xt')
9360 winid = popup_create('Y/N?',
9361 {filter: A.PopupFilter, callback: A.PopupCb})
9362 feedkeys('n', 'xt')
9363 popup_close(winid)
9364 assert_equal(200, A.selection)
9365 assert_equal(['y', 'n'], A.filterkeys)
9366 END
9367 v9.CheckSourceSuccess(lines)
9368
9369 # Use the popup from a def function
9370 lines =<< trim END
9371 vim9script
9372
9373 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009374 static var selection: number = -1
9375 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009376
9377 static def PopupFilter(id: number, key: string): bool
9378 add(filterkeys, key)
9379 return popup_filter_yesno(id, key)
9380 enddef
9381
9382 static def PopupCb(id: number, result: number)
9383 selection = result ? 100 : 200
9384 enddef
9385 endclass
9386
9387 def Foo()
9388 feedkeys('', 'xt')
9389 var winid = popup_create('Y/N?',
9390 {filter: A.PopupFilter, callback: A.PopupCb})
9391 feedkeys('y', 'xt')
9392 popup_close(winid)
9393 assert_equal(100, A.selection)
9394 assert_equal(['y'], A.filterkeys)
9395 feedkeys('', 'xt')
9396 winid = popup_create('Y/N?',
9397 {filter: A.PopupFilter, callback: A.PopupCb})
9398 feedkeys('n', 'xt')
9399 popup_close(winid)
9400 assert_equal(200, A.selection)
9401 assert_equal(['y', 'n'], A.filterkeys)
9402 enddef
9403 Foo()
9404 END
9405 v9.CheckSourceSuccess(lines)
9406enddef
9407
9408" Test for using an object method as a timer callback function
9409def Test_objmethod_timer_callback()
9410 # Use the timer callback from script level
9411 var lines =<< trim END
9412 vim9script
9413
9414 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009415 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009416 def TimerCb(timerID: number)
9417 this.timerTick = 6
9418 enddef
9419 endclass
9420
9421 var a = A.new()
9422 timer_start(0, a.TimerCb)
9423 var maxWait = 5
9424 while maxWait > 0 && a.timerTick == -1
9425 :sleep 10m
9426 maxWait -= 1
9427 endwhile
9428 assert_equal(6, a.timerTick)
9429 END
9430 v9.CheckSourceSuccess(lines)
9431
9432 # Use the timer callback from a def function
9433 lines =<< trim END
9434 vim9script
9435
9436 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009437 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009438 def TimerCb(timerID: number)
9439 this.timerTick = 6
9440 enddef
9441 endclass
9442
9443 def Foo()
9444 var a = A.new()
9445 timer_start(0, a.TimerCb)
9446 var maxWait = 5
9447 while maxWait > 0 && a.timerTick == -1
9448 :sleep 10m
9449 maxWait -= 1
9450 endwhile
9451 assert_equal(6, a.timerTick)
9452 enddef
9453 Foo()
9454 END
9455 v9.CheckSourceSuccess(lines)
9456enddef
9457
9458" Test for using a class method as a timer callback function
9459def Test_classmethod_timer_callback()
9460 # Use the timer callback from script level
9461 var lines =<< trim END
9462 vim9script
9463
9464 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009465 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009466 static def TimerCb(timerID: number)
9467 timerTick = 6
9468 enddef
9469 endclass
9470
9471 timer_start(0, A.TimerCb)
9472 var maxWait = 5
9473 while maxWait > 0 && A.timerTick == -1
9474 :sleep 10m
9475 maxWait -= 1
9476 endwhile
9477 assert_equal(6, A.timerTick)
9478 END
9479 v9.CheckSourceSuccess(lines)
9480
9481 # Use the timer callback from a def function
9482 lines =<< trim END
9483 vim9script
9484
9485 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009486 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009487 static def TimerCb(timerID: number)
9488 timerTick = 6
9489 enddef
9490 endclass
9491
9492 def Foo()
9493 timer_start(0, A.TimerCb)
9494 var maxWait = 5
9495 while maxWait > 0 && A.timerTick == -1
9496 :sleep 10m
9497 maxWait -= 1
9498 endwhile
9499 assert_equal(6, A.timerTick)
9500 enddef
9501 Foo()
9502 END
9503 v9.CheckSourceSuccess(lines)
9504enddef
9505
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009506" Test for using a class variable as the first and/or second operand of a binary
9507" operator.
9508def Test_class_variable_as_operands()
9509 var lines =<< trim END
9510 vim9script
9511 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009512 static var truthy: bool = true
9513 public static var TruthyFn: func
9514 static var list: list<any> = []
9515 static var four: number = 4
9516 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009517
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009518 static def Str(): string
9519 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009520 enddef
9521
9522 static def Four(): number
9523 return four
9524 enddef
9525
9526 static def List(): list<any>
9527 return list
9528 enddef
9529
9530 static def Truthy(): bool
9531 return truthy
9532 enddef
9533
9534 def TestOps()
9535 assert_true(Tests.truthy == truthy)
9536 assert_true(truthy == Tests.truthy)
9537 assert_true(Tests.list isnot [])
9538 assert_true([] isnot Tests.list)
9539 assert_equal(2, Tests.four >> 1)
9540 assert_equal(16, 1 << Tests.four)
9541 assert_equal(8, Tests.four + four)
9542 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009543 assert_equal('hellohello', Tests.str .. str)
9544 assert_equal('hellohello', str .. Tests.str)
9545
9546 # Using class variable for list indexing
9547 var l = range(10)
9548 assert_equal(4, l[Tests.four])
9549 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9550
9551 # Using class variable for Dict key
9552 var d = {hello: 'abc'}
9553 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009554 enddef
9555 endclass
9556
9557 def TestOps2()
9558 assert_true(Tests.truthy == Tests.Truthy())
9559 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009560 assert_true(Tests.truthy == Tests.TruthyFn())
9561 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009562 assert_true(Tests.list is Tests.List())
9563 assert_true(Tests.List() is Tests.list)
9564 assert_equal(2, Tests.four >> 1)
9565 assert_equal(16, 1 << Tests.four)
9566 assert_equal(8, Tests.four + Tests.Four())
9567 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009568 assert_equal('hellohello', Tests.str .. Tests.Str())
9569 assert_equal('hellohello', Tests.Str() .. Tests.str)
9570
9571 # Using class variable for list indexing
9572 var l = range(10)
9573 assert_equal(4, l[Tests.four])
9574 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9575
9576 # Using class variable for Dict key
9577 var d = {hello: 'abc'}
9578 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009579 enddef
9580
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009581 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009582 var t = Tests.new()
9583 t.TestOps()
9584 TestOps2()
9585
9586 assert_true(Tests.truthy == Tests.Truthy())
9587 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009588 assert_true(Tests.truthy == Tests.TruthyFn())
9589 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009590 assert_true(Tests.list is Tests.List())
9591 assert_true(Tests.List() is Tests.list)
9592 assert_equal(2, Tests.four >> 1)
9593 assert_equal(16, 1 << Tests.four)
9594 assert_equal(8, Tests.four + Tests.Four())
9595 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009596 assert_equal('hellohello', Tests.str .. Tests.Str())
9597 assert_equal('hellohello', Tests.Str() .. Tests.str)
9598
9599 # Using class variable for list indexing
9600 var l = range(10)
9601 assert_equal(4, l[Tests.four])
9602 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9603
9604 # Using class variable for Dict key
9605 var d = {hello: 'abc'}
9606 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009607 END
9608 v9.CheckSourceSuccess(lines)
9609enddef
9610
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009611" Test for checking the type of the key used to access an object dict member.
9612def Test_dict_member_key_type_check()
9613 var lines =<< trim END
9614 vim9script
9615
9616 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009617 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009618 endclass
9619
9620 class Test extends State
9621 def ObjMethodTests()
9622 var cursor: number = 0
9623 var z: number = 0
9624 [this.numbers[cursor]] = ['zero.1']
9625 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9626 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9627 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9628 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9629 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9630 [this.numbers[cursor], z] = ['zero.4', 1]
9631 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9632 [z, this.numbers[cursor]] = [1, 'zero.5']
9633 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9634 enddef
9635
9636 static def ClassMethodTests(that: State)
9637 var cursor: number = 0
9638 var z: number = 0
9639 [that.numbers[cursor]] = ['zero.1']
9640 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9641 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9642 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9643 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9644 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9645 [that.numbers[cursor], z] = ['zero.4', 1]
9646 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9647 [z, that.numbers[cursor]] = [1, 'zero.5']
9648 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9649 enddef
9650
9651 def new()
9652 enddef
9653
9654 def newMethodTests()
9655 var cursor: number = 0
9656 var z: number
9657 [this.numbers[cursor]] = ['zero.1']
9658 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9659 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9660 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9661 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9662 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9663 [this.numbers[cursor], z] = ['zero.4', 1]
9664 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9665 [z, this.numbers[cursor]] = [1, 'zero.5']
9666 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9667 enddef
9668 endclass
9669
9670 def DefFuncTests(that: Test)
9671 var cursor: number = 0
9672 var z: number
9673 [that.numbers[cursor]] = ['zero.1']
9674 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9675 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9676 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9677 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9678 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9679 [that.numbers[cursor], z] = ['zero.4', 1]
9680 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9681 [z, that.numbers[cursor]] = [1, 'zero.5']
9682 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9683 enddef
9684
9685 Test.newMethodTests()
9686 Test.new().ObjMethodTests()
9687 Test.ClassMethodTests(Test.new())
9688 DefFuncTests(Test.new())
9689
9690 const test: Test = Test.new()
9691 var cursor: number = 0
9692 [test.numbers[cursor], cursor] = ['zero', 1]
9693 [cursor, test.numbers[cursor]] = [1, 'one']
9694 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9695 END
9696 v9.CheckSourceSuccess(lines)
9697
9698 lines =<< trim END
9699 vim9script
9700
9701 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009702 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009703
9704 def new()
9705 enddef
9706
9707 def Foo()
9708 var z: number
9709 [this.numbers.a, z] = [{}, 10]
9710 enddef
9711 endclass
9712
9713 var a = A.new()
9714 a.Foo()
9715 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009716 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009717
9718 lines =<< trim END
9719 vim9script
9720
9721 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009722 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009723
9724 def new()
9725 enddef
9726
9727 def Foo()
9728 var x: string = 'a'
9729 var y: number
9730 [this.numbers[x], y] = [{}, 10]
9731 enddef
9732 endclass
9733
9734 var a = A.new()
9735 a.Foo()
9736 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009737 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009738enddef
9739
mityua5550692023-11-25 15:41:20 +01009740def Test_compile_many_def_functions_in_funcref_instr()
9741 # This used to crash Vim. This is reproducible only when run on new instance
9742 # of Vim.
9743 var lines =<< trim END
9744 vim9script
9745
9746 class A
9747 def new()
9748 this.TakeFunc(this.F00)
9749 enddef
9750
9751 def TakeFunc(F: func)
9752 enddef
9753
9754 def F00()
9755 this.F01()
9756 this.F02()
9757 this.F03()
9758 this.F04()
9759 this.F05()
9760 this.F06()
9761 this.F07()
9762 this.F08()
9763 this.F09()
9764 this.F10()
9765 this.F11()
9766 this.F12()
9767 this.F13()
9768 this.F14()
9769 this.F15()
9770 this.F16()
9771 this.F17()
9772 this.F18()
9773 this.F19()
9774 this.F20()
9775 this.F21()
9776 this.F22()
9777 this.F23()
9778 this.F24()
9779 this.F25()
9780 this.F26()
9781 this.F27()
9782 this.F28()
9783 this.F29()
9784 this.F30()
9785 this.F31()
9786 this.F32()
9787 this.F33()
9788 this.F34()
9789 this.F35()
9790 this.F36()
9791 this.F37()
9792 this.F38()
9793 this.F39()
9794 this.F40()
9795 this.F41()
9796 this.F42()
9797 this.F43()
9798 this.F44()
9799 this.F45()
9800 this.F46()
9801 this.F47()
9802 enddef
9803
9804 def F01()
9805 enddef
9806 def F02()
9807 enddef
9808 def F03()
9809 enddef
9810 def F04()
9811 enddef
9812 def F05()
9813 enddef
9814 def F06()
9815 enddef
9816 def F07()
9817 enddef
9818 def F08()
9819 enddef
9820 def F09()
9821 enddef
9822 def F10()
9823 enddef
9824 def F11()
9825 enddef
9826 def F12()
9827 enddef
9828 def F13()
9829 enddef
9830 def F14()
9831 enddef
9832 def F15()
9833 enddef
9834 def F16()
9835 enddef
9836 def F17()
9837 enddef
9838 def F18()
9839 enddef
9840 def F19()
9841 enddef
9842 def F20()
9843 enddef
9844 def F21()
9845 enddef
9846 def F22()
9847 enddef
9848 def F23()
9849 enddef
9850 def F24()
9851 enddef
9852 def F25()
9853 enddef
9854 def F26()
9855 enddef
9856 def F27()
9857 enddef
9858 def F28()
9859 enddef
9860 def F29()
9861 enddef
9862 def F30()
9863 enddef
9864 def F31()
9865 enddef
9866 def F32()
9867 enddef
9868 def F33()
9869 enddef
9870 def F34()
9871 enddef
9872 def F35()
9873 enddef
9874 def F36()
9875 enddef
9876 def F37()
9877 enddef
9878 def F38()
9879 enddef
9880 def F39()
9881 enddef
9882 def F40()
9883 enddef
9884 def F41()
9885 enddef
9886 def F42()
9887 enddef
9888 def F43()
9889 enddef
9890 def F44()
9891 enddef
9892 def F45()
9893 enddef
9894 def F46()
9895 enddef
9896 def F47()
9897 enddef
9898 endclass
9899
9900 A.new()
9901 END
9902 writefile(lines, 'Xscript', 'D')
9903 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9904 assert_equal(0, v:shell_error)
9905enddef
9906
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009907" Test for 'final' class and object variables
9908def Test_final_class_object_variable()
9909 # Test for changing a final object variable from an object function
9910 var lines =<< trim END
9911 vim9script
9912 class A
9913 final foo: string = "abc"
9914 def Foo()
9915 this.foo = "def"
9916 enddef
9917 endclass
9918 defcompile A.Foo
9919 END
9920 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9921
9922 # Test for changing a final object variable from the 'new' function
9923 lines =<< trim END
9924 vim9script
9925 class A
9926 final s1: string
9927 final s2: string
9928 def new(this.s1)
9929 this.s2 = 'def'
9930 enddef
9931 endclass
9932 var a = A.new('abc')
9933 assert_equal('abc', a.s1)
9934 assert_equal('def', a.s2)
9935 END
9936 v9.CheckSourceSuccess(lines)
9937
9938 # Test for a final class variable
9939 lines =<< trim END
9940 vim9script
9941 class A
9942 static final s1: string = "abc"
9943 endclass
9944 assert_equal('abc', A.s1)
9945 END
9946 v9.CheckSourceSuccess(lines)
9947
9948 # Test for changing a final class variable from a class function
9949 lines =<< trim END
9950 vim9script
9951 class A
9952 static final s1: string = "abc"
9953 static def Foo()
9954 s1 = "def"
9955 enddef
9956 endclass
9957 A.Foo()
9958 END
9959 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9960
9961 # Test for changing a public final class variable at script level
9962 lines =<< trim END
9963 vim9script
9964 class A
9965 public static final s1: string = "abc"
9966 endclass
9967 assert_equal('abc', A.s1)
9968 A.s1 = 'def'
9969 END
9970 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9971
9972 # Test for changing a public final class variable from a class function
9973 lines =<< trim END
9974 vim9script
9975 class A
9976 public static final s1: string = "abc"
9977 static def Foo()
9978 s1 = "def"
9979 enddef
9980 endclass
9981 A.Foo()
9982 END
9983 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9984
9985 # Test for changing a public final class variable from a function
9986 lines =<< trim END
9987 vim9script
9988 class A
9989 public static final s1: string = "abc"
9990 endclass
9991 def Foo()
9992 A.s1 = 'def'
9993 enddef
9994 defcompile
9995 END
9996 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9997
9998 # Test for using a final variable of composite type
9999 lines =<< trim END
10000 vim9script
10001 class A
10002 public final l: list<number>
10003 def new()
10004 this.l = [1, 2]
10005 enddef
10006 def Foo()
10007 this.l[0] = 3
10008 this.l->add(4)
10009 enddef
10010 endclass
10011 var a = A.new()
10012 assert_equal([1, 2], a.l)
10013 a.Foo()
10014 assert_equal([3, 2, 4], a.l)
10015 END
10016 v9.CheckSourceSuccess(lines)
10017
10018 # Test for changing a final variable of composite type from another object
10019 # function
10020 lines =<< trim END
10021 vim9script
10022 class A
10023 public final l: list<number> = [1, 2]
10024 def Foo()
10025 this.l = [3, 4]
10026 enddef
10027 endclass
10028 var a = A.new()
10029 a.Foo()
10030 END
10031 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10032
10033 # Test for modifying a final variable of composite type at script level
10034 lines =<< trim END
10035 vim9script
10036 class A
10037 public final l: list<number> = [1, 2]
10038 endclass
10039 var a = A.new()
10040 a.l[0] = 3
10041 a.l->add(4)
10042 assert_equal([3, 2, 4], a.l)
10043 END
10044 v9.CheckSourceSuccess(lines)
10045
10046 # Test for modifying a final variable of composite type from a function
10047 lines =<< trim END
10048 vim9script
10049 class A
10050 public final l: list<number> = [1, 2]
10051 endclass
10052 def Foo()
10053 var a = A.new()
10054 a.l[0] = 3
10055 a.l->add(4)
10056 assert_equal([3, 2, 4], a.l)
10057 enddef
10058 Foo()
10059 END
10060 v9.CheckSourceSuccess(lines)
10061
10062 # Test for modifying a final variable of composite type from another object
10063 # function
10064 lines =<< trim END
10065 vim9script
10066 class A
10067 public final l: list<number> = [1, 2]
10068 def Foo()
10069 this.l[0] = 3
10070 this.l->add(4)
10071 enddef
10072 endclass
10073 var a = A.new()
10074 a.Foo()
10075 assert_equal([3, 2, 4], a.l)
10076 END
10077 v9.CheckSourceSuccess(lines)
10078
10079 # Test for assigning a new value to a final variable of composite type at
10080 # script level
10081 lines =<< trim END
10082 vim9script
10083 class A
10084 public final l: list<number> = [1, 2]
10085 endclass
10086 var a = A.new()
10087 a.l = [3, 4]
10088 END
10089 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10090
10091 # Test for assigning a new value to a final variable of composite type from
10092 # another object function
10093 lines =<< trim END
10094 vim9script
10095 class A
10096 public final l: list<number> = [1, 2]
10097 def Foo()
10098 this.l = [3, 4]
10099 enddef
10100 endclass
10101 var a = A.new()
10102 a.Foo()
10103 END
10104 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10105
10106 # Test for assigning a new value to a final variable of composite type from
10107 # another function
10108 lines =<< trim END
10109 vim9script
10110 class A
10111 public final l: list<number> = [1, 2]
10112 endclass
10113 def Foo()
10114 var a = A.new()
10115 a.l = [3, 4]
10116 enddef
10117 Foo()
10118 END
10119 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10120
10121 # Error case: Use 'final' with just a variable name
10122 lines =<< trim END
10123 vim9script
10124 class A
10125 final foo
10126 endclass
10127 var a = A.new()
10128 END
10129 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10130
10131 # Error case: Use 'final' followed by 'public'
10132 lines =<< trim END
10133 vim9script
10134 class A
10135 final public foo: number
10136 endclass
10137 var a = A.new()
10138 END
10139 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10140
10141 # Error case: Use 'final' followed by 'static'
10142 lines =<< trim END
10143 vim9script
10144 class A
10145 final static foo: number
10146 endclass
10147 var a = A.new()
10148 END
10149 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10150
10151 # Error case: 'final' cannot be used in an interface
10152 lines =<< trim END
10153 vim9script
10154 interface A
10155 final foo: number = 10
10156 endinterface
10157 END
10158 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
10159
10160 # Error case: 'final' not supported for an object method
10161 lines =<< trim END
10162 vim9script
10163 class A
10164 final def Foo()
10165 enddef
10166 endclass
10167 END
10168 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10169
10170 # Error case: 'final' not supported for a class method
10171 lines =<< trim END
10172 vim9script
10173 class A
10174 static final def Foo()
10175 enddef
10176 endclass
10177 END
10178 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10179enddef
10180
10181" Test for 'const' class and object variables
10182def Test_const_class_object_variable()
10183 # Test for changing a const object variable from an object function
10184 var lines =<< trim END
10185 vim9script
10186 class A
10187 const foo: string = "abc"
10188 def Foo()
10189 this.foo = "def"
10190 enddef
10191 endclass
10192 defcompile A.Foo
10193 END
10194 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
10195
10196 # Test for changing a const object variable from the 'new' function
10197 lines =<< trim END
10198 vim9script
10199 class A
10200 const s1: string
10201 const s2: string
10202 def new(this.s1)
10203 this.s2 = 'def'
10204 enddef
10205 endclass
10206 var a = A.new('abc')
10207 assert_equal('abc', a.s1)
10208 assert_equal('def', a.s2)
10209 END
10210 v9.CheckSourceSuccess(lines)
10211
10212 # Test for changing a const object variable from an object method called from
10213 # the 'new' function
10214 lines =<< trim END
10215 vim9script
10216 class A
10217 const s1: string = 'abc'
10218 def new()
10219 this.ChangeStr()
10220 enddef
10221 def ChangeStr()
10222 this.s1 = 'def'
10223 enddef
10224 endclass
10225 var a = A.new()
10226 END
10227 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10228
10229 # Test for a const class variable
10230 lines =<< trim END
10231 vim9script
10232 class A
10233 static const s1: string = "abc"
10234 endclass
10235 assert_equal('abc', A.s1)
10236 END
10237 v9.CheckSourceSuccess(lines)
10238
10239 # Test for changing a const class variable from a class function
10240 lines =<< trim END
10241 vim9script
10242 class A
10243 static const s1: string = "abc"
10244 static def Foo()
10245 s1 = "def"
10246 enddef
10247 endclass
10248 A.Foo()
10249 END
10250 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10251
10252 # Test for changing a public const class variable at script level
10253 lines =<< trim END
10254 vim9script
10255 class A
10256 public static const s1: string = "abc"
10257 endclass
10258 assert_equal('abc', A.s1)
10259 A.s1 = 'def'
10260 END
10261 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
10262
10263 # Test for changing a public const class variable from a class function
10264 lines =<< trim END
10265 vim9script
10266 class A
10267 public static const s1: string = "abc"
10268 static def Foo()
10269 s1 = "def"
10270 enddef
10271 endclass
10272 A.Foo()
10273 END
10274 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10275
10276 # Test for changing a public const class variable from a function
10277 lines =<< trim END
10278 vim9script
10279 class A
10280 public static const s1: string = "abc"
10281 endclass
10282 def Foo()
10283 A.s1 = 'def'
10284 enddef
10285 defcompile
10286 END
10287 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10288
10289 # Test for changing a const List item from an object function
10290 lines =<< trim END
10291 vim9script
10292 class A
10293 public const l: list<number>
10294 def new()
10295 this.l = [1, 2]
10296 enddef
10297 def Foo()
10298 this.l[0] = 3
10299 enddef
10300 endclass
10301 var a = A.new()
10302 assert_equal([1, 2], a.l)
10303 a.Foo()
10304 END
10305 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10306
10307 # Test for adding a value to a const List from an object function
10308 lines =<< trim END
10309 vim9script
10310 class A
10311 public const l: list<number>
10312 def new()
10313 this.l = [1, 2]
10314 enddef
10315 def Foo()
10316 this.l->add(3)
10317 enddef
10318 endclass
10319 var a = A.new()
10320 a.Foo()
10321 END
10322 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10323
10324 # Test for reassigning a const List from an object function
10325 lines =<< trim END
10326 vim9script
10327 class A
10328 public const l: list<number> = [1, 2]
10329 def Foo()
10330 this.l = [3, 4]
10331 enddef
10332 endclass
10333 var a = A.new()
10334 a.Foo()
10335 END
10336 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10337
10338 # Test for changing a const List item at script level
10339 lines =<< trim END
10340 vim9script
10341 class A
10342 public const l: list<number> = [1, 2]
10343 endclass
10344 var a = A.new()
10345 a.l[0] = 3
10346 END
10347 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10348
10349 # Test for adding a value to a const List item at script level
10350 lines =<< trim END
10351 vim9script
10352 class A
10353 public const l: list<number> = [1, 2]
10354 endclass
10355 var a = A.new()
10356 a.l->add(4)
10357 END
10358 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10359
10360 # Test for changing a const List item from a function
10361 lines =<< trim END
10362 vim9script
10363 class A
10364 public const l: list<number> = [1, 2]
10365 endclass
10366 def Foo()
10367 var a = A.new()
10368 a.l[0] = 3
10369 enddef
10370 Foo()
10371 END
10372 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
10373
10374 # Test for adding a value to a const List item from a function
10375 lines =<< trim END
10376 vim9script
10377 class A
10378 public const l: list<number> = [1, 2]
10379 endclass
10380 def Foo()
10381 var a = A.new()
10382 a.l->add(4)
10383 enddef
10384 Foo()
10385 END
10386 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
10387
10388 # Test for changing a const List item from an object method
10389 lines =<< trim END
10390 vim9script
10391 class A
10392 public const l: list<number> = [1, 2]
10393 def Foo()
10394 this.l[0] = 3
10395 enddef
10396 endclass
10397 var a = A.new()
10398 a.Foo()
10399 END
10400 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10401
10402 # Test for adding a value to a const List item from an object method
10403 lines =<< trim END
10404 vim9script
10405 class A
10406 public const l: list<number> = [1, 2]
10407 def Foo()
10408 this.l->add(4)
10409 enddef
10410 endclass
10411 var a = A.new()
10412 a.Foo()
10413 END
10414 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10415
10416 # Test for reassigning a const List object variable at script level
10417 lines =<< trim END
10418 vim9script
10419 class A
10420 public const l: list<number> = [1, 2]
10421 endclass
10422 var a = A.new()
10423 a.l = [3, 4]
10424 END
10425 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10426
10427 # Test for reassigning a const List object variable from an object method
10428 lines =<< trim END
10429 vim9script
10430 class A
10431 public const l: list<number> = [1, 2]
10432 def Foo()
10433 this.l = [3, 4]
10434 enddef
10435 endclass
10436 var a = A.new()
10437 a.Foo()
10438 END
10439 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10440
10441 # Test for reassigning a const List object variable from another function
10442 lines =<< trim END
10443 vim9script
10444 class A
10445 public const l: list<number> = [1, 2]
10446 endclass
10447 def Foo()
10448 var a = A.new()
10449 a.l = [3, 4]
10450 enddef
10451 Foo()
10452 END
10453 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10454
10455 # Error case: Use 'const' with just a variable name
10456 lines =<< trim END
10457 vim9script
10458 class A
10459 const foo
10460 endclass
10461 var a = A.new()
10462 END
10463 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10464
10465 # Error case: Use 'const' followed by 'public'
10466 lines =<< trim END
10467 vim9script
10468 class A
10469 const public foo: number
10470 endclass
10471 var a = A.new()
10472 END
10473 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10474
10475 # Error case: Use 'const' followed by 'static'
10476 lines =<< trim END
10477 vim9script
10478 class A
10479 const static foo: number
10480 endclass
10481 var a = A.new()
10482 END
10483 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10484
10485 # Error case: 'const' cannot be used in an interface
10486 lines =<< trim END
10487 vim9script
10488 interface A
10489 const foo: number = 10
10490 endinterface
10491 END
10492 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10493
10494 # Error case: 'const' not supported for an object method
10495 lines =<< trim END
10496 vim9script
10497 class A
10498 const def Foo()
10499 enddef
10500 endclass
10501 END
10502 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10503
10504 # Error case: 'const' not supported for a class method
10505 lines =<< trim END
10506 vim9script
10507 class A
10508 static const def Foo()
10509 enddef
10510 endclass
10511 END
10512 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10513enddef
10514
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010515" Test for compiling class/object methods using :defcompile
10516def Test_defcompile_class()
10517 # defcompile all the classes in the current script
10518 var lines =<< trim END
10519 vim9script
10520 class A
10521 def Foo()
10522 var i = 10
10523 enddef
10524 endclass
10525 class B
10526 def Bar()
10527 var i = 20
10528 xxx
10529 enddef
10530 endclass
10531 defcompile
10532 END
10533 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10534
10535 # defcompile a specific class
10536 lines =<< trim END
10537 vim9script
10538 class A
10539 def Foo()
10540 xxx
10541 enddef
10542 endclass
10543 class B
10544 def Bar()
10545 yyy
10546 enddef
10547 endclass
10548 defcompile B
10549 END
10550 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10551
10552 # defcompile a non-class
10553 lines =<< trim END
10554 vim9script
10555 class A
10556 def Foo()
10557 enddef
10558 endclass
10559 var X: list<number> = []
10560 defcompile X
10561 END
10562 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10563
10564 # defcompile a class twice
10565 lines =<< trim END
10566 vim9script
10567 class A
10568 def new()
10569 enddef
10570 endclass
10571 defcompile A
10572 defcompile A
10573 assert_equal('Function A.new does not need compiling', v:statusmsg)
10574 END
10575 v9.CheckSourceSuccess(lines)
10576
10577 # defcompile should not compile an imported class
10578 lines =<< trim END
10579 vim9script
10580 export class A
10581 def Foo()
10582 xxx
10583 enddef
10584 endclass
10585 END
10586 writefile(lines, 'Xdefcompileimport.vim', 'D')
10587 lines =<< trim END
10588 vim9script
10589
10590 import './Xdefcompileimport.vim'
10591 class B
10592 endclass
10593 defcompile
10594 END
10595 v9.CheckScriptSuccess(lines)
10596enddef
10597
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010598" Test for cases common to all the object builtin methods
10599def Test_object_builtin_method()
10600 var lines =<< trim END
10601 vim9script
10602 class A
10603 def abc()
10604 enddef
10605 endclass
10606 END
10607 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10608
10609 for funcname in ["len", "string", "empty"]
10610 lines =<< trim eval END
10611 vim9script
10612 class A
10613 static def {funcname}(): number
10614 enddef
10615 endclass
10616 END
10617 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10618 endfor
10619enddef
10620
10621" Test for using the empty() builtin method with an object
10622" This is a legacy function to use the test_garbagecollect_now() function.
10623func Test_object_empty()
10624 let lines =<< trim END
10625 vim9script
10626 class A
10627 def empty(): bool
10628 return true
10629 enddef
10630 endclass
10631
10632 def Foo()
10633 var afoo = A.new()
10634 assert_equal(true, empty(afoo))
10635 assert_equal(true, afoo->empty())
10636 enddef
10637
10638 var a = A.new()
10639 assert_equal(1, empty(a))
10640 assert_equal(1, a->empty())
10641 test_garbagecollect_now()
10642 assert_equal(1, empty(a))
10643 Foo()
10644 test_garbagecollect_now()
10645 Foo()
10646 END
10647 call v9.CheckSourceSuccess(lines)
10648
10649 " empty() should return 1 without a builtin method
10650 let lines =<< trim END
10651 vim9script
10652 class A
10653 endclass
10654
10655 def Foo()
10656 var afoo = A.new()
10657 assert_equal(1, empty(afoo))
10658 enddef
10659
10660 var a = A.new()
10661 assert_equal(1, empty(a))
10662 Foo()
10663 END
10664 call v9.CheckSourceSuccess(lines)
10665
10666 " Unsupported signature for the empty() method
10667 let lines =<< trim END
10668 vim9script
10669 class A
10670 def empty()
10671 enddef
10672 endclass
10673 END
10674 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10675
10676 " Error when calling the empty() method
10677 let lines =<< trim END
10678 vim9script
10679 class A
10680 def empty(): bool
10681 throw "Failed to check emptiness"
10682 enddef
10683 endclass
10684
10685 def Foo()
10686 var afoo = A.new()
10687 var i = empty(afoo)
10688 enddef
10689
10690 var a = A.new()
10691 assert_fails('empty(a)', 'Failed to check emptiness')
10692 assert_fails('Foo()', 'Failed to check emptiness')
10693 END
10694 call v9.CheckSourceSuccess(lines)
10695
10696 " call empty() using an object from a script
10697 let lines =<< trim END
10698 vim9script
10699 class A
10700 def empty(): bool
10701 return true
10702 enddef
10703 endclass
10704 var afoo = A.new()
10705 assert_equal(true, afoo.empty())
10706 END
10707 call v9.CheckSourceSuccess(lines)
10708
10709 " call empty() using an object from a method
10710 let lines =<< trim END
10711 vim9script
10712 class A
10713 def empty(): bool
10714 return true
10715 enddef
10716 endclass
10717 def Foo()
10718 var afoo = A.new()
10719 assert_equal(true, afoo.empty())
10720 enddef
10721 Foo()
10722 END
10723 call v9.CheckSourceSuccess(lines)
10724
10725 " call empty() using "this" from an object method
10726 let lines =<< trim END
10727 vim9script
10728 class A
10729 def empty(): bool
10730 return true
10731 enddef
10732 def Foo(): bool
10733 return this.empty()
10734 enddef
10735 endclass
10736 def Bar()
10737 var abar = A.new()
10738 assert_equal(true, abar.Foo())
10739 enddef
10740 Bar()
10741 END
10742 call v9.CheckSourceSuccess(lines)
10743
10744 " Call empty() from a derived object
10745 let lines =<< trim END
10746 vim9script
10747 class A
10748 def empty(): bool
10749 return false
10750 enddef
10751 endclass
10752 class B extends A
10753 def empty(): bool
10754 return true
10755 enddef
10756 endclass
10757 def Foo(afoo: A)
10758 assert_equal(true, empty(afoo))
10759 var bfoo = B.new()
10760 assert_equal(true, empty(bfoo))
10761 enddef
10762 var b = B.new()
10763 assert_equal(1, empty(b))
10764 Foo(b)
10765 END
10766 call v9.CheckSourceSuccess(lines)
10767
10768 " Invoking empty method using an interface
10769 let lines =<< trim END
10770 vim9script
10771 interface A
10772 def empty(): bool
10773 endinterface
10774 class B implements A
10775 def empty(): bool
10776 return false
10777 enddef
10778 endclass
10779 def Foo(a: A)
10780 assert_equal(false, empty(a))
10781 enddef
10782 var b = B.new()
10783 Foo(b)
10784 END
10785 call v9.CheckSourceSuccess(lines)
10786endfunc
10787
10788" Test for using the len() builtin method with an object
10789" This is a legacy function to use the test_garbagecollect_now() function.
10790func Test_object_length()
10791 let lines =<< trim END
10792 vim9script
10793 class A
10794 var mylen: number = 0
10795 def new(n: number)
10796 this.mylen = n
10797 enddef
10798 def len(): number
10799 return this.mylen
10800 enddef
10801 endclass
10802
10803 def Foo()
10804 var afoo = A.new(12)
10805 assert_equal(12, len(afoo))
10806 assert_equal(12, afoo->len())
10807 enddef
10808
10809 var a = A.new(22)
10810 assert_equal(22, len(a))
10811 assert_equal(22, a->len())
10812 test_garbagecollect_now()
10813 assert_equal(22, len(a))
10814 Foo()
10815 test_garbagecollect_now()
10816 Foo()
10817 END
10818 call v9.CheckSourceSuccess(lines)
10819
10820 " len() should return 0 without a builtin method
10821 let lines =<< trim END
10822 vim9script
10823 class A
10824 endclass
10825
10826 def Foo()
10827 var afoo = A.new()
10828 assert_equal(0, len(afoo))
10829 enddef
10830
10831 var a = A.new()
10832 assert_equal(0, len(a))
10833 Foo()
10834 END
10835 call v9.CheckSourceSuccess(lines)
10836
10837 " Unsupported signature for the len() method
10838 let lines =<< trim END
10839 vim9script
10840 class A
10841 def len()
10842 enddef
10843 endclass
10844 END
10845 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10846
10847 " Error when calling the len() method
10848 let lines =<< trim END
10849 vim9script
10850 class A
10851 def len(): number
10852 throw "Failed to compute length"
10853 enddef
10854 endclass
10855
10856 def Foo()
10857 var afoo = A.new()
10858 var i = len(afoo)
10859 enddef
10860
10861 var a = A.new()
10862 assert_fails('len(a)', 'Failed to compute length')
10863 assert_fails('Foo()', 'Failed to compute length')
10864 END
10865 call v9.CheckSourceSuccess(lines)
10866
10867 " call len() using an object from a script
10868 let lines =<< trim END
10869 vim9script
10870 class A
10871 def len(): number
10872 return 5
10873 enddef
10874 endclass
10875 var afoo = A.new()
10876 assert_equal(5, afoo.len())
10877 END
10878 call v9.CheckSourceSuccess(lines)
10879
10880 " call len() using an object from a method
10881 let lines =<< trim END
10882 vim9script
10883 class A
10884 def len(): number
10885 return 5
10886 enddef
10887 endclass
10888 def Foo()
10889 var afoo = A.new()
10890 assert_equal(5, afoo.len())
10891 enddef
10892 Foo()
10893 END
10894 call v9.CheckSourceSuccess(lines)
10895
10896 " call len() using "this" from an object method
10897 let lines =<< trim END
10898 vim9script
10899 class A
10900 def len(): number
10901 return 8
10902 enddef
10903 def Foo(): number
10904 return this.len()
10905 enddef
10906 endclass
10907 def Bar()
10908 var abar = A.new()
10909 assert_equal(8, abar.Foo())
10910 enddef
10911 Bar()
10912 END
10913 call v9.CheckSourceSuccess(lines)
10914
10915 " Call len() from a derived object
10916 let lines =<< trim END
10917 vim9script
10918 class A
10919 def len(): number
10920 return 10
10921 enddef
10922 endclass
10923 class B extends A
10924 def len(): number
10925 return 20
10926 enddef
10927 endclass
10928 def Foo(afoo: A)
10929 assert_equal(20, len(afoo))
10930 var bfoo = B.new()
10931 assert_equal(20, len(bfoo))
10932 enddef
10933 var b = B.new()
10934 assert_equal(20, len(b))
10935 Foo(b)
10936 END
10937 call v9.CheckSourceSuccess(lines)
10938
10939 " Invoking len method using an interface
10940 let lines =<< trim END
10941 vim9script
10942 interface A
10943 def len(): number
10944 endinterface
10945 class B implements A
10946 def len(): number
10947 return 123
10948 enddef
10949 endclass
10950 def Foo(a: A)
10951 assert_equal(123, len(a))
10952 enddef
10953 var b = B.new()
10954 Foo(b)
10955 END
10956 call v9.CheckSourceSuccess(lines)
10957endfunc
10958
10959" Test for using the string() builtin method with an object
10960" This is a legacy function to use the test_garbagecollect_now() function.
10961func Test_object_string()
10962 let lines =<< trim END
10963 vim9script
10964 class A
10965 var name: string
10966 def string(): string
10967 return this.name
10968 enddef
10969 endclass
10970
10971 def Foo()
10972 var afoo = A.new("foo-A")
10973 assert_equal('foo-A', string(afoo))
10974 assert_equal('foo-A', afoo->string())
10975 enddef
10976
10977 var a = A.new("script-A")
10978 assert_equal('script-A', string(a))
10979 assert_equal('script-A', a->string())
10980 assert_equal(['script-A'], execute('echo a')->split("\n"))
10981 test_garbagecollect_now()
10982 assert_equal('script-A', string(a))
10983 Foo()
10984 test_garbagecollect_now()
10985 Foo()
10986 END
10987 call v9.CheckSourceSuccess(lines)
10988
10989 " string() should return "object of A {}" without a builtin method
10990 let lines =<< trim END
10991 vim9script
10992 class A
10993 endclass
10994
10995 def Foo()
10996 var afoo = A.new()
10997 assert_equal('object of A {}', string(afoo))
10998 enddef
10999
11000 var a = A.new()
11001 assert_equal('object of A {}', string(a))
11002 Foo()
11003 END
11004 call v9.CheckSourceSuccess(lines)
11005
11006 " Unsupported signature for the string() method
11007 let lines =<< trim END
11008 vim9script
11009 class A
11010 def string()
11011 enddef
11012 endclass
11013 END
11014 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
11015
11016 " Error when calling the string() method
11017 let lines =<< trim END
11018 vim9script
11019 class A
11020 def string(): string
11021 throw "Failed to get text"
11022 enddef
11023 endclass
11024
11025 def Foo()
11026 var afoo = A.new()
11027 var i = string(afoo)
11028 enddef
11029
11030 var a = A.new()
11031 assert_fails('string(a)', 'Failed to get text')
11032 assert_fails('Foo()', 'Failed to get text')
11033 END
11034 call v9.CheckSourceSuccess(lines)
11035
11036 " call string() using an object from a script
11037 let lines =<< trim END
11038 vim9script
11039 class A
11040 def string(): string
11041 return 'A'
11042 enddef
11043 endclass
11044 var afoo = A.new()
11045 assert_equal('A', afoo.string())
11046 END
11047 call v9.CheckSourceSuccess(lines)
11048
11049 " call string() using an object from a method
11050 let lines =<< trim END
11051 vim9script
11052 class A
11053 def string(): string
11054 return 'A'
11055 enddef
11056 endclass
11057 def Foo()
11058 var afoo = A.new()
11059 assert_equal('A', afoo.string())
11060 enddef
11061 Foo()
11062 END
11063 call v9.CheckSourceSuccess(lines)
11064
11065 " call string() using "this" from an object method
11066 let lines =<< trim END
11067 vim9script
11068 class A
11069 def string(): string
11070 return 'A'
11071 enddef
11072 def Foo(): string
11073 return this.string()
11074 enddef
11075 endclass
11076 def Bar()
11077 var abar = A.new()
11078 assert_equal('A', abar.string())
11079 enddef
11080 Bar()
11081 END
11082 call v9.CheckSourceSuccess(lines)
11083
11084 " Call string() from a derived object
11085 let lines =<< trim END
11086 vim9script
11087 class A
11088 def string(): string
11089 return 'A'
11090 enddef
11091 endclass
11092 class B extends A
11093 def string(): string
11094 return 'B'
11095 enddef
11096 endclass
11097 def Foo(afoo: A)
11098 assert_equal('B', string(afoo))
11099 var bfoo = B.new()
11100 assert_equal('B', string(bfoo))
11101 enddef
11102 var b = B.new()
11103 assert_equal('B', string(b))
11104 Foo(b)
11105 END
11106 call v9.CheckSourceSuccess(lines)
11107
11108 " Invoking string method using an interface
11109 let lines =<< trim END
11110 vim9script
11111 interface A
11112 def string(): string
11113 endinterface
11114 class B implements A
11115 def string(): string
11116 return 'B'
11117 enddef
11118 endclass
11119 def Foo(a: A)
11120 assert_equal('B', string(a))
11121 enddef
11122 var b = B.new()
11123 Foo(b)
11124 END
11125 call v9.CheckSourceSuccess(lines)
11126endfunc
11127
Ernie Rael9d779c52024-07-07 20:41:44 +020011128" Test for using the string() builtin method with an object's method
11129def Test_method_string()
11130 var lines =<< trim END
11131 vim9script
11132 class A
11133 def F()
11134 enddef
11135 endclass
11136 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
11137 END
11138 v9.CheckScriptSuccess(lines)
11139enddef
11140
11141
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010011142" Test for using a class in the class definition
11143def Test_Ref_Class_Within_Same_Class()
11144 var lines =<< trim END
11145 vim9script
11146 class A
11147 var n: number = 0
11148 def Equals(other: A): bool
11149 return this.n == other.n
11150 enddef
11151 endclass
11152
11153 var a1 = A.new(10)
11154 var a2 = A.new(10)
11155 var a3 = A.new(20)
11156 assert_equal(true, a1.Equals(a2))
11157 assert_equal(false, a2.Equals(a3))
11158 END
11159 v9.CheckScriptSuccess(lines)
11160
11161 lines =<< trim END
11162 vim9script
11163
11164 class Foo
11165 var num: number
11166 def Clone(): Foo
11167 return Foo.new(this.num)
11168 enddef
11169 endclass
11170
11171 var f1 = Foo.new(1)
11172
11173 def F()
11174 var f2: Foo = f1.Clone()
11175 assert_equal(false, f2 is f1)
11176 assert_equal(true, f2.num == f1.num)
11177 enddef
11178 F()
11179
11180 var f3: Foo = f1.Clone()
11181 assert_equal(false, f3 is f1)
11182 assert_equal(true, f3.num == f1.num)
11183 END
11184 v9.CheckScriptSuccess(lines)
11185
11186 # Test for trying to use a class to extend when defining the same class
11187 lines =<< trim END
11188 vim9script
11189 class A extends A
11190 endclass
11191 END
11192 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
11193
11194 # Test for trying to use a class to implement when defining the same class
11195 lines =<< trim END
11196 vim9script
11197 class A implements A
11198 endclass
11199 END
11200 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
11201enddef
11202
Ernie Raelf0e69142024-06-22 11:12:00 +020011203" Test for comparing a class referencing itself
11204def Test_Object_Compare_With_Recursive_Class_Ref()
11205 var lines =<< trim END
11206 vim9script
11207
11208 class C
11209 public var nest: C
11210 endclass
11211
11212 var o1 = C.new()
11213 o1.nest = o1
11214
11215 var result = o1 == o1
11216 assert_equal(true, result)
11217 END
11218 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020011219
11220 lines =<< trim END
11221 vim9script
11222
11223 class C
11224 public var nest: C
11225 endclass
11226 var o1 = C.new()
11227 var o2 = C.new(C.new())
11228
11229 var result = o1 == o2
11230 assert_equal(false, result)
11231 END
11232 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020011233
11234 lines =<< trim END
11235 vim9script
11236 class C
11237 var nest1: C
11238 var nest2: C
11239 def Init(n1: C, n2: C)
11240 this.nest1 = n1
11241 this.nest2 = n2
11242 enddef
11243 endclass
11244
11245 var o1 = C.new()
11246 var o2 = C.new()
11247 o1.Init(o1, o2)
11248 o2.Init(o2, o1)
11249
11250 var result = o1 == o2
11251 assert_equal(true, result)
11252 END
11253 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020011254enddef
11255
Ernie Raelf3975492024-07-06 11:44:37 +020011256" Test for comparing a class with nesting objects
11257def Test_Object_Compare_With_Nesting_Objects()
11258 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
11259 # return the compare is equal.
11260 # Test that limit
11261
11262 var lines =<< trim END
11263 vim9script
11264 class C
11265 public var n: number
11266 public var nest: C
11267
11268 # Create a "C" that chains/nests to indicated depth.
11269 # return {head: firstC, tail: lastC}
11270 static def CreateNested(depth: number): dict<C>
11271 var first = C.new(1, null_object)
11272 var last = first
11273 for i in range(2, depth)
11274 last.nest = C.new(i, null_object)
11275 last = last.nest
11276 endfor
11277 return {head: first, tail: last}
11278 enddef
11279
11280 # Return pointer to nth item in chain.
11281 def GetLink(depth: number): C
11282 var count = 1
11283 var p: C = this
11284 while count < depth
11285 p = p.nest
11286 if p == null
11287 throw "too deep"
11288 endif
11289 count += 1
11290 endwhile
11291 return p
11292 enddef
11293
11294 # Return the length of the chain
11295 def len(): number
11296 var count = 1
11297 var p: C = this
11298 while p.nest != null
11299 p = p.nest
11300 count += 1
11301 endwhile
11302 return count
11303 enddef
11304 endclass
11305
11306 var chain = C.CreateNested(3)
11307 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
11308 assert_equal(s, string(chain.head))
11309 assert_equal(3, chain.head->len())
11310
11311 var chain1 = C.CreateNested(100)
11312 var chain2 = C.CreateNested(100)
11313 assert_true(chain1.head == chain2.head)
11314
11315 # modify the tail of chain2, compare not equal
11316 chain2.tail.n = 123456
11317 assert_true(chain1.head != chain2.head)
11318
11319 # a tail of a different length compares not equal
11320 chain2 = C.CreateNested(101)
11321 assert_true(chain1.head != chain2.head)
11322
11323 chain1 = C.CreateNested(1000)
11324 chain2 = C.CreateNested(1000)
11325 assert_true(chain1.head == chain2.head)
11326
11327 # modify the tail of chain2, compare not equal
11328 chain2.tail.n = 123456
11329 assert_true(chain1.head != chain2.head)
11330
11331 # try a chain longer that the limit
11332 chain1 = C.CreateNested(1001)
11333 chain2 = C.CreateNested(1001)
11334 assert_true(chain1.head == chain2.head)
11335
11336 # modify the tail, but still equal
11337 chain2.tail.n = 123456
11338 assert_true(chain1.head == chain2.head)
11339
11340 # remove 2 items from front, shorten the chain by two.
11341 chain1.head = chain1.head.GetLink(3)
11342 chain2.head = chain2.head.GetLink(3)
11343 assert_equal(3, chain1.head.n)
11344 assert_equal(3, chain2.head.n)
11345 assert_equal(999, chain1.head->len())
11346 assert_equal(999, chain2.head->len())
11347 # Now less than the limit, compare not equal
11348 assert_true(chain1.head != chain2.head)
11349 END
11350 v9.CheckScriptSuccess(lines)
11351enddef
11352
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011353" Test for using a compound operator from a lambda function in an object method
11354def Test_compound_op_in_objmethod_lambda()
11355 # Test using the "+=" operator
11356 var lines =<< trim END
11357 vim9script
11358 class A
11359 var n: number = 10
11360 def Foo()
11361 var Fn = () => {
11362 this.n += 1
11363 }
11364 Fn()
11365 enddef
11366 endclass
11367
11368 var a = A.new()
11369 a.Foo()
11370 assert_equal(11, a.n)
11371 END
11372 v9.CheckScriptSuccess(lines)
11373
11374 # Test using the "..=" operator
11375 lines =<< trim END
11376 vim9script
11377 class A
11378 var s: string = "a"
11379 def Foo()
11380 var Fn = () => {
11381 this.s ..= "a"
11382 }
11383 Fn()
11384 enddef
11385 endclass
11386
11387 var a = A.new()
11388 a.Foo()
11389 a.Foo()
11390 assert_equal("aaa", a.s)
11391 END
11392 v9.CheckScriptSuccess(lines)
11393enddef
11394
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011395" Test for using test_refcount() with a class and an object
11396def Test_class_object_refcount()
11397 var lines =<< trim END
11398 vim9script
11399 class A
11400 endclass
11401 var a: A = A.new()
11402 assert_equal(2, test_refcount(A))
11403 assert_equal(1, test_refcount(a))
11404 var b = a
11405 assert_equal(2, test_refcount(A))
11406 assert_equal(2, test_refcount(a))
11407 assert_equal(2, test_refcount(b))
11408 END
11409 v9.CheckScriptSuccess(lines)
11410enddef
11411
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011412" call a lambda function in one object from another object
11413def Test_lambda_invocation_across_classes()
11414 var lines =<< trim END
11415 vim9script
11416 class A
11417 var s: string = "foo"
11418 def GetFn(): func
11419 var Fn = (): string => {
11420 return this.s
11421 }
11422 return Fn
11423 enddef
11424 endclass
11425
11426 class B
11427 var s: string = "bar"
11428 def GetFn(): func
11429 var a = A.new()
11430 return a.GetFn()
11431 enddef
11432 endclass
11433
11434 var b = B.new()
11435 var Fn = b.GetFn()
11436 assert_equal("foo", Fn())
11437 END
11438 v9.CheckScriptSuccess(lines)
11439enddef
11440
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011441" Test for using a class member which is an object of the current class
11442def Test_current_class_object_class_member()
11443 var lines =<< trim END
11444 vim9script
11445 class A
11446 public static var obj1: A = A.new(10)
11447 var n: number
11448 endclass
11449 defcompile
11450 assert_equal(10, A.obj1.n)
11451 END
11452 v9.CheckScriptSuccess(lines)
11453enddef
11454
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011455" Test for updating a base class variable from a base class method without the
11456" class name. This used to crash Vim (Github issue #14352).
11457def Test_use_base_class_variable_from_base_class_method()
11458 var lines =<< trim END
11459 vim9script
11460
11461 class DictKeyClass
11462 static var _obj_id_count = 1
11463 def _GenerateKey()
11464 _obj_id_count += 1
11465 enddef
11466 static def GetIdCount(): number
11467 return _obj_id_count
11468 enddef
11469 endclass
11470
11471 class C extends DictKeyClass
11472 def F()
11473 this._GenerateKey()
11474 enddef
11475 endclass
11476
11477 C.new().F()
11478 assert_equal(2, DictKeyClass.GetIdCount())
11479 END
11480 v9.CheckScriptSuccess(lines)
11481enddef
11482
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011483" Test for accessing protected funcref object and class variables
11484def Test_protected_funcref()
11485 # protected funcref object variable
11486 var lines =<< trim END
11487 vim9script
11488 class Test1
11489 const _Id: func(any): any = (v) => v
11490 endclass
11491 var n = Test1.new()._Id(1)
11492 END
11493 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11494
11495 # protected funcref class variable
11496 lines =<< trim END
11497 vim9script
11498 class Test2
11499 static const _Id: func(any): any = (v) => v
11500 endclass
11501 var n = Test2._Id(2)
11502 END
11503 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11504enddef
11505
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011506" Test for using lambda block in classes
11507def Test_lambda_block_in_class()
11508 # This used to crash Vim
11509 var lines =<< trim END
11510 vim9script
11511 class IdClass1
11512 const Id: func(number): number = (num: number): number => {
11513 # Return a ID
11514 return num * 10
11515 }
11516 endclass
11517 var id = IdClass1.new()
11518 assert_equal(20, id.Id(2))
11519 END
11520 v9.CheckScriptSuccess(lines)
11521
11522 # This used to crash Vim
11523 lines =<< trim END
11524 vim9script
11525 class IdClass2
11526 static const Id: func(number): number = (num: number): number => {
11527 # Return a ID
11528 return num * 2
11529 }
11530 endclass
11531 assert_equal(16, IdClass2.Id(8))
11532 END
11533 v9.CheckScriptSuccess(lines)
11534enddef
11535
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011536" Test for defcompiling an abstract method
11537def Test_abstract_method_defcompile()
11538 # Compile an abstract class with abstract object methods
11539 var lines =<< trim END
11540 vim9script
11541 abstract class A
11542 abstract def Foo(): string
11543 abstract def Bar(): list<string>
11544 endclass
11545 defcompile
11546 END
11547 v9.CheckScriptSuccess(lines)
11548
11549 # Compile a concrete object method in an abstract class
11550 lines =<< trim END
11551 vim9script
11552 abstract class A
11553 abstract def Foo(): string
11554 abstract def Bar(): list<string>
11555 def Baz(): string
11556 pass
11557 enddef
11558 endclass
11559 defcompile
11560 END
11561 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11562
11563 # Compile a concrete class method in an abstract class
11564 lines =<< trim END
11565 vim9script
11566 abstract class A
11567 abstract def Foo(): string
11568 abstract def Bar(): list<string>
11569 static def Baz(): string
11570 pass
11571 enddef
11572 endclass
11573 defcompile
11574 END
11575 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11576enddef
11577
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011578" Test for defining a class in a function
11579def Test_class_definition_in_a_function()
11580 var lines =<< trim END
11581 vim9script
11582 def Foo()
11583 class A
11584 endclass
11585 enddef
11586 defcompile
11587 END
11588 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11589enddef
11590
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011591" Test for using [] with a class and an object
11592def Test_class_object_index()
11593 var lines =<< trim END
11594 vim9script
11595 class A
11596 endclass
11597 A[10] = 1
11598 END
11599 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11600
11601 lines =<< trim END
11602 vim9script
11603 class A
11604 endclass
11605 var a = A.new()
11606 a[10] = 1
11607 END
11608 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11609enddef
11610
LemonBoyf4af3312024-07-04 13:43:12 +020011611def Test_class_member_init_typecheck()
11612 # Ensure the class member is assigned its declared type.
11613 var lines =<< trim END
11614 vim9script
11615 class S
11616 static var l: list<string> = []
11617 endclass
11618 S.l->add(123)
11619 END
11620 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11621
11622 # Ensure the initializer value and the declared type match.
11623 lines =<< trim END
11624 vim9script
11625 class S
11626 var l: list<string> = [1, 2, 3]
11627 endclass
11628 var o = S.new()
11629 END
11630 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11631
11632 # Ensure the class member is assigned its declared type.
11633 lines =<< trim END
11634 vim9script
11635 class S
11636 var l: list<string> = []
11637 endclass
11638 var o = S.new()
11639 o.l->add(123)
11640 END
11641 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11642enddef
11643
LemonBoy50d48542024-07-04 17:03:17 +020011644def Test_class_cast()
11645 var lines =<< trim END
11646 vim9script
11647 class A
11648 endclass
11649 class B extends A
11650 var mylen: number
11651 endclass
11652 def F(o: A): number
11653 return (<B>o).mylen
11654 enddef
11655
11656 defcompile F
11657 END
11658 v9.CheckScriptSuccess(lines)
11659enddef
11660
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011661" Test for using a variable of type "any" with an object
11662def Test_any_obj_var_type()
11663 var lines =<< trim END
11664 vim9script
11665 class A
11666 var name: string = "foobar"
11667 def Foo(): string
11668 return "func foo"
11669 enddef
11670 endclass
11671
11672 def CheckVals(x: any)
11673 assert_equal("foobar", x.name)
11674 assert_equal("func foo", x.Foo())
11675 enddef
11676
11677 var a = A.new()
11678 CheckVals(a)
11679 END
11680 v9.CheckScriptSuccess(lines)
11681
11682 # Try to set a non-existing variable
11683 lines =<< trim END
11684 vim9script
11685 class A
11686 var name: string = "foobar"
11687 endclass
11688
11689 def SetNonExistingVar(x: any)
11690 x.bar = [1, 2, 3]
11691 enddef
11692
11693 var a = A.new()
11694 SetNonExistingVar(a)
11695 END
11696 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11697
11698 # Try to read a non-existing variable
11699 lines =<< trim END
11700 vim9script
11701 class A
11702 var name: string = "foobar"
11703 endclass
11704
11705 def GetNonExistingVar(x: any)
11706 var i: dict<any> = x.bar
11707 enddef
11708
11709 var a = A.new()
11710 GetNonExistingVar(a)
11711 END
11712 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11713
11714 # Try to invoke a non-existing method
11715 lines =<< trim END
11716 vim9script
11717 class A
11718 def Foo(): number
11719 return 10
11720 enddef
11721 endclass
11722
11723 def CallNonExistingMethod(x: any)
11724 var i: number = x.Bar()
11725 enddef
11726
11727 var a = A.new()
11728 CallNonExistingMethod(a)
11729 END
11730 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11731
11732 # Use an object which is a Dict value
11733 lines =<< trim END
11734 vim9script
11735 class Foo
11736 def Bar(): number
11737 return 369
11738 enddef
11739 endclass
11740
11741 def GetValue(FooDict: dict<any>): number
11742 var n: number = 0
11743 for foo in values(FooDict)
11744 n += foo.Bar()
11745 endfor
11746 return n
11747 enddef
11748
11749 var d = {'x': Foo.new()}
11750 assert_equal(369, GetValue(d))
11751 END
11752 v9.CheckScriptSuccess(lines)
11753
zeertzjqd32bf0a2024-12-17 20:55:13 +010011754 # Nested data. Object containing a Dict containing another Object.
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011755 lines =<< trim END
11756 vim9script
11757 class Context
11758 public var state: dict<any> = {}
11759 endclass
11760
11761 class Metadata
11762 public var value = 0
11763 endclass
11764
11765 var ctx = Context.new()
11766 ctx.state["meta"] = Metadata.new(2468)
11767
11768 const foo = ctx.state.meta.value
11769
11770 def F(): number
11771 const bar = ctx.state.meta.value
11772 return bar
11773 enddef
11774
11775 assert_equal(2468, F())
11776 END
11777 v9.CheckScriptSuccess(lines)
11778
11779 # Accessing an object from a method inside the class using any type
11780 lines =<< trim END
11781 vim9script
11782 class C
11783 def _G(): string
11784 return '_G'
11785 enddef
11786 static def S(o_any: any): string
11787 return o_any._G()
11788 enddef
11789 endclass
11790
11791 var o1 = C.new()
11792 assert_equal('_G', C.S(o1))
11793 END
11794 v9.CheckScriptSuccess(lines)
11795
11796 # Modifying an object private variable from a method in another class using
11797 # any type
11798 lines =<< trim END
11799 vim9script
11800
11801 class A
11802 var num = 10
11803 endclass
11804
11805 class B
11806 def SetVal(x: any)
11807 x.num = 20
11808 enddef
11809 endclass
11810
11811 var a = A.new()
11812 var b = B.new()
11813 b.SetVal(a)
11814 END
11815 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11816
11817 # Accessing a object protected variable from a method in another class using
11818 # any type
11819 lines =<< trim END
11820 vim9script
11821
11822 class A
11823 var _num = 10
11824 endclass
11825
11826 class B
11827 def GetVal(x: any): number
11828 return x._num
11829 enddef
11830 endclass
11831
11832 var a = A.new()
11833 var b = B.new()
11834 var i = b.GetVal(a)
11835 END
11836 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11837
11838 # Accessing an object returned from an imported function and class
11839 lines =<< trim END
11840 vim9script
11841 export class Foo
11842 public var name: string
11843 endclass
11844
11845 export def ReturnFooObject(): Foo
11846 var r = Foo.new('star')
11847 return r
11848 enddef
11849 END
11850 writefile(lines, 'Xanyvar1.vim', 'D')
11851
11852 lines =<< trim END
11853 vim9script
11854
11855 import './Xanyvar1.vim'
11856
11857 def GetName(): string
11858 var whatever = Xanyvar1.ReturnFooObject()
11859 return whatever.name
11860 enddef
11861
11862 assert_equal('star', GetName())
11863 END
11864 v9.CheckScriptSuccess(lines)
11865
11866 # Try to modify a private object variable using a variable of type "any"
11867 lines =<< trim END
11868 vim9script
11869
11870 class Foo
11871 var n: number = 10
11872 endclass
11873 def Fn(x: any)
11874 x.n = 20
11875 enddef
11876 var a = Foo.new()
11877 Fn(a)
11878 END
11879 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11880
11881 # Try to read a protected object variable using a variable of type "any"
11882 lines =<< trim END
11883 vim9script
11884
11885 class Foo
11886 var _n: number = 10
11887 endclass
11888 def Fn(x: any): number
11889 return x._n
11890 enddef
11891
11892 var a = Foo.new()
11893 Fn(a)
11894 END
11895 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11896
11897 # Read a protected object variable using a variable of type "any" in an object
11898 # method
11899 lines =<< trim END
11900 vim9script
11901
11902 class Foo
11903 var _n: number = 10
11904 def Fn(x: any): number
11905 return x._n
11906 enddef
11907 endclass
11908
11909 var a = Foo.new()
11910 assert_equal(10, a.Fn(a))
11911 END
11912 v9.CheckScriptSuccess(lines)
11913
11914 # Try to call a protected object method using a "any" type variable
11915 lines =<< trim END
11916 vim9script
11917
11918 class Foo
11919 def _GetVal(): number
11920 return 234
11921 enddef
11922 endclass
11923 def Fn(x: any): number
11924 return x._GetVal()
11925 enddef
11926
11927 var a = Foo.new()
11928 Fn(a)
11929 END
11930 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11931
11932 # Call a protected object method using a "any" type variable from another
11933 # object method
11934 lines =<< trim END
11935 vim9script
11936
11937 class Foo
11938 def _GetVal(): number
11939 return 234
11940 enddef
11941 def FooVal(x: any): number
11942 return x._GetVal()
11943 enddef
11944 endclass
11945
11946 var a = Foo.new()
11947 assert_equal(234, a.FooVal(a))
11948 END
11949 v9.CheckScriptSuccess(lines)
11950
11951 # Method chaining
11952 lines =<< trim END
11953 vim9script
11954
11955 export class T
11956 var id: number = 268
11957 def F(): any
11958 return this
11959 enddef
11960 endclass
11961
11962 def H()
11963 var a = T.new().F().F()
11964 assert_equal(268, a.id)
11965 enddef
11966 H()
11967
11968 var b: T = T.new().F().F()
11969 assert_equal(268, b.id)
11970 END
11971 v9.CheckScriptSuccess(lines)
11972
11973 # Using a null object to access a member variable
11974 lines =<< trim END
11975 vim9script
11976 def Fn(x: any): number
11977 return x.num
11978 enddef
11979
11980 Fn(null_object)
11981 END
11982 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11983
11984 # Using a null object to invoke a method
11985 lines =<< trim END
11986 vim9script
11987 def Fn(x: any)
11988 x.Foo()
11989 enddef
11990
11991 Fn(null_object)
11992 END
11993 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
Yegappan Lakshmanane7984462024-11-12 21:03:00 +010011994
11995 # Try to change a const object variable using a "any" variable
11996 lines =<< trim END
11997 vim9script
11998 class A
11999 public const v1: number = 123
12000 endclass
12001
12002 def Fn(o: any)
12003 o.v1 = 321
12004 enddef
12005
12006 var a = A.new()
12007 Fn(a)
12008 END
12009 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
12010
12011 # Try to change a final object variable using a "any" variable
12012 lines =<< trim END
12013 vim9script
12014 class A
12015 public final v1: number = 123
12016 endclass
12017
12018 def Fn(o: any)
12019 o.v1 = 321
12020 enddef
12021
12022 var a = A.new()
12023 Fn(a)
12024 END
12025 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
12026
12027 # Assign a different type of value to an "any" type object variable
12028 lines =<< trim END
12029 vim9script
12030 class A
12031 public var v1: list<any> = [1, 2]
12032 endclass
12033
12034 def Fn(o: A)
12035 o.v1 = 'abc'
12036 enddef
12037
12038 var a = A.new()
12039 Fn(a)
12040 END
12041 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 1)
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010012042enddef
12043
Yegappan Lakshmanan481992c2024-12-06 18:35:12 +010012044" Test for using an object method with mapnew()
12045def Test_mapnew_with_instance_method()
12046 var lines =<< trim END
12047 vim9script
12048
12049 class Foo
12050 var str: string
12051 var nums: list<number> = [1, 2, 3]
12052
12053 def InstanceMethod(n: number): string
12054 return this.str .. n
12055 enddef
12056
12057 def MapperMethod(idx: number, elem: number): string
12058 return elem->this.InstanceMethod()
12059 enddef
12060
12061 def MapTest()
12062 this.str = "foo"
12063 var l = ['foo1', 'foo2', 'foo3']
12064 assert_equal(l, this.nums->mapnew(this.MapperMethod))
12065 enddef
12066 endclass
12067
12068 Foo.new().MapTest()
12069 END
12070 v9.CheckSourceSuccess(lines)
12071
12072 # Error in the mapnew() function
12073 lines =<< trim END
12074 vim9script
12075
12076 class Foo
12077 var str: string
12078 var nums: list<number> = [1, 2, 3]
12079
12080 def InstanceMethod(n: number): string
12081 throw "InstanceMethod failed"
12082 enddef
12083
12084 def MapperMethod(idx: number, elem: number): string
12085 return elem->this.InstanceMethod()
12086 enddef
12087
12088 def MapTest()
12089 this.str = "foo"
12090 var caught_exception: bool = false
12091 try
12092 this.nums->mapnew(this.MapperMethod)
12093 catch /InstanceMethod failed/
12094 caught_exception = true
12095 endtry
12096 assert_true(caught_exception)
12097 enddef
12098 endclass
12099
12100 Foo.new().MapTest()
12101 END
12102 v9.CheckSourceSuccess(lines)
12103enddef
12104
Yegappan Lakshmananb0206e92024-12-30 09:52:16 +010012105" Test for using an object method in a method call.
12106def Test_use_object_method_in_a_method_call()
12107 var lines =<< trim END
12108 vim9script
12109
12110 class Foo
12111 def Cost(nums: list<number>): number
12112 return nums[0] * nums[1]
12113 enddef
12114
12115 def ShowCost(): string
12116 var g = [4, 5]
12117 return $"Cost is: {g->this.Cost()}"
12118 enddef
12119 endclass
12120
12121 var d = Foo.new()
12122 assert_equal('Cost is: 20', d.ShowCost())
12123 END
12124 v9.CheckSourceSuccess(lines)
12125
12126 # Test for using a non-existing object method in string interpolation
12127 lines =<< trim END
12128 vim9script
12129
12130 class Foo
12131 def Cost(nums: list<number>): number
12132 return nums[0] * nums[1]
12133 enddef
12134
12135 def ShowCost(): string
12136 var g = [4, 5]
12137 echo $"Cost is: {g->this.NewCost()}"
12138 enddef
12139 endclass
12140
12141 var d = Foo.new()
12142 d.ShowCost()
12143 END
12144 v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
12145enddef
12146
Yegappan Lakshmananb04af4c2025-01-03 10:50:08 +010012147" Test for referencing an object variable which is not yet initialized
12148def Test_uninitialized_object_var()
12149 var lines =<< trim END
12150 vim9script
12151 class Foo
12152 const two: number = Foo.Two(this)
12153 const one: number = 1
12154
12155 static def Two(that: Foo): number
12156 return that.one + 2
12157 enddef
12158 endclass
12159
12160 echo Foo.Two(Foo.new())
12161 END
12162 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
12163
12164 lines =<< trim END
12165 vim9script
12166 class Foo
12167 const one: number = Foo.One(this)
12168
12169 static def One(that: Foo): number
12170 return 1
12171 enddef
12172 endclass
12173
12174 assert_equal(1, Foo.One(Foo.new()))
12175 END
12176 v9.CheckSourceSuccess(lines)
12177
12178 lines =<< trim END
12179 vim9script
12180 class Foo
12181 const one: number = 1
12182 const two: number = Foo.Two(this)
12183
12184 static def Two(that: Foo): number
12185 return that.one + 1
12186 enddef
12187 endclass
12188
12189 assert_equal(2, Foo.Two(Foo.new()))
12190 END
12191 v9.CheckSourceSuccess(lines)
12192
12193 lines =<< trim END
12194 vim9script
12195 class Foo
12196 const Id: func(any): any = ((_) => (v) => v)(this)
12197
12198 static def Id(that: Foo): func(any): any
12199 return that.Id
12200 enddef
12201 endclass
12202
12203 assert_equal(5, Foo.Id(Foo.new())(5))
12204 assert_equal(7, Foo.new().Id(7))
12205 END
12206 v9.CheckSourceSuccess(lines)
12207
12208 lines =<< trim END
12209 vim9script
12210 class Foo
12211 const Id: func(any): any = ((that) => (_) => that)(this)
12212
12213 static def Id(that: Foo): func(any): any
12214 return that.Id
12215 enddef
12216 endclass
12217
12218 const Id0: func(any): any = Foo.Id(Foo.new())
12219 const Id1: func(any): any = Foo.new().Id
12220 END
12221 v9.CheckSourceSuccess(lines)
12222
12223 lines =<< trim END
12224 vim9script
12225 class Foo
12226 const Id: any = Foo.Id(this)
12227
12228 static def Id(that: Foo): any
12229 return that.Id
12230 enddef
12231 endclass
12232
12233 const Id2: any = Foo.Id(Foo.new())
12234 const Id3: any = Foo.new().Id
12235 END
12236 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
12237
12238 lines =<< trim END
12239 vim9script
12240
12241 class Foo
12242 var x: string = ''
12243 var Y: func(): string = () => this.x
12244 endclass
12245
12246 var foo = Foo.new('ok')
12247 assert_equal('ok', foo.Y())
12248 END
12249 v9.CheckSourceSuccess(lines)
12250
12251 lines =<< trim END
12252 vim9script
12253
12254 class Foo
12255 var x: string = this.x
12256 endclass
12257
12258 var foo = Foo.new('ok')
12259 END
12260 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
12261enddef
12262
Yegappan Lakshmanan2050dcc2025-01-06 18:34:49 +010012263" Test for initializing member variables of compound type in the constructor
12264def Test_constructor_init_compound_member_var()
12265 var lines =<< trim END
12266 vim9script
12267
12268 class Foo
12269 var v1: string = "aaa"
12270 var v2: list<number> = [1, 2]
12271 var v3: dict<string> = {a: 'a', b: 'b'}
12272 endclass
12273
12274 class Bar
12275 var v4: string = "bbb"
12276 var v5: Foo = Foo.new()
12277 var v6: list<number> = [1, 2]
12278 endclass
12279
12280 var b: Bar = Bar.new()
12281 assert_equal("aaa", b.v5.v1)
12282 assert_equal([1, 2], b.v5.v2)
12283 assert_equal({a: 'a', b: 'b'}, b.v5.v3)
12284 assert_equal("bbb", b.v4)
12285 assert_equal([1, 2], b.v6)
12286 END
12287 v9.CheckSourceSuccess(lines)
12288enddef
12289
Bram Moolenaar00b28d62022-12-08 15:32:33 +000012290" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker