finally
return 6
endtry
- return -1
enddef
assert_equal(6, ReturnInFinally())
CheckDefAndScriptSuccess(lines)
enddef
+def Test_try_ends_in_return()
+ var lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ return 'foo'
+ catch
+ return 'caught'
+ endtry
+ enddef
+ assert_equal('foo', Foo())
+ END
+ CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ return 'foo'
+ catch
+ return 'caught'
+ endtry
+ echo 'notreached'
+ enddef
+ assert_equal('foo', Foo())
+ END
+ CheckScriptFailure(lines, 'E1095:')
+
+ lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ return 'foo'
+ catch /x/
+ return 'caught'
+ endtry
+ enddef
+ assert_equal('foo', Foo())
+ END
+ CheckScriptFailure(lines, 'E1027:')
+
+ lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ echo 'foo'
+ catch
+ echo 'caught'
+ finally
+ return 'done'
+ endtry
+ enddef
+ assert_equal('done', Foo())
+ END
+ CheckScriptSuccess(lines)
+
+enddef
+
def Test_try_in_catch()
var lines =<< trim END
vim9script
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 4071,
/**/
4070,
/**/
endlabel_T *ts_end_label; // jump to :finally or :endtry
int ts_catch_label; // instruction idx of last CATCH
int ts_caught_all; // "catch" without argument encountered
+ int ts_has_finally; // "finally" encountered
+ int ts_no_return; // one of the blocks did not end in return
} tryscope_T;
typedef enum {
emsg(_(e_catch_unreachable_after_catch_all));
return NULL;
}
+ if (!cctx->ctx_had_return)
+ scope->se_u.se_try.ts_no_return = TRUE;
if (cctx->ctx_skip != SKIP_YES)
{
isn->isn_arg.jump.jump_where = this_instr;
scope->se_u.se_try.ts_catch_label = 0;
}
+ scope->se_u.se_try.ts_has_finally = TRUE;
if (generate_instr(cctx, ISN_FINALLY) == NULL)
return NULL;
}
}
}
+ // If there is a finally clause that ends in return then we will return.
+ // If one of the blocks didn't end in "return" or we did not catch all
+ // exceptions reset the had_return flag.
+ if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
+ && (scope->se_u.se_try.ts_no_return
+ || !scope->se_u.se_try.ts_caught_all))
+ cctx->ctx_had_return = FALSE;
+
compile_endblock(cctx);
if (cctx->ctx_skip != SKIP_YES)
break;
case CMD_endtry:
line = compile_endtry(p, &cctx);
- cctx.ctx_had_return = FALSE;
break;
case CMD_throw:
line = compile_throw(p, &cctx);