mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 9.0.1041: cannot define a method in a class
Problem: Cannot define a method in a class. Solution: Implement defining an object method. Make calling an object method work.
This commit is contained in:
@@ -188,6 +188,7 @@ get_function_line(
|
||||
if (theline != NULL)
|
||||
{
|
||||
if (lines_to_free->ga_len > 0
|
||||
&& eap->cmdlinep != NULL
|
||||
&& *eap->cmdlinep == ((char_u **)lines_to_free->ga_data)
|
||||
[lines_to_free->ga_len - 1])
|
||||
*eap->cmdlinep = theline;
|
||||
@@ -214,7 +215,7 @@ get_function_args(
|
||||
garray_T *default_args,
|
||||
int skip,
|
||||
exarg_T *eap, // can be NULL
|
||||
class_T *class_arg,
|
||||
int in_class, // TRUE when inside a class
|
||||
garray_T *newlines, // function body lines
|
||||
garray_T *lines_to_free)
|
||||
{
|
||||
@@ -294,7 +295,7 @@ get_function_args(
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (class_arg != NULL && STRNCMP(p, "this.", 5) == 0)
|
||||
else if (in_class && STRNCMP(p, "this.", 5) == 0)
|
||||
{
|
||||
// this.memberName
|
||||
p += 5;
|
||||
@@ -1436,7 +1437,7 @@ get_lambda_tv(
|
||||
s = *arg + 1;
|
||||
ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL,
|
||||
types_optional ? &argtypes : NULL, types_optional, evalarg,
|
||||
NULL, &default_args, TRUE, NULL, NULL, NULL, NULL);
|
||||
NULL, &default_args, TRUE, NULL, FALSE, NULL, NULL);
|
||||
if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL)
|
||||
{
|
||||
if (types_optional)
|
||||
@@ -1453,7 +1454,7 @@ get_lambda_tv(
|
||||
ret = get_function_args(arg, equal_arrow ? ')' : '-', pnewargs,
|
||||
types_optional ? &argtypes : NULL, types_optional, evalarg,
|
||||
&varargs, &default_args,
|
||||
FALSE, NULL, NULL, NULL, NULL);
|
||||
FALSE, NULL, FALSE, NULL, NULL);
|
||||
if (ret == FAIL
|
||||
|| (s = skip_arrow(*arg, equal_arrow, &ret_type,
|
||||
equal_arrow || vim9script ? &white_error : NULL)) == NULL)
|
||||
@@ -2733,8 +2734,8 @@ call_user_func(
|
||||
profile_may_start_func(&profile_info, fp, caller);
|
||||
#endif
|
||||
sticky_cmdmod_flags = 0;
|
||||
call_def_function(fp, argcount, argvars, 0, funcexe->fe_partial,
|
||||
fc, rettv);
|
||||
call_def_function(fp, argcount, argvars, 0,
|
||||
funcexe->fe_partial, funcexe->fe_object, fc, rettv);
|
||||
funcdepth_decrement();
|
||||
#ifdef FEAT_PROFILE
|
||||
if (do_profiling == PROF_YES && (fp->uf_profiling
|
||||
@@ -3957,6 +3958,7 @@ list_func_head(ufunc_T *fp, int indent)
|
||||
* "is_global" is NULL.
|
||||
* flags:
|
||||
* TFN_INT: internal function name OK
|
||||
* TFN_IN_CLASS: function in a class
|
||||
* TFN_QUIET: be quiet
|
||||
* TFN_NO_AUTOLOAD: do not use script autoloading
|
||||
* TFN_NO_DEREF: do not dereference a Funcref
|
||||
@@ -4172,8 +4174,9 @@ trans_function_name(
|
||||
}
|
||||
|
||||
// In Vim9 script a user function is script-local by default, unless it
|
||||
// starts with a lower case character: dict.func().
|
||||
vim9_local = ASCII_ISUPPER(*start) && vim9script;
|
||||
// starts with a lower case character: dict.func(). Or when in a class.
|
||||
vim9_local = ASCII_ISUPPER(*start) && vim9script
|
||||
&& (flags & TFN_IN_CLASS) == 0;
|
||||
|
||||
/*
|
||||
* Copy the function name to allocated memory.
|
||||
@@ -4211,8 +4214,10 @@ trans_function_name(
|
||||
lead += (int)STRLEN(sid_buf);
|
||||
}
|
||||
}
|
||||
else if (!(flags & TFN_INT) && (builtin_function(lv.ll_name, len)
|
||||
|| (vim9script && *lv.ll_name == '_')))
|
||||
else if (!(flags & TFN_INT)
|
||||
&& (builtin_function(lv.ll_name, len)
|
||||
|| (vim9script && *lv.ll_name == '_'))
|
||||
&& !((flags & TFN_IN_CLASS) && STRNCMP(lv.ll_name, "new", 3) == 0))
|
||||
{
|
||||
semsg(_(vim9script ? e_function_name_must_start_with_capital_str
|
||||
: e_function_name_must_start_with_capital_or_s_str),
|
||||
@@ -4417,7 +4422,7 @@ list_functions(regmatch_T *regmatch)
|
||||
* When "name_arg" is not NULL this is a nested function, using "name_arg" for
|
||||
* the function name.
|
||||
* "lines_to_free" is a list of strings to be freed later.
|
||||
* If "class_arg" is not NULL then the function is defined in this class.
|
||||
* If "in_class" is TRUE then the function is defined inside a class.
|
||||
* Returns a pointer to the function or NULL if no function defined.
|
||||
*/
|
||||
ufunc_T *
|
||||
@@ -4425,7 +4430,7 @@ define_function(
|
||||
exarg_T *eap,
|
||||
char_u *name_arg,
|
||||
garray_T *lines_to_free,
|
||||
class_T *class_arg)
|
||||
int in_class)
|
||||
{
|
||||
int j;
|
||||
int c;
|
||||
@@ -4500,7 +4505,7 @@ define_function(
|
||||
|
||||
/*
|
||||
* Get the function name. There are these situations:
|
||||
* func normal function name
|
||||
* func normal function name, also when "in_class" is TRUE
|
||||
* "name" == func, "fudi.fd_dict" == NULL
|
||||
* dict.func new dictionary entry
|
||||
* "name" == NULL, "fudi.fd_dict" set,
|
||||
@@ -4541,7 +4546,7 @@ define_function(
|
||||
}
|
||||
|
||||
int tfn_flags = TFN_NO_AUTOLOAD | TFN_NEW_FUNC
|
||||
| (class_arg == 0 ? 0 : TFN_INT);
|
||||
| (in_class ? TFN_IN_CLASS : 0);
|
||||
name = save_function_name(&p, &is_global, eap->skip, tfn_flags, &fudi);
|
||||
paren = (vim_strchr(p, '(') != NULL);
|
||||
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
|
||||
@@ -4743,7 +4748,7 @@ define_function(
|
||||
if (get_function_args(&p, ')', &newargs,
|
||||
eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE,
|
||||
NULL, &varargs, &default_args, eap->skip,
|
||||
eap, class_arg, &newlines, lines_to_free) == FAIL)
|
||||
eap, in_class, &newlines, lines_to_free) == FAIL)
|
||||
goto errret_2;
|
||||
whitep = p;
|
||||
|
||||
@@ -4860,7 +4865,35 @@ define_function(
|
||||
/*
|
||||
* If there are no errors, add the function
|
||||
*/
|
||||
if (fudi.fd_dict == NULL)
|
||||
if (fudi.fd_dict != NULL)
|
||||
{
|
||||
char numbuf[20];
|
||||
|
||||
fp = NULL;
|
||||
if (fudi.fd_newkey == NULL && !eap->forceit)
|
||||
{
|
||||
emsg(_(e_dictionary_entry_already_exists));
|
||||
goto erret;
|
||||
}
|
||||
if (fudi.fd_di == NULL)
|
||||
{
|
||||
// Can't add a function to a locked dictionary
|
||||
if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE))
|
||||
goto erret;
|
||||
}
|
||||
// Can't change an existing function if it is locked
|
||||
else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE))
|
||||
goto erret;
|
||||
|
||||
// Give the function a sequential number. Can only be used with a
|
||||
// Funcref!
|
||||
vim_free(name);
|
||||
sprintf(numbuf, "%d", ++func_nr);
|
||||
name = vim_strsave((char_u *)numbuf);
|
||||
if (name == NULL)
|
||||
goto erret;
|
||||
}
|
||||
else if (!in_class)
|
||||
{
|
||||
hashtab_T *ht;
|
||||
char_u *find_name = name;
|
||||
@@ -4967,34 +5000,6 @@ define_function(
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char numbuf[20];
|
||||
|
||||
fp = NULL;
|
||||
if (fudi.fd_newkey == NULL && !eap->forceit)
|
||||
{
|
||||
emsg(_(e_dictionary_entry_already_exists));
|
||||
goto erret;
|
||||
}
|
||||
if (fudi.fd_di == NULL)
|
||||
{
|
||||
// Can't add a function to a locked dictionary
|
||||
if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE))
|
||||
goto erret;
|
||||
}
|
||||
// Can't change an existing function if it is locked
|
||||
else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE))
|
||||
goto erret;
|
||||
|
||||
// Give the function a sequential number. Can only be used with a
|
||||
// Funcref!
|
||||
vim_free(name);
|
||||
sprintf(numbuf, "%d", ++func_nr);
|
||||
name = vim_strsave((char_u *)numbuf);
|
||||
if (name == NULL)
|
||||
goto erret;
|
||||
}
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
@@ -5113,7 +5118,8 @@ define_function(
|
||||
hi = hash_find(&func_hashtab, name);
|
||||
hi->hi_key = UF2HIKEY(fp);
|
||||
}
|
||||
else if (hash_add(&func_hashtab, UF2HIKEY(fp), "add function") == FAIL)
|
||||
else if (!in_class && hash_add(&func_hashtab,
|
||||
UF2HIKEY(fp), "add function") == FAIL)
|
||||
{
|
||||
free_fp = TRUE;
|
||||
goto erret;
|
||||
@@ -5198,7 +5204,7 @@ ex_function(exarg_T *eap)
|
||||
garray_T lines_to_free;
|
||||
|
||||
ga_init2(&lines_to_free, sizeof(char_u *), 50);
|
||||
(void)define_function(eap, NULL, &lines_to_free, NULL);
|
||||
(void)define_function(eap, NULL, &lines_to_free, FALSE);
|
||||
ga_clear_strings(&lines_to_free);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user