From: Peter Kenny Date: Tue, 26 May 2026 19:02:20 +0000 (+0000) Subject: patch 9.2.0541: Vim9: endclass/endenum/endinterface can give errors X-Git-Tag: v9.2.0541^0 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=207039097a214fb64fce18f5675152ae45a1e37c;p=thirdparty%2Fvim.git patch 9.2.0541: Vim9: endclass/endenum/endinterface can give errors Problem: Vim9: ":endclass", ":endenum" and ":endinterface" can give a "command cannot be shortened" error, because the full-name check compares against the line start instead of the command word. Solution: Skip a leading colon and white space before checking the end command name, update tests (Peter Kenny). related: #20032 related: #20191 closes: #20253 Signed-off-by: Peter Kenny Signed-off-by: Christian Brabandt --- diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index 35b87b208a..e49e5a8dc3 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -1,4 +1,4 @@ -" Test Vim9 classes +" Tests for Vim9 script classes import './util/vim9.vim' as v9 @@ -50,6 +50,14 @@ def Test_class_basic() END v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endcl', 3) + # "endclass" cannot be shortened (variant incl. whitespace and colon) + lines =<< trim END + vim9script + class Something + : endcla + END + v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endcla', 3) + # Additional words after "endclass" lines =<< trim END vim9script @@ -11869,4 +11877,19 @@ func Test_class_member_lambda() call v9.CheckSourceSuccess(lines) endfunc +" Test for colon and whitespace before class, endclass, static, and abstract +def Test_colon_whitespace() + var lines =<< trim END + : vim9script + : class C + # TODO: Fix :public - gives E1065 + # : public var p = true + : static var s = true + : endclass + : abstract class A + : endclass + END + v9.CheckSourceSuccess(lines) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_enum.vim b/src/testdir/test_vim9_enum.vim index be4c8f6d5b..4e05c86687 100644 --- a/src/testdir/test_vim9_enum.vim +++ b/src/testdir/test_vim9_enum.vim @@ -1,8 +1,8 @@ -" Test Vim9 enums +" Tests for Vim9 script enums import './util/vim9.vim' as v9 -" Test for parsing an enum definition +" Test for parsing an enum definition {{{1 def Test_enum_parse() # enum supported only in a Vim9 script var lines =<< trim END @@ -11,6 +11,14 @@ def Test_enum_parse() END v9.CheckSourceFailure(lines, 'E1414: Enum can only be defined in Vim9 script', 1) + # ":enum" and ":endenum" + lines =<< trim END + vim9script + :enum Foo + :endenum + END + v9.CheckSourceSuccess(lines) + # First character in an enum name should be capitalized. lines =<< trim END vim9script @@ -46,10 +54,10 @@ def Test_enum_parse() # The complete "enum" should be specified. lines =<< trim END vim9script - enu Something + enu Nah endenum END - v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: enu', 2) + v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: enu Nah', 2) # The complete "endenum" should be specified. lines =<< trim END @@ -59,6 +67,14 @@ def Test_enum_parse() END v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: enden', 3) + # "endenum" cannot be shortened (variant incl. whitespace and colon) + lines =<< trim END + vim9script + enum NoAbbrev + : endenu + END + v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endenu', 3) + # Only the complete word "endenum" should be recognized lines =<< trim END vim9script @@ -271,6 +287,16 @@ def Test_enum_parse() END v9.CheckSourceFailure(lines, 'E1418: Invalid enum value declaration: $%@', 4) + # Additional command after "enumvalue" + lines =<< trim END + vim9script + enum NoAdditionalCmd + One, | var y = 10 + Two + endenum + END + v9.CheckSourceFailure(lines, "E1418: Invalid enum value declaration: | var y = 10", 3) + # Duplicate enum value lines =<< trim END vim9script @@ -352,6 +378,7 @@ def Test_enum_parse() v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: n: number = 10', 3) enddef +" Test for basic enum declaration and errors {{{1 def Test_basic_enum() # Declare a simple enum var lines =<< trim END @@ -493,7 +520,7 @@ def Test_basic_enum() v9.CheckSourceFailure(lines, 'E1421: Enum "Fruit" cannot be used as a value', 6) enddef -" Test for type() and typename() of an enum +" Test for type() and typename() of an enum {{{1 def Test_enum_type() var lines =<< trim END vim9script @@ -525,7 +552,7 @@ def Test_enum_type() v9.CheckSourceSuccess(lines) enddef -" Try modifying an enum or an enum item +" Test for trying to modify an enum or an enum item {{{1 def Test_enum_modify() # Try assigning an unsupported value to an enum var lines =<< trim END @@ -652,7 +679,7 @@ def Test_enum_modify() v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.Apple" cannot be modified', 1) enddef -" Test for using enum in an expression +" Test for using enum in an expression {{{1 def Test_enum_expr() var lines =<< trim END vim9script @@ -691,7 +718,7 @@ def Test_enum_expr() v9.CheckSourceFailure(lines, 'E1425: Using an Enum "Color" as a String', 5) enddef -" Using an enum in a lambda function +" Test for using an enum in a lambda function {{{1 def Test_enum_lambda() var lines =<< trim END vim9script @@ -708,7 +735,7 @@ def Test_enum_lambda() v9.CheckSourceSuccess(lines) enddef -" Comparison using enums +" Test for comparison using enums {{{1 def Test_enum_compare() var lines =<< trim END vim9script @@ -761,7 +788,7 @@ def Test_enum_compare() v9.CheckSourceSuccess(lines) enddef -" Test for using an enum as a default argument to a function +" Test for using an enum as a default argument to a function {{{1 def Test_enum_default_arg() var lines =<< trim END vim9script @@ -777,7 +804,7 @@ def Test_enum_default_arg() v9.CheckSourceSuccess(lines) enddef -" Test for enum garbage collection +" Test for enum garbage collection {{{1 func Test_enum_garbagecollect() let lines =<< trim END vim9script @@ -826,7 +853,7 @@ func Test_enum_garbagecollect() call v9.CheckSourceSuccess(lines) endfunc -" Test for the enum values class variable +" Test for the enum values class variable {{{1 def Test_enum_values() var lines =<< trim END vim9script @@ -912,7 +939,7 @@ def Test_enum_values() v9.CheckSourceSuccess(lines) enddef -" Test comments in enums +" Test for using comments in enums {{{1 def Test_enum_comments() var lines =<< trim END vim9script @@ -951,7 +978,7 @@ def Test_enum_comments() v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 4) enddef -" Test trailing whitespace after enum values +" Test for trailing whitespace after enum values {{{1 def Test_enum_whitespace() var lines =<< trim END vim9script @@ -966,7 +993,7 @@ def Test_enum_whitespace() lines =<< trim END vim9script enum Car - Honda(), + Honda(), Ford() endenum defcompile @@ -974,7 +1001,7 @@ def Test_enum_whitespace() v9.CheckSourceSuccess(lines) enddef -" Test string() with enums +" Test for using string() with enums {{{1 def Test_enum_string() var lines =<< trim END vim9script @@ -1004,7 +1031,7 @@ def Test_enum_string() v9.CheckSourceSuccess(lines) enddef -" Test for importing an enum +" Test for importing an enum {{{1 def Test_enum_import() var lines =<< trim END vim9script @@ -1040,7 +1067,7 @@ def Test_enum_import() v9.CheckScriptSuccess(lines) enddef -" Test for using test_refcount() with enum +" Test for using test_refcount() with enum {{{1 def Test_enum_refcount() var lines =<< trim END vim9script @@ -1099,7 +1126,7 @@ def Test_enum_refcount() v9.CheckSourceSuccess(lines) enddef -" Test for defining an enum with additional object variables and methods +" Test for defining an enum with additional object variables and methods {{{1 def Test_enum_enhanced() var lines =<< trim END vim9script @@ -1140,7 +1167,7 @@ def Test_enum_enhanced() v9.CheckSourceSuccess(lines) enddef -" Test for the enum value 'name' variable +" Test for the enum value 'name' variable {{{1 def Test_enum_name() # Check the names of enum values var lines =<< trim END @@ -1221,7 +1248,7 @@ def Test_enum_name() v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: name', 4) enddef -" Test for the enum value 'ordinal' variable +" Test for the enum value 'ordinal' variable {{{1 def Test_enum_ordinal() # Check the ordinal values of enum items var lines =<< trim END @@ -1302,7 +1329,7 @@ def Test_enum_ordinal() v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: ordinal', 4) enddef -" Test for trying to create a new enum object using the constructor +" Test for trying to create a new enum object using the constructor {{{1 def Test_enum_invoke_constructor() var lines =<< trim END vim9script @@ -1360,7 +1387,7 @@ def Test_enum_invoke_constructor() v9.CheckSourceFailureList(lines, ['E1100:', 'E1100:'], 1) enddef -" Test for checking "this" in an enum constructor +" Test for checking "this" in an enum constructor {{{1 def Test_enum_this_in_constructor() var lines =<< trim END vim9script @@ -1378,7 +1405,7 @@ def Test_enum_this_in_constructor() v9.CheckSourceSuccess(lines) enddef -" Test for using member variables in an enum object +" Test for using member variables in an enum object {{{1 def Test_enum_object_variable() var lines =<< trim END vim9script @@ -1483,7 +1510,7 @@ def Test_enum_object_variable() v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 8) enddef -" Test for using a custom constructor with an enum +" Test for using a custom constructor with an enum {{{1 def Test_enum_custom_constructor() # space before "(" var lines =<< trim END @@ -1556,7 +1583,7 @@ def Test_enum_custom_constructor() v9.CheckSourceSuccess(lines) enddef -" Test for using class variables in an enum class +" Test for using class variables in an enum class {{{1 def Test_enum_class_variable() var lines =<< trim END vim9script @@ -1571,7 +1598,7 @@ def Test_enum_class_variable() v9.CheckSourceSuccess(lines) enddef -" Test for converting a string to an enum value +" Test for converting a string to an enum value {{{1 def Test_enum_eval() var lines =<< trim END vim9script @@ -1588,7 +1615,7 @@ def Test_enum_eval() v9.CheckSourceSuccess(lines) enddef -" Test for using "values" in an enum class variable +" Test for using "values" in an enum class variable {{{1 def Test_use_enum_values_in_class_variable() var lines =<< trim END vim9script @@ -1601,7 +1628,7 @@ def Test_use_enum_values_in_class_variable() v9.CheckSourceSuccess(lines) enddef -" Test for using lambda block in enums +" Test for using lambda block in enums {{{1 def Test_lambda_block_in_enum() # This used to crash Vim var lines =<< trim END @@ -1632,7 +1659,7 @@ def Test_lambda_block_in_enum() v9.CheckScriptSuccess(lines) enddef -" Echo an enum +" Test for echoing an enum {{{1 def Test_enum_echo() var lines =<< trim END vim9script @@ -1647,8 +1674,8 @@ def Test_enum_echo() v9.CheckScriptSuccess(lines) enddef -" Test for garbage collecting an enum with a complex member variables. -func Test_class_selfref_gc() +" Test for garbage collecting an enum with a complex member variables {{{1 +func Test_enum_selfref_gc() let lines =<< trim END vim9script enum Foo @@ -1664,7 +1691,7 @@ func Test_class_selfref_gc() call v9.CheckSourceSuccess(lines) endfunc -" Test for defining an enum in a function +" Test for defining an enum in a function {{{1 def Test_enum_defined_in_function() var lines =<< trim END vim9script @@ -1678,5 +1705,5 @@ def Test_enum_defined_in_function() END v9.CheckScriptFailure(lines, 'E1435: Enum can only be used in a script', 2) enddef - +" }}} " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_interface.vim b/src/testdir/test_vim9_interface.vim index 742b871f16..6377eb38e0 100644 --- a/src/testdir/test_vim9_interface.vim +++ b/src/testdir/test_vim9_interface.vim @@ -1,8 +1,8 @@ -" Tests for Vim9 interface +" Tests for Vim9 script interfaces import './util/vim9.vim' as v9 -" Tests for basic interface declaration and errors +" Test for basic interface declaration and errors {{{1 def Test_interface_basics() var lines =<< trim END vim9script @@ -13,6 +13,14 @@ def Test_interface_basics() END v9.CheckSourceSuccess(lines) + # ":interface" and ":endinterface" + lines =<< trim END + vim9script + :interface I + :endinterface + END + v9.CheckSourceSuccess(lines) + lines =<< trim END interface SomethingWrong static var count = 7 @@ -78,6 +86,14 @@ def Test_interface_basics() END v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endin', 3) + # "endinterface" cannot be shortened (variant incl. whitespace and colon) + lines =<< trim END + vim9script + interface Short + : endint + END + v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: endint', 3) + # Additional commands after "interface name" lines =<< trim END vim9script @@ -86,6 +102,14 @@ def Test_interface_basics() END v9.CheckSourceFailure(lines, "E488: Trailing characters: | var x = 10", 2) + # Additional command after "endinterface" + lines =<< trim END + vim9script + interface NoTrailingCmd + endinterface | echo 'no' + END + v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'no'", 3) + lines =<< trim END vim9script export interface EnterExit @@ -124,6 +148,7 @@ def Test_interface_basics() v9.CheckScriptSuccess(lines) enddef +" Test for mismatched end command for class and interface {{{1 def Test_class_interface_wrong_end() var lines =<< trim END vim9script @@ -142,7 +167,7 @@ def Test_class_interface_wrong_end() v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface', 4) enddef -" Test for using string() with an interface +" Test for using string() with an interface {{{1 def Test_interface_to_string() var lines =<< trim END vim9script @@ -154,6 +179,7 @@ def Test_interface_to_string() v9.CheckSourceSuccess(lines) enddef +" Test for a class implementing an interface {{{1 def Test_class_implements_interface() var lines =<< trim END vim9script @@ -281,13 +307,21 @@ def Test_class_implements_interface() END v9.CheckSourceFailure(lines, 'E1315: White space required after name: A"', 4) - # Trailing characters after a class name + # Trailing characters after an interface name lines =<< trim END vim9script - class A bbb - endclass + interface I nah + endinterface END - v9.CheckSourceFailure(lines, 'E488: Trailing characters: bbb', 2) + v9.CheckSourceFailure(lines, 'E488: Trailing characters: nah', 2) + + # Additional words after "endinterface" + lines =<< trim END + vim9script + interface NoTrailingChars + endinterface nah + END + v9.CheckSourceFailure(lines, "E488: Trailing characters: nah", 3) # using "implements" with a non-existing class lines =<< trim END @@ -519,6 +553,7 @@ def Test_class_implements_interface() v9.CheckSourceFailure(lines, 'E1389: Missing name after implements', 2) enddef +" Test for calling a method via an interface-typed variable {{{1 def Test_call_interface_method() var lines =<< trim END vim9script @@ -639,7 +674,7 @@ def Test_call_interface_method() v9.CheckSourceSuccess(lines) enddef -" Test for implementing an imported interface +" Test for implementing an imported interface {{{1 def Test_implement_imported_interface() var lines =<< trim END vim9script @@ -671,7 +706,7 @@ def Test_implement_imported_interface() v9.CheckScriptSuccess(lines) enddef -" Test for changing the member access of an interface in a implementation class +" Test for changing the member access of an interface in a implementation class {{{1 def Test_change_interface_member_access() var lines =<< trim END vim9script @@ -696,7 +731,7 @@ def Test_change_interface_member_access() v9.CheckSourceFailure(lines, 'E1367: Access level of variable "val" of interface "A" is different', 7) enddef -" Test for using a interface method using a child object +" Test for using a interface method using a child object {{{1 def Test_interface_method_from_child() var lines =<< trim END vim9script @@ -732,8 +767,8 @@ def Test_interface_method_from_child() v9.CheckSourceSuccess(lines) enddef -" Test for using an interface method using a child object when it is overridden -" by the child class. +" Test for using an interface method using a child object when ... {{{1 +" it is overridden by the child class. def Test_interface_overridden_method_from_child() var lines =<< trim END vim9script @@ -772,7 +807,7 @@ def Test_interface_overridden_method_from_child() v9.CheckSourceSuccess(lines) enddef -" Test for interface inheritance +" Test for interface inheritance {{{1 def Test_interface_inheritance() var lines =<< trim END vim9script @@ -880,8 +915,8 @@ def Test_interface_inheritance() v9.CheckSourceSuccess(lines) enddef -" A interface cannot have a static variable or a static method or a protected -" variable or a protected method or a public variable +" Test for an interface cannot have a static variable/method ... {{{1 +" a protected variable/method, or a public variable def Test_interface_with_unsupported_members() var lines =<< trim END vim9script @@ -956,7 +991,7 @@ def Test_interface_with_unsupported_members() v9.CheckSourceFailure(lines, 'E1380: Protected method not supported in an interface', 3) enddef -" Test for extending an interface +" Test for extending an interface {{{1 def Test_extend_interface() var lines =<< trim END vim9script @@ -1079,8 +1114,8 @@ def Test_extend_interface() v9.CheckSourceFailure(lines, 'E1382: Variable "val1": type mismatch, expected number but got string', 11) enddef -" Test for a child class implementing an interface when some of the methods are -" defined in the parent class. +" Test for a child class implementing an interface when some ... {{{1 +" of the methods are defined in the parent class def Test_child_class_implements_interface() var lines =<< trim END vim9script @@ -1263,7 +1298,7 @@ def Test_child_class_implements_interface() v9.CheckSourceFailure(lines, 'E1382: Variable "var3": type mismatch, expected list> but got list>', 22) enddef -" Test for extending an interface with duplicate variables and methods +" Test for extending an interface with duplicate variables and methods {{{1 def Test_interface_extends_with_dup_members() var lines =<< trim END vim9script @@ -1304,8 +1339,8 @@ def Test_interface_extends_with_dup_members() v9.CheckSourceSuccess(lines) enddef -" Test for implementing an interface with different ordering for the interface -" member variables. +" Test for implementing an interface with different ordering for {{{1 +" the interface member variables def Test_implement_interface_with_different_variable_order() var lines =<< trim END vim9script @@ -1329,7 +1364,7 @@ def Test_implement_interface_with_different_variable_order() v9.CheckSourceSuccess(lines) enddef -" Test for inheriting interfaces from an imported super class +" Test for inheriting interfaces from an imported super class {{{1 def Test_interface_inheritance_with_imported_super() var lines =<< trim END vim9script @@ -1367,7 +1402,7 @@ def Test_interface_inheritance_with_imported_super() v9.CheckSourceSuccess(lines) enddef -" Test for defining an interface in a function +" Test for defining an interface in a function {{{1 def Test_interface_defined_in_function() var lines =<< trim END vim9script @@ -1381,8 +1416,8 @@ def Test_interface_defined_in_function() v9.CheckScriptFailure(lines, 'E1436: Interface can only be used in a script', 2) enddef -" Test for using "any" type for a variable in a sub-class while it has a -" concrete type in the interface +" Test for using "any" type for a variable in a sub-class while ... {{{1 +" it has a concrete type in the interface def Test_implements_using_var_type_any() var lines =<< trim END vim9script @@ -1411,7 +1446,7 @@ def Test_implements_using_var_type_any() v9.CheckSourceFailure(lines, 'E1382: Variable "val": type mismatch, expected list> but got dict', 1) enddef -" Test interface garbage collection +" Test interface garbage collection {{{1 func Test_interface_garbagecollect() let lines =<< trim END vim9script @@ -1455,5 +1490,5 @@ func Test_interface_garbagecollect() END call v9.CheckSourceSuccess(lines) endfunc - +" }}} " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index bee5c589c0..6b9c13f396 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 541, /**/ 540, /**/ diff --git a/src/vim9class.c b/src/vim9class.c index bc10ce8b07..908fb95a35 100644 --- a/src/vim9class.c +++ b/src/vim9class.c @@ -2230,10 +2230,14 @@ early_ret: fullen = 12; } + // skip ':' and blanks + for (; VIM_ISWHITE(*p) || *p == ':'; ++p) + ; + char_u *cmd_start = p; if (checkforcmd(&p, end_name, shortlen)) { - if (STRNCMP(line, end_name, fullen) != 0) - semsg(_(e_command_cannot_be_shortened_str), line); + if (STRNCMP(cmd_start, end_name, fullen) != 0) + semsg(_(e_command_cannot_be_shortened_str), cmd_start); else if (*p == '|' || !ends_excmd2(line, p)) semsg(_(e_trailing_characters_str), p); else