diff src/testdir/test_vim9_class.vim @ 33217:499ba27ba0f6 v9.0.1885

patch 9.0.1885: Vim9: no support for abstract methods Commit: https://github.com/vim/vim/commit/7bcd25cad3e9d5c9e25c7ae2bde67285c26f73cd Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Fri Sep 8 19:27:51 2023 +0200 patch 9.0.1885: Vim9: no support for abstract methods Problem: Vim9: no support for abstract methods Solution: Add support for defining abstract methods in an abstract class closes: #13044 closes: #13046 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Fri, 08 Sep 2023 19:45:03 +0200
parents 71a097aab64d
children def9fc5c92d1
line wrap: on
line diff
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -4473,4 +4473,140 @@ enddef
 "   v9.CheckScriptSuccess(lines)
 " enddef
 
+" Test for abstract methods
+def Test_abstract_method()
+  # Use two abstract methods
+  var lines =<< trim END
+    vim9script
+    abstract class A
+      def M1(): number
+        return 10
+      enddef
+      abstract def M2(): number
+      abstract def M3(): number
+    endclass
+    class B extends A
+      def M2(): number
+        return 20
+      enddef
+      def M3(): number
+        return 30
+      enddef
+    endclass
+    var b = B.new()
+    assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
+  END
+  v9.CheckScriptSuccess(lines)
+
+  # Don't define an abstract method
+  lines =<< trim END
+    vim9script
+    abstract class A
+      abstract def Foo()
+    endclass
+    class B extends A
+    endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
+
+  # Use abstract method in a concrete class
+  lines =<< trim END
+    vim9script
+    class A
+      abstract def Foo()
+    endclass
+    class B extends A
+    endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
+
+  # Use abstract method in an interface
+  lines =<< trim END
+    vim9script
+    interface A
+      abstract def Foo()
+    endinterface
+    class B implements A
+    endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
+
+  # Abbreviate the "abstract" keyword
+  lines =<< trim END
+    vim9script
+    class A
+      abs def Foo()
+    endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
+
+  # Use "abstract" with a member variable
+  lines =<< trim END
+    vim9script
+    abstract class A
+      abstract this.val = 10
+    endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
+
+  # Use a static abstract method
+  lines =<< trim END
+    vim9script
+    abstract class A
+      abstract static def Foo(): number
+    endclass
+    class B extends A
+      static def Foo(): number
+        return 4
+      enddef
+    endclass
+    assert_equal(4, B.Foo())
+  END
+  v9.CheckScriptSuccess(lines)
+
+  # Type mismatch between abstract method and concrete method
+  lines =<< trim END
+    vim9script
+    abstract class A
+      abstract def Foo(a: string, b: number): list<number>
+    endclass
+    class B extends A
+      def Foo(a: number, b: string): list<string>
+        return []
+      enddef
+    endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1407: Member "Foo": type mismatch, expected func(string, number): list<number> but got func(number, string): list<string>')
+
+  # Use an abstract class to invoke an abstract method
+  # FIXME: This should fail
+  lines =<< trim END
+    vim9script
+    abstract class A
+      abstract static def Foo()
+    endclass
+    A.Foo()
+  END
+  v9.CheckScriptSuccess(lines)
+
+  # Invoke an abstract method from a def function
+  lines =<< trim END
+    vim9script
+    abstract class A
+      abstract def Foo(): list<number>
+    endclass
+    class B extends A
+      def Foo(): list<number>
+        return [3, 5]
+      enddef
+    endclass
+    def Bar(c: B)
+      assert_equal([3, 5], c.Foo())
+    enddef
+    var b = B.new()
+    Bar(b)
+  END
+  v9.CheckScriptSuccess(lines)
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker