Mercurial > vim
diff src/vim9class.c @ 33047:9ef43d02dd8f v9.0.1814
patch 9.0.1814: Vim9 no error on duplicate object member var
Commit: https://github.com/vim/vim/commit/2ba9d2e14e3633c92a32abba2a12533f93fefbf5
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Mon Aug 28 21:26:23 2023 +0200
patch 9.0.1814: Vim9 no error on duplicate object member var
Problem: Vim9 no error on duplicate object member var
Solution: detect duplicate members and error out
closes: #12938
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 28 Aug 2023 21:30:10 +0200 |
parents | 1d18c7fe609f |
children | d42927c6e556 |
line wrap: on
line diff
--- a/src/vim9class.c +++ b/src/vim9class.c @@ -24,7 +24,7 @@ /* * Parse a member declaration, both object and class member. * Returns OK or FAIL. When OK then "varname_end" is set to just after the - * variable name and "type_ret" is set to the decleared or detected type. + * variable name and "type_ret" is set to the declared or detected type. * "init_expr" is set to the initialisation expression (allocated), if there is * one. For an interface "init_expr" is NULL. */ @@ -490,6 +490,52 @@ check_func_arg_names( } /* + * Returns TRUE if the member "varname" is already defined. + */ + static int +is_duplicate_member(garray_T *mgap, char_u *varname, char_u *varname_end) +{ + char_u *pstr = (*varname == '_') ? varname + 1 : varname; + + for (int i = 0; i < mgap->ga_len; ++i) + { + ocmember_T *m = ((ocmember_T *)mgap->ga_data) + i; + char_u *qstr = *m->ocm_name == '_' ? m->ocm_name + 1 : m->ocm_name; + if (STRNCMP(pstr, qstr, varname_end - pstr) == 0) + { + char_u *name = vim_strnsave(varname, varname_end - varname); + semsg(_(e_duplicate_member_str), name); + vim_free(name); + return TRUE; + } + } + + return FALSE; +} + +/* + * Returns TRUE if the method "name" is already defined. + */ + static int +is_duplicate_method(garray_T *fgap, char_u *name) +{ + char_u *pstr = (*name == '_') ? name + 1 : name; + + for (int i = 0; i < fgap->ga_len; ++i) + { + char_u *n = ((ufunc_T **)fgap->ga_data)[i]->uf_name; + char_u *qstr = *n == '_' ? n + 1 : n; + if (STRCMP(pstr, qstr) == 0) + { + semsg(_(e_duplicate_function_str), name); + return TRUE; + } + } + + return FALSE; +} + +/* * Update the interface class lookup table for the member index on the * interface to the member index in the class implementing the interface. * And a lookup table for the object method index on the interface @@ -1080,6 +1126,11 @@ early_ret: semsg(_(e_invalid_object_member_declaration_str), p); break; } + if (has_static) + { + emsg(_(e_static_cannot_be_followed_by_this)); + break; + } char_u *varname = p + 5; char_u *varname_end = NULL; type_T *type = NULL; @@ -1088,6 +1139,11 @@ early_ret: &varname_end, &type_list, &type, is_class ? &init_expr: NULL) == FAIL) break; + if (is_duplicate_member(&objmembers, varname, varname_end)) + { + vim_free(init_expr); + break; + } if (add_member(&objmembers, varname, varname_end, has_public, type, init_expr) == FAIL) { @@ -1154,17 +1210,8 @@ early_ret: garray_T *fgap = has_static || is_new ? &classfunctions : &objmethods; // Check the name isn't used already. - for (int i = 0; i < fgap->ga_len; ++i) - { - char_u *n = ((ufunc_T **)fgap->ga_data)[i]->uf_name; - char_u *pstr = *name == '_' ? name + 1 : name; - char_u *qstr = *n == '_' ? n + 1 : n; - if (STRCMP(pstr, qstr) == 0) - { - semsg(_(e_duplicate_function_str), name); - break; - } - } + if (is_duplicate_method(fgap, name)) + break; if (ga_grow(fgap, 1) == OK) { @@ -1197,6 +1244,11 @@ early_ret: &varname_end, &type_list, &type, is_class ? &init_expr : NULL) == FAIL) break; + if (is_duplicate_member(&classmembers, varname, varname_end)) + { + vim_free(init_expr); + break; + } if (add_member(&classmembers, varname, varname_end, has_public, type, init_expr) == FAIL) {