forked from aniani/vim
patch 8.2.1968: Vim9: has() assumes a feature does not change dynamically
Problem: Vim9: has() assumes a feature does not change dynamically. Solution: Check whether a feature may change dynamically. (closes #7265)
This commit is contained in:
@@ -5483,6 +5483,73 @@ f_has(typval_T *argvars, typval_T *rettv)
|
|||||||
rettv->vval.v_number = n;
|
rettv->vval.v_number = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if "feature" can change later.
|
||||||
|
* Also when checking for the feature has side effects, such as loading a DLL.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dynamic_feature(char_u *feature)
|
||||||
|
{
|
||||||
|
return (feature == NULL
|
||||||
|
#if defined(FEAT_BEVAL) && defined(FEAT_GUI_MSWIN)
|
||||||
|
|| STRICMP(feature, "balloon_multiline") == 0
|
||||||
|
#endif
|
||||||
|
#if defined(FEAT_GUI) && defined(FEAT_BROWSE)
|
||||||
|
|| (STRICMP(feature, "browse") == 0 && !gui.in_use)
|
||||||
|
#endif
|
||||||
|
#ifdef VIMDLL
|
||||||
|
|| STRICMP(feature, "filterpipe") == 0
|
||||||
|
#endif
|
||||||
|
#if defined(FEAT_GUI) && !defined(ALWAYS_USE_GUI)
|
||||||
|
// this can only change on Unix where the ":gui" command could be
|
||||||
|
// used.
|
||||||
|
|| (STRICMP(feature, "gui_running") == 0 && !gui.in_use)
|
||||||
|
#endif
|
||||||
|
#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
|
||||||
|
|| STRICMP(feature, "iconv") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_LUA
|
||||||
|
|| STRICMP(feature, "lua") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_MOUSE_GPM
|
||||||
|
|| (STRICMP(feature, "mouse_gpm_enabled") == 0 && !gpm_enabled())
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_MZSCHEME
|
||||||
|
|| STRICMP(feature, "mzscheme") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_NETBEANS_INTG
|
||||||
|
|| STRICMP(feature, "netbeans_enabled") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_PERL
|
||||||
|
|| STRICMP(feature, "perl") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_PYTHON
|
||||||
|
|| STRICMP(feature, "python") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_PYTHON3
|
||||||
|
|| STRICMP(feature, "python3") == 0
|
||||||
|
#endif
|
||||||
|
#if defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3)
|
||||||
|
|| STRICMP(feature, "pythonx") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_RUBY
|
||||||
|
|| STRICMP(feature, "ruby") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_SYN_HL
|
||||||
|
|| STRICMP(feature, "syntax_items") == 0
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_TCL
|
||||||
|
|| STRICMP(feature, "tcl") == 0
|
||||||
|
#endif
|
||||||
|
// once "starting" is zero it will stay that way
|
||||||
|
|| (STRICMP(feature, "vim_starting") == 0 && starting != 0)
|
||||||
|
|| STRICMP(feature, "multi_byte_encoding") == 0
|
||||||
|
#if defined(FEAT_TERMINAL) && defined(MSWIN)
|
||||||
|
|| STRICMP(feature, "conpty") == 0
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "haslocaldir()" function
|
* "haslocaldir()" function
|
||||||
*/
|
*/
|
||||||
|
@@ -16,6 +16,7 @@ win_T *get_optional_window(typval_T *argvars, int idx);
|
|||||||
void execute_redir_str(char_u *value, int value_len);
|
void execute_redir_str(char_u *value, int value_len);
|
||||||
void execute_common(typval_T *argvars, typval_T *rettv, int arg_off);
|
void execute_common(typval_T *argvars, typval_T *rettv, int arg_off);
|
||||||
void f_has(typval_T *argvars, typval_T *rettv);
|
void f_has(typval_T *argvars, typval_T *rettv);
|
||||||
|
int dynamic_feature(char_u *feature);
|
||||||
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
|
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
|
||||||
void range_list_materialize(list_T *list);
|
void range_list_materialize(list_T *list);
|
||||||
float_T vim_round(float_T f);
|
float_T vim_round(float_T f);
|
||||||
|
@@ -629,6 +629,14 @@ def HasSomething()
|
|||||||
endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def HasGuiRunning()
|
||||||
|
if has("gui_running")
|
||||||
|
echo "yes"
|
||||||
|
else
|
||||||
|
echo "no"
|
||||||
|
endif
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_disassemble_const_expr()
|
def Test_disassemble_const_expr()
|
||||||
assert_equal("\nyes", execute('HasEval()'))
|
assert_equal("\nyes", execute('HasEval()'))
|
||||||
var instr = execute('disassemble HasEval')
|
var instr = execute('disassemble HasEval')
|
||||||
@@ -676,6 +684,67 @@ def Test_disassemble_const_expr()
|
|||||||
assert_notmatch('PUSHS "something"', instr)
|
assert_notmatch('PUSHS "something"', instr)
|
||||||
assert_notmatch('PUSHS "less"', instr)
|
assert_notmatch('PUSHS "less"', instr)
|
||||||
assert_notmatch('JUMP', instr)
|
assert_notmatch('JUMP', instr)
|
||||||
|
|
||||||
|
var result: string
|
||||||
|
var instr_expected: string
|
||||||
|
if has('gui')
|
||||||
|
if has('gui_running')
|
||||||
|
# GUI already running, always returns "yes"
|
||||||
|
result = "\nyes"
|
||||||
|
instr_expected = 'HasGuiRunning.*' ..
|
||||||
|
'if has("gui_running")\_s*' ..
|
||||||
|
' echo "yes"\_s*' ..
|
||||||
|
'\d PUSHS "yes"\_s*' ..
|
||||||
|
'\d ECHO 1\_s*' ..
|
||||||
|
'else\_s*' ..
|
||||||
|
' echo "no"\_s*' ..
|
||||||
|
'endif'
|
||||||
|
else
|
||||||
|
result = "\nno"
|
||||||
|
if has('unix')
|
||||||
|
# GUI not running but can start later, call has()
|
||||||
|
instr_expected = 'HasGuiRunning.*' ..
|
||||||
|
'if has("gui_running")\_s*' ..
|
||||||
|
'\d PUSHS "gui_running"\_s*' ..
|
||||||
|
'\d BCALL has(argc 1)\_s*' ..
|
||||||
|
'\d JUMP_IF_FALSE -> \d\_s*' ..
|
||||||
|
' echo "yes"\_s*' ..
|
||||||
|
'\d PUSHS "yes"\_s*' ..
|
||||||
|
'\d ECHO 1\_s*' ..
|
||||||
|
'else\_s*' ..
|
||||||
|
'\d JUMP -> \d\_s*' ..
|
||||||
|
' echo "no"\_s*' ..
|
||||||
|
'\d PUSHS "no"\_s*' ..
|
||||||
|
'\d ECHO 1\_s*' ..
|
||||||
|
'endif'
|
||||||
|
else
|
||||||
|
# GUI not running, always return "no"
|
||||||
|
instr_expected = 'HasGuiRunning.*' ..
|
||||||
|
'if has("gui_running")\_s*' ..
|
||||||
|
' echo "yes"\_s*' ..
|
||||||
|
'else\_s*' ..
|
||||||
|
' echo "no"\_s*' ..
|
||||||
|
'\d PUSHS "no"\_s*' ..
|
||||||
|
'\d ECHO 1\_s*' ..
|
||||||
|
'endif'
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
# GUI not supported, always return "no"
|
||||||
|
result = "\nno"
|
||||||
|
instr_expected = 'HasGuiRunning.*' ..
|
||||||
|
'if has("gui_running")\_s*' ..
|
||||||
|
' echo "yes"\_s*' ..
|
||||||
|
'else\_s*' ..
|
||||||
|
' echo "no"\_s*' ..
|
||||||
|
'\d PUSHS "no"\_s*' ..
|
||||||
|
'\d ECHO 1\_s*' ..
|
||||||
|
'endif'
|
||||||
|
endif
|
||||||
|
|
||||||
|
assert_equal(result, execute('HasGuiRunning()'))
|
||||||
|
instr = execute('disassemble HasGuiRunning')
|
||||||
|
assert_match(instr_expected, instr)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def ReturnInIf(): string
|
def ReturnInIf(): string
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
1968,
|
||||||
/**/
|
/**/
|
||||||
1967,
|
1967,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2620,7 +2620,8 @@ compile_call(
|
|||||||
else if (*s == '\'')
|
else if (*s == '\'')
|
||||||
(void)eval_lit_string(&s, &argvars[0], TRUE);
|
(void)eval_lit_string(&s, &argvars[0], TRUE);
|
||||||
s = skipwhite(s);
|
s = skipwhite(s);
|
||||||
if (*s == ')' && argvars[0].v_type == VAR_STRING)
|
if (*s == ')' && argvars[0].v_type == VAR_STRING
|
||||||
|
&& !dynamic_feature(argvars[0].vval.v_string))
|
||||||
{
|
{
|
||||||
typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
|
typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user