aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/debugger.c22
-rw-r--r--test/old/testdir/test_debugger.vim268
-rw-r--r--test/old/testdir/test_lambda.vim1
3 files changed, 275 insertions, 16 deletions
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index 31aad11d60..bfb15d59f5 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -230,7 +230,7 @@ void do_debug(char *cmd)
}
if (last_cmd != 0) {
- // Execute debug command: decided where to break next and return.
+ // Execute debug command: decide where to break next and return.
switch (last_cmd) {
case CMD_CONT:
debug_break_level = -1;
@@ -475,6 +475,7 @@ static garray_T dbg_breakp = { 0, 0, sizeof(struct debuggy), 4, NULL };
#define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx])
#define DEBUGGY(gap, idx) (((struct debuggy *)(gap)->ga_data)[idx])
static int last_breakp = 0; // nr of last defined breakpoint
+static bool has_expr_breakpoint = false;
// Profiling uses file and func names similar to breakpoints.
static garray_T prof_ga = { 0, 0, sizeof(struct debuggy), 4, NULL };
@@ -550,7 +551,7 @@ static int dbg_parsearg(char *arg, garray_T *gap)
}
if (bp->dbg_type == DBG_FUNC) {
- bp->dbg_name = xstrdup(p);
+ bp->dbg_name = xstrdup(strncmp(p, "g:", 2) == 0 ? p + 2 : p);
} else if (here) {
bp->dbg_name = xstrdup(curbuf->b_ffname);
} else if (bp->dbg_type == DBG_EXPR) {
@@ -620,6 +621,9 @@ void ex_breakadd(exarg_T *eap)
// DBG_EXPR
DEBUGGY(gap, gap->ga_len++).dbg_nr = ++last_breakp;
debug_tick++;
+ if (gap == &dbg_breakp) {
+ has_expr_breakpoint = true;
+ }
}
}
@@ -633,6 +637,17 @@ void ex_debuggreedy(exarg_T *eap)
}
}
+static void update_has_expr_breakpoint(void)
+{
+ has_expr_breakpoint = false;
+ for (int i = 0; i < dbg_breakp.ga_len; i++) {
+ if (BREAKP(i).dbg_type == DBG_EXPR) {
+ has_expr_breakpoint = true;
+ break;
+ }
+ }
+}
+
/// ":breakdel" and ":profdel".
void ex_breakdel(exarg_T *eap)
{
@@ -708,6 +723,9 @@ void ex_breakdel(exarg_T *eap)
if (GA_EMPTY(gap)) {
ga_clear(gap);
}
+ if (gap == &dbg_breakp) {
+ update_has_expr_breakpoint();
+ }
}
/// ":breaklist".
diff --git a/test/old/testdir/test_debugger.vim b/test/old/testdir/test_debugger.vim
index ba3f4715ca..7ac45a0bd4 100644
--- a/test/old/testdir/test_debugger.vim
+++ b/test/old/testdir/test_debugger.vim
@@ -73,6 +73,13 @@ func Test_Debugger()
endtry
return var1
endfunc
+ def Vim9Func()
+ for cmd in ['confirm', 'xxxxxxx']
+ for _ in [1, 2]
+ echo cmd
+ endfor
+ endfor
+ enddef
END
call writefile(lines, 'Xtest.vim')
@@ -298,6 +305,14 @@ func Test_Debugger()
\ 'line 5: catch'])
call RunDbgCmd(buf, 'c')
+ " Test showing local variable in :def function
+ call RunDbgCmd(buf, ':breakadd func 2 Vim9Func')
+ call RunDbgCmd(buf, ':call Vim9Func()', ['line 2: for _ in [1, 2]'])
+ call RunDbgCmd(buf, 'next', ['line 2: for _ in [1, 2]'])
+ call RunDbgCmd(buf, 'echo cmd', ['confirm'])
+ call RunDbgCmd(buf, 'breakdel *')
+ call RunDbgCmd(buf, 'cont')
+
" Test for :quit
call RunDbgCmd(buf, ':debug echo Foo()')
call RunDbgCmd(buf, 'breakdel *')
@@ -880,7 +895,7 @@ func Test_Backtrace_DefFunction()
CheckCWD
let file1 =<< trim END
vim9script
- import File2Function from './Xtest2.vim'
+ import './Xtest2.vim' as imp
def SourceAnotherFile()
source Xtest2.vim
@@ -888,10 +903,11 @@ func Test_Backtrace_DefFunction()
def CallAFunction()
SourceAnotherFile()
- File2Function()
+ imp.File2Function()
enddef
def g:GlobalFunction()
+ var some = "some var"
CallAFunction()
enddef
@@ -923,19 +939,22 @@ func Test_Backtrace_DefFunction()
\ ':debug call GlobalFunction()',
\ ['cmd: call GlobalFunction()'])
- " FIXME: Vim9 lines are not debugged!
- call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
+ call RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
+ call RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
+ call RunDbgCmd(buf, 'echo some', ['some var'])
- " But they do appear in the backtrace
call RunDbgCmd(buf, 'backtrace', [
\ '\V>backtrace',
- \ '\V 2 function GlobalFunction[1]',
- \ '\V 1 <SNR>\.\*_CallAFunction[1]',
- \ '\V->0 <SNR>\.\*_SourceAnotherFile',
- \ '\Vline 1: source Xtest2.vim'],
+ \ '\V->0 function GlobalFunction',
+ \ '\Vline 2: CallAFunction()',
+ \ ],
\ #{match: 'pattern'})
-
+ call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
+ call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
+ " Repeated line, because we fist are in the compiled function before the
+ " EXEC and then in do_cmdline() before the :source command.
+ call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
call RunDbgCmd(buf, 'step', ['line 1: vim9script'])
call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
@@ -944,7 +963,7 @@ func Test_Backtrace_DefFunction()
call RunDbgCmd(buf, 'step', ['line 14: File2Function()'])
call RunDbgCmd(buf, 'backtrace', [
\ '\V>backtrace',
- \ '\V 3 function GlobalFunction[1]',
+ \ '\V 3 function GlobalFunction[2]',
\ '\V 2 <SNR>\.\*_CallAFunction[1]',
\ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
\ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
@@ -952,22 +971,242 @@ func Test_Backtrace_DefFunction()
\ #{match: 'pattern'})
" Don't step into compiled functions...
- call RunDbgCmd(buf, 'step', ['line 15: End of sourced file'])
+ call RunDbgCmd(buf, 'next', ['line 15: End of sourced file'])
call RunDbgCmd(buf, 'backtrace', [
\ '\V>backtrace',
- \ '\V 3 function GlobalFunction[1]',
+ \ '\V 3 function GlobalFunction[2]',
\ '\V 2 <SNR>\.\*_CallAFunction[1]',
\ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
\ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
\ '\Vline 15: End of sourced file'],
\ #{match: 'pattern'})
-
call StopVimInTerminal(buf)
call delete('Xtest1.vim')
call delete('Xtest2.vim')
endfunc
+func Test_DefFunction_expr()
+ CheckRunVimInTerminal
+ CheckCWD
+ let file3 =<< trim END
+ vim9script
+ g:someVar = "foo"
+ def g:ChangeVar()
+ g:someVar = "bar"
+ echo "changed"
+ enddef
+ defcompile
+ END
+ call writefile(file3, 'Xtest3.vim')
+ let buf = RunVimInTerminal('-S Xtest3.vim', {})
+
+ call RunDbgCmd(buf, ':breakadd expr g:someVar')
+ call RunDbgCmd(buf, ':call g:ChangeVar()', ['Oldval = "''foo''"', 'Newval = "''bar''"', 'function ChangeVar', 'line 2: echo "changed"'])
+
+ call StopVimInTerminal(buf)
+ call delete('Xtest3.vim')
+endfunc
+
+func Test_debug_def_and_legacy_function()
+ CheckRunVimInTerminal
+ CheckCWD
+ let file =<< trim END
+ vim9script
+ def g:SomeFunc()
+ echo "here"
+ echo "and"
+ echo "there"
+ breakadd func 2 LocalFunc
+ LocalFunc()
+ enddef
+
+ def LocalFunc()
+ echo "first"
+ echo "second"
+ breakadd func LegacyFunc
+ LegacyFunc()
+ enddef
+
+ func LegacyFunc()
+ echo "legone"
+ echo "legtwo"
+ endfunc
+
+ breakadd func 2 g:SomeFunc
+ END
+ call writefile(file, 'XtestDebug.vim')
+
+ let buf = RunVimInTerminal('-S XtestDebug.vim', {})
+
+ call RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
+ call RunDbgCmd(buf,'next', ['line 3: echo "there"'])
+ call RunDbgCmd(buf,'next', ['line 4: breakadd func 2 LocalFunc'])
+
+ " continue, next breakpoint is in LocalFunc()
+ call RunDbgCmd(buf,'cont', ['line 2: echo "second"'])
+
+ " continue, next breakpoint is in LegacyFunc()
+ call RunDbgCmd(buf,'cont', ['line 1: echo "legone"'])
+
+ call RunDbgCmd(buf, 'cont')
+
+ call StopVimInTerminal(buf)
+ call delete('XtestDebug.vim')
+endfunc
+
+func Test_debug_def_function()
+ CheckRunVimInTerminal
+ CheckCWD
+ let file =<< trim END
+ vim9script
+ def g:Func()
+ var n: number
+ def Closure(): number
+ return n + 3
+ enddef
+ n += Closure()
+ echo 'result: ' .. n
+ enddef
+
+ def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
+ echo text .. nr
+ for it in items
+ echo it
+ endfor
+ echo "done"
+ enddef
+
+ def g:FuncWithDict()
+ var d = {
+ a: 1,
+ b: 2,
+ }
+ # comment
+ def Inner()
+ eval 1 + 2
+ enddef
+ enddef
+
+ def g:FuncComment()
+ # comment
+ echo "first"
+ .. "one"
+ # comment
+ echo "second"
+ enddef
+
+ def g:FuncForLoop()
+ eval 1 + 2
+ for i in [11, 22, 33]
+ eval i + 2
+ endfor
+ echo "done"
+ enddef
+
+ def g:FuncWithSplitLine()
+ eval 1 + 2
+ | eval 2 + 3
+ enddef
+ END
+ call writefile(file, 'Xtest.vim')
+
+ let buf = RunVimInTerminal('-S Xtest.vim', {})
+
+ call RunDbgCmd(buf,
+ \ ':debug call Func()',
+ \ ['cmd: call Func()'])
+ call RunDbgCmd(buf, 'next', ['result: 3'])
+ call term_sendkeys(buf, "\r")
+ call RunDbgCmd(buf, 'cont')
+
+ call RunDbgCmd(buf,
+ \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
+ \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
+ call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
+ call RunDbgCmd(buf, 'echo text', ['asdf'])
+ call RunDbgCmd(buf, 'echo nr', ['42'])
+ call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
+ call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
+ call RunDbgCmd(buf, 'step', ['function FuncWithArgs', 'line 2: for it in items'])
+ call RunDbgCmd(buf, 'echo it', ['0'])
+ call RunDbgCmd(buf, 'step', ['line 3: echo it'])
+ call RunDbgCmd(buf, 'echo it', ['1'])
+ call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
+ call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
+ call RunDbgCmd(buf, 'echo it', ['1'])
+ call RunDbgCmd(buf, 'step', ['line 3: echo it'])
+ call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
+ call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
+ call RunDbgCmd(buf, 'echo it', ['2'])
+ call RunDbgCmd(buf, 'step', ['line 3: echo it'])
+ call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
+ call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
+ call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
+ call RunDbgCmd(buf, 'cont')
+
+ call RunDbgCmd(buf,
+ \ ':debug call FuncWithDict()',
+ \ ['cmd: call FuncWithDict()'])
+ call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
+ call RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
+ call RunDbgCmd(buf, 'cont')
+
+ call RunDbgCmd(buf, ':breakadd func 1 FuncComment')
+ call RunDbgCmd(buf, ':call FuncComment()', ['function FuncComment', 'line 2: echo "first" .. "one"'])
+ call RunDbgCmd(buf, ':breakadd func 3 FuncComment')
+ call RunDbgCmd(buf, 'cont', ['function FuncComment', 'line 5: echo "second"'])
+ call RunDbgCmd(buf, 'cont')
+
+ call RunDbgCmd(buf, ':breakadd func 2 FuncForLoop')
+ call RunDbgCmd(buf, ':call FuncForLoop()', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
+ call RunDbgCmd(buf, 'step', ['line 2: for i in [11, 22, 33]'])
+ call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 3: eval i + 2'])
+ call RunDbgCmd(buf, 'echo i', ['11'])
+ call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 4: endfor'])
+ call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
+ call RunDbgCmd(buf, 'next', ['line 3: eval i + 2'])
+ call RunDbgCmd(buf, 'echo i', ['22'])
+
+ call RunDbgCmd(buf, 'breakdel *')
+ call RunDbgCmd(buf, 'cont')
+
+ call RunDbgCmd(buf, ':breakadd func FuncWithSplitLine')
+ call RunDbgCmd(buf, ':call FuncWithSplitLine()', ['function FuncWithSplitLine', 'line 1: eval 1 + 2 | eval 2 + 3'])
+
+ call RunDbgCmd(buf, 'cont')
+ call StopVimInTerminal(buf)
+ call delete('Xtest.vim')
+endfunc
+
+func Test_debug_def_function_with_lambda()
+ CheckRunVimInTerminal
+ CheckCWD
+ let lines =<< trim END
+ vim9script
+ def g:Func()
+ var s = 'a'
+ ['b']->map((_, v) => s)
+ echo "done"
+ enddef
+ breakadd func 2 g:Func
+ END
+ call writefile(lines, 'XtestLambda.vim')
+
+ let buf = RunVimInTerminal('-S XtestLambda.vim', {})
+
+ call RunDbgCmd(buf,
+ \ ':call g:Func()',
+ \ ['function Func', 'line 2: [''b'']->map((_, v) => s)'])
+ call RunDbgCmd(buf,
+ \ 'next',
+ \ ['function Func', 'line 3: echo "done"'])
+
+ call RunDbgCmd(buf, 'cont')
+ call StopVimInTerminal(buf)
+ call delete('XtestLambda.vim')
+endfunc
+
func Test_debug_backtrace_level()
CheckRunVimInTerminal
CheckCWD
@@ -1156,6 +1395,7 @@ func Test_debug_backtrace_level()
\ [ 'E121: Undefined variable: s:file1_var' ] )
call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
+ call RunDbgCmd(buf, 'cont')
call StopVimInTerminal(buf)
call delete('Xtest1.vim')
call delete('Xtest2.vim')
diff --git a/test/old/testdir/test_lambda.vim b/test/old/testdir/test_lambda.vim
index 025eb016a8..810b41b389 100644
--- a/test/old/testdir/test_lambda.vim
+++ b/test/old/testdir/test_lambda.vim
@@ -329,6 +329,7 @@ func Test_closure_error()
let caught_932 = 1
endtry
call assert_equal(1, caught_932)
+ call delete('Xscript')
endfunc
" vim: shiftwidth=2 sts=2 expandtab