mirror of
https://github.com/vim/vim.git
synced 2025-07-25 10:54:51 -04:00
patch 8.2.2225: Vim9: error when using :import in legacy script twice
Problem: Vim9: error when using :import in legacy script twice. Solution: Make it possible to redefine an import when reloading.
This commit is contained in:
parent
07a65d26e7
commit
a629495530
@ -2531,7 +2531,7 @@ eval_variable(
|
|||||||
rettv->vval.v_string = vim_strsave(import->imp_funcname);
|
rettv->vval.v_string = vim_strsave(import->imp_funcname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (import->imp_all)
|
else if (import->imp_flags & IMP_FLAGS_STAR)
|
||||||
{
|
{
|
||||||
emsg("Sorry, 'import * as X' not implemented yet");
|
emsg("Sorry, 'import * as X' not implemented yet");
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
|
@ -4,6 +4,7 @@ void ex_vim9script(exarg_T *eap);
|
|||||||
int not_in_vim9(exarg_T *eap);
|
int not_in_vim9(exarg_T *eap);
|
||||||
void ex_export(exarg_T *eap);
|
void ex_export(exarg_T *eap);
|
||||||
void free_imports_and_script_vars(int sid);
|
void free_imports_and_script_vars(int sid);
|
||||||
|
void mark_imports_for_reload(int sid);
|
||||||
void ex_import(exarg_T *eap);
|
void ex_import(exarg_T *eap);
|
||||||
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx);
|
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx);
|
||||||
char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx);
|
char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx);
|
||||||
|
@ -1778,17 +1778,19 @@ typedef struct {
|
|||||||
char_u *imp_name; // name imported as (allocated)
|
char_u *imp_name; // name imported as (allocated)
|
||||||
int imp_sid; // script ID of "from"
|
int imp_sid; // script ID of "from"
|
||||||
|
|
||||||
// for "import * as Name", "imp_name" is "Name"
|
int imp_flags; // IMP_FLAGS_ values
|
||||||
int imp_all;
|
|
||||||
|
|
||||||
// for variable
|
// for a variable
|
||||||
type_T *imp_type;
|
type_T *imp_type;
|
||||||
int imp_var_vals_idx; // index in sn_var_vals of "from"
|
int imp_var_vals_idx; // index in sn_var_vals of "from"
|
||||||
|
|
||||||
// for function
|
// for a function
|
||||||
char_u *imp_funcname; // user func name (NOT allocated)
|
char_u *imp_funcname; // user func name (NOT allocated)
|
||||||
} imported_T;
|
} imported_T;
|
||||||
|
|
||||||
|
#define IMP_FLAGS_STAR 1 // using "import * as Name"
|
||||||
|
#define IMP_FLAGS_RELOAD 2 // script reloaded, OK to redefine
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Info about an already sourced scripts.
|
* Info about an already sourced scripts.
|
||||||
*/
|
*/
|
||||||
|
@ -899,6 +899,16 @@ def Test_vim9_import_export()
|
|||||||
writefile(import_star_as_lines_dot_space, 'Ximport.vim')
|
writefile(import_star_as_lines_dot_space, 'Ximport.vim')
|
||||||
assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func')
|
assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func')
|
||||||
|
|
||||||
|
var import_star_as_duplicated =<< trim END
|
||||||
|
vim9script
|
||||||
|
import * as Export from './Xexport.vim'
|
||||||
|
var some = 'other'
|
||||||
|
import * as Export from './Xexport.vim'
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
writefile(import_star_as_duplicated, 'Ximport.vim')
|
||||||
|
assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim')
|
||||||
|
|
||||||
var import_star_as_lines_missing_name =<< trim END
|
var import_star_as_lines_missing_name =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
import * as Export from './Xexport.vim'
|
import * as Export from './Xexport.vim'
|
||||||
@ -1160,9 +1170,15 @@ enddef
|
|||||||
|
|
||||||
def Test_vim9script_reload_noclear()
|
def Test_vim9script_reload_noclear()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
export var exported = 'thexport'
|
||||||
|
END
|
||||||
|
writefile(lines, 'XExportReload')
|
||||||
|
lines =<< trim END
|
||||||
vim9script noclear
|
vim9script noclear
|
||||||
g:loadCount += 1
|
g:loadCount += 1
|
||||||
var s:reloaded = 'init'
|
var s:reloaded = 'init'
|
||||||
|
import exported from './XExportReload'
|
||||||
|
|
||||||
def Again(): string
|
def Again(): string
|
||||||
return 'again'
|
return 'again'
|
||||||
@ -1174,7 +1190,7 @@ def Test_vim9script_reload_noclear()
|
|||||||
var s:notReloaded = 'yes'
|
var s:notReloaded = 'yes'
|
||||||
s:reloaded = 'first'
|
s:reloaded = 'first'
|
||||||
def g:Values(): list<string>
|
def g:Values(): list<string>
|
||||||
return [s:reloaded, s:notReloaded, Again(), Once()]
|
return [s:reloaded, s:notReloaded, Again(), Once(), exported]
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Once(): string
|
def Once(): string
|
||||||
@ -1185,15 +1201,16 @@ def Test_vim9script_reload_noclear()
|
|||||||
g:loadCount = 0
|
g:loadCount = 0
|
||||||
source XReloaded
|
source XReloaded
|
||||||
assert_equal(1, g:loadCount)
|
assert_equal(1, g:loadCount)
|
||||||
assert_equal(['first', 'yes', 'again', 'once'], g:Values())
|
assert_equal(['first', 'yes', 'again', 'once', 'thexport'], g:Values())
|
||||||
source XReloaded
|
source XReloaded
|
||||||
assert_equal(2, g:loadCount)
|
assert_equal(2, g:loadCount)
|
||||||
assert_equal(['init', 'yes', 'again', 'once'], g:Values())
|
assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values())
|
||||||
source XReloaded
|
source XReloaded
|
||||||
assert_equal(3, g:loadCount)
|
assert_equal(3, g:loadCount)
|
||||||
assert_equal(['init', 'yes', 'again', 'once'], g:Values())
|
assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values())
|
||||||
|
|
||||||
delete('Xreloaded')
|
delete('Xreloaded')
|
||||||
|
delete('XExportReload')
|
||||||
delfunc g:Values
|
delfunc g:Values
|
||||||
unlet g:loadCount
|
unlet g:loadCount
|
||||||
enddef
|
enddef
|
||||||
@ -2762,6 +2779,17 @@ def Test_forward_declaration()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_source_vim9_from_legacy()
|
def Test_source_vim9_from_legacy()
|
||||||
|
var vim9_lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
var local = 'local'
|
||||||
|
g:global = 'global'
|
||||||
|
export var exported = 'exported'
|
||||||
|
export def GetText(): string
|
||||||
|
return 'text'
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
writefile(vim9_lines, 'Xvim9_script.vim')
|
||||||
|
|
||||||
var legacy_lines =<< trim END
|
var legacy_lines =<< trim END
|
||||||
source Xvim9_script.vim
|
source Xvim9_script.vim
|
||||||
|
|
||||||
@ -2783,19 +2811,7 @@ def Test_source_vim9_from_legacy()
|
|||||||
END
|
END
|
||||||
writefile(legacy_lines, 'Xlegacy_script.vim')
|
writefile(legacy_lines, 'Xlegacy_script.vim')
|
||||||
|
|
||||||
var vim9_lines =<< trim END
|
|
||||||
vim9script
|
|
||||||
var local = 'local'
|
|
||||||
g:global = 'global'
|
|
||||||
export var exported = 'exported'
|
|
||||||
export def GetText(): string
|
|
||||||
return 'text'
|
|
||||||
enddef
|
|
||||||
END
|
|
||||||
writefile(vim9_lines, 'Xvim9_script.vim')
|
|
||||||
|
|
||||||
source Xlegacy_script.vim
|
source Xlegacy_script.vim
|
||||||
|
|
||||||
assert_equal('global', g:global)
|
assert_equal('global', g:global)
|
||||||
unlet g:global
|
unlet g:global
|
||||||
|
|
||||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2225,
|
||||||
/**/
|
/**/
|
||||||
2224,
|
2224,
|
||||||
/**/
|
/**/
|
||||||
|
@ -2416,7 +2416,7 @@ compile_load_scriptvar(
|
|||||||
import = find_imported(name, 0, cctx);
|
import = find_imported(name, 0, cctx);
|
||||||
if (import != NULL)
|
if (import != NULL)
|
||||||
{
|
{
|
||||||
if (import->imp_all)
|
if (import->imp_flags & IMP_FLAGS_STAR)
|
||||||
{
|
{
|
||||||
char_u *p = skipwhite(*end);
|
char_u *p = skipwhite(*end);
|
||||||
char_u *exp_name;
|
char_u *exp_name;
|
||||||
|
@ -173,6 +173,24 @@ free_imports_and_script_vars(int sid)
|
|||||||
clear_type_list(&si->sn_type_list);
|
clear_type_list(&si->sn_type_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark all imports as possible to redefine. Used when a script is loaded
|
||||||
|
* again but not cleared.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mark_imports_for_reload(int sid)
|
||||||
|
{
|
||||||
|
scriptitem_T *si = SCRIPT_ITEM(sid);
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
|
||||||
|
{
|
||||||
|
imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx;
|
||||||
|
|
||||||
|
imp->imp_flags |= IMP_FLAGS_RELOAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":import Item from 'filename'"
|
* ":import Item from 'filename'"
|
||||||
* ":import Item as Alias from 'filename'"
|
* ":import Item as Alias from 'filename'"
|
||||||
@ -459,15 +477,29 @@ handle_import(
|
|||||||
|
|
||||||
if (*arg_start == '*')
|
if (*arg_start == '*')
|
||||||
{
|
{
|
||||||
imported_T *imported = new_imported(gap != NULL ? gap
|
imported_T *imported;
|
||||||
: &SCRIPT_ITEM(import_sid)->sn_imports);
|
|
||||||
|
|
||||||
|
imported = find_imported(as_name, STRLEN(as_name), cctx);
|
||||||
|
if (imported != NULL && imported->imp_sid == sid)
|
||||||
|
{
|
||||||
|
if (imported->imp_flags & IMP_FLAGS_RELOAD)
|
||||||
|
// import already defined on a previous script load
|
||||||
|
imported->imp_flags &= ~IMP_FLAGS_RELOAD;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
semsg(_(e_name_already_defined_str), as_name);
|
||||||
|
goto erret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imported = new_imported(gap != NULL ? gap
|
||||||
|
: &SCRIPT_ITEM(import_sid)->sn_imports);
|
||||||
if (imported == NULL)
|
if (imported == NULL)
|
||||||
goto erret;
|
goto erret;
|
||||||
imported->imp_name = as_name;
|
imported->imp_name = as_name;
|
||||||
as_name = NULL;
|
as_name = NULL;
|
||||||
imported->imp_sid = sid;
|
imported->imp_sid = sid;
|
||||||
imported->imp_all = TRUE;
|
imported->imp_flags = IMP_FLAGS_STAR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -479,6 +511,7 @@ handle_import(
|
|||||||
for (i = 0; i < names.ga_len; ++i)
|
for (i = 0; i < names.ga_len; ++i)
|
||||||
{
|
{
|
||||||
char_u *name = ((char_u **)names.ga_data)[i];
|
char_u *name = ((char_u **)names.ga_data)[i];
|
||||||
|
size_t len = STRLEN(name);
|
||||||
int idx;
|
int idx;
|
||||||
imported_T *imported;
|
imported_T *imported;
|
||||||
ufunc_T *ufunc = NULL;
|
ufunc_T *ufunc = NULL;
|
||||||
@ -489,28 +522,47 @@ handle_import(
|
|||||||
if (idx < 0 && ufunc == NULL)
|
if (idx < 0 && ufunc == NULL)
|
||||||
goto erret;
|
goto erret;
|
||||||
|
|
||||||
if (check_defined(name, STRLEN(name), cctx) == FAIL)
|
// If already imported with the same propertis and the
|
||||||
goto erret;
|
// IMP_FLAGS_RELOAD set then we keep that entry. Otherwise create
|
||||||
|
// a new one (and give an error for an existing import).
|
||||||
imported = new_imported(gap != NULL ? gap
|
imported = find_imported(name, len, cctx);
|
||||||
: &SCRIPT_ITEM(import_sid)->sn_imports);
|
if (imported != NULL
|
||||||
if (imported == NULL)
|
&& (imported->imp_flags & IMP_FLAGS_RELOAD)
|
||||||
goto erret;
|
&& imported->imp_sid == sid
|
||||||
|
&& (idx >= 0
|
||||||
// TODO: check for "as" following
|
? (equal_type(imported->imp_type, type)
|
||||||
// imported->imp_name = vim_strsave(as_name);
|
&& imported->imp_var_vals_idx == idx)
|
||||||
imported->imp_name = name;
|
: (equal_type(imported->imp_type, ufunc->uf_func_type)
|
||||||
((char_u **)names.ga_data)[i] = NULL;
|
&& STRCMP(imported->imp_funcname,
|
||||||
imported->imp_sid = sid;
|
ufunc->uf_name) == 0)))
|
||||||
if (idx >= 0)
|
|
||||||
{
|
{
|
||||||
imported->imp_type = type;
|
imported->imp_flags &= ~IMP_FLAGS_RELOAD;
|
||||||
imported->imp_var_vals_idx = idx;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
imported->imp_type = ufunc->uf_func_type;
|
if (check_defined(name, len, cctx) == FAIL)
|
||||||
imported->imp_funcname = ufunc->uf_name;
|
goto erret;
|
||||||
|
|
||||||
|
imported = new_imported(gap != NULL ? gap
|
||||||
|
: &SCRIPT_ITEM(import_sid)->sn_imports);
|
||||||
|
if (imported == NULL)
|
||||||
|
goto erret;
|
||||||
|
|
||||||
|
// TODO: check for "as" following
|
||||||
|
// imported->imp_name = vim_strsave(as_name);
|
||||||
|
imported->imp_name = name;
|
||||||
|
((char_u **)names.ga_data)[i] = NULL;
|
||||||
|
imported->imp_sid = sid;
|
||||||
|
if (idx >= 0)
|
||||||
|
{
|
||||||
|
imported->imp_type = type;
|
||||||
|
imported->imp_var_vals_idx = idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
imported->imp_type = ufunc->uf_func_type;
|
||||||
|
imported->imp_funcname = ufunc->uf_name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user