summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/evalfunc.c67
-rw-r--r--src/proto/evalfunc.pro1
-rw-r--r--src/testdir/test_vim9_disassemble.vim69
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c3
5 files changed, 141 insertions, 1 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 5cc9ad755..6a43120d4 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -5484,6 +5484,73 @@ f_has(typval_T *argvars, typval_T *rettv)
}
/*
+ * 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
*/
static void
diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro
index c649b861b..562a7c83d 100644
--- a/src/proto/evalfunc.pro
+++ b/src/proto/evalfunc.pro
@@ -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_common(typval_T *argvars, typval_T *rettv, int arg_off);
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 range_list_materialize(list_T *list);
float_T vim_round(float_T f);
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 66ac9544b..07974d39a 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -629,6 +629,14 @@ def HasSomething()
endif
enddef
+def HasGuiRunning()
+ if has("gui_running")
+ echo "yes"
+ else
+ echo "no"
+ endif
+enddef
+
def Test_disassemble_const_expr()
assert_equal("\nyes", execute('HasEval()'))
var instr = execute('disassemble HasEval')
@@ -676,6 +684,67 @@ def Test_disassemble_const_expr()
assert_notmatch('PUSHS "something"', instr)
assert_notmatch('PUSHS "less"', 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
def ReturnInIf(): string
diff --git a/src/version.c b/src/version.c
index fe89862d4..40f385164 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1968,
+/**/
1967,
/**/
1966,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 5ade42ad5..bda1ab3e4 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2620,7 +2620,8 @@ compile_call(
else if (*s == '\'')
(void)eval_lit_string(&s, &argvars[0], TRUE);
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];