Merge pull request #26016 from zeertzjq/vim-8.2.2985

vim-patch:8.2.{2985,2996,3003,3011,3013,3017,3026,3027,3039,3066,3086,3096,3116,3138,3395,3984,4020,4541}
This commit is contained in:
zeertzjq 2023-11-13 07:24:08 +08:00 committed by GitHub
commit d65c574ca3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 275 additions and 16 deletions

View File

@ -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".

View File

@ -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')

View File

@ -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