patch 9.1.1094: Vim9: problem finding implemented method in type hierarchy
Problem: Vim9: problem finding implemented method for abstract method
in type hierarchy (Aliaksei Budavei)
Solution: When checking for abstract methods in an extended class, check
whether an abstract method is implemented in one of the parent
classes (Yegappan Lakshmanan)
fixes: #16495
closes: #16497
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index c39f18c..0b3ea4a 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -12221,4 +12221,157 @@
v9.CheckSourceSuccess(lines)
enddef
+" Test for using a concrete method in an abstract extended class which is
+" further extended
+def Test_abstract_method_across_hierarchy()
+ var lines =<< trim END
+ vim9script
+
+ abstract class A
+ abstract def Foo(): string
+ endclass
+
+ abstract class B extends A
+ abstract def Bar(): string
+ endclass
+
+ class C extends B
+ def Foo(): string
+ return 'foo'
+ enddef
+
+ def Bar(): string
+ return 'bar'
+ enddef
+ endclass
+
+ def Fn1(a: A): string
+ return a.Foo()
+ enddef
+
+ def Fn2(b: B): string
+ return b.Bar()
+ enddef
+
+ var c = C.new()
+ assert_equal('foo', Fn1(c))
+ assert_equal('bar', Fn2(c))
+ END
+ v9.CheckSourceSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+
+ abstract class A
+ abstract def Foo(): string
+ endclass
+
+ abstract class B extends A
+ abstract def Bar(): string
+ endclass
+
+ class C extends B
+ def Bar(): string
+ return 'bar'
+ enddef
+ endclass
+
+ defcompile
+ END
+ v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
+
+ lines =<< trim END
+ vim9script
+
+ abstract class A
+ abstract def M1(): string
+ abstract def M2(): string
+ endclass
+
+ abstract class B extends A
+ def M1(): string
+ return 'B: M1'
+ enddef
+
+ def M2(): string
+ return 'B: M2'
+ enddef
+ endclass
+
+ class C1 extends B
+ def M1(): string
+ return 'C1: M1'
+ enddef
+ endclass
+
+ class C2 extends B
+ def M2(): string
+ return 'C2: M2'
+ enddef
+ endclass
+
+ class D1 extends C1
+ endclass
+
+ class D2 extends C2
+ endclass
+
+ var l: list<string> = []
+ for Type in ['C1', 'C2', 'D1', 'D2']
+ l->add(eval($'{Type}.new().M1()'))
+ l->add(eval($'{Type}.new().M2()'))
+ endfor
+ assert_equal(['C1: M1', 'B: M2', 'B: M1', 'C2: M2', 'C1: M1', 'B: M2', 'B: M1', 'C2: M2'], l)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+
+ abstract class A
+ abstract def M1(): string
+ abstract def M2(): string
+ endclass
+
+ class B extends A
+ def M1(): string
+ return 'B: M1'
+ enddef
+
+ def M2(): string
+ return 'B: M2'
+ enddef
+ endclass
+
+ abstract class C extends B
+ endclass
+
+ class D1 extends C
+ def M1(): string
+ return 'D1: M1'
+ enddef
+ endclass
+
+ class D2 extends C
+ def M2(): string
+ return 'D2: M2'
+ enddef
+ endclass
+
+ class E1 extends D1
+ endclass
+
+ class E2 extends D2
+ endclass
+
+ var l: list<string> = []
+ for Type in ['B', 'D1', 'D2', 'E1', 'E2']
+ l->add(eval($'{Type}.new().M1()'))
+ l->add( eval($'{Type}.new().M2()'))
+ endfor
+ assert_equal(['B: M1', 'B: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2', 'D1: M1', 'B: M2', 'B: M1', 'D2: M2'], l)
+ END
+ v9.CheckSourceSuccess(lines)
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker