blob: 4ce9fcdc49e04c0ca3ec7086cf82caeaafa23dff [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
Yegappan Lakshmananac773182024-04-27 11:36:12 +02002389 # Additional commands after "interface name"
2390 lines =<< trim END
2391 vim9script
2392 interface Something | var x = 10 | var y = 20
2393 endinterface
2394 END
2395 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2)
2396
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002397 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002398 vim9script
2399 export interface EnterExit
2400 def Enter(): void
2401 def Exit(): void
2402 endinterface
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002403 END
2404 writefile(lines, 'XdefIntf.vim', 'D')
2405
2406 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002407 vim9script
2408 import './XdefIntf.vim' as defIntf
2409 export def With(ee: defIntf.EnterExit, F: func)
2410 ee.Enter()
2411 try
2412 F()
2413 finally
2414 ee.Exit()
2415 endtry
2416 enddef
Bram Moolenaar53f54e42023-01-26 20:36:56 +00002417 END
2418 v9.CheckScriptSuccess(lines)
Bram Moolenaar657aea72023-01-27 13:16:19 +00002419
2420 var imported =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002421 vim9script
2422 export abstract class EnterExit
2423 def Enter(): void
2424 enddef
2425 def Exit(): void
2426 enddef
2427 endclass
Bram Moolenaar657aea72023-01-27 13:16:19 +00002428 END
2429 writefile(imported, 'XdefIntf2.vim', 'D')
2430
2431 lines[1] = " import './XdefIntf2.vim' as defIntf"
2432 v9.CheckScriptSuccess(lines)
Bram Moolenaar554d0312023-01-05 19:59:18 +00002433enddef
2434
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01002435" Test for using string() with an interface
2436def Test_interface_to_string()
2437 var lines =<< trim END
2438 vim9script
2439 interface Intf
2440 def Method(nr: number)
2441 endinterface
2442 assert_equal("interface Intf", string(Intf))
2443 END
2444 v9.CheckSourceSuccess(lines)
2445enddef
2446
Bram Moolenaar94674f22023-01-06 18:42:20 +00002447def Test_class_implements_interface()
2448 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002449 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002450
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002451 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002452 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002453 def Method(nr: number)
2454 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002455
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002456 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002457 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002458 def Method(nr: number)
2459 echo nr
2460 enddef
2461 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002462
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002463 interface Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002464 var member: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002465 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002466
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002467 class AnotherImpl implements Some, Another
Doug Kearns74da0ee2023-12-14 20:26:26 +01002468 var member = 'abc'
2469 var count = 20
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002470 def Method(nr: number)
2471 echo nr
2472 enddef
2473 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002474 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002475 v9.CheckSourceSuccess(lines)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002476
2477 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002478 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002479
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002480 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002481 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002482 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002483
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002484 class SomeImpl implements Some implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002485 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002486 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002487 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002488 v9.CheckSourceFailure(lines, 'E1350: Duplicate "implements"', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002489
2490 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002491 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002492
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002493 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002494 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002495 endinterface
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002496
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002497 class SomeImpl implements Some, Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002498 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002499 endclass
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002500 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002501 v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some', 7)
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002502
2503 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002504 vim9script
Bram Moolenaardf8f9472023-01-07 14:51:03 +00002505
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002506 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002507 var counter: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002508 def Method(nr: number)
2509 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002510
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002511 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002512 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002513 def Method(nr: number)
2514 echo nr
2515 enddef
2516 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002517 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002518 v9.CheckSourceFailure(lines, 'E1348: Variable "counter" of interface "Some" is not implemented', 13)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002519
2520 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002521 vim9script
Bram Moolenaar94674f22023-01-06 18:42:20 +00002522
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002523 interface Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002524 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002525 def Methods(nr: number)
2526 endinterface
Bram Moolenaar94674f22023-01-06 18:42:20 +00002527
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002528 class SomeImpl implements Some
Doug Kearns74da0ee2023-12-14 20:26:26 +01002529 var count: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002530 def Method(nr: number)
2531 echo nr
2532 enddef
2533 endclass
Bram Moolenaar94674f22023-01-06 18:42:20 +00002534 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002535 v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented', 13)
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002536
2537 # Check different order of members in class and interface works.
2538 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002539 vim9script
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002540
2541 interface Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002542 var label: string
2543 var errpos: number
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002544 endinterface
2545
2546 # order of members is opposite of interface
2547 class Failure implements Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01002548 public var lnum: number = 5
2549 var errpos: number = 42
2550 var label: string = 'label'
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002551 endclass
2552
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002553 def Test()
2554 var result: Result = Failure.new()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002555
2556 assert_equal('label', result.label)
2557 assert_equal(42, result.errpos)
2558 enddef
2559
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002560 Test()
Bram Moolenaar29ac5df2023-01-16 19:43:47 +00002561 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002562 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002563
2564 # Interface name after "extends" doesn't end in a space or NUL character
2565 lines =<< trim END
2566 vim9script
2567 interface A
2568 endinterface
2569 class B extends A"
2570 endclass
2571 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002572 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002573
2574 # Trailing characters after a class name
2575 lines =<< trim END
2576 vim9script
2577 class A bbb
2578 endclass
2579 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002580 v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002581
2582 # using "implements" with a non-existing class
2583 lines =<< trim END
2584 vim9script
2585 class A implements B
2586 endclass
2587 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002588 v9.CheckSourceFailure(lines, 'E1346: Interface name not found: B', 3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002589
2590 # using "implements" with a regular class
2591 lines =<< trim END
2592 vim9script
2593 class A
2594 endclass
2595 class B implements A
2596 endclass
2597 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002598 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: A', 5)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002599
2600 # using "implements" with a variable
2601 lines =<< trim END
2602 vim9script
2603 var T: number = 10
2604 class A implements T
2605 endclass
2606 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002607 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: T', 4)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02002608
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002609 # implements should be followed by a white space
2610 lines =<< trim END
2611 vim9script
2612 interface A
2613 endinterface
2614 class B implements A;
2615 endclass
2616 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002617 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A;', 4)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02002618
LemonBoyc5d27442023-08-19 13:02:35 +02002619 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002620 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002621
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002622 interface One
2623 def IsEven(nr: number): bool
2624 endinterface
2625 class Two implements One
2626 def IsEven(nr: number): string
2627 enddef
2628 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002629 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002630 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002631
2632 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002633 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002634
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002635 interface One
2636 def IsEven(nr: number): bool
2637 endinterface
2638 class Two implements One
2639 def IsEven(nr: bool): bool
2640 enddef
2641 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002642 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002643 v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool', 9)
LemonBoyc5d27442023-08-19 13:02:35 +02002644
2645 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002646 vim9script
LemonBoyc5d27442023-08-19 13:02:35 +02002647
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002648 interface One
2649 def IsEven(nr: number): bool
2650 endinterface
2651 class Two implements One
2652 def IsEven(nr: number, ...extra: list<number>): bool
2653 enddef
2654 endclass
LemonBoyc5d27442023-08-19 13:02:35 +02002655 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002656 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 +02002657
2658 # access superclass interface members from subclass, mix variable order
2659 lines =<< trim END
2660 vim9script
2661
2662 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002663 var mvar1: number
2664 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002665 endinterface
2666
2667 # NOTE: the order is swapped
2668 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002669 var mvar2: number
2670 var mvar1: number
2671 public static var svar2: number
2672 public static var svar1: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002673 def new()
2674 svar1 = 11
2675 svar2 = 12
2676 this.mvar1 = 111
2677 this.mvar2 = 112
2678 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002679 endclass
2680
2681 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002682 def new()
2683 this.mvar1 = 121
2684 this.mvar2 = 122
2685 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002686 endclass
2687
2688 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002689 def new()
2690 this.mvar1 = 131
2691 this.mvar2 = 132
2692 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002693 endclass
2694
Ernie Raelcf138d42023-09-06 20:45:03 +02002695 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002696 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002697 enddef
2698
2699 var oa = A.new()
2700 var ob = B.new()
2701 var oc = C.new()
2702
Ernie Raelcf138d42023-09-06 20:45:03 +02002703 assert_equal([111, 112], F2(oa))
2704 assert_equal([121, 122], F2(ob))
2705 assert_equal([131, 132], F2(oc))
2706 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002707 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02002708
2709 # Access superclass interface members from subclass, mix variable order.
2710 # Two interfaces, one on A, one on B; each has both kinds of variables
2711 lines =<< trim END
2712 vim9script
2713
2714 interface I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002715 var mvar1: number
2716 var mvar2: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002717 endinterface
2718
2719 interface I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002720 var mvar3: number
2721 var mvar4: number
Ernie Raelcf138d42023-09-06 20:45:03 +02002722 endinterface
2723
2724 class A implements I1
Doug Kearns74da0ee2023-12-14 20:26:26 +01002725 public static var svar1: number
2726 public static var svar2: number
2727 var mvar1: number
2728 var mvar2: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002729 def new()
2730 svar1 = 11
2731 svar2 = 12
2732 this.mvar1 = 111
2733 this.mvar2 = 112
2734 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002735 endclass
2736
2737 class B extends A implements I2
Doug Kearns74da0ee2023-12-14 20:26:26 +01002738 static var svar3: number
2739 static var svar4: number
2740 var mvar3: number
2741 var mvar4: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002742 def new()
2743 svar3 = 23
2744 svar4 = 24
2745 this.mvar1 = 121
2746 this.mvar2 = 122
2747 this.mvar3 = 123
2748 this.mvar4 = 124
2749 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002750 endclass
2751
2752 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01002753 public static var svar5: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002754 def new()
2755 svar5 = 1001
2756 this.mvar1 = 131
2757 this.mvar2 = 132
2758 this.mvar3 = 133
2759 this.mvar4 = 134
2760 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02002761 endclass
2762
Ernie Raelcf138d42023-09-06 20:45:03 +02002763 def F2(i: I1): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002764 return [ i.mvar1, i.mvar2 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002765 enddef
2766
Ernie Raelcf138d42023-09-06 20:45:03 +02002767 def F4(i: I2): list<number>
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002768 return [ i.mvar3, i.mvar4 ]
Ernie Raelcf138d42023-09-06 20:45:03 +02002769 enddef
2770
Ernie Raelcf138d42023-09-06 20:45:03 +02002771 var oa = A.new()
2772 var ob = B.new()
2773 var oc = C.new()
2774
Ernie Raelcf138d42023-09-06 20:45:03 +02002775 assert_equal([[111, 112]], [F2(oa)])
2776 assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
2777 assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
Ernie Raelcf138d42023-09-06 20:45:03 +02002778 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002779 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02002780
2781 # Using two interface names without a space after the ","
2782 lines =<< trim END
2783 vim9script
2784 interface A
2785 endinterface
2786 interface B
2787 endinterface
2788 class C implements A,B
2789 endclass
2790 END
2791 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A,B', 6)
2792
2793 # No interface name after a comma
2794 lines =<< trim END
2795 vim9script
2796 interface A
2797 endinterface
2798 class B implements A,
2799 endclass
2800 END
2801 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 4)
2802
2803 # No interface name after implements
2804 lines =<< trim END
2805 vim9script
2806 class A implements
2807 endclass
2808 END
2809 v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2)
Bram Moolenaar94674f22023-01-06 18:42:20 +00002810enddef
2811
Bram Moolenaard0200c82023-01-28 15:19:40 +00002812def Test_call_interface_method()
2813 var lines =<< trim END
2814 vim9script
2815 interface Base
2816 def Enter(): void
2817 endinterface
2818
2819 class Child implements Base
2820 def Enter(): void
2821 g:result ..= 'child'
2822 enddef
2823 endclass
2824
2825 def F(obj: Base)
2826 obj.Enter()
2827 enddef
2828
2829 g:result = ''
2830 F(Child.new())
2831 assert_equal('child', g:result)
2832 unlet g:result
2833 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002834 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002835
2836 lines =<< trim END
2837 vim9script
2838 class Base
2839 def Enter(): void
2840 g:result ..= 'base'
2841 enddef
2842 endclass
2843
2844 class Child extends Base
2845 def Enter(): void
2846 g:result ..= 'child'
2847 enddef
2848 endclass
2849
2850 def F(obj: Base)
2851 obj.Enter()
2852 enddef
2853
2854 g:result = ''
2855 F(Child.new())
2856 assert_equal('child', g:result)
2857 unlet g:result
2858 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002859 v9.CheckSourceSuccess(lines)
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002860
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002861 # method of interface returns a value
2862 lines =<< trim END
2863 vim9script
2864 interface Base
2865 def Enter(): string
2866 endinterface
2867
2868 class Child implements Base
2869 def Enter(): string
2870 g:result ..= 'child'
2871 return "/resource"
2872 enddef
2873 endclass
2874
2875 def F(obj: Base)
2876 var r = obj.Enter()
2877 g:result ..= r
2878 enddef
2879
2880 g:result = ''
2881 F(Child.new())
2882 assert_equal('child/resource', g:result)
2883 unlet g:result
2884 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002885 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002886
2887 lines =<< trim END
2888 vim9script
2889 class Base
2890 def Enter(): string
2891 return null_string
2892 enddef
2893 endclass
2894
2895 class Child extends Base
2896 def Enter(): string
2897 g:result ..= 'child'
2898 return "/resource"
2899 enddef
2900 endclass
2901
2902 def F(obj: Base)
2903 var r = obj.Enter()
2904 g:result ..= r
2905 enddef
2906
2907 g:result = ''
2908 F(Child.new())
2909 assert_equal('child/resource', g:result)
2910 unlet g:result
2911 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002912 v9.CheckSourceSuccess(lines)
Bram Moolenaar7a1bdae2023-02-04 15:45:27 +00002913
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002914 # No class that implements the interface.
2915 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002916 vim9script
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002917
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002918 interface IWithEE
2919 def Enter(): any
2920 def Exit(): void
2921 endinterface
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002922
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002923 def With1(ee: IWithEE, F: func)
2924 var r = ee.Enter()
2925 enddef
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002926
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002927 defcompile
Bram Moolenaarb8bebd02023-01-30 20:24:23 +00002928 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002929 v9.CheckSourceSuccess(lines)
Bram Moolenaard0200c82023-01-28 15:19:40 +00002930enddef
2931
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002932def Test_class_used_as_type()
2933 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002934 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002935
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002936 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002937 var x = 0
2938 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002939 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002940
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002941 var p: Point
2942 p = Point.new(2, 33)
2943 assert_equal(2, p.x)
2944 assert_equal(33, p.y)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002945 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002946 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002947
2948 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002949 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002950
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002951 interface HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002952 var x: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002953 endinterface
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002954
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002955 class Point implements HasX
Doug Kearns74da0ee2023-12-14 20:26:26 +01002956 var x = 0
2957 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002958 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002959
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002960 var p: Point
2961 p = Point.new(2, 33)
2962 var hx = p
2963 assert_equal(2, hx.x)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002964 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02002965 v9.CheckSourceSuccess(lines)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002966
2967 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002968 vim9script
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002969
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002970 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01002971 var x = 0
2972 var y = 0
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002973 endclass
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002974
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002975 var p: Point
2976 p = 'text'
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002977 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002978 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string', 9)
Bram Moolenaareca2c5f2023-01-07 12:08:41 +00002979enddef
2980
Bram Moolenaar83677162023-01-08 19:54:10 +00002981def Test_class_extends()
2982 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002983 vim9script
2984 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01002985 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002986 def GetOne(): number
2987 return this.one
Bram Moolenaar6aa09372023-01-11 17:59:38 +00002988 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002989 endclass
2990 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01002991 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02002992 def GetTotal(): number
2993 return this.one + this.two
2994 enddef
2995 endclass
2996 var o = Child.new()
2997 assert_equal(1, o.one)
2998 assert_equal(2, o.two)
2999 assert_equal(1, o.GetOne())
3000 assert_equal(3, o.GetTotal())
Bram Moolenaar6481acc2023-01-11 21:14:17 +00003001 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003002 v9.CheckSourceSuccess(lines)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003003
3004 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003005 vim9script
3006 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003007 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003008 endclass
3009 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003010 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003011 endclass
3012 var o = Child.new(3, 44)
3013 assert_equal(3, o.one)
3014 assert_equal(44, o.two)
Bram Moolenaar4cae8452023-01-15 15:51:48 +00003015 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003016 v9.CheckSourceSuccess(lines)
3017
3018 lines =<< trim END
3019 vim9script
3020 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003021 var one = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003022 endclass
3023 class Child extends Base extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003024 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003025 endclass
3026 END
3027 v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"', 5)
3028
3029 lines =<< trim END
3030 vim9script
3031 class Child extends BaseClass
Doug Kearns74da0ee2023-12-14 20:26:26 +01003032 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003033 endclass
3034 END
3035 v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass', 4)
3036
3037 lines =<< trim END
3038 vim9script
3039 var SomeVar = 99
3040 class Child extends SomeVar
Doug Kearns74da0ee2023-12-14 20:26:26 +01003041 var two = 2
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003042 endclass
3043 END
3044 v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar', 5)
3045
3046 lines =<< trim END
3047 vim9script
3048 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003049 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003050 def ToString(): string
3051 return this.name
3052 enddef
3053 endclass
3054
3055 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003056 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003057 def ToString(): string
3058 return super.ToString() .. ': ' .. this.age
3059 enddef
3060 endclass
3061
3062 var o = Child.new('John', 42)
3063 assert_equal('John: 42', o.ToString())
3064 END
3065 v9.CheckSourceSuccess(lines)
3066
3067 lines =<< trim END
3068 vim9script
3069 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003070 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003071 def ToString(): number
3072 return this.age
3073 enddef
3074 def ToString(): string
3075 return this.age
3076 enddef
3077 endclass
3078 END
3079 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString', 9)
3080
3081 lines =<< trim END
3082 vim9script
3083 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003084 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003085 def ToString(): string
3086 return super .ToString() .. ': ' .. this.age
3087 enddef
3088 endclass
3089 var o = Child.new(42)
3090 echo o.ToString()
3091 END
3092 v9.CheckSourceFailure(lines, 'E1356: "super" must be followed by a dot', 1)
3093
3094 lines =<< trim END
3095 vim9script
3096 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003097 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003098 def ToString(): string
3099 return this.name
3100 enddef
3101 endclass
3102
3103 var age = 42
3104 def ToString(): string
3105 return super.ToString() .. ': ' .. age
3106 enddef
3107 echo ToString()
3108 END
3109 v9.CheckSourceFailure(lines, 'E1357: Using "super" not in a class method', 1)
3110
3111 lines =<< trim END
3112 vim9script
3113 class Child
Doug Kearns74da0ee2023-12-14 20:26:26 +01003114 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003115 def ToString(): string
3116 return super.ToString() .. ': ' .. this.age
3117 enddef
3118 endclass
3119 var o = Child.new(42)
3120 echo o.ToString()
3121 END
3122 v9.CheckSourceFailure(lines, 'E1358: Using "super" not in a child class', 1)
3123
3124 lines =<< trim END
3125 vim9script
3126 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003127 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003128 static def ToString(): string
3129 return 'Base class'
3130 enddef
3131 endclass
3132
3133 class Child extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003134 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003135 def ToString(): string
3136 return Base.ToString() .. ': ' .. this.age
3137 enddef
3138 endclass
3139
3140 var o = Child.new('John', 42)
3141 assert_equal('Base class: 42', o.ToString())
3142 END
3143 v9.CheckSourceSuccess(lines)
3144
3145 lines =<< trim END
3146 vim9script
3147 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003148 var value = 1
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003149 def new(init: number)
3150 this.value = number + 1
3151 enddef
3152 endclass
3153 class Child extends Base
3154 def new()
3155 this.new(3)
3156 enddef
3157 endclass
3158 var c = Child.new()
3159 END
3160 v9.CheckSourceFailure(lines, 'E1385: Class method "new" accessible only using class "Child"', 1)
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003161
3162 # base class with more than one object member
3163 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003164 vim9script
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003165
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003166 class Result
Doug Kearns74da0ee2023-12-14 20:26:26 +01003167 var success: bool
3168 var value: any = null
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003169 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003170
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003171 class Success extends Result
3172 def new(this.value = v:none)
3173 this.success = true
3174 enddef
3175 endclass
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003176
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003177 var v = Success.new('asdf')
3178 assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
Bram Moolenaarae3205a2023-01-15 20:49:00 +00003179 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003180 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003181
3182 # class name after "extends" doesn't end in a space or NUL character
3183 lines =<< trim END
3184 vim9script
3185 class A
3186 endclass
3187 class B extends A"
3188 endclass
3189 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003190 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4)
Bram Moolenaar83677162023-01-08 19:54:10 +00003191enddef
3192
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003193def Test_using_base_class()
3194 var lines =<< trim END
3195 vim9script
3196
3197 class BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003198 def Enter(): any
3199 return null
3200 enddef
3201 def Exit(resource: any): void
3202 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003203 endclass
3204
3205 class ChildEE extends BaseEE
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003206 def Enter(): any
3207 return 42
3208 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003209
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003210 def Exit(resource: number): void
3211 g:result ..= '/exit'
3212 enddef
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003213 endclass
3214
3215 def With(ee: BaseEE)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003216 var r = ee.Enter()
3217 try
3218 g:result ..= r
3219 finally
3220 g:result ..= '/finally'
3221 ee.Exit(r)
3222 endtry
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003223 enddef
3224
3225 g:result = ''
3226 With(ChildEE.new())
3227 assert_equal('42/finally/exit', g:result)
3228 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003229 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003230 unlet g:result
Ernie Rael114ec812023-06-04 18:11:35 +01003231
3232 # Using super, Child invokes Base method which has optional arg. #12471
3233 lines =<< trim END
3234 vim9script
3235
3236 class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003237 var success: bool = false
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003238 def Method(arg = 0)
3239 this.success = true
3240 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01003241 endclass
3242
3243 class Child extends Base
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003244 def new()
3245 super.Method()
3246 enddef
Ernie Rael114ec812023-06-04 18:11:35 +01003247 endclass
3248
3249 var obj = Child.new()
3250 assert_equal(true, obj.success)
3251 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003252 v9.CheckSourceSuccess(lines)
Bram Moolenaar094cf9f2023-02-10 15:52:25 +00003253enddef
3254
Ernie Rael58c95792024-08-13 23:27:22 +02003255def Test_super_dispatch()
3256 # See #15448 and #15463
3257 var lines =<< trim END
3258 vim9script
3259
3260 class A
3261 def String(): string
3262 return 'A'
3263 enddef
3264 endclass
3265
3266 class B extends A
3267 def String(): string
3268 return super.String()
3269 enddef
3270 endclass
3271
3272 class C extends B
3273 endclass
3274
3275 assert_equal('A', C.new().String())
3276 END
3277 v9.CheckSourceSuccess(lines)
3278
3279 lines =<< trim END
3280 vim9script
3281
3282 class A
3283 def F(): string
3284 return 'AA'
3285 enddef
3286 endclass
3287
3288 class B extends A
3289 def F(): string
3290 return 'BB'
3291 enddef
3292 def S(): string
3293 return super.F()
3294 enddef
3295 def S0(): string
3296 return this.S()
3297 enddef
3298 endclass
3299
3300 class C extends B
3301 def F(): string
3302 return 'CC'
3303 enddef
3304 def ToB(): string
3305 return super.F()
3306 enddef
3307 endclass
3308
3309 assert_equal('AA', B.new().S())
3310 assert_equal('AA', C.new().S())
3311 assert_equal('AA', B.new().S0())
3312 assert_equal('AA', C.new().S0())
3313
3314 assert_equal('BB', C.new().ToB())
3315
3316 assert_equal('CC', C.new().F())
3317 assert_equal('BB', B.new().F())
3318 assert_equal('AA', A.new().F())
3319 END
3320 v9.CheckSourceSuccess(lines)
3321
3322 lines =<< trim END
3323 vim9script
3324
3325 var call_chain: list<string>
3326
3327 abstract class A
3328 abstract def _G(): string
3329
3330 def F(): string
3331 call_chain->add('A.F()')
3332 return this._G()
3333 enddef
3334 def _H(): string
3335 call_chain->add('A._H()')
3336 return this.F()
3337 enddef
3338 endclass
3339
3340 class B extends A
3341 def _G(): string
3342 call_chain->add('B.G()')
3343 return 'BBB'
3344 enddef
3345 def SF(): string
3346 call_chain->add('B.SF()')
3347 return super._H()
3348 enddef
3349 endclass
3350
3351 class C extends B
3352 endclass
3353
3354 class D extends C
3355 def SF(): string
3356 call_chain->add('D.SF()')
3357 return super.SF()
3358 enddef
3359 endclass
3360
3361 class E extends D
3362 def SF(): string
3363 call_chain->add('E.SF()')
3364 return super.SF()
3365 enddef
3366 endclass
3367
3368 class F extends E
3369 def _G(): string
3370 call_chain->add('F._G()')
3371 return 'FFF'
3372 enddef
3373 endclass
3374
3375 # E.new() -> A.F() -> B._G()
3376 call_chain = []
3377 var o1 = E.new()
3378 assert_equal('BBB', o1.F())
3379 assert_equal(['A.F()', 'B.G()'], call_chain)
3380
3381 # F.new() -> E.SF() -> D.SF() -> B.SF() -> A._H() -> A.F() -> F._G()
3382 call_chain = []
3383 var o2 = F.new()
3384 assert_equal('FFF', o2.SF())
3385 assert_equal(['E.SF()', 'D.SF()', 'B.SF()', 'A._H()', 'A.F()', 'F._G()'], call_chain)
3386 END
3387 v9.CheckSourceSuccess(lines)
3388enddef
3389
Bram Moolenaara86655a2023-01-12 17:06:27 +00003390def Test_class_import()
3391 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003392 vim9script
3393 export class Animal
Doug Kearns74da0ee2023-12-14 20:26:26 +01003394 var kind: string
3395 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003396 endclass
Bram Moolenaara86655a2023-01-12 17:06:27 +00003397 END
3398 writefile(lines, 'Xanimal.vim', 'D')
3399
3400 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003401 vim9script
3402 import './Xanimal.vim' as animal
Bram Moolenaara86655a2023-01-12 17:06:27 +00003403
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003404 var a: animal.Animal
3405 a = animal.Animal.new('fish', 'Eric')
3406 assert_equal('fish', a.kind)
3407 assert_equal('Eric', a.name)
Bram Moolenaar40594002023-01-12 20:04:51 +00003408
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003409 var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
3410 assert_equal('cat', b.kind)
3411 assert_equal('Garfield', b.name)
Bram Moolenaara86655a2023-01-12 17:06:27 +00003412 END
3413 v9.CheckScriptSuccess(lines)
3414enddef
3415
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003416" Test for importing a class into a legacy script and calling the class method
3417def Test_class_method_from_legacy_script()
3418 var lines =<< trim END
3419 vim9script
3420 export class A
3421 static var name: string = 'a'
3422 static def SetName(n: string)
3423 name = n
3424 enddef
3425 endclass
3426 END
3427 writefile(lines, 'Xvim9export.vim', 'D')
3428
3429 lines =<< trim END
3430 import './Xvim9export.vim' as vim9
3431
3432 call s:vim9.A.SetName('b')
3433 call assert_equal('b', s:vim9.A.name)
3434 END
3435 v9.CheckScriptSuccess(lines)
3436enddef
3437
Yegappan Lakshmanand2e1c832023-12-14 19:59:45 +01003438" Test for implementing an imported interface
3439def Test_implement_imported_interface()
3440 var lines =<< trim END
3441 vim9script
3442 export interface Imp_Intf1
3443 def Fn1(): number
3444 endinterface
3445 export interface Imp_Intf2
3446 def Fn2(): number
3447 endinterface
3448 END
3449 writefile(lines, 'Ximportinterface.vim', 'D')
3450
3451 lines =<< trim END
3452 vim9script
3453 import './Ximportinterface.vim' as Xintf
3454
3455 class A implements Xintf.Imp_Intf1, Xintf.Imp_Intf2
3456 def Fn1(): number
3457 return 10
3458 enddef
3459 def Fn2(): number
3460 return 20
3461 enddef
3462 endclass
3463 var a = A.new()
3464 assert_equal(10, a.Fn1())
3465 assert_equal(20, a.Fn2())
3466 END
3467 v9.CheckScriptSuccess(lines)
3468enddef
3469
3470" Test for extending an imported class
3471def Test_extend_imported_class()
3472 var lines =<< trim END
3473 vim9script
3474 export class Imp_C1
3475 def Fn1(): number
3476 return 5
3477 enddef
3478 endclass
3479 END
3480 writefile(lines, 'Xextendimportclass.vim', 'D')
3481
3482 lines =<< trim END
3483 vim9script
3484 import './Xextendimportclass.vim' as XClass
3485
3486 class A extends XClass.Imp_C1
3487 endclass
3488 var a = A.new()
3489 assert_equal(5, a.Fn1())
3490 END
3491 v9.CheckScriptSuccess(lines)
3492enddef
3493
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003494def Test_abstract_class()
3495 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003496 vim9script
3497 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003498 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003499 endclass
3500 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003501 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003502 endclass
3503 var p: Base = Person.new('Peter', 42)
3504 assert_equal('Peter', p.name)
3505 assert_equal(42, p.age)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003506 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003507 v9.CheckSourceSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003508
3509 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003510 vim9script
3511 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003512 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003513 endclass
3514 class Person extends Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003515 var age: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003516 endclass
3517 var p = Base.new('Peter')
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003518 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02003519 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Base"', 8)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003520
3521 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003522 abstract class Base
Doug Kearns74da0ee2023-12-14 20:26:26 +01003523 var name: string
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003524 endclass
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003525 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003526 v9.CheckSourceFailure(lines, 'E1316: Class can only be defined in Vim9 script', 1)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003527
Yegappan Lakshmananac773182024-04-27 11:36:12 +02003528 # Additional commands after "abstract class"
3529 lines =<< trim END
3530 vim9script
3531 abstract class Something | var x = []
3532 endclass
3533 END
3534 v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = []", 2)
3535
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003536 # Abstract class cannot have a "new" function
3537 lines =<< trim END
3538 vim9script
3539 abstract class Base
3540 def new()
3541 enddef
3542 endclass
3543 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003544 v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02003545
3546 # extending an abstract class with class methods and variables
3547 lines =<< trim END
3548 vim9script
3549 abstract class A
3550 static var s: string = 'vim'
3551 static def Fn(): list<number>
3552 return [10]
3553 enddef
3554 endclass
3555 class B extends A
3556 endclass
3557 var b = B.new()
3558 assert_equal('vim', A.s)
3559 assert_equal([10], A.Fn())
3560 END
3561 v9.CheckScriptSuccess(lines)
Bram Moolenaar24a8d062023-01-14 13:12:06 +00003562enddef
3563
Bram Moolenaar486fc252023-01-18 14:51:07 +00003564def Test_closure_in_class()
3565 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003566 vim9script
Bram Moolenaar486fc252023-01-18 14:51:07 +00003567
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003568 class Foo
Doug Kearns74da0ee2023-12-14 20:26:26 +01003569 var y: list<string> = ['B']
Bram Moolenaar486fc252023-01-18 14:51:07 +00003570
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003571 def new()
3572 g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
3573 enddef
3574 endclass
Bram Moolenaar486fc252023-01-18 14:51:07 +00003575
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003576 Foo.new()
3577 assert_equal(['A'], g:result)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003578 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003579 v9.CheckSourceSuccess(lines)
Bram Moolenaar486fc252023-01-18 14:51:07 +00003580enddef
3581
Ernie Rael9ed53752023-12-11 17:40:46 +01003582def Test_construct_object_from_legacy()
3583 # Cannot directly invoke constructor from legacy
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003584 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003585 vim9script
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003586
Ernie Rael9ed53752023-12-11 17:40:46 +01003587 var newCalled = false
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003588
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003589 class A
Ernie Rael9ed53752023-12-11 17:40:46 +01003590 def new(arg: string)
3591 newCalled = true
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003592 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003593 endclass
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003594
Ernie Rael9ed53752023-12-11 17:40:46 +01003595 export def CreateA(...args: list<any>): A
3596 return call(A.new, args)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003597 enddef
3598
Ernie Rael9ed53752023-12-11 17:40:46 +01003599 g:P = CreateA
3600 legacy call g:P('some_arg')
3601 assert_equal(true, newCalled)
3602 unlet g:P
3603 END
3604 v9.CheckSourceSuccess(lines)
3605
3606 lines =<< trim END
3607 vim9script
3608
3609 var newCalled = false
3610
3611 class A
3612 static def CreateA(options = {}): any
3613 return A.new()
3614 enddef
3615 def new()
3616 newCalled = true
3617 enddef
3618 endclass
3619
3620 g:P = A.CreateA
3621 legacy call g:P()
3622 assert_equal(true, newCalled)
3623 unlet g:P
3624 END
3625 v9.CheckSourceSuccess(lines)
3626
3627 # This also tests invoking "new()" with "call"
3628 lines =<< trim END
3629 vim9script
3630
3631 var createdObject: any
3632
3633 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01003634 var val1: number
3635 var val2: number
Ernie Rael9ed53752023-12-11 17:40:46 +01003636 static def CreateA(...args: list<any>): any
3637 createdObject = call(A.new, args)
3638 return createdObject
3639 enddef
3640 endclass
3641
3642 g:P = A.CreateA
3643 legacy call g:P(3, 5)
3644 assert_equal(3, createdObject.val1)
3645 assert_equal(5, createdObject.val2)
3646 legacy call g:P()
3647 assert_equal(0, createdObject.val1)
3648 assert_equal(0, createdObject.val2)
3649 legacy call g:P(7)
3650 assert_equal(7, createdObject.val1)
3651 assert_equal(0, createdObject.val2)
3652 unlet g:P
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003653 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003654 v9.CheckSourceSuccess(lines)
Bram Moolenaar5ca05fa2023-06-10 16:45:13 +01003655enddef
3656
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003657def Test_defer_with_object()
3658 var lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003659 vim9script
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003660
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003661 class CWithEE
3662 def Enter()
3663 g:result ..= "entered/"
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003664 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003665 def Exit()
3666 g:result ..= "exited"
3667 enddef
3668 endclass
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003669
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003670 def With(ee: CWithEE, F: func)
3671 ee.Enter()
3672 defer ee.Exit()
3673 F()
3674 enddef
3675
3676 g:result = ''
3677 var obj = CWithEE.new()
3678 obj->With(() => {
3679 g:result ..= "called/"
3680 })
3681 assert_equal('entered/called/exited', g:result)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003682 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003683 v9.CheckSourceSuccess(lines)
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003684 unlet g:result
Bram Moolenaar313e4722023-02-08 20:55:27 +00003685
3686 lines =<< trim END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003687 vim9script
Bram Moolenaar313e4722023-02-08 20:55:27 +00003688
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003689 class BaseWithEE
3690 def Enter()
3691 g:result ..= "entered-base/"
Bram Moolenaar313e4722023-02-08 20:55:27 +00003692 enddef
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003693 def Exit()
3694 g:result ..= "exited-base"
3695 enddef
3696 endclass
Bram Moolenaar313e4722023-02-08 20:55:27 +00003697
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02003698 class CWithEE extends BaseWithEE
3699 def Enter()
3700 g:result ..= "entered-child/"
3701 enddef
3702 def Exit()
3703 g:result ..= "exited-child"
3704 enddef
3705 endclass
3706
3707 def With(ee: BaseWithEE, F: func)
3708 ee.Enter()
3709 defer ee.Exit()
3710 F()
3711 enddef
3712
3713 g:result = ''
3714 var obj = CWithEE.new()
3715 obj->With(() => {
3716 g:result ..= "called/"
3717 })
3718 assert_equal('entered-child/called/exited-child', g:result)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003719 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003720 v9.CheckSourceSuccess(lines)
Bram Moolenaar313e4722023-02-08 20:55:27 +00003721 unlet g:result
Bram Moolenaar8dbab1d2023-01-27 20:14:02 +00003722enddef
3723
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003724" The following test used to crash Vim (Github issue #12676)
3725def Test_extends_method_crashes_vim()
3726 var lines =<< trim END
3727 vim9script
3728
3729 class Observer
3730 endclass
3731
3732 class Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003733 var value: any
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003734
3735 def Set(v: any)
3736 if v != this.value
3737 this.value = v
3738 endif
3739 enddef
3740
3741 def Register(observer: Observer)
3742 enddef
3743 endclass
3744
3745 class Bool extends Property
Doug Kearns74da0ee2023-12-14 20:26:26 +01003746 var value2: bool
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003747 endclass
3748
3749 def Observe(obj: Property, who: Observer)
3750 obj.Register(who)
3751 enddef
3752
3753 var p = Bool.new(false)
3754 var myObserver = Observer.new()
3755
3756 Observe(p, myObserver)
3757
3758 p.Set(true)
3759 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003760 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan57a02cc2023-08-13 10:19:38 +02003761enddef
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003762
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003763" Test for calling a method in a class that is extended
3764def Test_call_method_in_extended_class()
3765 var lines =<< trim END
3766 vim9script
3767
3768 var prop_init_called = false
3769 var prop_register_called = false
3770
3771 class Property
3772 def Init()
3773 prop_init_called = true
3774 enddef
3775
3776 def Register()
3777 prop_register_called = true
3778 enddef
3779 endclass
3780
3781 class Bool extends Property
3782 endclass
3783
3784 def Observe(obj: Property)
3785 obj.Register()
3786 enddef
3787
3788 var p = Property.new()
3789 Observe(p)
3790
3791 p.Init()
3792 assert_true(prop_init_called)
3793 assert_true(prop_register_called)
3794 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003795 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan74cc13c2023-08-13 17:41:26 +02003796enddef
3797
LemonBoyafe04662023-08-23 21:08:11 +02003798def Test_instanceof()
3799 var lines =<< trim END
3800 vim9script
3801
3802 class Base1
3803 endclass
3804
3805 class Base2 extends Base1
3806 endclass
3807
3808 interface Intf1
3809 endinterface
3810
3811 class Mix1 implements Intf1
3812 endclass
3813
3814 class Base3 extends Mix1
3815 endclass
3816
Ernie Rael2025af12023-12-12 16:58:00 +01003817 type AliasBase1 = Base1
3818 type AliasBase2 = Base2
3819 type AliasIntf1 = Intf1
3820 type AliasMix1 = Mix1
3821
LemonBoyafe04662023-08-23 21:08:11 +02003822 var b1 = Base1.new()
3823 var b2 = Base2.new()
3824 var b3 = Base3.new()
3825
3826 assert_true(instanceof(b1, Base1))
3827 assert_true(instanceof(b2, Base1))
3828 assert_false(instanceof(b1, Base2))
3829 assert_true(instanceof(b3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003830 assert_true(instanceof(b3, Base1, Base2, Intf1))
3831
3832 assert_true(instanceof(b1, AliasBase1))
3833 assert_true(instanceof(b2, AliasBase1))
3834 assert_false(instanceof(b1, AliasBase2))
3835 assert_true(instanceof(b3, AliasMix1))
3836 assert_true(instanceof(b3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003837
3838 def Foo()
3839 var a1 = Base1.new()
3840 var a2 = Base2.new()
3841 var a3 = Base3.new()
3842
3843 assert_true(instanceof(a1, Base1))
3844 assert_true(instanceof(a2, Base1))
3845 assert_false(instanceof(a1, Base2))
3846 assert_true(instanceof(a3, Mix1))
Ernie Rael2025af12023-12-12 16:58:00 +01003847 assert_true(instanceof(a3, Base1, Base2, Intf1))
3848
3849 assert_true(instanceof(a1, AliasBase1))
3850 assert_true(instanceof(a2, AliasBase1))
3851 assert_false(instanceof(a1, AliasBase2))
3852 assert_true(instanceof(a3, AliasMix1))
3853 assert_true(instanceof(a3, AliasBase1, AliasBase2, AliasIntf1))
Yegappan Lakshmananb49ad282023-08-27 19:08:40 +02003854 enddef
3855 Foo()
Ernie Rael3da696d2023-09-19 20:14:18 +02003856
3857 var o_null: Base1
3858 assert_false(instanceof(o_null, Base1))
3859
LemonBoyafe04662023-08-23 21:08:11 +02003860 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003861 v9.CheckSourceSuccess(lines)
Ernie Rael2025af12023-12-12 16:58:00 +01003862
3863 lines =<< trim END
3864 vim9script
3865
3866 class Base1
3867 endclass
3868 instanceof(Base1.new())
3869 END
3870 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3871
3872 lines =<< trim END
3873 vim9script
3874
3875 class Base1
3876 endclass
3877 def F()
3878 instanceof(Base1.new())
3879 enddef
3880 F()
3881 END
3882 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: instanceof')
3883
3884 lines =<< trim END
3885 vim9script
3886
3887 class Base1
3888 endclass
3889
3890 class Base2
3891 endclass
3892
3893 var o = Base2.new()
3894 instanceof(o, Base1, Base2, 3)
3895 END
3896 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4', 10)
3897
3898 lines =<< trim END
3899 vim9script
3900
3901 class Base1
3902 endclass
3903
3904 class Base2
3905 endclass
3906
3907 def F()
3908 var o = Base2.new()
3909 instanceof(o, Base1, Base2, 3)
3910 enddef
3911 F()
3912 END
3913 v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 4')
LemonBoyafe04662023-08-23 21:08:11 +02003914enddef
3915
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003916" Test for calling a method in the parent class that is extended partially.
3917" This used to fail with the 'E118: Too many arguments for function: Text' error
3918" message (Github issue #12524).
3919def Test_call_method_in_parent_class()
3920 var lines =<< trim END
3921 vim9script
3922
3923 class Widget
Doug Kearns74da0ee2023-12-14 20:26:26 +01003924 var _lnum: number = 1
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003925
3926 def SetY(lnum: number)
3927 this._lnum = lnum
3928 enddef
3929
3930 def Text(): string
3931 return ''
3932 enddef
3933 endclass
3934
3935 class Foo extends Widget
3936 def Text(): string
3937 return '<Foo>'
3938 enddef
3939 endclass
3940
3941 def Stack(w1: Widget, w2: Widget): list<Widget>
3942 w1.SetY(1)
3943 w2.SetY(2)
3944 return [w1, w2]
3945 enddef
3946
3947 var foo1 = Foo.new()
3948 var foo2 = Foo.new()
3949 var l = Stack(foo1, foo2)
3950 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02003951 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanana456b122023-08-16 20:14:37 +02003952enddef
3953
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02003954" Test for calling methods from three levels of classes
3955def Test_multi_level_method_call()
3956 var lines =<< trim END
3957 vim9script
3958
3959 var A_func1: number = 0
3960 var A_func2: number = 0
3961 var A_func3: number = 0
3962 var B_func2: number = 0
3963 var B_func3: number = 0
3964 var C_func3: number = 0
3965
3966 class A
3967 def Func1()
3968 A_func1 += 1
3969 enddef
3970
3971 def Func2()
3972 A_func2 += 1
3973 enddef
3974
3975 def Func3()
3976 A_func3 += 1
3977 enddef
3978 endclass
3979
3980 class B extends A
3981 def Func2()
3982 B_func2 += 1
3983 enddef
3984
3985 def Func3()
3986 B_func3 += 1
3987 enddef
3988 endclass
3989
3990 class C extends B
3991 def Func3()
3992 C_func3 += 1
3993 enddef
3994 endclass
3995
3996 def A_CallFuncs(a: A)
3997 a.Func1()
3998 a.Func2()
3999 a.Func3()
4000 enddef
4001
4002 def B_CallFuncs(b: B)
4003 b.Func1()
4004 b.Func2()
4005 b.Func3()
4006 enddef
4007
4008 def C_CallFuncs(c: C)
4009 c.Func1()
4010 c.Func2()
4011 c.Func3()
4012 enddef
4013
4014 var cobj = C.new()
4015 A_CallFuncs(cobj)
4016 B_CallFuncs(cobj)
4017 C_CallFuncs(cobj)
4018 assert_equal(3, A_func1)
4019 assert_equal(0, A_func2)
4020 assert_equal(0, A_func3)
4021 assert_equal(3, B_func2)
4022 assert_equal(0, B_func3)
4023 assert_equal(3, C_func3)
4024 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004025 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004026enddef
4027
4028" Test for using members from three levels of classes
4029def Test_multi_level_member_access()
4030 var lines =<< trim END
4031 vim9script
4032
4033 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004034 public var val1: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004035 endclass
4036
4037 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01004038 public var val2: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004039 endclass
4040
4041 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01004042 public var val3: number = 0
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004043 endclass
4044
4045 def A_members(a: A)
4046 a.val1 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004047 enddef
4048
4049 def B_members(b: B)
4050 b.val1 += 1
4051 b.val2 += 1
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004052 enddef
4053
4054 def C_members(c: C)
4055 c.val1 += 1
4056 c.val2 += 1
4057 c.val3 += 1
4058 enddef
4059
4060 var cobj = C.new()
4061 A_members(cobj)
4062 B_members(cobj)
4063 C_members(cobj)
4064 assert_equal(3, cobj.val1)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02004065 assert_equal(2, cobj.val2)
4066 assert_equal(1, cobj.val3)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004067 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004068 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananb1027282023-08-19 11:26:42 +02004069enddef
4070
LemonBoy0ffc17a2023-08-20 18:09:11 +02004071" Test expansion of <stack> with class methods.
4072def Test_stack_expansion_with_methods()
4073 var lines =<< trim END
4074 vim9script
4075
4076 class C
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004077 def M1()
4078 F0()
4079 enddef
LemonBoy0ffc17a2023-08-20 18:09:11 +02004080 endclass
4081
4082 def F0()
Ernie Rael16cdfa62024-04-02 19:05:39 +02004083 assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
LemonBoy0ffc17a2023-08-20 18:09:11 +02004084 enddef
4085
4086 def F()
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004087 C.new().M1()
LemonBoy0ffc17a2023-08-20 18:09:11 +02004088 enddef
4089
4090 F()
4091 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004092 v9.CheckSourceSuccess(lines)
LemonBoy0ffc17a2023-08-20 18:09:11 +02004093enddef
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004094
4095" Test the return type of the new() constructor
4096def Test_new_return_type()
4097 # new() uses the default return type and there is no return statement
4098 var lines =<< trim END
4099 vim9script
4100
4101 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004102 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004103
4104 def new(this._bufnr)
4105 if !bufexists(this._bufnr)
4106 this._bufnr = -1
4107 endif
4108 enddef
4109 endclass
4110
4111 var c = C.new(12345)
4112 assert_equal('object<C>', typename(c))
4113
4114 var v1: C
4115 v1 = C.new(12345)
4116 assert_equal('object<C>', typename(v1))
4117
4118 def F()
4119 var v2: C
4120 v2 = C.new(12345)
4121 assert_equal('object<C>', typename(v2))
4122 enddef
4123 F()
4124 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004125 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004126
4127 # new() uses the default return type and an empty 'return' statement
4128 lines =<< trim END
4129 vim9script
4130
4131 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004132 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004133
4134 def new(this._bufnr)
4135 if !bufexists(this._bufnr)
4136 this._bufnr = -1
4137 return
4138 endif
4139 enddef
4140 endclass
4141
4142 var c = C.new(12345)
4143 assert_equal('object<C>', typename(c))
4144
4145 var v1: C
4146 v1 = C.new(12345)
4147 assert_equal('object<C>', typename(v1))
4148
4149 def F()
4150 var v2: C
4151 v2 = C.new(12345)
4152 assert_equal('object<C>', typename(v2))
4153 enddef
4154 F()
4155 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004156 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004157
4158 # new() uses "any" return type and returns "this"
4159 lines =<< trim END
4160 vim9script
4161
4162 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004163 var _bufnr: number
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004164
4165 def new(this._bufnr): any
4166 if !bufexists(this._bufnr)
4167 this._bufnr = -1
4168 return this
4169 endif
4170 enddef
4171 endclass
4172 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004173 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 11)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004174
4175 # new() uses 'Dict' return type and returns a Dict
4176 lines =<< trim END
4177 vim9script
4178
4179 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004180 var _state: dict<any>
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004181
4182 def new(): dict<any>
4183 this._state = {}
4184 return this._state
4185 enddef
4186 endclass
4187
4188 var c = C.new()
4189 assert_equal('object<C>', typename(c))
4190 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004191 v9.CheckSourceFailure(lines, 'E1365: Cannot use a return type with the "new" method', 9)
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +02004192enddef
4193
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004194" Test for checking a member initialization type at run time.
4195def Test_runtime_type_check_for_member_init()
4196 var lines =<< trim END
4197 vim9script
4198
4199 var retnum: bool = false
4200
4201 def F(): any
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004202 retnum = !retnum
4203 if retnum
4204 return 1
4205 else
4206 return "hello"
4207 endif
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004208 enddef
4209
4210 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004211 var _foo: bool = F()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004212 endclass
4213
4214 var c1 = C.new()
4215 var c2 = C.new()
4216 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02004217 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected bool but got string', 0)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004218enddef
4219
4220" Test for locking a variable referring to an object and reassigning to another
4221" object.
Ernie Raelee865f32023-09-29 19:53:55 +02004222def Test_lockvar_object()
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004223 var lines =<< trim END
4224 vim9script
4225
4226 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004227 var val: number
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004228 def new(this.val)
4229 enddef
4230 endclass
4231
4232 var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
4233 lockvar 2 some_dict
4234
4235 var current: C
4236 current = some_dict['c']
4237 assert_equal(3, current.val)
4238 current = some_dict['b']
4239 assert_equal(2, current.val)
4240
4241 def F()
4242 current = some_dict['c']
4243 enddef
4244
4245 def G()
4246 current = some_dict['b']
4247 enddef
4248
4249 F()
4250 assert_equal(3, current.val)
4251 G()
4252 assert_equal(2, current.val)
4253 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02004254 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +02004255enddef
4256
Ernie Raelee865f32023-09-29 19:53:55 +02004257" Test trying to lock an object variable from various places
4258def Test_lockvar_object_variable()
4259 # An object variable lockvar has several cases:
4260 # object method, scriptlevel, scriplevel from :def, :def arg
4261 # method arg, static method arg.
4262 # Also different depths
4263
Ernie Raelee865f32023-09-29 19:53:55 +02004264 #
4265 # lockvar of read-only object variable
4266 #
4267
4268 # read-only lockvar from object method
4269 var lines =<< trim END
4270 vim9script
4271
4272 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004273 var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004274 def Lock()
4275 lockvar this.val1
4276 enddef
4277 endclass
4278 var o = C.new(3)
4279 o.Lock()
4280 END
Ernie Rael64885642023-10-04 20:16:22 +02004281 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004282
4283 # read-only lockvar from scriptlevel
4284 lines =<< trim END
4285 vim9script
4286
4287 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004288 var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004289 endclass
4290 var o = C.new(3)
4291 lockvar o.val2
4292 END
4293 v9.CheckSourceFailure(lines, 'E1335: Variable "val2" in class "C" is not writable')
4294
4295 # read-only lockvar of scriptlevel variable from def
4296 lines =<< trim END
4297 vim9script
4298
4299 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004300 var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004301 endclass
4302 var o = C.new(3)
4303 def Lock()
4304 lockvar o.val3
4305 enddef
4306 Lock()
4307 END
4308 v9.CheckSourceFailure(lines, 'E1335: Variable "val3" in class "C" is not writable')
4309
4310 # read-only lockvar of def argument variable
4311 lines =<< trim END
4312 vim9script
4313
4314 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004315 var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004316 endclass
4317 def Lock(o: C)
4318 lockvar o.val4
4319 enddef
4320 Lock(C.new(3))
4321 END
4322 v9.CheckSourceFailure(lines, 'E1335: Variable "val4" in class "C" is not writable')
4323
4324 # TODO: the following tests use type "any" for argument. Need a run time
4325 # check for access. Probably OK as is for now.
4326
4327 # read-only lockvar from object method arg
4328 lines =<< trim END
4329 vim9script
4330
4331 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004332 var val5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004333 def Lock(o_any: any)
4334 lockvar o_any.val5
4335 enddef
4336 endclass
4337 var o = C.new(3)
4338 o.Lock(C.new(5))
4339 END
Ernie Rael64885642023-10-04 20:16:22 +02004340 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val5" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004341
4342 # read-only lockvar from class method arg
4343 lines =<< trim END
4344 vim9script
4345
4346 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004347 var val6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004348 static def Lock(o_any: any)
4349 lockvar o_any.val6
4350 enddef
4351 endclass
4352 var o = C.new(3)
4353 C.Lock(o)
4354 END
Ernie Rael64885642023-10-04 20:16:22 +02004355 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val6" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004356
4357 #
4358 # lockvar of public object variable
4359 #
4360
4361 # lockvar from object method
4362 lines =<< trim END
4363 vim9script
4364
4365 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004366 public var val1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004367 def Lock()
4368 lockvar this.val1
4369 enddef
4370 endclass
4371 var o = C.new(3)
4372 o.Lock()
4373 END
4374 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "this.val1" in class "C"', 1)
4375
4376 # lockvar from scriptlevel
4377 lines =<< trim END
4378 vim9script
4379
4380 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004381 public var val2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004382 endclass
4383 var o = C.new(3)
4384 lockvar o.val2
4385 END
4386 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val2" in class "C"', 7)
4387
4388 # lockvar of scriptlevel variable from def
4389 lines =<< trim END
4390 vim9script
4391
4392 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004393 public var val3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004394 endclass
4395 var o = C.new(3)
4396 def Lock()
4397 lockvar o.val3
4398 enddef
4399 Lock()
4400 END
4401 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val3" in class "C"', 1)
4402
4403 # lockvar of def argument variable
4404 lines =<< trim END
4405 vim9script
4406
4407 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004408 public var val4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004409 endclass
4410 def Lock(o: C)
4411 lockvar o.val4
4412 enddef
4413 Lock(C.new(3))
4414 END
4415 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o.val4" in class "C"', 1)
4416
4417 # lockvar from object method arg
4418 lines =<< trim END
4419 vim9script
4420
4421 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004422 public var val5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004423 def Lock(o_any: any)
4424 lockvar o_any.val5
4425 enddef
4426 endclass
4427 var o = C.new(3)
4428 o.Lock(C.new(5))
4429 END
4430 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val5" in class "C"', 1)
4431
4432 # lockvar from class method arg
4433 lines =<< trim END
4434 vim9script
4435
4436 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004437 public var val6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004438 static def Lock(o_any: any)
4439 lockvar o_any.val6
4440 enddef
4441 endclass
4442 var o = C.new(3)
4443 C.Lock(o)
4444 END
4445 v9.CheckSourceFailure(lines, 'E1391: Cannot (un)lock variable "o_any.val6" in class "C"', 1)
4446enddef
4447
4448" Test trying to lock a class variable from various places
4449def Test_lockvar_class_variable()
4450
4451 # lockvar bare static from object method
4452 var lines =<< trim END
4453 vim9script
4454
4455 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004456 public static var sval1: number
Ernie Raelee865f32023-09-29 19:53:55 +02004457 def Lock()
4458 lockvar sval1
4459 enddef
4460 endclass
4461 var o = C.new()
4462 o.Lock()
4463 END
4464 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval1" in class "C"', 1)
4465
4466 # lockvar C.static from object method
4467 lines =<< trim END
4468 vim9script
4469
4470 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004471 public static var sval2: number
Ernie Raelee865f32023-09-29 19:53:55 +02004472 def Lock()
4473 lockvar C.sval2
4474 enddef
4475 endclass
4476 var o = C.new()
4477 o.Lock()
4478 END
4479 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval2" in class "C"', 1)
4480
4481 # lockvar bare static from class method
4482 lines =<< trim END
4483 vim9script
4484
4485 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004486 public static var sval3: number
Ernie Raelee865f32023-09-29 19:53:55 +02004487 static def Lock()
4488 lockvar sval3
4489 enddef
4490 endclass
4491 C.Lock()
4492 END
4493 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval3" in class "C"', 1)
4494
4495 # lockvar C.static from class method
4496 lines =<< trim END
4497 vim9script
4498
4499 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004500 public static var sval4: number
Ernie Raelee865f32023-09-29 19:53:55 +02004501 static def Lock()
4502 lockvar C.sval4
4503 enddef
4504 endclass
4505 C.Lock()
4506 END
4507 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval4" in class "C"', 1)
4508
4509 # lockvar C.static from script level
4510 lines =<< trim END
4511 vim9script
4512
4513 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004514 public static var sval5: number
Ernie Raelee865f32023-09-29 19:53:55 +02004515 endclass
4516 lockvar C.sval5
4517 END
4518 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "C.sval5" in class "C"', 6)
4519
4520 # lockvar o.static from script level
4521 lines =<< trim END
4522 vim9script
4523
4524 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004525 public static var sval6: number
Ernie Raelee865f32023-09-29 19:53:55 +02004526 endclass
4527 var o = C.new()
4528 lockvar o.sval6
4529 END
4530 v9.CheckSourceFailure(lines, 'E1375: Class variable "sval6" accessible only using class "C"', 7)
4531enddef
4532
4533" Test locking an argument to :def
4534def Test_lockvar_argument()
4535 # Lockvar a function arg
4536 var lines =<< trim END
4537 vim9script
4538
4539 def Lock(val: any)
4540 lockvar val
4541 enddef
4542
4543 var d = {a: 1, b: 2}
4544 Lock(d)
4545
4546 d->extend({c: 3})
4547 END
4548 v9.CheckSourceFailure(lines, 'E741: Value is locked: extend() argument')
4549
4550 # Lockvar a function arg. Verify "sval" is interpreted as argument and not a
4551 # class member in "C". This tests lval_root_is_arg.
4552 lines =<< trim END
4553 vim9script
4554
4555 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004556 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004557 endclass
4558
4559 def Lock2(sval: any)
4560 lockvar sval
4561 enddef
4562
4563 var o = C.new()
4564 Lock2(o)
4565 END
4566 v9.CheckSourceSuccess(lines)
4567
4568 # Lock a class.
4569 lines =<< trim END
4570 vim9script
4571
4572 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004573 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004574 endclass
4575
4576 def Lock2(sval: any)
4577 lockvar sval
4578 enddef
4579
4580 Lock2(C)
4581 END
Ernie Raelb077b582023-12-14 20:11:44 +01004582 v9.CheckSourceFailure(lines, 'E1405: Class "C" cannot be used as a value')
Ernie Raelee865f32023-09-29 19:53:55 +02004583
4584 # Lock an object.
4585 lines =<< trim END
4586 vim9script
4587
4588 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004589 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004590 endclass
4591
4592 def Lock2(sval: any)
4593 lockvar sval
4594 enddef
4595
4596 Lock2(C.new())
4597 END
4598 v9.CheckSourceSuccess(lines)
4599
4600 # In this case (unlike previous) "lockvar sval" is a class member.
4601 lines =<< trim END
4602 vim9script
4603
4604 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004605 public static var sval: list<number>
Ernie Raelee865f32023-09-29 19:53:55 +02004606 def Lock2()
4607 lockvar sval
4608 enddef
4609 endclass
4610
4611
4612 var o = C.new()
4613 o.Lock2()
4614 END
4615 v9.CheckSourceFailure(lines, 'E1392: Cannot (un)lock class variable "sval" in class "C"', 1)
4616enddef
4617
4618" Test that this can be locked without error
4619def Test_lockvar_this()
4620 # lockvar this
4621 var lines =<< trim END
4622 vim9script
4623 class C
4624 def TLock()
4625 lockvar this
4626 enddef
4627 endclass
4628 var o = C.new()
4629 o.TLock()
4630 END
4631 v9.CheckSourceSuccess(lines)
4632
4633 # lockvar four (four letter word, but not this)
4634 lines =<< trim END
4635 vim9script
4636 class C
4637 def TLock4()
4638 var four: number
4639 lockvar four
4640 enddef
4641 endclass
4642 var o = C.new()
4643 o.TLock4()
4644 END
4645 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4646
4647 # lockvar this5; "this" + one char, 5 letter word, starting with "this"
4648 lines =<< trim END
4649 vim9script
4650 class C
4651 def TLock5()
4652 var this5: number
4653 lockvar this5
4654 enddef
4655 endclass
4656 var o = C.new()
4657 o.TLock5()
4658 END
4659 v9.CheckSourceFailure(lines, 'E1178: Cannot lock or unlock a local variable')
4660enddef
4661
4662" Test some general lockvar cases
4663def Test_lockvar_general()
4664 # lockvar an object and a class. It does nothing
4665 var lines =<< trim END
4666 vim9script
4667 class C
4668 endclass
4669 var o = C.new()
4670 lockvar o
4671 lockvar C
4672 END
4673 v9.CheckSourceSuccess(lines)
4674
4675 # Lock a list element that's nested in an object variable from a :def
4676 lines =<< trim END
4677 vim9script
4678
4679 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004680 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004681 endclass
4682 def Lock2(obj: any)
4683 lockvar obj.val[1]
4684 enddef
4685
4686 var o = C.new()
4687 Lock2(o)
4688 o.val[0] = [9]
4689 assert_equal([ [9], [2], [3] ], o.val)
4690 try
4691 o.val[1] = [999]
4692 call assert_false(true, 'assign should have failed')
4693 catch
4694 assert_exception('E741:')
4695 endtry
4696 o.val[2] = [8]
4697 assert_equal([ [9], [2], [8] ], o.val)
4698 END
4699 v9.CheckSourceSuccess(lines)
4700
4701 # Lock a list element that's nested in an object variable from scriptlevel
4702 lines =<< trim END
4703 vim9script
4704
4705 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004706 public var val: list<list<number>> = [ [1], [2], [3] ]
Ernie Raelee865f32023-09-29 19:53:55 +02004707 endclass
4708
4709 var o = C.new()
4710 lockvar o.val[1]
4711 o.val[0] = [9]
4712 assert_equal([ [9], [2], [3] ], o.val)
4713 try
4714 o.val[1] = [999]
4715 call assert_false(true, 'assign should have failed')
4716 catch
4717 assert_exception('E741:')
4718 endtry
4719 o.val[2] = [8]
4720 assert_equal([ [9], [2], [8] ], o.val)
4721 END
4722 v9.CheckSourceSuccess(lines)
Ernie Rael64885642023-10-04 20:16:22 +02004723
4724 # lock a script level variable from an object method
4725 lines =<< trim END
4726 vim9script
4727
4728 class C
4729 def Lock()
4730 lockvar l
4731 enddef
4732 endclass
4733
4734 var l = [1]
4735 C.new().Lock()
4736 l[0] = 11
4737 END
4738 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[0] = 11', 11)
4739
Ernie Rael03042a22023-11-11 08:53:32 +01004740 # lock a list element referenced by a protected object variable
Ernie Rael64885642023-10-04 20:16:22 +02004741 # in an object fetched via a script level list
4742 lines =<< trim END
4743 vim9script
4744
4745 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004746 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004747 def Lock()
4748 lockvar lc[0]._v1[1]
4749 enddef
4750 endclass
4751
4752 var l = [[1], [2], [3]]
4753 var o = C.new(l)
4754 var lc: list<C> = [ o ]
4755
4756 o.Lock()
4757 l[0] = [22]
4758 l[1] = [33]
4759 END
4760 v9.CheckSourceFailure(lines, 'E741: Value is locked: l[1] = [33]', 16)
4761
4762 # similar to the previous test, except the locking code is executing
Ernie Rael03042a22023-11-11 08:53:32 +01004763 # in a class that does not own the protected variable.
4764 # Note that the locking code is in a class has a protected variable of
Ernie Rael64885642023-10-04 20:16:22 +02004765 # the same name.
4766 lines =<< trim END
4767 vim9script
4768
4769 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004770 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004771 def Lock(obj: any)
4772 lockvar lc[0]._v1[1]
4773 enddef
4774 endclass
4775
4776 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004777 var _v1: list<list<number>>
Ernie Rael64885642023-10-04 20:16:22 +02004778 endclass
4779
4780 var l = [[1], [2], [3]]
4781 var o = C.new(l)
4782 var lc: list<C> = [ o ]
4783
4784 var o2 = C2.new()
4785 o2.Lock(o)
4786 END
Ernie Rael03042a22023-11-11 08:53:32 +01004787 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_v1" in class "C"')
Ernie Raelee865f32023-09-29 19:53:55 +02004788enddef
4789
Ernie Rael9771b2a2023-10-07 22:05:40 +02004790" Test builtin islocked()
4791def Test_lockvar_islocked()
4792 # Can't lock class/object variable
4793 # Lock class/object variable's value
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01004794 # Lock item of variable's value (a list item)
4795 # variable is at index 1 within class/object
Ernie Rael9771b2a2023-10-07 22:05:40 +02004796 var lines =<< trim END
4797 vim9script
4798
4799 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01004800 var o0: list<list<number>> = [ [0], [1], [2]]
4801 var o1: list<list<number>> = [[10], [11], [12]]
4802 static var c0: list<list<number>> = [[20], [21], [22]]
4803 static var c1: list<list<number>> = [[30], [31], [32]]
Ernie Rael9771b2a2023-10-07 22:05:40 +02004804 endclass
4805
4806 def LockIt(arg: any)
4807 lockvar arg
4808 enddef
4809
4810 def UnlockIt(arg: any)
4811 unlockvar arg
4812 enddef
4813
4814 var obj = C.new()
4815 #lockvar obj.o1 # can't lock something you can't write to
4816
4817 try
4818 lockvar obj.o1 # can't lock something you can't write to
4819 call assert_false(1, '"lockvar obj.o1" should have failed')
4820 catch
4821 call assert_exception('E1335:')
4822 endtry
4823
4824 LockIt(obj.o1) # but can lock it's value
4825 assert_equal(1, islocked("obj.o1"))
4826 assert_equal(1, islocked("obj.o1[0]"))
4827 assert_equal(1, islocked("obj.o1[1]"))
4828 UnlockIt(obj.o1)
4829 assert_equal(0, islocked("obj.o1"))
4830 assert_equal(0, islocked("obj.o1[0]"))
4831
4832 lockvar obj.o1[0]
4833 assert_equal(0, islocked("obj.o1"))
4834 assert_equal(1, islocked("obj.o1[0]"))
4835 assert_equal(0, islocked("obj.o1[1]"))
4836 unlockvar obj.o1[0]
4837 assert_equal(0, islocked("obj.o1"))
4838 assert_equal(0, islocked("obj.o1[0]"))
4839
4840 # Same thing, but with a static
4841
4842 try
4843 lockvar C.c1 # can't lock something you can't write to
4844 call assert_false(1, '"lockvar C.c1" should have failed')
4845 catch
4846 call assert_exception('E1335:')
4847 endtry
4848
4849 LockIt(C.c1) # but can lock it's value
4850 assert_equal(1, islocked("C.c1"))
4851 assert_equal(1, islocked("C.c1[0]"))
4852 assert_equal(1, islocked("C.c1[1]"))
4853 UnlockIt(C.c1)
4854 assert_equal(0, islocked("C.c1"))
4855 assert_equal(0, islocked("C.c1[0]"))
4856
4857 lockvar C.c1[0]
4858 assert_equal(0, islocked("C.c1"))
4859 assert_equal(1, islocked("C.c1[0]"))
4860 assert_equal(0, islocked("C.c1[1]"))
4861 unlockvar C.c1[0]
4862 assert_equal(0, islocked("C.c1"))
4863 assert_equal(0, islocked("C.c1[0]"))
4864 END
4865 v9.CheckSourceSuccess(lines)
Ernie Rael4c8da022023-10-11 21:35:11 +02004866
4867 # Do islocked() from an object method
4868 # and then from a class method
Ernie Rael9771b2a2023-10-07 22:05:40 +02004869 lines =<< trim END
Ernie Rael4c8da022023-10-11 21:35:11 +02004870 vim9script
4871
4872 var l0o0 = [ [0], [1], [2]]
4873 var l0o1 = [ [10], [11], [12]]
4874 var l0c0 = [[120], [121], [122]]
4875 var l0c1 = [[130], [131], [132]]
4876
4877 class C0
Doug Kearns74da0ee2023-12-14 20:26:26 +01004878 var o0: list<list<number>> = l0o0
4879 var o1: list<list<number>> = l0o1
4880 static var c0: list<list<number>> = l0c0
4881 static var c1: list<list<number>> = l0c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004882 def Islocked(arg: string): number
4883 return islocked(arg)
4884 enddef
4885 static def SIslocked(arg: string): number
4886 return islocked(arg)
4887 enddef
4888 endclass
4889
4890 var l2o0 = [[20000], [20001], [20002]]
4891 var l2o1 = [[20010], [20011], [20012]]
4892 var l2c0 = [[20120], [20121], [20122]]
4893 var l2c1 = [[20130], [20131], [20132]]
4894
4895 class C2
Doug Kearns74da0ee2023-12-14 20:26:26 +01004896 var o0: list<list<number>> = l2o0
4897 var o1: list<list<number>> = l2o1
4898 static var c0: list<list<number>> = l2c0
4899 static var c1: list<list<number>> = l2c1
Ernie Rael4c8da022023-10-11 21:35:11 +02004900 def Islocked(arg: string): number
4901 return islocked(arg)
4902 enddef
4903 static def SIslocked(arg: string): number
4904 return islocked(arg)
4905 enddef
4906 endclass
4907
4908 var obj0 = C0.new()
4909 var obj2 = C2.new()
4910
4911 var l = [ obj0, null_object, obj2 ]
4912
4913 # lock list, object func access through script var expr
4914 assert_equal(0, obj0.Islocked("l[0].o0"))
4915 assert_equal(0, obj0.Islocked("l[0].o0[2]"))
4916 lockvar l0o0
4917 assert_equal(1, obj0.Islocked("l[0].o0"))
4918 assert_equal(1, obj0.Islocked("l[0].o0[2]"))
4919
4920 #echo "check-b" obj2.Islocked("l[1].o1") # NULL OBJECT
4921
4922 # lock list element, object func access through script var expr
4923 lockvar l0o1[1]
4924 assert_equal(0, obj0.Islocked("this.o1[0]"))
4925 assert_equal(1, obj0.Islocked("this.o1[1]"))
4926
4927 assert_equal(0, obj0.Islocked("this.o1"))
4928 lockvar l0o1
4929 assert_equal(1, obj0.Islocked("this.o1"))
4930 unlockvar l0o1
4931
4932 lockvar l0c1[1]
4933
4934 # static by class name member expr from same class
4935 assert_equal(0, obj0.Islocked("C0.c1[0]"))
4936 assert_equal(1, obj0.Islocked("C0.c1[1]"))
4937 # static by bare name member expr from same class
4938 assert_equal(0, obj0.Islocked("c1[0]"))
4939 assert_equal(1, obj0.Islocked("c1[1]"))
4940
4941 # static by class name member expr from other class
4942 assert_equal(0, obj2.Islocked("C0.c1[0]"))
4943 assert_equal(1, obj2.Islocked("C0.c1[1]"))
4944 # static by bare name member expr from other class
4945 assert_equal(0, obj2.Islocked("c1[0]"))
4946 assert_equal(0, obj2.Islocked("c1[1]"))
4947
4948
4949 # static by bare name in same class
4950 assert_equal(0, obj0.Islocked("c0"))
4951 lockvar l0c0
4952 assert_equal(1, obj0.Islocked("c0"))
4953
4954 #
4955 # similar stuff, but use static method
4956 #
4957
4958 unlockvar l0o0
4959
4960 # lock list, object func access through script var expr
4961 assert_equal(0, C0.SIslocked("l[0].o0"))
4962 assert_equal(0, C0.SIslocked("l[0].o0[2]"))
4963 lockvar l0o0
4964 assert_equal(1, C0.SIslocked("l[0].o0"))
4965 assert_equal(1, C0.SIslocked("l[0].o0[2]"))
4966
4967 unlockvar l0o1
4968
4969 # can't access "this" from class method
4970 try
4971 C0.SIslocked("this.o1[0]")
4972 call assert_0(1, '"C0.SIslocked("this.o1[0]")" should have failed')
4973 catch
4974 call assert_exception('E121: Undefined variable: this')
4975 endtry
4976
4977 lockvar l0c1[1]
4978
4979 # static by class name member expr from same class
4980 assert_equal(0, C0.SIslocked("C0.c1[0]"))
4981 assert_equal(1, C0.SIslocked("C0.c1[1]"))
4982 # static by bare name member expr from same class
4983 assert_equal(0, C0.SIslocked("c1[0]"))
4984 assert_equal(1, C0.SIslocked("c1[1]"))
4985
4986 # static by class name member expr from other class
4987 assert_equal(0, C2.SIslocked("C0.c1[0]"))
4988 assert_equal(1, C2.SIslocked("C0.c1[1]"))
4989 # static by bare name member expr from other class
4990 assert_equal(0, C2.SIslocked("c1[0]"))
4991 assert_equal(0, C2.SIslocked("c1[1]"))
4992
4993
4994 # static by bare name in same class
4995 unlockvar l0c0
4996 assert_equal(0, C0.SIslocked("c0"))
4997 lockvar l0c0
4998 assert_equal(1, C0.SIslocked("c0"))
Ernie Rael9771b2a2023-10-07 22:05:40 +02004999 END
Ernie Rael4c8da022023-10-11 21:35:11 +02005000 v9.CheckSourceSuccess(lines)
5001
5002 # Check islocked class/object from various places.
5003 lines =<< trim END
5004 vim9script
5005
5006 class C
5007 def Islocked(arg: string): number
5008 return islocked(arg)
5009 enddef
5010 static def SIslocked(arg: string): number
5011 return islocked(arg)
5012 enddef
5013 endclass
5014 var obj = C.new()
5015
5016 # object method
5017 assert_equal(0, obj.Islocked("this"))
5018 assert_equal(0, obj.Islocked("C"))
5019
5020 # class method
5021 ### assert_equal(0, C.SIslocked("this"))
5022 assert_equal(0, C.SIslocked("C"))
5023
5024 #script level
5025 var v: number
5026 v = islocked("C")
5027 assert_equal(0, v)
5028 v = islocked("obj")
5029 assert_equal(0, v)
5030 END
5031 v9.CheckSourceSuccess(lines)
5032enddef
5033
5034def Test_lockvar_islocked_notfound()
5035 # Try non-existent things
5036 var lines =<< trim END
5037 vim9script
5038
5039 class C
5040 def Islocked(arg: string): number
5041 return islocked(arg)
5042 enddef
5043 static def SIslocked(arg: string): number
5044 return islocked(arg)
5045 enddef
5046 endclass
5047 var obj = C.new()
5048 assert_equal(-1, obj.Islocked("anywhere"))
5049 assert_equal(-1, C.SIslocked("notanywhere"))
5050 END
5051 v9.CheckSourceSuccess(lines)
5052
5053 # Something not found of the form "name1.name2" is an error
5054 lines =<< trim END
5055 vim9script
5056
5057 islocked("one.two")
5058 END
5059 v9.CheckSourceFailure(lines, 'E121: Undefined variable: one')
5060
5061 lines =<< trim END
5062 vim9script
5063
5064 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005065 var val = { key: "value" }
Ernie Rael4c8da022023-10-11 21:35:11 +02005066 def Islocked(arg: string): number
5067 return islocked(arg)
5068 enddef
5069 endclass
5070 var obj = C.new()
5071 obj.Islocked("this.val.not_there"))
5072 END
5073 v9.CheckSourceFailure(lines, 'E716: Key not present in Dictionary: "not_there"')
5074
5075 lines =<< trim END
5076 vim9script
5077
5078 class C
5079 def Islocked(arg: string): number
5080 return islocked(arg)
5081 enddef
5082 endclass
5083 var obj = C.new()
5084 obj.Islocked("this.notobjmember")
5085 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005086 v9.CheckSourceFailure(lines, 'E1326: Variable "notobjmember" not found in object "C"')
Ernie Rael4c8da022023-10-11 21:35:11 +02005087
5088 # access a script variable through methods
5089 lines =<< trim END
5090 vim9script
5091
5092 var l = [1]
5093 class C
5094 def Islocked(arg: string): number
5095 return islocked(arg)
5096 enddef
5097 static def SIslocked(arg: string): number
5098 return islocked(arg)
5099 enddef
5100 endclass
5101 var obj = C.new()
5102 assert_equal(0, obj.Islocked("l"))
5103 assert_equal(0, C.SIslocked("l"))
5104 lockvar l
5105 assert_equal(1, obj.Islocked("l"))
5106 assert_equal(1, C.SIslocked("l"))
5107 END
5108 v9.CheckSourceSuccess(lines)
Ernie Rael9771b2a2023-10-07 22:05:40 +02005109enddef
5110
Ernie Rael03042a22023-11-11 08:53:32 +01005111" Test for a protected object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005112def Test_private_object_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005113 # Try calling a protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005114 var lines =<< trim END
5115 vim9script
5116
5117 class A
5118 def _Foo(): number
5119 return 1234
5120 enddef
5121 endclass
5122 var a = A.new()
5123 a._Foo()
5124 END
Ernie Rael03042a22023-11-11 08:53:32 +01005125 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005126
Ernie Rael03042a22023-11-11 08:53:32 +01005127 # Try calling a protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005128 lines =<< trim END
5129 vim9script
5130
5131 class A
5132 def _Foo(): number
5133 return 1234
5134 enddef
5135 endclass
5136 def T()
5137 var a = A.new()
5138 a._Foo()
5139 enddef
5140 T()
5141 END
Ernie Rael03042a22023-11-11 08:53:32 +01005142 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005143
Ernie Rael03042a22023-11-11 08:53:32 +01005144 # Use a protected method from another object method (in script context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005145 lines =<< trim END
5146 vim9script
5147
5148 class A
5149 def _Foo(): number
5150 return 1234
5151 enddef
5152 def Bar(): number
5153 return this._Foo()
5154 enddef
5155 endclass
5156 var a = A.new()
5157 assert_equal(1234, a.Bar())
5158 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005159 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005160
Ernie Rael03042a22023-11-11 08:53:32 +01005161 # Use a protected method from another object method (def function context)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005162 lines =<< trim END
5163 vim9script
5164
5165 class A
5166 def _Foo(): number
5167 return 1234
5168 enddef
5169 def Bar(): number
5170 return this._Foo()
5171 enddef
5172 endclass
5173 def T()
5174 var a = A.new()
5175 assert_equal(1234, a.Bar())
5176 enddef
5177 T()
5178 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005179 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005180
Ernie Rael03042a22023-11-11 08:53:32 +01005181 # Try calling a protected method without the "this" prefix
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005182 lines =<< trim END
5183 vim9script
5184
5185 class A
5186 def _Foo(): number
5187 return 1234
5188 enddef
5189 def Bar(): number
5190 return _Foo()
5191 enddef
5192 endclass
5193 var a = A.new()
5194 a.Bar()
5195 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005196 v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005197
Ernie Rael03042a22023-11-11 08:53:32 +01005198 # Try calling a protected method using the class name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005199 lines =<< trim END
5200 vim9script
5201
5202 class A
5203 def _Foo(): number
5204 return 1234
5205 enddef
5206 endclass
5207 A._Foo()
5208 END
Ernie Rael03042a22023-11-11 08:53:32 +01005209 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005210
Ernie Rael03042a22023-11-11 08:53:32 +01005211 # Define two protected methods with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005212 lines =<< trim END
5213 vim9script
5214
5215 class A
5216 def _Foo()
5217 enddef
5218 def _Foo()
5219 enddef
5220 endclass
5221 var a = A.new()
5222 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005223 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005224
Ernie Rael03042a22023-11-11 08:53:32 +01005225 # Define a protected method and a object method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005226 lines =<< trim END
5227 vim9script
5228
5229 class A
5230 def _Foo()
5231 enddef
5232 def Foo()
5233 enddef
5234 endclass
5235 var a = A.new()
5236 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005237 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005238
Ernie Rael03042a22023-11-11 08:53:32 +01005239 # Define an object method and a protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005240 lines =<< trim END
5241 vim9script
5242
5243 class A
5244 def Foo()
5245 enddef
5246 def _Foo()
5247 enddef
5248 endclass
5249 var a = A.new()
5250 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005251 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005252
Ernie Rael03042a22023-11-11 08:53:32 +01005253 # Call a public method and a protected method from a protected method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005254 lines =<< trim END
5255 vim9script
5256
5257 class A
5258 def Foo(): number
5259 return 100
5260 enddef
5261 def _Bar(): number
5262 return 200
5263 enddef
5264 def _Baz()
5265 assert_equal(100, this.Foo())
5266 assert_equal(200, this._Bar())
5267 enddef
5268 def T()
5269 this._Baz()
5270 enddef
5271 endclass
5272 var a = A.new()
5273 a.T()
5274 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005275 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005276
Ernie Rael03042a22023-11-11 08:53:32 +01005277 # Try calling a protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005278 lines =<< trim END
5279 vim9script
5280
5281 class A
5282 def _Foo(): number
5283 return 100
5284 enddef
5285 endclass
5286 class B
5287 def Foo(): number
5288 var a = A.new()
5289 a._Foo()
5290 enddef
5291 endclass
5292 var b = B.new()
5293 b.Foo()
5294 END
Ernie Rael03042a22023-11-11 08:53:32 +01005295 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005296
Ernie Rael03042a22023-11-11 08:53:32 +01005297 # Call a protected object method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005298 lines =<< trim END
5299 vim9script
5300 class A
5301 def _Foo(): number
5302 return 1234
5303 enddef
5304 endclass
5305 class B extends A
5306 def Bar()
5307 enddef
5308 endclass
5309 class C extends B
5310 def Baz(): number
5311 return this._Foo()
5312 enddef
5313 endclass
5314 var c = C.new()
5315 assert_equal(1234, c.Baz())
5316 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005317 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005318
Ernie Rael03042a22023-11-11 08:53:32 +01005319 # Call a protected object method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005320 lines =<< trim END
5321 vim9script
5322 class A
5323 def _Foo(): number
5324 return 1234
5325 enddef
5326 endclass
5327 class B extends A
5328 def Bar()
5329 enddef
5330 endclass
5331 class C extends B
5332 def Baz(): number
5333 enddef
5334 endclass
5335 var c = C.new()
5336 assert_equal(1234, c._Foo())
5337 END
Ernie Rael03042a22023-11-11 08:53:32 +01005338 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005339
5340 # Using "_" prefix in a method name should fail outside of a class
5341 lines =<< trim END
5342 vim9script
5343 def _Foo(): number
5344 return 1234
5345 enddef
5346 var a = _Foo()
5347 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005348 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005349enddef
5350
Ernie Rael03042a22023-11-11 08:53:32 +01005351" Test for an protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005352def Test_private_class_method()
Ernie Rael03042a22023-11-11 08:53:32 +01005353 # Try calling a class protected method (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005354 var lines =<< trim END
5355 vim9script
5356
5357 class A
5358 static def _Foo(): number
5359 return 1234
5360 enddef
5361 endclass
5362 A._Foo()
5363 END
Ernie Rael03042a22023-11-11 08:53:32 +01005364 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 8)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005365
Ernie Rael03042a22023-11-11 08:53:32 +01005366 # Try calling a class protected method (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005367 lines =<< trim END
5368 vim9script
5369
5370 class A
5371 static def _Foo(): number
5372 return 1234
5373 enddef
5374 endclass
5375 def T()
5376 A._Foo()
5377 enddef
5378 T()
5379 END
Ernie Rael03042a22023-11-11 08:53:32 +01005380 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005381
Ernie Rael03042a22023-11-11 08:53:32 +01005382 # Try calling a class protected method using an object (at the script level)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005383 lines =<< trim END
5384 vim9script
5385
5386 class A
5387 static def _Foo(): number
5388 return 1234
5389 enddef
5390 endclass
5391 var a = A.new()
5392 a._Foo()
5393 END
Ernie Rael03042a22023-11-11 08:53:32 +01005394 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 9)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005395
Ernie Rael03042a22023-11-11 08:53:32 +01005396 # Try calling a class protected method using an object (from a def function)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005397 lines =<< trim END
5398 vim9script
5399
5400 class A
5401 static def _Foo(): number
5402 return 1234
5403 enddef
5404 endclass
5405 def T()
5406 var a = A.new()
5407 a._Foo()
5408 enddef
5409 T()
5410 END
Ernie Rael03042a22023-11-11 08:53:32 +01005411 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005412
Ernie Rael03042a22023-11-11 08:53:32 +01005413 # Use a class protected method from an object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005414 lines =<< trim END
5415 vim9script
5416
5417 class A
5418 static def _Foo(): number
5419 return 1234
5420 enddef
5421 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005422 assert_equal(1234, _Foo())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005423 enddef
5424 endclass
5425 var a = A.new()
5426 a.Bar()
5427 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005428 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005429
Ernie Rael03042a22023-11-11 08:53:32 +01005430 # Use a class protected method from another class protected method without the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005431 # class name prefix.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005432 lines =<< trim END
5433 vim9script
5434
5435 class A
5436 static def _Foo1(): number
5437 return 1234
5438 enddef
5439 static def _Foo2()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005440 assert_equal(1234, _Foo1())
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005441 enddef
5442 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02005443 _Foo2()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005444 enddef
5445 endclass
5446 var a = A.new()
5447 a.Bar()
5448 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005449 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005450
Ernie Rael03042a22023-11-11 08:53:32 +01005451 # Declare a class method and a class protected method with the same name
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005452 lines =<< trim END
5453 vim9script
5454
5455 class A
5456 static def _Foo()
5457 enddef
5458 static def Foo()
5459 enddef
5460 endclass
5461 var a = A.new()
5462 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005463 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 7)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005464
Ernie Rael03042a22023-11-11 08:53:32 +01005465 # Try calling a class protected method from another class
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005466 lines =<< trim END
5467 vim9script
5468
5469 class A
5470 static def _Foo(): number
5471 return 1234
5472 enddef
5473 endclass
5474 class B
5475 def Foo(): number
5476 return A._Foo()
5477 enddef
5478 endclass
5479 var b = B.new()
5480 assert_equal(1234, b.Foo())
5481 END
Ernie Rael03042a22023-11-11 08:53:32 +01005482 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005483
Ernie Rael03042a22023-11-11 08:53:32 +01005484 # Call a protected class method from a child class object method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005485 lines =<< trim END
5486 vim9script
5487 class A
5488 static def _Foo(): number
5489 return 1234
5490 enddef
5491 endclass
5492 class B extends A
5493 def Bar()
5494 enddef
5495 endclass
5496 class C extends B
5497 def Baz(): number
5498 return A._Foo()
5499 enddef
5500 endclass
5501 var c = C.new()
5502 assert_equal(1234, c.Baz())
5503 END
Ernie Rael03042a22023-11-11 08:53:32 +01005504 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005505
Ernie Rael03042a22023-11-11 08:53:32 +01005506 # Call a protected class method from a child class protected class method
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005507 lines =<< trim END
5508 vim9script
5509 class A
5510 static def _Foo(): number
5511 return 1234
5512 enddef
5513 endclass
5514 class B extends A
5515 def Bar()
5516 enddef
5517 endclass
5518 class C extends B
5519 static def Baz(): number
5520 return A._Foo()
5521 enddef
5522 endclass
5523 assert_equal(1234, C.Baz())
5524 END
Ernie Rael03042a22023-11-11 08:53:32 +01005525 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 1)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005526
Ernie Rael03042a22023-11-11 08:53:32 +01005527 # Call a protected class method from a child class object
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005528 lines =<< trim END
5529 vim9script
5530 class A
5531 static def _Foo(): number
5532 return 1234
5533 enddef
5534 endclass
5535 class B extends A
5536 def Bar()
5537 enddef
5538 endclass
5539 class C extends B
5540 def Baz(): number
5541 enddef
5542 endclass
5543 var c = C.new()
5544 assert_equal(1234, C._Foo())
5545 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005546 v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +02005547enddef
5548
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005549" Test for using the return value of a class/object method as a function
5550" argument.
5551def Test_objmethod_funcarg()
5552 var lines =<< trim END
5553 vim9script
5554
5555 class C
5556 def Foo(): string
5557 return 'foo'
5558 enddef
5559 endclass
5560
5561 def Bar(a: number, s: string): string
5562 return s
5563 enddef
5564
5565 def Baz(c: C)
5566 assert_equal('foo', Bar(10, c.Foo()))
5567 enddef
5568
5569 var t = C.new()
5570 Baz(t)
5571 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005572 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005573
5574 lines =<< trim END
5575 vim9script
5576
5577 class C
5578 static def Foo(): string
5579 return 'foo'
5580 enddef
5581 endclass
5582
5583 def Bar(a: number, s: string): string
5584 return s
5585 enddef
5586
5587 def Baz()
5588 assert_equal('foo', Bar(10, C.Foo()))
5589 enddef
5590
5591 Baz()
5592 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005593 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan639751d2023-08-27 19:23:37 +02005594enddef
5595
Ernie Raelcf138d42023-09-06 20:45:03 +02005596def Test_static_inheritence()
5597 # subclasses get their own static copy
5598 var lines =<< trim END
5599 vim9script
5600
5601 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005602 static var _svar: number
5603 var _mvar: number
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005604 def new()
5605 _svar = 1
5606 this._mvar = 101
5607 enddef
5608 def AccessObject(): number
5609 return this._mvar
5610 enddef
5611 def AccessStaticThroughObject(): number
5612 return _svar
5613 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005614 endclass
5615
5616 class B extends A
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005617 def new()
5618 this._mvar = 102
5619 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005620 endclass
5621
5622 class C extends B
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005623 def new()
5624 this._mvar = 103
5625 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005626
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005627 def AccessPrivateStaticThroughClassName(): number
5628 assert_equal(1, A._svar)
5629 return 444
5630 enddef
Ernie Raelcf138d42023-09-06 20:45:03 +02005631 endclass
5632
5633 var oa = A.new()
5634 var ob = B.new()
5635 var oc = C.new()
5636 assert_equal(101, oa.AccessObject())
5637 assert_equal(102, ob.AccessObject())
5638 assert_equal(103, oc.AccessObject())
5639
Ernie Rael03042a22023-11-11 08:53:32 +01005640 assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access protected variable "_svar" in class "A"')
Ernie Raelcf138d42023-09-06 20:45:03 +02005641
5642 # verify object properly resolves to correct static
5643 assert_equal(1, oa.AccessStaticThroughObject())
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005644 assert_equal(1, ob.AccessStaticThroughObject())
5645 assert_equal(1, oc.AccessStaticThroughObject())
Ernie Raelcf138d42023-09-06 20:45:03 +02005646 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005647 v9.CheckSourceSuccess(lines)
Ernie Raelcf138d42023-09-06 20:45:03 +02005648enddef
5649
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005650" Test for declaring duplicate object and class members
5651def Test_dup_member_variable()
5652 # Duplicate member variable
5653 var lines =<< trim END
5654 vim9script
5655 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005656 var val = 10
5657 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005658 endclass
5659 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005660 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005661
Ernie Rael03042a22023-11-11 08:53:32 +01005662 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005663 lines =<< trim END
5664 vim9script
5665 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005666 var _val = 10
5667 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005668 endclass
5669 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005670 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005671
5672 # Duplicate public member variable
5673 lines =<< trim END
5674 vim9script
5675 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005676 public var val = 10
5677 public var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005678 endclass
5679 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005680 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005681
Ernie Rael03042a22023-11-11 08:53:32 +01005682 # Duplicate protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005683 lines =<< trim END
5684 vim9script
5685 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005686 var val = 10
5687 var _val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005688 endclass
5689 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005690 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005691
Ernie Rael03042a22023-11-11 08:53:32 +01005692 # Duplicate public and protected member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005693 lines =<< trim END
5694 vim9script
5695 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005696 var _val = 20
5697 public var val = 10
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005698 endclass
5699 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005700 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005701
5702 # Duplicate class member variable
5703 lines =<< trim END
5704 vim9script
5705 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005706 static var s: string = "abc"
5707 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005708 endclass
5709 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005710 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005711
Ernie Rael03042a22023-11-11 08:53:32 +01005712 # Duplicate public and protected class member variable
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005713 lines =<< trim END
5714 vim9script
5715 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005716 public static var s: string = "abc"
5717 static var _s: string = "def"
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005718 endclass
5719 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005720 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _s', 4)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005721
5722 # Duplicate class and object member variable
5723 lines =<< trim END
5724 vim9script
5725 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01005726 static var val = 10
5727 var val = 20
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005728 def new()
5729 enddef
5730 endclass
5731 var c = C.new()
5732 assert_equal(10, C.val)
5733 assert_equal(20, c.val)
5734 END
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02005735 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 4)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005736
5737 # Duplicate object member variable in a derived class
5738 lines =<< trim END
5739 vim9script
5740 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005741 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005742 endclass
5743 class B extends A
5744 endclass
5745 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005746 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005747 endclass
5748 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005749 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005750
Ernie Rael03042a22023-11-11 08:53:32 +01005751 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005752 lines =<< trim END
5753 vim9script
5754 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005755 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005756 endclass
5757 class B extends A
5758 endclass
5759 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005760 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005761 endclass
5762 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005763 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005764
Ernie Rael03042a22023-11-11 08:53:32 +01005765 # Duplicate object protected member variable in a derived class
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005766 lines =<< trim END
5767 vim9script
5768 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005769 var val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005770 endclass
5771 class B extends A
5772 endclass
5773 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005774 var _val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005775 endclass
5776 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005777 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: _val', 9)
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005778
5779 # Duplicate object member variable in a derived class
5780 lines =<< trim END
5781 vim9script
5782 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005783 var _val = 10
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005784 endclass
5785 class B extends A
5786 endclass
5787 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01005788 var val = 20
Yegappan Lakshmanane3b6c782023-08-29 22:32:02 +02005789 endclass
5790 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005791 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: val', 9)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005792
5793 # Two member variables with a common prefix
5794 lines =<< trim END
5795 vim9script
5796 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005797 public static var svar2: number
5798 public static var svar: number
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005799 endclass
5800 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005801 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan2ba9d2e2023-08-28 21:26:23 +02005802enddef
5803
Ernie Rael03042a22023-11-11 08:53:32 +01005804" Test for accessing a protected member outside a class in a def function
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005805def Test_private_member_access_outside_class()
Ernie Rael03042a22023-11-11 08:53:32 +01005806 # protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005807 var lines =<< trim END
5808 vim9script
5809 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005810 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005811 def GetVal(): number
5812 return this._val
5813 enddef
5814 endclass
5815 def T()
5816 var a = A.new()
5817 a._val = 20
5818 enddef
5819 T()
5820 END
Ernie Rael03042a22023-11-11 08:53:32 +01005821 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005822
Ernie Rael03042a22023-11-11 08:53:32 +01005823 # access a non-existing protected object member variable
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005824 lines =<< trim END
5825 vim9script
5826 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005827 var _val = 10
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005828 endclass
5829 def T()
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005830 var a = A.new()
5831 a._a = 1
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005832 enddef
5833 T()
5834 END
Ernie Raeld4802ec2023-10-20 11:59:00 +02005835 v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005836
Ernie Rael03042a22023-11-11 08:53:32 +01005837 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005838 lines =<< trim END
5839 vim9script
5840 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005841 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005842 endclass
5843 def T()
5844 var a = A.new()
5845 var x = a._val
5846 enddef
5847 T()
5848 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005849 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005850
Ernie Rael03042a22023-11-11 08:53:32 +01005851 # protected static member variable
Ernie Rael18143d32023-09-04 22:30:41 +02005852 lines =<< trim END
5853 vim9script
5854 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005855 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005856 endclass
5857 def T()
5858 var a = A.new()
5859 a._val = 3
5860 enddef
5861 T()
5862 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005863 v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
Ernie Rael18143d32023-09-04 22:30:41 +02005864
Ernie Rael03042a22023-11-11 08:53:32 +01005865 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005866 lines =<< trim END
5867 vim9script
5868 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005869 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005870 endclass
5871 def T()
5872 var x = A._val
5873 enddef
5874 T()
5875 END
Ernie Rael03042a22023-11-11 08:53:32 +01005876 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Ernie Rael18143d32023-09-04 22:30:41 +02005877
Ernie Rael03042a22023-11-11 08:53:32 +01005878 # protected static class variable
Ernie Rael18143d32023-09-04 22:30:41 +02005879 lines =<< trim END
5880 vim9script
5881 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005882 static var _val = 10
Ernie Rael18143d32023-09-04 22:30:41 +02005883 endclass
5884 def T()
5885 A._val = 3
5886 enddef
5887 T()
5888 END
Ernie Rael03042a22023-11-11 08:53:32 +01005889 v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005890enddef
5891
5892" Test for changing the member access of an interface in a implementation class
5893def Test_change_interface_member_access()
5894 var lines =<< trim END
5895 vim9script
5896 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005897 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005898 endinterface
5899 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005900 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005901 endclass
5902 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005903 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005904
5905 lines =<< trim END
5906 vim9script
5907 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005908 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005909 endinterface
5910 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005911 public var val = 10
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005912 endclass
5913 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005914 v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7)
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005915enddef
5916
5917" Test for trying to change a readonly member from a def function
5918def Test_readonly_member_change_in_def_func()
5919 var lines =<< trim END
5920 vim9script
5921 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005922 var val: number
Yegappan Lakshmananeb91e242023-08-31 18:10:46 +02005923 endclass
5924 def T()
5925 var a = A.new()
5926 a.val = 20
5927 enddef
5928 T()
5929 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02005930 v9.CheckSourceFailure(lines, 'E1335: Variable "val" in class "A" is not writable', 2)
Yegappan Lakshmanan5bbcfbc2023-08-30 16:38:26 +02005931enddef
5932
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005933" Test for reading and writing a class member from a def function
5934def Test_modify_class_member_from_def_function()
5935 var lines =<< trim END
5936 vim9script
5937 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005938 var var1: number = 10
5939 public static var var2: list<number> = [1, 2]
5940 public static var var3: dict<number> = {a: 1, b: 2}
5941 static var _priv_var4: number = 40
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005942 endclass
5943 def T()
Yegappan Lakshmanane651e112023-09-04 07:51:01 +02005944 assert_equal([1, 2], A.var2)
5945 assert_equal({a: 1, b: 2}, A.var3)
5946 A.var2 = [3, 4]
5947 A.var3 = {c: 3, d: 4}
5948 assert_equal([3, 4], A.var2)
5949 assert_equal({c: 3, d: 4}, A.var3)
Ernie Rael03042a22023-11-11 08:53:32 +01005950 assert_fails('echo A._priv_var4', 'E1333: Cannot access protected variable "_priv_var4" in class "A"')
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005951 enddef
5952 T()
5953 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005954 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan3775f772023-09-01 22:05:45 +02005955enddef
5956
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005957" Test for accessing a class member variable using an object
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005958def Test_class_variable_access_using_object()
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005959 var lines =<< trim END
5960 vim9script
5961 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005962 public static var svar1: list<number> = [1]
5963 public static var svar2: list<number> = [2]
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005964 endclass
5965
5966 A.svar1->add(3)
5967 A.svar2->add(4)
5968 assert_equal([1, 3], A.svar1)
5969 assert_equal([2, 4], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005970
5971 def Foo()
5972 A.svar1->add(7)
5973 A.svar2->add(8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005974 assert_equal([1, 3, 7], A.svar1)
5975 assert_equal([2, 4, 8], A.svar2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02005976 enddef
5977 Foo()
5978 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02005979 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005980
5981 # Cannot read from a class variable using an object in script context
5982 lines =<< trim END
5983 vim9script
5984 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005985 public var var1: number
5986 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005987 endclass
5988
5989 var a = A.new()
5990 echo a.svar2
5991 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02005992 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02005993
5994 # Cannot write to a class variable using an object in script context
5995 lines =<< trim END
5996 vim9script
5997 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01005998 public var var1: number
5999 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006000 endclass
6001
6002 var a = A.new()
6003 a.svar2 = [2]
6004 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006005 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 8)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006006
6007 # Cannot read from a class variable using an object in def method context
6008 lines =<< trim END
6009 vim9script
6010 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006011 public var var1: number
6012 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006013 endclass
6014
6015 def T()
6016 var a = A.new()
6017 echo a.svar2
6018 enddef
6019 T()
6020 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006021 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006022
6023 # Cannot write to a class variable using an object in def method context
6024 lines =<< trim END
6025 vim9script
6026 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006027 public var var1: number
6028 public static var svar2: list<number> = [1]
Yegappan Lakshmanan23c92d92023-09-09 11:33:29 +02006029 endclass
6030
6031 def T()
6032 var a = A.new()
6033 a.svar2 = [2]
6034 enddef
6035 T()
6036 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006037 v9.CheckSourceFailure(lines, 'E1375: Class variable "svar2" accessible only using class "A"', 2)
Yegappan Lakshmanan1689e842023-09-06 20:23:23 +02006038enddef
6039
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006040" Test for using a interface method using a child object
6041def Test_interface_method_from_child()
6042 var lines =<< trim END
6043 vim9script
6044
6045 interface A
6046 def Foo(): string
6047 endinterface
6048
6049 class B implements A
6050 def Foo(): string
6051 return 'foo'
6052 enddef
6053 endclass
6054
6055 class C extends B
6056 def Bar(): string
6057 return 'bar'
6058 enddef
6059 endclass
6060
6061 def T1(a: A)
6062 assert_equal('foo', a.Foo())
6063 enddef
6064
6065 def T2(b: B)
6066 assert_equal('foo', b.Foo())
6067 enddef
6068
6069 var c = C.new()
6070 T1(c)
6071 T2(c)
6072 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006073 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006074enddef
6075
6076" Test for using an interface method using a child object when it is overridden
6077" by the child class.
6078" FIXME: This test fails.
6079" def Test_interface_overridden_method_from_child()
6080" var lines =<< trim END
6081" vim9script
6082"
6083" interface A
6084" def Foo(): string
6085" endinterface
6086"
6087" class B implements A
6088" def Foo(): string
6089" return 'b-foo'
6090" enddef
6091" endclass
6092"
6093" class C extends B
6094" def Bar(): string
6095" return 'bar'
6096" enddef
6097" def Foo(): string
6098" return 'c-foo'
6099" enddef
6100" endclass
6101"
6102" def T1(a: A)
6103" assert_equal('c-foo', a.Foo())
6104" enddef
6105"
6106" def T2(b: B)
6107" assert_equal('c-foo', b.Foo())
6108" enddef
6109"
6110" var c = C.new()
6111" T1(c)
6112" T2(c)
6113" END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006114" v9.CheckSourceSuccess(lines)
Yegappan Lakshmanancc0bcf42023-09-08 19:12:03 +02006115" enddef
6116
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006117" Test for abstract methods
6118def Test_abstract_method()
6119 # Use two abstract methods
6120 var lines =<< trim END
6121 vim9script
6122 abstract class A
6123 def M1(): number
6124 return 10
6125 enddef
6126 abstract def M2(): number
6127 abstract def M3(): number
6128 endclass
6129 class B extends A
6130 def M2(): number
6131 return 20
6132 enddef
6133 def M3(): number
6134 return 30
6135 enddef
6136 endclass
6137 var b = B.new()
6138 assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
6139 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006140 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006141
6142 # Don't define an abstract method
6143 lines =<< trim END
6144 vim9script
6145 abstract class A
6146 abstract def Foo()
6147 endclass
6148 class B extends A
6149 endclass
6150 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006151 v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented', 6)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006152
6153 # Use abstract method in a concrete class
6154 lines =<< trim END
6155 vim9script
6156 class A
6157 abstract def Foo()
6158 endclass
6159 class B extends A
6160 endclass
6161 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006162 v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006163
6164 # Use abstract method in an interface
6165 lines =<< trim END
6166 vim9script
6167 interface A
6168 abstract def Foo()
6169 endinterface
6170 class B implements A
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006171 def Foo()
6172 enddef
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006173 endclass
6174 END
Yegappan Lakshmanan2b358ad2023-11-02 20:57:32 +01006175 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6176
6177 # Use abstract static method in an interface
6178 lines =<< trim END
6179 vim9script
6180 interface A
6181 abstract static def Foo()
6182 enddef
6183 endinterface
6184 END
6185 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
6186
6187 # Use abstract static variable in an interface
6188 lines =<< trim END
6189 vim9script
6190 interface A
6191 abstract static foo: number = 10
6192 endinterface
6193 END
6194 v9.CheckSourceFailure(lines, 'E1404: Abstract cannot be used in an interface', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006195
6196 # Abbreviate the "abstract" keyword
6197 lines =<< trim END
6198 vim9script
6199 class A
6200 abs def Foo()
6201 endclass
6202 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006203 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006204
6205 # Use "abstract" with a member variable
6206 lines =<< trim END
6207 vim9script
6208 abstract class A
6209 abstract this.val = 10
6210 endclass
6211 END
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006212 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006213
6214 # Use a static abstract method
Yegappan Lakshmanan5a539252023-11-04 09:42:46 +01006215 lines =<< trim END
6216 vim9script
6217 abstract class A
6218 abstract static def Foo(): number
6219 endclass
6220 END
6221 v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def"', 3)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006222
6223 # Type mismatch between abstract method and concrete method
6224 lines =<< trim END
6225 vim9script
6226 abstract class A
6227 abstract def Foo(a: string, b: number): list<number>
6228 endclass
6229 class B extends A
6230 def Foo(a: number, b: string): list<string>
6231 return []
6232 enddef
6233 endclass
6234 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006235 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 +02006236
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006237 # Invoke an abstract method from a def function
6238 lines =<< trim END
6239 vim9script
6240 abstract class A
6241 abstract def Foo(): list<number>
6242 endclass
6243 class B extends A
6244 def Foo(): list<number>
6245 return [3, 5]
6246 enddef
6247 endclass
6248 def Bar(c: B)
6249 assert_equal([3, 5], c.Foo())
6250 enddef
6251 var b = B.new()
6252 Bar(b)
6253 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006254 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +01006255
6256 # Use a static method in an abstract class
6257 lines =<< trim END
6258 vim9script
6259 abstract class A
6260 static def Foo(): string
6261 return 'foo'
6262 enddef
6263 endclass
6264 assert_equal('foo', A.Foo())
6265 END
6266 v9.CheckSourceSuccess(lines)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006267enddef
6268
6269" Test for calling a class method from a subclass
6270def Test_class_method_call_from_subclass()
6271 # class method call from a subclass
6272 var lines =<< trim END
6273 vim9script
6274
6275 class A
6276 static def Foo()
6277 echo "foo"
6278 enddef
6279 endclass
6280
6281 class B extends A
6282 def Bar()
6283 Foo()
6284 enddef
6285 endclass
6286
6287 var b = B.new()
6288 b.Bar()
6289 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006290 v9.CheckSourceFailure(lines, 'E1384: Class method "Foo" accessible only inside class "A"', 1)
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +02006291enddef
6292
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006293" Test for calling a class method using an object in a def function context and
6294" script context.
6295def Test_class_method_call_using_object()
6296 # script context
6297 var lines =<< trim END
6298 vim9script
6299 class A
6300 static def Foo(): list<string>
6301 return ['a', 'b']
6302 enddef
6303 def Bar()
6304 assert_equal(['a', 'b'], A.Foo())
6305 assert_equal(['a', 'b'], Foo())
6306 enddef
6307 endclass
6308
6309 def T()
6310 assert_equal(['a', 'b'], A.Foo())
6311 var t_a = A.new()
6312 t_a.Bar()
6313 enddef
6314
6315 assert_equal(['a', 'b'], A.Foo())
6316 var a = A.new()
6317 a.Bar()
6318 T()
6319 END
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006320 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006321
6322 # script context
6323 lines =<< trim END
6324 vim9script
6325 class A
6326 static def Foo(): string
6327 return 'foo'
6328 enddef
6329 endclass
6330
6331 var a = A.new()
6332 assert_equal('foo', a.Foo())
6333 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006334 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 9)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006335
6336 # def function context
6337 lines =<< trim END
6338 vim9script
6339 class A
6340 static def Foo(): string
6341 return 'foo'
6342 enddef
6343 endclass
6344
6345 def T()
6346 var a = A.new()
6347 assert_equal('foo', a.Foo())
6348 enddef
6349 T()
6350 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006351 v9.CheckSourceFailure(lines, 'E1385: Class method "Foo" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006352enddef
6353
6354def Test_class_variable()
6355 var lines =<< trim END
6356 vim9script
6357
6358 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006359 public static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006360 static def ClassFunc()
6361 assert_equal(10, val)
6362 enddef
6363 def ObjFunc()
6364 assert_equal(10, val)
6365 enddef
6366 endclass
6367
6368 class B extends A
6369 endclass
6370
6371 assert_equal(10, A.val)
6372 A.ClassFunc()
6373 var a = A.new()
6374 a.ObjFunc()
6375 var b = B.new()
6376 b.ObjFunc()
6377
6378 def T1(a1: A)
6379 a1.ObjFunc()
6380 A.ClassFunc()
6381 enddef
6382 T1(b)
6383
6384 A.val = 20
6385 assert_equal(20, A.val)
6386 END
6387 v9.CheckSourceSuccess(lines)
6388
6389 # Modifying a parent class variable from a child class method
6390 lines =<< trim END
6391 vim9script
6392
6393 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006394 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006395 endclass
6396
6397 class B extends A
6398 static def ClassFunc()
6399 val = 20
6400 enddef
6401 endclass
6402 B.ClassFunc()
6403 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006404 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006405
6406 # Reading a parent class variable from a child class method
6407 lines =<< trim END
6408 vim9script
6409
6410 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006411 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006412 endclass
6413
6414 class B extends A
6415 static def ClassFunc()
6416 var i = val
6417 enddef
6418 endclass
6419 B.ClassFunc()
6420 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006421 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006422
6423 # Modifying a parent class variable from a child object method
6424 lines =<< trim END
6425 vim9script
6426
6427 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006428 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006429 endclass
6430
6431 class B extends A
6432 def ObjFunc()
6433 val = 20
6434 enddef
6435 endclass
6436 var b = B.new()
6437 b.ObjFunc()
6438 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006439 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006440
6441 # Reading a parent class variable from a child object method
6442 lines =<< trim END
6443 vim9script
6444
6445 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006446 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006447 endclass
6448
6449 class B extends A
6450 def ObjFunc()
6451 var i = val
6452 enddef
6453 endclass
6454 var b = B.new()
6455 b.ObjFunc()
6456 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006457 v9.CheckSourceFailure(lines, 'E1374: Class variable "val" accessible only inside class "A"', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006458
6459 # Modifying a class variable using an object at script level
6460 lines =<< trim END
6461 vim9script
6462
6463 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006464 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006465 endclass
6466 var a = A.new()
6467 a.val = 20
6468 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006469 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006470
6471 # Reading a class variable using an object at script level
6472 lines =<< trim END
6473 vim9script
6474
6475 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006476 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006477 endclass
6478 var a = A.new()
6479 var i = a.val
6480 END
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02006481 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006482
6483 # Modifying a class variable using an object at function level
6484 lines =<< trim END
6485 vim9script
6486
6487 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006488 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006489 endclass
6490
6491 def T()
6492 var a = A.new()
6493 a.val = 20
6494 enddef
6495 T()
6496 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006497 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006498
6499 # Reading a class variable using an object at function level
6500 lines =<< trim END
6501 vim9script
6502
6503 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006504 static var val: number = 10
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006505 endclass
6506 def T()
6507 var a = A.new()
6508 var i = a.val
6509 enddef
6510 T()
6511 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006512 v9.CheckSourceFailure(lines, 'E1375: Class variable "val" accessible only using class "A"', 2)
Doug Kearns74da0ee2023-12-14 20:26:26 +01006513
6514 # Use old implicit var declaration syntax (without initialization)
6515 lines =<< trim END
6516 vim9script
6517
6518 class A
6519 static val: number
6520 endclass
6521 END
6522 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6523
6524 # Use old implicit var declaration syntax (with initialization)
6525 lines =<< trim END
6526 vim9script
6527
6528 class A
6529 static val: number = 10
6530 endclass
6531 END
6532 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6533
6534 # Use old implicit var declaration syntax (type inferred)
6535 lines =<< trim END
6536 vim9script
6537
6538 class A
6539 static val = 10
6540 endclass
6541 END
6542 v9.CheckSourceFailure(lines, 'E1368: Static must be followed by "var" or "def"', 4)
6543
6544 # Missing ":var" in "var" class variable declaration (without initialization)
6545 lines =<< trim END
6546 vim9script
6547
6548 class A
6549 static var: number
6550 endclass
6551 END
6552 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number', 4)
6553
6554 # Missing ":var" in "var" class variable declaration (with initialization)
6555 lines =<< trim END
6556 vim9script
6557
6558 class A
6559 static var: number = 10
6560 endclass
6561 END
6562 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var: number = 10', 4)
6563
6564 # Missing ":var" in "var" class variable declaration (type inferred)
6565 lines =<< trim END
6566 vim9script
6567
6568 class A
6569 static var = 10
6570 endclass
6571 END
6572 v9.CheckSourceFailure(lines, 'E1329: Invalid class variable declaration: static var = 10', 4)
6573
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006574enddef
6575
6576" Test for using a duplicate class method and class variable in a child class
6577def Test_dup_class_member()
6578 # duplicate class variable, class method and overridden object method
6579 var lines =<< trim END
6580 vim9script
6581 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006582 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006583 static def Check()
6584 assert_equal(100, sval)
6585 enddef
6586 def GetVal(): number
6587 return sval
6588 enddef
6589 endclass
6590
6591 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006592 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006593 static def Check()
6594 assert_equal(200, sval)
6595 enddef
6596 def GetVal(): number
6597 return sval
6598 enddef
6599 endclass
6600
6601 def T1(aa: A): number
6602 return aa.GetVal()
6603 enddef
6604
6605 def T2(bb: B): number
6606 return bb.GetVal()
6607 enddef
6608
6609 assert_equal(100, A.sval)
6610 assert_equal(200, B.sval)
6611 var a = A.new()
6612 assert_equal(100, a.GetVal())
6613 var b = B.new()
6614 assert_equal(200, b.GetVal())
6615 assert_equal(200, T1(b))
6616 assert_equal(200, T2(b))
6617 END
6618 v9.CheckSourceSuccess(lines)
6619
6620 # duplicate class variable and class method
6621 lines =<< trim END
6622 vim9script
6623 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006624 static var sval = 100
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006625 static def Check()
6626 assert_equal(100, sval)
6627 enddef
6628 def GetVal(): number
6629 return sval
6630 enddef
6631 endclass
6632
6633 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006634 static var sval = 200
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006635 static def Check()
6636 assert_equal(200, sval)
6637 enddef
6638 endclass
6639
6640 def T1(aa: A): number
6641 return aa.GetVal()
6642 enddef
6643
6644 def T2(bb: B): number
6645 return bb.GetVal()
6646 enddef
6647
6648 assert_equal(100, A.sval)
6649 assert_equal(200, B.sval)
6650 var a = A.new()
6651 assert_equal(100, a.GetVal())
6652 var b = B.new()
6653 assert_equal(100, b.GetVal())
6654 assert_equal(100, T1(b))
6655 assert_equal(100, T2(b))
6656 END
6657 v9.CheckSourceSuccess(lines)
6658enddef
6659
6660" Test for calling an instance method using the class
6661def Test_instance_method_call_using_class()
6662 # Invoke an object method using a class in script context
6663 var lines =<< trim END
6664 vim9script
6665 class A
6666 def Foo()
6667 echo "foo"
6668 enddef
6669 endclass
6670 A.Foo()
6671 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006672 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 7)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006673
6674 # Invoke an object method using a class in def function context
6675 lines =<< trim END
6676 vim9script
6677 class A
6678 def Foo()
6679 echo "foo"
6680 enddef
6681 endclass
6682 def T()
6683 A.Foo()
6684 enddef
6685 T()
6686 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006687 v9.CheckSourceFailure(lines, 'E1386: Object method "Foo" accessible only using class "A" object', 1)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006688enddef
6689
6690" Test for duplicate class method and instance method
6691def Test_dup_classmethod_objmethod()
6692 # Duplicate instance method
6693 var lines =<< trim END
6694 vim9script
6695 class A
6696 static def Foo()
6697 enddef
6698 def Foo()
6699 enddef
6700 endclass
6701 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006702 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006703
Ernie Rael03042a22023-11-11 08:53:32 +01006704 # Duplicate protected instance method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006705 lines =<< trim END
6706 vim9script
6707 class A
6708 static def Foo()
6709 enddef
6710 def _Foo()
6711 enddef
6712 endclass
6713 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006714 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006715
6716 # Duplicate class method
6717 lines =<< trim END
6718 vim9script
6719 class A
6720 def Foo()
6721 enddef
6722 static def Foo()
6723 enddef
6724 endclass
6725 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006726 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006727
Ernie Rael03042a22023-11-11 08:53:32 +01006728 # Duplicate protected class method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006729 lines =<< trim END
6730 vim9script
6731 class A
6732 def Foo()
6733 enddef
6734 static def _Foo()
6735 enddef
6736 endclass
6737 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006738 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006739
Ernie Rael03042a22023-11-11 08:53:32 +01006740 # Duplicate protected class and object method
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006741 lines =<< trim END
6742 vim9script
6743 class A
6744 def _Foo()
6745 enddef
6746 static def _Foo()
6747 enddef
6748 endclass
6749 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006750 v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo', 6)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006751enddef
6752
6753" Test for an instance method access level comparison with parent instance
6754" methods.
6755def Test_instance_method_access_level()
Ernie Rael03042a22023-11-11 08:53:32 +01006756 # protected method in subclass
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006757 var lines =<< trim END
6758 vim9script
6759 class A
6760 def Foo()
6761 enddef
6762 endclass
6763 class B extends A
6764 endclass
6765 class C extends B
6766 def _Foo()
6767 enddef
6768 endclass
6769 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006770 v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006771
6772 # Public method in subclass
6773 lines =<< trim END
6774 vim9script
6775 class A
6776 def _Foo()
6777 enddef
6778 endclass
6779 class B extends A
6780 endclass
6781 class C extends B
6782 def Foo()
6783 enddef
6784 endclass
6785 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006786 v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"', 11)
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006787enddef
6788
6789def Test_extend_empty_class()
6790 var lines =<< trim END
6791 vim9script
6792 class A
6793 endclass
6794 class B extends A
6795 endclass
6796 class C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006797 public static var rw_class_var = 1
6798 public var rw_obj_var = 2
Yegappan Lakshmananc30a90d2023-09-15 20:14:55 +02006799 static def ClassMethod(): number
6800 return 3
6801 enddef
6802 def ObjMethod(): number
6803 return 4
6804 enddef
6805 endclass
6806 assert_equal(1, C.rw_class_var)
6807 assert_equal(3, C.ClassMethod())
6808 var c = C.new()
6809 assert_equal(2, c.rw_obj_var)
6810 assert_equal(4, c.ObjMethod())
6811 END
6812 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan342f4f62023-09-09 11:37:23 +02006813enddef
6814
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006815" A interface cannot have a static variable or a static method or a private
Ernie Rael03042a22023-11-11 08:53:32 +01006816" variable or a protected method or a public variable
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006817def Test_interface_with_unsupported_members()
6818 var lines =<< trim END
6819 vim9script
6820 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006821 static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006822 endinterface
6823 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006824 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006825
6826 lines =<< trim END
6827 vim9script
6828 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006829 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006830 endinterface
6831 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006832 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006833
6834 lines =<< trim END
6835 vim9script
6836 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006837 public static var num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006838 endinterface
6839 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02006840 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006841
6842 lines =<< trim END
6843 vim9script
6844 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006845 public static var num: number
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006846 endinterface
6847 END
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +02006848 v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3)
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +02006849
6850 lines =<< trim END
6851 vim9script
6852 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006853 static var _num: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006854 endinterface
6855 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006856 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006857
6858 lines =<< trim END
6859 vim9script
6860 interface A
6861 static def Foo(d: dict<any>): list<string>
6862 endinterface
6863 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006864 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006865
6866 lines =<< trim END
6867 vim9script
6868 interface A
6869 static def _Foo(d: dict<any>): list<string>
6870 endinterface
6871 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006872 v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006873
6874 lines =<< trim END
6875 vim9script
6876 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006877 var _Foo: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006878 endinterface
6879 END
Ernie Rael03042a22023-11-11 08:53:32 +01006880 v9.CheckSourceFailure(lines, 'E1379: Protected variable not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006881
6882 lines =<< trim END
6883 vim9script
6884 interface A
6885 def _Foo(d: dict<any>): list<string>
6886 endinterface
6887 END
Ernie Rael03042a22023-11-11 08:53:32 +01006888 v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006889enddef
6890
6891" Test for extending an interface
6892def Test_extend_interface()
6893 var lines =<< trim END
6894 vim9script
6895 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006896 var var1: list<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006897 def Foo()
6898 endinterface
6899 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006900 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006901 def Bar()
6902 endinterface
6903 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006904 var var1 = [1, 2]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006905 def Foo()
6906 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01006907 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006908 def Bar()
6909 enddef
6910 endclass
6911 END
6912 v9.CheckSourceSuccess(lines)
6913
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02006914 # extending empty interface
6915 lines =<< trim END
6916 vim9script
6917 interface A
6918 endinterface
6919 interface B extends A
6920 endinterface
6921 class C implements B
6922 endclass
6923 END
6924 v9.CheckSourceSuccess(lines)
6925
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006926 lines =<< trim END
6927 vim9script
6928 interface A
6929 def Foo()
6930 endinterface
6931 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006932 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006933 endinterface
6934 class C implements A, B
Doug Kearns74da0ee2023-12-14 20:26:26 +01006935 var var2 = {a: '1'}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006936 endclass
6937 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006938 v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented', 10)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006939
6940 lines =<< trim END
6941 vim9script
6942 interface A
6943 def Foo()
6944 endinterface
6945 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01006946 var var2: dict<string>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006947 endinterface
6948 class C implements A, B
6949 def Foo()
6950 enddef
6951 endclass
6952 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006953 v9.CheckSourceFailure(lines, 'E1348: Variable "var2" of interface "B" is not implemented', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006954
6955 # interface cannot extend a class
6956 lines =<< trim END
6957 vim9script
6958 class A
6959 endclass
6960 interface B extends A
6961 endinterface
6962 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006963 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006964
6965 # class cannot extend an interface
6966 lines =<< trim END
6967 vim9script
6968 interface A
6969 endinterface
6970 class B extends A
6971 endclass
6972 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006973 v9.CheckSourceFailure(lines, 'E1354: Cannot extend A', 5)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006974
6975 # interface cannot implement another interface
6976 lines =<< trim END
6977 vim9script
6978 interface A
6979 endinterface
6980 interface B implements A
6981 endinterface
6982 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006983 v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"', 4)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006984
6985 # interface cannot extend multiple interfaces
6986 lines =<< trim END
6987 vim9script
6988 interface A
6989 endinterface
6990 interface B
6991 endinterface
6992 interface C extends A, B
6993 endinterface
6994 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02006995 v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B', 6)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02006996
6997 # Variable type in an extended interface is of different type
6998 lines =<< trim END
6999 vim9script
7000 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007001 var val1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007002 endinterface
7003 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007004 var val2: string
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007005 endinterface
7006 interface C extends B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007007 var val1: string
7008 var val2: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007009 endinterface
7010 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007011 v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007012enddef
7013
7014" Test for a child class implementing an interface when some of the methods are
7015" defined in the parent class.
7016def Test_child_class_implements_interface()
7017 var lines =<< trim END
7018 vim9script
7019
7020 interface Intf
7021 def F1(): list<list<number>>
7022 def F2(): list<list<number>>
7023 def F3(): list<list<number>>
Doug Kearns74da0ee2023-12-14 20:26:26 +01007024 var var1: list<dict<number>>
7025 var var2: list<dict<number>>
7026 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007027 endinterface
7028
7029 class A
7030 def A1()
7031 enddef
7032 def F3(): list<list<number>>
7033 return [[3]]
7034 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007035 var v1: list<list<number>> = [[0]]
7036 var var3 = [{c: 30}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007037 endclass
7038
7039 class B extends A
7040 def B1()
7041 enddef
7042 def F2(): list<list<number>>
7043 return [[2]]
7044 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007045 var v2: list<list<number>> = [[0]]
7046 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007047 endclass
7048
7049 class C extends B implements Intf
7050 def C1()
7051 enddef
7052 def F1(): list<list<number>>
7053 return [[1]]
7054 enddef
Doug Kearns74da0ee2023-12-14 20:26:26 +01007055 var v3: list<list<number>> = [[0]]
7056 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007057 endclass
7058
7059 def T(if: Intf)
7060 assert_equal([[1]], if.F1())
7061 assert_equal([[2]], if.F2())
7062 assert_equal([[3]], if.F3())
7063 assert_equal([{a: 10}], if.var1)
7064 assert_equal([{b: 20}], if.var2)
7065 assert_equal([{c: 30}], if.var3)
7066 enddef
7067
7068 var c = C.new()
7069 T(c)
7070 assert_equal([[1]], c.F1())
7071 assert_equal([[2]], c.F2())
7072 assert_equal([[3]], c.F3())
7073 assert_equal([{a: 10}], c.var1)
7074 assert_equal([{b: 20}], c.var2)
7075 assert_equal([{c: 30}], c.var3)
7076 END
7077 v9.CheckSourceSuccess(lines)
7078
7079 # One of the interface methods is not found
7080 lines =<< trim END
7081 vim9script
7082
7083 interface Intf
7084 def F1()
7085 def F2()
7086 def F3()
7087 endinterface
7088
7089 class A
7090 def A1()
7091 enddef
7092 endclass
7093
7094 class B extends A
7095 def B1()
7096 enddef
7097 def F2()
7098 enddef
7099 endclass
7100
7101 class C extends B implements Intf
7102 def C1()
7103 enddef
7104 def F1()
7105 enddef
7106 endclass
7107 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007108 v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented', 26)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007109
7110 # One of the interface methods is of different type
7111 lines =<< trim END
7112 vim9script
7113
7114 interface Intf
7115 def F1()
7116 def F2()
7117 def F3()
7118 endinterface
7119
7120 class A
7121 def F3(): number
7122 return 0
7123 enddef
7124 def A1()
7125 enddef
7126 endclass
7127
7128 class B extends A
7129 def B1()
7130 enddef
7131 def F2()
7132 enddef
7133 endclass
7134
7135 class C extends B implements Intf
7136 def C1()
7137 enddef
7138 def F1()
7139 enddef
7140 endclass
7141 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007142 v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number', 29)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007143
7144 # One of the interface variables is not present
7145 lines =<< trim END
7146 vim9script
7147
7148 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007149 var var1: list<dict<number>>
7150 var var2: list<dict<number>>
7151 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007152 endinterface
7153
7154 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007155 var v1: list<list<number>> = [[0]]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007156 endclass
7157
7158 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007159 var v2: list<list<number>> = [[0]]
7160 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007161 endclass
7162
7163 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007164 var v3: list<list<number>> = [[0]]
7165 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007166 endclass
7167 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007168 v9.CheckSourceFailure(lines, 'E1348: Variable "var3" of interface "Intf" is not implemented', 21)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007169
7170 # One of the interface variables is of different type
7171 lines =<< trim END
7172 vim9script
7173
7174 interface Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007175 var var1: list<dict<number>>
7176 var var2: list<dict<number>>
7177 var var3: list<dict<number>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007178 endinterface
7179
7180 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007181 var v1: list<list<number>> = [[0]]
7182 var var3: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007183 endclass
7184
7185 class B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007186 var v2: list<list<number>> = [[0]]
7187 var var2 = [{b: 20}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007188 endclass
7189
7190 class C extends B implements Intf
Doug Kearns74da0ee2023-12-14 20:26:26 +01007191 var v3: list<list<number>> = [[0]]
7192 var var1 = [{a: 10}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007193 endclass
7194 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007195 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 +02007196enddef
7197
7198" Test for extending an interface with duplicate variables and methods
7199def Test_interface_extends_with_dup_members()
7200 var lines =<< trim END
7201 vim9script
7202 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007203 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007204 def Foo1(): number
7205 endinterface
7206 interface B extends A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007207 var n2: number
7208 var n1: number
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007209 def Foo2(): number
7210 def Foo1(): number
7211 endinterface
7212 class C implements B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007213 var n1 = 10
7214 var n2 = 20
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007215 def Foo1(): number
7216 return 30
7217 enddef
7218 def Foo2(): number
7219 return 40
7220 enddef
7221 endclass
7222 def T1(a: A)
7223 assert_equal(10, a.n1)
7224 assert_equal(30, a.Foo1())
7225 enddef
7226 def T2(b: B)
7227 assert_equal(10, b.n1)
7228 assert_equal(20, b.n2)
7229 assert_equal(30, b.Foo1())
7230 assert_equal(40, b.Foo2())
7231 enddef
7232 var c = C.new()
7233 T1(c)
7234 T2(c)
7235 END
7236 v9.CheckSourceSuccess(lines)
7237enddef
7238
7239" Test for using "any" type for a variable in a sub-class while it has a
7240" concrete type in the interface
7241def Test_implements_using_var_type_any()
7242 var lines =<< trim END
7243 vim9script
7244 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007245 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007246 endinterface
7247 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007248 var val = [{a: '1'}, {b: '2'}]
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007249 endclass
7250 var b = B.new()
7251 assert_equal([{a: '1'}, {b: '2'}], b.val)
7252 END
7253 v9.CheckSourceSuccess(lines)
7254
7255 # initialize instance variable using a different type
7256 lines =<< trim END
7257 vim9script
7258 interface A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007259 var val: list<dict<string>>
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007260 endinterface
7261 class B implements A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007262 var val = {a: 1, b: 2}
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007263 endclass
7264 var b = B.new()
7265 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007266 v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list<dict<string>> but got dict<number>', 1)
Yegappan Lakshmanan92d9ee52023-09-17 17:03:19 +02007267enddef
7268
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007269" Test for assigning to a member variable in a nested class
7270def Test_nested_object_assignment()
7271 var lines =<< trim END
7272 vim9script
7273
7274 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007275 var value: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007276 endclass
7277
7278 class B
Doug Kearns74da0ee2023-12-14 20:26:26 +01007279 var a: A = A.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007280 endclass
7281
7282 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007283 var b: B = B.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007284 endclass
7285
7286 class D
Doug Kearns74da0ee2023-12-14 20:26:26 +01007287 var c: C = C.new()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007288 endclass
7289
7290 def T(da: D)
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007291 da.c.b.a.value = 10
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007292 enddef
7293
7294 var d = D.new()
7295 T(d)
7296 END
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +02007297 v9.CheckSourceFailure(lines, 'E1335: Variable "value" in class "A" is not writable', 1)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02007298enddef
7299
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007300" Test for calling methods using a null object
7301def Test_null_object_method_call()
7302 # Calling a object method using a null object in script context
7303 var lines =<< trim END
7304 vim9script
7305
7306 class C
7307 def Foo()
7308 assert_report('This method should not be executed')
7309 enddef
7310 endclass
7311
7312 var o: C
7313 o.Foo()
7314 END
7315 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
7316
7317 # Calling a object method using a null object in def function context
7318 lines =<< trim END
7319 vim9script
7320
7321 class C
7322 def Foo()
7323 assert_report('This method should not be executed')
7324 enddef
7325 endclass
7326
7327 def T()
7328 var o: C
7329 o.Foo()
7330 enddef
7331 T()
7332 END
7333 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7334
7335 # Calling a object method through another class method using a null object in
7336 # script context
7337 lines =<< trim END
7338 vim9script
7339
7340 class C
7341 def Foo()
7342 assert_report('This method should not be executed')
7343 enddef
7344
7345 static def Bar(o_any: any)
7346 var o_typed: C = o_any
7347 o_typed.Foo()
7348 enddef
7349 endclass
7350
7351 var o: C
7352 C.Bar(o)
7353 END
7354 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7355
7356 # Calling a object method through another class method using a null object in
7357 # def function context
7358 lines =<< trim END
7359 vim9script
7360
7361 class C
7362 def Foo()
7363 assert_report('This method should not be executed')
7364 enddef
7365
7366 static def Bar(o_any: any)
7367 var o_typed: C = o_any
7368 o_typed.Foo()
7369 enddef
7370 endclass
7371
7372 def T()
7373 var o: C
7374 C.Bar(o)
7375 enddef
7376 T()
7377 END
7378 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Ernie Raelbe828252024-07-26 18:37:02 +02007379
7380 # Calling an object method defined in a class that is extended. This differs
7381 # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL.
7382 lines =<< trim END
7383 vim9script
7384
7385 class C0
7386 def F()
7387 enddef
7388 endclass
7389
7390 class C extends C0
7391 endclass
7392
7393 def X()
7394 var o: C0 = null_object
7395 o.F()
7396 enddef
7397 X()
7398 END
7399 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
7400
7401 # Getting a function ref an object method.
7402 lines =<< trim END
7403 vim9script
7404
7405 class C0
7406 def F()
7407 enddef
7408 endclass
7409
7410 class C extends C0
7411 endclass
7412
7413 def X()
7414 var o: C0 = null_object
7415 var XXX = o.F
7416 enddef
7417 X()
7418 END
7419 v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007420enddef
7421
7422" Test for using a dict as an object member
7423def Test_dict_object_member()
7424 var lines =<< trim END
7425 vim9script
7426
7427 class Context
Doug Kearns74da0ee2023-12-14 20:26:26 +01007428 public var state: dict<number> = {}
Yegappan Lakshmanan1db15142023-09-19 20:34:05 +02007429 def GetState(): dict<number>
7430 return this.state
7431 enddef
7432 endclass
7433
7434 var ctx = Context.new()
7435 ctx.state->extend({a: 1})
7436 ctx.state['b'] = 2
7437 assert_equal({a: 1, b: 2}, ctx.GetState())
7438
7439 def F()
7440 ctx.state['c'] = 3
7441 assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
7442 enddef
7443 F()
7444 assert_equal(3, ctx.state.c)
7445 ctx.state.c = 4
7446 assert_equal(4, ctx.state.c)
7447 END
7448 v9.CheckSourceSuccess(lines)
7449enddef
7450
Yegappan Lakshmanan7398f362023-09-24 23:09:10 +02007451" The following test was failing after 9.0.1914. This was caused by using a
7452" freed object from a previous method call.
7453def Test_freed_object_from_previous_method_call()
7454 var lines =<< trim END
7455 vim9script
7456
7457 class Context
7458 endclass
7459
7460 class Result
7461 endclass
7462
7463 def Failure(): Result
7464 return Result.new()
7465 enddef
7466
7467 def GetResult(ctx: Context): Result
7468 return Failure()
7469 enddef
7470
7471 def Test_GetResult()
7472 var ctx = Context.new()
7473 var result = GetResult(ctx)
7474 enddef
7475
7476 Test_GetResult()
7477 END
7478 v9.CheckSourceSuccess(lines)
7479enddef
7480
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007481" Test for duplicate object and class variable
7482def Test_duplicate_variable()
7483 # Object variable name is same as the class variable name
7484 var lines =<< trim END
7485 vim9script
7486 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007487 public static var sval: number
7488 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007489 endclass
7490 var a = A.new()
7491 END
7492 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7493
7494 # Duplicate variable name and calling a class method
7495 lines =<< trim END
7496 vim9script
7497 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007498 public static var sval: number
7499 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007500 def F1()
7501 echo this.sval
7502 enddef
7503 static def F2()
7504 echo sval
7505 enddef
7506 endclass
7507 A.F2()
7508 END
7509 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7510
7511 # Duplicate variable with an empty constructor
7512 lines =<< trim END
7513 vim9script
7514 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007515 public static var sval: number
7516 public var sval: number
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007517 def new()
7518 enddef
7519 endclass
7520 var a = A.new()
7521 END
7522 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: sval', 4)
7523enddef
7524
7525" Test for using a reserved keyword as a variable name
7526def Test_reserved_varname()
7527 for kword in ['true', 'false', 'null', 'null_blob', 'null_dict',
7528 'null_function', 'null_list', 'null_partial', 'null_string',
7529 'null_channel', 'null_job', 'super', 'this']
7530
7531 var lines =<< trim eval END
7532 vim9script
7533 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007534 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007535 endclass
7536 var o = C.new()
7537 END
7538 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7539
7540 lines =<< trim eval END
7541 vim9script
7542 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007543 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007544 def new()
7545 enddef
7546 endclass
7547 var o = C.new()
7548 END
7549 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7550
7551 lines =<< trim eval END
7552 vim9script
7553 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007554 public var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007555 def new()
7556 enddef
7557 def F()
7558 echo this.{kword}
7559 enddef
7560 endclass
7561 var o = C.new()
7562 o.F()
7563 END
7564 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007565
7566 # class variable name
7567 if kword != 'this'
7568 lines =<< trim eval END
7569 vim9script
7570 class C
Doug Kearns74da0ee2023-12-14 20:26:26 +01007571 public static var {kword}: list<number> = [1, 2, 3]
Yegappan Lakshmananb8523052023-10-08 19:07:39 +02007572 endclass
7573 END
7574 v9.CheckSourceFailure(lines, $'E1034: Cannot use reserved name {kword}', 3)
7575 endif
Yegappan Lakshmananf057aca2023-09-28 22:28:15 +02007576 endfor
7577enddef
7578
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007579" Test for checking the type of the arguments and the return value of a object
7580" method in an extended class.
7581def Test_extended_obj_method_type_check()
7582 var lines =<< trim END
7583 vim9script
7584
7585 class A
7586 endclass
7587 class B extends A
7588 endclass
7589 class C extends B
7590 endclass
7591
7592 class Foo
7593 def Doit(p: B): B
7594 return B.new()
7595 enddef
7596 endclass
7597
7598 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007599 def Doit(p: C): B
7600 return B.new()
7601 enddef
7602 endclass
7603 END
7604 v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object<B>): object<B> but got func(object<C>): object<B>', 20)
7605
7606 lines =<< trim END
7607 vim9script
7608
7609 class A
7610 endclass
7611 class B extends A
7612 endclass
7613 class C extends B
7614 endclass
7615
7616 class Foo
7617 def Doit(p: B): B
7618 return B.new()
7619 enddef
7620 endclass
7621
7622 class Bar extends Foo
7623 def Doit(p: B): C
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007624 return C.new()
7625 enddef
7626 endclass
7627 END
7628 v9.CheckSourceSuccess(lines)
7629
7630 lines =<< trim END
7631 vim9script
7632
7633 class A
7634 endclass
7635 class B extends A
7636 endclass
7637 class C extends B
7638 endclass
7639
7640 class Foo
7641 def Doit(p: B): B
7642 return B.new()
7643 enddef
7644 endclass
7645
7646 class Bar extends Foo
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007647 def Doit(p: A): B
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +02007648 return B.new()
7649 enddef
7650 endclass
7651 END
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +02007652 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 +02007653
7654 lines =<< trim END
7655 vim9script
7656
7657 class A
7658 endclass
7659 class B extends A
7660 endclass
7661 class C extends B
7662 endclass
7663
7664 class Foo
7665 def Doit(p: B): B
7666 return B.new()
7667 enddef
7668 endclass
7669
7670 class Bar extends Foo
7671 def Doit(p: B): A
7672 return A.new()
7673 enddef
7674 endclass
7675 END
7676 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 +02007677
7678 # check varargs type mismatch
7679 lines =<< trim END
7680 vim9script
7681
7682 class B
7683 def F(...xxx: list<any>)
7684 enddef
7685 endclass
7686 class C extends B
7687 def F(xxx: list<any>)
7688 enddef
7689 endclass
7690 END
7691 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 +02007692enddef
7693
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007694" Test type checking for class variable in assignments
7695func Test_class_variable_complex_type_check()
7696 " class variable with a specific type. Try assigning a different type at
7697 " script level.
7698 let lines =<< trim END
7699 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007700 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007701 return {}
7702 enddef
7703 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007704 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007705 endclass
7706 test_garbagecollect_now()
7707 A.Fn = "abc"
7708 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007709 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 +02007710
7711 " class variable with a specific type. Try assigning a different type at
7712 " class def method level.
7713 let lines =<< trim END
7714 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007715 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007716 return {}
7717 enddef
7718 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007719 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007720 def Bar()
7721 Fn = "abc"
7722 enddef
7723 endclass
7724 var a = A.new()
7725 test_garbagecollect_now()
7726 a.Bar()
7727 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007728 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 +02007729
7730 " class variable with a specific type. Try assigning a different type at
7731 " script def method level.
7732 let lines =<< trim END
7733 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007734 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007735 return {}
7736 enddef
7737 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007738 public static var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007739 endclass
7740 def Bar()
7741 A.Fn = "abc"
7742 enddef
7743 test_garbagecollect_now()
7744 Bar()
7745 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007746 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 +02007747
7748 " class variable without any type. Should be set to the initialization
7749 " expression type. Try assigning a different type from script level.
7750 let lines =<< trim END
7751 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007752 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007753 return {}
7754 enddef
7755 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007756 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007757 endclass
7758 test_garbagecollect_now()
7759 A.Fn = "abc"
7760 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007761 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 +02007762
7763 " class variable without any type. Should be set to the initialization
7764 " expression type. Try assigning a different type at class def level.
7765 let lines =<< trim END
7766 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007767 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007768 return {}
7769 enddef
7770 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007771 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007772 def Bar()
7773 Fn = "abc"
7774 enddef
7775 endclass
7776 var a = A.new()
7777 test_garbagecollect_now()
7778 a.Bar()
7779 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007780 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 +02007781
7782 " class variable without any type. Should be set to the initialization
7783 " expression type. Try assigning a different type at script def level.
7784 let lines =<< trim END
7785 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007786 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007787 return {}
7788 enddef
7789 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007790 public static var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007791 endclass
7792 def Bar()
7793 A.Fn = "abc"
7794 enddef
7795 test_garbagecollect_now()
7796 Bar()
7797 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007798 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 +02007799
7800 " class variable with 'any" type. Can be assigned different types.
7801 let lines =<< trim END
7802 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007803 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007804 return {}
7805 enddef
7806 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007807 public static var Fn: any = Foo
7808 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007809 endclass
7810 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007811 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007812 A.Fn = "abc"
7813 test_garbagecollect_now()
7814 assert_equal('string', typename(A.Fn))
7815 A.Fn2 = Foo
7816 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007817 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007818 A.Fn2 = "xyz"
7819 test_garbagecollect_now()
7820 assert_equal('string', typename(A.Fn2))
7821 END
7822 call v9.CheckSourceSuccess(lines)
7823
7824 " class variable with 'any" type. Can be assigned different types.
7825 let lines =<< trim END
7826 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007827 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007828 return {}
7829 enddef
7830 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007831 public static var Fn: any = Foo
7832 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007833
7834 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007835 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007836 Fn = "abc"
7837 assert_equal('string', typename(Fn))
7838 Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007839 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007840 Fn2 = "xyz"
7841 assert_equal('string', typename(Fn2))
7842 enddef
7843 endclass
7844 var a = A.new()
7845 test_garbagecollect_now()
7846 a.Bar()
7847 test_garbagecollect_now()
7848 A.Fn = Foo
7849 a.Bar()
7850 END
7851 call v9.CheckSourceSuccess(lines)
7852
7853 " class variable with 'any" type. Can be assigned different types.
7854 let lines =<< trim END
7855 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007856 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007857 return {}
7858 enddef
7859 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007860 public static var Fn: any = Foo
7861 public static var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007862 endclass
7863
7864 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007865 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007866 A.Fn = "abc"
7867 assert_equal('string', typename(A.Fn))
7868 A.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007869 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(A.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007870 A.Fn2 = "xyz"
7871 assert_equal('string', typename(A.Fn2))
7872 enddef
7873 Bar()
7874 test_garbagecollect_now()
7875 A.Fn = Foo
7876 Bar()
7877 END
7878 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007879
7880 let lines =<< trim END
7881 vim9script
7882 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007883 public static var foo = [0z10, 0z20]
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007884 endclass
7885 assert_equal([0z10, 0z20], A.foo)
7886 A.foo = [0z30]
7887 assert_equal([0z30], A.foo)
7888 var a = A.foo
7889 assert_equal([0z30], a)
7890 END
7891 call v9.CheckSourceSuccess(lines)
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007892endfunc
7893
7894" Test type checking for object variable in assignments
7895func Test_object_variable_complex_type_check()
7896 " object variable with a specific type. Try assigning a different type at
7897 " script level.
7898 let lines =<< trim END
7899 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007900 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007901 return {}
7902 enddef
7903 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007904 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007905 endclass
7906 var a = A.new()
7907 test_garbagecollect_now()
7908 a.Fn = "abc"
7909 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007910 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 +02007911
7912 " object variable with a specific type. Try assigning a different type at
7913 " object def method level.
7914 let lines =<< trim END
7915 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007916 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007917 return {}
7918 enddef
7919 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007920 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007921 def Bar()
7922 this.Fn = "abc"
7923 this.Fn = Foo
7924 enddef
7925 endclass
7926 var a = A.new()
7927 test_garbagecollect_now()
7928 a.Bar()
7929 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007930 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 +02007931
7932 " object variable with a specific type. Try assigning a different type at
7933 " script def method level.
7934 let lines =<< trim END
7935 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007936 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007937 return {}
7938 enddef
7939 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007940 public var Fn: func(list<dict<blob>>): dict<list<blob>> = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007941 endclass
7942 def Bar()
7943 var a = A.new()
7944 a.Fn = "abc"
7945 a.Fn = Foo
7946 enddef
7947 test_garbagecollect_now()
7948 Bar()
7949 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007950 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 +02007951
7952 " object variable without any type. Should be set to the initialization
7953 " expression type. Try assigning a different type from script level.
7954 let lines =<< trim END
7955 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007956 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007957 return {}
7958 enddef
7959 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007960 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007961 endclass
7962 var a = A.new()
7963 test_garbagecollect_now()
7964 a.Fn = "abc"
7965 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007966 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 +02007967
7968 " object variable without any type. Should be set to the initialization
7969 " expression type. Try assigning a different type at object def level.
7970 let lines =<< trim END
7971 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007972 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007973 return {}
7974 enddef
7975 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007976 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007977 def Bar()
7978 this.Fn = "abc"
7979 this.Fn = Foo
7980 enddef
7981 endclass
7982 var a = A.new()
7983 test_garbagecollect_now()
7984 a.Bar()
7985 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007986 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 +02007987
7988 " object variable without any type. Should be set to the initialization
7989 " expression type. Try assigning a different type at script def level.
7990 let lines =<< trim END
7991 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02007992 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007993 return {}
7994 enddef
7995 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01007996 public var Fn = Foo
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02007997 endclass
7998 def Bar()
7999 var a = A.new()
8000 a.Fn = "abc"
8001 a.Fn = Foo
8002 enddef
8003 test_garbagecollect_now()
8004 Bar()
8005 END
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008006 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 +02008007
8008 " object variable with 'any" type. Can be assigned different types.
8009 let lines =<< trim END
8010 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008011 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008012 return {}
8013 enddef
8014 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008015 public var Fn: any = Foo
8016 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008017 endclass
8018
8019 var a = A.new()
8020 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008021 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008022 a.Fn = "abc"
8023 test_garbagecollect_now()
8024 assert_equal('string', typename(a.Fn))
8025 a.Fn2 = Foo
8026 test_garbagecollect_now()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008027 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008028 a.Fn2 = "xyz"
8029 test_garbagecollect_now()
8030 assert_equal('string', typename(a.Fn2))
8031 END
8032 call v9.CheckSourceSuccess(lines)
8033
8034 " object variable with 'any" type. Can be assigned different types.
8035 let lines =<< trim END
8036 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008037 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008038 return {}
8039 enddef
8040 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008041 public var Fn: any = Foo
8042 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008043
8044 def Bar()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008045 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008046 this.Fn = "abc"
8047 assert_equal('string', typename(this.Fn))
8048 this.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008049 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(this.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008050 this.Fn2 = "xyz"
8051 assert_equal('string', typename(this.Fn2))
8052 enddef
8053 endclass
8054
8055 var a = A.new()
8056 test_garbagecollect_now()
8057 a.Bar()
8058 test_garbagecollect_now()
8059 a.Fn = Foo
8060 a.Bar()
8061 END
8062 call v9.CheckSourceSuccess(lines)
8063
8064 " object variable with 'any" type. Can be assigned different types.
8065 let lines =<< trim END
8066 vim9script
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008067 def Foo(l: list<dict<blob>>): dict<list<blob>>
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008068 return {}
8069 enddef
8070 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008071 public var Fn: any = Foo
8072 public var Fn2: any
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008073 endclass
8074
8075 def Bar()
8076 var a = A.new()
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008077 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008078 a.Fn = "abc"
8079 assert_equal('string', typename(a.Fn))
8080 a.Fn2 = Foo
Yegappan Lakshmanand2f48002023-10-05 20:24:18 +02008081 assert_equal('func(list<dict<blob>>): dict<list<blob>>', typename(a.Fn2))
Yegappan Lakshmananfe7b20a2023-10-04 19:47:52 +02008082 a.Fn2 = "xyz"
8083 assert_equal('string', typename(a.Fn2))
8084 enddef
8085 test_garbagecollect_now()
8086 Bar()
8087 test_garbagecollect_now()
8088 Bar()
8089 END
8090 call v9.CheckSourceSuccess(lines)
8091endfunc
8092
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008093" Test for recursively calling an object method. This used to cause an
8094" use-after-free error.
8095def Test_recursive_object_method_call()
8096 var lines =<< trim END
8097 vim9script
8098 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008099 var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008100 def Foo(): number
8101 if this.val >= 90
8102 return this.val
8103 endif
8104 this.val += 1
8105 return this.Foo()
8106 enddef
8107 endclass
8108 var a = A.new()
8109 assert_equal(90, a.Foo())
8110 END
8111 v9.CheckSourceSuccess(lines)
8112enddef
8113
8114" Test for recursively calling a class method.
8115def Test_recursive_class_method_call()
8116 var lines =<< trim END
8117 vim9script
8118 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008119 static var val: number = 0
Yegappan Lakshmanan1087b8c2023-10-07 22:03:18 +02008120 static def Foo(): number
8121 if val >= 90
8122 return val
8123 endif
8124 val += 1
8125 return Foo()
8126 enddef
8127 endclass
8128 assert_equal(90, A.Foo())
8129 END
8130 v9.CheckSourceSuccess(lines)
8131enddef
8132
Yegappan Lakshmanane4671892023-10-09 18:01:06 +02008133" Test for checking the argument types and the return type when assigning a
8134" funcref to make sure the invariant class type is used.
8135def Test_funcref_argtype_returntype_check()
8136 var lines =<< trim END
8137 vim9script
8138 class A
8139 endclass
8140 class B extends A
8141 endclass
8142
8143 def Foo(p: B): B
8144 return B.new()
8145 enddef
8146
8147 var Bar: func(A): A = Foo
8148 END
8149 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 11)
8150
8151 lines =<< trim END
8152 vim9script
8153 class A
8154 endclass
8155 class B extends A
8156 endclass
8157
8158 def Foo(p: B): B
8159 return B.new()
8160 enddef
8161
8162 def Baz()
8163 var Bar: func(A): A = Foo
8164 enddef
8165 Baz()
8166 END
8167 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
8168enddef
8169
Ernie Rael96952b22023-10-17 18:15:01 +02008170def Test_funcref_argtype_invariance_check()
8171 var lines =<< trim END
8172 vim9script
8173
8174 class A
8175 endclass
8176 class B extends A
8177 endclass
8178 class C extends B
8179 endclass
8180
8181 var Func: func(B): number
8182 Func = (o: B): number => 3
8183 assert_equal(3, Func(B.new()))
8184 END
8185 v9.CheckSourceSuccess(lines)
8186
8187 lines =<< trim END
8188 vim9script
8189
8190 class A
8191 endclass
8192 class B extends A
8193 endclass
8194 class C extends B
8195 endclass
8196
8197 var Func: func(B): number
8198 Func = (o: A): number => 3
8199 END
8200 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<A>): number', 11)
8201
8202 lines =<< trim END
8203 vim9script
8204
8205 class A
8206 endclass
8207 class B extends A
8208 endclass
8209 class C extends B
8210 endclass
8211
8212 var Func: func(B): number
8213 Func = (o: C): number => 3
8214 END
8215 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<B>): number but got func(object<C>): number', 11)
8216enddef
8217
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008218" Test for using an operator (e.g. +) with an assignment
8219def Test_op_and_assignment()
8220 # Using += with a class variable
8221 var lines =<< trim END
8222 vim9script
8223 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008224 public static var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008225 static def Foo(): list<number>
8226 val += [1]
8227 return val
8228 enddef
8229 endclass
8230 def Bar(): list<number>
8231 A.val += [2]
8232 return A.val
8233 enddef
8234 assert_equal([1], A.Foo())
8235 assert_equal([1, 2], Bar())
8236 A.val += [3]
8237 assert_equal([1, 2, 3], A.val)
8238 END
8239 v9.CheckSourceSuccess(lines)
8240
8241 # Using += with an object variable
8242 lines =<< trim END
8243 vim9script
8244 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008245 public var val: list<number> = []
Yegappan Lakshmanan1ea42882023-10-11 21:43:52 +02008246 def Foo(): list<number>
8247 this.val += [1]
8248 return this.val
8249 enddef
8250 endclass
8251 def Bar(bar_a: A): list<number>
8252 bar_a.val += [2]
8253 return bar_a.val
8254 enddef
8255 var a = A.new()
8256 assert_equal([1], a.Foo())
8257 assert_equal([1, 2], Bar(a))
8258 a.val += [3]
8259 assert_equal([1, 2, 3], a.val)
8260 END
8261 v9.CheckSourceSuccess(lines)
8262enddef
8263
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008264" Test for using an object method as a funcref
8265def Test_object_funcref()
8266 # Using object method funcref from a def function
8267 var lines =<< trim END
8268 vim9script
8269 class A
8270 def Foo(): list<number>
8271 return [3, 2, 1]
8272 enddef
8273 endclass
8274 def Bar()
8275 var a = A.new()
8276 var Fn = a.Foo
8277 assert_equal([3, 2, 1], Fn())
8278 enddef
8279 Bar()
8280 END
8281 v9.CheckSourceSuccess(lines)
8282
8283 # Using object method funcref at the script level
8284 lines =<< trim END
8285 vim9script
8286 class A
8287 def Foo(): dict<number>
8288 return {a: 1, b: 2}
8289 enddef
8290 endclass
8291 var a = A.new()
8292 var Fn = a.Foo
8293 assert_equal({a: 1, b: 2}, Fn())
8294 END
8295 v9.CheckSourceSuccess(lines)
8296
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008297 # Using object method funcref at the script level
8298 lines =<< trim END
8299 vim9script
8300 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008301 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008302 def Foo(): number
8303 return this.val
8304 enddef
8305 endclass
8306 var a = A.new(345)
8307 var Fn = a.Foo
8308 assert_equal(345, Fn())
8309 END
8310 v9.CheckSourceSuccess(lines)
8311
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008312 # Using object method funcref from another object method
8313 lines =<< trim END
8314 vim9script
8315 class A
8316 def Foo(): list<number>
8317 return [3, 2, 1]
8318 enddef
8319 def Bar()
8320 var Fn = this.Foo
8321 assert_equal([3, 2, 1], Fn())
8322 enddef
8323 endclass
8324 var a = A.new()
8325 a.Bar()
8326 END
8327 v9.CheckSourceSuccess(lines)
8328
8329 # Using function() to get a object method funcref
8330 lines =<< trim END
8331 vim9script
8332 class A
8333 def Foo(l: list<any>): list<any>
8334 return l
8335 enddef
8336 endclass
8337 var a = A.new()
8338 var Fn = function(a.Foo, [[{a: 1, b: 2}, [3, 4]]])
8339 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8340 END
8341 v9.CheckSourceSuccess(lines)
8342
8343 # Use an object method with a function returning a funcref and then call the
8344 # funcref.
8345 lines =<< trim END
8346 vim9script
8347
8348 def Map(F: func(number): number): func(number): number
8349 return (n: number) => F(n)
8350 enddef
8351
8352 class Math
8353 def Double(n: number): number
8354 return 2 * n
8355 enddef
8356 endclass
8357
8358 const math = Math.new()
8359 assert_equal(48, Map(math.Double)(24))
8360 END
8361 v9.CheckSourceSuccess(lines)
8362
Ernie Rael03042a22023-11-11 08:53:32 +01008363 # Try using a protected object method funcref from a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008364 lines =<< trim END
8365 vim9script
8366 class A
8367 def _Foo()
8368 enddef
8369 endclass
8370 def Bar()
8371 var a = A.new()
8372 var Fn = a._Foo
8373 enddef
8374 Bar()
8375 END
Ernie Rael03042a22023-11-11 08:53:32 +01008376 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 2)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008377
Ernie Rael03042a22023-11-11 08:53:32 +01008378 # Try using a protected object method funcref at the script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008379 lines =<< trim END
8380 vim9script
8381 class A
8382 def _Foo()
8383 enddef
8384 endclass
8385 var a = A.new()
8386 var Fn = a._Foo
8387 END
Ernie Rael03042a22023-11-11 08:53:32 +01008388 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 7)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008389
Ernie Rael03042a22023-11-11 08:53:32 +01008390 # Using a protected object method funcref from another object method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008391 lines =<< trim END
8392 vim9script
8393 class A
8394 def _Foo(): list<number>
8395 return [3, 2, 1]
8396 enddef
8397 def Bar()
8398 var Fn = this._Foo
8399 assert_equal([3, 2, 1], Fn())
8400 enddef
8401 endclass
8402 var a = A.new()
8403 a.Bar()
8404 END
8405 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008406
8407 # Using object method funcref using call()
8408 lines =<< trim END
8409 vim9script
8410 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008411 var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008412 def Foo(): number
8413 return this.val
8414 enddef
8415 endclass
8416
8417 def Bar(obj: A)
8418 assert_equal(123, call(obj.Foo, []))
8419 enddef
8420
8421 var a = A.new(123)
8422 Bar(a)
8423 assert_equal(123, call(a.Foo, []))
8424 END
8425 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008426enddef
8427
8428" Test for using a class method as a funcref
8429def Test_class_funcref()
8430 # Using class method funcref in a def function
8431 var lines =<< trim END
8432 vim9script
8433 class A
8434 static def Foo(): list<number>
8435 return [3, 2, 1]
8436 enddef
8437 endclass
8438 def Bar()
8439 var Fn = A.Foo
8440 assert_equal([3, 2, 1], Fn())
8441 enddef
8442 Bar()
8443 END
8444 v9.CheckSourceSuccess(lines)
8445
8446 # Using class method funcref at script level
8447 lines =<< trim END
8448 vim9script
8449 class A
8450 static def Foo(): dict<number>
8451 return {a: 1, b: 2}
8452 enddef
8453 endclass
8454 var Fn = A.Foo
8455 assert_equal({a: 1, b: 2}, Fn())
8456 END
8457 v9.CheckSourceSuccess(lines)
8458
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008459 # Using class method funcref at the script level
8460 lines =<< trim END
8461 vim9script
8462 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008463 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008464 static def Foo(): number
8465 return val
8466 enddef
8467 endclass
8468 A.val = 567
8469 var Fn = A.Foo
8470 assert_equal(567, Fn())
8471 END
8472 v9.CheckSourceSuccess(lines)
8473
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008474 # Using function() to get a class method funcref
8475 lines =<< trim END
8476 vim9script
8477 class A
8478 static def Foo(l: list<any>): list<any>
8479 return l
8480 enddef
8481 endclass
8482 var Fn = function(A.Foo, [[{a: 1, b: 2}, [3, 4]]])
8483 assert_equal([{a: 1, b: 2}, [3, 4]], Fn())
8484 END
8485 v9.CheckSourceSuccess(lines)
8486
8487 # Using a class method funcref from another class method
8488 lines =<< trim END
8489 vim9script
8490 class A
8491 static def Foo(): list<number>
8492 return [3, 2, 1]
8493 enddef
8494 static def Bar()
8495 var Fn = Foo
8496 assert_equal([3, 2, 1], Fn())
8497 enddef
8498 endclass
8499 A.Bar()
8500 END
8501 v9.CheckSourceSuccess(lines)
8502
8503 # Use a class method with a function returning a funcref and then call the
8504 # funcref.
8505 lines =<< trim END
8506 vim9script
8507
8508 def Map(F: func(number): number): func(number): number
8509 return (n: number) => F(n)
8510 enddef
8511
8512 class Math
8513 static def StaticDouble(n: number): number
8514 return 2 * n
8515 enddef
8516 endclass
8517
8518 assert_equal(48, Map(Math.StaticDouble)(24))
8519 END
8520 v9.CheckSourceSuccess(lines)
8521
Ernie Rael03042a22023-11-11 08:53:32 +01008522 # Try using a protected class method funcref in a def function
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008523 lines =<< trim END
8524 vim9script
8525 class A
8526 static def _Foo()
8527 enddef
8528 endclass
8529 def Bar()
8530 var Fn = A._Foo
8531 enddef
8532 Bar()
8533 END
Ernie Rael03042a22023-11-11 08:53:32 +01008534 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 1)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008535
Ernie Rael03042a22023-11-11 08:53:32 +01008536 # Try using a protected class method funcref at script level
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008537 lines =<< trim END
8538 vim9script
8539 class A
8540 static def _Foo()
8541 enddef
8542 endclass
8543 var Fn = A._Foo
8544 END
Ernie Rael03042a22023-11-11 08:53:32 +01008545 v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo', 6)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008546
Ernie Rael03042a22023-11-11 08:53:32 +01008547 # Using a protected class method funcref from another class method
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008548 lines =<< trim END
8549 vim9script
8550 class A
8551 static def _Foo(): list<number>
8552 return [3, 2, 1]
8553 enddef
8554 static def Bar()
8555 var Fn = _Foo
8556 assert_equal([3, 2, 1], Fn())
8557 enddef
8558 endclass
8559 A.Bar()
8560 END
8561 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008562
8563 # Using class method funcref using call()
8564 lines =<< trim END
8565 vim9script
8566 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008567 public static var val: number
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02008568 static def Foo(): number
8569 return val
8570 enddef
8571 endclass
8572
8573 def Bar()
8574 A.val = 468
8575 assert_equal(468, call(A.Foo, []))
8576 enddef
8577 Bar()
8578 assert_equal(468, call(A.Foo, []))
8579 END
8580 v9.CheckSourceSuccess(lines)
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008581enddef
8582
8583" Test for using an object member as a funcref
8584def Test_object_member_funcref()
8585 # Using a funcref object variable in an object method
8586 var lines =<< trim END
8587 vim9script
8588 def Foo(n: number): number
8589 return n * 10
8590 enddef
8591
8592 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008593 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008594 def Bar()
8595 assert_equal(200, this.Cb(20))
8596 enddef
8597 endclass
8598
8599 var a = A.new()
8600 a.Bar()
8601 END
8602 v9.CheckSourceSuccess(lines)
8603
8604 # Using a funcref object variable in a def method
8605 lines =<< trim END
8606 vim9script
8607 def Foo(n: number): number
8608 return n * 10
8609 enddef
8610
8611 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008612 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008613 endclass
8614
8615 def Bar()
8616 var a = A.new()
8617 assert_equal(200, a.Cb(20))
8618 enddef
8619 Bar()
8620 END
8621 v9.CheckSourceSuccess(lines)
8622
8623 # Using a funcref object variable at script level
8624 lines =<< trim END
8625 vim9script
8626 def Foo(n: number): number
8627 return n * 10
8628 enddef
8629
8630 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008631 var Cb: func(number): number = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008632 endclass
8633
8634 var a = A.new()
8635 assert_equal(200, a.Cb(20))
8636 END
8637 v9.CheckSourceSuccess(lines)
8638
8639 # Using a funcref object variable pointing to an object method in an object
8640 # method.
8641 lines =<< trim END
8642 vim9script
8643 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008644 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008645 def Foo(n: number): number
8646 return n * 10
8647 enddef
8648 def Bar()
8649 assert_equal(200, this.Cb(20))
8650 enddef
8651 endclass
8652
8653 var a = A.new()
8654 a.Bar()
8655 END
8656 v9.CheckSourceSuccess(lines)
8657
8658 # Using a funcref object variable pointing to an object method in a def
8659 # method.
8660 lines =<< trim END
8661 vim9script
8662 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008663 var Cb: func(number): number = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008664 def Foo(n: number): number
8665 return n * 10
8666 enddef
8667 endclass
8668
8669 def Bar()
8670 var a = A.new()
8671 assert_equal(200, a.Cb(20))
8672 enddef
8673 Bar()
8674 END
8675 v9.CheckSourceSuccess(lines)
8676
8677 # Using a funcref object variable pointing to an object method at script
8678 # level.
8679 lines =<< trim END
8680 vim9script
8681 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008682 var Cb = this.Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008683 def Foo(n: number): number
8684 return n * 10
8685 enddef
8686 endclass
8687
8688 var a = A.new()
8689 assert_equal(200, a.Cb(20))
8690 END
8691 v9.CheckSourceSuccess(lines)
8692enddef
8693
8694" Test for using a class member as a funcref
8695def Test_class_member_funcref()
8696 # Using a funcref class variable in a class method
8697 var lines =<< trim END
8698 vim9script
8699 def Foo(n: number): number
8700 return n * 10
8701 enddef
8702
8703 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008704 static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008705 static def Bar()
8706 assert_equal(200, Cb(20))
8707 enddef
8708 endclass
8709
8710 A.Bar()
8711 END
8712 v9.CheckSourceSuccess(lines)
8713
8714 # Using a funcref class variable in a def method
8715 lines =<< trim END
8716 vim9script
8717 def Foo(n: number): number
8718 return n * 10
8719 enddef
8720
8721 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008722 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008723 endclass
8724
8725 def Bar()
8726 assert_equal(200, A.Cb(20))
8727 enddef
8728 Bar()
8729 END
8730 v9.CheckSourceSuccess(lines)
8731
8732 # Using a funcref class variable at script level
8733 lines =<< trim END
8734 vim9script
8735 def Foo(n: number): number
8736 return n * 10
8737 enddef
8738
8739 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008740 public static var Cb = Foo
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008741 endclass
8742
8743 assert_equal(200, A.Cb(20))
8744 END
8745 v9.CheckSourceSuccess(lines)
8746
8747 # Using a funcref class variable pointing to a class method in a class
8748 # method.
8749 lines =<< trim END
8750 vim9script
8751 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008752 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008753 static def Foo(n: number): number
8754 return n * 10
8755 enddef
8756 static def Init()
8757 Cb = Foo
8758 enddef
8759 static def Bar()
8760 assert_equal(200, Cb(20))
8761 enddef
8762 endclass
8763
8764 A.Init()
8765 A.Bar()
8766 END
8767 v9.CheckSourceSuccess(lines)
8768
8769 # Using a funcref class variable pointing to a class method in a def method.
8770 lines =<< trim END
8771 vim9script
8772 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008773 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008774 static def Foo(n: number): number
8775 return n * 10
8776 enddef
8777 static def Init()
8778 Cb = Foo
8779 enddef
8780 endclass
8781
8782 def Bar()
8783 A.Init()
8784 assert_equal(200, A.Cb(20))
8785 enddef
8786 Bar()
8787 END
8788 v9.CheckSourceSuccess(lines)
8789
8790 # Using a funcref class variable pointing to a class method at script level.
8791 lines =<< trim END
8792 vim9script
8793 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008794 static var Cb: func(number): number
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02008795 static def Foo(n: number): number
8796 return n * 10
8797 enddef
8798 static def Init()
8799 Cb = Foo
8800 enddef
8801 endclass
8802
8803 A.Init()
8804 assert_equal(200, A.Cb(20))
8805 END
8806 v9.CheckSourceSuccess(lines)
8807enddef
8808
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008809" Test for using object methods as popup callback functions
8810def Test_objmethod_popup_callback()
8811 # Use the popup from the script level
8812 var lines =<< trim END
8813 vim9script
8814
8815 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008816 var selection: number = -1
8817 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008818
8819 def PopupFilter(id: number, key: string): bool
8820 add(this.filterkeys, key)
8821 return popup_filter_yesno(id, key)
8822 enddef
8823
8824 def PopupCb(id: number, result: number)
8825 this.selection = result ? 100 : 200
8826 enddef
8827 endclass
8828
8829 var a = A.new()
8830 feedkeys('', 'xt')
8831 var winid = popup_create('Y/N?',
8832 {filter: a.PopupFilter, callback: a.PopupCb})
8833 feedkeys('y', 'xt')
8834 popup_close(winid)
8835 assert_equal(100, a.selection)
8836 assert_equal(['y'], a.filterkeys)
8837 feedkeys('', 'xt')
8838 winid = popup_create('Y/N?',
8839 {filter: a.PopupFilter, callback: a.PopupCb})
8840 feedkeys('n', 'xt')
8841 popup_close(winid)
8842 assert_equal(200, a.selection)
8843 assert_equal(['y', 'n'], a.filterkeys)
8844 END
8845 v9.CheckSourceSuccess(lines)
8846
8847 # Use the popup from a def function
8848 lines =<< trim END
8849 vim9script
8850
8851 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008852 var selection: number = -1
8853 var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008854
8855 def PopupFilter(id: number, key: string): bool
8856 add(this.filterkeys, key)
8857 return popup_filter_yesno(id, key)
8858 enddef
8859
8860 def PopupCb(id: number, result: number)
8861 this.selection = result ? 100 : 200
8862 enddef
8863 endclass
8864
8865 def Foo()
8866 var a = A.new()
8867 feedkeys('', 'xt')
8868 var winid = popup_create('Y/N?',
8869 {filter: a.PopupFilter, callback: a.PopupCb})
8870 feedkeys('y', 'xt')
8871 popup_close(winid)
8872 assert_equal(100, a.selection)
8873 assert_equal(['y'], a.filterkeys)
8874 feedkeys('', 'xt')
8875 winid = popup_create('Y/N?',
8876 {filter: a.PopupFilter, callback: a.PopupCb})
8877 feedkeys('n', 'xt')
8878 popup_close(winid)
8879 assert_equal(200, a.selection)
8880 assert_equal(['y', 'n'], a.filterkeys)
8881 enddef
8882 Foo()
8883 END
8884 v9.CheckSourceSuccess(lines)
8885enddef
8886
8887" Test for using class methods as popup callback functions
8888def Test_classmethod_popup_callback()
8889 # Use the popup from the script level
8890 var lines =<< trim END
8891 vim9script
8892
8893 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008894 static var selection: number = -1
8895 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008896
8897 static def PopupFilter(id: number, key: string): bool
8898 add(filterkeys, key)
8899 return popup_filter_yesno(id, key)
8900 enddef
8901
8902 static def PopupCb(id: number, result: number)
8903 selection = result ? 100 : 200
8904 enddef
8905 endclass
8906
8907 feedkeys('', 'xt')
8908 var winid = popup_create('Y/N?',
8909 {filter: A.PopupFilter, callback: A.PopupCb})
8910 feedkeys('y', 'xt')
8911 popup_close(winid)
8912 assert_equal(100, A.selection)
8913 assert_equal(['y'], A.filterkeys)
8914 feedkeys('', 'xt')
8915 winid = popup_create('Y/N?',
8916 {filter: A.PopupFilter, callback: A.PopupCb})
8917 feedkeys('n', 'xt')
8918 popup_close(winid)
8919 assert_equal(200, A.selection)
8920 assert_equal(['y', 'n'], A.filterkeys)
8921 END
8922 v9.CheckSourceSuccess(lines)
8923
8924 # Use the popup from a def function
8925 lines =<< trim END
8926 vim9script
8927
8928 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008929 static var selection: number = -1
8930 static var filterkeys: list<string> = []
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008931
8932 static def PopupFilter(id: number, key: string): bool
8933 add(filterkeys, key)
8934 return popup_filter_yesno(id, key)
8935 enddef
8936
8937 static def PopupCb(id: number, result: number)
8938 selection = result ? 100 : 200
8939 enddef
8940 endclass
8941
8942 def Foo()
8943 feedkeys('', 'xt')
8944 var winid = popup_create('Y/N?',
8945 {filter: A.PopupFilter, callback: A.PopupCb})
8946 feedkeys('y', 'xt')
8947 popup_close(winid)
8948 assert_equal(100, A.selection)
8949 assert_equal(['y'], A.filterkeys)
8950 feedkeys('', 'xt')
8951 winid = popup_create('Y/N?',
8952 {filter: A.PopupFilter, callback: A.PopupCb})
8953 feedkeys('n', 'xt')
8954 popup_close(winid)
8955 assert_equal(200, A.selection)
8956 assert_equal(['y', 'n'], A.filterkeys)
8957 enddef
8958 Foo()
8959 END
8960 v9.CheckSourceSuccess(lines)
8961enddef
8962
8963" Test for using an object method as a timer callback function
8964def Test_objmethod_timer_callback()
8965 # Use the timer callback from script level
8966 var lines =<< trim END
8967 vim9script
8968
8969 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008970 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008971 def TimerCb(timerID: number)
8972 this.timerTick = 6
8973 enddef
8974 endclass
8975
8976 var a = A.new()
8977 timer_start(0, a.TimerCb)
8978 var maxWait = 5
8979 while maxWait > 0 && a.timerTick == -1
8980 :sleep 10m
8981 maxWait -= 1
8982 endwhile
8983 assert_equal(6, a.timerTick)
8984 END
8985 v9.CheckSourceSuccess(lines)
8986
8987 # Use the timer callback from a def function
8988 lines =<< trim END
8989 vim9script
8990
8991 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01008992 var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02008993 def TimerCb(timerID: number)
8994 this.timerTick = 6
8995 enddef
8996 endclass
8997
8998 def Foo()
8999 var a = A.new()
9000 timer_start(0, a.TimerCb)
9001 var maxWait = 5
9002 while maxWait > 0 && a.timerTick == -1
9003 :sleep 10m
9004 maxWait -= 1
9005 endwhile
9006 assert_equal(6, a.timerTick)
9007 enddef
9008 Foo()
9009 END
9010 v9.CheckSourceSuccess(lines)
9011enddef
9012
9013" Test for using a class method as a timer callback function
9014def Test_classmethod_timer_callback()
9015 # Use the timer callback from script level
9016 var lines =<< trim END
9017 vim9script
9018
9019 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009020 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009021 static def TimerCb(timerID: number)
9022 timerTick = 6
9023 enddef
9024 endclass
9025
9026 timer_start(0, A.TimerCb)
9027 var maxWait = 5
9028 while maxWait > 0 && A.timerTick == -1
9029 :sleep 10m
9030 maxWait -= 1
9031 endwhile
9032 assert_equal(6, A.timerTick)
9033 END
9034 v9.CheckSourceSuccess(lines)
9035
9036 # Use the timer callback from a def function
9037 lines =<< trim END
9038 vim9script
9039
9040 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009041 static var timerTick: number = -1
Yegappan Lakshmananf3eac692023-10-17 11:00:45 +02009042 static def TimerCb(timerID: number)
9043 timerTick = 6
9044 enddef
9045 endclass
9046
9047 def Foo()
9048 timer_start(0, A.TimerCb)
9049 var maxWait = 5
9050 while maxWait > 0 && A.timerTick == -1
9051 :sleep 10m
9052 maxWait -= 1
9053 endwhile
9054 assert_equal(6, A.timerTick)
9055 enddef
9056 Foo()
9057 END
9058 v9.CheckSourceSuccess(lines)
9059enddef
9060
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009061" Test for using a class variable as the first and/or second operand of a binary
9062" operator.
9063def Test_class_variable_as_operands()
9064 var lines =<< trim END
9065 vim9script
9066 class Tests
Doug Kearns74da0ee2023-12-14 20:26:26 +01009067 static var truthy: bool = true
9068 public static var TruthyFn: func
9069 static var list: list<any> = []
9070 static var four: number = 4
9071 static var str: string = 'hello'
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009072
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009073 static def Str(): string
9074 return str
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009075 enddef
9076
9077 static def Four(): number
9078 return four
9079 enddef
9080
9081 static def List(): list<any>
9082 return list
9083 enddef
9084
9085 static def Truthy(): bool
9086 return truthy
9087 enddef
9088
9089 def TestOps()
9090 assert_true(Tests.truthy == truthy)
9091 assert_true(truthy == Tests.truthy)
9092 assert_true(Tests.list isnot [])
9093 assert_true([] isnot Tests.list)
9094 assert_equal(2, Tests.four >> 1)
9095 assert_equal(16, 1 << Tests.four)
9096 assert_equal(8, Tests.four + four)
9097 assert_equal(8, four + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009098 assert_equal('hellohello', Tests.str .. str)
9099 assert_equal('hellohello', str .. Tests.str)
9100
9101 # Using class variable for list indexing
9102 var l = range(10)
9103 assert_equal(4, l[Tests.four])
9104 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9105
9106 # Using class variable for Dict key
9107 var d = {hello: 'abc'}
9108 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009109 enddef
9110 endclass
9111
9112 def TestOps2()
9113 assert_true(Tests.truthy == Tests.Truthy())
9114 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009115 assert_true(Tests.truthy == Tests.TruthyFn())
9116 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009117 assert_true(Tests.list is Tests.List())
9118 assert_true(Tests.List() is Tests.list)
9119 assert_equal(2, Tests.four >> 1)
9120 assert_equal(16, 1 << Tests.four)
9121 assert_equal(8, Tests.four + Tests.Four())
9122 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009123 assert_equal('hellohello', Tests.str .. Tests.Str())
9124 assert_equal('hellohello', Tests.Str() .. Tests.str)
9125
9126 # Using class variable for list indexing
9127 var l = range(10)
9128 assert_equal(4, l[Tests.four])
9129 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9130
9131 # Using class variable for Dict key
9132 var d = {hello: 'abc'}
9133 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009134 enddef
9135
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009136 Tests.TruthyFn = Tests.Truthy
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009137 var t = Tests.new()
9138 t.TestOps()
9139 TestOps2()
9140
9141 assert_true(Tests.truthy == Tests.Truthy())
9142 assert_true(Tests.Truthy() == Tests.truthy)
Yegappan Lakshmanan00b55372023-10-19 17:18:28 +02009143 assert_true(Tests.truthy == Tests.TruthyFn())
9144 assert_true(Tests.TruthyFn() == Tests.truthy)
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009145 assert_true(Tests.list is Tests.List())
9146 assert_true(Tests.List() is Tests.list)
9147 assert_equal(2, Tests.four >> 1)
9148 assert_equal(16, 1 << Tests.four)
9149 assert_equal(8, Tests.four + Tests.Four())
9150 assert_equal(8, Tests.Four() + Tests.four)
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +02009151 assert_equal('hellohello', Tests.str .. Tests.Str())
9152 assert_equal('hellohello', Tests.Str() .. Tests.str)
9153
9154 # Using class variable for list indexing
9155 var l = range(10)
9156 assert_equal(4, l[Tests.four])
9157 assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
9158
9159 # Using class variable for Dict key
9160 var d = {hello: 'abc'}
9161 assert_equal('abc', d[Tests.str])
Yegappan Lakshmanand7b616d2023-10-19 10:47:53 +02009162 END
9163 v9.CheckSourceSuccess(lines)
9164enddef
9165
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009166" Test for checking the type of the key used to access an object dict member.
9167def Test_dict_member_key_type_check()
9168 var lines =<< trim END
9169 vim9script
9170
9171 abstract class State
Doug Kearns74da0ee2023-12-14 20:26:26 +01009172 var numbers: dict<string> = {0: 'nil', 1: 'unity'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009173 endclass
9174
9175 class Test extends State
9176 def ObjMethodTests()
9177 var cursor: number = 0
9178 var z: number = 0
9179 [this.numbers[cursor]] = ['zero.1']
9180 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9181 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9182 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9183 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9184 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9185 [this.numbers[cursor], z] = ['zero.4', 1]
9186 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9187 [z, this.numbers[cursor]] = [1, 'zero.5']
9188 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9189 enddef
9190
9191 static def ClassMethodTests(that: State)
9192 var cursor: number = 0
9193 var z: number = 0
9194 [that.numbers[cursor]] = ['zero.1']
9195 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9196 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9197 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9198 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9199 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9200 [that.numbers[cursor], z] = ['zero.4', 1]
9201 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9202 [z, that.numbers[cursor]] = [1, 'zero.5']
9203 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9204 enddef
9205
9206 def new()
9207 enddef
9208
9209 def newMethodTests()
9210 var cursor: number = 0
9211 var z: number
9212 [this.numbers[cursor]] = ['zero.1']
9213 assert_equal({0: 'zero.1', 1: 'unity'}, this.numbers)
9214 [this.numbers[string(cursor)], z] = ['zero.2', 1]
9215 assert_equal({0: 'zero.2', 1: 'unity'}, this.numbers)
9216 [z, this.numbers[string(cursor)]] = [1, 'zero.3']
9217 assert_equal({0: 'zero.3', 1: 'unity'}, this.numbers)
9218 [this.numbers[cursor], z] = ['zero.4', 1]
9219 assert_equal({0: 'zero.4', 1: 'unity'}, this.numbers)
9220 [z, this.numbers[cursor]] = [1, 'zero.5']
9221 assert_equal({0: 'zero.5', 1: 'unity'}, this.numbers)
9222 enddef
9223 endclass
9224
9225 def DefFuncTests(that: Test)
9226 var cursor: number = 0
9227 var z: number
9228 [that.numbers[cursor]] = ['zero.1']
9229 assert_equal({0: 'zero.1', 1: 'unity'}, that.numbers)
9230 [that.numbers[string(cursor)], z] = ['zero.2', 1]
9231 assert_equal({0: 'zero.2', 1: 'unity'}, that.numbers)
9232 [z, that.numbers[string(cursor)]] = [1, 'zero.3']
9233 assert_equal({0: 'zero.3', 1: 'unity'}, that.numbers)
9234 [that.numbers[cursor], z] = ['zero.4', 1]
9235 assert_equal({0: 'zero.4', 1: 'unity'}, that.numbers)
9236 [z, that.numbers[cursor]] = [1, 'zero.5']
9237 assert_equal({0: 'zero.5', 1: 'unity'}, that.numbers)
9238 enddef
9239
9240 Test.newMethodTests()
9241 Test.new().ObjMethodTests()
9242 Test.ClassMethodTests(Test.new())
9243 DefFuncTests(Test.new())
9244
9245 const test: Test = Test.new()
9246 var cursor: number = 0
9247 [test.numbers[cursor], cursor] = ['zero', 1]
9248 [cursor, test.numbers[cursor]] = [1, 'one']
9249 assert_equal({0: 'zero', 1: 'one'}, test.numbers)
9250 END
9251 v9.CheckSourceSuccess(lines)
9252
9253 lines =<< trim END
9254 vim9script
9255
9256 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009257 var numbers: dict<string> = {a: '1', b: '2'}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009258
9259 def new()
9260 enddef
9261
9262 def Foo()
9263 var z: number
9264 [this.numbers.a, z] = [{}, 10]
9265 enddef
9266 endclass
9267
9268 var a = A.new()
9269 a.Foo()
9270 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009271 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got dict<any>', 2)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009272
9273 lines =<< trim END
9274 vim9script
9275
9276 class A
Doug Kearns74da0ee2023-12-14 20:26:26 +01009277 var numbers: dict<number> = {a: 1, b: 2}
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009278
9279 def new()
9280 enddef
9281
9282 def Foo()
9283 var x: string = 'a'
9284 var y: number
9285 [this.numbers[x], y] = [{}, 10]
9286 enddef
9287 endclass
9288
9289 var a = A.new()
9290 a.Foo()
9291 END
Yegappan Lakshmanan66897192023-12-05 15:51:50 +01009292 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got dict<any>', 3)
Yegappan Lakshmananc229a6a2023-10-26 23:05:07 +02009293enddef
9294
mityua5550692023-11-25 15:41:20 +01009295def Test_compile_many_def_functions_in_funcref_instr()
9296 # This used to crash Vim. This is reproducible only when run on new instance
9297 # of Vim.
9298 var lines =<< trim END
9299 vim9script
9300
9301 class A
9302 def new()
9303 this.TakeFunc(this.F00)
9304 enddef
9305
9306 def TakeFunc(F: func)
9307 enddef
9308
9309 def F00()
9310 this.F01()
9311 this.F02()
9312 this.F03()
9313 this.F04()
9314 this.F05()
9315 this.F06()
9316 this.F07()
9317 this.F08()
9318 this.F09()
9319 this.F10()
9320 this.F11()
9321 this.F12()
9322 this.F13()
9323 this.F14()
9324 this.F15()
9325 this.F16()
9326 this.F17()
9327 this.F18()
9328 this.F19()
9329 this.F20()
9330 this.F21()
9331 this.F22()
9332 this.F23()
9333 this.F24()
9334 this.F25()
9335 this.F26()
9336 this.F27()
9337 this.F28()
9338 this.F29()
9339 this.F30()
9340 this.F31()
9341 this.F32()
9342 this.F33()
9343 this.F34()
9344 this.F35()
9345 this.F36()
9346 this.F37()
9347 this.F38()
9348 this.F39()
9349 this.F40()
9350 this.F41()
9351 this.F42()
9352 this.F43()
9353 this.F44()
9354 this.F45()
9355 this.F46()
9356 this.F47()
9357 enddef
9358
9359 def F01()
9360 enddef
9361 def F02()
9362 enddef
9363 def F03()
9364 enddef
9365 def F04()
9366 enddef
9367 def F05()
9368 enddef
9369 def F06()
9370 enddef
9371 def F07()
9372 enddef
9373 def F08()
9374 enddef
9375 def F09()
9376 enddef
9377 def F10()
9378 enddef
9379 def F11()
9380 enddef
9381 def F12()
9382 enddef
9383 def F13()
9384 enddef
9385 def F14()
9386 enddef
9387 def F15()
9388 enddef
9389 def F16()
9390 enddef
9391 def F17()
9392 enddef
9393 def F18()
9394 enddef
9395 def F19()
9396 enddef
9397 def F20()
9398 enddef
9399 def F21()
9400 enddef
9401 def F22()
9402 enddef
9403 def F23()
9404 enddef
9405 def F24()
9406 enddef
9407 def F25()
9408 enddef
9409 def F26()
9410 enddef
9411 def F27()
9412 enddef
9413 def F28()
9414 enddef
9415 def F29()
9416 enddef
9417 def F30()
9418 enddef
9419 def F31()
9420 enddef
9421 def F32()
9422 enddef
9423 def F33()
9424 enddef
9425 def F34()
9426 enddef
9427 def F35()
9428 enddef
9429 def F36()
9430 enddef
9431 def F37()
9432 enddef
9433 def F38()
9434 enddef
9435 def F39()
9436 enddef
9437 def F40()
9438 enddef
9439 def F41()
9440 enddef
9441 def F42()
9442 enddef
9443 def F43()
9444 enddef
9445 def F44()
9446 enddef
9447 def F45()
9448 enddef
9449 def F46()
9450 enddef
9451 def F47()
9452 enddef
9453 endclass
9454
9455 A.new()
9456 END
9457 writefile(lines, 'Xscript', 'D')
9458 g:RunVim([], [], '-u NONE -S Xscript -c qa')
9459 assert_equal(0, v:shell_error)
9460enddef
9461
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +01009462" Test for 'final' class and object variables
9463def Test_final_class_object_variable()
9464 # Test for changing a final object variable from an object function
9465 var lines =<< trim END
9466 vim9script
9467 class A
9468 final foo: string = "abc"
9469 def Foo()
9470 this.foo = "def"
9471 enddef
9472 endclass
9473 defcompile A.Foo
9474 END
9475 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9476
9477 # Test for changing a final object variable from the 'new' function
9478 lines =<< trim END
9479 vim9script
9480 class A
9481 final s1: string
9482 final s2: string
9483 def new(this.s1)
9484 this.s2 = 'def'
9485 enddef
9486 endclass
9487 var a = A.new('abc')
9488 assert_equal('abc', a.s1)
9489 assert_equal('def', a.s2)
9490 END
9491 v9.CheckSourceSuccess(lines)
9492
9493 # Test for a final class variable
9494 lines =<< trim END
9495 vim9script
9496 class A
9497 static final s1: string = "abc"
9498 endclass
9499 assert_equal('abc', A.s1)
9500 END
9501 v9.CheckSourceSuccess(lines)
9502
9503 # Test for changing a final class variable from a class function
9504 lines =<< trim END
9505 vim9script
9506 class A
9507 static final s1: string = "abc"
9508 static def Foo()
9509 s1 = "def"
9510 enddef
9511 endclass
9512 A.Foo()
9513 END
9514 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9515
9516 # Test for changing a public final class variable at script level
9517 lines =<< trim END
9518 vim9script
9519 class A
9520 public static final s1: string = "abc"
9521 endclass
9522 assert_equal('abc', A.s1)
9523 A.s1 = 'def'
9524 END
9525 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9526
9527 # Test for changing a public final class variable from a class function
9528 lines =<< trim END
9529 vim9script
9530 class A
9531 public static final s1: string = "abc"
9532 static def Foo()
9533 s1 = "def"
9534 enddef
9535 endclass
9536 A.Foo()
9537 END
9538 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9539
9540 # Test for changing a public final class variable from a function
9541 lines =<< trim END
9542 vim9script
9543 class A
9544 public static final s1: string = "abc"
9545 endclass
9546 def Foo()
9547 A.s1 = 'def'
9548 enddef
9549 defcompile
9550 END
9551 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9552
9553 # Test for using a final variable of composite type
9554 lines =<< trim END
9555 vim9script
9556 class A
9557 public final l: list<number>
9558 def new()
9559 this.l = [1, 2]
9560 enddef
9561 def Foo()
9562 this.l[0] = 3
9563 this.l->add(4)
9564 enddef
9565 endclass
9566 var a = A.new()
9567 assert_equal([1, 2], a.l)
9568 a.Foo()
9569 assert_equal([3, 2, 4], a.l)
9570 END
9571 v9.CheckSourceSuccess(lines)
9572
9573 # Test for changing a final variable of composite type from another object
9574 # function
9575 lines =<< trim END
9576 vim9script
9577 class A
9578 public final l: list<number> = [1, 2]
9579 def Foo()
9580 this.l = [3, 4]
9581 enddef
9582 endclass
9583 var a = A.new()
9584 a.Foo()
9585 END
9586 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9587
9588 # Test for modifying a final variable of composite type at script level
9589 lines =<< trim END
9590 vim9script
9591 class A
9592 public final l: list<number> = [1, 2]
9593 endclass
9594 var a = A.new()
9595 a.l[0] = 3
9596 a.l->add(4)
9597 assert_equal([3, 2, 4], a.l)
9598 END
9599 v9.CheckSourceSuccess(lines)
9600
9601 # Test for modifying a final variable of composite type from a function
9602 lines =<< trim END
9603 vim9script
9604 class A
9605 public final l: list<number> = [1, 2]
9606 endclass
9607 def Foo()
9608 var a = A.new()
9609 a.l[0] = 3
9610 a.l->add(4)
9611 assert_equal([3, 2, 4], a.l)
9612 enddef
9613 Foo()
9614 END
9615 v9.CheckSourceSuccess(lines)
9616
9617 # Test for modifying a final variable of composite type from another object
9618 # function
9619 lines =<< trim END
9620 vim9script
9621 class A
9622 public final l: list<number> = [1, 2]
9623 def Foo()
9624 this.l[0] = 3
9625 this.l->add(4)
9626 enddef
9627 endclass
9628 var a = A.new()
9629 a.Foo()
9630 assert_equal([3, 2, 4], a.l)
9631 END
9632 v9.CheckSourceSuccess(lines)
9633
9634 # Test for assigning a new value to a final variable of composite type at
9635 # script level
9636 lines =<< trim END
9637 vim9script
9638 class A
9639 public final l: list<number> = [1, 2]
9640 endclass
9641 var a = A.new()
9642 a.l = [3, 4]
9643 END
9644 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
9645
9646 # Test for assigning a new value to a final variable of composite type from
9647 # another object function
9648 lines =<< trim END
9649 vim9script
9650 class A
9651 public final l: list<number> = [1, 2]
9652 def Foo()
9653 this.l = [3, 4]
9654 enddef
9655 endclass
9656 var a = A.new()
9657 a.Foo()
9658 END
9659 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9660
9661 # Test for assigning a new value to a final variable of composite type from
9662 # another function
9663 lines =<< trim END
9664 vim9script
9665 class A
9666 public final l: list<number> = [1, 2]
9667 endclass
9668 def Foo()
9669 var a = A.new()
9670 a.l = [3, 4]
9671 enddef
9672 Foo()
9673 END
9674 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
9675
9676 # Error case: Use 'final' with just a variable name
9677 lines =<< trim END
9678 vim9script
9679 class A
9680 final foo
9681 endclass
9682 var a = A.new()
9683 END
9684 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9685
9686 # Error case: Use 'final' followed by 'public'
9687 lines =<< trim END
9688 vim9script
9689 class A
9690 final public foo: number
9691 endclass
9692 var a = A.new()
9693 END
9694 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9695
9696 # Error case: Use 'final' followed by 'static'
9697 lines =<< trim END
9698 vim9script
9699 class A
9700 final static foo: number
9701 endclass
9702 var a = A.new()
9703 END
9704 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9705
9706 # Error case: 'final' cannot be used in an interface
9707 lines =<< trim END
9708 vim9script
9709 interface A
9710 final foo: number = 10
9711 endinterface
9712 END
9713 v9.CheckSourceFailure(lines, 'E1408: Final variable not supported in an interface', 3)
9714
9715 # Error case: 'final' not supported for an object method
9716 lines =<< trim END
9717 vim9script
9718 class A
9719 final def Foo()
9720 enddef
9721 endclass
9722 END
9723 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9724
9725 # Error case: 'final' not supported for a class method
9726 lines =<< trim END
9727 vim9script
9728 class A
9729 static final def Foo()
9730 enddef
9731 endclass
9732 END
9733 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
9734enddef
9735
9736" Test for 'const' class and object variables
9737def Test_const_class_object_variable()
9738 # Test for changing a const object variable from an object function
9739 var lines =<< trim END
9740 vim9script
9741 class A
9742 const foo: string = "abc"
9743 def Foo()
9744 this.foo = "def"
9745 enddef
9746 endclass
9747 defcompile A.Foo
9748 END
9749 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "foo" in class "A"', 1)
9750
9751 # Test for changing a const object variable from the 'new' function
9752 lines =<< trim END
9753 vim9script
9754 class A
9755 const s1: string
9756 const s2: string
9757 def new(this.s1)
9758 this.s2 = 'def'
9759 enddef
9760 endclass
9761 var a = A.new('abc')
9762 assert_equal('abc', a.s1)
9763 assert_equal('def', a.s2)
9764 END
9765 v9.CheckSourceSuccess(lines)
9766
9767 # Test for changing a const object variable from an object method called from
9768 # the 'new' function
9769 lines =<< trim END
9770 vim9script
9771 class A
9772 const s1: string = 'abc'
9773 def new()
9774 this.ChangeStr()
9775 enddef
9776 def ChangeStr()
9777 this.s1 = 'def'
9778 enddef
9779 endclass
9780 var a = A.new()
9781 END
9782 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9783
9784 # Test for a const class variable
9785 lines =<< trim END
9786 vim9script
9787 class A
9788 static const s1: string = "abc"
9789 endclass
9790 assert_equal('abc', A.s1)
9791 END
9792 v9.CheckSourceSuccess(lines)
9793
9794 # Test for changing a const class variable from a class function
9795 lines =<< trim END
9796 vim9script
9797 class A
9798 static const s1: string = "abc"
9799 static def Foo()
9800 s1 = "def"
9801 enddef
9802 endclass
9803 A.Foo()
9804 END
9805 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9806
9807 # Test for changing a public const class variable at script level
9808 lines =<< trim END
9809 vim9script
9810 class A
9811 public static const s1: string = "abc"
9812 endclass
9813 assert_equal('abc', A.s1)
9814 A.s1 = 'def'
9815 END
9816 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 6)
9817
9818 # Test for changing a public const class variable from a class function
9819 lines =<< trim END
9820 vim9script
9821 class A
9822 public static const s1: string = "abc"
9823 static def Foo()
9824 s1 = "def"
9825 enddef
9826 endclass
9827 A.Foo()
9828 END
9829 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9830
9831 # Test for changing a public const class variable from a function
9832 lines =<< trim END
9833 vim9script
9834 class A
9835 public static const s1: string = "abc"
9836 endclass
9837 def Foo()
9838 A.s1 = 'def'
9839 enddef
9840 defcompile
9841 END
9842 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "s1" in class "A"', 1)
9843
9844 # Test for changing a const List item from an object function
9845 lines =<< trim END
9846 vim9script
9847 class A
9848 public const l: list<number>
9849 def new()
9850 this.l = [1, 2]
9851 enddef
9852 def Foo()
9853 this.l[0] = 3
9854 enddef
9855 endclass
9856 var a = A.new()
9857 assert_equal([1, 2], a.l)
9858 a.Foo()
9859 END
9860 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
9861
9862 # Test for adding a value to a const List from an object function
9863 lines =<< trim END
9864 vim9script
9865 class A
9866 public const l: list<number>
9867 def new()
9868 this.l = [1, 2]
9869 enddef
9870 def Foo()
9871 this.l->add(3)
9872 enddef
9873 endclass
9874 var a = A.new()
9875 a.Foo()
9876 END
9877 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
9878
9879 # Test for reassigning a const List from an object function
9880 lines =<< trim END
9881 vim9script
9882 class A
9883 public const l: list<number> = [1, 2]
9884 def Foo()
9885 this.l = [3, 4]
9886 enddef
9887 endclass
9888 var a = A.new()
9889 a.Foo()
9890 END
9891 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9892
9893 # Test for changing a const List item at script level
9894 lines =<< trim END
9895 vim9script
9896 class A
9897 public const l: list<number> = [1, 2]
9898 endclass
9899 var a = A.new()
9900 a.l[0] = 3
9901 END
9902 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
9903
9904 # Test for adding a value to a const List item at script level
9905 lines =<< trim END
9906 vim9script
9907 class A
9908 public const l: list<number> = [1, 2]
9909 endclass
9910 var a = A.new()
9911 a.l->add(4)
9912 END
9913 v9.CheckSourceFailure(lines, 'E741: Value is locked:', 6)
9914
9915 # Test for changing a const List item from a function
9916 lines =<< trim END
9917 vim9script
9918 class A
9919 public const l: list<number> = [1, 2]
9920 endclass
9921 def Foo()
9922 var a = A.new()
9923 a.l[0] = 3
9924 enddef
9925 Foo()
9926 END
9927 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 2)
9928
9929 # Test for adding a value to a const List item from a function
9930 lines =<< trim END
9931 vim9script
9932 class A
9933 public const l: list<number> = [1, 2]
9934 endclass
9935 def Foo()
9936 var a = A.new()
9937 a.l->add(4)
9938 enddef
9939 Foo()
9940 END
9941 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 2)
9942
9943 # Test for changing a const List item from an object method
9944 lines =<< trim END
9945 vim9script
9946 class A
9947 public const l: list<number> = [1, 2]
9948 def Foo()
9949 this.l[0] = 3
9950 enddef
9951 endclass
9952 var a = A.new()
9953 a.Foo()
9954 END
9955 v9.CheckSourceFailure(lines, 'E1119: Cannot change locked list item', 1)
9956
9957 # Test for adding a value to a const List item from an object method
9958 lines =<< trim END
9959 vim9script
9960 class A
9961 public const l: list<number> = [1, 2]
9962 def Foo()
9963 this.l->add(4)
9964 enddef
9965 endclass
9966 var a = A.new()
9967 a.Foo()
9968 END
9969 v9.CheckSourceFailure(lines, 'E741: Value is locked: add() argument', 1)
9970
9971 # Test for reassigning a const List object variable at script level
9972 lines =<< trim END
9973 vim9script
9974 class A
9975 public const l: list<number> = [1, 2]
9976 endclass
9977 var a = A.new()
9978 a.l = [3, 4]
9979 END
9980 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 6)
9981
9982 # Test for reassigning a const List object variable from an object method
9983 lines =<< trim END
9984 vim9script
9985 class A
9986 public const l: list<number> = [1, 2]
9987 def Foo()
9988 this.l = [3, 4]
9989 enddef
9990 endclass
9991 var a = A.new()
9992 a.Foo()
9993 END
9994 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 1)
9995
9996 # Test for reassigning a const List object variable from another function
9997 lines =<< trim END
9998 vim9script
9999 class A
10000 public const l: list<number> = [1, 2]
10001 endclass
10002 def Foo()
10003 var a = A.new()
10004 a.l = [3, 4]
10005 enddef
10006 Foo()
10007 END
10008 v9.CheckSourceFailure(lines, 'E1409: Cannot change read-only variable "l" in class "A"', 2)
10009
10010 # Error case: Use 'const' with just a variable name
10011 lines =<< trim END
10012 vim9script
10013 class A
10014 const foo
10015 endclass
10016 var a = A.new()
10017 END
10018 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10019
10020 # Error case: Use 'const' followed by 'public'
10021 lines =<< trim END
10022 vim9script
10023 class A
10024 const public foo: number
10025 endclass
10026 var a = A.new()
10027 END
10028 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10029
10030 # Error case: Use 'const' followed by 'static'
10031 lines =<< trim END
10032 vim9script
10033 class A
10034 const static foo: number
10035 endclass
10036 var a = A.new()
10037 END
10038 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10039
10040 # Error case: 'const' cannot be used in an interface
10041 lines =<< trim END
10042 vim9script
10043 interface A
10044 const foo: number = 10
10045 endinterface
10046 END
10047 v9.CheckSourceFailure(lines, 'E1410: Const variable not supported in an interface', 3)
10048
10049 # Error case: 'const' not supported for an object method
10050 lines =<< trim END
10051 vim9script
10052 class A
10053 const def Foo()
10054 enddef
10055 endclass
10056 END
10057 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10058
10059 # Error case: 'const' not supported for a class method
10060 lines =<< trim END
10061 vim9script
10062 class A
10063 static const def Foo()
10064 enddef
10065 endclass
10066 END
10067 v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
10068enddef
10069
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +010010070" Test for compiling class/object methods using :defcompile
10071def Test_defcompile_class()
10072 # defcompile all the classes in the current script
10073 var lines =<< trim END
10074 vim9script
10075 class A
10076 def Foo()
10077 var i = 10
10078 enddef
10079 endclass
10080 class B
10081 def Bar()
10082 var i = 20
10083 xxx
10084 enddef
10085 endclass
10086 defcompile
10087 END
10088 v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
10089
10090 # defcompile a specific class
10091 lines =<< trim END
10092 vim9script
10093 class A
10094 def Foo()
10095 xxx
10096 enddef
10097 endclass
10098 class B
10099 def Bar()
10100 yyy
10101 enddef
10102 endclass
10103 defcompile B
10104 END
10105 v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
10106
10107 # defcompile a non-class
10108 lines =<< trim END
10109 vim9script
10110 class A
10111 def Foo()
10112 enddef
10113 endclass
10114 var X: list<number> = []
10115 defcompile X
10116 END
10117 v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
10118
10119 # defcompile a class twice
10120 lines =<< trim END
10121 vim9script
10122 class A
10123 def new()
10124 enddef
10125 endclass
10126 defcompile A
10127 defcompile A
10128 assert_equal('Function A.new does not need compiling', v:statusmsg)
10129 END
10130 v9.CheckSourceSuccess(lines)
10131
10132 # defcompile should not compile an imported class
10133 lines =<< trim END
10134 vim9script
10135 export class A
10136 def Foo()
10137 xxx
10138 enddef
10139 endclass
10140 END
10141 writefile(lines, 'Xdefcompileimport.vim', 'D')
10142 lines =<< trim END
10143 vim9script
10144
10145 import './Xdefcompileimport.vim'
10146 class B
10147 endclass
10148 defcompile
10149 END
10150 v9.CheckScriptSuccess(lines)
10151enddef
10152
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +010010153" Test for cases common to all the object builtin methods
10154def Test_object_builtin_method()
10155 var lines =<< trim END
10156 vim9script
10157 class A
10158 def abc()
10159 enddef
10160 endclass
10161 END
10162 v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
10163
10164 for funcname in ["len", "string", "empty"]
10165 lines =<< trim eval END
10166 vim9script
10167 class A
10168 static def {funcname}(): number
10169 enddef
10170 endclass
10171 END
10172 v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
10173 endfor
10174enddef
10175
10176" Test for using the empty() builtin method with an object
10177" This is a legacy function to use the test_garbagecollect_now() function.
10178func Test_object_empty()
10179 let lines =<< trim END
10180 vim9script
10181 class A
10182 def empty(): bool
10183 return true
10184 enddef
10185 endclass
10186
10187 def Foo()
10188 var afoo = A.new()
10189 assert_equal(true, empty(afoo))
10190 assert_equal(true, afoo->empty())
10191 enddef
10192
10193 var a = A.new()
10194 assert_equal(1, empty(a))
10195 assert_equal(1, a->empty())
10196 test_garbagecollect_now()
10197 assert_equal(1, empty(a))
10198 Foo()
10199 test_garbagecollect_now()
10200 Foo()
10201 END
10202 call v9.CheckSourceSuccess(lines)
10203
10204 " empty() should return 1 without a builtin method
10205 let lines =<< trim END
10206 vim9script
10207 class A
10208 endclass
10209
10210 def Foo()
10211 var afoo = A.new()
10212 assert_equal(1, empty(afoo))
10213 enddef
10214
10215 var a = A.new()
10216 assert_equal(1, empty(a))
10217 Foo()
10218 END
10219 call v9.CheckSourceSuccess(lines)
10220
10221 " Unsupported signature for the empty() method
10222 let lines =<< trim END
10223 vim9script
10224 class A
10225 def empty()
10226 enddef
10227 endclass
10228 END
10229 call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
10230
10231 " Error when calling the empty() method
10232 let lines =<< trim END
10233 vim9script
10234 class A
10235 def empty(): bool
10236 throw "Failed to check emptiness"
10237 enddef
10238 endclass
10239
10240 def Foo()
10241 var afoo = A.new()
10242 var i = empty(afoo)
10243 enddef
10244
10245 var a = A.new()
10246 assert_fails('empty(a)', 'Failed to check emptiness')
10247 assert_fails('Foo()', 'Failed to check emptiness')
10248 END
10249 call v9.CheckSourceSuccess(lines)
10250
10251 " call empty() using an object from a script
10252 let lines =<< trim END
10253 vim9script
10254 class A
10255 def empty(): bool
10256 return true
10257 enddef
10258 endclass
10259 var afoo = A.new()
10260 assert_equal(true, afoo.empty())
10261 END
10262 call v9.CheckSourceSuccess(lines)
10263
10264 " call empty() using an object from a method
10265 let lines =<< trim END
10266 vim9script
10267 class A
10268 def empty(): bool
10269 return true
10270 enddef
10271 endclass
10272 def Foo()
10273 var afoo = A.new()
10274 assert_equal(true, afoo.empty())
10275 enddef
10276 Foo()
10277 END
10278 call v9.CheckSourceSuccess(lines)
10279
10280 " call empty() using "this" from an object method
10281 let lines =<< trim END
10282 vim9script
10283 class A
10284 def empty(): bool
10285 return true
10286 enddef
10287 def Foo(): bool
10288 return this.empty()
10289 enddef
10290 endclass
10291 def Bar()
10292 var abar = A.new()
10293 assert_equal(true, abar.Foo())
10294 enddef
10295 Bar()
10296 END
10297 call v9.CheckSourceSuccess(lines)
10298
10299 " Call empty() from a derived object
10300 let lines =<< trim END
10301 vim9script
10302 class A
10303 def empty(): bool
10304 return false
10305 enddef
10306 endclass
10307 class B extends A
10308 def empty(): bool
10309 return true
10310 enddef
10311 endclass
10312 def Foo(afoo: A)
10313 assert_equal(true, empty(afoo))
10314 var bfoo = B.new()
10315 assert_equal(true, empty(bfoo))
10316 enddef
10317 var b = B.new()
10318 assert_equal(1, empty(b))
10319 Foo(b)
10320 END
10321 call v9.CheckSourceSuccess(lines)
10322
10323 " Invoking empty method using an interface
10324 let lines =<< trim END
10325 vim9script
10326 interface A
10327 def empty(): bool
10328 endinterface
10329 class B implements A
10330 def empty(): bool
10331 return false
10332 enddef
10333 endclass
10334 def Foo(a: A)
10335 assert_equal(false, empty(a))
10336 enddef
10337 var b = B.new()
10338 Foo(b)
10339 END
10340 call v9.CheckSourceSuccess(lines)
10341endfunc
10342
10343" Test for using the len() builtin method with an object
10344" This is a legacy function to use the test_garbagecollect_now() function.
10345func Test_object_length()
10346 let lines =<< trim END
10347 vim9script
10348 class A
10349 var mylen: number = 0
10350 def new(n: number)
10351 this.mylen = n
10352 enddef
10353 def len(): number
10354 return this.mylen
10355 enddef
10356 endclass
10357
10358 def Foo()
10359 var afoo = A.new(12)
10360 assert_equal(12, len(afoo))
10361 assert_equal(12, afoo->len())
10362 enddef
10363
10364 var a = A.new(22)
10365 assert_equal(22, len(a))
10366 assert_equal(22, a->len())
10367 test_garbagecollect_now()
10368 assert_equal(22, len(a))
10369 Foo()
10370 test_garbagecollect_now()
10371 Foo()
10372 END
10373 call v9.CheckSourceSuccess(lines)
10374
10375 " len() should return 0 without a builtin method
10376 let lines =<< trim END
10377 vim9script
10378 class A
10379 endclass
10380
10381 def Foo()
10382 var afoo = A.new()
10383 assert_equal(0, len(afoo))
10384 enddef
10385
10386 var a = A.new()
10387 assert_equal(0, len(a))
10388 Foo()
10389 END
10390 call v9.CheckSourceSuccess(lines)
10391
10392 " Unsupported signature for the len() method
10393 let lines =<< trim END
10394 vim9script
10395 class A
10396 def len()
10397 enddef
10398 endclass
10399 END
10400 call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
10401
10402 " Error when calling the len() method
10403 let lines =<< trim END
10404 vim9script
10405 class A
10406 def len(): number
10407 throw "Failed to compute length"
10408 enddef
10409 endclass
10410
10411 def Foo()
10412 var afoo = A.new()
10413 var i = len(afoo)
10414 enddef
10415
10416 var a = A.new()
10417 assert_fails('len(a)', 'Failed to compute length')
10418 assert_fails('Foo()', 'Failed to compute length')
10419 END
10420 call v9.CheckSourceSuccess(lines)
10421
10422 " call len() using an object from a script
10423 let lines =<< trim END
10424 vim9script
10425 class A
10426 def len(): number
10427 return 5
10428 enddef
10429 endclass
10430 var afoo = A.new()
10431 assert_equal(5, afoo.len())
10432 END
10433 call v9.CheckSourceSuccess(lines)
10434
10435 " call len() using an object from a method
10436 let lines =<< trim END
10437 vim9script
10438 class A
10439 def len(): number
10440 return 5
10441 enddef
10442 endclass
10443 def Foo()
10444 var afoo = A.new()
10445 assert_equal(5, afoo.len())
10446 enddef
10447 Foo()
10448 END
10449 call v9.CheckSourceSuccess(lines)
10450
10451 " call len() using "this" from an object method
10452 let lines =<< trim END
10453 vim9script
10454 class A
10455 def len(): number
10456 return 8
10457 enddef
10458 def Foo(): number
10459 return this.len()
10460 enddef
10461 endclass
10462 def Bar()
10463 var abar = A.new()
10464 assert_equal(8, abar.Foo())
10465 enddef
10466 Bar()
10467 END
10468 call v9.CheckSourceSuccess(lines)
10469
10470 " Call len() from a derived object
10471 let lines =<< trim END
10472 vim9script
10473 class A
10474 def len(): number
10475 return 10
10476 enddef
10477 endclass
10478 class B extends A
10479 def len(): number
10480 return 20
10481 enddef
10482 endclass
10483 def Foo(afoo: A)
10484 assert_equal(20, len(afoo))
10485 var bfoo = B.new()
10486 assert_equal(20, len(bfoo))
10487 enddef
10488 var b = B.new()
10489 assert_equal(20, len(b))
10490 Foo(b)
10491 END
10492 call v9.CheckSourceSuccess(lines)
10493
10494 " Invoking len method using an interface
10495 let lines =<< trim END
10496 vim9script
10497 interface A
10498 def len(): number
10499 endinterface
10500 class B implements A
10501 def len(): number
10502 return 123
10503 enddef
10504 endclass
10505 def Foo(a: A)
10506 assert_equal(123, len(a))
10507 enddef
10508 var b = B.new()
10509 Foo(b)
10510 END
10511 call v9.CheckSourceSuccess(lines)
10512endfunc
10513
10514" Test for using the string() builtin method with an object
10515" This is a legacy function to use the test_garbagecollect_now() function.
10516func Test_object_string()
10517 let lines =<< trim END
10518 vim9script
10519 class A
10520 var name: string
10521 def string(): string
10522 return this.name
10523 enddef
10524 endclass
10525
10526 def Foo()
10527 var afoo = A.new("foo-A")
10528 assert_equal('foo-A', string(afoo))
10529 assert_equal('foo-A', afoo->string())
10530 enddef
10531
10532 var a = A.new("script-A")
10533 assert_equal('script-A', string(a))
10534 assert_equal('script-A', a->string())
10535 assert_equal(['script-A'], execute('echo a')->split("\n"))
10536 test_garbagecollect_now()
10537 assert_equal('script-A', string(a))
10538 Foo()
10539 test_garbagecollect_now()
10540 Foo()
10541 END
10542 call v9.CheckSourceSuccess(lines)
10543
10544 " string() should return "object of A {}" without a builtin method
10545 let lines =<< trim END
10546 vim9script
10547 class A
10548 endclass
10549
10550 def Foo()
10551 var afoo = A.new()
10552 assert_equal('object of A {}', string(afoo))
10553 enddef
10554
10555 var a = A.new()
10556 assert_equal('object of A {}', string(a))
10557 Foo()
10558 END
10559 call v9.CheckSourceSuccess(lines)
10560
10561 " Unsupported signature for the string() method
10562 let lines =<< trim END
10563 vim9script
10564 class A
10565 def string()
10566 enddef
10567 endclass
10568 END
10569 call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
10570
10571 " Error when calling the string() method
10572 let lines =<< trim END
10573 vim9script
10574 class A
10575 def string(): string
10576 throw "Failed to get text"
10577 enddef
10578 endclass
10579
10580 def Foo()
10581 var afoo = A.new()
10582 var i = string(afoo)
10583 enddef
10584
10585 var a = A.new()
10586 assert_fails('string(a)', 'Failed to get text')
10587 assert_fails('Foo()', 'Failed to get text')
10588 END
10589 call v9.CheckSourceSuccess(lines)
10590
10591 " call string() using an object from a script
10592 let lines =<< trim END
10593 vim9script
10594 class A
10595 def string(): string
10596 return 'A'
10597 enddef
10598 endclass
10599 var afoo = A.new()
10600 assert_equal('A', afoo.string())
10601 END
10602 call v9.CheckSourceSuccess(lines)
10603
10604 " call string() using an object from a method
10605 let lines =<< trim END
10606 vim9script
10607 class A
10608 def string(): string
10609 return 'A'
10610 enddef
10611 endclass
10612 def Foo()
10613 var afoo = A.new()
10614 assert_equal('A', afoo.string())
10615 enddef
10616 Foo()
10617 END
10618 call v9.CheckSourceSuccess(lines)
10619
10620 " call string() using "this" from an object method
10621 let lines =<< trim END
10622 vim9script
10623 class A
10624 def string(): string
10625 return 'A'
10626 enddef
10627 def Foo(): string
10628 return this.string()
10629 enddef
10630 endclass
10631 def Bar()
10632 var abar = A.new()
10633 assert_equal('A', abar.string())
10634 enddef
10635 Bar()
10636 END
10637 call v9.CheckSourceSuccess(lines)
10638
10639 " Call string() from a derived object
10640 let lines =<< trim END
10641 vim9script
10642 class A
10643 def string(): string
10644 return 'A'
10645 enddef
10646 endclass
10647 class B extends A
10648 def string(): string
10649 return 'B'
10650 enddef
10651 endclass
10652 def Foo(afoo: A)
10653 assert_equal('B', string(afoo))
10654 var bfoo = B.new()
10655 assert_equal('B', string(bfoo))
10656 enddef
10657 var b = B.new()
10658 assert_equal('B', string(b))
10659 Foo(b)
10660 END
10661 call v9.CheckSourceSuccess(lines)
10662
10663 " Invoking string method using an interface
10664 let lines =<< trim END
10665 vim9script
10666 interface A
10667 def string(): string
10668 endinterface
10669 class B implements A
10670 def string(): string
10671 return 'B'
10672 enddef
10673 endclass
10674 def Foo(a: A)
10675 assert_equal('B', string(a))
10676 enddef
10677 var b = B.new()
10678 Foo(b)
10679 END
10680 call v9.CheckSourceSuccess(lines)
10681endfunc
10682
Ernie Rael9d779c52024-07-07 20:41:44 +020010683" Test for using the string() builtin method with an object's method
10684def Test_method_string()
10685 var lines =<< trim END
10686 vim9script
10687 class A
10688 def F()
10689 enddef
10690 endclass
10691 assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F))
10692 END
10693 v9.CheckScriptSuccess(lines)
10694enddef
10695
10696
Yegappan Lakshmanan35b867b2024-03-09 15:44:19 +010010697" Test for using a class in the class definition
10698def Test_Ref_Class_Within_Same_Class()
10699 var lines =<< trim END
10700 vim9script
10701 class A
10702 var n: number = 0
10703 def Equals(other: A): bool
10704 return this.n == other.n
10705 enddef
10706 endclass
10707
10708 var a1 = A.new(10)
10709 var a2 = A.new(10)
10710 var a3 = A.new(20)
10711 assert_equal(true, a1.Equals(a2))
10712 assert_equal(false, a2.Equals(a3))
10713 END
10714 v9.CheckScriptSuccess(lines)
10715
10716 lines =<< trim END
10717 vim9script
10718
10719 class Foo
10720 var num: number
10721 def Clone(): Foo
10722 return Foo.new(this.num)
10723 enddef
10724 endclass
10725
10726 var f1 = Foo.new(1)
10727
10728 def F()
10729 var f2: Foo = f1.Clone()
10730 assert_equal(false, f2 is f1)
10731 assert_equal(true, f2.num == f1.num)
10732 enddef
10733 F()
10734
10735 var f3: Foo = f1.Clone()
10736 assert_equal(false, f3 is f1)
10737 assert_equal(true, f3.num == f1.num)
10738 END
10739 v9.CheckScriptSuccess(lines)
10740
10741 # Test for trying to use a class to extend when defining the same class
10742 lines =<< trim END
10743 vim9script
10744 class A extends A
10745 endclass
10746 END
10747 v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
10748
10749 # Test for trying to use a class to implement when defining the same class
10750 lines =<< trim END
10751 vim9script
10752 class A implements A
10753 endclass
10754 END
10755 v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
10756enddef
10757
Ernie Raelf0e69142024-06-22 11:12:00 +020010758" Test for comparing a class referencing itself
10759def Test_Object_Compare_With_Recursive_Class_Ref()
10760 var lines =<< trim END
10761 vim9script
10762
10763 class C
10764 public var nest: C
10765 endclass
10766
10767 var o1 = C.new()
10768 o1.nest = o1
10769
10770 var result = o1 == o1
10771 assert_equal(true, result)
10772 END
10773 v9.CheckScriptSuccess(lines)
Ernie Rael86257142024-06-23 09:54:45 +020010774
10775 lines =<< trim END
10776 vim9script
10777
10778 class C
10779 public var nest: C
10780 endclass
10781 var o1 = C.new()
10782 var o2 = C.new(C.new())
10783
10784 var result = o1 == o2
10785 assert_equal(false, result)
10786 END
10787 v9.CheckScriptSuccess(lines)
Ernie Rael05ff4e42024-07-04 16:50:11 +020010788
10789 lines =<< trim END
10790 vim9script
10791 class C
10792 var nest1: C
10793 var nest2: C
10794 def Init(n1: C, n2: C)
10795 this.nest1 = n1
10796 this.nest2 = n2
10797 enddef
10798 endclass
10799
10800 var o1 = C.new()
10801 var o2 = C.new()
10802 o1.Init(o1, o2)
10803 o2.Init(o2, o1)
10804
10805 var result = o1 == o2
10806 assert_equal(true, result)
10807 END
10808 v9.CheckScriptSuccess(lines)
Ernie Raelf0e69142024-06-22 11:12:00 +020010809enddef
10810
Ernie Raelf3975492024-07-06 11:44:37 +020010811" Test for comparing a class with nesting objects
10812def Test_Object_Compare_With_Nesting_Objects()
10813 # On a compare, after vim equal recurses 1000 times, not finding an unequal,
10814 # return the compare is equal.
10815 # Test that limit
10816
10817 var lines =<< trim END
10818 vim9script
10819 class C
10820 public var n: number
10821 public var nest: C
10822
10823 # Create a "C" that chains/nests to indicated depth.
10824 # return {head: firstC, tail: lastC}
10825 static def CreateNested(depth: number): dict<C>
10826 var first = C.new(1, null_object)
10827 var last = first
10828 for i in range(2, depth)
10829 last.nest = C.new(i, null_object)
10830 last = last.nest
10831 endfor
10832 return {head: first, tail: last}
10833 enddef
10834
10835 # Return pointer to nth item in chain.
10836 def GetLink(depth: number): C
10837 var count = 1
10838 var p: C = this
10839 while count < depth
10840 p = p.nest
10841 if p == null
10842 throw "too deep"
10843 endif
10844 count += 1
10845 endwhile
10846 return p
10847 enddef
10848
10849 # Return the length of the chain
10850 def len(): number
10851 var count = 1
10852 var p: C = this
10853 while p.nest != null
10854 p = p.nest
10855 count += 1
10856 endwhile
10857 return count
10858 enddef
10859 endclass
10860
10861 var chain = C.CreateNested(3)
10862 var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}"
10863 assert_equal(s, string(chain.head))
10864 assert_equal(3, chain.head->len())
10865
10866 var chain1 = C.CreateNested(100)
10867 var chain2 = C.CreateNested(100)
10868 assert_true(chain1.head == chain2.head)
10869
10870 # modify the tail of chain2, compare not equal
10871 chain2.tail.n = 123456
10872 assert_true(chain1.head != chain2.head)
10873
10874 # a tail of a different length compares not equal
10875 chain2 = C.CreateNested(101)
10876 assert_true(chain1.head != chain2.head)
10877
10878 chain1 = C.CreateNested(1000)
10879 chain2 = C.CreateNested(1000)
10880 assert_true(chain1.head == chain2.head)
10881
10882 # modify the tail of chain2, compare not equal
10883 chain2.tail.n = 123456
10884 assert_true(chain1.head != chain2.head)
10885
10886 # try a chain longer that the limit
10887 chain1 = C.CreateNested(1001)
10888 chain2 = C.CreateNested(1001)
10889 assert_true(chain1.head == chain2.head)
10890
10891 # modify the tail, but still equal
10892 chain2.tail.n = 123456
10893 assert_true(chain1.head == chain2.head)
10894
10895 # remove 2 items from front, shorten the chain by two.
10896 chain1.head = chain1.head.GetLink(3)
10897 chain2.head = chain2.head.GetLink(3)
10898 assert_equal(3, chain1.head.n)
10899 assert_equal(3, chain2.head.n)
10900 assert_equal(999, chain1.head->len())
10901 assert_equal(999, chain2.head->len())
10902 # Now less than the limit, compare not equal
10903 assert_true(chain1.head != chain2.head)
10904 END
10905 v9.CheckScriptSuccess(lines)
10906enddef
10907
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010010908" Test for using a compound operator from a lambda function in an object method
10909def Test_compound_op_in_objmethod_lambda()
10910 # Test using the "+=" operator
10911 var lines =<< trim END
10912 vim9script
10913 class A
10914 var n: number = 10
10915 def Foo()
10916 var Fn = () => {
10917 this.n += 1
10918 }
10919 Fn()
10920 enddef
10921 endclass
10922
10923 var a = A.new()
10924 a.Foo()
10925 assert_equal(11, a.n)
10926 END
10927 v9.CheckScriptSuccess(lines)
10928
10929 # Test using the "..=" operator
10930 lines =<< trim END
10931 vim9script
10932 class A
10933 var s: string = "a"
10934 def Foo()
10935 var Fn = () => {
10936 this.s ..= "a"
10937 }
10938 Fn()
10939 enddef
10940 endclass
10941
10942 var a = A.new()
10943 a.Foo()
10944 a.Foo()
10945 assert_equal("aaa", a.s)
10946 END
10947 v9.CheckScriptSuccess(lines)
10948enddef
10949
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010010950" Test for using test_refcount() with a class and an object
10951def Test_class_object_refcount()
10952 var lines =<< trim END
10953 vim9script
10954 class A
10955 endclass
10956 var a: A = A.new()
10957 assert_equal(2, test_refcount(A))
10958 assert_equal(1, test_refcount(a))
10959 var b = a
10960 assert_equal(2, test_refcount(A))
10961 assert_equal(2, test_refcount(a))
10962 assert_equal(2, test_refcount(b))
10963 END
10964 v9.CheckScriptSuccess(lines)
10965enddef
10966
Yegappan Lakshmanand990bf02024-03-22 19:56:17 +010010967" call a lambda function in one object from another object
10968def Test_lambda_invocation_across_classes()
10969 var lines =<< trim END
10970 vim9script
10971 class A
10972 var s: string = "foo"
10973 def GetFn(): func
10974 var Fn = (): string => {
10975 return this.s
10976 }
10977 return Fn
10978 enddef
10979 endclass
10980
10981 class B
10982 var s: string = "bar"
10983 def GetFn(): func
10984 var a = A.new()
10985 return a.GetFn()
10986 enddef
10987 endclass
10988
10989 var b = B.new()
10990 var Fn = b.GetFn()
10991 assert_equal("foo", Fn())
10992 END
10993 v9.CheckScriptSuccess(lines)
10994enddef
10995
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +010010996" Test for using a class member which is an object of the current class
10997def Test_current_class_object_class_member()
10998 var lines =<< trim END
10999 vim9script
11000 class A
11001 public static var obj1: A = A.new(10)
11002 var n: number
11003 endclass
11004 defcompile
11005 assert_equal(10, A.obj1.n)
11006 END
11007 v9.CheckScriptSuccess(lines)
11008enddef
11009
Yegappan Lakshmanan2ed5a112024-04-01 14:50:41 +020011010" Test for updating a base class variable from a base class method without the
11011" class name. This used to crash Vim (Github issue #14352).
11012def Test_use_base_class_variable_from_base_class_method()
11013 var lines =<< trim END
11014 vim9script
11015
11016 class DictKeyClass
11017 static var _obj_id_count = 1
11018 def _GenerateKey()
11019 _obj_id_count += 1
11020 enddef
11021 static def GetIdCount(): number
11022 return _obj_id_count
11023 enddef
11024 endclass
11025
11026 class C extends DictKeyClass
11027 def F()
11028 this._GenerateKey()
11029 enddef
11030 endclass
11031
11032 C.new().F()
11033 assert_equal(2, DictKeyClass.GetIdCount())
11034 END
11035 v9.CheckScriptSuccess(lines)
11036enddef
11037
Yegappan Lakshmanan3e336502024-04-04 19:35:59 +020011038" Test for accessing protected funcref object and class variables
11039def Test_protected_funcref()
11040 # protected funcref object variable
11041 var lines =<< trim END
11042 vim9script
11043 class Test1
11044 const _Id: func(any): any = (v) => v
11045 endclass
11046 var n = Test1.new()._Id(1)
11047 END
11048 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
11049
11050 # protected funcref class variable
11051 lines =<< trim END
11052 vim9script
11053 class Test2
11054 static const _Id: func(any): any = (v) => v
11055 endclass
11056 var n = Test2._Id(2)
11057 END
11058 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
11059enddef
11060
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +020011061" Test for using lambda block in classes
11062def Test_lambda_block_in_class()
11063 # This used to crash Vim
11064 var lines =<< trim END
11065 vim9script
11066 class IdClass1
11067 const Id: func(number): number = (num: number): number => {
11068 # Return a ID
11069 return num * 10
11070 }
11071 endclass
11072 var id = IdClass1.new()
11073 assert_equal(20, id.Id(2))
11074 END
11075 v9.CheckScriptSuccess(lines)
11076
11077 # This used to crash Vim
11078 lines =<< trim END
11079 vim9script
11080 class IdClass2
11081 static const Id: func(number): number = (num: number): number => {
11082 # Return a ID
11083 return num * 2
11084 }
11085 endclass
11086 assert_equal(16, IdClass2.Id(8))
11087 END
11088 v9.CheckScriptSuccess(lines)
11089enddef
11090
Yegappan Lakshmanan1af0fbf2024-04-09 21:39:27 +020011091" Test for defcompiling an abstract method
11092def Test_abstract_method_defcompile()
11093 # Compile an abstract class with abstract object methods
11094 var lines =<< trim END
11095 vim9script
11096 abstract class A
11097 abstract def Foo(): string
11098 abstract def Bar(): list<string>
11099 endclass
11100 defcompile
11101 END
11102 v9.CheckScriptSuccess(lines)
11103
11104 # Compile a concrete object method in an abstract class
11105 lines =<< trim END
11106 vim9script
11107 abstract class A
11108 abstract def Foo(): string
11109 abstract def Bar(): list<string>
11110 def Baz(): string
11111 pass
11112 enddef
11113 endclass
11114 defcompile
11115 END
11116 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11117
11118 # Compile a concrete class method in an abstract class
11119 lines =<< trim END
11120 vim9script
11121 abstract class A
11122 abstract def Foo(): string
11123 abstract def Bar(): list<string>
11124 static def Baz(): string
11125 pass
11126 enddef
11127 endclass
11128 defcompile
11129 END
11130 v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1)
11131enddef
11132
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +020011133" Test for defining a class in a function
11134def Test_class_definition_in_a_function()
11135 var lines =<< trim END
11136 vim9script
11137 def Foo()
11138 class A
11139 endclass
11140 enddef
11141 defcompile
11142 END
11143 v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
11144enddef
11145
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +020011146" Test for using [] with a class and an object
11147def Test_class_object_index()
11148 var lines =<< trim END
11149 vim9script
11150 class A
11151 endclass
11152 A[10] = 1
11153 END
11154 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
11155
11156 lines =<< trim END
11157 vim9script
11158 class A
11159 endclass
11160 var a = A.new()
11161 a[10] = 1
11162 END
11163 v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
11164enddef
11165
LemonBoyf4af3312024-07-04 13:43:12 +020011166def Test_class_member_init_typecheck()
11167 # Ensure the class member is assigned its declared type.
11168 var lines =<< trim END
11169 vim9script
11170 class S
11171 static var l: list<string> = []
11172 endclass
11173 S.l->add(123)
11174 END
11175 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
11176
11177 # Ensure the initializer value and the declared type match.
11178 lines =<< trim END
11179 vim9script
11180 class S
11181 var l: list<string> = [1, 2, 3]
11182 endclass
11183 var o = S.new()
11184 END
11185 v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>')
11186
11187 # Ensure the class member is assigned its declared type.
11188 lines =<< trim END
11189 vim9script
11190 class S
11191 var l: list<string> = []
11192 endclass
11193 var o = S.new()
11194 o.l->add(123)
11195 END
11196 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6)
11197enddef
11198
LemonBoy50d48542024-07-04 17:03:17 +020011199def Test_class_cast()
11200 var lines =<< trim END
11201 vim9script
11202 class A
11203 endclass
11204 class B extends A
11205 var mylen: number
11206 endclass
11207 def F(o: A): number
11208 return (<B>o).mylen
11209 enddef
11210
11211 defcompile F
11212 END
11213 v9.CheckScriptSuccess(lines)
11214enddef
11215
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +010011216" Test for using a variable of type "any" with an object
11217def Test_any_obj_var_type()
11218 var lines =<< trim END
11219 vim9script
11220 class A
11221 var name: string = "foobar"
11222 def Foo(): string
11223 return "func foo"
11224 enddef
11225 endclass
11226
11227 def CheckVals(x: any)
11228 assert_equal("foobar", x.name)
11229 assert_equal("func foo", x.Foo())
11230 enddef
11231
11232 var a = A.new()
11233 CheckVals(a)
11234 END
11235 v9.CheckScriptSuccess(lines)
11236
11237 # Try to set a non-existing variable
11238 lines =<< trim END
11239 vim9script
11240 class A
11241 var name: string = "foobar"
11242 endclass
11243
11244 def SetNonExistingVar(x: any)
11245 x.bar = [1, 2, 3]
11246 enddef
11247
11248 var a = A.new()
11249 SetNonExistingVar(a)
11250 END
11251 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11252
11253 # Try to read a non-existing variable
11254 lines =<< trim END
11255 vim9script
11256 class A
11257 var name: string = "foobar"
11258 endclass
11259
11260 def GetNonExistingVar(x: any)
11261 var i: dict<any> = x.bar
11262 enddef
11263
11264 var a = A.new()
11265 GetNonExistingVar(a)
11266 END
11267 v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
11268
11269 # Try to invoke a non-existing method
11270 lines =<< trim END
11271 vim9script
11272 class A
11273 def Foo(): number
11274 return 10
11275 enddef
11276 endclass
11277
11278 def CallNonExistingMethod(x: any)
11279 var i: number = x.Bar()
11280 enddef
11281
11282 var a = A.new()
11283 CallNonExistingMethod(a)
11284 END
11285 v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
11286
11287 # Use an object which is a Dict value
11288 lines =<< trim END
11289 vim9script
11290 class Foo
11291 def Bar(): number
11292 return 369
11293 enddef
11294 endclass
11295
11296 def GetValue(FooDict: dict<any>): number
11297 var n: number = 0
11298 for foo in values(FooDict)
11299 n += foo.Bar()
11300 endfor
11301 return n
11302 enddef
11303
11304 var d = {'x': Foo.new()}
11305 assert_equal(369, GetValue(d))
11306 END
11307 v9.CheckScriptSuccess(lines)
11308
11309 # Nested data. Object containg a Dict containing another Object.
11310 lines =<< trim END
11311 vim9script
11312 class Context
11313 public var state: dict<any> = {}
11314 endclass
11315
11316 class Metadata
11317 public var value = 0
11318 endclass
11319
11320 var ctx = Context.new()
11321 ctx.state["meta"] = Metadata.new(2468)
11322
11323 const foo = ctx.state.meta.value
11324
11325 def F(): number
11326 const bar = ctx.state.meta.value
11327 return bar
11328 enddef
11329
11330 assert_equal(2468, F())
11331 END
11332 v9.CheckScriptSuccess(lines)
11333
11334 # Accessing an object from a method inside the class using any type
11335 lines =<< trim END
11336 vim9script
11337 class C
11338 def _G(): string
11339 return '_G'
11340 enddef
11341 static def S(o_any: any): string
11342 return o_any._G()
11343 enddef
11344 endclass
11345
11346 var o1 = C.new()
11347 assert_equal('_G', C.S(o1))
11348 END
11349 v9.CheckScriptSuccess(lines)
11350
11351 # Modifying an object private variable from a method in another class using
11352 # any type
11353 lines =<< trim END
11354 vim9script
11355
11356 class A
11357 var num = 10
11358 endclass
11359
11360 class B
11361 def SetVal(x: any)
11362 x.num = 20
11363 enddef
11364 endclass
11365
11366 var a = A.new()
11367 var b = B.new()
11368 b.SetVal(a)
11369 END
11370 v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
11371
11372 # Accessing a object protected variable from a method in another class using
11373 # any type
11374 lines =<< trim END
11375 vim9script
11376
11377 class A
11378 var _num = 10
11379 endclass
11380
11381 class B
11382 def GetVal(x: any): number
11383 return x._num
11384 enddef
11385 endclass
11386
11387 var a = A.new()
11388 var b = B.new()
11389 var i = b.GetVal(a)
11390 END
11391 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
11392
11393 # Accessing an object returned from an imported function and class
11394 lines =<< trim END
11395 vim9script
11396 export class Foo
11397 public var name: string
11398 endclass
11399
11400 export def ReturnFooObject(): Foo
11401 var r = Foo.new('star')
11402 return r
11403 enddef
11404 END
11405 writefile(lines, 'Xanyvar1.vim', 'D')
11406
11407 lines =<< trim END
11408 vim9script
11409
11410 import './Xanyvar1.vim'
11411
11412 def GetName(): string
11413 var whatever = Xanyvar1.ReturnFooObject()
11414 return whatever.name
11415 enddef
11416
11417 assert_equal('star', GetName())
11418 END
11419 v9.CheckScriptSuccess(lines)
11420
11421 # Try to modify a private object variable using a variable of type "any"
11422 lines =<< trim END
11423 vim9script
11424
11425 class Foo
11426 var n: number = 10
11427 endclass
11428 def Fn(x: any)
11429 x.n = 20
11430 enddef
11431 var a = Foo.new()
11432 Fn(a)
11433 END
11434 v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
11435
11436 # Try to read a protected object variable using a variable of type "any"
11437 lines =<< trim END
11438 vim9script
11439
11440 class Foo
11441 var _n: number = 10
11442 endclass
11443 def Fn(x: any): number
11444 return x._n
11445 enddef
11446
11447 var a = Foo.new()
11448 Fn(a)
11449 END
11450 v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
11451
11452 # Read a protected object variable using a variable of type "any" in an object
11453 # method
11454 lines =<< trim END
11455 vim9script
11456
11457 class Foo
11458 var _n: number = 10
11459 def Fn(x: any): number
11460 return x._n
11461 enddef
11462 endclass
11463
11464 var a = Foo.new()
11465 assert_equal(10, a.Fn(a))
11466 END
11467 v9.CheckScriptSuccess(lines)
11468
11469 # Try to call a protected object method using a "any" type variable
11470 lines =<< trim END
11471 vim9script
11472
11473 class Foo
11474 def _GetVal(): number
11475 return 234
11476 enddef
11477 endclass
11478 def Fn(x: any): number
11479 return x._GetVal()
11480 enddef
11481
11482 var a = Foo.new()
11483 Fn(a)
11484 END
11485 v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
11486
11487 # Call a protected object method using a "any" type variable from another
11488 # object method
11489 lines =<< trim END
11490 vim9script
11491
11492 class Foo
11493 def _GetVal(): number
11494 return 234
11495 enddef
11496 def FooVal(x: any): number
11497 return x._GetVal()
11498 enddef
11499 endclass
11500
11501 var a = Foo.new()
11502 assert_equal(234, a.FooVal(a))
11503 END
11504 v9.CheckScriptSuccess(lines)
11505
11506 # Method chaining
11507 lines =<< trim END
11508 vim9script
11509
11510 export class T
11511 var id: number = 268
11512 def F(): any
11513 return this
11514 enddef
11515 endclass
11516
11517 def H()
11518 var a = T.new().F().F()
11519 assert_equal(268, a.id)
11520 enddef
11521 H()
11522
11523 var b: T = T.new().F().F()
11524 assert_equal(268, b.id)
11525 END
11526 v9.CheckScriptSuccess(lines)
11527
11528 # Using a null object to access a member variable
11529 lines =<< trim END
11530 vim9script
11531 def Fn(x: any): number
11532 return x.num
11533 enddef
11534
11535 Fn(null_object)
11536 END
11537 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11538
11539 # Using a null object to invoke a method
11540 lines =<< trim END
11541 vim9script
11542 def Fn(x: any)
11543 x.Foo()
11544 enddef
11545
11546 Fn(null_object)
11547 END
11548 v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
11549enddef
11550
Bram Moolenaar00b28d62022-12-08 15:32:33 +000011551" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker