Patch 9.0.1150
Problem:    :interface is not implemented yet.
Solution:   Implement the basics of :interface.
Files:      src/ex_cmds.h, src/ex_docmd.c, src/vim9class.c,
            src/proto/vim9class.pro, src/errors.h, src/vim.h, src/userfunc.c,
            src/proto/userfunc.pro, src/vim9compile.c, src/vim9execute.c,
            src/testdir/test_vim9_class.vim


*** ../vim-9.0.1149/src/ex_cmds.h       2022-12-04 20:11:12.791828025 +0000
--- src/ex_cmds.h       2023-01-05 15:14:46.898026429 +0000
***************
*** 756,762 ****
  EXCMD(CMD_intro,      "intro",        ex_intro,
        EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! EXCMD(CMD_interface,  "interface",    ex_interface,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_isearch,    "isearch",      ex_findpat,
--- 756,762 ----
  EXCMD(CMD_intro,      "intro",        ex_intro,
        EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
! EXCMD(CMD_interface,  "interface",    ex_class,
        EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_isearch,    "isearch",      ex_findpat,
*** ../vim-9.0.1149/src/ex_docmd.c      2023-01-02 16:54:48.932860868 +0000
--- src/ex_docmd.c      2023-01-05 15:12:03.626228517 +0000
***************
*** 288,294 ****
  # define ex_execute           ex_ni
  # define ex_finally           ex_ni
  # define ex_incdec            ex_ni
- # define ex_interface         ex_ni
  # define ex_finish            ex_ni
  # define ex_function          ex_ni
  # define ex_if                        ex_ni
--- 288,293 ----
*** ../vim-9.0.1149/src/vim9class.c     2023-01-02 21:03:59.900493426 +0000
--- src/vim9class.c     2023-01-05 18:31:17.896153189 +0000
***************
*** 26,32 ****
   * Returns OK or FAIL.  When OK then "varname_end" is set to just after the
   * variable name and "type_ret" is set to the decleared or detected type.
   * "init_expr" is set to the initialisation expression (allocated), if there 
is
!  * one.
   */
      static int
  parse_member(
--- 26,32 ----
   * Returns OK or FAIL.  When OK then "varname_end" is set to just after the
   * variable name and "type_ret" is set to the decleared or detected type.
   * "init_expr" is set to the initialisation expression (allocated), if there 
is
!  * one.  For an interface "init_expr" is NULL.
   */
      static int
  parse_member(
***************
*** 119,125 ****
--- 119,132 ----
  
      *type_ret = type;
      if (expr_end > expr_start)
+     {
+       if (init_expr == NULL)
+       {
+           emsg(_(e_cannot_initialize_member_in_interface));
+           return FAIL;
+       }
        *init_expr = vim_strnsave(expr_start, expr_end - expr_start);
+     }
      return OK;
  }
  
***************
*** 175,189 ****
  
  /*
   * Handle ":class" and ":abstract class" up to ":endclass".
   */
      void
  ex_class(exarg_T *eap)
  {
      if (!current_script_is_vim9()
                || (cmdmod.cmod_flags & CMOD_LEGACY)
                || !getline_equal(eap->getline, eap->cookie, getsourceline))
      {
!       emsg(_(e_class_can_only_be_defined_in_vim9_script));
        return;
      }
  
--- 182,202 ----
  
  /*
   * Handle ":class" and ":abstract class" up to ":endclass".
+  * Handle ":interface" up to ":endinterface".
   */
      void
  ex_class(exarg_T *eap)
  {
+     int is_class = eap->cmdidx == CMD_class;  // FALSE for :interface
+ 
      if (!current_script_is_vim9()
                || (cmdmod.cmod_flags & CMOD_LEGACY)
                || !getline_equal(eap->getline, eap->cookie, getsourceline))
      {
!       if (is_class)
!           emsg(_(e_class_can_only_be_defined_in_vim9_script));
!       else
!           emsg(_(e_interface_can_only_be_defined_in_vim9_script));
        return;
      }
  
***************
*** 201,213 ****
  
      if (!ASCII_ISUPPER(*arg))
      {
!       semsg(_(e_class_name_must_start_with_uppercase_letter_str), arg);
        return;
      }
      char_u *name_end = find_name_end(arg, NULL, NULL, FNE_CHECK_START);
      if (!IS_WHITE_OR_NUL(*name_end))
      {
!       semsg(_(e_white_space_required_after_class_name_str), arg);
        return;
      }
  
--- 214,230 ----
  
      if (!ASCII_ISUPPER(*arg))
      {
!       if (is_class)
!           semsg(_(e_class_name_must_start_with_uppercase_letter_str), arg);
!       else
!           semsg(_(e_interface_name_must_start_with_uppercase_letter_str),
!                                                                         arg);
        return;
      }
      char_u *name_end = find_name_end(arg, NULL, NULL, FNE_CHECK_START);
      if (!IS_WHITE_OR_NUL(*name_end))
      {
!       semsg(_(e_white_space_required_after_name_str), arg);
        return;
      }
  
***************
*** 239,245 ****
      ga_init2(&objmethods, sizeof(ufunc_T *), 10);
  
      /*
!      * Go over the body of the class until "endclass" is found.
       */
      char_u *theline = NULL;
      int success = FALSE;
--- 256,263 ----
      ga_init2(&objmethods, sizeof(ufunc_T *), 10);
  
      /*
!      * Go over the body of the class/interface until "endclass" or
!      * "endinterface" is found.
       */
      char_u *theline = NULL;
      int success = FALSE;
***************
*** 262,270 ****
        }
  
        char_u *p = line;
!       if (checkforcmd(&p, "endclass", 4))
        {
!           if (STRNCMP(line, "endclass", 8) != 0)
                semsg(_(e_command_cannot_be_shortened_str), line);
            else if (*p == '|' || !ends_excmd2(line, p))
                semsg(_(e_trailing_characters_str), p);
--- 280,289 ----
        }
  
        char_u *p = line;
!       char *end_name = is_class ? "endclass" : "endinterface";
!       if (checkforcmd(&p, end_name, is_class ? 4 : 5))
        {
!           if (STRNCMP(line, end_name, is_class ? 8 : 12) != 0)
                semsg(_(e_command_cannot_be_shortened_str), line);
            else if (*p == '|' || !ends_excmd2(line, p))
                semsg(_(e_trailing_characters_str), p);
***************
*** 272,277 ****
--- 291,302 ----
                success = TRUE;
            break;
        }
+       char *wrong_name = is_class ? "endinterface" : "endclass";
+       if (checkforcmd(&p, wrong_name, is_class ? 5 : 4))
+       {
+           semsg(_(e_invalid_command_str), line);
+           break;
+       }
  
        int has_public = FALSE;
        if (checkforcmd(&p, "public", 3))
***************
*** 320,326 ****
            type_T *type = NULL;
            char_u *init_expr = NULL;
            if (parse_member(eap, line, varname, has_public,
!                         &varname_end, &type_list, &type, &init_expr) == FAIL)
                break;
            if (add_member(&objmembers, varname, varname_end,
                                          has_public, type, init_expr) == FAIL)
--- 345,352 ----
            type_T *type = NULL;
            char_u *init_expr = NULL;
            if (parse_member(eap, line, varname, has_public,
!                         &varname_end, &type_list, &type,
!                         is_class ? &init_expr: NULL) == FAIL)
                break;
            if (add_member(&objmembers, varname, varname_end,
                                          has_public, type, init_expr) == FAIL)
***************
*** 358,364 ****
            ea.cookie = eap->cookie;
  
            ga_init2(&lines_to_free, sizeof(char_u *), 50);
!           ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE);
            ga_clear_strings(&lines_to_free);
  
            if (uf != NULL)
--- 384,391 ----
            ea.cookie = eap->cookie;
  
            ga_init2(&lines_to_free, sizeof(char_u *), 50);
!           ufunc_T *uf = define_function(&ea, NULL, &lines_to_free,
!                                          is_class ? CF_CLASS : CF_INTERFACE);
            ga_clear_strings(&lines_to_free);
  
            if (uf != NULL)
***************
*** 389,395 ****
            type_T *type = NULL;
            char_u *init_expr = NULL;
            if (parse_member(eap, line, varname, has_public,
!                     &varname_end, &type_list, &type, &init_expr) == FAIL)
                break;
            if (add_member(&classmembers, varname, varname_end,
                                      has_public, type, init_expr) == FAIL)
--- 416,423 ----
            type_T *type = NULL;
            char_u *init_expr = NULL;
            if (parse_member(eap, line, varname, has_public,
!                     &varname_end, &type_list, &type,
!                     is_class ? &init_expr : NULL) == FAIL)
                break;
            if (add_member(&classmembers, varname, varname_end,
                                      has_public, type, init_expr) == FAIL)
***************
*** 401,407 ****
  
        else
        {
!           semsg(_(e_not_valid_command_in_class_str), line);
            break;
        }
      }
--- 429,438 ----
  
        else
        {
!           if (is_class)
!               semsg(_(e_not_valid_command_in_class_str), line);
!           else
!               semsg(_(e_not_valid_command_in_interface_str), line);
            break;
        }
      }
***************
*** 415,420 ****
--- 446,454 ----
        cl = ALLOC_CLEAR_ONE(class_T);
        if (cl == NULL)
            goto cleanup;
+       if (!is_class)
+           cl->class_flags = CLASS_INTERFACE;
+ 
        cl->class_refcount = 1;
        cl->class_name = vim_strnsave(arg, name_end - arg);
        if (cl->class_name == NULL)
***************
*** 429,435 ****
                                    &cl->class_obj_member_count) == FAIL)
            goto cleanup;
  
!       if (cl->class_class_member_count > 0)
        {
            // Allocate a typval for each class member and initialize it.
            cl->class_members_tv = ALLOC_CLEAR_MULT(typval_T,
--- 463,469 ----
                                    &cl->class_obj_member_count) == FAIL)
            goto cleanup;
  
!       if (is_class && cl->class_class_member_count > 0)
        {
            // Allocate a typval for each class member and initialize it.
            cl->class_members_tv = ALLOC_CLEAR_MULT(typval_T,
***************
*** 491,497 ****
            garray_T lines_to_free;
            ga_init2(&lines_to_free, sizeof(char_u *), 50);
  
!           ufunc_T *nf = define_function(&fea, NULL, &lines_to_free, TRUE);
  
            ga_clear_strings(&lines_to_free);
            vim_free(fga.ga_data);
--- 525,532 ----
            garray_T lines_to_free;
            ga_init2(&lines_to_free, sizeof(char_u *), 50);
  
!           ufunc_T *nf = define_function(&fea, NULL, &lines_to_free,
!                                          is_class ? CF_CLASS : CF_INTERFACE);
  
            ga_clear_strings(&lines_to_free);
            vim_free(fga.ga_data);
***************
*** 634,648 ****
  }
  
  /*
-  * Handle ":interface" up to ":endinterface".
-  */
-     void
- ex_interface(exarg_T *eap UNUSED)
- {
-     // TODO
- }
- 
- /*
   * Handle ":enum" up to ":endenum".
   */
      void
--- 669,674 ----
*** ../vim-9.0.1149/src/proto/vim9class.pro     2023-01-01 19:53:26.582445815 
+0000
--- src/proto/vim9class.pro     2023-01-05 15:15:14.373993702 +0000
***************
*** 1,7 ****
  /* vim9class.c */
  void ex_class(exarg_T *eap);
  type_T *class_member_type(class_T *cl, char_u *name, char_u *name_end, int 
*member_idx);
- void ex_interface(exarg_T *eap);
  void ex_enum(exarg_T *eap);
  void ex_type(exarg_T *eap);
  int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int 
verbose);
--- 1,6 ----
*** ../vim-9.0.1149/src/errors.h        2023-01-02 18:10:00.015271225 +0000
--- src/errors.h        2023-01-05 19:32:27.942723658 +0000
***************
*** 3346,3353 ****
  #ifdef FEAT_EVAL
  EXTERN char e_class_name_must_start_with_uppercase_letter_str[]
        INIT(= N_("E1314: Class name must start with an uppercase letter: %s"));
! EXTERN char e_white_space_required_after_class_name_str[]
!       INIT(= N_("E1315: White space required after class name: %s"));
  EXTERN char e_class_can_only_be_defined_in_vim9_script[]
        INIT(= N_("E1316: Class can only be defined in Vim9 script"));
  EXTERN char e_invalid_object_member_declaration_str[]
--- 3346,3353 ----
  #ifdef FEAT_EVAL
  EXTERN char e_class_name_must_start_with_uppercase_letter_str[]
        INIT(= N_("E1314: Class name must start with an uppercase letter: %s"));
! EXTERN char e_white_space_required_after_name_str[]
!       INIT(= N_("E1315: White space required after name: %s"));
  EXTERN char e_class_can_only_be_defined_in_vim9_script[]
        INIT(= N_("E1316: Class can only be defined in Vim9 script"));
  EXTERN char e_invalid_object_member_declaration_str[]
***************
*** 3406,3409 ****
--- 3406,3417 ----
        INIT(= N_("E1340: Argument already declared in the class: %s"));
  EXTERN char e_variable_already_declared_in_class_str[]
        INIT(= N_("E1341: Variable already declared in the class: %s"));
+ EXTERN char e_interface_can_only_be_defined_in_vim9_script[]
+       INIT(= N_("E1342: Interface can only be defined in Vim9 script"));
+ EXTERN char e_interface_name_must_start_with_uppercase_letter_str[]
+       INIT(= N_("E1343: Interface name must start with an uppercase letter: 
%s"));
+ EXTERN char e_cannot_initialize_member_in_interface[]
+       INIT(= N_("E1344: Cannot initialize a member in an interface"));
+ EXTERN char e_not_valid_command_in_interface_str[]
+       INIT(= N_("E1345: Not a valid command in an interface: %s"));
  #endif
*** ../vim-9.0.1149/src/vim.h   2022-12-09 21:41:43.908327271 +0000
--- src/vim.h   2023-01-05 15:35:43.760309581 +0000
***************
*** 2854,2857 ****
--- 2854,2861 ----
  
  #define MAX_LSHIFT_BITS (varnumber_T)((sizeof(uvarnumber_T) * 8) - 1)
  
+ // Flags used by "class_flags" of define_function()
+ #define CF_CLASS      1       // inside a class
+ #define CF_INTERFACE  2       // inside an interface
+ 
  #endif // VIM__H
*** ../vim-9.0.1149/src/userfunc.c      2023-01-04 13:16:16.555907760 +0000
--- src/userfunc.c      2023-01-05 15:36:49.500376818 +0000
***************
*** 215,221 ****
      garray_T  *default_args,
      int               skip,
      exarg_T   *eap,           // can be NULL
!     int               in_class,       // TRUE when inside a class
      garray_T  *newlines,      // function body lines
      garray_T  *lines_to_free)
  {
--- 215,221 ----
      garray_T  *default_args,
      int               skip,
      exarg_T   *eap,           // can be NULL
!     int               in_class,       // non-zero when inside a class or 
interface
      garray_T  *newlines,      // function body lines
      garray_T  *lines_to_free)
  {
***************
*** 4462,4468 ****
   * When "name_arg" is not NULL this is a nested function, using "name_arg" for
   * the function name.
   * "lines_to_free" is a list of strings to be freed later.
!  * If "in_class" is TRUE then the function is defined inside a class.
   * Returns a pointer to the function or NULL if no function defined.
   */
      ufunc_T *
--- 4462,4470 ----
   * When "name_arg" is not NULL this is a nested function, using "name_arg" for
   * the function name.
   * "lines_to_free" is a list of strings to be freed later.
!  * If "class_flags" has CF_CLASS then the function is defined inside a class.
!  * With CF_INTERFACE the function is define inside an interface, only the
!  * ":def"/":function" line is expected, no function body.
   * Returns a pointer to the function or NULL if no function defined.
   */
      ufunc_T *
***************
*** 4470,4476 ****
        exarg_T     *eap,
        char_u      *name_arg,
        garray_T    *lines_to_free,
!       int         in_class)
  {
      int               j;
      int               c;
--- 4472,4478 ----
        exarg_T     *eap,
        char_u      *name_arg,
        garray_T    *lines_to_free,
!       int         class_flags)
  {
      int               j;
      int               c;
***************
*** 4545,4551 ****
  
      /*
       * Get the function name.  There are these situations:
!      * func       normal function name, also when "in_class" is TRUE
       *                    "name" == func, "fudi.fd_dict" == NULL
       * dict.func    new dictionary entry
       *                    "name" == NULL, "fudi.fd_dict" set,
--- 4547,4553 ----
  
      /*
       * Get the function name.  There are these situations:
!      * func       normal function name, also when "class_flags" is non-zero
       *                    "name" == func, "fudi.fd_dict" == NULL
       * dict.func    new dictionary entry
       *                    "name" == NULL, "fudi.fd_dict" set,
***************
*** 4586,4592 ****
        }
  
        int tfn_flags = TFN_NO_AUTOLOAD | TFN_NEW_FUNC
!                                              | (in_class ? TFN_IN_CLASS : 0);
        name = save_function_name(&p, &is_global, eap->skip, tfn_flags, &fudi);
        paren = (vim_strchr(p, '(') != NULL);
        if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
--- 4588,4594 ----
        }
  
        int tfn_flags = TFN_NO_AUTOLOAD | TFN_NEW_FUNC
!                                      | (class_flags != 0 ? TFN_IN_CLASS : 0);
        name = save_function_name(&p, &is_global, eap->skip, tfn_flags, &fudi);
        paren = (vim_strchr(p, '(') != NULL);
        if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
***************
*** 4789,4795 ****
      if (get_function_args(&p, ')', &newargs,
                         eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE,
                         NULL, &varargs, &default_args, eap->skip,
!                        eap, in_class, &newlines, lines_to_free) == FAIL)
        goto errret_2;
      whitep = p;
  
--- 4791,4797 ----
      if (get_function_args(&p, ')', &newargs,
                         eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE,
                         NULL, &varargs, &default_args, eap->skip,
!                        eap, class_flags, &newlines, lines_to_free) == FAIL)
        goto errret_2;
      whitep = p;
  
***************
*** 4899,4905 ****
  
      // Do not define the function when getting the body fails and when
      // skipping.
!     if (get_function_body(eap, &newlines, line_arg, lines_to_free) == FAIL
            || eap->skip)
        goto erret;
  
--- 4901,4909 ----
  
      // Do not define the function when getting the body fails and when
      // skipping.
!     if (((class_flags & CF_INTERFACE) == 0
!               && get_function_body(eap, &newlines, line_arg, lines_to_free)
!                                                                      == FAIL)
            || eap->skip)
        goto erret;
  
***************
*** 4934,4940 ****
        if (name == NULL)
            goto erret;
      }
!     else if (!in_class)
      {
        hashtab_T       *ht;
        char_u          *find_name = name;
--- 4938,4944 ----
        if (name == NULL)
            goto erret;
      }
!     else if (class_flags == 0)
      {
        hashtab_T       *ht;
        char_u          *find_name = name;
***************
*** 5159,5165 ****
            hi = hash_find(&func_hashtab, name);
            hi->hi_key = UF2HIKEY(fp);
        }
!       else if (!in_class && hash_add(&func_hashtab,
                                         UF2HIKEY(fp), "add function") == FAIL)
        {
            free_fp = TRUE;
--- 5163,5169 ----
            hi = hash_find(&func_hashtab, name);
            hi->hi_key = UF2HIKEY(fp);
        }
!       else if (class_flags == 0 && hash_add(&func_hashtab,
                                         UF2HIKEY(fp), "add function") == FAIL)
        {
            free_fp = TRUE;
***************
*** 5251,5257 ****
      garray_T lines_to_free;
  
      ga_init2(&lines_to_free, sizeof(char_u *), 50);
!     (void)define_function(eap, NULL, &lines_to_free, FALSE);
      ga_clear_strings(&lines_to_free);
  }
  
--- 5255,5261 ----
      garray_T lines_to_free;
  
      ga_init2(&lines_to_free, sizeof(char_u *), 50);
!     (void)define_function(eap, NULL, &lines_to_free, 0);
      ga_clear_strings(&lines_to_free);
  }
  
*** ../vim-9.0.1149/src/proto/userfunc.pro      2022-12-09 21:41:43.908327271 
+0000
--- src/proto/userfunc.pro      2023-01-05 15:36:56.676383590 +0000
***************
*** 46,52 ****
  char_u *alloc_printable_func_name(char_u *fname);
  char_u *save_function_name(char_u **name, int *is_global, int skip, int 
flags, funcdict_T *fudi);
  void list_functions(regmatch_T *regmatch);
! ufunc_T *define_function(exarg_T *eap, char_u *name_arg, garray_T 
*lines_to_free, int in_class);
  void ex_function(exarg_T *eap);
  ufunc_T *find_func_by_name(char_u *name, compiletype_T *compile_type);
  void ex_defcompile(exarg_T *eap);
--- 46,52 ----
  char_u *alloc_printable_func_name(char_u *fname);
  char_u *save_function_name(char_u **name, int *is_global, int skip, int 
flags, funcdict_T *fudi);
  void list_functions(regmatch_T *regmatch);
! ufunc_T *define_function(exarg_T *eap, char_u *name_arg, garray_T 
*lines_to_free, int class_flags);
  void ex_function(exarg_T *eap);
  ufunc_T *find_func_by_name(char_u *name, compiletype_T *compile_type);
  void ex_defcompile(exarg_T *eap);
*** ../vim-9.0.1149/src/vim9compile.c   2023-01-03 19:08:46.005020599 +0000
--- src/vim9compile.c   2023-01-05 19:32:15.026773197 +0000
***************
*** 991,997 ****
      int save_KeyTyped = KeyTyped;
      KeyTyped = FALSE;
  
!     ufunc = define_function(eap, lambda_name, lines_to_free, FALSE);
  
      KeyTyped = save_KeyTyped;
  
--- 991,997 ----
      int save_KeyTyped = KeyTyped;
      KeyTyped = FALSE;
  
!     ufunc = define_function(eap, lambda_name, lines_to_free, 0);
  
      KeyTyped = save_KeyTyped;
  
*** ../vim-9.0.1149/src/vim9execute.c   2023-01-03 19:08:46.005020599 +0000
--- src/vim9execute.c   2023-01-05 15:35:26.336290068 +0000
***************
*** 4280,4286 ****
                    CLEAR_FIELD(ea);
                    ea.cmd = ea.arg = iptr->isn_arg.string;
                    ga_init2(&lines_to_free, sizeof(char_u *), 50);
!                   define_function(&ea, NULL, &lines_to_free, FALSE);
                    ga_clear_strings(&lines_to_free);
                }
                break;
--- 4280,4286 ----
                    CLEAR_FIELD(ea);
                    ea.cmd = ea.arg = iptr->isn_arg.string;
                    ga_init2(&lines_to_free, sizeof(char_u *), 50);
!                   define_function(&ea, NULL, &lines_to_free, 0);
                    ga_clear_strings(&lines_to_free);
                }
                break;
*** ../vim-9.0.1149/src/testdir/test_vim9_class.vim     2023-01-05 
13:16:00.304020639 +0000
--- src/testdir/test_vim9_class.vim     2023-01-05 19:33:13.118555970 +0000
***************
*** 552,556 ****
--- 552,616 ----
    v9.CheckScriptSuccess(lines)
  enddef
  
+ def Test_interface_basics()
+   var lines =<< trim END
+       vim9script
+       interface Something
+         this.value: string
+         static count: number
+         def GetCount(): number
+       endinterface
+   END
+   v9.CheckScriptSuccess(lines)
+ 
+   lines =<< trim END
+       interface SomethingWrong
+         static count = 7
+       endinterface
+   END
+   v9.CheckScriptFailure(lines, 'E1342:')
+ 
+   lines =<< trim END
+       vim9script
+ 
+       interface Some
+         static count: number
+         def Method(count: number)
+       endinterface
+   END
+   # TODO: this should give an error for "count" shadowing
+   v9.CheckScriptSuccess(lines)
+ 
+   lines =<< trim END
+       vim9script
+       interface somethingWrong
+         static count = 7
+       endinterface
+   END
+   v9.CheckScriptFailure(lines, 'E1343: Interface name must start with an 
uppercase letter: somethingWrong')
+ 
+   lines =<< trim END
+       vim9script
+       interface SomethingWrong
+         this.value: string
+         static count = 7
+         def GetCount(): number
+       endinterface
+   END
+   v9.CheckScriptFailure(lines, 'E1344:')
+ 
+   lines =<< trim END
+       vim9script
+       interface SomethingWrong
+         this.value: string
+         static count: number
+         def GetCount(): number
+           return 5
+         enddef
+       endinterface
+   END
+   v9.CheckScriptFailure(lines, 'E1345: Not a valid command in an interface: 
return 5')
+ enddef
+ 
  
  " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-9.0.1149/src/version.c       2023-01-05 13:16:00.304020639 +0000
--- src/version.c       2023-01-05 18:20:08.591743051 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1150,
  /**/

-- 
"I've been teaching myself to play the piano for about 5 years and now write
most of my songs on it, mainly because I can never find any paper."
                Jeff Lynne, ELO's greatest hits

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230105200043.613A71C02DC%40moolenaar.net.

Raspunde prin e-mail lui