1
0
forked from aniani/vim

patch 9.0.1054: object member can't get type from initializer

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.
This commit is contained in:
Bram Moolenaar
2022-12-13 21:14:28 +00:00
parent 65b0d16768
commit 74e1274edf
6 changed files with 148 additions and 29 deletions

View File

@@ -125,43 +125,74 @@ ex_class(exarg_T *eap)
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 != ':')
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 (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])))
if (*expr_start == '=')
{
semsg(_(e_white_space_required_before_and_after_str_at_str),
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);
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);
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;