Patch 9.0.1054
Problem:    Object member can't get type from initializer.
Solution:   If there is no type specified try to use the type of the
            initializer.  Check for a valid type.
Files:      src/vim9class.c, src/errors.h, src/vim9type.c,
            src/proto/vim9type.pro, src/testdir/test_vim9_class.vim


*** ../vim-9.0.1053/src/vim9class.c     2022-12-13 18:42:19.749879633 +0000
--- src/vim9class.c     2022-12-13 21:00:20.555936418 +0000
***************
*** 125,167 ****
            char_u *varname_end = to_name_end(varname, FALSE);
  
            char_u *colon = skipwhite(varname_end);
!           // TODO: accept initialization and figure out type from it
!           if (*colon != ':')
            {
!               emsg(_(e_type_or_initialization_required));
!               break;
!           }
!           if (VIM_ISWHITE(*varname_end))
!           {
!               semsg(_(e_no_white_space_allowed_before_colon_str), varname);
!               break;
            }
!           if (!VIM_ISWHITE(colon[1]))
            {
!               semsg(_(e_white_space_required_after_str_str), ":", varname);
                break;
            }
  
!           char_u *type_arg = skipwhite(colon + 1);
!           type_T *type = parse_type(&type_arg, &type_list, TRUE);
!           if (type == NULL)
!               break;
! 
!           char_u *expr_start = skipwhite(type_arg);
!           if (*expr_start == '=' && (!VIM_ISWHITE(expr_start[-1])
!                                              || !VIM_ISWHITE(expr_start[1])))
            {
!               semsg(_(e_white_space_required_before_and_after_str_at_str),
                                                                "=", type_arg);
!               break;
!           }
!           expr_start = skipwhite(expr_start + 1);
  
!           char_u *expr_end = expr_start;
!           evalarg_T   evalarg;
!           init_evalarg(&evalarg);
!           skip_expr(&expr_end, &evalarg);
!           clear_evalarg(&evalarg, NULL);
  
            if (ga_grow(&objmembers, 1) == FAIL)
                break;
--- 125,198 ----
            char_u *varname_end = to_name_end(varname, FALSE);
  
            char_u *colon = skipwhite(varname_end);
!           char_u *type_arg = colon;
!           type_T *type = NULL;
!           if (*colon == ':')
            {
!               if (VIM_ISWHITE(*varname_end))
!               {
!                   semsg(_(e_no_white_space_allowed_before_colon_str),
!                                                                     varname);
!                   break;
!               }
!               if (!VIM_ISWHITE(colon[1]))
!               {
!                   semsg(_(e_white_space_required_after_str_str), ":",
!                                                                     varname);
!                   break;
!               }
!               type_arg = skipwhite(colon + 1);
!               type = parse_type(&type_arg, &type_list, TRUE);
!               if (type == NULL)
!                   break;
            }
! 
!           char_u *expr_start = skipwhite(type_arg);
!           char_u *expr_end = expr_start;
!           if (type == NULL && *expr_start != '=')
            {
!               emsg(_(e_type_or_initialization_required));
                break;
            }
  
!           if (*expr_start == '=')
            {
!               if (!VIM_ISWHITE(expr_start[-1]) || !VIM_ISWHITE(expr_start[1]))
!               {
!                   semsg(_(e_white_space_required_before_and_after_str_at_str),
                                                                "=", type_arg);
!                   break;
!               }
!               expr_start = skipwhite(expr_start + 1);
  
!               expr_end = expr_start;
!               evalarg_T evalarg;
!               fill_evalarg_from_eap(&evalarg, eap, FALSE);
!               skip_expr(&expr_end, &evalarg);
! 
!               if (type == NULL)
!               {
!                   // No type specified, use the type of the initializer.
!                   typval_T tv;
!                   tv.v_type = VAR_UNKNOWN;
!                   char_u *expr = expr_start;
!                   int res = eval0(expr, &tv, eap, &evalarg);
! 
!                   if (res == OK)
!                       type = typval2type(&tv, get_copyID(), &type_list,
!                                                              TVTT_DO_MEMBER);
!                   if (type == NULL)
!                   {
!                       
semsg(_(e_cannot_get_object_member_type_from_initializer_str),
!                               expr_start);
!                       clear_evalarg(&evalarg, NULL);
!                       break;
!                   }
!               }
!               clear_evalarg(&evalarg, NULL);
!           }
!           if (!valid_declaration_type(type))
!               break;
  
            if (ga_grow(&objmembers, 1) == FAIL)
                break;
*** ../vim-9.0.1053/src/errors.h        2022-12-13 18:42:19.745879637 +0000
--- src/errors.h        2022-12-13 21:07:59.167945331 +0000
***************
*** 3374,3377 ****
--- 3374,3381 ----
        INIT(= N_("E1327: Object required, found %s"));
  EXTERN char e_constructor_default_value_must_be_vnone_str[]
        INIT(= N_("E1328: Constructor default value must be v:none: %s"));
+ EXTERN char e_cannot_get_object_member_type_from_initializer_str[]
+       INIT(= N_("E1329: Cannot get object member type from initializer: %s"));
+ EXTERN char e_invalid_type_for_object_member_str[]
+       INIT(= N_("E1330: Invalid type for object member: %s"));
  #endif
*** ../vim-9.0.1053/src/vim9type.c      2022-12-13 13:42:32.179427634 +0000
--- src/vim9type.c      2022-12-13 21:09:35.995942904 +0000
***************
*** 425,430 ****
--- 425,441 ----
        return &t_number;
      if (tv->v_type == VAR_BOOL)
        return &t_bool;
+     if (tv->v_type == VAR_SPECIAL)
+     {
+       if (tv->vval.v_number == VVAL_NULL)
+           return &t_null;
+       if (tv->vval.v_number == VVAL_NONE)
+           return &t_none;
+       if (tv->vval.v_number == VVAL_TRUE
+               || tv->vval.v_number == VVAL_TRUE)
+           return &t_bool;
+       return &t_unknown;
+     }
      if (tv->v_type == VAR_STRING)
        return &t_string;
      if (tv->v_type == VAR_BLOB)
***************
*** 620,625 ****
--- 631,655 ----
  }
  
  /*
+  * Return TRUE if "type" can be used for a variable declaration.
+  * Give an error and return FALSE if not.
+  */
+     int
+ valid_declaration_type(type_T *type)
+ {
+     if (type->tt_type == VAR_SPECIAL  // null, none
+           || type->tt_type == VAR_VOID)
+     {
+       char *tofree = NULL;
+       char *name = type_name(type, &tofree);
+       semsg(_(e_invalid_type_for_object_member_str), name);
+       vim_free(tofree);
+       return FALSE;
+     }
+     return TRUE;
+ }
+ 
+ /*
   * Get a type_T for a typval_T, used for v: variables.
   * "type_list" is used to temporarily create types in.
   */
*** ../vim-9.0.1053/src/proto/vim9type.pro      2022-12-08 15:32:11.087034211 
+0000
--- src/proto/vim9type.pro      2022-12-13 21:08:20.707944884 +0000
***************
*** 13,18 ****
--- 13,19 ----
  int type_any_or_unknown(type_T *type);
  int need_convert_to_bool(type_T *type, typval_T *tv);
  type_T *typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags);
+ int valid_declaration_type(type_T *type);
  type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
  int check_typval_arg_type(type_T *expected, typval_T *actual_tv, char 
*func_name, int arg_idx);
  int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where);
*** ../vim-9.0.1053/src/testdir/test_vim9_class.vim     2022-12-13 
18:42:19.749879633 +0000
--- src/testdir/test_vim9_class.vim     2022-12-13 21:10:32.755941033 +0000
***************
*** 231,237 ****
--- 231,288 ----
        assert_equal("none", chris.education)
    END
    v9.CheckScriptSuccess(lines)
+ 
+   lines =<< trim END
+       vim9script
+       class Person
+         this.name: string
+         this.age: number = 42
+         this.education: string = "unknown"
+ 
+         def new(this.name, this.age = v:none, this.education = v:none)
+         enddef
+       endclass
+ 
+       var missing = Person.new()
+   END
+   v9.CheckScriptFailure(lines, 'E119:')
+ enddef
+ 
+ def Test_class_object_member_inits()
+   var lines =<< trim END
+       vim9script
+       class TextPosition
+         this.lnum: number
+         this.col = 1
+         this.addcol: number = 2
+       endclass
+ 
+       var pos = TextPosition.new()
+       assert_equal(0, pos.lnum)
+       assert_equal(1, pos.col)
+       assert_equal(2, pos.addcol)
+   END
+   v9.CheckScriptSuccess(lines)
+ 
+   lines =<< trim END
+       vim9script
+       class TextPosition
+         this.lnum
+         this.col = 1
+       endclass
+   END
+   v9.CheckScriptFailure(lines, 'E1022:')
+ 
+   lines =<< trim END
+       vim9script
+       class TextPosition
+         this.lnum = v:none
+         this.col = 1
+       endclass
+   END
+   v9.CheckScriptFailure(lines, 'E1330:')
  enddef
  
  
+ 
  " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-9.0.1053/src/version.c       2022-12-13 18:42:19.749879633 +0000
--- src/version.c       2022-12-13 20:43:31.263950568 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1054,
  /**/

-- 
            ### Hiroshima 45, Chernobyl 86, Windows 95 ###

 /// 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/20221213211507.870E91C0BAE%40moolenaar.net.

Raspunde prin e-mail lui