mirror of
https://github.com/vim/vim
synced 2025-07-16 01:01:58 +00:00
patch 9.1.1274: Vim9: no support for object<type> as variable type
Problem: Vim9: no support for object<type> as variable type Solution: add support for object<type> (Yegappan Lakshmanan) closes: #17041 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
f16d8b2dda
commit
6fa62085ff
@ -1,4 +1,4 @@
|
|||||||
*version9.txt* For Vim version 9.1. Last change: 2025 Mar 27
|
*version9.txt* For Vim version 9.1. Last change: 2025 Apr 03
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -41553,6 +41553,8 @@ Enum support for Vim9 script |:enum|
|
|||||||
|
|
||||||
Support for protected _new() method
|
Support for protected _new() method
|
||||||
|
|
||||||
|
Add support for object<{type}> as variable data type |vim9-types|
|
||||||
|
|
||||||
Diff mode ~
|
Diff mode ~
|
||||||
---------
|
---------
|
||||||
Include the "linematch" algorithm for the 'diffopt' setting. This aligns
|
Include the "linematch" algorithm for the 'diffopt' setting. This aligns
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*vim9.txt* For Vim version 9.1. Last change: 2025 Mar 23
|
*vim9.txt* For Vim version 9.1. Last change: 2025 Apr 03
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -1467,6 +1467,7 @@ The following builtin types are supported:
|
|||||||
blob
|
blob
|
||||||
list<{type}>
|
list<{type}>
|
||||||
dict<{type}>
|
dict<{type}>
|
||||||
|
object<{type}>
|
||||||
job
|
job
|
||||||
channel
|
channel
|
||||||
tuple<{type}>
|
tuple<{type}>
|
||||||
|
@ -12808,4 +12808,178 @@ def Test_dict_of_objects()
|
|||||||
v9.CheckSourceSuccess(lines)
|
v9.CheckSourceSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
" Test for using the type() and typename() functions with a variable of type
|
||||||
|
" object
|
||||||
|
def Test_type_typename_funcs_with_object_variable()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
|
||||||
|
var o1: object<any>
|
||||||
|
assert_equal([13, 'object<any>'], [type(o1), typename(o1)])
|
||||||
|
|
||||||
|
var o2: object<A>
|
||||||
|
assert_equal([13, 'object<any>'], [type(o2), typename(o2)])
|
||||||
|
|
||||||
|
var o3: A
|
||||||
|
assert_equal([13, 'object<any>'], [type(o3), typename(o3)])
|
||||||
|
|
||||||
|
var o4 = A.new()
|
||||||
|
assert_equal([13, 'object<A>'], [type(o4), typename(o4)])
|
||||||
|
|
||||||
|
var l = [A.new(), B.new()]
|
||||||
|
assert_equal([13, 'object<B>'], [type(l[1]), typename(l[1])])
|
||||||
|
|
||||||
|
var d = {o_a: A.new(), o_b: B.new()}
|
||||||
|
assert_equal([13, 'object<B>'], [type(d.o_b), typename(d.o_b)])
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
" Test for object<any> type
|
||||||
|
def Test_object_any_type()
|
||||||
|
# assigning different objects to variable of type object<any>
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
var x: object<any>
|
||||||
|
x = A.new()
|
||||||
|
assert_true(instanceof(x, A))
|
||||||
|
x = B.new()
|
||||||
|
assert_true(instanceof(x, B))
|
||||||
|
x = null_object
|
||||||
|
assert_true(instanceof(x, null_class))
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
|
# Use a list of object<any> variable
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
var l: list<object<any>>
|
||||||
|
l->add(A.new())
|
||||||
|
l->add(B.new())
|
||||||
|
assert_true(instanceof(l[0], A))
|
||||||
|
assert_true(instanceof(l[1], B))
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
|
# Using object<any> as a function argument type and the return type
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
def Fn(x: object<any>): object<any>
|
||||||
|
return x
|
||||||
|
enddef
|
||||||
|
assert_true(instanceof(Fn(A.new()), A))
|
||||||
|
assert_true(instanceof(Fn(B.new()), B))
|
||||||
|
END
|
||||||
|
|
||||||
|
# Try assigning a different type of value to a object<any> variable
|
||||||
|
lines =<< trim END
|
||||||
|
var x: object<any> = []
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got list<any>', 'E1012: Type mismatch; expected object<any> but got list<any>'])
|
||||||
|
|
||||||
|
# Try assigning a different type of value to a object<any> variable
|
||||||
|
lines =<< trim END
|
||||||
|
var x: object<any>
|
||||||
|
x = 0z10
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got blob', 'E1012: Type mismatch; expected object<any> but got blob'])
|
||||||
|
|
||||||
|
# Try adding a different type of value to a list<object<any>> variable
|
||||||
|
lines =<< trim END
|
||||||
|
var x: list<object<any>>
|
||||||
|
x->add({})
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got dict<any>', 'E1012: Type mismatch; expected object<any> but got dict<any>'])
|
||||||
|
|
||||||
|
# Try adding a different type of value to a dict<object<any>> variable
|
||||||
|
lines =<< trim END
|
||||||
|
var x: dict<object<any>>
|
||||||
|
x['a'] = {}
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefAndScriptFailure(lines, ['E1012: Type mismatch; expected object<any> but got dict<any>', 'E1012: Type mismatch; expected object<any> but got dict<any>'])
|
||||||
|
enddef
|
||||||
|
|
||||||
|
" Test for object<{class}> type
|
||||||
|
def Test_object_of_class_type()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
var x: object<A>
|
||||||
|
x = A.new()
|
||||||
|
assert_true(instanceof(x, A))
|
||||||
|
var y: object<A> = A.new()
|
||||||
|
assert_true(instanceof(y, A))
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
var x: object<A>
|
||||||
|
x = B.new()
|
||||||
|
END
|
||||||
|
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got object<B>')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
class B
|
||||||
|
endclass
|
||||||
|
def Fn(x: object<A>): object<B>
|
||||||
|
return B.new()
|
||||||
|
enddef
|
||||||
|
assert_true(instanceof(Fn(A.new()), B))
|
||||||
|
END
|
||||||
|
v9.CheckSourceSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
var x: object
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefAndScriptFailure(lines, ['E1008: Missing <type> after object', 'E1008: Missing <type> after object'])
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
var x: object <any>
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefAndScriptFailure(lines, ['E1068: No white space allowed before ''<'': <any>', 'E1068: No white space allowed before ''<'': <any>'])
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
var x: object<any
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefAndScriptFailure(lines, ['E1009: Missing > after type: <any', 'E1009: Missing > after type: <any'])
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
var x: object<any,any>
|
||||||
|
END
|
||||||
|
v9.CheckSourceDefFailure(lines, 'E1009: Missing > after type: <any,any>')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
var x: object<any,any>
|
||||||
|
END
|
||||||
|
v9.CheckSourceFailure(lines, 'E488: Trailing characters: ,any>')
|
||||||
|
enddef
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1274,
|
||||||
/**/
|
/**/
|
||||||
1273,
|
1273,
|
||||||
/**/
|
/**/
|
||||||
|
@ -4132,7 +4132,12 @@ f_instanceof(typval_T *argvars, typval_T *rettv)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (object_tv->vval.v_object == NULL)
|
if (object_tv->vval.v_object == NULL)
|
||||||
|
{
|
||||||
|
if (classinfo_tv->vval.v_class == NULL)
|
||||||
|
// consider null_object as an instance of null_class
|
||||||
|
rettv->vval.v_number = VVAL_TRUE;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (; classinfo_tv->v_type != VAR_UNKNOWN; ++classinfo_tv)
|
for (; classinfo_tv->v_type != VAR_UNKNOWN; ++classinfo_tv)
|
||||||
{
|
{
|
||||||
|
@ -1784,6 +1784,63 @@ on_err:
|
|||||||
return ret_type;
|
return ret_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a "object" type at "*arg" and advance over it.
|
||||||
|
* When "give_error" is TRUE give error messages, otherwise be quiet.
|
||||||
|
* Return NULL for failure.
|
||||||
|
*/
|
||||||
|
static type_T *
|
||||||
|
parse_type_object(char_u **arg, garray_T *type_gap, int give_error)
|
||||||
|
{
|
||||||
|
char_u *arg_start = *arg;
|
||||||
|
type_T *object_type;
|
||||||
|
int prev_called_emsg = called_emsg;
|
||||||
|
|
||||||
|
// object<X> or object<any>
|
||||||
|
if (**arg != '<')
|
||||||
|
{
|
||||||
|
if (give_error)
|
||||||
|
{
|
||||||
|
if (*skipwhite(*arg) == '<')
|
||||||
|
semsg(_(e_no_white_space_allowed_before_str_str), "<", *arg);
|
||||||
|
else
|
||||||
|
semsg(_(e_missing_type_after_str), "object");
|
||||||
|
}
|
||||||
|
|
||||||
|
// only "object" is specified
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip spaces following "object<"
|
||||||
|
*arg = skipwhite(*arg + 1);
|
||||||
|
|
||||||
|
object_type = parse_type(arg, type_gap, give_error);
|
||||||
|
if (object_type == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*arg = skipwhite(*arg);
|
||||||
|
if (**arg != '>' && called_emsg == prev_called_emsg)
|
||||||
|
{
|
||||||
|
if (give_error)
|
||||||
|
semsg(_(e_missing_gt_after_type_str), arg_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
++*arg;
|
||||||
|
|
||||||
|
if (object_type->tt_type == VAR_ANY)
|
||||||
|
return &t_object_any;
|
||||||
|
|
||||||
|
if (object_type->tt_type != VAR_OBJECT)
|
||||||
|
{
|
||||||
|
// specified type is not a class
|
||||||
|
if (give_error)
|
||||||
|
semsg(_(e_class_name_not_found_str), arg_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return object_type;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a user defined type at "*arg" and advance over it.
|
* Parse a user defined type at "*arg" and advance over it.
|
||||||
* It can be a class or an interface or a typealias name, possibly imported.
|
* It can be a class or an interface or a typealias name, possibly imported.
|
||||||
@ -1932,6 +1989,13 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
|
|||||||
return &t_number;
|
return &t_number;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'o':
|
||||||
|
if (len == 6 && STRNCMP(*arg, "object", len) == 0)
|
||||||
|
{
|
||||||
|
*arg += len;
|
||||||
|
return parse_type_object(arg, type_gap, give_error);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (len == 6 && STRNCMP(*arg, "string", len) == 0)
|
if (len == 6 && STRNCMP(*arg, "string", len) == 0)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user