changeset 28263:c446812efd60 v8.2.4657

patch 8.2.4657: errors for functions are sometimes hard to read Commit: https://github.com/vim/vim/commit/a6c18d38ca2df0a92403f2265a480d9dba08290f Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Thu, 31 Mar 2022 21:15:03 +0200
parents 59a7125e87f4
children 9c13b183de2e
files src/eval.c src/proto/userfunc.pro src/testdir/test_vim9_expr.vim src/userfunc.c src/version.c src/vim9execute.c src/vim9expr.c src/vim9instr.c src/vim9type.c
diffstat 9 files changed, 68 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- 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;
 
--- 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);
--- 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
 
--- 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, "<SNR>", 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)
--- 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,
--- 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);
--- 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);
--- 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)
--- 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)