summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2023-01-11 21:14:17 +0000
committerBram Moolenaar <Bram@vim.org>2023-01-11 21:14:17 +0000
commit6481accd4086845cfce7548e06cb797c80587a98 (patch)
tree3d7be8192bf33602eae9203730c7a8d3e882f7de
parentbcbfaf32e02a92a6d6d35fc409b1b16aa931e3fa (diff)
downloadvim-git-6481accd4086845cfce7548e06cb797c80587a98.tar.gz
patch 9.0.1181: class inheritance and typing insufficiently testedv9.0.1181
Problem: Class inheritance and typing insufficiently tested. Solution: Add more tests. Implement missing behavior.
-rw-r--r--src/testdir/test_vim9_class.vim61
-rw-r--r--src/version.c2
-rw-r--r--src/vim9type.c29
3 files changed, 88 insertions, 4 deletions
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index c6da4f49c..139a632ed 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -419,6 +419,44 @@ def Test_class_object_compare()
endfor
enddef
+def Test_object_type()
+ var lines =<< trim END
+ vim9script
+
+ class One
+ this.one = 1
+ endclass
+ class Two
+ this.two = 2
+ endclass
+ class TwoMore extends Two
+ this.more = 9
+ endclass
+
+ var o: One = One.new()
+ var t: Two = Two.new()
+ var m: TwoMore = TwoMore.new()
+ var tm: Two = TwoMore.new()
+
+ t = m
+ END
+ v9.CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+
+ class One
+ this.one = 1
+ endclass
+ class Two
+ this.two = 2
+ endclass
+
+ var o: One = Two.new()
+ END
+ v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
+enddef
+
def Test_class_member()
# check access rules
var lines =<< trim END
@@ -750,7 +788,7 @@ def Test_class_used_as_type()
var p: Point
p = 'text'
END
- v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object but got string')
+ v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
enddef
def Test_class_extends()
@@ -895,6 +933,27 @@ def Test_class_extends()
echo o.ToString()
END
v9.CheckScriptFailure(lines, 'E1358:')
+
+ lines =<< trim END
+ vim9script
+ class Base
+ this.name: string
+ static def ToString(): string
+ return 'Base class'
+ enddef
+ endclass
+
+ class Child extends Base
+ this.age: number
+ def ToString(): string
+ return Base.ToString() .. ': ' .. this.age
+ enddef
+ endclass
+
+ var o = Child.new('John', 42)
+ assert_equal('Base class: 42', o.ToString())
+ END
+ v9.CheckScriptSuccess(lines)
enddef
diff --git a/src/version.c b/src/version.c
index 5036e070e..898cc6b57 100644
--- 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 */
/**/
+ 1181,
+/**/
1180,
/**/
1179,
diff --git a/src/vim9type.c b/src/vim9type.c
index ba925e0eb..5d3f815b5 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -874,6 +874,17 @@ check_type_maybe(
// check the argument count at runtime
ret = MAYBE;
}
+ else if (expected->tt_type == VAR_OBJECT)
+ {
+ class_T *cl;
+ for (cl = (class_T *)actual->tt_member; cl != NULL;
+ cl = cl->class_extends)
+ if ((class_T *)expected->tt_member == cl)
+ break;
+ if (cl == NULL)
+ ret = FAIL;
+ }
+
if (ret == FAIL && give_msg)
type_mismatch_where(expected, actual, where);
}
@@ -1601,13 +1612,12 @@ type_name(type_T *type, char **tofree)
if (type == NULL)
return "[unknown]";
name = vartype_name(type->tt_type);
+
if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
{
char *member_free;
char *member_name = type_name(type->tt_member, &member_free);
- size_t len;
-
- len = STRLEN(name) + STRLEN(member_name) + 3;
+ size_t len = STRLEN(name) + STRLEN(member_name) + 3;
*tofree = alloc(len);
if (*tofree != NULL)
{
@@ -1616,6 +1626,19 @@ type_name(type_T *type, char **tofree)
return *tofree;
}
}
+
+ if (type->tt_type == VAR_OBJECT || type->tt_type == VAR_CLASS)
+ {
+ char_u *class_name = ((class_T *)type->tt_member)->class_name;
+ size_t len = STRLEN(name) + STRLEN(class_name) + 3;
+ *tofree = alloc(len);
+ if (*tofree != NULL)
+ {
+ vim_snprintf(*tofree, len, "%s<%s>", name, class_name);
+ return *tofree;
+ }
+ }
+
if (type->tt_type == VAR_FUNC)
{
garray_T ga;