changeset 31649:520857d1fda7 v9.0.1157

patch 9.0.1157: "implements" only handles one interface name Commit: https://github.com/vim/vim/commit/df8f9473596c8fb18ec893de677dba455e8925b3 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 7 14:51:03 2023 +0000 patch 9.0.1157: "implements" only handles one interface name Problem: "implements" only handles one interface name. Solution: Handle a comma separated list of names. Check for duplicate names.
author Bram Moolenaar <Bram@vim.org>
date Sat, 07 Jan 2023 16:00:05 +0100
parents 0dbf2cc7b334
children 0f3310ec8487
files src/errors.h src/testdir/test_vim9_class.vim src/version.c src/vim9class.c
diffstat 4 files changed, 80 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/errors.h
+++ b/src/errors.h
@@ -3422,4 +3422,8 @@ EXTERN char e_member_str_of_interface_st
 	INIT(= N_("E1348: Member \"%s\" of interface \"%s\" not implemented"));
 EXTERN char e_function_str_of_interface_str_not_implemented[]
 	INIT(= N_("E1349: Function \"%s\" of interface \"%s\" not implemented"));
-#endif
+EXTERN char e_duplicate_implements[]
+	INIT(= N_("E1350: Duplicate \"implements\""));
+EXTERN char e_duplicate_interface_after_implements_str[]
+	INIT(= N_("E1351: Duplicate interface after \"implements\": %s"));
+#endif
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -627,6 +627,19 @@ def Test_class_implements_interface()
           echo nr
         enddef
       endclass
+
+      interface Another
+        this.member: string
+      endinterface
+
+      class SomeImpl implements Some, Another
+        this.member = 'abc'
+        static count: number
+        def Method(nr: number)
+          echo nr
+        enddef
+      endclass
+
   END
   v9.CheckScriptSuccess(lines)
 
@@ -635,6 +648,32 @@ def Test_class_implements_interface()
 
       interface Some
         static counter: number
+      endinterface
+
+      class SomeImpl implements Some implements Some
+        static count: number
+      endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1350:')
+
+  lines =<< trim END
+      vim9script
+
+      interface Some
+        static counter: number
+      endinterface
+
+      class SomeImpl implements Some, Some
+        static count: number
+      endclass
+  END
+  v9.CheckScriptFailure(lines, 'E1351: Duplicate interface after "implements": Some')
+
+  lines =<< trim END
+      vim9script
+
+      interface Some
+        static counter: number
         def Method(nr: number)
       endinterface
 
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1157,
+/**/
     1156,
 /**/
     1155,
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -245,22 +245,45 @@ ex_class(exarg_T *eap)
 	//    specifies SomeInterface
 	if (STRNCMP(arg, "implements", 10) == 0 && IS_WHITE_OR_NUL(arg[10]))
 	{
-	    arg = skipwhite(arg + 10);
-	    char_u *impl_end = find_name_end(arg, NULL, NULL, FNE_CHECK_START);
-	    if (!IS_WHITE_OR_NUL(*impl_end))
+	    if (ga_impl.ga_len > 0)
 	    {
-		semsg(_(e_white_space_required_after_name_str), arg);
+		emsg(_(e_duplicate_implements));
 		goto early_ret;
 	    }
-	    char_u *iname = vim_strnsave(arg, impl_end - arg);
-	    if (iname == NULL)
-		goto early_ret;
-	    if (ga_add_string(&ga_impl, iname) == FAIL)
+	    arg = skipwhite(arg + 10);
+
+	    for (;;)
 	    {
-		vim_free(iname);
-		goto early_ret;
+		char_u *impl_end = find_name_end(arg, NULL, NULL,
+							      FNE_CHECK_START);
+		if (!IS_WHITE_OR_NUL(*impl_end) && *impl_end != ',')
+		{
+		    semsg(_(e_white_space_required_after_name_str), arg);
+		    goto early_ret;
+		}
+		char_u *iname = vim_strnsave(arg, impl_end - arg);
+		if (iname == NULL)
+		    goto early_ret;
+		for (int i = 0; i < ga_impl.ga_len; ++i)
+		    if (STRCMP(((char_u **)ga_impl.ga_data)[i], iname) == 0)
+		    {
+			semsg(_(e_duplicate_interface_after_implements_str),
+									iname);
+			vim_free(iname);
+			goto early_ret;
+		    }
+		if (ga_add_string(&ga_impl, iname) == FAIL)
+		{
+		    vim_free(iname);
+		    goto early_ret;
+		}
+		if (*impl_end != ',')
+		{
+		    arg = skipwhite(impl_end);
+		    break;
+		}
+		arg = skipwhite(impl_end + 1);
 	    }
-	    arg = skipwhite(impl_end);
 	}
 	else
 	{