blob: 7a269fc8f286c352d866e91da1c5fdde3022d076 [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
Christian Brabandtd9a1f262025-01-21 22:17:50 +01003665def Test_abstract_class()
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003666 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003667 vim9script
3668 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003669 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003670 endclass
3671 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003672 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003673 endclass
3674 var p: Base = Person.new('Peter', 42)
3675 assert_equal('Peter', p.name)
3676 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003677 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003678 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003679
3680 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003681 vim9script
3682 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003683 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003684 endclass
3685 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003686 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003687 endclass
3688 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003689 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003690 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003691
3692 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003693 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003694 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003695 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003696 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003697 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003698
h-eastaa979c72025-01-03 10:19:45 +01003699 # Test for "abstract" cannot be abbreviated
3700 lines =<< trim END
3701 vim9script
3702 abs class A
3703 endclass
3704 END
3705 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs class A', 2)
3706
Yegappan Lakshmananac773182024-04-27 11:36:12 +02003707 # Additional commands after "abstract class"
3708 lines =<< trim END
3709 vim9script
3710 abstract class Something | var x = []
3711 endclass
3712 END
3713 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = []", 2)
3714
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003715 # Abstract class cannot have a "new" function
3716 lines =<< trim END
3717 vim9script
3718 abstract class Base
3719 def new()
3720 enddef
3721 endclass
3722 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003723 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003724
3725 # extending an abstract class with class methods and variables
3726 lines =<< trim END
3727 vim9script
3728 abstract class A
3729 static var s: string = 'vim'
3730 static def Fn(): list<number>
3731 return [10]
3732 enddef
3733 endclass
3734 class B extends A
3735 endclass
3736 var b = B.new()
3737 assert_equal('vim', A.s)
3738 assert_equal([10], A.Fn())
3739 END
3740 v9.CheckScriptSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003741enddef
3742
Bram Moolenaar486fc252023-01-18 14:51:07 +00003743def Test_closure_in_class()
3744 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003745 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003746
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003747 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01003748 var y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003749
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003750 def new()
3751 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3752 enddef
3753 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003754
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003755 Foo.new()
3756 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003757 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003758 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003759enddef
3760
Ernie Rael9ed53752023-12-11 17:40:46 +01003761def Test_construct_object_from_legacy()
3762 # Cannot directly invoke constructor from legacy
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003763 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003764 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003765
Ernie Rael9ed53752023-12-11 17:40:46 +01003766 var newCalled = false
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003767
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003768 class A
Ernie Rael9ed53752023-12-11 17:40:46 +01003769 def new(arg: string)
3770 newCalled = true
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003771 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003772 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003773
Ernie Rael9ed53752023-12-11 17:40:46 +01003774 export def CreateA(...args: list<any>): A
3775 return call(A.new, args)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003776 enddef
3777
Ernie Rael9ed53752023-12-11 17:40:46 +01003778 g:P = CreateA
3779 legacy call g:P('some_arg')
3780 assert_equal(true, newCalled)
3781 unlet g:P
3782 END
3783 v9.CheckSourceSuccess(lines)
3784
3785 lines =<< trim END
3786 vim9script
3787
3788 var newCalled = false
3789
3790 class A
3791 static def CreateA(options = {}): any
3792 return A.new()
3793 enddef
3794 def new()
3795 newCalled = true
3796 enddef
3797 endclass
3798
3799 g:P = A.CreateA
3800 legacy call g:P()
3801 assert_equal(true, newCalled)
3802 unlet g:P
3803 END
3804 v9.CheckSourceSuccess(lines)
3805
3806 # This also tests invoking "new()" with "call"
3807 lines =<< trim END
3808 vim9script
3809
3810 var createdObject: any
3811
3812 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01003813 var val1: number
3814 var val2: number
Ernie Rael9ed53752023-12-11 17:40:46 +01003815 static def CreateA(...args: list<any>): any
3816 createdObject = call(A.new, args)
3817 return createdObject
3818 enddef
3819 endclass
3820
3821 g:P = A.CreateA
3822 legacy call g:P(3, 5)
3823 assert_equal(3, createdObject.val1)
3824 assert_equal(5, createdObject.val2)
3825 legacy call g:P()
3826 assert_equal(0, createdObject.val1)
3827 assert_equal(0, createdObject.val2)
3828 legacy call g:P(7)
3829 assert_equal(7, createdObject.val1)
3830 assert_equal(0, createdObject.val2)
3831 unlet g:P
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003832 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003833 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003834enddef
3835
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003836def Test_defer_with_object()
3837 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003838 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003839
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003840 class CWithEE
3841 def Enter()
3842 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003843 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003844 def Exit()
3845 g:result ..= "exited"
3846 enddef
3847 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003848
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003849 def With(ee: CWithEE, F: func)
3850 ee.Enter()
3851 defer ee.Exit()
3852 F()
3853 enddef
3854
3855 g:result = ''
3856 var obj = CWithEE.new()
3857 obj->With(() => {
3858 g:result ..= "called/"
3859 })
3860 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003861 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003862 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003863 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003864
3865 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003866 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003867
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003868 class BaseWithEE
3869 def Enter()
3870 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003871 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003872 def Exit()
3873 g:result ..= "exited-base"
3874 enddef
3875 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003876
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003877 class CWithEE extends BaseWithEE
3878 def Enter()
3879 g:result ..= "entered-child/"
3880 enddef
3881 def Exit()
3882 g:result ..= "exited-child"
3883 enddef
3884 endclass
3885
3886 def With(ee: BaseWithEE, F: func)
3887 ee.Enter()
3888 defer ee.Exit()
3889 F()
3890 enddef
3891
3892 g:result = ''
3893 var obj = CWithEE.new()
3894 obj->With(() => {
3895 g:result ..= "called/"
3896 })
3897 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003898 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003899 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003900 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003901enddef
3902
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003903" The following test used to crash Vim (Github issue #12676)
3904def Test_extends_method_crashes_vim()
3905 var lines =<< trim END
3906 vim9script
3907
3908 class Observer
3909 endclass
3910
3911 class Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003912 var value: any
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003913
3914 def Set(v: any)
3915 if v != this.value
3916 this.value = v
3917 endif
3918 enddef
3919
3920 def Register(observer: Observer)
3921 enddef
3922 endclass
3923
3924 class Bool extends Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003925 var value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003926 endclass
3927
3928 def Observe(obj: Property, who: Observer)
3929 obj.Register(who)
3930 enddef
3931
3932 var p = Bool.new(false)
3933 var myObserver = Observer.new()
3934
3935 Observe(p, myObserver)
3936
3937 p.Set(true)
3938 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003939 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003940enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003941
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003942" Test for calling a method in a class that is extended
3943def Test_call_method_in_extended_class()
3944 var lines =<< trim END
3945 vim9script
3946
3947 var prop_init_called = false
3948 var prop_register_called = false
3949
3950 class Property
3951 def Init()
3952 prop_init_called = true
3953 enddef
3954
3955 def Register()
3956 prop_register_called = true
3957 enddef
3958 endclass
3959
3960 class Bool extends Property
3961 endclass
3962
3963 def Observe(obj: Property)
3964 obj.Register()
3965 enddef
3966
3967 var p = Property.new()
3968 Observe(p)
3969
3970 p.Init()
3971 assert_true(prop_init_called)
3972 assert_true(prop_register_called)
3973 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003974 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003975enddef
3976
LemonBoyafe04662023-08-23 21:08:11 +02003977def Test_instanceof()
3978 var lines =<< trim END
3979 vim9script
3980
3981 class Base1
3982 endclass
3983
3984 class Base2 extends Base1
3985 endclass
3986
3987 interface Intf1
3988 endinterface
3989
3990 class Mix1 implements Intf1
3991 endclass
3992
3993 class Base3 extends Mix1
3994 endclass
3995
Ernie Rael2025af12023-12-12 16:58:00 +01003996 type AliasBase1 = Base1
3997 type AliasBase2 = Base2
3998 type AliasIntf1 = Intf1
3999 type AliasMix1 = Mix1
4000
LemonBoyafe04662023-08-23 21:08:11 +02004001 var b1 = Base1.new()
4002 var b2 = Base2.new()
4003 var b3 = Base3.new()
4004
4005 assert_true(instanceof(b1, Base1))
4006 assert_true(instanceof(b2, Base1))
4007 assert_false(instanceof(b1, Base2))
4008 assert_true(instanceof(b3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01004009 assert_true(instanceof(b3, Base1, Base2, Intf1))
4010
4011 assert_true(instanceof(b1, AliasBase1))
4012 assert_true(instanceof(b2, AliasBase1))
4013 assert_false(instanceof(b1, AliasBase2))
4014 assert_true(instanceof(b3, AliasMix1))
4015 assert_true(instanceof(b3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02004016
4017 def Foo()
4018 var a1 = Base1.new()
4019 var a2 = Base2.new()
4020 var a3 = Base3.new()
4021
4022 assert_true(instanceof(a1, Base1))
4023 assert_true(instanceof(a2, Base1))
4024 assert_false(instanceof(a1, Base2))
4025 assert_true(instanceof(a3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01004026 assert_true(instanceof(a3, Base1, Base2, Intf1))
4027
4028 assert_true(instanceof(a1, AliasBase1))
4029 assert_true(instanceof(a2, AliasBase1))
4030 assert_false(instanceof(a1, AliasBase2))
4031 assert_true(instanceof(a3, AliasMix1))
4032 assert_true(instanceof(a3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02004033 enddef
4034 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02004035
4036 var o_null: Base1
4037 assert_false(instanceof(o_null, Base1))
4038
LemonBoyafe04662023-08-23 21:08:11 +02004039 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004040 v9.CheckSourceSuccess(lines)
Ernie Rael2025af12023-12-12 16:58:00 +01004041
4042 lines =<< trim END
4043 vim9script
4044
4045 class Base1
4046 endclass
4047 instanceof(Base1.new())
4048 END
4049 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
4050
4051 lines =<< trim END
4052 vim9script
4053
4054 class Base1
4055 endclass
4056 def F()
4057 instanceof(Base1.new())
4058 enddef
4059 F()
4060 END
4061 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
4062
4063 lines =<< trim END
4064 vim9script
4065
4066 class Base1
4067 endclass
4068
4069 class Base2
4070 endclass
4071
4072 var o = Base2.new()
4073 instanceof(o, Base1, Base2, 3)
4074 END
4075 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4', 10)
4076
4077 lines =<< trim END
4078 vim9script
4079
4080 class Base1
4081 endclass
4082
4083 class Base2
4084 endclass
4085
4086 def F()
4087 var o = Base2.new()
4088 instanceof(o, Base1, Base2, 3)
4089 enddef
4090 F()
4091 END
4092 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4')
LemonBoyafe04662023-08-23 21:08:11 +02004093enddef
4094
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004095" Test for calling a method in the parent class that is extended partially.
4096" This used to fail with the 'E118: Too many arguments for function: Text' error
4097" message (Github issue #12524).
4098def Test_call_method_in_parent_class()
4099 var lines =<< trim END
4100 vim9script
4101
4102 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01004103 var _lnum: number = 1
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004104
4105 def SetY(lnum: number)
4106 this._lnum = lnum
4107 enddef
4108
4109 def Text(): string
4110 return ''
4111 enddef
4112 endclass
4113
4114 class Foo extends Widget
4115 def Text(): string
4116 return '<Foo>'
4117 enddef
4118 endclass
4119
4120 def Stack(w1: Widget, w2: Widget): list<Widget>
4121 w1.SetY(1)
4122 w2.SetY(2)
4123 return [w1, w2]
4124 enddef
4125
4126 var foo1 = Foo.new()
4127 var foo2 = Foo.new()
4128 var l = Stack(foo1, foo2)
4129 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004130 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02004131enddef
4132
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004133" Test for calling methods from three levels of classes
4134def Test_multi_level_method_call()
4135 var lines =<< trim END
4136 vim9script
4137
4138 var A_func1: number = 0
4139 var A_func2: number = 0
4140 var A_func3: number = 0
4141 var B_func2: number = 0
4142 var B_func3: number = 0
4143 var C_func3: number = 0
4144
4145 class A
4146 def Func1()
4147 A_func1 += 1
4148 enddef
4149
4150 def Func2()
4151 A_func2 += 1
4152 enddef
4153
4154 def Func3()
4155 A_func3 += 1
4156 enddef
4157 endclass
4158
4159 class B extends A
4160 def Func2()
4161 B_func2 += 1
4162 enddef
4163
4164 def Func3()
4165 B_func3 += 1
4166 enddef
4167 endclass
4168
4169 class C extends B
4170 def Func3()
4171 C_func3 += 1
4172 enddef
4173 endclass
4174
4175 def A_CallFuncs(a: A)
4176 a.Func1()
4177 a.Func2()
4178 a.Func3()
4179 enddef
4180
4181 def B_CallFuncs(b: B)
4182 b.Func1()
4183 b.Func2()
4184 b.Func3()
4185 enddef
4186
4187 def C_CallFuncs(c: C)
4188 c.Func1()
4189 c.Func2()
4190 c.Func3()
4191 enddef
4192
4193 var cobj = C.new()
4194 A_CallFuncs(cobj)
4195 B_CallFuncs(cobj)
4196 C_CallFuncs(cobj)
4197 assert_equal(3, A_func1)
4198 assert_equal(0, A_func2)
4199 assert_equal(0, A_func3)
4200 assert_equal(3, B_func2)
4201 assert_equal(0, B_func3)
4202 assert_equal(3, C_func3)
4203 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004204 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004205enddef
4206
4207" Test for using members from three levels of classes
4208def Test_multi_level_member_access()
4209 var lines =<< trim END
4210 vim9script
4211
4212 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004213 public var val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004214 endclass
4215
4216 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004217 public var val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004218 endclass
4219
4220 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01004221 public var val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004222 endclass
4223
4224 def A_members(a: A)
4225 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004226 enddef
4227
4228 def B_members(b: B)
4229 b.val1 += 1
4230 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004231 enddef
4232
4233 def C_members(c: C)
4234 c.val1 += 1
4235 c.val2 += 1
4236 c.val3 += 1
4237 enddef
4238
4239 var cobj = C.new()
4240 A_members(cobj)
4241 B_members(cobj)
4242 C_members(cobj)
4243 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004244 assert_equal(2, cobj.val2)
4245 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004246 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004247 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004248enddef
4249
LemonBoy0ffc17a2023-08-20 18:09:11 +02004250" Test expansion of <stack> with class methods.
4251def Test_stack_expansion_with_methods()
4252 var lines =<< trim END
4253 vim9script
4254
4255 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004256 def M1()
4257 F0()
4258 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02004259 endclass
4260
4261 def F0()
Ernie Rael16cdfa62024-04-02 19:05:39 +02004262 assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
LemonBoy0ffc17a2023-08-20 18:09:11 +02004263 enddef
4264
4265 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004266 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02004267 enddef
4268
4269 F()
4270 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004271 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02004272enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004273
4274" Test the return type of the new() constructor
4275def Test_new_return_type()
4276 # new() uses the default return type and there is no return statement
4277 var lines =<< trim END
4278 vim9script
4279
4280 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004281 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004282
4283 def new(this._bufnr)
4284 if !bufexists(this._bufnr)
4285 this._bufnr = -1
4286 endif
4287 enddef
4288 endclass
4289
4290 var c = C.new(12345)
4291 assert_equal('object<C>', typename(c))
4292
4293 var v1: C
4294 v1 = C.new(12345)
4295 assert_equal('object<C>', typename(v1))
4296
4297 def F()
4298 var v2: C
4299 v2 = C.new(12345)
4300 assert_equal('object<C>', typename(v2))
4301 enddef
4302 F()
4303 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004304 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004305
4306 # new() uses the default return type and an empty 'return' statement
4307 lines =<< trim END
4308 vim9script
4309
4310 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004311 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004312
4313 def new(this._bufnr)
4314 if !bufexists(this._bufnr)
4315 this._bufnr = -1
4316 return
4317 endif
4318 enddef
4319 endclass
4320
4321 var c = C.new(12345)
4322 assert_equal('object<C>', typename(c))
4323
4324 var v1: C
4325 v1 = C.new(12345)
4326 assert_equal('object<C>', typename(v1))
4327
4328 def F()
4329 var v2: C
4330 v2 = C.new(12345)
4331 assert_equal('object<C>', typename(v2))
4332 enddef
4333 F()
4334 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004335 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004336
4337 # new() uses "any" return type and returns "this"
4338 lines =<< trim END
4339 vim9script
4340
4341 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004342 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004343
4344 def new(this._bufnr): any
4345 if !bufexists(this._bufnr)
4346 this._bufnr = -1
4347 return this
4348 endif
4349 enddef
4350 endclass
4351 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004352 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004353
4354 # new() uses 'Dict' return type and returns a Dict
4355 lines =<< trim END
4356 vim9script
4357
4358 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004359 var _state: dict<any>
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004360
4361 def new(): dict<any>
4362 this._state = {}
4363 return this._state
4364 enddef
4365 endclass
4366
4367 var c = C.new()
4368 assert_equal('object<C>', typename(c))
4369 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004370 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004371enddef
4372
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004373" Test for checking a member initialization type at run time.
4374def Test_runtime_type_check_for_member_init()
4375 var lines =<< trim END
4376 vim9script
4377
4378 var retnum: bool = false
4379
4380 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004381 retnum = !retnum
4382 if retnum
4383 return 1
4384 else
4385 return "hello"
4386 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004387 enddef
4388
4389 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004390 var _foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004391 endclass
4392
4393 var c1 = C.new()
4394 var c2 = C.new()
4395 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004396 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004397enddef
4398
4399" Test for locking a variable referring to an object and reassigning to another
4400" object.
Ernie Raelee865f32023-09-29 19:53:55 +02004401def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004402 var lines =<< trim END
4403 vim9script
4404
4405 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004406 var val: number
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004407 def new(this.val)
4408 enddef
4409 endclass
4410
4411 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
4412 lockvar 2 some_dict
4413
4414 var current: C
4415 current = some_dict['c']
4416 assert_equal(3, current.val)
4417 current = some_dict['b']
4418 assert_equal(2, current.val)
4419
4420 def F()
4421 current = some_dict['c']
4422 enddef
4423
4424 def G()
4425 current = some_dict['b']
4426 enddef
4427
4428 F()
4429 assert_equal(3, current.val)
4430 G()
4431 assert_equal(2, current.val)
4432 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004433 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004434enddef
4435
Ernie Raelee865f32023-09-29 19:53:55 +02004436" Test trying to lock an object variable from various places
4437def Test_lockvar_object_variable()
4438 # An object variable lockvar has several cases:
4439 # object method, scriptlevel, scriplevel from :def, :def arg
4440 # method arg, static method arg.
4441 # Also different depths
4442
Ernie Raelee865f32023-09-29 19:53:55 +02004443 #
4444 # lockvar of read-only object variable
4445 #
4446
4447 # read-only lockvar from object method
4448 var lines =<< trim END
4449 vim9script
4450
4451 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004452 var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004453 def Lock()
4454 lockvar this.val1
4455 enddef
4456 endclass
4457 var o = C.new(3)
4458 o.Lock()
4459 END
Ernie Rael64885642023-10-04 20:16:22 +02004460 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004461
4462 # read-only lockvar from scriptlevel
4463 lines =<< trim END
4464 vim9script
4465
4466 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004467 var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004468 endclass
4469 var o = C.new(3)
4470 lockvar o.val2
4471 END
4472 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
4473
4474 # read-only lockvar of scriptlevel variable from def
4475 lines =<< trim END
4476 vim9script
4477
4478 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004479 var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004480 endclass
4481 var o = C.new(3)
4482 def Lock()
4483 lockvar o.val3
4484 enddef
4485 Lock()
4486 END
4487 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
4488
4489 # read-only lockvar of def argument variable
4490 lines =<< trim END
4491 vim9script
4492
4493 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004494 var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004495 endclass
4496 def Lock(o: C)
4497 lockvar o.val4
4498 enddef
4499 Lock(C.new(3))
4500 END
4501 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
4502
Ernie Raelee865f32023-09-29 19:53:55 +02004503 # read-only lockvar from object method arg
4504 lines =<< trim END
4505 vim9script
4506
4507 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004508 var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004509 def Lock(c: C)
4510 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004511 enddef
4512 endclass
4513 var o = C.new(3)
4514 o.Lock(C.new(5))
4515 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004516 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004517
4518 # read-only lockvar from class method arg
4519 lines =<< trim END
4520 vim9script
4521
4522 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004523 var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004524 static def Lock(c: C)
4525 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004526 enddef
4527 endclass
4528 var o = C.new(3)
4529 C.Lock(o)
4530 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004531 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004532
4533 #
4534 # lockvar of public object variable
4535 #
4536
4537 # lockvar from object method
4538 lines =<< trim END
4539 vim9script
4540
4541 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004542 public var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004543 def Lock()
4544 lockvar this.val1
4545 enddef
4546 endclass
4547 var o = C.new(3)
4548 o.Lock()
4549 END
4550 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
4551
4552 # lockvar from scriptlevel
4553 lines =<< trim END
4554 vim9script
4555
4556 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004557 public var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004558 endclass
4559 var o = C.new(3)
4560 lockvar o.val2
4561 END
4562 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
4563
4564 # lockvar of scriptlevel variable from def
4565 lines =<< trim END
4566 vim9script
4567
4568 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004569 public var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004570 endclass
4571 var o = C.new(3)
4572 def Lock()
4573 lockvar o.val3
4574 enddef
4575 Lock()
4576 END
4577 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
4578
4579 # lockvar of def argument variable
4580 lines =<< trim END
4581 vim9script
4582
4583 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004584 public var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004585 endclass
4586 def Lock(o: C)
4587 lockvar o.val4
4588 enddef
4589 Lock(C.new(3))
4590 END
4591 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
4592
4593 # lockvar from object method arg
4594 lines =<< trim END
4595 vim9script
4596
4597 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004598 public var val5: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004599 def Lock(c: C)
4600 lockvar c.val5
Ernie Raelee865f32023-09-29 19:53:55 +02004601 enddef
4602 endclass
4603 var o = C.new(3)
4604 o.Lock(C.new(5))
4605 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004606 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val5" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004607
4608 # lockvar from class method arg
4609 lines =<< trim END
4610 vim9script
4611
4612 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004613 public var val6: number
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004614 static def Lock(c: C)
4615 lockvar c.val6
Ernie Raelee865f32023-09-29 19:53:55 +02004616 enddef
4617 endclass
4618 var o = C.new(3)
4619 C.Lock(o)
4620 END
Yegappan Lakshmanan0072cee2025-01-07 20:22:32 +01004621 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "c.val6" in class "C"', 1)
Ernie Raelee865f32023-09-29 19:53:55 +02004622enddef
4623
4624" Test trying to lock a class variable from various places
4625def Test_lockvar_class_variable()
4626
4627 # lockvar bare static from object method
4628 var lines =<< trim END
4629 vim9script
4630
4631 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004632 public static var sval1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004633 def Lock()
4634 lockvar sval1
4635 enddef
4636 endclass
4637 var o = C.new()
4638 o.Lock()
4639 END
4640 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
4641
4642 # lockvar C.static from object method
4643 lines =<< trim END
4644 vim9script
4645
4646 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004647 public static var sval2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004648 def Lock()
4649 lockvar C.sval2
4650 enddef
4651 endclass
4652 var o = C.new()
4653 o.Lock()
4654 END
4655 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
4656
4657 # lockvar bare static from class method
4658 lines =<< trim END
4659 vim9script
4660
4661 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004662 public static var sval3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004663 static def Lock()
4664 lockvar sval3
4665 enddef
4666 endclass
4667 C.Lock()
4668 END
4669 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
4670
4671 # lockvar C.static from class method
4672 lines =<< trim END
4673 vim9script
4674
4675 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004676 public static var sval4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004677 static def Lock()
4678 lockvar C.sval4
4679 enddef
4680 endclass
4681 C.Lock()
4682 END
4683 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
4684
4685 # lockvar C.static from script level
4686 lines =<< trim END
4687 vim9script
4688
4689 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004690 public static var sval5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004691 endclass
4692 lockvar C.sval5
4693 END
4694 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
4695
4696 # lockvar o.static from script level
4697 lines =<< trim END
4698 vim9script
4699
4700 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004701 public static var sval6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004702 endclass
4703 var o = C.new()
4704 lockvar o.sval6
4705 END
4706 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
4707enddef
4708
4709" Test locking an argument to :def
4710def Test_lockvar_argument()
4711 # Lockvar a function arg
4712 var lines =<< trim END
4713 vim9script
4714
4715 def Lock(val: any)
4716 lockvar val
4717 enddef
4718
4719 var d = {a: 1, b: 2}
4720 Lock(d)
4721
4722 d->extend({c: 3})
4723 END
4724 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
4725
4726 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
4727 # class member in "C". This tests lval_root_is_arg.
4728 lines =<< trim END
4729 vim9script
4730
4731 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004732 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004733 endclass
4734
4735 def Lock2(sval: any)
4736 lockvar sval
4737 enddef
4738
4739 var o = C.new()
4740 Lock2(o)
4741 END
4742 v9.CheckSourceSuccess(lines)
4743
4744 # Lock a class.
4745 lines =<< trim END
4746 vim9script
4747
4748 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004749 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004750 endclass
4751
4752 def Lock2(sval: any)
4753 lockvar sval
4754 enddef
4755
4756 Lock2(C)
4757 END
Ernie Raelb077b582023-12-14 20:11:44 +01004758 v9.CheckSourceFailure(lines, 'E1405: Class "C" cannot be used as a value')
Ernie Raelee865f32023-09-29 19:53:55 +02004759
4760 # Lock an object.
4761 lines =<< trim END
4762 vim9script
4763
4764 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004765 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004766 endclass
4767
4768 def Lock2(sval: any)
4769 lockvar sval
4770 enddef
4771
4772 Lock2(C.new())
4773 END
4774 v9.CheckSourceSuccess(lines)
4775
4776 # In this case (unlike previous) "lockvar sval" is a class member.
4777 lines =<< trim END
4778 vim9script
4779
4780 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004781 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004782 def Lock2()
4783 lockvar sval
4784 enddef
4785 endclass
4786
4787
4788 var o = C.new()
4789 o.Lock2()
4790 END
4791 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4792enddef
4793
4794" Test that this can be locked without error
4795def Test_lockvar_this()
4796 # lockvar this
4797 var lines =<< trim END
4798 vim9script
4799 class C
4800 def TLock()
4801 lockvar this
4802 enddef
4803 endclass
4804 var o = C.new()
4805 o.TLock()
4806 END
4807 v9.CheckSourceSuccess(lines)
4808
4809 # lockvar four (four letter word, but not this)
4810 lines =<< trim END
4811 vim9script
4812 class C
4813 def TLock4()
4814 var four: number
4815 lockvar four
4816 enddef
4817 endclass
4818 var o = C.new()
4819 o.TLock4()
4820 END
4821 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4822
4823 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4824 lines =<< trim END
4825 vim9script
4826 class C
4827 def TLock5()
4828 var this5: number
4829 lockvar this5
4830 enddef
4831 endclass
4832 var o = C.new()
4833 o.TLock5()
4834 END
4835 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4836enddef
4837
4838" Test some general lockvar cases
4839def Test_lockvar_general()
4840 # lockvar an object and a class. It does nothing
4841 var lines =<< trim END
4842 vim9script
4843 class C
4844 endclass
4845 var o = C.new()
4846 lockvar o
4847 lockvar C
4848 END
4849 v9.CheckSourceSuccess(lines)
4850
4851 # Lock a list element that's nested in an object variable from a :def
4852 lines =<< trim END
4853 vim9script
4854
4855 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004856 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004857 endclass
4858 def Lock2(obj: any)
4859 lockvar obj.val[1]
4860 enddef
4861
4862 var o = C.new()
4863 Lock2(o)
4864 o.val[0] = [9]
4865 assert_equal([ [9], [2], [3] ], o.val)
4866 try
4867 o.val[1] = [999]
4868 call assert_false(true, 'assign should have failed')
4869 catch
4870 assert_exception('E741:')
4871 endtry
4872 o.val[2] = [8]
4873 assert_equal([ [9], [2], [8] ], o.val)
4874 END
4875 v9.CheckSourceSuccess(lines)
4876
4877 # Lock a list element that's nested in an object variable from scriptlevel
4878 lines =<< trim END
4879 vim9script
4880
4881 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004882 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004883 endclass
4884
4885 var o = C.new()
4886 lockvar o.val[1]
4887 o.val[0] = [9]
4888 assert_equal([ [9], [2], [3] ], o.val)
4889 try
4890 o.val[1] = [999]
4891 call assert_false(true, 'assign should have failed')
4892 catch
4893 assert_exception('E741:')
4894 endtry
4895 o.val[2] = [8]
4896 assert_equal([ [9], [2], [8] ], o.val)
4897 END
4898 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004899
4900 # lock a script level variable from an object method
4901 lines =<< trim END
4902 vim9script
4903
4904 class C
4905 def Lock()
4906 lockvar l
4907 enddef
4908 endclass
4909
4910 var l = [1]
4911 C.new().Lock()
4912 l[0] = 11
4913 END
4914 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4915
Ernie Rael03042a22023-11-11 08:53:32 +01004916 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004917 # in an object fetched via a script level list
4918 lines =<< trim END
4919 vim9script
4920
4921 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004922 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004923 def Lock()
4924 lockvar lc[0]._v1[1]
4925 enddef
4926 endclass
4927
4928 var l = [[1], [2], [3]]
4929 var o = C.new(l)
4930 var lc: list<C> = [ o ]
4931
4932 o.Lock()
4933 l[0] = [22]
4934 l[1] = [33]
4935 END
4936 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4937
4938 # similar to the previous test, except the locking code is executing
Ernie Rael03042a22023-11-11 08:53:32 +01004939 # in a class that does not own the protected variable.
4940 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02004941 # the same name.
4942 lines =<< trim END
4943 vim9script
4944
4945 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004946 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004947 def Lock(obj: any)
4948 lockvar lc[0]._v1[1]
4949 enddef
4950 endclass
4951
4952 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004953 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004954 endclass
4955
4956 var l = [[1], [2], [3]]
4957 var o = C.new(l)
4958 var lc: list<C> = [ o ]
4959
4960 var o2 = C2.new()
4961 o2.Lock(o)
4962 END
Ernie Rael03042a22023-11-11 08:53:32 +01004963 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004964enddef
4965
Ernie Rael9771b2a2023-10-07 22:05:40 +02004966" Test builtin islocked()
4967def Test_lockvar_islocked()
4968 # Can't lock class/object variable
4969 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01004970 # Lock item of variable's value (a list item)
4971 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02004972 var lines =<< trim END
4973 vim9script
4974
4975 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004976 var o0: list<list<number>> = [ [0], [1], [2]]
4977 var o1: list<list<number>> = [[10], [11], [12]]
4978 static var c0: list<list<number>> = [[20], [21], [22]]
4979 static var c1: list<list<number>> = [[30], [31], [32]]
Ernie Rael9771b2a2023-10-07 22:05:40 +02004980 endclass
4981
4982 def LockIt(arg: any)
4983 lockvar arg
4984 enddef
4985
4986 def UnlockIt(arg: any)
4987 unlockvar arg
4988 enddef
4989
4990 var obj = C.new()
4991 #lockvar obj.o1 # can't lock something you can't write to
4992
4993 try
4994 lockvar obj.o1 # can't lock something you can't write to
4995 call assert_false(1, '"lockvar obj.o1" should have failed')
4996 catch
4997 call assert_exception('E1335:')
4998 endtry
4999
5000 LockIt(obj.o1) # but can lock it's value
5001 assert_equal(1, islocked("obj.o1"))
5002 assert_equal(1, islocked("obj.o1[0]"))
5003 assert_equal(1, islocked("obj.o1[1]"))
5004 UnlockIt(obj.o1)
5005 assert_equal(0, islocked("obj.o1"))
5006 assert_equal(0, islocked("obj.o1[0]"))
5007
5008 lockvar obj.o1[0]
5009 assert_equal(0, islocked("obj.o1"))
5010 assert_equal(1, islocked("obj.o1[0]"))
5011 assert_equal(0, islocked("obj.o1[1]"))
5012 unlockvar obj.o1[0]
5013 assert_equal(0, islocked("obj.o1"))
5014 assert_equal(0, islocked("obj.o1[0]"))
5015
5016 # Same thing, but with a static
5017
5018 try
5019 lockvar C.c1 # can't lock something you can't write to
5020 call assert_false(1, '"lockvar C.c1" should have failed')
5021 catch
5022 call assert_exception('E1335:')
5023 endtry
5024
5025 LockIt(C.c1) # but can lock it's value
5026 assert_equal(1, islocked("C.c1"))
5027 assert_equal(1, islocked("C.c1[0]"))
5028 assert_equal(1, islocked("C.c1[1]"))
5029 UnlockIt(C.c1)
5030 assert_equal(0, islocked("C.c1"))
5031 assert_equal(0, islocked("C.c1[0]"))
5032
5033 lockvar C.c1[0]
5034 assert_equal(0, islocked("C.c1"))
5035 assert_equal(1, islocked("C.c1[0]"))
5036 assert_equal(0, islocked("C.c1[1]"))
5037 unlockvar C.c1[0]
5038 assert_equal(0, islocked("C.c1"))
5039 assert_equal(0, islocked("C.c1[0]"))
5040 END
5041 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02005042
5043 # Do islocked() from an object method
5044 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02005045 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02005046 vim9script
5047
5048 var l0o0 = [ [0], [1], [2]]
5049 var l0o1 = [ [10], [11], [12]]
5050 var l0c0 = [[120], [121], [122]]
5051 var l0c1 = [[130], [131], [132]]
5052
5053 class C0
Doug Kearns74da0ee2023-12-14 20:26:26 +01005054 var o0: list<list<number>> = l0o0
5055 var o1: list<list<number>> = l0o1
5056 static var c0: list<list<number>> = l0c0
5057 static var c1: list<list<number>> = l0c1
Ernie Rael4c8da022023-10-11 21:35:11 +02005058 def Islocked(arg: string): number
5059 return islocked(arg)
5060 enddef
5061 static def SIslocked(arg: string): number
5062 return islocked(arg)
5063 enddef
5064 endclass
5065
5066 var l2o0 = [[20000], [20001], [20002]]
5067 var l2o1 = [[20010], [20011], [20012]]
5068 var l2c0 = [[20120], [20121], [20122]]
5069 var l2c1 = [[20130], [20131], [20132]]
5070
5071 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01005072 var o0: list<list<number>> = l2o0
5073 var o1: list<list<number>> = l2o1
5074 static var c0: list<list<number>> = l2c0
5075 static var c1: list<list<number>> = l2c1
Ernie Rael4c8da022023-10-11 21:35:11 +02005076 def Islocked(arg: string): number
5077 return islocked(arg)
5078 enddef
5079 static def SIslocked(arg: string): number
5080 return islocked(arg)
5081 enddef
5082 endclass
5083
5084 var obj0 = C0.new()
5085 var obj2 = C2.new()
5086
5087 var l = [ obj0, null_object, obj2 ]
5088
5089 # lock list, object func access through script var expr
5090 assert_equal(0, obj0.Islocked("l[0].o0"))
5091 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
5092 lockvar l0o0
5093 assert_equal(1, obj0.Islocked("l[0].o0"))
5094 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
5095
5096 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
5097
5098 # lock list element, object func access through script var expr
5099 lockvar l0o1[1]
5100 assert_equal(0, obj0.Islocked("this.o1[0]"))
5101 assert_equal(1, obj0.Islocked("this.o1[1]"))
5102
5103 assert_equal(0, obj0.Islocked("this.o1"))
5104 lockvar l0o1
5105 assert_equal(1, obj0.Islocked("this.o1"))
5106 unlockvar l0o1
5107
5108 lockvar l0c1[1]
5109
5110 # static by class name member expr from same class
5111 assert_equal(0, obj0.Islocked("C0.c1[0]"))
5112 assert_equal(1, obj0.Islocked("C0.c1[1]"))
5113 # static by bare name member expr from same class
5114 assert_equal(0, obj0.Islocked("c1[0]"))
5115 assert_equal(1, obj0.Islocked("c1[1]"))
5116
5117 # static by class name member expr from other class
5118 assert_equal(0, obj2.Islocked("C0.c1[0]"))
5119 assert_equal(1, obj2.Islocked("C0.c1[1]"))
5120 # static by bare name member expr from other class
5121 assert_equal(0, obj2.Islocked("c1[0]"))
5122 assert_equal(0, obj2.Islocked("c1[1]"))
5123
5124
5125 # static by bare name in same class
5126 assert_equal(0, obj0.Islocked("c0"))
5127 lockvar l0c0
5128 assert_equal(1, obj0.Islocked("c0"))
5129
5130 #
5131 # similar stuff, but use static method
5132 #
5133
5134 unlockvar l0o0
5135
5136 # lock list, object func access through script var expr
5137 assert_equal(0, C0.SIslocked("l[0].o0"))
5138 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
5139 lockvar l0o0
5140 assert_equal(1, C0.SIslocked("l[0].o0"))
5141 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
5142
5143 unlockvar l0o1
5144
5145 # can't access "this" from class method
5146 try
5147 C0.SIslocked("this.o1[0]")
5148 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
5149 catch
5150 call assert_exception('E121: Undefined variable: this')
5151 endtry
5152
5153 lockvar l0c1[1]
5154
5155 # static by class name member expr from same class
5156 assert_equal(0, C0.SIslocked("C0.c1[0]"))
5157 assert_equal(1, C0.SIslocked("C0.c1[1]"))
5158 # static by bare name member expr from same class
5159 assert_equal(0, C0.SIslocked("c1[0]"))
5160 assert_equal(1, C0.SIslocked("c1[1]"))
5161
5162 # static by class name member expr from other class
5163 assert_equal(0, C2.SIslocked("C0.c1[0]"))
5164 assert_equal(1, C2.SIslocked("C0.c1[1]"))
5165 # static by bare name member expr from other class
5166 assert_equal(0, C2.SIslocked("c1[0]"))
5167 assert_equal(0, C2.SIslocked("c1[1]"))
5168
5169
5170 # static by bare name in same class
5171 unlockvar l0c0
5172 assert_equal(0, C0.SIslocked("c0"))
5173 lockvar l0c0
5174 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02005175 END
Ernie Rael4c8da022023-10-11 21:35:11 +02005176 v9.CheckSourceSuccess(lines)
5177
5178 # Check islocked class/object from various places.
5179 lines =<< trim END
5180 vim9script
5181
5182 class C
5183 def Islocked(arg: string): number
5184 return islocked(arg)
5185 enddef
5186 static def SIslocked(arg: string): number
5187 return islocked(arg)
5188 enddef
5189 endclass
5190 var obj = C.new()
5191
5192 # object method
5193 assert_equal(0, obj.Islocked("this"))
5194 assert_equal(0, obj.Islocked("C"))
5195
5196 # class method
5197 ### assert_equal(0, C.SIslocked("this"))
5198 assert_equal(0, C.SIslocked("C"))
5199
5200 #script level
5201 var v: number
5202 v = islocked("C")
5203 assert_equal(0, v)
5204 v = islocked("obj")
5205 assert_equal(0, v)
5206 END
5207 v9.CheckSourceSuccess(lines)
5208enddef
5209
5210def Test_lockvar_islocked_notfound()
5211 # Try non-existent things
5212 var lines =<< trim END
5213 vim9script
5214
5215 class C
5216 def Islocked(arg: string): number
5217 return islocked(arg)
5218 enddef
5219 static def SIslocked(arg: string): number
5220 return islocked(arg)
5221 enddef
5222 endclass
5223 var obj = C.new()
5224 assert_equal(-1, obj.Islocked("anywhere"))
5225 assert_equal(-1, C.SIslocked("notanywhere"))
5226 END
5227 v9.CheckSourceSuccess(lines)
5228
5229 # Something not found of the form "name1.name2" is an error
5230 lines =<< trim END
5231 vim9script
5232
5233 islocked("one.two")
5234 END
5235 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
5236
5237 lines =<< trim END
5238 vim9script
5239
5240 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005241 var val = { key: "value" }
Ernie Rael4c8da022023-10-11 21:35:11 +02005242 def Islocked(arg: string): number
5243 return islocked(arg)
5244 enddef
5245 endclass
5246 var obj = C.new()
5247 obj.Islocked("this.val.not_there"))
5248 END
5249 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
5250
5251 lines =<< trim END
5252 vim9script
5253
5254 class C
5255 def Islocked(arg: string): number
5256 return islocked(arg)
5257 enddef
5258 endclass
5259 var obj = C.new()
5260 obj.Islocked("this.notobjmember")
5261 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005262 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02005263
5264 # access a script variable through methods
5265 lines =<< trim END
5266 vim9script
5267
5268 var l = [1]
5269 class C
5270 def Islocked(arg: string): number
5271 return islocked(arg)
5272 enddef
5273 static def SIslocked(arg: string): number
5274 return islocked(arg)
5275 enddef
5276 endclass
5277 var obj = C.new()
5278 assert_equal(0, obj.Islocked("l"))
5279 assert_equal(0, C.SIslocked("l"))
5280 lockvar l
5281 assert_equal(1, obj.Islocked("l"))
5282 assert_equal(1, C.SIslocked("l"))
5283 END
5284 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02005285enddef
5286
Ernie Rael03042a22023-11-11 08:53:32 +01005287" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005288def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005289 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005290 var lines =<< trim END
5291 vim9script
5292
5293 class A
5294 def _Foo(): number
5295 return 1234
5296 enddef
5297 endclass
5298 var a = A.new()
5299 a._Foo()
5300 END
Ernie Rael03042a22023-11-11 08:53:32 +01005301 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005302
Ernie Rael03042a22023-11-11 08:53:32 +01005303 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005304 lines =<< trim END
5305 vim9script
5306
5307 class A
5308 def _Foo(): number
5309 return 1234
5310 enddef
5311 endclass
5312 def T()
5313 var a = A.new()
5314 a._Foo()
5315 enddef
5316 T()
5317 END
Ernie Rael03042a22023-11-11 08:53:32 +01005318 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005319
Ernie Rael03042a22023-11-11 08:53:32 +01005320 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005321 lines =<< trim END
5322 vim9script
5323
5324 class A
5325 def _Foo(): number
5326 return 1234
5327 enddef
5328 def Bar(): number
5329 return this._Foo()
5330 enddef
5331 endclass
5332 var a = A.new()
5333 assert_equal(1234, a.Bar())
5334 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005335 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005336
Ernie Rael03042a22023-11-11 08:53:32 +01005337 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005338 lines =<< trim END
5339 vim9script
5340
5341 class A
5342 def _Foo(): number
5343 return 1234
5344 enddef
5345 def Bar(): number
5346 return this._Foo()
5347 enddef
5348 endclass
5349 def T()
5350 var a = A.new()
5351 assert_equal(1234, a.Bar())
5352 enddef
5353 T()
5354 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005355 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005356
Ernie Rael03042a22023-11-11 08:53:32 +01005357 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005358 lines =<< trim END
5359 vim9script
5360
5361 class A
5362 def _Foo(): number
5363 return 1234
5364 enddef
5365 def Bar(): number
5366 return _Foo()
5367 enddef
5368 endclass
5369 var a = A.new()
5370 a.Bar()
5371 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005372 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005373
Ernie Rael03042a22023-11-11 08:53:32 +01005374 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005375 lines =<< trim END
5376 vim9script
5377
5378 class A
5379 def _Foo(): number
5380 return 1234
5381 enddef
5382 endclass
5383 A._Foo()
5384 END
Ernie Rael03042a22023-11-11 08:53:32 +01005385 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005386
Ernie Rael03042a22023-11-11 08:53:32 +01005387 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005388 lines =<< trim END
5389 vim9script
5390
5391 class A
5392 def _Foo()
5393 enddef
5394 def _Foo()
5395 enddef
5396 endclass
5397 var a = A.new()
5398 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005399 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005400
Ernie Rael03042a22023-11-11 08:53:32 +01005401 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005402 lines =<< trim END
5403 vim9script
5404
5405 class A
5406 def _Foo()
5407 enddef
5408 def Foo()
5409 enddef
5410 endclass
5411 var a = A.new()
5412 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005413 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005414
Ernie Rael03042a22023-11-11 08:53:32 +01005415 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005416 lines =<< trim END
5417 vim9script
5418
5419 class A
5420 def Foo()
5421 enddef
5422 def _Foo()
5423 enddef
5424 endclass
5425 var a = A.new()
5426 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005427 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005428
Ernie Rael03042a22023-11-11 08:53:32 +01005429 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005430 lines =<< trim END
5431 vim9script
5432
5433 class A
5434 def Foo(): number
5435 return 100
5436 enddef
5437 def _Bar(): number
5438 return 200
5439 enddef
5440 def _Baz()
5441 assert_equal(100, this.Foo())
5442 assert_equal(200, this._Bar())
5443 enddef
5444 def T()
5445 this._Baz()
5446 enddef
5447 endclass
5448 var a = A.new()
5449 a.T()
5450 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005451 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005452
Ernie Rael03042a22023-11-11 08:53:32 +01005453 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005454 lines =<< trim END
5455 vim9script
5456
5457 class A
5458 def _Foo(): number
5459 return 100
5460 enddef
5461 endclass
5462 class B
5463 def Foo(): number
5464 var a = A.new()
5465 a._Foo()
5466 enddef
5467 endclass
5468 var b = B.new()
5469 b.Foo()
5470 END
Ernie Rael03042a22023-11-11 08:53:32 +01005471 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005472
Ernie Rael03042a22023-11-11 08:53:32 +01005473 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005474 lines =<< trim END
5475 vim9script
5476 class A
5477 def _Foo(): number
5478 return 1234
5479 enddef
5480 endclass
5481 class B extends A
5482 def Bar()
5483 enddef
5484 endclass
5485 class C extends B
5486 def Baz(): number
5487 return this._Foo()
5488 enddef
5489 endclass
5490 var c = C.new()
5491 assert_equal(1234, c.Baz())
5492 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005493 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005494
Ernie Rael03042a22023-11-11 08:53:32 +01005495 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005496 lines =<< trim END
5497 vim9script
5498 class A
5499 def _Foo(): number
5500 return 1234
5501 enddef
5502 endclass
5503 class B extends A
5504 def Bar()
5505 enddef
5506 endclass
5507 class C extends B
5508 def Baz(): number
5509 enddef
5510 endclass
5511 var c = C.new()
5512 assert_equal(1234, c._Foo())
5513 END
Ernie Rael03042a22023-11-11 08:53:32 +01005514 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005515
5516 # Using "_" prefix in a method name should fail outside of a class
5517 lines =<< trim END
5518 vim9script
5519 def _Foo(): number
5520 return 1234
5521 enddef
5522 var a = _Foo()
5523 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005524 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005525enddef
5526
Ernie Rael03042a22023-11-11 08:53:32 +01005527" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005528def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005529 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005530 var lines =<< trim END
5531 vim9script
5532
5533 class A
5534 static def _Foo(): number
5535 return 1234
5536 enddef
5537 endclass
5538 A._Foo()
5539 END
Ernie Rael03042a22023-11-11 08:53:32 +01005540 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005541
Ernie Rael03042a22023-11-11 08:53:32 +01005542 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005543 lines =<< trim END
5544 vim9script
5545
5546 class A
5547 static def _Foo(): number
5548 return 1234
5549 enddef
5550 endclass
5551 def T()
5552 A._Foo()
5553 enddef
5554 T()
5555 END
Ernie Rael03042a22023-11-11 08:53:32 +01005556 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005557
Ernie Rael03042a22023-11-11 08:53:32 +01005558 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005559 lines =<< trim END
5560 vim9script
5561
5562 class A
5563 static def _Foo(): number
5564 return 1234
5565 enddef
5566 endclass
5567 var a = A.new()
5568 a._Foo()
5569 END
Ernie Rael03042a22023-11-11 08:53:32 +01005570 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005571
Ernie Rael03042a22023-11-11 08:53:32 +01005572 # Try calling a class protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005573 lines =<< trim END
5574 vim9script
5575
5576 class A
5577 static def _Foo(): number
5578 return 1234
5579 enddef
5580 endclass
5581 def T()
5582 var a = A.new()
5583 a._Foo()
5584 enddef
5585 T()
5586 END
Ernie Rael03042a22023-11-11 08:53:32 +01005587 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005588
Ernie Rael03042a22023-11-11 08:53:32 +01005589 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005590 lines =<< trim END
5591 vim9script
5592
5593 class A
5594 static def _Foo(): number
5595 return 1234
5596 enddef
5597 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005598 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005599 enddef
5600 endclass
5601 var a = A.new()
5602 a.Bar()
5603 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005604 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005605
Ernie Rael03042a22023-11-11 08:53:32 +01005606 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005607 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005608 lines =<< trim END
5609 vim9script
5610
5611 class A
5612 static def _Foo1(): number
5613 return 1234
5614 enddef
5615 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005616 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005617 enddef
5618 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005619 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005620 enddef
5621 endclass
5622 var a = A.new()
5623 a.Bar()
5624 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005625 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005626
Ernie Rael03042a22023-11-11 08:53:32 +01005627 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005628 lines =<< trim END
5629 vim9script
5630
5631 class A
5632 static def _Foo()
5633 enddef
5634 static def Foo()
5635 enddef
5636 endclass
5637 var a = A.new()
5638 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005639 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005640
Ernie Rael03042a22023-11-11 08:53:32 +01005641 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005642 lines =<< trim END
5643 vim9script
5644
5645 class A
5646 static def _Foo(): number
5647 return 1234
5648 enddef
5649 endclass
5650 class B
5651 def Foo(): number
5652 return A._Foo()
5653 enddef
5654 endclass
5655 var b = B.new()
5656 assert_equal(1234, b.Foo())
5657 END
Ernie Rael03042a22023-11-11 08:53:32 +01005658 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005659
Ernie Rael03042a22023-11-11 08:53:32 +01005660 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005661 lines =<< trim END
5662 vim9script
5663 class A
5664 static def _Foo(): number
5665 return 1234
5666 enddef
5667 endclass
5668 class B extends A
5669 def Bar()
5670 enddef
5671 endclass
5672 class C extends B
5673 def Baz(): number
5674 return A._Foo()
5675 enddef
5676 endclass
5677 var c = C.new()
5678 assert_equal(1234, c.Baz())
5679 END
Ernie Rael03042a22023-11-11 08:53:32 +01005680 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005681
Ernie Rael03042a22023-11-11 08:53:32 +01005682 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005683 lines =<< trim END
5684 vim9script
5685 class A
5686 static def _Foo(): number
5687 return 1234
5688 enddef
5689 endclass
5690 class B extends A
5691 def Bar()
5692 enddef
5693 endclass
5694 class C extends B
5695 static def Baz(): number
5696 return A._Foo()
5697 enddef
5698 endclass
5699 assert_equal(1234, C.Baz())
5700 END
Ernie Rael03042a22023-11-11 08:53:32 +01005701 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005702
Ernie Rael03042a22023-11-11 08:53:32 +01005703 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005704 lines =<< trim END
5705 vim9script
5706 class A
5707 static def _Foo(): number
5708 return 1234
5709 enddef
5710 endclass
5711 class B extends A
5712 def Bar()
5713 enddef
5714 endclass
5715 class C extends B
5716 def Baz(): number
5717 enddef
5718 endclass
5719 var c = C.new()
5720 assert_equal(1234, C._Foo())
5721 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005722 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005723enddef
5724
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005725" Test for using the return value of a class/object method as a function
5726" argument.
5727def Test_objmethod_funcarg()
5728 var lines =<< trim END
5729 vim9script
5730
5731 class C
5732 def Foo(): string
5733 return 'foo'
5734 enddef
5735 endclass
5736
5737 def Bar(a: number, s: string): string
5738 return s
5739 enddef
5740
5741 def Baz(c: C)
5742 assert_equal('foo', Bar(10, c.Foo()))
5743 enddef
5744
5745 var t = C.new()
5746 Baz(t)
5747 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005748 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005749
5750 lines =<< trim END
5751 vim9script
5752
5753 class C
5754 static def Foo(): string
5755 return 'foo'
5756 enddef
5757 endclass
5758
5759 def Bar(a: number, s: string): string
5760 return s
5761 enddef
5762
5763 def Baz()
5764 assert_equal('foo', Bar(10, C.Foo()))
5765 enddef
5766
5767 Baz()
5768 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005769 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005770enddef
5771
Ernie Raelcf138d42023-09-06 20:45:03 +02005772def Test_static_inheritence()
5773 # subclasses get their own static copy
5774 var lines =<< trim END
5775 vim9script
5776
5777 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005778 static var _svar: number
5779 var _mvar: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005780 def new()
5781 _svar = 1
5782 this._mvar = 101
5783 enddef
5784 def AccessObject(): number
5785 return this._mvar
5786 enddef
5787 def AccessStaticThroughObject(): number
5788 return _svar
5789 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005790 endclass
5791
5792 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005793 def new()
5794 this._mvar = 102
5795 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005796 endclass
5797
5798 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005799 def new()
5800 this._mvar = 103
5801 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005802
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005803 def AccessPrivateStaticThroughClassName(): number
5804 assert_equal(1, A._svar)
5805 return 444
5806 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005807 endclass
5808
5809 var oa = A.new()
5810 var ob = B.new()
5811 var oc = C.new()
5812 assert_equal(101, oa.AccessObject())
5813 assert_equal(102, ob.AccessObject())
5814 assert_equal(103, oc.AccessObject())
5815
Ernie Rael03042a22023-11-11 08:53:32 +01005816 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005817
5818 # verify object properly resolves to correct static
5819 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005820 assert_equal(1, ob.AccessStaticThroughObject())
5821 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005822 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005823 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005824enddef
5825
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005826" Test for declaring duplicate object and class members
5827def Test_dup_member_variable()
5828 # Duplicate member variable
5829 var lines =<< trim END
5830 vim9script
5831 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005832 var val = 10
5833 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005834 endclass
5835 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005836 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005837
Ernie Rael03042a22023-11-11 08:53:32 +01005838 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005839 lines =<< trim END
5840 vim9script
5841 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005842 var _val = 10
5843 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005844 endclass
5845 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005846 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005847
5848 # Duplicate public member variable
5849 lines =<< trim END
5850 vim9script
5851 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005852 public var val = 10
5853 public var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005854 endclass
5855 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005856 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005857
Ernie Rael03042a22023-11-11 08:53:32 +01005858 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005859 lines =<< trim END
5860 vim9script
5861 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005862 var val = 10
5863 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005864 endclass
5865 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005866 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005867
Ernie Rael03042a22023-11-11 08:53:32 +01005868 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005869 lines =<< trim END
5870 vim9script
5871 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005872 var _val = 20
5873 public var val = 10
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005874 endclass
5875 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005876 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005877
5878 # Duplicate class member variable
5879 lines =<< trim END
5880 vim9script
5881 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005882 static var s: string = "abc"
5883 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005884 endclass
5885 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005886 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005887
Ernie Rael03042a22023-11-11 08:53:32 +01005888 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005889 lines =<< trim END
5890 vim9script
5891 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005892 public static var s: string = "abc"
5893 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005894 endclass
5895 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005896 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005897
5898 # Duplicate class and object member variable
5899 lines =<< trim END
5900 vim9script
5901 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005902 static var val = 10
5903 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005904 def new()
5905 enddef
5906 endclass
5907 var c = C.new()
5908 assert_equal(10, C.val)
5909 assert_equal(20, c.val)
5910 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005911 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005912
5913 # Duplicate object member variable in a derived class
5914 lines =<< trim END
5915 vim9script
5916 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005917 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005918 endclass
5919 class B extends A
5920 endclass
5921 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005922 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005923 endclass
5924 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005925 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005926
Ernie Rael03042a22023-11-11 08:53:32 +01005927 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005928 lines =<< trim END
5929 vim9script
5930 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005931 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005932 endclass
5933 class B extends A
5934 endclass
5935 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005936 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005937 endclass
5938 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005939 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005940
Ernie Rael03042a22023-11-11 08:53:32 +01005941 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005942 lines =<< trim END
5943 vim9script
5944 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005945 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005946 endclass
5947 class B extends A
5948 endclass
5949 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005950 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005951 endclass
5952 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005953 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005954
5955 # Duplicate object member variable in a derived class
5956 lines =<< trim END
5957 vim9script
5958 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005959 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005960 endclass
5961 class B extends A
5962 endclass
5963 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005964 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005965 endclass
5966 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005967 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005968
5969 # Two member variables with a common prefix
5970 lines =<< trim END
5971 vim9script
5972 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005973 public static var svar2: number
5974 public static var svar: number
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005975 endclass
5976 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005977 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005978enddef
5979
Ernie Rael03042a22023-11-11 08:53:32 +01005980" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005981def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01005982 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005983 var lines =<< trim END
5984 vim9script
5985 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005986 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005987 def GetVal(): number
5988 return this._val
5989 enddef
5990 endclass
5991 def T()
5992 var a = A.new()
5993 a._val = 20
5994 enddef
5995 T()
5996 END
Ernie Rael03042a22023-11-11 08:53:32 +01005997 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005998
Ernie Rael03042a22023-11-11 08:53:32 +01005999 # access a non-existing protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006000 lines =<< trim END
6001 vim9script
6002 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006003 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006004 endclass
6005 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006006 var a = A.new()
6007 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006008 enddef
6009 T()
6010 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02006011 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02006012
Ernie Rael03042a22023-11-11 08:53:32 +01006013 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02006014 lines =<< trim END
6015 vim9script
6016 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006017 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006018 endclass
6019 def T()
6020 var a = A.new()
6021 var x = a._val
6022 enddef
6023 T()
6024 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006025 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02006026
Ernie Rael03042a22023-11-11 08:53:32 +01006027 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02006028 lines =<< trim END
6029 vim9script
6030 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006031 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006032 endclass
6033 def T()
6034 var a = A.new()
6035 a._val = 3
6036 enddef
6037 T()
6038 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006039 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02006040
Ernie Rael03042a22023-11-11 08:53:32 +01006041 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02006042 lines =<< trim END
6043 vim9script
6044 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006045 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006046 endclass
6047 def T()
6048 var x = A._val
6049 enddef
6050 T()
6051 END
Ernie Rael03042a22023-11-11 08:53:32 +01006052 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02006053
Ernie Rael03042a22023-11-11 08:53:32 +01006054 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02006055 lines =<< trim END
6056 vim9script
6057 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006058 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02006059 endclass
6060 def T()
6061 A._val = 3
6062 enddef
6063 T()
6064 END
Ernie Rael03042a22023-11-11 08:53:32 +01006065 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006066enddef
6067
6068" Test for changing the member access of an interface in a implementation class
6069def Test_change_interface_member_access()
6070 var lines =<< trim END
6071 vim9script
6072 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006073 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006074 endinterface
6075 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006076 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006077 endclass
6078 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006079 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006080
6081 lines =<< trim END
6082 vim9script
6083 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006084 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006085 endinterface
6086 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006087 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006088 endclass
6089 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006090 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006091enddef
6092
6093" Test for trying to change a readonly member from a def function
6094def Test_readonly_member_change_in_def_func()
6095 var lines =<< trim END
6096 vim9script
6097 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006098 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02006099 endclass
6100 def T()
6101 var a = A.new()
6102 a.val = 20
6103 enddef
6104 T()
6105 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006106 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02006107enddef
6108
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006109" Test for reading and writing a class member from a def function
6110def Test_modify_class_member_from_def_function()
6111 var lines =<< trim END
6112 vim9script
6113 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006114 var var1: number = 10
6115 public static var var2: list<number> = [1, 2]
6116 public static var var3: dict<number> = {a: 1, b: 2}
6117 static var _priv_var4: number = 40
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006118 endclass
6119 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02006120 assert_equal([1, 2], A.var2)
6121 assert_equal({a: 1, b: 2}, A.var3)
6122 A.var2 = [3, 4]
6123 A.var3 = {c: 3, d: 4}
6124 assert_equal([3, 4], A.var2)
6125 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael03042a22023-11-11 08:53:32 +01006126 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006127 enddef
6128 T()
6129 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006130 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02006131enddef
6132
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006133" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006134def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006135 var lines =<< trim END
6136 vim9script
6137 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006138 public static var svar1: list<number> = [1]
6139 public static var svar2: list<number> = [2]
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006140 endclass
6141
6142 A.svar1->add(3)
6143 A.svar2->add(4)
6144 assert_equal([1, 3], A.svar1)
6145 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006146
6147 def Foo()
6148 A.svar1->add(7)
6149 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006150 assert_equal([1, 3, 7], A.svar1)
6151 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006152 enddef
6153 Foo()
6154 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006155 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006156
6157 # Cannot read from a class variable using an object in script context
6158 lines =<< trim END
6159 vim9script
6160 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006161 public var var1: number
6162 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006163 endclass
6164
6165 var a = A.new()
6166 echo a.svar2
6167 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006168 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006169
6170 # Cannot write to a class variable using an object in script context
6171 lines =<< trim END
6172 vim9script
6173 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006174 public var var1: number
6175 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006176 endclass
6177
6178 var a = A.new()
6179 a.svar2 = [2]
6180 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006181 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006182
6183 # Cannot read from a class variable using an object in def method context
6184 lines =<< trim END
6185 vim9script
6186 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006187 public var var1: number
6188 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006189 endclass
6190
6191 def T()
6192 var a = A.new()
6193 echo a.svar2
6194 enddef
6195 T()
6196 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006197 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006198
6199 # Cannot write to a class variable using an object in def method context
6200 lines =<< trim END
6201 vim9script
6202 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006203 public var var1: number
6204 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006205 endclass
6206
6207 def T()
6208 var a = A.new()
6209 a.svar2 = [2]
6210 enddef
6211 T()
6212 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006213 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006214enddef
6215
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006216" Test for using a interface method using a child object
6217def Test_interface_method_from_child()
6218 var lines =<< trim END
6219 vim9script
6220
6221 interface A
6222 def Foo(): string
6223 endinterface
6224
6225 class B implements A
6226 def Foo(): string
6227 return 'foo'
6228 enddef
6229 endclass
6230
6231 class C extends B
6232 def Bar(): string
6233 return 'bar'
6234 enddef
6235 endclass
6236
6237 def T1(a: A)
6238 assert_equal('foo', a.Foo())
6239 enddef
6240
6241 def T2(b: B)
6242 assert_equal('foo', b.Foo())
6243 enddef
6244
6245 var c = C.new()
6246 T1(c)
6247 T2(c)
6248 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006249 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006250enddef
6251
6252" Test for using an interface method using a child object when it is overridden
6253" by the child class.
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01006254def Test_interface_overridden_method_from_child()
6255 var lines =<< trim END
6256 vim9script
6257
6258 interface A
6259 def Foo(): string
6260 endinterface
6261
6262 class B implements A
6263 def Foo(): string
6264 return 'b-foo'
6265 enddef
6266 endclass
6267
6268 class C extends B
6269 def Bar(): string
6270 return 'bar'
6271 enddef
6272 def Foo(): string
6273 return 'c-foo'
6274 enddef
6275 endclass
6276
6277 def T1(a: A)
6278 assert_equal('c-foo', a.Foo())
6279 enddef
6280
6281 def T2(b: B)
6282 assert_equal('c-foo', b.Foo())
6283 enddef
6284
6285 var c = C.new()
6286 T1(c)
6287 T2(c)
6288 END
6289 v9.CheckSourceSuccess(lines)
6290enddef
6291
6292" Test for interface inheritance
6293def Test_interface_inheritance()
6294 var lines =<< trim END
6295 vim9script
6296
6297 interface A
6298 def A_Fn(): string
6299 endinterface
6300
6301 interface B
6302 def B_Fn(): string
6303 endinterface
6304
6305 interface C
6306 def C_Fn(): string
6307 endinterface
6308
6309 class C1 implements A
6310 def A_Fn(): string
6311 return 'c1-a'
6312 enddef
6313 endclass
6314
6315 class C2 extends C1 implements B
6316 def B_Fn(): string
6317 return 'c2-b'
6318 enddef
6319 def A_Fn(): string
6320 return 'c2-a'
6321 enddef
6322 endclass
6323
6324 class C3 extends C2 implements C
6325 def C_Fn(): string
6326 return 'c3-c'
6327 enddef
6328 def A_Fn(): string
6329 return 'c3-a'
6330 enddef
6331 def B_Fn(): string
6332 return 'c3-b'
6333 enddef
6334 endclass
6335
6336 def T1(a: A, s: string)
6337 assert_equal(s, a.A_Fn())
6338 enddef
6339
6340 def T2(b: B, s: string)
6341 assert_equal(s, b.B_Fn())
6342 enddef
6343
6344 def T3(c: C, s: string)
6345 assert_equal(s, c.C_Fn())
6346 enddef
6347
6348 def T4(c1: C1)
6349 T1(c1, 'c3-a')
6350 enddef
6351
6352 def T5(c2: C2)
6353 T1(c2, 'c3-a')
6354 T2(c2, 'c3-b')
6355 enddef
6356
6357 def T6(c3: C3)
6358 T1(c3, 'c3-a')
6359 T2(c3, 'c3-b')
6360 T3(c3, 'c3-c')
6361 enddef
6362
6363 var o3 = C3.new()
6364 T4(o3)
6365 T5(o3)
6366 T6(o3)
6367 END
6368 v9.CheckSourceSuccess(lines)
6369
6370 # Both the parent and child classes implement the same interface
6371 lines =<< trim END
6372 vim9script
6373
6374 interface I
6375 def Foo(): string
6376 endinterface
6377
6378 class A implements I
6379 def Foo(): string
6380 return 'A-foo'
6381 enddef
6382 endclass
6383
6384 class B implements I
6385 def Foo(): string
6386 return 'B-foo'
6387 enddef
6388 endclass
6389
6390 def Bar(i1: I): string
6391 return i1.Foo()
6392 enddef
6393
6394 var b = B.new()
6395 assert_equal('B-foo', Bar(b))
6396 END
6397 v9.CheckSourceSuccess(lines)
6398enddef
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006399
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006400" Test for abstract methods
6401def Test_abstract_method()
6402 # Use two abstract methods
6403 var lines =<< trim END
6404 vim9script
6405 abstract class A
6406 def M1(): number
6407 return 10
6408 enddef
6409 abstract def M2(): number
6410 abstract def M3(): number
6411 endclass
6412 class B extends A
6413 def M2(): number
6414 return 20
6415 enddef
6416 def M3(): number
6417 return 30
6418 enddef
6419 endclass
6420 var b = B.new()
6421 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6422 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006423 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006424
6425 # Don't define an abstract method
6426 lines =<< trim END
6427 vim9script
6428 abstract class A
6429 abstract def Foo()
6430 endclass
6431 class B extends A
6432 endclass
6433 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006434 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006435
6436 # Use abstract method in a concrete class
6437 lines =<< trim END
6438 vim9script
6439 class A
6440 abstract def Foo()
6441 endclass
6442 class B extends A
6443 endclass
6444 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006445 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006446
6447 # Use abstract method in an interface
6448 lines =<< trim END
6449 vim9script
6450 interface A
6451 abstract def Foo()
6452 endinterface
6453 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006454 def Foo()
6455 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006456 endclass
6457 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006458 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6459
6460 # Use abstract static method in an interface
6461 lines =<< trim END
6462 vim9script
6463 interface A
6464 abstract static def Foo()
6465 enddef
6466 endinterface
6467 END
6468 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6469
6470 # Use abstract static variable in an interface
6471 lines =<< trim END
6472 vim9script
6473 interface A
6474 abstract static foo: number = 10
6475 endinterface
6476 END
6477 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006478
6479 # Abbreviate the "abstract" keyword
6480 lines =<< trim END
6481 vim9script
6482 class A
6483 abs def Foo()
6484 endclass
6485 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006486 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006487
6488 # Use "abstract" with a member variable
6489 lines =<< trim END
6490 vim9script
6491 abstract class A
6492 abstract this.val = 10
6493 endclass
6494 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006495 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006496
6497 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006498 lines =<< trim END
6499 vim9script
6500 abstract class A
6501 abstract static def Foo(): number
6502 endclass
6503 END
6504 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006505
6506 # Type mismatch between abstract method and concrete method
6507 lines =<< trim END
6508 vim9script
6509 abstract class A
6510 abstract def Foo(a: string, b: number): list<number>
6511 endclass
6512 class B extends A
6513 def Foo(a: number, b: string): list<string>
6514 return []
6515 enddef
6516 endclass
6517 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006518 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 +02006519
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006520 # Invoke an abstract method from a def function
6521 lines =<< trim END
6522 vim9script
6523 abstract class A
6524 abstract def Foo(): list<number>
6525 endclass
6526 class B extends A
6527 def Foo(): list<number>
6528 return [3, 5]
6529 enddef
6530 endclass
6531 def Bar(c: B)
6532 assert_equal([3, 5], c.Foo())
6533 enddef
6534 var b = B.new()
6535 Bar(b)
6536 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006537 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006538
6539 # Use a static method in an abstract class
6540 lines =<< trim END
6541 vim9script
6542 abstract class A
6543 static def Foo(): string
6544 return 'foo'
6545 enddef
6546 endclass
6547 assert_equal('foo', A.Foo())
6548 END
6549 v9.CheckSourceSuccess(lines)
Ernie Rael7c92e882025-01-18 17:26:39 +01006550
6551 # Invoke method returning a value through the abstract class. See #15432.
6552 lines =<< trim END
6553 vim9script
6554
6555 abstract class A
6556 abstract def String(): string
6557 endclass
6558
6559 class B extends A
6560 def String(): string
6561 return 'B'
6562 enddef
6563 endclass
6564
6565 def F(o: A)
6566 assert_equal('B', o.String())
6567 enddef
6568 F(B.new())
6569 END
6570 v9.CheckSourceSuccess(lines)
6571
6572 # Invoke abstract method returning a value does not compile
6573 lines =<< trim END
6574 vim9script
6575
6576 abstract class A
6577 abstract def String(): string
6578 return 'X'
6579 enddef
6580 endclass
6581 END
6582 v9.CheckScriptFailure(lines, "E1318: Not a valid command in a class: return 'X'")
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006583enddef
6584
6585" Test for calling a class method from a subclass
6586def Test_class_method_call_from_subclass()
6587 # class method call from a subclass
6588 var lines =<< trim END
6589 vim9script
6590
6591 class A
6592 static def Foo()
6593 echo "foo"
6594 enddef
6595 endclass
6596
6597 class B extends A
6598 def Bar()
6599 Foo()
6600 enddef
6601 endclass
6602
6603 var b = B.new()
6604 b.Bar()
6605 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006606 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006607enddef
6608
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006609" Test for calling a class method using an object in a def function context and
6610" script context.
6611def Test_class_method_call_using_object()
6612 # script context
6613 var lines =<< trim END
6614 vim9script
6615 class A
6616 static def Foo(): list<string>
6617 return ['a', 'b']
6618 enddef
6619 def Bar()
6620 assert_equal(['a', 'b'], A.Foo())
6621 assert_equal(['a', 'b'], Foo())
6622 enddef
6623 endclass
6624
6625 def T()
6626 assert_equal(['a', 'b'], A.Foo())
6627 var t_a = A.new()
6628 t_a.Bar()
6629 enddef
6630
6631 assert_equal(['a', 'b'], A.Foo())
6632 var a = A.new()
6633 a.Bar()
6634 T()
6635 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006636 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006637
6638 # script context
6639 lines =<< trim END
6640 vim9script
6641 class A
6642 static def Foo(): string
6643 return 'foo'
6644 enddef
6645 endclass
6646
6647 var a = A.new()
6648 assert_equal('foo', a.Foo())
6649 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006650 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006651
6652 # def function context
6653 lines =<< trim END
6654 vim9script
6655 class A
6656 static def Foo(): string
6657 return 'foo'
6658 enddef
6659 endclass
6660
6661 def T()
6662 var a = A.new()
6663 assert_equal('foo', a.Foo())
6664 enddef
6665 T()
6666 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006667 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006668enddef
6669
6670def Test_class_variable()
6671 var lines =<< trim END
6672 vim9script
6673
6674 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006675 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006676 static def ClassFunc()
6677 assert_equal(10, val)
6678 enddef
6679 def ObjFunc()
6680 assert_equal(10, val)
6681 enddef
6682 endclass
6683
6684 class B extends A
6685 endclass
6686
6687 assert_equal(10, A.val)
6688 A.ClassFunc()
6689 var a = A.new()
6690 a.ObjFunc()
6691 var b = B.new()
6692 b.ObjFunc()
6693
6694 def T1(a1: A)
6695 a1.ObjFunc()
6696 A.ClassFunc()
6697 enddef
6698 T1(b)
6699
6700 A.val = 20
6701 assert_equal(20, A.val)
6702 END
6703 v9.CheckSourceSuccess(lines)
6704
6705 # Modifying a parent class variable from a child class method
6706 lines =<< trim END
6707 vim9script
6708
6709 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006710 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006711 endclass
6712
6713 class B extends A
6714 static def ClassFunc()
6715 val = 20
6716 enddef
6717 endclass
6718 B.ClassFunc()
6719 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006720 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006721
6722 # Reading a parent class variable from a child class method
6723 lines =<< trim END
6724 vim9script
6725
6726 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006727 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006728 endclass
6729
6730 class B extends A
6731 static def ClassFunc()
6732 var i = val
6733 enddef
6734 endclass
6735 B.ClassFunc()
6736 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006737 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006738
6739 # Modifying a parent class variable from a child object method
6740 lines =<< trim END
6741 vim9script
6742
6743 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006744 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006745 endclass
6746
6747 class B extends A
6748 def ObjFunc()
6749 val = 20
6750 enddef
6751 endclass
6752 var b = B.new()
6753 b.ObjFunc()
6754 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006755 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006756
6757 # Reading a parent class variable from a child object method
6758 lines =<< trim END
6759 vim9script
6760
6761 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006762 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006763 endclass
6764
6765 class B extends A
6766 def ObjFunc()
6767 var i = val
6768 enddef
6769 endclass
6770 var b = B.new()
6771 b.ObjFunc()
6772 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006773 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006774
6775 # Modifying a class variable using an object at script level
6776 lines =<< trim END
6777 vim9script
6778
6779 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006780 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006781 endclass
6782 var a = A.new()
6783 a.val = 20
6784 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006785 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006786
6787 # Reading a class variable using an object at script level
6788 lines =<< trim END
6789 vim9script
6790
6791 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006792 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006793 endclass
6794 var a = A.new()
6795 var i = a.val
6796 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006797 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006798
6799 # Modifying a class variable using an object at function level
6800 lines =<< trim END
6801 vim9script
6802
6803 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006804 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006805 endclass
6806
6807 def T()
6808 var a = A.new()
6809 a.val = 20
6810 enddef
6811 T()
6812 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006813 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006814
6815 # Reading a class variable using an object at function level
6816 lines =<< trim END
6817 vim9script
6818
6819 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006820 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006821 endclass
6822 def T()
6823 var a = A.new()
6824 var i = a.val
6825 enddef
6826 T()
6827 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006828 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006829
6830 # Use old implicit var declaration syntax (without initialization)
6831 lines =<< trim END
6832 vim9script
6833
6834 class A
6835 static val: number
6836 endclass
6837 END
6838 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6839
6840 # Use old implicit var declaration syntax (with initialization)
6841 lines =<< trim END
6842 vim9script
6843
6844 class A
6845 static val: number = 10
6846 endclass
6847 END
6848 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6849
6850 # Use old implicit var declaration syntax (type inferred)
6851 lines =<< trim END
6852 vim9script
6853
6854 class A
6855 static val = 10
6856 endclass
6857 END
6858 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6859
6860 # Missing ":var" in "var" class variable declaration (without initialization)
6861 lines =<< trim END
6862 vim9script
6863
6864 class A
6865 static var: number
6866 endclass
6867 END
6868 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6869
6870 # Missing ":var" in "var" class variable declaration (with initialization)
6871 lines =<< trim END
6872 vim9script
6873
6874 class A
6875 static var: number = 10
6876 endclass
6877 END
6878 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6879
6880 # Missing ":var" in "var" class variable declaration (type inferred)
6881 lines =<< trim END
6882 vim9script
6883
6884 class A
6885 static var = 10
6886 endclass
6887 END
6888 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6889
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006890enddef
6891
6892" Test for using a duplicate class method and class variable in a child class
6893def Test_dup_class_member()
6894 # duplicate class variable, class method and overridden object method
6895 var lines =<< trim END
6896 vim9script
6897 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006898 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006899 static def Check()
6900 assert_equal(100, sval)
6901 enddef
6902 def GetVal(): number
6903 return sval
6904 enddef
6905 endclass
6906
6907 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006908 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006909 static def Check()
6910 assert_equal(200, sval)
6911 enddef
6912 def GetVal(): number
6913 return sval
6914 enddef
6915 endclass
6916
6917 def T1(aa: A): number
6918 return aa.GetVal()
6919 enddef
6920
6921 def T2(bb: B): number
6922 return bb.GetVal()
6923 enddef
6924
6925 assert_equal(100, A.sval)
6926 assert_equal(200, B.sval)
6927 var a = A.new()
6928 assert_equal(100, a.GetVal())
6929 var b = B.new()
6930 assert_equal(200, b.GetVal())
6931 assert_equal(200, T1(b))
6932 assert_equal(200, T2(b))
6933 END
6934 v9.CheckSourceSuccess(lines)
6935
6936 # duplicate class variable and class method
6937 lines =<< trim END
6938 vim9script
6939 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006940 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006941 static def Check()
6942 assert_equal(100, sval)
6943 enddef
6944 def GetVal(): number
6945 return sval
6946 enddef
6947 endclass
6948
6949 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006950 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006951 static def Check()
6952 assert_equal(200, sval)
6953 enddef
6954 endclass
6955
6956 def T1(aa: A): number
6957 return aa.GetVal()
6958 enddef
6959
6960 def T2(bb: B): number
6961 return bb.GetVal()
6962 enddef
6963
6964 assert_equal(100, A.sval)
6965 assert_equal(200, B.sval)
6966 var a = A.new()
6967 assert_equal(100, a.GetVal())
6968 var b = B.new()
6969 assert_equal(100, b.GetVal())
6970 assert_equal(100, T1(b))
6971 assert_equal(100, T2(b))
6972 END
6973 v9.CheckSourceSuccess(lines)
6974enddef
6975
6976" Test for calling an instance method using the class
6977def Test_instance_method_call_using_class()
6978 # Invoke an object method using a class in script context
6979 var lines =<< trim END
6980 vim9script
6981 class A
6982 def Foo()
6983 echo "foo"
6984 enddef
6985 endclass
6986 A.Foo()
6987 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006988 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006989
6990 # Invoke an object method using a class in def function context
6991 lines =<< trim END
6992 vim9script
6993 class A
6994 def Foo()
6995 echo "foo"
6996 enddef
6997 endclass
6998 def T()
6999 A.Foo()
7000 enddef
7001 T()
7002 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007003 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007004enddef
7005
7006" Test for duplicate class method and instance method
7007def Test_dup_classmethod_objmethod()
7008 # Duplicate instance method
7009 var lines =<< trim END
7010 vim9script
7011 class A
7012 static def Foo()
7013 enddef
7014 def Foo()
7015 enddef
7016 endclass
7017 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007018 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007019
Ernie Rael03042a22023-11-11 08:53:32 +01007020 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007021 lines =<< trim END
7022 vim9script
7023 class A
7024 static def Foo()
7025 enddef
7026 def _Foo()
7027 enddef
7028 endclass
7029 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007030 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007031
7032 # Duplicate class method
7033 lines =<< trim END
7034 vim9script
7035 class A
7036 def Foo()
7037 enddef
7038 static def Foo()
7039 enddef
7040 endclass
7041 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007042 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007043
Ernie Rael03042a22023-11-11 08:53:32 +01007044 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007045 lines =<< trim END
7046 vim9script
7047 class A
7048 def Foo()
7049 enddef
7050 static def _Foo()
7051 enddef
7052 endclass
7053 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007054 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007055
Ernie Rael03042a22023-11-11 08:53:32 +01007056 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007057 lines =<< trim END
7058 vim9script
7059 class A
7060 def _Foo()
7061 enddef
7062 static def _Foo()
7063 enddef
7064 endclass
7065 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007066 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007067enddef
7068
7069" Test for an instance method access level comparison with parent instance
7070" methods.
7071def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01007072 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007073 var lines =<< trim END
7074 vim9script
7075 class A
7076 def Foo()
7077 enddef
7078 endclass
7079 class B extends A
7080 endclass
7081 class C extends B
7082 def _Foo()
7083 enddef
7084 endclass
7085 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007086 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007087
7088 # Public method in subclass
7089 lines =<< trim END
7090 vim9script
7091 class A
7092 def _Foo()
7093 enddef
7094 endclass
7095 class B extends A
7096 endclass
7097 class C extends B
7098 def Foo()
7099 enddef
7100 endclass
7101 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007102 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007103enddef
7104
7105def Test_extend_empty_class()
7106 var lines =<< trim END
7107 vim9script
7108 class A
7109 endclass
7110 class B extends A
7111 endclass
7112 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007113 public static var rw_class_var = 1
7114 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02007115 static def ClassMethod(): number
7116 return 3
7117 enddef
7118 def ObjMethod(): number
7119 return 4
7120 enddef
7121 endclass
7122 assert_equal(1, C.rw_class_var)
7123 assert_equal(3, C.ClassMethod())
7124 var c = C.new()
7125 assert_equal(2, c.rw_obj_var)
7126 assert_equal(4, c.ObjMethod())
7127 END
7128 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02007129enddef
7130
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007131" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01007132" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007133def Test_interface_with_unsupported_members()
7134 var lines =<< trim END
7135 vim9script
7136 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007137 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007138 endinterface
7139 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007140 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007141
7142 lines =<< trim END
7143 vim9script
7144 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007145 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007146 endinterface
7147 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007148 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007149
7150 lines =<< trim END
7151 vim9script
7152 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007153 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007154 endinterface
7155 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007156 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007157
7158 lines =<< trim END
7159 vim9script
7160 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007161 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007162 endinterface
7163 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02007164 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02007165
7166 lines =<< trim END
7167 vim9script
7168 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007169 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007170 endinterface
7171 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007172 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007173
7174 lines =<< trim END
7175 vim9script
7176 interface A
7177 static def Foo(d: dict<any>): list<string>
7178 endinterface
7179 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007180 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007181
7182 lines =<< trim END
7183 vim9script
7184 interface A
7185 static def _Foo(d: dict<any>): list<string>
7186 endinterface
7187 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007188 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007189
7190 lines =<< trim END
7191 vim9script
7192 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007193 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007194 endinterface
7195 END
Ernie Rael03042a22023-11-11 08:53:32 +01007196 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007197
7198 lines =<< trim END
7199 vim9script
7200 interface A
7201 def _Foo(d: dict<any>): list<string>
7202 endinterface
7203 END
Ernie Rael03042a22023-11-11 08:53:32 +01007204 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007205enddef
7206
7207" Test for extending an interface
7208def Test_extend_interface()
7209 var lines =<< trim END
7210 vim9script
7211 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007212 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007213 def Foo()
7214 endinterface
7215 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007216 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007217 def Bar()
7218 endinterface
7219 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007220 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007221 def Foo()
7222 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007223 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007224 def Bar()
7225 enddef
7226 endclass
7227 END
7228 v9.CheckSourceSuccess(lines)
7229
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007230 # extending empty interface
7231 lines =<< trim END
7232 vim9script
7233 interface A
7234 endinterface
7235 interface B extends A
7236 endinterface
7237 class C implements B
7238 endclass
7239 END
7240 v9.CheckSourceSuccess(lines)
7241
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007242 lines =<< trim END
7243 vim9script
7244 interface A
7245 def Foo()
7246 endinterface
7247 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007248 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007249 endinterface
7250 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007251 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007252 endclass
7253 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007254 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007255
7256 lines =<< trim END
7257 vim9script
7258 interface A
7259 def Foo()
7260 endinterface
7261 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007262 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007263 endinterface
7264 class C implements A, B
7265 def Foo()
7266 enddef
7267 endclass
7268 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007269 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007270
7271 # interface cannot extend a class
7272 lines =<< trim END
7273 vim9script
7274 class A
7275 endclass
7276 interface B extends A
7277 endinterface
7278 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007279 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007280
7281 # class cannot extend an interface
7282 lines =<< trim END
7283 vim9script
7284 interface A
7285 endinterface
7286 class B extends A
7287 endclass
7288 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007289 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007290
7291 # interface cannot implement another interface
7292 lines =<< trim END
7293 vim9script
7294 interface A
7295 endinterface
7296 interface B implements A
7297 endinterface
7298 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007299 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007300
7301 # interface cannot extend multiple interfaces
7302 lines =<< trim END
7303 vim9script
7304 interface A
7305 endinterface
7306 interface B
7307 endinterface
7308 interface C extends A, B
7309 endinterface
7310 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007311 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007312
7313 # Variable type in an extended interface is of different type
7314 lines =<< trim END
7315 vim9script
7316 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007317 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007318 endinterface
7319 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007320 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007321 endinterface
7322 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007323 var val1: string
7324 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007325 endinterface
7326 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007327 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007328enddef
7329
7330" Test for a child class implementing an interface when some of the methods are
7331" defined in the parent class.
7332def Test_child_class_implements_interface()
7333 var lines =<< trim END
7334 vim9script
7335
7336 interface Intf
7337 def F1(): list<list<number>>
7338 def F2(): list<list<number>>
7339 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007340 var var1: list<dict<number>>
7341 var var2: list<dict<number>>
7342 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007343 endinterface
7344
7345 class A
7346 def A1()
7347 enddef
7348 def F3(): list<list<number>>
7349 return [[3]]
7350 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007351 var v1: list<list<number>> = [[0]]
7352 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007353 endclass
7354
7355 class B extends A
7356 def B1()
7357 enddef
7358 def F2(): list<list<number>>
7359 return [[2]]
7360 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007361 var v2: list<list<number>> = [[0]]
7362 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007363 endclass
7364
7365 class C extends B implements Intf
7366 def C1()
7367 enddef
7368 def F1(): list<list<number>>
7369 return [[1]]
7370 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007371 var v3: list<list<number>> = [[0]]
7372 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007373 endclass
7374
7375 def T(if: Intf)
7376 assert_equal([[1]], if.F1())
7377 assert_equal([[2]], if.F2())
7378 assert_equal([[3]], if.F3())
7379 assert_equal([{a: 10}], if.var1)
7380 assert_equal([{b: 20}], if.var2)
7381 assert_equal([{c: 30}], if.var3)
7382 enddef
7383
7384 var c = C.new()
7385 T(c)
7386 assert_equal([[1]], c.F1())
7387 assert_equal([[2]], c.F2())
7388 assert_equal([[3]], c.F3())
7389 assert_equal([{a: 10}], c.var1)
7390 assert_equal([{b: 20}], c.var2)
7391 assert_equal([{c: 30}], c.var3)
7392 END
7393 v9.CheckSourceSuccess(lines)
7394
7395 # One of the interface methods is not found
7396 lines =<< trim END
7397 vim9script
7398
7399 interface Intf
7400 def F1()
7401 def F2()
7402 def F3()
7403 endinterface
7404
7405 class A
7406 def A1()
7407 enddef
7408 endclass
7409
7410 class B extends A
7411 def B1()
7412 enddef
7413 def F2()
7414 enddef
7415 endclass
7416
7417 class C extends B implements Intf
7418 def C1()
7419 enddef
7420 def F1()
7421 enddef
7422 endclass
7423 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007424 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007425
7426 # One of the interface methods is of different type
7427 lines =<< trim END
7428 vim9script
7429
7430 interface Intf
7431 def F1()
7432 def F2()
7433 def F3()
7434 endinterface
7435
7436 class A
7437 def F3(): number
7438 return 0
7439 enddef
7440 def A1()
7441 enddef
7442 endclass
7443
7444 class B extends A
7445 def B1()
7446 enddef
7447 def F2()
7448 enddef
7449 endclass
7450
7451 class C extends B implements Intf
7452 def C1()
7453 enddef
7454 def F1()
7455 enddef
7456 endclass
7457 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007458 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007459
7460 # One of the interface variables is not present
7461 lines =<< trim END
7462 vim9script
7463
7464 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007465 var var1: list<dict<number>>
7466 var var2: list<dict<number>>
7467 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007468 endinterface
7469
7470 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007471 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007472 endclass
7473
7474 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007475 var v2: list<list<number>> = [[0]]
7476 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007477 endclass
7478
7479 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007480 var v3: list<list<number>> = [[0]]
7481 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007482 endclass
7483 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007484 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007485
7486 # One of the interface variables is of different type
7487 lines =<< trim END
7488 vim9script
7489
7490 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007491 var var1: list<dict<number>>
7492 var var2: list<dict<number>>
7493 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007494 endinterface
7495
7496 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007497 var v1: list<list<number>> = [[0]]
7498 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007499 endclass
7500
7501 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007502 var v2: list<list<number>> = [[0]]
7503 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007504 endclass
7505
7506 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007507 var v3: list<list<number>> = [[0]]
7508 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007509 endclass
7510 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007511 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 +02007512enddef
7513
7514" Test for extending an interface with duplicate variables and methods
7515def Test_interface_extends_with_dup_members()
7516 var lines =<< trim END
7517 vim9script
7518 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007519 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007520 def Foo1(): number
7521 endinterface
7522 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007523 var n2: number
7524 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007525 def Foo2(): number
7526 def Foo1(): number
7527 endinterface
7528 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007529 var n1 = 10
7530 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007531 def Foo1(): number
7532 return 30
7533 enddef
7534 def Foo2(): number
7535 return 40
7536 enddef
7537 endclass
7538 def T1(a: A)
7539 assert_equal(10, a.n1)
7540 assert_equal(30, a.Foo1())
7541 enddef
7542 def T2(b: B)
7543 assert_equal(10, b.n1)
7544 assert_equal(20, b.n2)
7545 assert_equal(30, b.Foo1())
7546 assert_equal(40, b.Foo2())
7547 enddef
7548 var c = C.new()
7549 T1(c)
7550 T2(c)
7551 END
7552 v9.CheckSourceSuccess(lines)
7553enddef
7554
Yegappan Lakshmananc10342d2025-01-11 09:39:01 +01007555" Test for implementing an interface with different ordering for the interface
7556" member variables.
7557def Test_implement_interface_with_different_variable_order()
7558 var lines =<< trim END
7559 vim9script
7560
7561 interface IX
7562 var F: func(): string
7563 endinterface
7564
7565 class X implements IX
7566 var x: number
7567 var F: func(): string = () => 'ok'
7568 endclass
7569
7570 def Foo(ix: IX): string
7571 return ix.F()
7572 enddef
7573
7574 var x0 = X.new(0)
7575 assert_equal('ok', Foo(x0))
7576 END
7577 v9.CheckSourceSuccess(lines)
7578enddef
7579
Yegappan Lakshmanan8e92db42025-01-13 07:30:11 +01007580" Test for inheriting interfaces from an imported super class
7581def Test_interface_inheritance_with_imported_super()
7582 var lines =<< trim END
7583 vim9script
7584
7585 export interface I
7586 def F(): string
7587 endinterface
7588
7589 export class A implements I
7590 def F(): string
7591 return 'A'
7592 enddef
7593 endclass
7594 END
7595 writefile(lines, 'Xinheritintfimportclass.vim', 'D')
7596
7597 lines =<< trim END
7598 vim9script
7599
7600 import './Xinheritintfimportclass.vim' as i_imp
7601
7602 # class C extends i_imp.A
7603 class C extends i_imp.A implements i_imp.I
7604 def F(): string
7605 return 'C'
7606 enddef
7607 endclass
7608
7609 def TestI(i: i_imp.I): string
7610 return i.F()
7611 enddef
7612
7613 assert_equal('C', TestI(C.new()))
7614 END
7615 v9.CheckSourceSuccess(lines)
7616enddef
7617
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007618" Test for using "any" type for a variable in a sub-class while it has a
7619" concrete type in the interface
7620def Test_implements_using_var_type_any()
7621 var lines =<< trim END
7622 vim9script
7623 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007624 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007625 endinterface
7626 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007627 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007628 endclass
7629 var b = B.new()
7630 assert_equal([{a: '1'}, {b: '2'}], b.val)
7631 END
7632 v9.CheckSourceSuccess(lines)
7633
7634 # initialize instance variable using a different type
7635 lines =<< trim END
7636 vim9script
7637 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007638 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007639 endinterface
7640 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007641 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007642 endclass
7643 var b = B.new()
7644 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007645 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007646enddef
7647
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007648" Test for assigning to a member variable in a nested class
7649def Test_nested_object_assignment()
7650 var lines =<< trim END
7651 vim9script
7652
7653 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007654 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007655 endclass
7656
7657 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007658 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007659 endclass
7660
7661 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007662 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007663 endclass
7664
7665 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007666 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007667 endclass
7668
7669 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007670 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007671 enddef
7672
7673 var d = D.new()
7674 T(d)
7675 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007676 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007677enddef
7678
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007679" Test for calling methods using a null object
7680def Test_null_object_method_call()
7681 # Calling a object method using a null object in script context
7682 var lines =<< trim END
7683 vim9script
7684
7685 class C
7686 def Foo()
7687 assert_report('This method should not be executed')
7688 enddef
7689 endclass
7690
7691 var o: C
7692 o.Foo()
7693 END
7694 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7695
7696 # Calling a object method using a null object in def function context
7697 lines =<< trim END
7698 vim9script
7699
7700 class C
7701 def Foo()
7702 assert_report('This method should not be executed')
7703 enddef
7704 endclass
7705
7706 def T()
7707 var o: C
7708 o.Foo()
7709 enddef
7710 T()
7711 END
7712 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7713
7714 # Calling a object method through another class method using a null object in
7715 # script context
7716 lines =<< trim END
7717 vim9script
7718
7719 class C
7720 def Foo()
7721 assert_report('This method should not be executed')
7722 enddef
7723
7724 static def Bar(o_any: any)
7725 var o_typed: C = o_any
7726 o_typed.Foo()
7727 enddef
7728 endclass
7729
7730 var o: C
7731 C.Bar(o)
7732 END
7733 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7734
7735 # Calling a object method through another class method using a null object in
7736 # def function context
7737 lines =<< trim END
7738 vim9script
7739
7740 class C
7741 def Foo()
7742 assert_report('This method should not be executed')
7743 enddef
7744
7745 static def Bar(o_any: any)
7746 var o_typed: C = o_any
7747 o_typed.Foo()
7748 enddef
7749 endclass
7750
7751 def T()
7752 var o: C
7753 C.Bar(o)
7754 enddef
7755 T()
7756 END
7757 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007758
7759 # Calling an object method defined in a class that is extended. This differs
7760 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7761 lines =<< trim END
7762 vim9script
7763
7764 class C0
7765 def F()
7766 enddef
7767 endclass
7768
7769 class C extends C0
7770 endclass
7771
7772 def X()
7773 var o: C0 = null_object
7774 o.F()
7775 enddef
7776 X()
7777 END
7778 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7779
7780 # Getting a function ref an object method.
7781 lines =<< trim END
7782 vim9script
7783
7784 class C0
7785 def F()
7786 enddef
7787 endclass
7788
7789 class C extends C0
7790 endclass
7791
7792 def X()
7793 var o: C0 = null_object
7794 var XXX = o.F
7795 enddef
7796 X()
7797 END
7798 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007799enddef
7800
7801" Test for using a dict as an object member
7802def Test_dict_object_member()
7803 var lines =<< trim END
7804 vim9script
7805
7806 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007807 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007808 def GetState(): dict<number>
7809 return this.state
7810 enddef
7811 endclass
7812
7813 var ctx = Context.new()
7814 ctx.state->extend({a: 1})
7815 ctx.state['b'] = 2
7816 assert_equal({a: 1, b: 2}, ctx.GetState())
7817
7818 def F()
7819 ctx.state['c'] = 3
7820 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7821 enddef
7822 F()
7823 assert_equal(3, ctx.state.c)
7824 ctx.state.c = 4
7825 assert_equal(4, ctx.state.c)
7826 END
7827 v9.CheckSourceSuccess(lines)
7828enddef
7829
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007830" The following test was failing after 9.0.1914. This was caused by using a
7831" freed object from a previous method call.
7832def Test_freed_object_from_previous_method_call()
7833 var lines =<< trim END
7834 vim9script
7835
7836 class Context
7837 endclass
7838
7839 class Result
7840 endclass
7841
7842 def Failure(): Result
7843 return Result.new()
7844 enddef
7845
7846 def GetResult(ctx: Context): Result
7847 return Failure()
7848 enddef
7849
7850 def Test_GetResult()
7851 var ctx = Context.new()
7852 var result = GetResult(ctx)
7853 enddef
7854
7855 Test_GetResult()
7856 END
7857 v9.CheckSourceSuccess(lines)
7858enddef
7859
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007860" Test for duplicate object and class variable
7861def Test_duplicate_variable()
7862 # Object variable name is same as the class variable name
7863 var lines =<< trim END
7864 vim9script
7865 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007866 public static var sval: number
7867 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007868 endclass
7869 var a = A.new()
7870 END
7871 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7872
7873 # Duplicate variable name and calling a class method
7874 lines =<< trim END
7875 vim9script
7876 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007877 public static var sval: number
7878 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007879 def F1()
7880 echo this.sval
7881 enddef
7882 static def F2()
7883 echo sval
7884 enddef
7885 endclass
7886 A.F2()
7887 END
7888 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7889
7890 # Duplicate variable with an empty constructor
7891 lines =<< trim END
7892 vim9script
7893 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007894 public static var sval: number
7895 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007896 def new()
7897 enddef
7898 endclass
7899 var a = A.new()
7900 END
7901 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7902enddef
7903
7904" Test for using a reserved keyword as a variable name
7905def Test_reserved_varname()
7906 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7907 'null_function', 'null_list', 'null_partial', 'null_string',
7908 'null_channel', 'null_job', 'super', 'this']
7909
7910 var lines =<< trim eval END
7911 vim9script
7912 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007913 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007914 endclass
7915 var o = C.new()
7916 END
7917 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7918
7919 lines =<< trim eval END
7920 vim9script
7921 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007922 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007923 def new()
7924 enddef
7925 endclass
7926 var o = C.new()
7927 END
7928 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7929
7930 lines =<< trim eval END
7931 vim9script
7932 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007933 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007934 def new()
7935 enddef
7936 def F()
7937 echo this.{kword}
7938 enddef
7939 endclass
7940 var o = C.new()
7941 o.F()
7942 END
7943 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007944
7945 # class variable name
7946 if kword != 'this'
7947 lines =<< trim eval END
7948 vim9script
7949 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007950 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007951 endclass
7952 END
7953 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7954 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007955 endfor
7956enddef
7957
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007958" Test for checking the type of the arguments and the return value of a object
7959" method in an extended class.
7960def Test_extended_obj_method_type_check()
7961 var lines =<< trim END
7962 vim9script
7963
7964 class A
7965 endclass
7966 class B extends A
7967 endclass
7968 class C extends B
7969 endclass
7970
7971 class Foo
7972 def Doit(p: B): B
7973 return B.new()
7974 enddef
7975 endclass
7976
7977 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007978 def Doit(p: C): B
7979 return B.new()
7980 enddef
7981 endclass
7982 END
7983 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
7984
7985 lines =<< trim END
7986 vim9script
7987
7988 class A
7989 endclass
7990 class B extends A
7991 endclass
7992 class C extends B
7993 endclass
7994
7995 class Foo
7996 def Doit(p: B): B
7997 return B.new()
7998 enddef
7999 endclass
8000
8001 class Bar extends Foo
8002 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02008003 return C.new()
8004 enddef
8005 endclass
8006 END
8007 v9.CheckSourceSuccess(lines)
8008
8009 lines =<< trim END
8010 vim9script
8011
8012 class A
8013 endclass
8014 class B extends A
8015 endclass
8016 class C extends B
8017 endclass
8018
8019 class Foo
8020 def Doit(p: B): B
8021 return B.new()
8022 enddef
8023 endclass
8024
8025 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02008026 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02008027 return B.new()
8028 enddef
8029 endclass
8030 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02008031 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 +02008032
8033 lines =<< trim END
8034 vim9script
8035
8036 class A
8037 endclass
8038 class B extends A
8039 endclass
8040 class C extends B
8041 endclass
8042
8043 class Foo
8044 def Doit(p: B): B
8045 return B.new()
8046 enddef
8047 endclass
8048
8049 class Bar extends Foo
8050 def Doit(p: B): A
8051 return A.new()
8052 enddef
8053 endclass
8054 END
8055 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 +02008056
8057 # check varargs type mismatch
8058 lines =<< trim END
8059 vim9script
8060
8061 class B
8062 def F(...xxx: list<any>)
8063 enddef
8064 endclass
8065 class C extends B
8066 def F(xxx: list<any>)
8067 enddef
8068 endclass
8069 END
8070 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 +02008071enddef
8072
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008073" Test type checking for class variable in assignments
8074func Test_class_variable_complex_type_check()
8075 " class variable with a specific type. Try assigning a different type at
8076 " script level.
8077 let lines =<< trim END
8078 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008079 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008080 return {}
8081 enddef
8082 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008083 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008084 endclass
8085 test_garbagecollect_now()
8086 A.Fn = "abc"
8087 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008088 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 +02008089
8090 " class variable with a specific type. Try assigning a different type at
8091 " class def method level.
8092 let lines =<< trim END
8093 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008094 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008095 return {}
8096 enddef
8097 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008098 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008099 def Bar()
8100 Fn = "abc"
8101 enddef
8102 endclass
8103 var a = A.new()
8104 test_garbagecollect_now()
8105 a.Bar()
8106 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008107 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 +02008108
8109 " class variable with a specific type. Try assigning a different type at
8110 " script def method level.
8111 let lines =<< trim END
8112 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008113 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008114 return {}
8115 enddef
8116 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008117 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008118 endclass
8119 def Bar()
8120 A.Fn = "abc"
8121 enddef
8122 test_garbagecollect_now()
8123 Bar()
8124 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008125 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 +02008126
8127 " class variable without any type. Should be set to the initialization
8128 " expression type. Try assigning a different type from script level.
8129 let lines =<< trim END
8130 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008131 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008132 return {}
8133 enddef
8134 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008135 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008136 endclass
8137 test_garbagecollect_now()
8138 A.Fn = "abc"
8139 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008140 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 +02008141
8142 " class variable without any type. Should be set to the initialization
8143 " expression type. Try assigning a different type at class def level.
8144 let lines =<< trim END
8145 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008146 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008147 return {}
8148 enddef
8149 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008150 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008151 def Bar()
8152 Fn = "abc"
8153 enddef
8154 endclass
8155 var a = A.new()
8156 test_garbagecollect_now()
8157 a.Bar()
8158 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008159 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 +02008160
8161 " class variable without any type. Should be set to the initialization
8162 " expression type. Try assigning a different type at script def level.
8163 let lines =<< trim END
8164 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008165 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008166 return {}
8167 enddef
8168 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008169 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008170 endclass
8171 def Bar()
8172 A.Fn = "abc"
8173 enddef
8174 test_garbagecollect_now()
8175 Bar()
8176 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008177 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(list<dict<blob>>): dict<list<blob>> but got string', 1)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008178
8179 " class variable with 'any" type. Can be assigned different types.
8180 let lines =<< trim END
8181 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008182 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008183 return {}
8184 enddef
8185 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008186 public static var Fn: any = Foo
8187 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008188 endclass
8189 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008190 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008191 A.Fn = "abc"
8192 test_garbagecollect_now()
8193 assert_equal('string', typename(A.Fn))
8194 A.Fn2 = Foo
8195 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008196 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008197 A.Fn2 = "xyz"
8198 test_garbagecollect_now()
8199 assert_equal('string', typename(A.Fn2))
8200 END
8201 call v9.CheckSourceSuccess(lines)
8202
8203 " class variable with 'any" type. Can be assigned different types.
8204 let lines =<< trim END
8205 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008206 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008207 return {}
8208 enddef
8209 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008210 public static var Fn: any = Foo
8211 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008212
8213 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008214 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008215 Fn = "abc"
8216 assert_equal('string', typename(Fn))
8217 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008218 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008219 Fn2 = "xyz"
8220 assert_equal('string', typename(Fn2))
8221 enddef
8222 endclass
8223 var a = A.new()
8224 test_garbagecollect_now()
8225 a.Bar()
8226 test_garbagecollect_now()
8227 A.Fn = Foo
8228 a.Bar()
8229 END
8230 call v9.CheckSourceSuccess(lines)
8231
8232 " class variable with 'any" type. Can be assigned different types.
8233 let lines =<< trim END
8234 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008235 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008236 return {}
8237 enddef
8238 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008239 public static var Fn: any = Foo
8240 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008241 endclass
8242
8243 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008244 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008245 A.Fn = "abc"
8246 assert_equal('string', typename(A.Fn))
8247 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008248 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008249 A.Fn2 = "xyz"
8250 assert_equal('string', typename(A.Fn2))
8251 enddef
8252 Bar()
8253 test_garbagecollect_now()
8254 A.Fn = Foo
8255 Bar()
8256 END
8257 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008258
8259 let lines =<< trim END
8260 vim9script
8261 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008262 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008263 endclass
8264 assert_equal([0z10, 0z20], A.foo)
8265 A.foo = [0z30]
8266 assert_equal([0z30], A.foo)
8267 var a = A.foo
8268 assert_equal([0z30], a)
8269 END
8270 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008271endfunc
8272
8273" Test type checking for object variable in assignments
8274func Test_object_variable_complex_type_check()
8275 " object variable with a specific type. Try assigning a different type at
8276 " script level.
8277 let lines =<< trim END
8278 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008279 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008280 return {}
8281 enddef
8282 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008283 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008284 endclass
8285 var a = A.new()
8286 test_garbagecollect_now()
8287 a.Fn = "abc"
8288 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008289 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 +02008290
8291 " object variable with a specific type. Try assigning a different type at
8292 " object def method level.
8293 let lines =<< trim END
8294 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008295 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008296 return {}
8297 enddef
8298 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008299 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008300 def Bar()
8301 this.Fn = "abc"
8302 this.Fn = Foo
8303 enddef
8304 endclass
8305 var a = A.new()
8306 test_garbagecollect_now()
8307 a.Bar()
8308 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008309 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 +02008310
8311 " object variable with a specific type. Try assigning a different type at
8312 " script def method level.
8313 let lines =<< trim END
8314 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008315 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008316 return {}
8317 enddef
8318 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008319 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008320 endclass
8321 def Bar()
8322 var a = A.new()
8323 a.Fn = "abc"
8324 a.Fn = Foo
8325 enddef
8326 test_garbagecollect_now()
8327 Bar()
8328 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008329 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 +02008330
8331 " object variable without any type. Should be set to the initialization
8332 " expression type. Try assigning a different type from script level.
8333 let lines =<< trim END
8334 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008335 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008336 return {}
8337 enddef
8338 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008339 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008340 endclass
8341 var a = A.new()
8342 test_garbagecollect_now()
8343 a.Fn = "abc"
8344 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008345 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 +02008346
8347 " object variable without any type. Should be set to the initialization
8348 " expression type. Try assigning a different type at object def level.
8349 let lines =<< trim END
8350 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008351 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008352 return {}
8353 enddef
8354 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008355 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008356 def Bar()
8357 this.Fn = "abc"
8358 this.Fn = Foo
8359 enddef
8360 endclass
8361 var a = A.new()
8362 test_garbagecollect_now()
8363 a.Bar()
8364 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008365 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 +02008366
8367 " object variable without any type. Should be set to the initialization
8368 " expression type. Try assigning a different type at script def level.
8369 let lines =<< trim END
8370 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008371 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008372 return {}
8373 enddef
8374 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008375 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008376 endclass
8377 def Bar()
8378 var a = A.new()
8379 a.Fn = "abc"
8380 a.Fn = Foo
8381 enddef
8382 test_garbagecollect_now()
8383 Bar()
8384 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008385 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 +02008386
8387 " object variable with 'any" type. Can be assigned different types.
8388 let lines =<< trim END
8389 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008390 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008391 return {}
8392 enddef
8393 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008394 public var Fn: any = Foo
8395 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008396 endclass
8397
8398 var a = A.new()
8399 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008400 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008401 a.Fn = "abc"
8402 test_garbagecollect_now()
8403 assert_equal('string', typename(a.Fn))
8404 a.Fn2 = Foo
8405 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008406 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008407 a.Fn2 = "xyz"
8408 test_garbagecollect_now()
8409 assert_equal('string', typename(a.Fn2))
8410 END
8411 call v9.CheckSourceSuccess(lines)
8412
8413 " object variable with 'any" type. Can be assigned different types.
8414 let lines =<< trim END
8415 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008416 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008417 return {}
8418 enddef
8419 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008420 public var Fn: any = Foo
8421 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008422
8423 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008424 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008425 this.Fn = "abc"
8426 assert_equal('string', typename(this.Fn))
8427 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008428 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008429 this.Fn2 = "xyz"
8430 assert_equal('string', typename(this.Fn2))
8431 enddef
8432 endclass
8433
8434 var a = A.new()
8435 test_garbagecollect_now()
8436 a.Bar()
8437 test_garbagecollect_now()
8438 a.Fn = Foo
8439 a.Bar()
8440 END
8441 call v9.CheckSourceSuccess(lines)
8442
8443 " object variable with 'any" type. Can be assigned different types.
8444 let lines =<< trim END
8445 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008446 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008447 return {}
8448 enddef
8449 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008450 public var Fn: any = Foo
8451 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008452 endclass
8453
8454 def Bar()
8455 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008456 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008457 a.Fn = "abc"
8458 assert_equal('string', typename(a.Fn))
8459 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008460 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008461 a.Fn2 = "xyz"
8462 assert_equal('string', typename(a.Fn2))
8463 enddef
8464 test_garbagecollect_now()
8465 Bar()
8466 test_garbagecollect_now()
8467 Bar()
8468 END
8469 call v9.CheckSourceSuccess(lines)
8470endfunc
8471
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008472" Test for recursively calling an object method. This used to cause an
8473" use-after-free error.
8474def Test_recursive_object_method_call()
8475 var lines =<< trim END
8476 vim9script
8477 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008478 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008479 def Foo(): number
8480 if this.val >= 90
8481 return this.val
8482 endif
8483 this.val += 1
8484 return this.Foo()
8485 enddef
8486 endclass
8487 var a = A.new()
8488 assert_equal(90, a.Foo())
8489 END
8490 v9.CheckSourceSuccess(lines)
8491enddef
8492
8493" Test for recursively calling a class method.
8494def Test_recursive_class_method_call()
8495 var lines =<< trim END
8496 vim9script
8497 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008498 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008499 static def Foo(): number
8500 if val >= 90
8501 return val
8502 endif
8503 val += 1
8504 return Foo()
8505 enddef
8506 endclass
8507 assert_equal(90, A.Foo())
8508 END
8509 v9.CheckSourceSuccess(lines)
8510enddef
8511
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008512" Test for checking the argument types and the return type when assigning a
8513" funcref to make sure the invariant class type is used.
8514def Test_funcref_argtype_returntype_check()
8515 var lines =<< trim END
8516 vim9script
8517 class A
8518 endclass
8519 class B extends A
8520 endclass
8521
8522 def Foo(p: B): B
8523 return B.new()
8524 enddef
8525
8526 var Bar: func(A): A = Foo
8527 END
8528 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8529
8530 lines =<< trim END
8531 vim9script
8532 class A
8533 endclass
8534 class B extends A
8535 endclass
8536
8537 def Foo(p: B): B
8538 return B.new()
8539 enddef
8540
8541 def Baz()
8542 var Bar: func(A): A = Foo
8543 enddef
8544 Baz()
8545 END
8546 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8547enddef
8548
Ernie Rael96952b22023-10-17 18:15:01 +02008549def Test_funcref_argtype_invariance_check()
8550 var lines =<< trim END
8551 vim9script
8552
8553 class A
8554 endclass
8555 class B extends A
8556 endclass
8557 class C extends B
8558 endclass
8559
8560 var Func: func(B): number
8561 Func = (o: B): number => 3
8562 assert_equal(3, Func(B.new()))
8563 END
8564 v9.CheckSourceSuccess(lines)
8565
8566 lines =<< trim END
8567 vim9script
8568
8569 class A
8570 endclass
8571 class B extends A
8572 endclass
8573 class C extends B
8574 endclass
8575
8576 var Func: func(B): number
8577 Func = (o: A): number => 3
8578 END
8579 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8580
8581 lines =<< trim END
8582 vim9script
8583
8584 class A
8585 endclass
8586 class B extends A
8587 endclass
8588 class C extends B
8589 endclass
8590
8591 var Func: func(B): number
8592 Func = (o: C): number => 3
8593 END
8594 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8595enddef
8596
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008597" Test for using an operator (e.g. +) with an assignment
8598def Test_op_and_assignment()
8599 # Using += with a class variable
8600 var lines =<< trim END
8601 vim9script
8602 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008603 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008604 static def Foo(): list<number>
8605 val += [1]
8606 return val
8607 enddef
8608 endclass
8609 def Bar(): list<number>
8610 A.val += [2]
8611 return A.val
8612 enddef
8613 assert_equal([1], A.Foo())
8614 assert_equal([1, 2], Bar())
8615 A.val += [3]
8616 assert_equal([1, 2, 3], A.val)
8617 END
8618 v9.CheckSourceSuccess(lines)
8619
8620 # Using += with an object variable
8621 lines =<< trim END
8622 vim9script
8623 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008624 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008625 def Foo(): list<number>
8626 this.val += [1]
8627 return this.val
8628 enddef
8629 endclass
8630 def Bar(bar_a: A): list<number>
8631 bar_a.val += [2]
8632 return bar_a.val
8633 enddef
8634 var a = A.new()
8635 assert_equal([1], a.Foo())
8636 assert_equal([1, 2], Bar(a))
8637 a.val += [3]
8638 assert_equal([1, 2, 3], a.val)
8639 END
8640 v9.CheckSourceSuccess(lines)
8641enddef
8642
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008643" Test for using an object method as a funcref
8644def Test_object_funcref()
8645 # Using object method funcref from a def function
8646 var lines =<< trim END
8647 vim9script
8648 class A
8649 def Foo(): list<number>
8650 return [3, 2, 1]
8651 enddef
8652 endclass
8653 def Bar()
8654 var a = A.new()
8655 var Fn = a.Foo
8656 assert_equal([3, 2, 1], Fn())
8657 enddef
8658 Bar()
8659 END
8660 v9.CheckSourceSuccess(lines)
8661
8662 # Using object method funcref at the script level
8663 lines =<< trim END
8664 vim9script
8665 class A
8666 def Foo(): dict<number>
8667 return {a: 1, b: 2}
8668 enddef
8669 endclass
8670 var a = A.new()
8671 var Fn = a.Foo
8672 assert_equal({a: 1, b: 2}, Fn())
8673 END
8674 v9.CheckSourceSuccess(lines)
8675
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008676 # Using object method funcref at the script level
8677 lines =<< trim END
8678 vim9script
8679 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008680 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008681 def Foo(): number
8682 return this.val
8683 enddef
8684 endclass
8685 var a = A.new(345)
8686 var Fn = a.Foo
8687 assert_equal(345, Fn())
8688 END
8689 v9.CheckSourceSuccess(lines)
8690
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008691 # Using object method funcref from another object method
8692 lines =<< trim END
8693 vim9script
8694 class A
8695 def Foo(): list<number>
8696 return [3, 2, 1]
8697 enddef
8698 def Bar()
8699 var Fn = this.Foo
8700 assert_equal([3, 2, 1], Fn())
8701 enddef
8702 endclass
8703 var a = A.new()
8704 a.Bar()
8705 END
8706 v9.CheckSourceSuccess(lines)
8707
8708 # Using function() to get a object method funcref
8709 lines =<< trim END
8710 vim9script
8711 class A
8712 def Foo(l: list<any>): list<any>
8713 return l
8714 enddef
8715 endclass
8716 var a = A.new()
8717 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8718 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8719 END
8720 v9.CheckSourceSuccess(lines)
8721
8722 # Use an object method with a function returning a funcref and then call the
8723 # funcref.
8724 lines =<< trim END
8725 vim9script
8726
8727 def Map(F: func(number): number): func(number): number
8728 return (n: number) => F(n)
8729 enddef
8730
8731 class Math
8732 def Double(n: number): number
8733 return 2 * n
8734 enddef
8735 endclass
8736
8737 const math = Math.new()
8738 assert_equal(48, Map(math.Double)(24))
8739 END
8740 v9.CheckSourceSuccess(lines)
8741
Ernie Rael03042a22023-11-11 08:53:32 +01008742 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008743 lines =<< trim END
8744 vim9script
8745 class A
8746 def _Foo()
8747 enddef
8748 endclass
8749 def Bar()
8750 var a = A.new()
8751 var Fn = a._Foo
8752 enddef
8753 Bar()
8754 END
Ernie Rael03042a22023-11-11 08:53:32 +01008755 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008756
Ernie Rael03042a22023-11-11 08:53:32 +01008757 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008758 lines =<< trim END
8759 vim9script
8760 class A
8761 def _Foo()
8762 enddef
8763 endclass
8764 var a = A.new()
8765 var Fn = a._Foo
8766 END
Ernie Rael03042a22023-11-11 08:53:32 +01008767 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008768
Ernie Rael03042a22023-11-11 08:53:32 +01008769 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008770 lines =<< trim END
8771 vim9script
8772 class A
8773 def _Foo(): list<number>
8774 return [3, 2, 1]
8775 enddef
8776 def Bar()
8777 var Fn = this._Foo
8778 assert_equal([3, 2, 1], Fn())
8779 enddef
8780 endclass
8781 var a = A.new()
8782 a.Bar()
8783 END
8784 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008785
8786 # Using object method funcref using call()
8787 lines =<< trim END
8788 vim9script
8789 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008790 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008791 def Foo(): number
8792 return this.val
8793 enddef
8794 endclass
8795
8796 def Bar(obj: A)
8797 assert_equal(123, call(obj.Foo, []))
8798 enddef
8799
8800 var a = A.new(123)
8801 Bar(a)
8802 assert_equal(123, call(a.Foo, []))
8803 END
8804 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008805enddef
8806
8807" Test for using a class method as a funcref
8808def Test_class_funcref()
8809 # Using class method funcref in a def function
8810 var lines =<< trim END
8811 vim9script
8812 class A
8813 static def Foo(): list<number>
8814 return [3, 2, 1]
8815 enddef
8816 endclass
8817 def Bar()
8818 var Fn = A.Foo
8819 assert_equal([3, 2, 1], Fn())
8820 enddef
8821 Bar()
8822 END
8823 v9.CheckSourceSuccess(lines)
8824
8825 # Using class method funcref at script level
8826 lines =<< trim END
8827 vim9script
8828 class A
8829 static def Foo(): dict<number>
8830 return {a: 1, b: 2}
8831 enddef
8832 endclass
8833 var Fn = A.Foo
8834 assert_equal({a: 1, b: 2}, Fn())
8835 END
8836 v9.CheckSourceSuccess(lines)
8837
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008838 # Using class method funcref at the script level
8839 lines =<< trim END
8840 vim9script
8841 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008842 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008843 static def Foo(): number
8844 return val
8845 enddef
8846 endclass
8847 A.val = 567
8848 var Fn = A.Foo
8849 assert_equal(567, Fn())
8850 END
8851 v9.CheckSourceSuccess(lines)
8852
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008853 # Using function() to get a class method funcref
8854 lines =<< trim END
8855 vim9script
8856 class A
8857 static def Foo(l: list<any>): list<any>
8858 return l
8859 enddef
8860 endclass
8861 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8862 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8863 END
8864 v9.CheckSourceSuccess(lines)
8865
8866 # Using a class method funcref from another class method
8867 lines =<< trim END
8868 vim9script
8869 class A
8870 static def Foo(): list<number>
8871 return [3, 2, 1]
8872 enddef
8873 static def Bar()
8874 var Fn = Foo
8875 assert_equal([3, 2, 1], Fn())
8876 enddef
8877 endclass
8878 A.Bar()
8879 END
8880 v9.CheckSourceSuccess(lines)
8881
8882 # Use a class method with a function returning a funcref and then call the
8883 # funcref.
8884 lines =<< trim END
8885 vim9script
8886
8887 def Map(F: func(number): number): func(number): number
8888 return (n: number) => F(n)
8889 enddef
8890
8891 class Math
8892 static def StaticDouble(n: number): number
8893 return 2 * n
8894 enddef
8895 endclass
8896
8897 assert_equal(48, Map(Math.StaticDouble)(24))
8898 END
8899 v9.CheckSourceSuccess(lines)
8900
Ernie Rael03042a22023-11-11 08:53:32 +01008901 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008902 lines =<< trim END
8903 vim9script
8904 class A
8905 static def _Foo()
8906 enddef
8907 endclass
8908 def Bar()
8909 var Fn = A._Foo
8910 enddef
8911 Bar()
8912 END
Ernie Rael03042a22023-11-11 08:53:32 +01008913 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008914
Ernie Rael03042a22023-11-11 08:53:32 +01008915 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008916 lines =<< trim END
8917 vim9script
8918 class A
8919 static def _Foo()
8920 enddef
8921 endclass
8922 var Fn = A._Foo
8923 END
Ernie Rael03042a22023-11-11 08:53:32 +01008924 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008925
Ernie Rael03042a22023-11-11 08:53:32 +01008926 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008927 lines =<< trim END
8928 vim9script
8929 class A
8930 static def _Foo(): list<number>
8931 return [3, 2, 1]
8932 enddef
8933 static def Bar()
8934 var Fn = _Foo
8935 assert_equal([3, 2, 1], Fn())
8936 enddef
8937 endclass
8938 A.Bar()
8939 END
8940 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008941
8942 # Using class method funcref using call()
8943 lines =<< trim END
8944 vim9script
8945 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008946 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008947 static def Foo(): number
8948 return val
8949 enddef
8950 endclass
8951
8952 def Bar()
8953 A.val = 468
8954 assert_equal(468, call(A.Foo, []))
8955 enddef
8956 Bar()
8957 assert_equal(468, call(A.Foo, []))
8958 END
8959 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008960enddef
8961
8962" Test for using an object member as a funcref
8963def Test_object_member_funcref()
8964 # Using a funcref object variable in an object method
8965 var lines =<< trim END
8966 vim9script
8967 def Foo(n: number): number
8968 return n * 10
8969 enddef
8970
8971 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008972 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008973 def Bar()
8974 assert_equal(200, this.Cb(20))
8975 enddef
8976 endclass
8977
8978 var a = A.new()
8979 a.Bar()
8980 END
8981 v9.CheckSourceSuccess(lines)
8982
8983 # Using a funcref object variable in a def method
8984 lines =<< trim END
8985 vim9script
8986 def Foo(n: number): number
8987 return n * 10
8988 enddef
8989
8990 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008991 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008992 endclass
8993
8994 def Bar()
8995 var a = A.new()
8996 assert_equal(200, a.Cb(20))
8997 enddef
8998 Bar()
8999 END
9000 v9.CheckSourceSuccess(lines)
9001
9002 # Using a funcref object variable at script level
9003 lines =<< trim END
9004 vim9script
9005 def Foo(n: number): number
9006 return n * 10
9007 enddef
9008
9009 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009010 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009011 endclass
9012
9013 var a = A.new()
9014 assert_equal(200, a.Cb(20))
9015 END
9016 v9.CheckSourceSuccess(lines)
9017
9018 # Using a funcref object variable pointing to an object method in an object
9019 # method.
9020 lines =<< trim END
9021 vim9script
9022 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009023 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009024 def Foo(n: number): number
9025 return n * 10
9026 enddef
9027 def Bar()
9028 assert_equal(200, this.Cb(20))
9029 enddef
9030 endclass
9031
9032 var a = A.new()
9033 a.Bar()
9034 END
9035 v9.CheckSourceSuccess(lines)
9036
9037 # Using a funcref object variable pointing to an object method in a def
9038 # method.
9039 lines =<< trim END
9040 vim9script
9041 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009042 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009043 def Foo(n: number): number
9044 return n * 10
9045 enddef
9046 endclass
9047
9048 def Bar()
9049 var a = A.new()
9050 assert_equal(200, a.Cb(20))
9051 enddef
9052 Bar()
9053 END
9054 v9.CheckSourceSuccess(lines)
9055
9056 # Using a funcref object variable pointing to an object method at script
9057 # level.
9058 lines =<< trim END
9059 vim9script
9060 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009061 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009062 def Foo(n: number): number
9063 return n * 10
9064 enddef
9065 endclass
9066
9067 var a = A.new()
9068 assert_equal(200, a.Cb(20))
9069 END
9070 v9.CheckSourceSuccess(lines)
9071enddef
9072
9073" Test for using a class member as a funcref
9074def Test_class_member_funcref()
9075 # Using a funcref class variable in a class method
9076 var lines =<< trim END
9077 vim9script
9078 def Foo(n: number): number
9079 return n * 10
9080 enddef
9081
9082 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009083 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009084 static def Bar()
9085 assert_equal(200, Cb(20))
9086 enddef
9087 endclass
9088
9089 A.Bar()
9090 END
9091 v9.CheckSourceSuccess(lines)
9092
9093 # Using a funcref class variable in a def method
9094 lines =<< trim END
9095 vim9script
9096 def Foo(n: number): number
9097 return n * 10
9098 enddef
9099
9100 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009101 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009102 endclass
9103
9104 def Bar()
9105 assert_equal(200, A.Cb(20))
9106 enddef
9107 Bar()
9108 END
9109 v9.CheckSourceSuccess(lines)
9110
9111 # Using a funcref class variable at script level
9112 lines =<< trim END
9113 vim9script
9114 def Foo(n: number): number
9115 return n * 10
9116 enddef
9117
9118 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009119 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009120 endclass
9121
9122 assert_equal(200, A.Cb(20))
9123 END
9124 v9.CheckSourceSuccess(lines)
9125
9126 # Using a funcref class variable pointing to a class method in a class
9127 # method.
9128 lines =<< trim END
9129 vim9script
9130 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009131 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009132 static def Foo(n: number): number
9133 return n * 10
9134 enddef
9135 static def Init()
9136 Cb = Foo
9137 enddef
9138 static def Bar()
9139 assert_equal(200, Cb(20))
9140 enddef
9141 endclass
9142
9143 A.Init()
9144 A.Bar()
9145 END
9146 v9.CheckSourceSuccess(lines)
9147
9148 # Using a funcref class variable pointing to a class method in a def method.
9149 lines =<< trim END
9150 vim9script
9151 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009152 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009153 static def Foo(n: number): number
9154 return n * 10
9155 enddef
9156 static def Init()
9157 Cb = Foo
9158 enddef
9159 endclass
9160
9161 def Bar()
9162 A.Init()
9163 assert_equal(200, A.Cb(20))
9164 enddef
9165 Bar()
9166 END
9167 v9.CheckSourceSuccess(lines)
9168
9169 # Using a funcref class variable pointing to a class method at script level.
9170 lines =<< trim END
9171 vim9script
9172 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009173 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02009174 static def Foo(n: number): number
9175 return n * 10
9176 enddef
9177 static def Init()
9178 Cb = Foo
9179 enddef
9180 endclass
9181
9182 A.Init()
9183 assert_equal(200, A.Cb(20))
9184 END
9185 v9.CheckSourceSuccess(lines)
9186enddef
9187
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009188" Test for using object methods as popup callback functions
9189def Test_objmethod_popup_callback()
9190 # Use the popup from the script level
9191 var lines =<< trim END
9192 vim9script
9193
9194 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009195 var selection: number = -1
9196 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009197
9198 def PopupFilter(id: number, key: string): bool
9199 add(this.filterkeys, key)
9200 return popup_filter_yesno(id, key)
9201 enddef
9202
9203 def PopupCb(id: number, result: number)
9204 this.selection = result ? 100 : 200
9205 enddef
9206 endclass
9207
9208 var a = A.new()
9209 feedkeys('', 'xt')
9210 var winid = popup_create('Y/N?',
9211 {filter: a.PopupFilter, callback: a.PopupCb})
9212 feedkeys('y', 'xt')
9213 popup_close(winid)
9214 assert_equal(100, a.selection)
9215 assert_equal(['y'], a.filterkeys)
9216 feedkeys('', 'xt')
9217 winid = popup_create('Y/N?',
9218 {filter: a.PopupFilter, callback: a.PopupCb})
9219 feedkeys('n', 'xt')
9220 popup_close(winid)
9221 assert_equal(200, a.selection)
9222 assert_equal(['y', 'n'], a.filterkeys)
9223 END
9224 v9.CheckSourceSuccess(lines)
9225
9226 # Use the popup from a def function
9227 lines =<< trim END
9228 vim9script
9229
9230 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009231 var selection: number = -1
9232 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009233
9234 def PopupFilter(id: number, key: string): bool
9235 add(this.filterkeys, key)
9236 return popup_filter_yesno(id, key)
9237 enddef
9238
9239 def PopupCb(id: number, result: number)
9240 this.selection = result ? 100 : 200
9241 enddef
9242 endclass
9243
9244 def Foo()
9245 var a = A.new()
9246 feedkeys('', 'xt')
9247 var winid = popup_create('Y/N?',
9248 {filter: a.PopupFilter, callback: a.PopupCb})
9249 feedkeys('y', 'xt')
9250 popup_close(winid)
9251 assert_equal(100, a.selection)
9252 assert_equal(['y'], a.filterkeys)
9253 feedkeys('', 'xt')
9254 winid = popup_create('Y/N?',
9255 {filter: a.PopupFilter, callback: a.PopupCb})
9256 feedkeys('n', 'xt')
9257 popup_close(winid)
9258 assert_equal(200, a.selection)
9259 assert_equal(['y', 'n'], a.filterkeys)
9260 enddef
9261 Foo()
9262 END
9263 v9.CheckSourceSuccess(lines)
9264enddef
9265
9266" Test for using class methods as popup callback functions
9267def Test_classmethod_popup_callback()
9268 # Use the popup from the script level
9269 var lines =<< trim END
9270 vim9script
9271
9272 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009273 static var selection: number = -1
9274 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009275
9276 static def PopupFilter(id: number, key: string): bool
9277 add(filterkeys, key)
9278 return popup_filter_yesno(id, key)
9279 enddef
9280
9281 static def PopupCb(id: number, result: number)
9282 selection = result ? 100 : 200
9283 enddef
9284 endclass
9285
9286 feedkeys('', 'xt')
9287 var winid = popup_create('Y/N?',
9288 {filter: A.PopupFilter, callback: A.PopupCb})
9289 feedkeys('y', 'xt')
9290 popup_close(winid)
9291 assert_equal(100, A.selection)
9292 assert_equal(['y'], A.filterkeys)
9293 feedkeys('', 'xt')
9294 winid = popup_create('Y/N?',
9295 {filter: A.PopupFilter, callback: A.PopupCb})
9296 feedkeys('n', 'xt')
9297 popup_close(winid)
9298 assert_equal(200, A.selection)
9299 assert_equal(['y', 'n'], A.filterkeys)
9300 END
9301 v9.CheckSourceSuccess(lines)
9302
9303 # Use the popup from a def function
9304 lines =<< trim END
9305 vim9script
9306
9307 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009308 static var selection: number = -1
9309 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009310
9311 static def PopupFilter(id: number, key: string): bool
9312 add(filterkeys, key)
9313 return popup_filter_yesno(id, key)
9314 enddef
9315
9316 static def PopupCb(id: number, result: number)
9317 selection = result ? 100 : 200
9318 enddef
9319 endclass
9320
9321 def Foo()
9322 feedkeys('', 'xt')
9323 var winid = popup_create('Y/N?',
9324 {filter: A.PopupFilter, callback: A.PopupCb})
9325 feedkeys('y', 'xt')
9326 popup_close(winid)
9327 assert_equal(100, A.selection)
9328 assert_equal(['y'], A.filterkeys)
9329 feedkeys('', 'xt')
9330 winid = popup_create('Y/N?',
9331 {filter: A.PopupFilter, callback: A.PopupCb})
9332 feedkeys('n', 'xt')
9333 popup_close(winid)
9334 assert_equal(200, A.selection)
9335 assert_equal(['y', 'n'], A.filterkeys)
9336 enddef
9337 Foo()
9338 END
9339 v9.CheckSourceSuccess(lines)
9340enddef
9341
9342" Test for using an object method as a timer callback function
9343def Test_objmethod_timer_callback()
9344 # Use the timer callback from script level
9345 var lines =<< trim END
9346 vim9script
9347
9348 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009349 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009350 def TimerCb(timerID: number)
9351 this.timerTick = 6
9352 enddef
9353 endclass
9354
9355 var a = A.new()
9356 timer_start(0, a.TimerCb)
9357 var maxWait = 5
9358 while maxWait > 0 && a.timerTick == -1
9359 :sleep 10m
9360 maxWait -= 1
9361 endwhile
9362 assert_equal(6, a.timerTick)
9363 END
9364 v9.CheckSourceSuccess(lines)
9365
9366 # Use the timer callback from a def function
9367 lines =<< trim END
9368 vim9script
9369
9370 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009371 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009372 def TimerCb(timerID: number)
9373 this.timerTick = 6
9374 enddef
9375 endclass
9376
9377 def Foo()
9378 var a = A.new()
9379 timer_start(0, a.TimerCb)
9380 var maxWait = 5
9381 while maxWait > 0 && a.timerTick == -1
9382 :sleep 10m
9383 maxWait -= 1
9384 endwhile
9385 assert_equal(6, a.timerTick)
9386 enddef
9387 Foo()
9388 END
9389 v9.CheckSourceSuccess(lines)
9390enddef
9391
9392" Test for using a class method as a timer callback function
9393def Test_classmethod_timer_callback()
9394 # Use the timer callback from script level
9395 var lines =<< trim END
9396 vim9script
9397
9398 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009399 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009400 static def TimerCb(timerID: number)
9401 timerTick = 6
9402 enddef
9403 endclass
9404
9405 timer_start(0, A.TimerCb)
9406 var maxWait = 5
9407 while maxWait > 0 && A.timerTick == -1
9408 :sleep 10m
9409 maxWait -= 1
9410 endwhile
9411 assert_equal(6, A.timerTick)
9412 END
9413 v9.CheckSourceSuccess(lines)
9414
9415 # Use the timer callback from a def function
9416 lines =<< trim END
9417 vim9script
9418
9419 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009420 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009421 static def TimerCb(timerID: number)
9422 timerTick = 6
9423 enddef
9424 endclass
9425
9426 def Foo()
9427 timer_start(0, A.TimerCb)
9428 var maxWait = 5
9429 while maxWait > 0 && A.timerTick == -1
9430 :sleep 10m
9431 maxWait -= 1
9432 endwhile
9433 assert_equal(6, A.timerTick)
9434 enddef
9435 Foo()
9436 END
9437 v9.CheckSourceSuccess(lines)
9438enddef
9439
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009440" Test for using a class variable as the first and/or second operand of a binary
9441" operator.
9442def Test_class_variable_as_operands()
9443 var lines =<< trim END
9444 vim9script
9445 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009446 static var truthy: bool = true
9447 public static var TruthyFn: func
9448 static var list: list<any> = []
9449 static var four: number = 4
9450 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009451
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009452 static def Str(): string
9453 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009454 enddef
9455
9456 static def Four(): number
9457 return four
9458 enddef
9459
9460 static def List(): list<any>
9461 return list
9462 enddef
9463
9464 static def Truthy(): bool
9465 return truthy
9466 enddef
9467
9468 def TestOps()
9469 assert_true(Tests.truthy == truthy)
9470 assert_true(truthy == Tests.truthy)
9471 assert_true(Tests.list isnot [])
9472 assert_true([] isnot Tests.list)
9473 assert_equal(2, Tests.four >> 1)
9474 assert_equal(16, 1 << Tests.four)
9475 assert_equal(8, Tests.four + four)
9476 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009477 assert_equal('hellohello', Tests.str .. str)
9478 assert_equal('hellohello', str .. Tests.str)
9479
9480 # Using class variable for list indexing
9481 var l = range(10)
9482 assert_equal(4, l[Tests.four])
9483 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9484
9485 # Using class variable for Dict key
9486 var d = {hello: 'abc'}
9487 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009488 enddef
9489 endclass
9490
9491 def TestOps2()
9492 assert_true(Tests.truthy == Tests.Truthy())
9493 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009494 assert_true(Tests.truthy == Tests.TruthyFn())
9495 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009496 assert_true(Tests.list is Tests.List())
9497 assert_true(Tests.List() is Tests.list)
9498 assert_equal(2, Tests.four >> 1)
9499 assert_equal(16, 1 << Tests.four)
9500 assert_equal(8, Tests.four + Tests.Four())
9501 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009502 assert_equal('hellohello', Tests.str .. Tests.Str())
9503 assert_equal('hellohello', Tests.Str() .. Tests.str)
9504
9505 # Using class variable for list indexing
9506 var l = range(10)
9507 assert_equal(4, l[Tests.four])
9508 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9509
9510 # Using class variable for Dict key
9511 var d = {hello: 'abc'}
9512 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009513 enddef
9514
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009515 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009516 var t = Tests.new()
9517 t.TestOps()
9518 TestOps2()
9519
9520 assert_true(Tests.truthy == Tests.Truthy())
9521 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009522 assert_true(Tests.truthy == Tests.TruthyFn())
9523 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009524 assert_true(Tests.list is Tests.List())
9525 assert_true(Tests.List() is Tests.list)
9526 assert_equal(2, Tests.four >> 1)
9527 assert_equal(16, 1 << Tests.four)
9528 assert_equal(8, Tests.four + Tests.Four())
9529 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009530 assert_equal('hellohello', Tests.str .. Tests.Str())
9531 assert_equal('hellohello', Tests.Str() .. Tests.str)
9532
9533 # Using class variable for list indexing
9534 var l = range(10)
9535 assert_equal(4, l[Tests.four])
9536 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9537
9538 # Using class variable for Dict key
9539 var d = {hello: 'abc'}
9540 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009541 END
9542 v9.CheckSourceSuccess(lines)
9543enddef
9544
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009545" Test for checking the type of the key used to access an object dict member.
9546def Test_dict_member_key_type_check()
9547 var lines =<< trim END
9548 vim9script
9549
9550 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009551 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009552 endclass
9553
9554 class Test extends State
9555 def ObjMethodTests()
9556 var cursor: number = 0
9557 var z: number = 0
9558 [this.numbers[cursor]] = ['zero.1']
9559 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9560 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9561 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9562 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9563 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9564 [this.numbers[cursor], z] = ['zero.4', 1]
9565 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9566 [z, this.numbers[cursor]] = [1, 'zero.5']
9567 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9568 enddef
9569
9570 static def ClassMethodTests(that: State)
9571 var cursor: number = 0
9572 var z: number = 0
9573 [that.numbers[cursor]] = ['zero.1']
9574 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9575 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9576 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9577 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9578 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9579 [that.numbers[cursor], z] = ['zero.4', 1]
9580 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9581 [z, that.numbers[cursor]] = [1, 'zero.5']
9582 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9583 enddef
9584
9585 def new()
9586 enddef
9587
9588 def newMethodTests()
9589 var cursor: number = 0
9590 var z: number
9591 [this.numbers[cursor]] = ['zero.1']
9592 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9593 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9594 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9595 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9596 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9597 [this.numbers[cursor], z] = ['zero.4', 1]
9598 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9599 [z, this.numbers[cursor]] = [1, 'zero.5']
9600 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9601 enddef
9602 endclass
9603
9604 def DefFuncTests(that: Test)
9605 var cursor: number = 0
9606 var z: number
9607 [that.numbers[cursor]] = ['zero.1']
9608 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9609 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9610 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9611 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9612 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9613 [that.numbers[cursor], z] = ['zero.4', 1]
9614 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9615 [z, that.numbers[cursor]] = [1, 'zero.5']
9616 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9617 enddef
9618
9619 Test.newMethodTests()
9620 Test.new().ObjMethodTests()
9621 Test.ClassMethodTests(Test.new())
9622 DefFuncTests(Test.new())
9623
9624 const test: Test = Test.new()
9625 var cursor: number = 0
9626 [test.numbers[cursor], cursor] = ['zero', 1]
9627 [cursor, test.numbers[cursor]] = [1, 'one']
9628 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9629 END
9630 v9.CheckSourceSuccess(lines)
9631
9632 lines =<< trim END
9633 vim9script
9634
9635 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009636 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009637
9638 def new()
9639 enddef
9640
9641 def Foo()
9642 var z: number
9643 [this.numbers.a, z] = [{}, 10]
9644 enddef
9645 endclass
9646
9647 var a = A.new()
9648 a.Foo()
9649 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009650 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009651
9652 lines =<< trim END
9653 vim9script
9654
9655 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009656 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009657
9658 def new()
9659 enddef
9660
9661 def Foo()
9662 var x: string = 'a'
9663 var y: number
9664 [this.numbers[x], y] = [{}, 10]
9665 enddef
9666 endclass
9667
9668 var a = A.new()
9669 a.Foo()
9670 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009671 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009672enddef
9673
mityua5550692023-11-25 15:41:20 +01009674def Test_compile_many_def_functions_in_funcref_instr()
9675 # This used to crash Vim. This is reproducible only when run on new instance
9676 # of Vim.
9677 var lines =<< trim END
9678 vim9script
9679
9680 class A
9681 def new()
9682 this.TakeFunc(this.F00)
9683 enddef
9684
9685 def TakeFunc(F: func)
9686 enddef
9687
9688 def F00()
9689 this.F01()
9690 this.F02()
9691 this.F03()
9692 this.F04()
9693 this.F05()
9694 this.F06()
9695 this.F07()
9696 this.F08()
9697 this.F09()
9698 this.F10()
9699 this.F11()
9700 this.F12()
9701 this.F13()
9702 this.F14()
9703 this.F15()
9704 this.F16()
9705 this.F17()
9706 this.F18()
9707 this.F19()
9708 this.F20()
9709 this.F21()
9710 this.F22()
9711 this.F23()
9712 this.F24()
9713 this.F25()
9714 this.F26()
9715 this.F27()
9716 this.F28()
9717 this.F29()
9718 this.F30()
9719 this.F31()
9720 this.F32()
9721 this.F33()
9722 this.F34()
9723 this.F35()
9724 this.F36()
9725 this.F37()
9726 this.F38()
9727 this.F39()
9728 this.F40()
9729 this.F41()
9730 this.F42()
9731 this.F43()
9732 this.F44()
9733 this.F45()
9734 this.F46()
9735 this.F47()
9736 enddef
9737
9738 def F01()
9739 enddef
9740 def F02()
9741 enddef
9742 def F03()
9743 enddef
9744 def F04()
9745 enddef
9746 def F05()
9747 enddef
9748 def F06()
9749 enddef
9750 def F07()
9751 enddef
9752 def F08()
9753 enddef
9754 def F09()
9755 enddef
9756 def F10()
9757 enddef
9758 def F11()
9759 enddef
9760 def F12()
9761 enddef
9762 def F13()
9763 enddef
9764 def F14()
9765 enddef
9766 def F15()
9767 enddef
9768 def F16()
9769 enddef
9770 def F17()
9771 enddef
9772 def F18()
9773 enddef
9774 def F19()
9775 enddef
9776 def F20()
9777 enddef
9778 def F21()
9779 enddef
9780 def F22()
9781 enddef
9782 def F23()
9783 enddef
9784 def F24()
9785 enddef
9786 def F25()
9787 enddef
9788 def F26()
9789 enddef
9790 def F27()
9791 enddef
9792 def F28()
9793 enddef
9794 def F29()
9795 enddef
9796 def F30()
9797 enddef
9798 def F31()
9799 enddef
9800 def F32()
9801 enddef
9802 def F33()
9803 enddef
9804 def F34()
9805 enddef
9806 def F35()
9807 enddef
9808 def F36()
9809 enddef
9810 def F37()
9811 enddef
9812 def F38()
9813 enddef
9814 def F39()
9815 enddef
9816 def F40()
9817 enddef
9818 def F41()
9819 enddef
9820 def F42()
9821 enddef
9822 def F43()
9823 enddef
9824 def F44()
9825 enddef
9826 def F45()
9827 enddef
9828 def F46()
9829 enddef
9830 def F47()
9831 enddef
9832 endclass
9833
9834 A.new()
9835 END
9836 writefile(lines, 'Xscript', 'D')
9837 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9838 assert_equal(0, v:shell_error)
9839enddef
9840
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009841" Test for 'final' class and object variables
9842def Test_final_class_object_variable()
9843 # Test for changing a final object variable from an object function
9844 var lines =<< trim END
9845 vim9script
9846 class A
9847 final foo: string = "abc"
9848 def Foo()
9849 this.foo = "def"
9850 enddef
9851 endclass
9852 defcompile A.Foo
9853 END
9854 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9855
9856 # Test for changing a final object variable from the 'new' function
9857 lines =<< trim END
9858 vim9script
9859 class A
9860 final s1: string
9861 final s2: string
9862 def new(this.s1)
9863 this.s2 = 'def'
9864 enddef
9865 endclass
9866 var a = A.new('abc')
9867 assert_equal('abc', a.s1)
9868 assert_equal('def', a.s2)
9869 END
9870 v9.CheckSourceSuccess(lines)
9871
9872 # Test for a final class variable
9873 lines =<< trim END
9874 vim9script
9875 class A
9876 static final s1: string = "abc"
9877 endclass
9878 assert_equal('abc', A.s1)
9879 END
9880 v9.CheckSourceSuccess(lines)
9881
9882 # Test for changing a final class variable from a class function
9883 lines =<< trim END
9884 vim9script
9885 class A
9886 static final s1: string = "abc"
9887 static def Foo()
9888 s1 = "def"
9889 enddef
9890 endclass
9891 A.Foo()
9892 END
9893 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9894
9895 # Test for changing a public final class variable at script level
9896 lines =<< trim END
9897 vim9script
9898 class A
9899 public static final s1: string = "abc"
9900 endclass
9901 assert_equal('abc', A.s1)
9902 A.s1 = 'def'
9903 END
9904 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9905
9906 # Test for changing a public final class variable from a class function
9907 lines =<< trim END
9908 vim9script
9909 class A
9910 public static final s1: string = "abc"
9911 static def Foo()
9912 s1 = "def"
9913 enddef
9914 endclass
9915 A.Foo()
9916 END
9917 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9918
9919 # Test for changing a public final class variable from a function
9920 lines =<< trim END
9921 vim9script
9922 class A
9923 public static final s1: string = "abc"
9924 endclass
9925 def Foo()
9926 A.s1 = 'def'
9927 enddef
9928 defcompile
9929 END
9930 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9931
9932 # Test for using a final variable of composite type
9933 lines =<< trim END
9934 vim9script
9935 class A
9936 public final l: list<number>
9937 def new()
9938 this.l = [1, 2]
9939 enddef
9940 def Foo()
9941 this.l[0] = 3
9942 this.l->add(4)
9943 enddef
9944 endclass
9945 var a = A.new()
9946 assert_equal([1, 2], a.l)
9947 a.Foo()
9948 assert_equal([3, 2, 4], a.l)
9949 END
9950 v9.CheckSourceSuccess(lines)
9951
9952 # Test for changing a final variable of composite type from another object
9953 # function
9954 lines =<< trim END
9955 vim9script
9956 class A
9957 public final l: list<number> = [1, 2]
9958 def Foo()
9959 this.l = [3, 4]
9960 enddef
9961 endclass
9962 var a = A.new()
9963 a.Foo()
9964 END
9965 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9966
9967 # Test for modifying a final variable of composite type at script level
9968 lines =<< trim END
9969 vim9script
9970 class A
9971 public final l: list<number> = [1, 2]
9972 endclass
9973 var a = A.new()
9974 a.l[0] = 3
9975 a.l->add(4)
9976 assert_equal([3, 2, 4], a.l)
9977 END
9978 v9.CheckSourceSuccess(lines)
9979
9980 # Test for modifying a final variable of composite type from a function
9981 lines =<< trim END
9982 vim9script
9983 class A
9984 public final l: list<number> = [1, 2]
9985 endclass
9986 def Foo()
9987 var a = A.new()
9988 a.l[0] = 3
9989 a.l->add(4)
9990 assert_equal([3, 2, 4], a.l)
9991 enddef
9992 Foo()
9993 END
9994 v9.CheckSourceSuccess(lines)
9995
9996 # Test for modifying a final variable of composite type from another object
9997 # function
9998 lines =<< trim END
9999 vim9script
10000 class A
10001 public final l: list<number> = [1, 2]
10002 def Foo()
10003 this.l[0] = 3
10004 this.l->add(4)
10005 enddef
10006 endclass
10007 var a = A.new()
10008 a.Foo()
10009 assert_equal([3, 2, 4], a.l)
10010 END
10011 v9.CheckSourceSuccess(lines)
10012
10013 # Test for assigning a new value to a final variable of composite type at
10014 # script level
10015 lines =<< trim END
10016 vim9script
10017 class A
10018 public final l: list<number> = [1, 2]
10019 endclass
10020 var a = A.new()
10021 a.l = [3, 4]
10022 END
10023 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10024
10025 # Test for assigning a new value to a final variable of composite type from
10026 # another object function
10027 lines =<< trim END
10028 vim9script
10029 class A
10030 public final l: list<number> = [1, 2]
10031 def Foo()
10032 this.l = [3, 4]
10033 enddef
10034 endclass
10035 var a = A.new()
10036 a.Foo()
10037 END
10038 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10039
10040 # Test for assigning a new value to a final variable of composite type from
10041 # another function
10042 lines =<< trim END
10043 vim9script
10044 class A
10045 public final l: list<number> = [1, 2]
10046 endclass
10047 def Foo()
10048 var a = A.new()
10049 a.l = [3, 4]
10050 enddef
10051 Foo()
10052 END
10053 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10054
10055 # Error case: Use 'final' with just a variable name
10056 lines =<< trim END
10057 vim9script
10058 class A
10059 final foo
10060 endclass
10061 var a = A.new()
10062 END
10063 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10064
10065 # Error case: Use 'final' followed by 'public'
10066 lines =<< trim END
10067 vim9script
10068 class A
10069 final public foo: number
10070 endclass
10071 var a = A.new()
10072 END
10073 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10074
10075 # Error case: Use 'final' followed by 'static'
10076 lines =<< trim END
10077 vim9script
10078 class A
10079 final static foo: number
10080 endclass
10081 var a = A.new()
10082 END
10083 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10084
10085 # Error case: 'final' cannot be used in an interface
10086 lines =<< trim END
10087 vim9script
10088 interface A
10089 final foo: number = 10
10090 endinterface
10091 END
10092 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
10093
10094 # Error case: 'final' not supported for an object method
10095 lines =<< trim END
10096 vim9script
10097 class A
10098 final def Foo()
10099 enddef
10100 endclass
10101 END
10102 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10103
10104 # Error case: 'final' not supported for a class method
10105 lines =<< trim END
10106 vim9script
10107 class A
10108 static final def Foo()
10109 enddef
10110 endclass
10111 END
10112 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10113enddef
10114
10115" Test for 'const' class and object variables
10116def Test_const_class_object_variable()
10117 # Test for changing a const object variable from an object function
10118 var lines =<< trim END
10119 vim9script
10120 class A
10121 const foo: string = "abc"
10122 def Foo()
10123 this.foo = "def"
10124 enddef
10125 endclass
10126 defcompile A.Foo
10127 END
10128 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
10129
10130 # Test for changing a const object variable from the 'new' function
10131 lines =<< trim END
10132 vim9script
10133 class A
10134 const s1: string
10135 const s2: string
10136 def new(this.s1)
10137 this.s2 = 'def'
10138 enddef
10139 endclass
10140 var a = A.new('abc')
10141 assert_equal('abc', a.s1)
10142 assert_equal('def', a.s2)
10143 END
10144 v9.CheckSourceSuccess(lines)
10145
10146 # Test for changing a const object variable from an object method called from
10147 # the 'new' function
10148 lines =<< trim END
10149 vim9script
10150 class A
10151 const s1: string = 'abc'
10152 def new()
10153 this.ChangeStr()
10154 enddef
10155 def ChangeStr()
10156 this.s1 = 'def'
10157 enddef
10158 endclass
10159 var a = A.new()
10160 END
10161 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10162
10163 # Test for a const class variable
10164 lines =<< trim END
10165 vim9script
10166 class A
10167 static const s1: string = "abc"
10168 endclass
10169 assert_equal('abc', A.s1)
10170 END
10171 v9.CheckSourceSuccess(lines)
10172
10173 # Test for changing a const class variable from a class function
10174 lines =<< trim END
10175 vim9script
10176 class A
10177 static const s1: string = "abc"
10178 static def Foo()
10179 s1 = "def"
10180 enddef
10181 endclass
10182 A.Foo()
10183 END
10184 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10185
10186 # Test for changing a public const class variable at script level
10187 lines =<< trim END
10188 vim9script
10189 class A
10190 public static const s1: string = "abc"
10191 endclass
10192 assert_equal('abc', A.s1)
10193 A.s1 = 'def'
10194 END
10195 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
10196
10197 # Test for changing a public const class variable from a class function
10198 lines =<< trim END
10199 vim9script
10200 class A
10201 public static const s1: string = "abc"
10202 static def Foo()
10203 s1 = "def"
10204 enddef
10205 endclass
10206 A.Foo()
10207 END
10208 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10209
10210 # Test for changing a public const class variable from a function
10211 lines =<< trim END
10212 vim9script
10213 class A
10214 public static const s1: string = "abc"
10215 endclass
10216 def Foo()
10217 A.s1 = 'def'
10218 enddef
10219 defcompile
10220 END
10221 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
10222
10223 # Test for changing a const List item from an object function
10224 lines =<< trim END
10225 vim9script
10226 class A
10227 public const l: list<number>
10228 def new()
10229 this.l = [1, 2]
10230 enddef
10231 def Foo()
10232 this.l[0] = 3
10233 enddef
10234 endclass
10235 var a = A.new()
10236 assert_equal([1, 2], a.l)
10237 a.Foo()
10238 END
10239 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10240
10241 # Test for adding a value to a const List from an object function
10242 lines =<< trim END
10243 vim9script
10244 class A
10245 public const l: list<number>
10246 def new()
10247 this.l = [1, 2]
10248 enddef
10249 def Foo()
10250 this.l->add(3)
10251 enddef
10252 endclass
10253 var a = A.new()
10254 a.Foo()
10255 END
10256 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10257
10258 # Test for reassigning a const List from an object function
10259 lines =<< trim END
10260 vim9script
10261 class A
10262 public const l: list<number> = [1, 2]
10263 def Foo()
10264 this.l = [3, 4]
10265 enddef
10266 endclass
10267 var a = A.new()
10268 a.Foo()
10269 END
10270 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10271
10272 # Test for changing a const List item at script level
10273 lines =<< trim END
10274 vim9script
10275 class A
10276 public const l: list<number> = [1, 2]
10277 endclass
10278 var a = A.new()
10279 a.l[0] = 3
10280 END
10281 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10282
10283 # Test for adding a value to a const List item at script level
10284 lines =<< trim END
10285 vim9script
10286 class A
10287 public const l: list<number> = [1, 2]
10288 endclass
10289 var a = A.new()
10290 a.l->add(4)
10291 END
10292 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
10293
10294 # Test for changing a const List item from a function
10295 lines =<< trim END
10296 vim9script
10297 class A
10298 public const l: list<number> = [1, 2]
10299 endclass
10300 def Foo()
10301 var a = A.new()
10302 a.l[0] = 3
10303 enddef
10304 Foo()
10305 END
10306 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
10307
10308 # Test for adding a value to a const List item from a function
10309 lines =<< trim END
10310 vim9script
10311 class A
10312 public const l: list<number> = [1, 2]
10313 endclass
10314 def Foo()
10315 var a = A.new()
10316 a.l->add(4)
10317 enddef
10318 Foo()
10319 END
10320 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
10321
10322 # Test for changing a const List item from an object method
10323 lines =<< trim END
10324 vim9script
10325 class A
10326 public const l: list<number> = [1, 2]
10327 def Foo()
10328 this.l[0] = 3
10329 enddef
10330 endclass
10331 var a = A.new()
10332 a.Foo()
10333 END
10334 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
10335
10336 # Test for adding a value to a const List item from an object method
10337 lines =<< trim END
10338 vim9script
10339 class A
10340 public const l: list<number> = [1, 2]
10341 def Foo()
10342 this.l->add(4)
10343 enddef
10344 endclass
10345 var a = A.new()
10346 a.Foo()
10347 END
10348 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
10349
10350 # Test for reassigning a const List object variable at script level
10351 lines =<< trim END
10352 vim9script
10353 class A
10354 public const l: list<number> = [1, 2]
10355 endclass
10356 var a = A.new()
10357 a.l = [3, 4]
10358 END
10359 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
10360
10361 # Test for reassigning a const List object variable from an object method
10362 lines =<< trim END
10363 vim9script
10364 class A
10365 public const l: list<number> = [1, 2]
10366 def Foo()
10367 this.l = [3, 4]
10368 enddef
10369 endclass
10370 var a = A.new()
10371 a.Foo()
10372 END
10373 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
10374
10375 # Test for reassigning a const List object variable from another function
10376 lines =<< trim END
10377 vim9script
10378 class A
10379 public const l: list<number> = [1, 2]
10380 endclass
10381 def Foo()
10382 var a = A.new()
10383 a.l = [3, 4]
10384 enddef
10385 Foo()
10386 END
10387 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10388
10389 # Error case: Use 'const' with just a variable name
10390 lines =<< trim END
10391 vim9script
10392 class A
10393 const foo
10394 endclass
10395 var a = A.new()
10396 END
10397 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10398
10399 # Error case: Use 'const' followed by 'public'
10400 lines =<< trim END
10401 vim9script
10402 class A
10403 const public foo: number
10404 endclass
10405 var a = A.new()
10406 END
10407 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10408
10409 # Error case: Use 'const' followed by 'static'
10410 lines =<< trim END
10411 vim9script
10412 class A
10413 const static foo: number
10414 endclass
10415 var a = A.new()
10416 END
10417 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10418
10419 # Error case: 'const' cannot be used in an interface
10420 lines =<< trim END
10421 vim9script
10422 interface A
10423 const foo: number = 10
10424 endinterface
10425 END
10426 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10427
10428 # Error case: 'const' not supported for an object method
10429 lines =<< trim END
10430 vim9script
10431 class A
10432 const def Foo()
10433 enddef
10434 endclass
10435 END
10436 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10437
10438 # Error case: 'const' not supported for a class method
10439 lines =<< trim END
10440 vim9script
10441 class A
10442 static const def Foo()
10443 enddef
10444 endclass
10445 END
10446 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10447enddef
10448
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010449" Test for compiling class/object methods using :defcompile
10450def Test_defcompile_class()
10451 # defcompile all the classes in the current script
10452 var lines =<< trim END
10453 vim9script
10454 class A
10455 def Foo()
10456 var i = 10
10457 enddef
10458 endclass
10459 class B
10460 def Bar()
10461 var i = 20
10462 xxx
10463 enddef
10464 endclass
10465 defcompile
10466 END
10467 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10468
10469 # defcompile a specific class
10470 lines =<< trim END
10471 vim9script
10472 class A
10473 def Foo()
10474 xxx
10475 enddef
10476 endclass
10477 class B
10478 def Bar()
10479 yyy
10480 enddef
10481 endclass
10482 defcompile B
10483 END
10484 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10485
10486 # defcompile a non-class
10487 lines =<< trim END
10488 vim9script
10489 class A
10490 def Foo()
10491 enddef
10492 endclass
10493 var X: list<number> = []
10494 defcompile X
10495 END
10496 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10497
10498 # defcompile a class twice
10499 lines =<< trim END
10500 vim9script
10501 class A
10502 def new()
10503 enddef
10504 endclass
10505 defcompile A
10506 defcompile A
10507 assert_equal('Function A.new does not need compiling', v:statusmsg)
10508 END
10509 v9.CheckSourceSuccess(lines)
10510
10511 # defcompile should not compile an imported class
10512 lines =<< trim END
10513 vim9script
10514 export class A
10515 def Foo()
10516 xxx
10517 enddef
10518 endclass
10519 END
10520 writefile(lines, 'Xdefcompileimport.vim', 'D')
10521 lines =<< trim END
10522 vim9script
10523
10524 import './Xdefcompileimport.vim'
10525 class B
10526 endclass
10527 defcompile
10528 END
10529 v9.CheckScriptSuccess(lines)
10530enddef
10531
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010532" Test for cases common to all the object builtin methods
10533def Test_object_builtin_method()
10534 var lines =<< trim END
10535 vim9script
10536 class A
10537 def abc()
10538 enddef
10539 endclass
10540 END
10541 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10542
10543 for funcname in ["len", "string", "empty"]
10544 lines =<< trim eval END
10545 vim9script
10546 class A
10547 static def {funcname}(): number
10548 enddef
10549 endclass
10550 END
10551 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10552 endfor
10553enddef
10554
10555" Test for using the empty() builtin method with an object
10556" This is a legacy function to use the test_garbagecollect_now() function.
10557func Test_object_empty()
10558 let lines =<< trim END
10559 vim9script
10560 class A
10561 def empty(): bool
10562 return true
10563 enddef
10564 endclass
10565
10566 def Foo()
10567 var afoo = A.new()
10568 assert_equal(true, empty(afoo))
10569 assert_equal(true, afoo->empty())
10570 enddef
10571
10572 var a = A.new()
10573 assert_equal(1, empty(a))
10574 assert_equal(1, a->empty())
10575 test_garbagecollect_now()
10576 assert_equal(1, empty(a))
10577 Foo()
10578 test_garbagecollect_now()
10579 Foo()
10580 END
10581 call v9.CheckSourceSuccess(lines)
10582
10583 " empty() should return 1 without a builtin method
10584 let lines =<< trim END
10585 vim9script
10586 class A
10587 endclass
10588
10589 def Foo()
10590 var afoo = A.new()
10591 assert_equal(1, empty(afoo))
10592 enddef
10593
10594 var a = A.new()
10595 assert_equal(1, empty(a))
10596 Foo()
10597 END
10598 call v9.CheckSourceSuccess(lines)
10599
10600 " Unsupported signature for the empty() method
10601 let lines =<< trim END
10602 vim9script
10603 class A
10604 def empty()
10605 enddef
10606 endclass
10607 END
10608 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10609
10610 " Error when calling the empty() method
10611 let lines =<< trim END
10612 vim9script
10613 class A
10614 def empty(): bool
10615 throw "Failed to check emptiness"
10616 enddef
10617 endclass
10618
10619 def Foo()
10620 var afoo = A.new()
10621 var i = empty(afoo)
10622 enddef
10623
10624 var a = A.new()
10625 assert_fails('empty(a)', 'Failed to check emptiness')
10626 assert_fails('Foo()', 'Failed to check emptiness')
10627 END
10628 call v9.CheckSourceSuccess(lines)
10629
10630 " call empty() using an object from a script
10631 let lines =<< trim END
10632 vim9script
10633 class A
10634 def empty(): bool
10635 return true
10636 enddef
10637 endclass
10638 var afoo = A.new()
10639 assert_equal(true, afoo.empty())
10640 END
10641 call v9.CheckSourceSuccess(lines)
10642
10643 " call empty() using an object from a method
10644 let lines =<< trim END
10645 vim9script
10646 class A
10647 def empty(): bool
10648 return true
10649 enddef
10650 endclass
10651 def Foo()
10652 var afoo = A.new()
10653 assert_equal(true, afoo.empty())
10654 enddef
10655 Foo()
10656 END
10657 call v9.CheckSourceSuccess(lines)
10658
10659 " call empty() using "this" from an object method
10660 let lines =<< trim END
10661 vim9script
10662 class A
10663 def empty(): bool
10664 return true
10665 enddef
10666 def Foo(): bool
10667 return this.empty()
10668 enddef
10669 endclass
10670 def Bar()
10671 var abar = A.new()
10672 assert_equal(true, abar.Foo())
10673 enddef
10674 Bar()
10675 END
10676 call v9.CheckSourceSuccess(lines)
10677
10678 " Call empty() from a derived object
10679 let lines =<< trim END
10680 vim9script
10681 class A
10682 def empty(): bool
10683 return false
10684 enddef
10685 endclass
10686 class B extends A
10687 def empty(): bool
10688 return true
10689 enddef
10690 endclass
10691 def Foo(afoo: A)
10692 assert_equal(true, empty(afoo))
10693 var bfoo = B.new()
10694 assert_equal(true, empty(bfoo))
10695 enddef
10696 var b = B.new()
10697 assert_equal(1, empty(b))
10698 Foo(b)
10699 END
10700 call v9.CheckSourceSuccess(lines)
10701
10702 " Invoking empty method using an interface
10703 let lines =<< trim END
10704 vim9script
10705 interface A
10706 def empty(): bool
10707 endinterface
10708 class B implements A
10709 def empty(): bool
10710 return false
10711 enddef
10712 endclass
10713 def Foo(a: A)
10714 assert_equal(false, empty(a))
10715 enddef
10716 var b = B.new()
10717 Foo(b)
10718 END
10719 call v9.CheckSourceSuccess(lines)
10720endfunc
10721
10722" Test for using the len() builtin method with an object
10723" This is a legacy function to use the test_garbagecollect_now() function.
10724func Test_object_length()
10725 let lines =<< trim END
10726 vim9script
10727 class A
10728 var mylen: number = 0
10729 def new(n: number)
10730 this.mylen = n
10731 enddef
10732 def len(): number
10733 return this.mylen
10734 enddef
10735 endclass
10736
10737 def Foo()
10738 var afoo = A.new(12)
10739 assert_equal(12, len(afoo))
10740 assert_equal(12, afoo->len())
10741 enddef
10742
10743 var a = A.new(22)
10744 assert_equal(22, len(a))
10745 assert_equal(22, a->len())
10746 test_garbagecollect_now()
10747 assert_equal(22, len(a))
10748 Foo()
10749 test_garbagecollect_now()
10750 Foo()
10751 END
10752 call v9.CheckSourceSuccess(lines)
10753
10754 " len() should return 0 without a builtin method
10755 let lines =<< trim END
10756 vim9script
10757 class A
10758 endclass
10759
10760 def Foo()
10761 var afoo = A.new()
10762 assert_equal(0, len(afoo))
10763 enddef
10764
10765 var a = A.new()
10766 assert_equal(0, len(a))
10767 Foo()
10768 END
10769 call v9.CheckSourceSuccess(lines)
10770
10771 " Unsupported signature for the len() method
10772 let lines =<< trim END
10773 vim9script
10774 class A
10775 def len()
10776 enddef
10777 endclass
10778 END
10779 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10780
10781 " Error when calling the len() method
10782 let lines =<< trim END
10783 vim9script
10784 class A
10785 def len(): number
10786 throw "Failed to compute length"
10787 enddef
10788 endclass
10789
10790 def Foo()
10791 var afoo = A.new()
10792 var i = len(afoo)
10793 enddef
10794
10795 var a = A.new()
10796 assert_fails('len(a)', 'Failed to compute length')
10797 assert_fails('Foo()', 'Failed to compute length')
10798 END
10799 call v9.CheckSourceSuccess(lines)
10800
10801 " call len() using an object from a script
10802 let lines =<< trim END
10803 vim9script
10804 class A
10805 def len(): number
10806 return 5
10807 enddef
10808 endclass
10809 var afoo = A.new()
10810 assert_equal(5, afoo.len())
10811 END
10812 call v9.CheckSourceSuccess(lines)
10813
10814 " call len() using an object from a method
10815 let lines =<< trim END
10816 vim9script
10817 class A
10818 def len(): number
10819 return 5
10820 enddef
10821 endclass
10822 def Foo()
10823 var afoo = A.new()
10824 assert_equal(5, afoo.len())
10825 enddef
10826 Foo()
10827 END
10828 call v9.CheckSourceSuccess(lines)
10829
10830 " call len() using "this" from an object method
10831 let lines =<< trim END
10832 vim9script
10833 class A
10834 def len(): number
10835 return 8
10836 enddef
10837 def Foo(): number
10838 return this.len()
10839 enddef
10840 endclass
10841 def Bar()
10842 var abar = A.new()
10843 assert_equal(8, abar.Foo())
10844 enddef
10845 Bar()
10846 END
10847 call v9.CheckSourceSuccess(lines)
10848
10849 " Call len() from a derived object
10850 let lines =<< trim END
10851 vim9script
10852 class A
10853 def len(): number
10854 return 10
10855 enddef
10856 endclass
10857 class B extends A
10858 def len(): number
10859 return 20
10860 enddef
10861 endclass
10862 def Foo(afoo: A)
10863 assert_equal(20, len(afoo))
10864 var bfoo = B.new()
10865 assert_equal(20, len(bfoo))
10866 enddef
10867 var b = B.new()
10868 assert_equal(20, len(b))
10869 Foo(b)
10870 END
10871 call v9.CheckSourceSuccess(lines)
10872
10873 " Invoking len method using an interface
10874 let lines =<< trim END
10875 vim9script
10876 interface A
10877 def len(): number
10878 endinterface
10879 class B implements A
10880 def len(): number
10881 return 123
10882 enddef
10883 endclass
10884 def Foo(a: A)
10885 assert_equal(123, len(a))
10886 enddef
10887 var b = B.new()
10888 Foo(b)
10889 END
10890 call v9.CheckSourceSuccess(lines)
10891endfunc
10892
10893" Test for using the string() builtin method with an object
10894" This is a legacy function to use the test_garbagecollect_now() function.
10895func Test_object_string()
10896 let lines =<< trim END
10897 vim9script
10898 class A
10899 var name: string
10900 def string(): string
10901 return this.name
10902 enddef
10903 endclass
10904
10905 def Foo()
10906 var afoo = A.new("foo-A")
10907 assert_equal('foo-A', string(afoo))
10908 assert_equal('foo-A', afoo->string())
10909 enddef
10910
10911 var a = A.new("script-A")
10912 assert_equal('script-A', string(a))
10913 assert_equal('script-A', a->string())
10914 assert_equal(['script-A'], execute('echo a')->split("\n"))
10915 test_garbagecollect_now()
10916 assert_equal('script-A', string(a))
10917 Foo()
10918 test_garbagecollect_now()
10919 Foo()
10920 END
10921 call v9.CheckSourceSuccess(lines)
10922
10923 " string() should return "object of A {}" without a builtin method
10924 let lines =<< trim END
10925 vim9script
10926 class A
10927 endclass
10928
10929 def Foo()
10930 var afoo = A.new()
10931 assert_equal('object of A {}', string(afoo))
10932 enddef
10933
10934 var a = A.new()
10935 assert_equal('object of A {}', string(a))
10936 Foo()
10937 END
10938 call v9.CheckSourceSuccess(lines)
10939
10940 " Unsupported signature for the string() method
10941 let lines =<< trim END
10942 vim9script
10943 class A
10944 def string()
10945 enddef
10946 endclass
10947 END
10948 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
10949
10950 " Error when calling the string() method
10951 let lines =<< trim END
10952 vim9script
10953 class A
10954 def string(): string
10955 throw "Failed to get text"
10956 enddef
10957 endclass
10958
10959 def Foo()
10960 var afoo = A.new()
10961 var i = string(afoo)
10962 enddef
10963
10964 var a = A.new()
10965 assert_fails('string(a)', 'Failed to get text')
10966 assert_fails('Foo()', 'Failed to get text')
10967 END
10968 call v9.CheckSourceSuccess(lines)
10969
10970 " call string() using an object from a script
10971 let lines =<< trim END
10972 vim9script
10973 class A
10974 def string(): string
10975 return 'A'
10976 enddef
10977 endclass
10978 var afoo = A.new()
10979 assert_equal('A', afoo.string())
10980 END
10981 call v9.CheckSourceSuccess(lines)
10982
10983 " call string() using an object from a method
10984 let lines =<< trim END
10985 vim9script
10986 class A
10987 def string(): string
10988 return 'A'
10989 enddef
10990 endclass
10991 def Foo()
10992 var afoo = A.new()
10993 assert_equal('A', afoo.string())
10994 enddef
10995 Foo()
10996 END
10997 call v9.CheckSourceSuccess(lines)
10998
10999 " call string() using "this" from an object method
11000 let lines =<< trim END
11001 vim9script
11002 class A
11003 def string(): string
11004 return 'A'
11005 enddef
11006 def Foo(): string
11007 return this.string()
11008 enddef
11009 endclass
11010 def Bar()
11011 var abar = A.new()
11012 assert_equal('A', abar.string())
11013 enddef
11014 Bar()
11015 END
11016 call v9.CheckSourceSuccess(lines)
11017
11018 " Call string() from a derived object
11019 let lines =<< trim END
11020 vim9script
11021 class A
11022 def string(): string
11023 return 'A'
11024 enddef
11025 endclass
11026 class B extends A
11027 def string(): string
11028 return 'B'
11029 enddef
11030 endclass
11031 def Foo(afoo: A)
11032 assert_equal('B', string(afoo))
11033 var bfoo = B.new()
11034 assert_equal('B', string(bfoo))
11035 enddef
11036 var b = B.new()
11037 assert_equal('B', string(b))
11038 Foo(b)
11039 END
11040 call v9.CheckSourceSuccess(lines)
11041
11042 " Invoking string method using an interface
11043 let lines =<< trim END
11044 vim9script
11045 interface A
11046 def string(): string
11047 endinterface
11048 class B implements A
11049 def string(): string
11050 return 'B'
11051 enddef
11052 endclass
11053 def Foo(a: A)
11054 assert_equal('B', string(a))
11055 enddef
11056 var b = B.new()
11057 Foo(b)
11058 END
11059 call v9.CheckSourceSuccess(lines)
11060endfunc
11061
Ernie Rael9d779c52024-07-07 20:41:44 +020011062" Test for using the string() builtin method with an object's method
11063def Test_method_string()
11064 var lines =<< trim END
11065 vim9script
11066 class A
11067 def F()
11068 enddef
11069 endclass
11070 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
11071 END
11072 v9.CheckScriptSuccess(lines)
11073enddef
11074
11075
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010011076" Test for using a class in the class definition
11077def Test_Ref_Class_Within_Same_Class()
11078 var lines =<< trim END
11079 vim9script
11080 class A
11081 var n: number = 0
11082 def Equals(other: A): bool
11083 return this.n == other.n
11084 enddef
11085 endclass
11086
11087 var a1 = A.new(10)
11088 var a2 = A.new(10)
11089 var a3 = A.new(20)
11090 assert_equal(true, a1.Equals(a2))
11091 assert_equal(false, a2.Equals(a3))
11092 END
11093 v9.CheckScriptSuccess(lines)
11094
11095 lines =<< trim END
11096 vim9script
11097
11098 class Foo
11099 var num: number
11100 def Clone(): Foo
11101 return Foo.new(this.num)
11102 enddef
11103 endclass
11104
11105 var f1 = Foo.new(1)
11106
11107 def F()
11108 var f2: Foo = f1.Clone()
11109 assert_equal(false, f2 is f1)
11110 assert_equal(true, f2.num == f1.num)
11111 enddef
11112 F()
11113
11114 var f3: Foo = f1.Clone()
11115 assert_equal(false, f3 is f1)
11116 assert_equal(true, f3.num == f1.num)
11117 END
11118 v9.CheckScriptSuccess(lines)
11119
11120 # Test for trying to use a class to extend when defining the same class
11121 lines =<< trim END
11122 vim9script
11123 class A extends A
11124 endclass
11125 END
11126 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
11127
11128 # Test for trying to use a class to implement when defining the same class
11129 lines =<< trim END
11130 vim9script
11131 class A implements A
11132 endclass
11133 END
11134 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
11135enddef
11136
Ernie Raelf0e69142024-06-22 11:12:00 +020011137" Test for comparing a class referencing itself
11138def Test_Object_Compare_With_Recursive_Class_Ref()
11139 var lines =<< trim END
11140 vim9script
11141
11142 class C
11143 public var nest: C
11144 endclass
11145
11146 var o1 = C.new()
11147 o1.nest = o1
11148
11149 var result = o1 == o1
11150 assert_equal(true, result)
11151 END
11152 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020011153
11154 lines =<< trim END
11155 vim9script
11156
11157 class C
11158 public var nest: C
11159 endclass
11160 var o1 = C.new()
11161 var o2 = C.new(C.new())
11162
11163 var result = o1 == o2
11164 assert_equal(false, result)
11165 END
11166 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020011167
11168 lines =<< trim END
11169 vim9script
11170 class C
11171 var nest1: C
11172 var nest2: C
11173 def Init(n1: C, n2: C)
11174 this.nest1 = n1
11175 this.nest2 = n2
11176 enddef
11177 endclass
11178
11179 var o1 = C.new()
11180 var o2 = C.new()
11181 o1.Init(o1, o2)
11182 o2.Init(o2, o1)
11183
11184 var result = o1 == o2
11185 assert_equal(true, result)
11186 END
11187 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020011188enddef
11189
Ernie Raelf3975492024-07-06 11:44:37 +020011190" Test for comparing a class with nesting objects
11191def Test_Object_Compare_With_Nesting_Objects()
11192 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
11193 # return the compare is equal.
11194 # Test that limit
11195
11196 var lines =<< trim END
11197 vim9script
11198 class C
11199 public var n: number
11200 public var nest: C
11201
11202 # Create a "C" that chains/nests to indicated depth.
11203 # return {head: firstC, tail: lastC}
11204 static def CreateNested(depth: number): dict<C>
11205 var first = C.new(1, null_object)
11206 var last = first
11207 for i in range(2, depth)
11208 last.nest = C.new(i, null_object)
11209 last = last.nest
11210 endfor
11211 return {head: first, tail: last}
11212 enddef
11213
11214 # Return pointer to nth item in chain.
11215 def GetLink(depth: number): C
11216 var count = 1
11217 var p: C = this
11218 while count < depth
11219 p = p.nest
11220 if p == null
11221 throw "too deep"
11222 endif
11223 count += 1
11224 endwhile
11225 return p
11226 enddef
11227
11228 # Return the length of the chain
11229 def len(): number
11230 var count = 1
11231 var p: C = this
11232 while p.nest != null
11233 p = p.nest
11234 count += 1
11235 endwhile
11236 return count
11237 enddef
11238 endclass
11239
11240 var chain = C.CreateNested(3)
11241 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
11242 assert_equal(s, string(chain.head))
11243 assert_equal(3, chain.head->len())
11244
11245 var chain1 = C.CreateNested(100)
11246 var chain2 = C.CreateNested(100)
11247 assert_true(chain1.head == chain2.head)
11248
11249 # modify the tail of chain2, compare not equal
11250 chain2.tail.n = 123456
11251 assert_true(chain1.head != chain2.head)
11252
11253 # a tail of a different length compares not equal
11254 chain2 = C.CreateNested(101)
11255 assert_true(chain1.head != chain2.head)
11256
11257 chain1 = C.CreateNested(1000)
11258 chain2 = C.CreateNested(1000)
11259 assert_true(chain1.head == chain2.head)
11260
11261 # modify the tail of chain2, compare not equal
11262 chain2.tail.n = 123456
11263 assert_true(chain1.head != chain2.head)
11264
11265 # try a chain longer that the limit
11266 chain1 = C.CreateNested(1001)
11267 chain2 = C.CreateNested(1001)
11268 assert_true(chain1.head == chain2.head)
11269
11270 # modify the tail, but still equal
11271 chain2.tail.n = 123456
11272 assert_true(chain1.head == chain2.head)
11273
11274 # remove 2 items from front, shorten the chain by two.
11275 chain1.head = chain1.head.GetLink(3)
11276 chain2.head = chain2.head.GetLink(3)
11277 assert_equal(3, chain1.head.n)
11278 assert_equal(3, chain2.head.n)
11279 assert_equal(999, chain1.head->len())
11280 assert_equal(999, chain2.head->len())
11281 # Now less than the limit, compare not equal
11282 assert_true(chain1.head != chain2.head)
11283 END
11284 v9.CheckScriptSuccess(lines)
11285enddef
11286
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011287" Test for using a compound operator from a lambda function in an object method
11288def Test_compound_op_in_objmethod_lambda()
11289 # Test using the "+=" operator
11290 var lines =<< trim END
11291 vim9script
11292 class A
11293 var n: number = 10
11294 def Foo()
11295 var Fn = () => {
11296 this.n += 1
11297 }
11298 Fn()
11299 enddef
11300 endclass
11301
11302 var a = A.new()
11303 a.Foo()
11304 assert_equal(11, a.n)
11305 END
11306 v9.CheckScriptSuccess(lines)
11307
11308 # Test using the "..=" operator
11309 lines =<< trim END
11310 vim9script
11311 class A
11312 var s: string = "a"
11313 def Foo()
11314 var Fn = () => {
11315 this.s ..= "a"
11316 }
11317 Fn()
11318 enddef
11319 endclass
11320
11321 var a = A.new()
11322 a.Foo()
11323 a.Foo()
11324 assert_equal("aaa", a.s)
11325 END
11326 v9.CheckScriptSuccess(lines)
11327enddef
11328
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011329" Test for using test_refcount() with a class and an object
11330def Test_class_object_refcount()
11331 var lines =<< trim END
11332 vim9script
11333 class A
11334 endclass
11335 var a: A = A.new()
11336 assert_equal(2, test_refcount(A))
11337 assert_equal(1, test_refcount(a))
11338 var b = a
11339 assert_equal(2, test_refcount(A))
11340 assert_equal(2, test_refcount(a))
11341 assert_equal(2, test_refcount(b))
11342 END
11343 v9.CheckScriptSuccess(lines)
11344enddef
11345
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010011346" call a lambda function in one object from another object
11347def Test_lambda_invocation_across_classes()
11348 var lines =<< trim END
11349 vim9script
11350 class A
11351 var s: string = "foo"
11352 def GetFn(): func
11353 var Fn = (): string => {
11354 return this.s
11355 }
11356 return Fn
11357 enddef
11358 endclass
11359
11360 class B
11361 var s: string = "bar"
11362 def GetFn(): func
11363 var a = A.new()
11364 return a.GetFn()
11365 enddef
11366 endclass
11367
11368 var b = B.new()
11369 var Fn = b.GetFn()
11370 assert_equal("foo", Fn())
11371 END
11372 v9.CheckScriptSuccess(lines)
11373enddef
11374
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010011375" Test for using a class member which is an object of the current class
11376def Test_current_class_object_class_member()
11377 var lines =<< trim END
11378 vim9script
11379 class A
11380 public static var obj1: A = A.new(10)
11381 var n: number
11382 endclass
11383 defcompile
11384 assert_equal(10, A.obj1.n)
11385 END
11386 v9.CheckScriptSuccess(lines)
11387enddef
11388
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011389" Test for updating a base class variable from a base class method without the
11390" class name. This used to crash Vim (Github issue #14352).
11391def Test_use_base_class_variable_from_base_class_method()
11392 var lines =<< trim END
11393 vim9script
11394
11395 class DictKeyClass
11396 static var _obj_id_count = 1
11397 def _GenerateKey()
11398 _obj_id_count += 1
11399 enddef
11400 static def GetIdCount(): number
11401 return _obj_id_count
11402 enddef
11403 endclass
11404
11405 class C extends DictKeyClass
11406 def F()
11407 this._GenerateKey()
11408 enddef
11409 endclass
11410
11411 C.new().F()
11412 assert_equal(2, DictKeyClass.GetIdCount())
11413 END
11414 v9.CheckScriptSuccess(lines)
11415enddef
11416
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011417" Test for accessing protected funcref object and class variables
11418def Test_protected_funcref()
11419 # protected funcref object variable
11420 var lines =<< trim END
11421 vim9script
11422 class Test1
11423 const _Id: func(any): any = (v) => v
11424 endclass
11425 var n = Test1.new()._Id(1)
11426 END
11427 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11428
11429 # protected funcref class variable
11430 lines =<< trim END
11431 vim9script
11432 class Test2
11433 static const _Id: func(any): any = (v) => v
11434 endclass
11435 var n = Test2._Id(2)
11436 END
11437 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11438enddef
11439
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011440" Test for using lambda block in classes
11441def Test_lambda_block_in_class()
11442 # This used to crash Vim
11443 var lines =<< trim END
11444 vim9script
11445 class IdClass1
11446 const Id: func(number): number = (num: number): number => {
11447 # Return a ID
11448 return num * 10
11449 }
11450 endclass
11451 var id = IdClass1.new()
11452 assert_equal(20, id.Id(2))
11453 END
11454 v9.CheckScriptSuccess(lines)
11455
11456 # This used to crash Vim
11457 lines =<< trim END
11458 vim9script
11459 class IdClass2
11460 static const Id: func(number): number = (num: number): number => {
11461 # Return a ID
11462 return num * 2
11463 }
11464 endclass
11465 assert_equal(16, IdClass2.Id(8))
11466 END
11467 v9.CheckScriptSuccess(lines)
11468enddef
11469
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011470" Test for defcompiling an abstract method
11471def Test_abstract_method_defcompile()
11472 # Compile an abstract class with abstract object methods
11473 var lines =<< trim END
11474 vim9script
11475 abstract class A
11476 abstract def Foo(): string
11477 abstract def Bar(): list<string>
11478 endclass
11479 defcompile
11480 END
11481 v9.CheckScriptSuccess(lines)
11482
11483 # Compile a concrete object method in an abstract class
11484 lines =<< trim END
11485 vim9script
11486 abstract class A
11487 abstract def Foo(): string
11488 abstract def Bar(): list<string>
11489 def Baz(): string
11490 pass
11491 enddef
11492 endclass
11493 defcompile
11494 END
11495 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11496
11497 # Compile a concrete class method in an abstract class
11498 lines =<< trim END
11499 vim9script
11500 abstract class A
11501 abstract def Foo(): string
11502 abstract def Bar(): list<string>
11503 static def Baz(): string
11504 pass
11505 enddef
11506 endclass
11507 defcompile
11508 END
11509 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11510enddef
11511
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011512" Test for defining a class in a function
11513def Test_class_definition_in_a_function()
11514 var lines =<< trim END
11515 vim9script
11516 def Foo()
11517 class A
11518 endclass
11519 enddef
11520 defcompile
11521 END
11522 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11523enddef
11524
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011525" Test for using [] with a class and an object
11526def Test_class_object_index()
11527 var lines =<< trim END
11528 vim9script
11529 class A
11530 endclass
11531 A[10] = 1
11532 END
11533 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11534
11535 lines =<< trim END
11536 vim9script
11537 class A
11538 endclass
11539 var a = A.new()
11540 a[10] = 1
11541 END
11542 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11543enddef
11544
LemonBoyf4af3312024-07-04 13:43:12 +020011545def Test_class_member_init_typecheck()
11546 # Ensure the class member is assigned its declared type.
11547 var lines =<< trim END
11548 vim9script
11549 class S
11550 static var l: list<string> = []
11551 endclass
11552 S.l->add(123)
11553 END
11554 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11555
11556 # Ensure the initializer value and the declared type match.
11557 lines =<< trim END
11558 vim9script
11559 class S
11560 var l: list<string> = [1, 2, 3]
11561 endclass
11562 var o = S.new()
11563 END
11564 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11565
11566 # Ensure the class member is assigned its declared type.
11567 lines =<< trim END
11568 vim9script
11569 class S
11570 var l: list<string> = []
11571 endclass
11572 var o = S.new()
11573 o.l->add(123)
11574 END
11575 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11576enddef
11577
LemonBoy50d48542024-07-04 17:03:17 +020011578def Test_class_cast()
11579 var lines =<< trim END
11580 vim9script
11581 class A
11582 endclass
11583 class B extends A
11584 var mylen: number
11585 endclass
11586 def F(o: A): number
11587 return (<B>o).mylen
11588 enddef
11589
11590 defcompile F
11591 END
11592 v9.CheckScriptSuccess(lines)
11593enddef
11594
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011595" Test for using a variable of type "any" with an object
11596def Test_any_obj_var_type()
11597 var lines =<< trim END
11598 vim9script
11599 class A
11600 var name: string = "foobar"
11601 def Foo(): string
11602 return "func foo"
11603 enddef
11604 endclass
11605
11606 def CheckVals(x: any)
11607 assert_equal("foobar", x.name)
11608 assert_equal("func foo", x.Foo())
11609 enddef
11610
11611 var a = A.new()
11612 CheckVals(a)
11613 END
11614 v9.CheckScriptSuccess(lines)
11615
11616 # Try to set a non-existing variable
11617 lines =<< trim END
11618 vim9script
11619 class A
11620 var name: string = "foobar"
11621 endclass
11622
11623 def SetNonExistingVar(x: any)
11624 x.bar = [1, 2, 3]
11625 enddef
11626
11627 var a = A.new()
11628 SetNonExistingVar(a)
11629 END
11630 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11631
11632 # Try to read a non-existing variable
11633 lines =<< trim END
11634 vim9script
11635 class A
11636 var name: string = "foobar"
11637 endclass
11638
11639 def GetNonExistingVar(x: any)
11640 var i: dict<any> = x.bar
11641 enddef
11642
11643 var a = A.new()
11644 GetNonExistingVar(a)
11645 END
11646 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11647
11648 # Try to invoke a non-existing method
11649 lines =<< trim END
11650 vim9script
11651 class A
11652 def Foo(): number
11653 return 10
11654 enddef
11655 endclass
11656
11657 def CallNonExistingMethod(x: any)
11658 var i: number = x.Bar()
11659 enddef
11660
11661 var a = A.new()
11662 CallNonExistingMethod(a)
11663 END
11664 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11665
11666 # Use an object which is a Dict value
11667 lines =<< trim END
11668 vim9script
11669 class Foo
11670 def Bar(): number
11671 return 369
11672 enddef
11673 endclass
11674
11675 def GetValue(FooDict: dict<any>): number
11676 var n: number = 0
11677 for foo in values(FooDict)
11678 n += foo.Bar()
11679 endfor
11680 return n
11681 enddef
11682
11683 var d = {'x': Foo.new()}
11684 assert_equal(369, GetValue(d))
11685 END
11686 v9.CheckScriptSuccess(lines)
11687
zeertzjqd32bf0a2024-12-17 20:55:13 +010011688 # Nested data. Object containing a Dict containing another Object.
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011689 lines =<< trim END
11690 vim9script
11691 class Context
11692 public var state: dict<any> = {}
11693 endclass
11694
11695 class Metadata
11696 public var value = 0
11697 endclass
11698
11699 var ctx = Context.new()
11700 ctx.state["meta"] = Metadata.new(2468)
11701
11702 const foo = ctx.state.meta.value
11703
11704 def F(): number
11705 const bar = ctx.state.meta.value
11706 return bar
11707 enddef
11708
11709 assert_equal(2468, F())
11710 END
11711 v9.CheckScriptSuccess(lines)
11712
11713 # Accessing an object from a method inside the class using any type
11714 lines =<< trim END
11715 vim9script
11716 class C
11717 def _G(): string
11718 return '_G'
11719 enddef
11720 static def S(o_any: any): string
11721 return o_any._G()
11722 enddef
11723 endclass
11724
11725 var o1 = C.new()
11726 assert_equal('_G', C.S(o1))
11727 END
11728 v9.CheckScriptSuccess(lines)
11729
11730 # Modifying an object private variable from a method in another class using
11731 # any type
11732 lines =<< trim END
11733 vim9script
11734
11735 class A
11736 var num = 10
11737 endclass
11738
11739 class B
11740 def SetVal(x: any)
11741 x.num = 20
11742 enddef
11743 endclass
11744
11745 var a = A.new()
11746 var b = B.new()
11747 b.SetVal(a)
11748 END
11749 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11750
11751 # Accessing a object protected variable from a method in another class using
11752 # any type
11753 lines =<< trim END
11754 vim9script
11755
11756 class A
11757 var _num = 10
11758 endclass
11759
11760 class B
11761 def GetVal(x: any): number
11762 return x._num
11763 enddef
11764 endclass
11765
11766 var a = A.new()
11767 var b = B.new()
11768 var i = b.GetVal(a)
11769 END
11770 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11771
11772 # Accessing an object returned from an imported function and class
11773 lines =<< trim END
11774 vim9script
11775 export class Foo
11776 public var name: string
11777 endclass
11778
11779 export def ReturnFooObject(): Foo
11780 var r = Foo.new('star')
11781 return r
11782 enddef
11783 END
11784 writefile(lines, 'Xanyvar1.vim', 'D')
11785
11786 lines =<< trim END
11787 vim9script
11788
11789 import './Xanyvar1.vim'
11790
11791 def GetName(): string
11792 var whatever = Xanyvar1.ReturnFooObject()
11793 return whatever.name
11794 enddef
11795
11796 assert_equal('star', GetName())
11797 END
11798 v9.CheckScriptSuccess(lines)
11799
11800 # Try to modify a private object variable using a variable of type "any"
11801 lines =<< trim END
11802 vim9script
11803
11804 class Foo
11805 var n: number = 10
11806 endclass
11807 def Fn(x: any)
11808 x.n = 20
11809 enddef
11810 var a = Foo.new()
11811 Fn(a)
11812 END
11813 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11814
11815 # Try to read a protected object variable using a variable of type "any"
11816 lines =<< trim END
11817 vim9script
11818
11819 class Foo
11820 var _n: number = 10
11821 endclass
11822 def Fn(x: any): number
11823 return x._n
11824 enddef
11825
11826 var a = Foo.new()
11827 Fn(a)
11828 END
11829 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11830
11831 # Read a protected object variable using a variable of type "any" in an object
11832 # method
11833 lines =<< trim END
11834 vim9script
11835
11836 class Foo
11837 var _n: number = 10
11838 def Fn(x: any): number
11839 return x._n
11840 enddef
11841 endclass
11842
11843 var a = Foo.new()
11844 assert_equal(10, a.Fn(a))
11845 END
11846 v9.CheckScriptSuccess(lines)
11847
11848 # Try to call a protected object method using a "any" type variable
11849 lines =<< trim END
11850 vim9script
11851
11852 class Foo
11853 def _GetVal(): number
11854 return 234
11855 enddef
11856 endclass
11857 def Fn(x: any): number
11858 return x._GetVal()
11859 enddef
11860
11861 var a = Foo.new()
11862 Fn(a)
11863 END
11864 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11865
11866 # Call a protected object method using a "any" type variable from another
11867 # object method
11868 lines =<< trim END
11869 vim9script
11870
11871 class Foo
11872 def _GetVal(): number
11873 return 234
11874 enddef
11875 def FooVal(x: any): number
11876 return x._GetVal()
11877 enddef
11878 endclass
11879
11880 var a = Foo.new()
11881 assert_equal(234, a.FooVal(a))
11882 END
11883 v9.CheckScriptSuccess(lines)
11884
11885 # Method chaining
11886 lines =<< trim END
11887 vim9script
11888
11889 export class T
11890 var id: number = 268
11891 def F(): any
11892 return this
11893 enddef
11894 endclass
11895
11896 def H()
11897 var a = T.new().F().F()
11898 assert_equal(268, a.id)
11899 enddef
11900 H()
11901
11902 var b: T = T.new().F().F()
11903 assert_equal(268, b.id)
11904 END
11905 v9.CheckScriptSuccess(lines)
11906
11907 # Using a null object to access a member variable
11908 lines =<< trim END
11909 vim9script
11910 def Fn(x: any): number
11911 return x.num
11912 enddef
11913
11914 Fn(null_object)
11915 END
11916 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11917
11918 # Using a null object to invoke a method
11919 lines =<< trim END
11920 vim9script
11921 def Fn(x: any)
11922 x.Foo()
11923 enddef
11924
11925 Fn(null_object)
11926 END
11927 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
Yegappan Lakshmanane7984462024-11-12 21:03:00 +010011928
11929 # Try to change a const object variable using a "any" variable
11930 lines =<< trim END
11931 vim9script
11932 class A
11933 public const v1: number = 123
11934 endclass
11935
11936 def Fn(o: any)
11937 o.v1 = 321
11938 enddef
11939
11940 var a = A.new()
11941 Fn(a)
11942 END
11943 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11944
11945 # Try to change a final object variable using a "any" variable
11946 lines =<< trim END
11947 vim9script
11948 class A
11949 public final v1: number = 123
11950 endclass
11951
11952 def Fn(o: any)
11953 o.v1 = 321
11954 enddef
11955
11956 var a = A.new()
11957 Fn(a)
11958 END
11959 v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1)
11960
11961 # Assign a different type of value to an "any" type object variable
11962 lines =<< trim END
11963 vim9script
11964 class A
11965 public var v1: list<any> = [1, 2]
11966 endclass
11967
11968 def Fn(o: A)
11969 o.v1 = 'abc'
11970 enddef
11971
11972 var a = A.new()
11973 Fn(a)
11974 END
11975 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 1)
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011976enddef
11977
Yegappan Lakshmanan481992c2024-12-06 18:35:12 +010011978" Test for using an object method with mapnew()
11979def Test_mapnew_with_instance_method()
11980 var lines =<< trim END
11981 vim9script
11982
11983 class Foo
11984 var str: string
11985 var nums: list<number> = [1, 2, 3]
11986
11987 def InstanceMethod(n: number): string
11988 return this.str .. n
11989 enddef
11990
11991 def MapperMethod(idx: number, elem: number): string
11992 return elem->this.InstanceMethod()
11993 enddef
11994
11995 def MapTest()
11996 this.str = "foo"
11997 var l = ['foo1', 'foo2', 'foo3']
11998 assert_equal(l, this.nums->mapnew(this.MapperMethod))
11999 enddef
12000 endclass
12001
12002 Foo.new().MapTest()
12003 END
12004 v9.CheckSourceSuccess(lines)
12005
12006 # Error in the mapnew() function
12007 lines =<< trim END
12008 vim9script
12009
12010 class Foo
12011 var str: string
12012 var nums: list<number> = [1, 2, 3]
12013
12014 def InstanceMethod(n: number): string
12015 throw "InstanceMethod failed"
12016 enddef
12017
12018 def MapperMethod(idx: number, elem: number): string
12019 return elem->this.InstanceMethod()
12020 enddef
12021
12022 def MapTest()
12023 this.str = "foo"
12024 var caught_exception: bool = false
12025 try
12026 this.nums->mapnew(this.MapperMethod)
12027 catch /InstanceMethod failed/
12028 caught_exception = true
12029 endtry
12030 assert_true(caught_exception)
12031 enddef
12032 endclass
12033
12034 Foo.new().MapTest()
12035 END
12036 v9.CheckSourceSuccess(lines)
12037enddef
12038
Yegappan Lakshmananb0206e92024-12-30 09:52:16 +010012039" Test for using an object method in a method call.
12040def Test_use_object_method_in_a_method_call()
12041 var lines =<< trim END
12042 vim9script
12043
12044 class Foo
12045 def Cost(nums: list<number>): number
12046 return nums[0] * nums[1]
12047 enddef
12048
12049 def ShowCost(): string
12050 var g = [4, 5]
12051 return $"Cost is: {g->this.Cost()}"
12052 enddef
12053 endclass
12054
12055 var d = Foo.new()
12056 assert_equal('Cost is: 20', d.ShowCost())
12057 END
12058 v9.CheckSourceSuccess(lines)
12059
12060 # Test for using a non-existing object method in string interpolation
12061 lines =<< trim END
12062 vim9script
12063
12064 class Foo
12065 def Cost(nums: list<number>): number
12066 return nums[0] * nums[1]
12067 enddef
12068
12069 def ShowCost(): string
12070 var g = [4, 5]
12071 echo $"Cost is: {g->this.NewCost()}"
12072 enddef
12073 endclass
12074
12075 var d = Foo.new()
12076 d.ShowCost()
12077 END
12078 v9.CheckSourceFailure(lines, 'E1326: Variable "NewCost" not found in object "Foo"')
12079enddef
12080
Yegappan Lakshmananb04af4c2025-01-03 10:50:08 +010012081" Test for referencing an object variable which is not yet initialized
12082def Test_uninitialized_object_var()
12083 var lines =<< trim END
12084 vim9script
12085 class Foo
12086 const two: number = Foo.Two(this)
12087 const one: number = 1
12088
12089 static def Two(that: Foo): number
12090 return that.one + 2
12091 enddef
12092 endclass
12093
12094 echo Foo.Two(Foo.new())
12095 END
12096 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'one' referenced")
12097
12098 lines =<< trim END
12099 vim9script
12100 class Foo
12101 const one: number = Foo.One(this)
12102
12103 static def One(that: Foo): number
12104 return 1
12105 enddef
12106 endclass
12107
12108 assert_equal(1, Foo.One(Foo.new()))
12109 END
12110 v9.CheckSourceSuccess(lines)
12111
12112 lines =<< trim END
12113 vim9script
12114 class Foo
12115 const one: number = 1
12116 const two: number = Foo.Two(this)
12117
12118 static def Two(that: Foo): number
12119 return that.one + 1
12120 enddef
12121 endclass
12122
12123 assert_equal(2, Foo.Two(Foo.new()))
12124 END
12125 v9.CheckSourceSuccess(lines)
12126
12127 lines =<< trim END
12128 vim9script
12129 class Foo
12130 const Id: func(any): any = ((_) => (v) => v)(this)
12131
12132 static def Id(that: Foo): func(any): any
12133 return that.Id
12134 enddef
12135 endclass
12136
12137 assert_equal(5, Foo.Id(Foo.new())(5))
12138 assert_equal(7, Foo.new().Id(7))
12139 END
12140 v9.CheckSourceSuccess(lines)
12141
12142 lines =<< trim END
12143 vim9script
12144 class Foo
12145 const Id: func(any): any = ((that) => (_) => that)(this)
12146
12147 static def Id(that: Foo): func(any): any
12148 return that.Id
12149 enddef
12150 endclass
12151
12152 const Id0: func(any): any = Foo.Id(Foo.new())
12153 const Id1: func(any): any = Foo.new().Id
12154 END
12155 v9.CheckSourceSuccess(lines)
12156
12157 lines =<< trim END
12158 vim9script
12159 class Foo
12160 const Id: any = Foo.Id(this)
12161
12162 static def Id(that: Foo): any
12163 return that.Id
12164 enddef
12165 endclass
12166
12167 const Id2: any = Foo.Id(Foo.new())
12168 const Id3: any = Foo.new().Id
12169 END
12170 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'Id' referenced")
12171
12172 lines =<< trim END
12173 vim9script
12174
12175 class Foo
12176 var x: string = ''
12177 var Y: func(): string = () => this.x
12178 endclass
12179
12180 var foo = Foo.new('ok')
12181 assert_equal('ok', foo.Y())
12182 END
12183 v9.CheckSourceSuccess(lines)
12184
12185 lines =<< trim END
12186 vim9script
12187
12188 class Foo
12189 var x: string = this.x
12190 endclass
12191
12192 var foo = Foo.new('ok')
12193 END
12194 v9.CheckSourceFailure(lines, "E1430: Uninitialized object variable 'x' referenced")
12195enddef
12196
Yegappan Lakshmanan2050dcc2025-01-06 18:34:49 +010012197" Test for initializing member variables of compound type in the constructor
12198def Test_constructor_init_compound_member_var()
12199 var lines =<< trim END
12200 vim9script
12201
12202 class Foo
12203 var v1: string = "aaa"
12204 var v2: list<number> = [1, 2]
12205 var v3: dict<string> = {a: 'a', b: 'b'}
12206 endclass
12207
12208 class Bar
12209 var v4: string = "bbb"
12210 var v5: Foo = Foo.new()
12211 var v6: list<number> = [1, 2]
12212 endclass
12213
12214 var b: Bar = Bar.new()
12215 assert_equal("aaa", b.v5.v1)
12216 assert_equal([1, 2], b.v5.v2)
12217 assert_equal({a: 'a', b: 'b'}, b.v5.v3)
12218 assert_equal("bbb", b.v4)
12219 assert_equal([1, 2], b.v6)
12220 END
12221 v9.CheckSourceSuccess(lines)
12222enddef
12223
Yegappan Lakshmanan68d08582025-02-09 19:39:52 +010012224" Test for using a concrete method in an abstract extended class which is
12225" further extended
12226def Test_abstract_method_across_hierarchy()
12227 var lines =<< trim END
12228 vim9script
12229
12230 abstract class A
12231 abstract def Foo(): string
12232 endclass
12233
12234 abstract class B extends A
12235 abstract def Bar(): string
12236 endclass
12237
12238 class C extends B
12239 def Foo(): string
12240 return 'foo'
12241 enddef
12242
12243 def Bar(): string
12244 return 'bar'
12245 enddef
12246 endclass
12247
12248 def Fn1(a: A): string
12249 return a.Foo()
12250 enddef
12251
12252 def Fn2(b: B): string
12253 return b.Bar()
12254 enddef
12255
12256 var c = C.new()
12257 assert_equal('foo', Fn1(c))
12258 assert_equal('bar', Fn2(c))
12259 END
12260 v9.CheckSourceSuccess(lines)
12261
12262 lines =<< trim END
12263 vim9script
12264
12265 abstract class A
12266 abstract def Foo(): string
12267 endclass
12268
12269 abstract class B extends A
12270 abstract def Bar(): string
12271 endclass
12272
12273 class C extends B
12274 def Bar(): string
12275 return 'bar'
12276 enddef
12277 endclass
12278
12279 defcompile
12280 END
12281 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
12282
12283 lines =<< trim END
12284 vim9script
12285
12286 abstract class A
12287 abstract def M1(): string
12288 abstract def M2(): string
12289 endclass
12290
12291 abstract class B extends A
12292 def M1(): string
12293 return 'B: M1'
12294 enddef
12295
12296 def M2(): string
12297 return 'B: M2'
12298 enddef
12299 endclass
12300
12301 class C1 extends B
12302 def M1(): string
12303 return 'C1: M1'
12304 enddef
12305 endclass
12306
12307 class C2 extends B
12308 def M2(): string
12309 return 'C2: M2'
12310 enddef
12311 endclass
12312
12313 class D1 extends C1
12314 endclass
12315
12316 class D2 extends C2
12317 endclass
12318
12319 var l: list<string> = []
12320 for Type in ['C1', 'C2', 'D1', 'D2']
12321 l->add(eval($'{Type}.new().M1()'))
12322 l->add(eval($'{Type}.new().M2()'))
12323 endfor
12324 assert_equal(['C1: M1', 'B: M2', 'B: M1', 'C2: M2', 'C1: M1', 'B: M2', 'B: M1', 'C2: M2'], l)
12325 END
12326 v9.CheckSourceSuccess(lines)
12327
12328 lines =<< trim END
12329 vim9script
12330
12331 abstract class A
12332 abstract def M1(): string
12333 abstract def M2(): string
12334 endclass
12335
12336 class B extends A
12337 def M1(): string
12338 return 'B: M1'
12339 enddef
12340
12341 def M2(): string
12342 return 'B: M2'
12343 enddef
12344 endclass
12345
12346 abstract class C extends B
12347 endclass
12348
12349 class D1 extends C
12350 def M1(): string
12351 return 'D1: M1'
12352 enddef
12353 endclass
12354
12355 class D2 extends C
12356 def M2(): string
12357 return 'D2: M2'
12358 enddef
12359 endclass
12360
12361 class E1 extends D1
12362 endclass
12363
12364 class E2 extends D2
12365 endclass
12366
12367 var l: list<string> = []
12368 for Type in ['B', 'D1', 'D2', 'E1', 'E2']
12369 l->add(eval($'{Type}.new().M1()'))
12370 l->add( eval($'{Type}.new().M2()'))
12371 endfor
12372 assert_equal(['B: M1', 'B: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2'], l)
12373 END
12374 v9.CheckSourceSuccess(lines)
12375enddef
12376
Yegappan Lakshmanan7e898002025-02-11 22:07:05 +010012377" Test for using a protected new() method (singleton design pattern)
12378def Test_protected_new_method()
12379 var lines =<< trim END
12380 vim9script
12381 class A
12382 def _new()
12383 enddef
12384 endclass
12385 var a = A.new()
12386 END
12387 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "A"', 6)
12388
12389 lines =<< trim END
12390 vim9script
12391 class A
12392 static var _instance: A
12393 var str: string
12394 def _new(str: string)
12395 this.str = str
12396 enddef
12397 static def GetInstance(str: string): A
12398 if _instance == null
12399 _instance = A._new(str)
12400 endif
12401 return _instance
12402 enddef
12403 endclass
12404 var a: A = A.GetInstance('foo')
12405 var b: A = A.GetInstance('bar')
12406 assert_equal('foo', a.str)
12407 assert_equal('foo', b.str)
12408 END
12409 v9.CheckSourceSuccess(lines)
12410enddef
12411
Bram Moolenaar00b28d62022-12-08 15:32:33 +000012412" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker