Mercurial > vim
comparison src/testdir/test_vim9_class.vim @ 32854:5fd9fe58c791 v9.0.1737
patch 9.0.1737: Calling a base class method through an extended class fails
Commit: https://github.com/vim/vim/commit/b102728c204430b16a5d9e6720c882e12a687570
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Sat Aug 19 11:26:42 2023 +0200
patch 9.0.1737: Calling a base class method through an extended class fails
Problem: Calling a base class method through an extended class fails
Solution: Create lookup table for member index in the interface to
to the member class implementing the interface
Create additional tests for Vim9 classes. Fix unconvered memory leaks
and crashes found by the new tests.
closes: #12848
closes: #12089
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>author
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 19 Aug 2023 11:45:03 +0200 |
parents | b3a42579bb3f |
children | a39314fa9495 |
comparison
equal
deleted
inserted
replaced
32853:1061521240a3 | 32854:5fd9fe58c791 |
---|---|
132 class Something | 132 class Something |
133 this.count:number | 133 this.count:number |
134 endclass | 134 endclass |
135 END | 135 END |
136 v9.CheckScriptFailure(lines, 'E1069:') | 136 v9.CheckScriptFailure(lines, 'E1069:') |
137 | |
138 # Test for unsupported comment specifier | |
139 lines =<< trim END | |
140 vim9script | |
141 class Something | |
142 # comment | |
143 #{ | |
144 endclass | |
145 END | |
146 v9.CheckScriptFailure(lines, 'E1170:') | |
137 | 147 |
138 lines =<< trim END | 148 lines =<< trim END |
139 vim9script | 149 vim9script |
140 | 150 |
141 class TextPosition | 151 class TextPosition |
160 assert_equal(v:t_object, type(pos)) | 170 assert_equal(v:t_object, type(pos)) |
161 assert_equal('class<TextPosition>', typename(TextPosition)) | 171 assert_equal('class<TextPosition>', typename(TextPosition)) |
162 assert_equal('object<TextPosition>', typename(pos)) | 172 assert_equal('object<TextPosition>', typename(pos)) |
163 END | 173 END |
164 v9.CheckScriptSuccess(lines) | 174 v9.CheckScriptSuccess(lines) |
175 | |
176 # When referencing object methods, space cannot be used after a "." | |
177 lines =<< trim END | |
178 vim9script | |
179 class A | |
180 def Foo(): number | |
181 return 10 | |
182 enddef | |
183 endclass | |
184 var a = A.new() | |
185 var v = a. Foo() | |
186 END | |
187 v9.CheckScriptFailure(lines, 'E1202:') | |
188 | |
189 # Using an object without specifying a method or a member variable | |
190 lines =<< trim END | |
191 vim9script | |
192 class A | |
193 def Foo(): number | |
194 return 10 | |
195 enddef | |
196 endclass | |
197 var a = A.new() | |
198 var v = a. | |
199 END | |
200 v9.CheckScriptFailure(lines, 'E15:') | |
201 | |
202 # Error when parsing the arguments of an object method. | |
203 lines =<< trim END | |
204 vim9script | |
205 class A | |
206 def Foo() | |
207 enddef | |
208 endclass | |
209 var a = A.new() | |
210 var v = a.Foo(,) | |
211 END | |
212 v9.CheckScriptFailure(lines, 'E15:') | |
165 enddef | 213 enddef |
166 | 214 |
167 def Test_class_defined_twice() | 215 def Test_class_defined_twice() |
168 # class defined twice should fail | 216 # class defined twice should fail |
169 var lines =<< trim END | 217 var lines =<< trim END |
626 this.lnum = v:none | 674 this.lnum = v:none |
627 this.col = 1 | 675 this.col = 1 |
628 endclass | 676 endclass |
629 END | 677 END |
630 v9.CheckScriptFailure(lines, 'E1330:') | 678 v9.CheckScriptFailure(lines, 'E1330:') |
679 | |
680 # Test for initializing an object member with an unknown variable/type | |
681 lines =<< trim END | |
682 vim9script | |
683 class A | |
684 this.value = init_val | |
685 endclass | |
686 END | |
687 v9.CheckScriptFailureList(lines, ['E121:', 'E1329:']) | |
631 enddef | 688 enddef |
632 | 689 |
633 def Test_class_object_member_access() | 690 def Test_class_object_member_access() |
634 var lines =<< trim END | 691 var lines =<< trim END |
635 vim9script | 692 vim9script |
655 assert_equal(33, trip.three) | 712 assert_equal(33, trip.three) |
656 | 713 |
657 assert_fails('trip.four = 4', 'E1334') | 714 assert_fails('trip.four = 4', 'E1334') |
658 END | 715 END |
659 v9.CheckScriptSuccess(lines) | 716 v9.CheckScriptSuccess(lines) |
717 | |
718 # Test for a public member variable name beginning with an underscore | |
719 lines =<< trim END | |
720 vim9script | |
721 class A | |
722 public this._val = 10 | |
723 endclass | |
724 END | |
725 v9.CheckScriptFailure(lines, 'E1332:') | |
660 | 726 |
661 lines =<< trim END | 727 lines =<< trim END |
662 vim9script | 728 vim9script |
663 | 729 |
664 class MyCar | 730 class MyCar |
733 .Add(1) | 799 .Add(1) |
734 .Add(2) | 800 .Add(2) |
735 .x | 801 .x |
736 END | 802 END |
737 v9.CheckScriptSuccess(lines) | 803 v9.CheckScriptSuccess(lines) |
804 | |
805 # Test for "public" cannot be abbreviated | |
806 lines =<< trim END | |
807 vim9script | |
808 class Something | |
809 pub this.val = 1 | |
810 endclass | |
811 END | |
812 v9.CheckScriptFailure(lines, 'E1065:') | |
813 | |
814 # Test for "public" keyword must be followed by "this" or "static". | |
815 lines =<< trim END | |
816 vim9script | |
817 class Something | |
818 public val = 1 | |
819 endclass | |
820 END | |
821 v9.CheckScriptFailure(lines, 'E1331:') | |
822 | |
823 # Test for "static" cannot be abbreviated | |
824 lines =<< trim END | |
825 vim9script | |
826 class Something | |
827 stat this.val = 1 | |
828 endclass | |
829 END | |
830 v9.CheckScriptFailure(lines, 'E1065:') | |
738 enddef | 831 enddef |
739 | 832 |
740 def Test_class_object_compare() | 833 def Test_class_object_compare() |
741 var class_lines =<< trim END | 834 var class_lines =<< trim END |
742 vim9script | 835 vim9script |
1000 | 1093 |
1001 var s = Some.new() | 1094 var s = Some.new() |
1002 s.Method(7) | 1095 s.Method(7) |
1003 END | 1096 END |
1004 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count') | 1097 v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count') |
1098 | |
1099 # Test for using an invalid type for a member variable | |
1100 lines =<< trim END | |
1101 vim9script | |
1102 class A | |
1103 this.val: xxx | |
1104 endclass | |
1105 END | |
1106 v9.CheckScriptFailure(lines, 'E1010:') | |
1107 | |
1108 # Test for no space before or after the '=' when initializing a member | |
1109 # variable | |
1110 lines =<< trim END | |
1111 vim9script | |
1112 class A | |
1113 this.val: number= 10 | |
1114 endclass | |
1115 END | |
1116 v9.CheckScriptFailure(lines, 'E1004:') | |
1117 lines =<< trim END | |
1118 vim9script | |
1119 class A | |
1120 this.val: number =10 | |
1121 endclass | |
1122 END | |
1123 v9.CheckScriptFailure(lines, 'E1004:') | |
1124 | |
1125 # Access a non-existing member | |
1126 lines =<< trim END | |
1127 vim9script | |
1128 class A | |
1129 endclass | |
1130 var a = A.new() | |
1131 var v = a.bar | |
1132 END | |
1133 v9.CheckScriptFailure(lines, 'E1326:') | |
1005 enddef | 1134 enddef |
1006 | 1135 |
1007 func Test_class_garbagecollect() | 1136 func Test_class_garbagecollect() |
1008 let lines =<< trim END | 1137 let lines =<< trim END |
1009 vim9script | 1138 vim9script |
1070 assert_equal(1, Value.GetCount()) | 1199 assert_equal(1, Value.GetCount()) |
1071 var v2 = Value.new(7) | 1200 var v2 = Value.new(7) |
1072 assert_equal(2, Value.GetCount()) | 1201 assert_equal(2, Value.GetCount()) |
1073 END | 1202 END |
1074 v9.CheckScriptSuccess(lines) | 1203 v9.CheckScriptSuccess(lines) |
1204 | |
1205 # Test for cleaning up after a class definition failure when using class | |
1206 # functions. | |
1207 lines =<< trim END | |
1208 vim9script | |
1209 class A | |
1210 static def Foo() | |
1211 enddef | |
1212 aaa | |
1213 endclass | |
1214 END | |
1215 v9.CheckScriptFailure(lines, 'E1318:') | |
1075 enddef | 1216 enddef |
1076 | 1217 |
1077 def Test_class_defcompile() | 1218 def Test_class_defcompile() |
1078 var lines =<< trim END | 1219 var lines =<< trim END |
1079 vim9script | 1220 vim9script |
1098 endclass | 1239 endclass |
1099 | 1240 |
1100 defcompile C.Fc | 1241 defcompile C.Fc |
1101 END | 1242 END |
1102 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string') | 1243 v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string') |
1244 | |
1245 # Trying to compile a function using a non-existing class variable | |
1246 lines =<< trim END | |
1247 vim9script | |
1248 defcompile x.Foo() | |
1249 END | |
1250 v9.CheckScriptFailure(lines, 'E475:') | |
1251 | |
1252 # Trying to compile a function using a variable which is not a class | |
1253 lines =<< trim END | |
1254 vim9script | |
1255 var x: number | |
1256 defcompile x.Foo() | |
1257 END | |
1258 v9.CheckScriptFailure(lines, 'E475:') | |
1259 | |
1260 # Trying to compile a function without specifying the name | |
1261 lines =<< trim END | |
1262 vim9script | |
1263 class A | |
1264 endclass | |
1265 defcompile A. | |
1266 END | |
1267 v9.CheckScriptFailure(lines, 'E475:') | |
1268 | |
1269 # Trying to compile a non-existing class object member function | |
1270 lines =<< trim END | |
1271 vim9script | |
1272 class A | |
1273 endclass | |
1274 var a = A.new() | |
1275 defcompile a.Foo() | |
1276 END | |
1277 v9.CheckScriptFailureList(lines, ['E1334:', 'E475:']) | |
1103 enddef | 1278 enddef |
1104 | 1279 |
1105 def Test_class_object_to_string() | 1280 def Test_class_object_to_string() |
1106 var lines =<< trim END | 1281 var lines =<< trim END |
1107 vim9script | 1282 vim9script |
1343 enddef | 1518 enddef |
1344 | 1519 |
1345 Test() | 1520 Test() |
1346 END | 1521 END |
1347 v9.CheckScriptSuccess(lines) | 1522 v9.CheckScriptSuccess(lines) |
1523 | |
1524 # Interface name after "extends" doesn't end in a space or NUL character | |
1525 lines =<< trim END | |
1526 vim9script | |
1527 interface A | |
1528 endinterface | |
1529 class B extends A" | |
1530 endclass | |
1531 END | |
1532 v9.CheckScriptFailure(lines, 'E1315:') | |
1533 | |
1534 # Trailing characters after a class name | |
1535 lines =<< trim END | |
1536 vim9script | |
1537 class A bbb | |
1538 endclass | |
1539 END | |
1540 v9.CheckScriptFailure(lines, 'E488:') | |
1541 | |
1542 # using "implements" with a non-existing class | |
1543 lines =<< trim END | |
1544 vim9script | |
1545 class A implements B | |
1546 endclass | |
1547 END | |
1548 v9.CheckScriptFailure(lines, 'E1346:') | |
1549 | |
1550 # using "implements" with a regular class | |
1551 lines =<< trim END | |
1552 vim9script | |
1553 class A | |
1554 endclass | |
1555 class B implements A | |
1556 endclass | |
1557 END | |
1558 v9.CheckScriptFailure(lines, 'E1347:') | |
1559 | |
1560 # using "implements" with a variable | |
1561 lines =<< trim END | |
1562 vim9script | |
1563 var T: number = 10 | |
1564 class A implements T | |
1565 endclass | |
1566 END | |
1567 v9.CheckScriptFailure(lines, 'E1347:') | |
1568 | |
1569 # all the class methods in an "interface" should be implemented | |
1570 lines =<< trim END | |
1571 vim9script | |
1572 interface A | |
1573 static def Foo() | |
1574 endinterface | |
1575 class B implements A | |
1576 endclass | |
1577 END | |
1578 v9.CheckScriptFailure(lines, 'E1349:') | |
1348 enddef | 1579 enddef |
1349 | 1580 |
1350 def Test_call_interface_method() | 1581 def Test_call_interface_method() |
1351 var lines =<< trim END | 1582 var lines =<< trim END |
1352 vim9script | 1583 vim9script |
1715 | 1946 |
1716 var v = Success.new('asdf') | 1947 var v = Success.new('asdf') |
1717 assert_equal("object of Success {success: true, value: 'asdf'}", string(v)) | 1948 assert_equal("object of Success {success: true, value: 'asdf'}", string(v)) |
1718 END | 1949 END |
1719 v9.CheckScriptSuccess(lines) | 1950 v9.CheckScriptSuccess(lines) |
1951 | |
1952 # class name after "extends" doesn't end in a space or NUL character | |
1953 lines =<< trim END | |
1954 vim9script | |
1955 class A | |
1956 endclass | |
1957 class B extends A" | |
1958 endclass | |
1959 END | |
1960 v9.CheckScriptFailure(lines, 'E1315:') | |
1720 enddef | 1961 enddef |
1721 | 1962 |
1722 def Test_using_base_class() | 1963 def Test_using_base_class() |
1723 var lines =<< trim END | 1964 var lines =<< trim END |
1724 vim9script | 1965 vim9script |
1839 abstract class Base | 2080 abstract class Base |
1840 this.name: string | 2081 this.name: string |
1841 endclass | 2082 endclass |
1842 END | 2083 END |
1843 v9.CheckScriptFailure(lines, 'E1316:') | 2084 v9.CheckScriptFailure(lines, 'E1316:') |
2085 | |
2086 # Abstract class cannot have a "new" function | |
2087 lines =<< trim END | |
2088 vim9script | |
2089 abstract class Base | |
2090 def new() | |
2091 enddef | |
2092 endclass | |
2093 END | |
2094 v9.CheckScriptFailure(lines, 'E1359:') | |
1844 enddef | 2095 enddef |
1845 | 2096 |
1846 def Test_closure_in_class() | 2097 def Test_closure_in_class() |
1847 var lines =<< trim END | 2098 var lines =<< trim END |
1848 vim9script | 2099 vim9script |
2061 var l = Stack(foo1, foo2) | 2312 var l = Stack(foo1, foo2) |
2062 END | 2313 END |
2063 v9.CheckScriptSuccess(lines) | 2314 v9.CheckScriptSuccess(lines) |
2064 enddef | 2315 enddef |
2065 | 2316 |
2317 " Test for calling methods from three levels of classes | |
2318 def Test_multi_level_method_call() | |
2319 var lines =<< trim END | |
2320 vim9script | |
2321 | |
2322 var A_func1: number = 0 | |
2323 var A_func2: number = 0 | |
2324 var A_func3: number = 0 | |
2325 var B_func2: number = 0 | |
2326 var B_func3: number = 0 | |
2327 var C_func3: number = 0 | |
2328 | |
2329 class A | |
2330 def Func1() | |
2331 A_func1 += 1 | |
2332 enddef | |
2333 | |
2334 def Func2() | |
2335 A_func2 += 1 | |
2336 enddef | |
2337 | |
2338 def Func3() | |
2339 A_func3 += 1 | |
2340 enddef | |
2341 endclass | |
2342 | |
2343 class B extends A | |
2344 def Func2() | |
2345 B_func2 += 1 | |
2346 enddef | |
2347 | |
2348 def Func3() | |
2349 B_func3 += 1 | |
2350 enddef | |
2351 endclass | |
2352 | |
2353 class C extends B | |
2354 def Func3() | |
2355 C_func3 += 1 | |
2356 enddef | |
2357 endclass | |
2358 | |
2359 def A_CallFuncs(a: A) | |
2360 a.Func1() | |
2361 a.Func2() | |
2362 a.Func3() | |
2363 enddef | |
2364 | |
2365 def B_CallFuncs(b: B) | |
2366 b.Func1() | |
2367 b.Func2() | |
2368 b.Func3() | |
2369 enddef | |
2370 | |
2371 def C_CallFuncs(c: C) | |
2372 c.Func1() | |
2373 c.Func2() | |
2374 c.Func3() | |
2375 enddef | |
2376 | |
2377 var cobj = C.new() | |
2378 A_CallFuncs(cobj) | |
2379 B_CallFuncs(cobj) | |
2380 C_CallFuncs(cobj) | |
2381 assert_equal(3, A_func1) | |
2382 assert_equal(0, A_func2) | |
2383 assert_equal(0, A_func3) | |
2384 assert_equal(3, B_func2) | |
2385 assert_equal(0, B_func3) | |
2386 assert_equal(3, C_func3) | |
2387 END | |
2388 v9.CheckScriptSuccess(lines) | |
2389 enddef | |
2390 | |
2391 " Test for using members from three levels of classes | |
2392 def Test_multi_level_member_access() | |
2393 var lines =<< trim END | |
2394 vim9script | |
2395 | |
2396 class A | |
2397 this.val1: number = 0 | |
2398 this.val2: number = 0 | |
2399 this.val3: number = 0 | |
2400 endclass | |
2401 | |
2402 class B extends A | |
2403 this.val2: number = 0 | |
2404 this.val3: number = 0 | |
2405 endclass | |
2406 | |
2407 class C extends B | |
2408 this.val3: number = 0 | |
2409 endclass | |
2410 | |
2411 def A_members(a: A) | |
2412 a.val1 += 1 | |
2413 a.val2 += 1 | |
2414 a.val3 += 1 | |
2415 enddef | |
2416 | |
2417 def B_members(b: B) | |
2418 b.val1 += 1 | |
2419 b.val2 += 1 | |
2420 b.val3 += 1 | |
2421 enddef | |
2422 | |
2423 def C_members(c: C) | |
2424 c.val1 += 1 | |
2425 c.val2 += 1 | |
2426 c.val3 += 1 | |
2427 enddef | |
2428 | |
2429 var cobj = C.new() | |
2430 A_members(cobj) | |
2431 B_members(cobj) | |
2432 C_members(cobj) | |
2433 assert_equal(3, cobj.val1) | |
2434 assert_equal(3, cobj.val2) | |
2435 assert_equal(3, cobj.val3) | |
2436 END | |
2437 v9.CheckScriptSuccess(lines) | |
2438 enddef | |
2439 | |
2066 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker | 2440 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker |