Skip to content

Commit

Permalink
patch 9.0.1185: using class from imported script not tested
Browse files Browse the repository at this point in the history
Problem:    Using class from imported script not tested.
Solution:   Add tests.  Implement what is missing.
  • Loading branch information
brammool committed Jan 12, 2023
1 parent a94bd9d commit a86655a
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 7 deletions.
25 changes: 25 additions & 0 deletions src/evalvars.c
Expand Up @@ -3104,6 +3104,31 @@ eval_variable(
return ret;
}

/*
* Get the value of internal variable "name", also handling "import.name".
* Return OK or FAIL. If OK is returned "rettv" must be cleared.
*/
int
eval_variable_import(
char_u *name,
typval_T *rettv)
{
char_u *s = name;
while (ASCII_ISALNUM(*s) || *s == '_')
++s;
int len = (int)(s - name);

if (eval_variable(name, len, 0, rettv, NULL, EVAL_VAR_IMPORT) == FAIL)
return FAIL;
if (rettv->v_type == VAR_ANY && *s == '.')
{
int sid = rettv->vval.v_number;
return eval_variable(s + 1, 0, sid, rettv, NULL, 0);
}
return OK;
}


/*
* Check if variable "name[len]" is a local variable or an argument.
* If so, "*eval_lavars_used" is set to TRUE.
Expand Down
1 change: 1 addition & 0 deletions src/proto/evalvars.pro
Expand Up @@ -60,6 +60,7 @@ char_u *v_exception(char_u *oldval);
char_u *v_throwpoint(char_u *oldval);
char_u *set_cmdarg(exarg_T *eap, char_u *oldarg);
int eval_variable(char_u *name, int len, scid_T sid, typval_T *rettv, dictitem_T **dip, int flags);
int eval_variable_import(char_u *name, typval_T *rettv);
void check_vars(char_u *name, int len);
dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
dictitem_T *find_var_also_in_script(char_u *name, hashtab_T **htp, int no_autoload);
Expand Down
22 changes: 22 additions & 0 deletions src/testdir/test_vim9_class.vim
Expand Up @@ -974,5 +974,27 @@ def Test_class_extends()
v9.CheckScriptSuccess(lines)
enddef

def Test_class_import()
var lines =<< trim END
vim9script
export class Animal
this.kind: string
this.name: string
endclass
END
writefile(lines, 'Xanimal.vim', 'D')

lines =<< trim END
vim9script
import './Xanimal.vim' as animal

var a: animal.Animal
a = animal.Animal.new('fish', 'Eric')
assert_equal('fish', a.kind)
assert_equal('Eric', a.name)
END
v9.CheckScriptSuccess(lines)
enddef


" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -695,6 +695,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1185,
/**/
1184,
/**/
Expand Down
11 changes: 8 additions & 3 deletions src/vim9class.c
Expand Up @@ -244,9 +244,13 @@ ex_class(exarg_T *eap)
}
char_u *name_start = arg;

// "export class" gets used when creating the class, don't use "is_export"
// for the items inside the class.
int class_export = is_export;
is_export = FALSE;

// TODO:
// generics: <Tkey, Tentry>
// handle "is_export" if it is set

// Name for "extends BaseClass"
char_u *extends = NULL;
Expand Down Expand Up @@ -558,7 +562,7 @@ ex_class(exarg_T *eap)
{
typval_T tv;
tv.v_type = VAR_UNKNOWN;
if (eval_variable(extends, 0, 0, &tv, NULL, EVAL_VAR_IMPORT) == FAIL)
if (eval_variable_import(extends, &tv) == FAIL)
{
semsg(_(e_class_name_not_found_str), extends);
success = FALSE;
Expand Down Expand Up @@ -594,7 +598,7 @@ ex_class(exarg_T *eap)
char_u *impl = ((char_u **)ga_impl.ga_data)[i];
typval_T tv;
tv.v_type = VAR_UNKNOWN;
if (eval_variable(impl, 0, 0, &tv, NULL, EVAL_VAR_IMPORT) == FAIL)
if (eval_variable_import(impl, &tv) == FAIL)
{
semsg(_(e_interface_name_not_found_str), impl);
success = FALSE;
Expand Down Expand Up @@ -930,6 +934,7 @@ ex_class(exarg_T *eap)
typval_T tv;
tv.v_type = VAR_CLASS;
tv.vval.v_class = cl;
is_export = class_export;
set_var_const(cl->class_name, current_sctx.sc_sid,
NULL, &tv, FALSE, ASSIGN_DECL, 0);
return;
Expand Down
10 changes: 6 additions & 4 deletions src/vim9type.c
Expand Up @@ -982,7 +982,9 @@ skip_type(char_u *start, int optional)

if (optional && *p == '?')
++p;
while (ASCII_ISALNUM(*p) || *p == '_')

// Also skip over "." for imported classes: "import.ClassName".
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '.')
++p;

// Skip over "<type>"; this is permissive about white space.
Expand Down Expand Up @@ -1091,7 +1093,7 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
char_u *p = *arg;
size_t len;

// skip over the first word
// Skip over the first word.
while (ASCII_ISALNUM(*p) || *p == '_')
++p;
len = p - *arg;
Expand Down Expand Up @@ -1293,10 +1295,10 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
break;
}

// It can be a class or interface name.
// It can be a class or interface name, possibly imported.
typval_T tv;
tv.v_type = VAR_UNKNOWN;
if (eval_variable(*arg, (int)len, 0, &tv, NULL, EVAL_VAR_IMPORT) == OK)
if (eval_variable_import(*arg, &tv) == OK)
{
if (tv.v_type == VAR_CLASS && tv.vval.v_class != NULL)
{
Expand Down

2 comments on commit a86655a

@bfrg
Copy link
Contributor

@bfrg bfrg commented on a86655a Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this deserves a separate issue but the following still doesn't work:

var a: animal.Animal = animal.Animal.new('fish', 'nemo')

In your test above the declaration and assignment are on separate lines.

@brammool
Copy link
Contributor Author

@brammool brammool commented on a86655a Jan 12, 2023 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.