# HG changeset patch # User Bram Moolenaar # Date 1648754103 -7200 # Node ID c446812efd6050c392f4fb40b7eca8d09d0c595e # Parent 59a7125e87f4166f3c5dcaf0a0f152e1312b150b patch 8.2.4657: errors for functions are sometimes hard to read Commit: https://github.com/vim/vim/commit/a6c18d38ca2df0a92403f2265a480d9dba08290f Author: Bram Moolenaar Date: Thu Mar 31 20:02:56 2022 +0100 patch 8.2.4657: errors for functions are sometimes hard to read Problem: Errors for functions are sometimes hard to read. Solution: Use printable_func_name() in more places. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -5296,15 +5296,29 @@ echo_string_core( break; case VAR_FUNC: - if (echo_style) { - *tofree = NULL; - r = tv->vval.v_string; - } - else - { - *tofree = string_quote(tv->vval.v_string, TRUE); - r = *tofree; + char_u buf[MAX_FUNC_NAME_LEN]; + + if (echo_style) + { + r = make_ufunc_name_readable(tv->vval.v_string, + buf, MAX_FUNC_NAME_LEN); + if (r == buf) + { + r = vim_strsave(buf); + *tofree = r; + } + else + *tofree = NULL; + } + else + { + *tofree = string_quote(tv->vval.v_string == NULL ? NULL + : make_ufunc_name_readable( + tv->vval.v_string, buf, MAX_FUNC_NAME_LEN), + TRUE); + r = *tofree; + } } break; diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -1,6 +1,7 @@ /* userfunc.c */ void func_init(void); hashtab_T *func_tbl_get(void); +char_u *make_ufunc_name_readable(char_u *name, char_u *buf, size_t bufsize); char_u *get_lambda_name(void); char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state); int get_lambda_tv(char_u **arg, typval_T *rettv, int types_optional, evalarg_T *evalarg); diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -4010,7 +4010,7 @@ func Test_expr_fails() call v9.CheckDefFailure(["echo len('asdf'"], 'E110:', 2) call v9.CheckScriptFailure(['vim9script', "echo len('asdf'"], 'E116:', 2) - call v9.CheckDefAndScriptFailure(["echo Func0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789()"], ['E1011:', 'E117:'], 1) + call v9.CheckDefAndScriptFailure(["echo Func01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789()"], ['E1011:', 'E117:'], 1) call v9.CheckDefAndScriptFailure(["echo doesnotexist()"], 'E117:', 1) endfunc diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -527,6 +527,28 @@ set_ufunc_name(ufunc_T *fp, char_u *name } /* + * If "name" starts with K_SPECIAL and "buf[bufsize]" is big enough + * return "buf" filled with a readable function name. + * Otherwise just return "name", thus the return value can always be used. + * "name" and "buf" may be equal. + */ + char_u * +make_ufunc_name_readable(char_u *name, char_u *buf, size_t bufsize) +{ + size_t len; + + if (name[0] != K_SPECIAL) + return name; + len = STRLEN(name); + if (len + 3 > bufsize) + return name; + + mch_memmove(buf + 5, name + 3, len + 1); + mch_memmove(buf, "", 5); + return buf; +} + +/* * Get a name for a lambda. Returned in static memory. */ char_u * @@ -3354,13 +3376,12 @@ user_func_error(int error, char_u *name, { case FCERR_UNKNOWN: if (funcexe->fe_found_var) - semsg(_(e_not_callable_type_str), name); + emsg_funcname(e_not_callable_type_str, name); else emsg_funcname(e_unknown_function_str, name); break; case FCERR_NOTMETHOD: - emsg_funcname( - N_(e_cannot_use_function_as_method_str), name); + emsg_funcname(e_cannot_use_function_as_method_str, name); break; case FCERR_DELETED: emsg_funcname(e_function_was_deleted_str, name); @@ -3372,8 +3393,7 @@ user_func_error(int error, char_u *name, emsg_funcname(e_not_enough_arguments_for_function_str, name); break; case FCERR_SCRIPT: - emsg_funcname( - e_using_sid_not_in_script_context_str, name); + emsg_funcname(e_using_sid_not_in_script_context_str, name); break; case FCERR_DICT: emsg_funcname(e_calling_dict_function_without_dictionary_str, @@ -3613,9 +3633,7 @@ theend: * cancelled due to an aborting error, an interrupt, or an exception. */ if (!aborting()) - { user_func_error(error, (name != NULL) ? name : funcname, funcexe); - } // clear the copies made from the partial while (argv_clear > 0) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4657, +/**/ 4656, /**/ 4655, diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1012,10 +1012,11 @@ call_ufunc( if (error != FCERR_UNKNOWN) { if (error == FCERR_TOOMANY) - semsg(_(e_too_many_arguments_for_function_str), ufunc->uf_name); + semsg(_(e_too_many_arguments_for_function_str), + printable_func_name(ufunc)); else semsg(_(e_not_enough_arguments_for_function_str), - ufunc->uf_name); + printable_func_name(ufunc)); return FAIL; } @@ -1047,7 +1048,7 @@ call_ufunc( if (error != FCERR_NONE) { - user_func_error(error, ufunc->uf_name, &funcexe); + user_func_error(error, printable_func_name(ufunc), &funcexe); return FAIL; } if (did_emsg > did_emsg_before) @@ -1211,7 +1212,7 @@ call_partial( if (res == FAIL) { if (called_emsg == called_emsg_before) - semsg(_(e_unknown_function_str), + emsg_funcname(e_unknown_function_str, name == NULL ? (char_u *)"[unknown]" : name); return FAIL; } @@ -1570,14 +1571,10 @@ call_eval_func( dictitem_T *v; v = find_var(name, NULL, FALSE); - if (v == NULL) + if (v == NULL || (v->di_tv.v_type != VAR_PARTIAL + && v->di_tv.v_type != VAR_FUNC)) { - semsg(_(e_unknown_function_str), name); - return FAIL; - } - if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC) - { - semsg(_(e_unknown_function_str), name); + emsg_funcname(e_unknown_function_str, name); return FAIL; } return call_partial(&v->di_tv, argcount, ectx); diff --git a/src/vim9expr.c b/src/vim9expr.c --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -698,7 +698,7 @@ compile_call( char_u *name = *arg; char_u *p; int argcount = argcount_init; - char_u namebuf[100]; + char_u namebuf[MAX_FUNC_NAME_LEN]; char_u fname_buf[FLEN_FIXED + 1]; char_u *tofree = NULL; int error = FCERR_NONE; @@ -818,7 +818,7 @@ compile_call( res = generate_BCALL(cctx, idx, argcount, argcount_init == 1); } else - semsg(_(e_unknown_function_str), namebuf); + emsg_funcname(e_unknown_function_str, namebuf); goto theend; } @@ -843,7 +843,7 @@ compile_call( && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL) { // A function name without g: prefix must be found locally. - semsg(_(e_unknown_function_str), namebuf); + emsg_funcname(e_unknown_function_str, namebuf); goto theend; } } @@ -874,7 +874,7 @@ compile_call( if (has_g_namespace || is_autoload) res = generate_UCALL(cctx, name, argcount); else - semsg(_(e_unknown_function_str), namebuf); + emsg_funcname(e_unknown_function_str, namebuf); theend: vim_free(tofree); diff --git a/src/vim9instr.c b/src/vim9instr.c --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -1517,7 +1517,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufu } if (ufunc->uf_def_status == UF_COMPILE_ERROR) { - emsg_funcname(_(e_call_to_function_that_failed_to_compile_str), + emsg_funcname(e_call_to_function_that_failed_to_compile_str, ufunc->uf_name); return FAIL; } @@ -1594,12 +1594,12 @@ generate_PCALL( if (argcount < type->tt_min_argcount - varargs) { - semsg(_(e_not_enough_arguments_for_function_str), name); + emsg_funcname(e_not_enough_arguments_for_function_str, name); return FAIL; } if (!varargs && argcount > type->tt_argcount) { - semsg(_(e_too_many_arguments_for_function_str), name); + emsg_funcname(e_too_many_arguments_for_function_str, name); return FAIL; } if (type->tt_args != NULL) diff --git a/src/vim9type.c b/src/vim9type.c --- a/src/vim9type.c +++ b/src/vim9type.c @@ -780,12 +780,12 @@ check_argument_types( return OK; // just in case if (totcount < type->tt_min_argcount - varargs) { - semsg(_(e_not_enough_arguments_for_function_str), name); + emsg_funcname(e_not_enough_arguments_for_function_str, name); return FAIL; } if (!varargs && type->tt_argcount >= 0 && totcount > type->tt_argcount) { - semsg(_(e_too_many_arguments_for_function_str), name); + emsg_funcname(e_too_many_arguments_for_function_str, name); return FAIL; } if (type->tt_args == NULL)