Skip to content

Commit

Permalink
Check the imported variable type properly
Browse files Browse the repository at this point in the history
  • Loading branch information
yegappan committed May 8, 2024
1 parent fb74575 commit 74a2eb3
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 17 deletions.
37 changes: 21 additions & 16 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,12 +1170,10 @@ get_lval_check_access(
static char_u *
get_lval_imported(
lval_T *lp,
typval_T *rettv,
scid_T imp_sid,
char_u *p,
dictitem_T **dip,
int fne_flags,
int vim9script)
int fne_flags)
{
ufunc_T *ufunc;
type_T *type = NULL;
Expand All @@ -1197,16 +1195,6 @@ get_lval_imported(
TRUE) == -1)
goto failed;

if (vim9script && type != NULL)
{
where_T where = WHERE_INIT;

// In a vim9 script, do type check and make sure the variable is
// writable.
if (check_typval_type(type, rettv, where) == FAIL)
goto failed;
}

// Get the typval for the exported item
hashtab_T *ht = &SCRIPT_VARS(imp_sid);
if (ht == NULL)
Expand All @@ -1232,6 +1220,7 @@ get_lval_imported(
goto failed;

lp->ll_tv = &di->di_tv;
lp->ll_valtype = type;

success:
rc = OK;
Expand Down Expand Up @@ -1410,8 +1399,7 @@ get_lval(
if (import != NULL)
{
p++; // skip '.'
p = get_lval_imported(lp, rettv, import->imp_sid, p, &v,
fne_flags, vim9script);
p = get_lval_imported(lp, import->imp_sid, p, &v, fne_flags);
if (p == NULL)
return NULL;
}
Expand Down Expand Up @@ -1754,6 +1742,12 @@ get_lval(
== FAIL)
return NULL;
}

if (!lp->ll_range)
// Indexing a single byte in a blob. So the rhs type is a
// number.
lp->ll_valtype = &t_number;

lp->ll_blob = lp->ll_tv->vval.v_blob;
lp->ll_tv = NULL;
break;
Expand Down Expand Up @@ -1782,7 +1776,7 @@ get_lval(
return NULL;
}

if (lp->ll_valtype != NULL)
if (lp->ll_valtype != NULL && !lp->ll_range)
// use the type of the member
lp->ll_valtype = lp->ll_valtype->tt_member;

Expand Down Expand Up @@ -1896,6 +1890,17 @@ get_lval(
}
}

if (vim9script && lp->ll_valtype != NULL && rettv != NULL)
{
where_T where = WHERE_INIT;

// In a vim9 script, do type check and make sure the variable is
// writable.
if (check_typval_type(lp->ll_valtype, rettv, where) == FAIL)
return NULL;
}


clear_tv(&var1);
lp->ll_name_end = p;
return p;
Expand Down
12 changes: 12 additions & 0 deletions src/testdir/test_blob.vim
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ func Test_blob_assign()
END
call v9.CheckLegacyAndVim9Failure(lines, 'E979:')

let lines =<< trim END
VAR b = 0zDEADBEEF
LET b[0 : 1] = 0x1122
END
call v9.CheckLegacyAndVim9Failure(lines, ['E709:', 'E1012:', 'E709:'])

let lines =<< trim END
VAR b = 0zDEADBEEF
LET b[0] = 0z11
END
call v9.CheckLegacyAndVim9Failure(lines, ['E974:', 'E974:', 'E1012:'])

let lines =<< trim END
VAR b = 0zDEADBEEF
LET b ..= 0z33
Expand Down
2 changes: 1 addition & 1 deletion src/testdir/test_vim9_assign.vim
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ def Test_assign_index()
var bl = 0z11
bl[1] = g:val
END
v9.CheckDefExecAndScriptFailure(lines, 'E1030: Using a String as a Number: "22"')
v9.CheckDefExecAndScriptFailure(lines, ['E1030: Using a String as a Number: "22"', 'E1012: Type mismatch; expected number but got string'])

# should not read the next line when generating "a.b"
var a = {}
Expand Down
61 changes: 61 additions & 0 deletions src/testdir/test_vim9_import.vim
Original file line number Diff line number Diff line change
Expand Up @@ -3222,4 +3222,65 @@ def Test_autoload_import_dict_func()
&rtp = save_rtp
enddef

" Test for changing the value of an imported Dict item
def Test_set_imported_dict_item()
var lines =<< trim END
vim9script
export var dict1: dict<bool> = {bflag: false}
export var dict2: dict<dict<bool>> = {x: {bflag: false}}
END
writefile(lines, 'XimportedDict.vim', 'D')

lines =<< trim END
vim9script
import './XimportedDict.vim'
assert_equal(XimportedDict.dict1.bflag, false)
XimportedDict.dict1.bflag = true
assert_equal(XimportedDict.dict1.bflag, true)
XimportedDict.dict2.x.bflag = true
assert_equal(XimportedDict.dict2.x.bflag, true)
assert_equal('bool', typename(XimportedDict.dict1.bflag))
assert_equal('bool', typename(XimportedDict.dict2.x.bflag))
assert_equal('bool', typename(XimportedDict.dict2['x'].bflag))
assert_equal('bool', typename(XimportedDict.dict2.x['bflag']))

assert_equal(XimportedDict.dict1['bflag'], true)
XimportedDict.dict1['bflag'] = false
assert_equal(XimportedDict.dict1.bflag, false)
XimportedDict.dict2['x']['bflag'] = false
assert_equal(XimportedDict.dict2['x'].bflag, false)
END
v9.CheckScriptSuccess(lines)

lines =<< trim END
vim9script
import './XimportedDict.vim'
XimportedDict.dict2.x.bflag = []
END
v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected bool but got list<any>', 3)
enddef

" Test for changing the value of an imported class member
def Test_set_imported_class_member()
var lines =<< trim END
vim9script
export class Config
public static var option = false
endclass
END
writefile(lines, 'XimportedClass.vim', 'D')

lines =<< trim END
vim9script
import './XimportedClass.vim' as foo
type FooConfig = foo.Config
assert_equal(false, FooConfig.option)
assert_equal(false, foo.Config.option)
foo.Config.option = true
assert_equal(true, foo.Config.option)
assert_equal(true, FooConfig.option)
END
v9.CheckScriptSuccess(lines)
enddef

" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker

0 comments on commit 74a2eb3

Please sign in to comment.