Mirror of the Vim source from https://github.com/vim/vim
リビジョン | b471038ec3ea56fc0ec959bd6e546c94c0fc3fdd (tree) |
---|---|
日時 | 2020-04-08 04:00:04 |
作者 | Bram Moolenaar <Bram@vim....> |
コミッター | Bram Moolenaar |
patch 8.2.0527: Vim9: function types insufficiently tested
Commit: https://github.com/vim/vim/commit/ec5929d0fe7e90f953fa5b019486c0c4e5826d92
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Apr 7 20:53:39 2020 +0200
@@ -2301,7 +2301,7 @@ | ||
2301 | 2301 | # export TEST_FILTER=Test_terminal_wipe_buffer |
2302 | 2302 | # A partial match also works: |
2303 | 2303 | # export TEST_FILTER=wipe_buffer |
2304 | -$(NEW_TESTS): | |
2304 | +$(NEW_TESTS) test_vim9: | |
2305 | 2305 | cd testdir; $(MAKE) $@ VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) |
2306 | 2306 | |
2307 | 2307 | newtests: |
@@ -43,6 +43,19 @@ | ||
43 | 43 | # Tests for the GUI. |
44 | 44 | SCRIPTS_GUI = |
45 | 45 | |
46 | +# Tests for Vim9 script. | |
47 | +TEST_VIM9 = \ | |
48 | + test_vim9_disassemble \ | |
49 | + test_vim9_expr \ | |
50 | + test_vim9_func \ | |
51 | + test_vim9_script | |
52 | + | |
53 | +TEST_VIM9_RES = \ | |
54 | + test_vim9_disassemble.res \ | |
55 | + test_vim9_expr.res \ | |
56 | + test_vim9_func.res \ | |
57 | + test_vim9_script.res | |
58 | + | |
46 | 59 | # Individual tests, including the ones part of test_alot. |
47 | 60 | # Please keep sorted up to test_alot. |
48 | 61 | NEW_TESTS = \ |
@@ -272,10 +285,7 @@ | ||
272 | 285 | test_utf8 \ |
273 | 286 | test_utf8_comparisons \ |
274 | 287 | test_vartabs \ |
275 | - test_vim9_disassemble \ | |
276 | - test_vim9_expr \ | |
277 | - test_vim9_func \ | |
278 | - test_vim9_script \ | |
288 | + $(TEST_VIM9) \ | |
279 | 289 | test_viminfo \ |
280 | 290 | test_vimscript \ |
281 | 291 | test_virtualedit \ |
@@ -482,10 +492,7 @@ | ||
482 | 492 | test_user_func.res \ |
483 | 493 | test_usercommands.res \ |
484 | 494 | test_vartabs.res \ |
485 | - test_vim9_disassemble.res \ | |
486 | - test_vim9_expr.res \ | |
487 | - test_vim9_func.res \ | |
488 | - test_vim9_script.res \ | |
495 | + $(TEST_VIM9_RES) \ | |
489 | 496 | test_viminfo.res \ |
490 | 497 | test_vimscript.res \ |
491 | 498 | test_virtualedit.res \ |
@@ -79,6 +79,16 @@ | ||
79 | 79 | exit 1; \ |
80 | 80 | fi |
81 | 81 | |
82 | +# Run only tests specific for Vim9 script | |
83 | +test_vim9: | |
84 | + rm -f test_vim9_*.res test.log messages | |
85 | + @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile $(TEST_VIM9_RES) VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE) | |
86 | + @cat messages | |
87 | + @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile report VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE) | |
88 | + @if test -f test.log; then \ | |
89 | + exit 1; \ | |
90 | + fi | |
91 | + | |
82 | 92 | RM_ON_RUN = test.out X* viminfo |
83 | 93 | RM_ON_START = tiny.vim small.vim mbyte.vim mzscheme.vim test.ok benchmark.out |
84 | 94 | RUN_VIM = VIMRUNTIME=$(SCRIPTSOURCE) $(VALGRIND) $(VIMPROG) -f $(GUI_FLAG) -u unix.vim $(NO_INITS) -s dotest.in |
@@ -373,6 +373,11 @@ | ||
373 | 373 | return 1234 |
374 | 374 | enddef |
375 | 375 | |
376 | +def FuncNoArgRetString(): string | |
377 | + funcResult = 45 | |
378 | + return 'text' | |
379 | +enddef | |
380 | + | |
376 | 381 | def FuncOneArgNoRet(arg: number) |
377 | 382 | funcResult = arg |
378 | 383 | enddef |
@@ -382,6 +387,10 @@ | ||
382 | 387 | return arg |
383 | 388 | enddef |
384 | 389 | |
390 | +def FuncOneArgRetString(arg: string): string | |
391 | + return arg | |
392 | +enddef | |
393 | + | |
385 | 394 | def FuncOneArgRetAny(arg: any): any |
386 | 395 | return arg |
387 | 396 | enddef |
@@ -415,6 +424,32 @@ | ||
415 | 424 | assert_equal(13, funcResult) |
416 | 425 | enddef |
417 | 426 | |
427 | +def Test_func_type_part() | |
428 | + let RefVoid: func: void | |
429 | + RefVoid = FuncNoArgNoRet | |
430 | + RefVoid = FuncOneArgNoRet | |
431 | + CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') | |
432 | + CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') | |
433 | + | |
434 | + let RefAny: func(): any | |
435 | + RefAny = FuncNoArgRetNumber | |
436 | + RefAny = FuncNoArgRetString | |
437 | + CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') | |
438 | + CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') | |
439 | + | |
440 | + let RefNr: func: number | |
441 | + RefNr = FuncNoArgRetNumber | |
442 | + RefNr = FuncOneArgRetNumber | |
443 | + CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') | |
444 | + CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') | |
445 | + | |
446 | + let RefStr: func: string | |
447 | + RefStr = FuncNoArgRetString | |
448 | + RefStr = FuncOneArgRetString | |
449 | + CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') | |
450 | + CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') | |
451 | +enddef | |
452 | + | |
418 | 453 | def Test_func_type_fails() |
419 | 454 | CheckDefFailure(['let ref1: func()'], 'E704:') |
420 | 455 |
@@ -739,6 +739,8 @@ | ||
739 | 739 | static int included_patches[] = |
740 | 740 | { /* Add new patch number below this line */ |
741 | 741 | /**/ |
742 | + 527, | |
743 | +/**/ | |
742 | 744 | 526, |
743 | 745 | /**/ |
744 | 746 | 525, |
@@ -314,6 +314,11 @@ | ||
314 | 314 | // recognize commonly used types |
315 | 315 | if (argcount <= 0) |
316 | 316 | { |
317 | + if (ret_type == &t_unknown) | |
318 | + { | |
319 | + // (argcount == 0) is not possible | |
320 | + return &t_func_unknown; | |
321 | + } | |
317 | 322 | if (ret_type == &t_void) |
318 | 323 | { |
319 | 324 | if (argcount == 0) |
@@ -350,6 +355,7 @@ | ||
350 | 355 | return &t_any; |
351 | 356 | type->tt_type = VAR_FUNC; |
352 | 357 | type->tt_member = ret_type; |
358 | + type->tt_argcount = argcount; | |
353 | 359 | type->tt_args = NULL; |
354 | 360 | return type; |
355 | 361 | } |
@@ -1589,7 +1595,7 @@ | ||
1589 | 1595 | if (len == 4 && STRNCMP(*arg, "func", len) == 0) |
1590 | 1596 | { |
1591 | 1597 | type_T *type; |
1592 | - type_T *ret_type = &t_any; | |
1598 | + type_T *ret_type = &t_unknown; | |
1593 | 1599 | int argcount = -1; |
1594 | 1600 | int flags = 0; |
1595 | 1601 | int first_optional = -1; |
@@ -1657,7 +1663,7 @@ | ||
1657 | 1663 | { |
1658 | 1664 | // parse return type |
1659 | 1665 | ++*arg; |
1660 | - if (!VIM_ISWHITE(*p)) | |
1666 | + if (!VIM_ISWHITE(**arg)) | |
1661 | 1667 | semsg(_(e_white_after), ":"); |
1662 | 1668 | *arg = skipwhite(*arg); |
1663 | 1669 | ret_type = parse_type(arg, type_gap); |
@@ -2405,7 +2411,10 @@ | ||
2405 | 2411 | { |
2406 | 2412 | int ret = OK; |
2407 | 2413 | |
2408 | - if (expected->tt_type != VAR_UNKNOWN && expected->tt_type != VAR_ANY) | |
2414 | + // When expected is "unknown" we accept any actual type. | |
2415 | + // When expected is "any" we accept any actual type except "void". | |
2416 | + if (expected->tt_type != VAR_UNKNOWN | |
2417 | + && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID)) | |
2409 | 2418 | { |
2410 | 2419 | if (expected->tt_type != actual->tt_type) |
2411 | 2420 | { |
@@ -2421,8 +2430,7 @@ | ||
2421 | 2430 | } |
2422 | 2431 | else if (expected->tt_type == VAR_FUNC) |
2423 | 2432 | { |
2424 | - if (expected->tt_member != &t_any | |
2425 | - && expected->tt_member != &t_unknown) | |
2433 | + if (expected->tt_member != &t_unknown) | |
2426 | 2434 | ret = check_type(expected->tt_member, actual->tt_member, FALSE); |
2427 | 2435 | if (ret == OK && expected->tt_argcount != -1 |
2428 | 2436 | && (actual->tt_argcount < expected->tt_min_argcount |
@@ -4044,36 +4052,39 @@ | ||
4044 | 4052 | if (r == FAIL) |
4045 | 4053 | goto theend; |
4046 | 4054 | |
4047 | - stack = &cctx->ctx_type_stack; | |
4048 | - stacktype = stack->ga_len == 0 ? &t_void | |
4049 | - : ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
4050 | - if (idx >= 0 && (is_decl || !has_type)) | |
4055 | + if (cctx->ctx_skip != TRUE) | |
4051 | 4056 | { |
4052 | - lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
4053 | - if (new_local && !has_type) | |
4057 | + stack = &cctx->ctx_type_stack; | |
4058 | + stacktype = stack->ga_len == 0 ? &t_void | |
4059 | + : ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
4060 | + if (idx >= 0 && (is_decl || !has_type)) | |
4054 | 4061 | { |
4055 | - if (stacktype->tt_type == VAR_VOID) | |
4062 | + lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
4063 | + if (new_local && !has_type) | |
4056 | 4064 | { |
4057 | - emsg(_("E1031: Cannot use void value")); | |
4058 | - goto theend; | |
4065 | + if (stacktype->tt_type == VAR_VOID) | |
4066 | + { | |
4067 | + emsg(_("E1031: Cannot use void value")); | |
4068 | + goto theend; | |
4069 | + } | |
4070 | + else | |
4071 | + { | |
4072 | + // An empty list or dict has a &t_void member, for a | |
4073 | + // variable that implies &t_any. | |
4074 | + if (stacktype == &t_list_empty) | |
4075 | + lvar->lv_type = &t_list_any; | |
4076 | + else if (stacktype == &t_dict_empty) | |
4077 | + lvar->lv_type = &t_dict_any; | |
4078 | + else | |
4079 | + lvar->lv_type = stacktype; | |
4080 | + } | |
4059 | 4081 | } |
4060 | - else | |
4061 | - { | |
4062 | - // An empty list or dict has a &t_void member, for a | |
4063 | - // variable that implies &t_any. | |
4064 | - if (stacktype == &t_list_empty) | |
4065 | - lvar->lv_type = &t_list_any; | |
4066 | - else if (stacktype == &t_dict_empty) | |
4067 | - lvar->lv_type = &t_dict_any; | |
4068 | - else | |
4069 | - lvar->lv_type = stacktype; | |
4070 | - } | |
4082 | + else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) | |
4083 | + goto theend; | |
4071 | 4084 | } |
4072 | - else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) | |
4085 | + else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) | |
4073 | 4086 | goto theend; |
4074 | 4087 | } |
4075 | - else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) | |
4076 | - goto theend; | |
4077 | 4088 | } |
4078 | 4089 | else if (cmdidx == CMD_const) |
4079 | 4090 | { |