|
|
@ -2,6 +2,31 @@ |
|
|
|
|
|
|
|
source shared.vim |
|
|
|
source screendump.vim |
|
|
|
source check.vim |
|
|
|
|
|
|
|
func CheckCWD() |
|
|
|
" Check that the longer lines don't wrap due to the length of the script name |
|
|
|
" in cwd |
|
|
|
let script_len = len( getcwd() .. '/Xtest1.vim' ) |
|
|
|
let longest_line = len( 'Breakpoint in "" line 1' ) |
|
|
|
if script_len > ( 75 - longest_line ) |
|
|
|
throw 'Skipped: Your CWD has too many characters' |
|
|
|
endif |
|
|
|
endfunc |
|
|
|
command! -nargs=0 -bar CheckCWD call CheckCWD() |
|
|
|
|
|
|
|
func CheckDbgOutput(buf, lines, options = {}) |
|
|
|
" Verify the expected output |
|
|
|
let lnum = 20 - len(a:lines) |
|
|
|
for l in a:lines |
|
|
|
if get(a:options, 'match', 'equal') ==# 'pattern' |
|
|
|
call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, 200) |
|
|
|
else |
|
|
|
call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200) |
|
|
|
endif |
|
|
|
let lnum += 1 |
|
|
|
endfor |
|
|
|
endfunc |
|
|
|
|
|
|
|
" Run a Vim debugger command |
|
|
|
" If the expected output argument is supplied, then check for it. |
|
|
@ -10,20 +35,17 @@ func RunDbgCmd(buf, cmd, ...) |
|
|
|
call term_wait(a:buf) |
|
|
|
|
|
|
|
if a:0 != 0 |
|
|
|
" Verify the expected output |
|
|
|
let lnum = 20 - len(a:1) |
|
|
|
for l in a:1 |
|
|
|
call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}) |
|
|
|
let lnum += 1 |
|
|
|
endfor |
|
|
|
let options = #{match: 'equal'} |
|
|
|
if a:0 > 1 |
|
|
|
call extend(options, a:2) |
|
|
|
endif |
|
|
|
call CheckDbgOutput(a:buf, a:1, options) |
|
|
|
endif |
|
|
|
endfunc |
|
|
|
|
|
|
|
" Debugger tests |
|
|
|
func Test_Debugger() |
|
|
|
if !CanRunVimInTerminal() |
|
|
|
throw 'Skipped: cannot run Vim in a terminal window' |
|
|
|
endif |
|
|
|
CheckRunVimInTerminal |
|
|
|
|
|
|
|
" Create a Vim script with some functions |
|
|
|
let lines =<< trim END |
|
|
@ -317,6 +339,785 @@ func Test_Debugger() |
|
|
|
call delete('Xtest.vim') |
|
|
|
endfunc |
|
|
|
|
|
|
|
func Test_Backtrace_Through_Source() |
|
|
|
CheckRunVimInTerminal |
|
|
|
CheckCWD |
|
|
|
let file1 =<< trim END |
|
|
|
func SourceAnotherFile() |
|
|
|
source Xtest2.vim |
|
|
|
endfunc |
|
|
|
|
|
|
|
func CallAFunction() |
|
|
|
call SourceAnotherFile() |
|
|
|
call File2Function() |
|
|
|
endfunc |
|
|
|
|
|
|
|
func GlobalFunction() |
|
|
|
call CallAFunction() |
|
|
|
endfunc |
|
|
|
END |
|
|
|
call writefile(file1, 'Xtest1.vim') |
|
|
|
|
|
|
|
let file2 =<< trim END |
|
|
|
func DoAThing() |
|
|
|
echo "DoAThing" |
|
|
|
endfunc |
|
|
|
|
|
|
|
func File2Function() |
|
|
|
call DoAThing() |
|
|
|
endfunc |
|
|
|
|
|
|
|
call File2Function() |
|
|
|
END |
|
|
|
call writefile(file2, 'Xtest2.vim') |
|
|
|
|
|
|
|
let buf = RunVimInTerminal('-S Xtest1.vim', {}) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, |
|
|
|
\ ':debug call GlobalFunction()', |
|
|
|
\ ['cmd: call GlobalFunction()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'backtrace', ['>backtrace', |
|
|
|
\ '->0 function GlobalFunction', |
|
|
|
\ 'line 1: call CallAFunction()']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'backtrace', ['>backtrace', |
|
|
|
\ ' 2 function GlobalFunction[1]', |
|
|
|
\ ' 1 CallAFunction[1]', |
|
|
|
\ '->0 SourceAnotherFile', |
|
|
|
\ 'line 1: source Xtest2.vim']) |
|
|
|
|
|
|
|
" Step into the 'source' command. Note that we print the full trace all the |
|
|
|
" way though the source command. |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ '->0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()']) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ '->1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ '->2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ '->3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ '->3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ '->2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ '->1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ '->0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down', [ 'frame is zero' ] ) |
|
|
|
|
|
|
|
" step until we have another meaninfgul trace |
|
|
|
call RunDbgCmd(buf, 'step', ['line 5: func File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 9: call File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ '->0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 9: call File2Function()']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 5 function GlobalFunction[1]', |
|
|
|
\ ' 4 CallAFunction[1]', |
|
|
|
\ ' 3 SourceAnotherFile[1]', |
|
|
|
\ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]', |
|
|
|
\ ' 1 function File2Function[1]', |
|
|
|
\ '->0 DoAThing', |
|
|
|
\ 'line 1: echo "DoAThing"']) |
|
|
|
|
|
|
|
" Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 10: End of sourced file']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 2: call File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 1 function GlobalFunction[1]', |
|
|
|
\ '->0 CallAFunction', |
|
|
|
\ 'line 2: call File2Function()']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 2 function GlobalFunction[1]', |
|
|
|
\ ' 1 CallAFunction[2]', |
|
|
|
\ '->0 File2Function', |
|
|
|
\ 'line 1: call DoAThing()']) |
|
|
|
|
|
|
|
call StopVimInTerminal(buf) |
|
|
|
call delete('Xtest1.vim') |
|
|
|
call delete('Xtest2.vim') |
|
|
|
endfunc |
|
|
|
|
|
|
|
func Test_Backtrace_Autocmd() |
|
|
|
CheckRunVimInTerminal |
|
|
|
CheckCWD |
|
|
|
let file1 =<< trim END |
|
|
|
func SourceAnotherFile() |
|
|
|
source Xtest2.vim |
|
|
|
endfunc |
|
|
|
|
|
|
|
func CallAFunction() |
|
|
|
call SourceAnotherFile() |
|
|
|
call File2Function() |
|
|
|
endfunc |
|
|
|
|
|
|
|
func GlobalFunction() |
|
|
|
call CallAFunction() |
|
|
|
endfunc |
|
|
|
|
|
|
|
au User TestGlobalFunction :call GlobalFunction() | echo "Done" |
|
|
|
END |
|
|
|
call writefile(file1, 'Xtest1.vim') |
|
|
|
|
|
|
|
let file2 =<< trim END |
|
|
|
func DoAThing() |
|
|
|
echo "DoAThing" |
|
|
|
endfunc |
|
|
|
|
|
|
|
func File2Function() |
|
|
|
call DoAThing() |
|
|
|
endfunc |
|
|
|
|
|
|
|
call File2Function() |
|
|
|
END |
|
|
|
call writefile(file2, 'Xtest2.vim') |
|
|
|
|
|
|
|
let buf = RunVimInTerminal('-S Xtest1.vim', {}) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, |
|
|
|
\ ':debug doautocmd User TestGlobalFunction', |
|
|
|
\ ['cmd: doautocmd User TestGlobalFunction']) |
|
|
|
call RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"']) |
|
|
|
|
|
|
|
" At this point the ontly thing in the stack is the autocommand |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ '->0 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ 'cmd: call GlobalFunction() | echo "Done"']) |
|
|
|
|
|
|
|
" And now we're back into the call stack |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 1 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ '->0 function GlobalFunction', |
|
|
|
\ 'line 1: call CallAFunction()']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 2 function GlobalFunction[1]', |
|
|
|
\ ' 1 CallAFunction[1]', |
|
|
|
\ '->0 SourceAnotherFile', |
|
|
|
\ 'line 1: source Xtest2.vim']) |
|
|
|
|
|
|
|
" Step into the 'source' command. Note that we print the full trace all the |
|
|
|
" way though the source command. |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ '->0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()']) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ '->1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ '->2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ '->3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ '->4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'up', [ 'frame at highest level: 4' ] ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ '->4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ '->3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ '->2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ '->1 SourceAnotherFile[1]', |
|
|
|
\ ' 0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down' ) |
|
|
|
call RunDbgCmd( buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ '->0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 1: func DoAThing()' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd( buf, 'down', [ 'frame is zero' ] ) |
|
|
|
|
|
|
|
" step until we have another meaninfgul trace |
|
|
|
call RunDbgCmd(buf, 'step', ['line 5: func File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 9: call File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 4 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 3 function GlobalFunction[1]', |
|
|
|
\ ' 2 CallAFunction[1]', |
|
|
|
\ ' 1 SourceAnotherFile[1]', |
|
|
|
\ '->0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ 'line 9: call File2Function()']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 6 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 5 function GlobalFunction[1]', |
|
|
|
\ ' 4 CallAFunction[1]', |
|
|
|
\ ' 3 SourceAnotherFile[1]', |
|
|
|
\ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]', |
|
|
|
\ ' 1 function File2Function[1]', |
|
|
|
\ '->0 DoAThing', |
|
|
|
\ 'line 1: echo "DoAThing"']) |
|
|
|
|
|
|
|
" Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 10: End of sourced file']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 2: call File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 2 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 1 function GlobalFunction[1]', |
|
|
|
\ '->0 CallAFunction', |
|
|
|
\ 'line 2: call File2Function()']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 2 function GlobalFunction[1]', |
|
|
|
\ ' 1 CallAFunction[2]', |
|
|
|
\ '->0 File2Function', |
|
|
|
\ 'line 1: call DoAThing()']) |
|
|
|
|
|
|
|
|
|
|
|
" Now unwind so that we get back to the original autocommand (and the second |
|
|
|
" cmd echo "Done") |
|
|
|
call RunDbgCmd(buf, 'finish', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 3 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 2 function GlobalFunction[1]', |
|
|
|
\ ' 1 CallAFunction[2]', |
|
|
|
\ '->0 File2Function', |
|
|
|
\ 'line 1: End of function']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'finish', ['line 2: End of function']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 2 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ ' 1 function GlobalFunction[1]', |
|
|
|
\ '->0 CallAFunction', |
|
|
|
\ 'line 2: End of function']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'finish', ['line 1: End of function']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 1 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ '->0 function GlobalFunction', |
|
|
|
\ 'line 1: End of function']) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', ['cmd: echo "Done"']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ '->0 User Autocommands for "TestGlobalFunction"', |
|
|
|
\ 'cmd: echo "Done"']) |
|
|
|
|
|
|
|
call StopVimInTerminal(buf) |
|
|
|
call delete('Xtest1.vim') |
|
|
|
call delete('Xtest2.vim') |
|
|
|
endfunc |
|
|
|
|
|
|
|
func Test_Backtrace_CmdLine() |
|
|
|
CheckRunVimInTerminal |
|
|
|
CheckCWD |
|
|
|
let file1 =<< trim END |
|
|
|
func SourceAnotherFile() |
|
|
|
source Xtest2.vim |
|
|
|
endfunc |
|
|
|
|
|
|
|
func CallAFunction() |
|
|
|
call SourceAnotherFile() |
|
|
|
call File2Function() |
|
|
|
endfunc |
|
|
|
|
|
|
|
func GlobalFunction() |
|
|
|
call CallAFunction() |
|
|
|
endfunc |
|
|
|
|
|
|
|
au User TestGlobalFunction :call GlobalFunction() | echo "Done" |
|
|
|
END |
|
|
|
call writefile(file1, 'Xtest1.vim') |
|
|
|
|
|
|
|
let file2 =<< trim END |
|
|
|
func DoAThing() |
|
|
|
echo "DoAThing" |
|
|
|
endfunc |
|
|
|
|
|
|
|
func File2Function() |
|
|
|
call DoAThing() |
|
|
|
endfunc |
|
|
|
|
|
|
|
call File2Function() |
|
|
|
END |
|
|
|
call writefile(file2, 'Xtest2.vim') |
|
|
|
|
|
|
|
let buf = RunVimInTerminal( |
|
|
|
\ '-S Xtest1.vim -c "debug call GlobalFunction()"', |
|
|
|
\ {'wait_for_ruler': 0}) |
|
|
|
|
|
|
|
" Need to wait for the vim-in-terminal to be ready |
|
|
|
call CheckDbgOutput(buf, ['command line', |
|
|
|
\ 'cmd: call GlobalFunction()']) |
|
|
|
|
|
|
|
" At this point the ontly thing in the stack is the cmdline |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ '->0 command line', |
|
|
|
\ 'cmd: call GlobalFunction()']) |
|
|
|
|
|
|
|
" And now we're back into the call stack |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '>backtrace', |
|
|
|
\ ' 1 command line', |
|
|
|
\ '->0 function GlobalFunction', |
|
|
|
\ 'line 1: call CallAFunction()']) |
|
|
|
|
|
|
|
call StopVimInTerminal(buf) |
|
|
|
call delete('Xtest1.vim') |
|
|
|
call delete('Xtest2.vim') |
|
|
|
endfunc |
|
|
|
|
|
|
|
func Test_Backtrace_DefFunction() |
|
|
|
CheckRunVimInTerminal |
|
|
|
CheckCWD |
|
|
|
let file1 =<< trim END |
|
|
|
vim9script |
|
|
|
import File2Function from './Xtest2.vim' |
|
|
|
|
|
|
|
def SourceAnotherFile() |
|
|
|
source Xtest2.vim |
|
|
|
enddef |
|
|
|
|
|
|
|
def CallAFunction() |
|
|
|
SourceAnotherFile() |
|
|
|
File2Function() |
|
|
|
enddef |
|
|
|
|
|
|
|
def g:GlobalFunction() |
|
|
|
CallAFunction() |
|
|
|
enddef |
|
|
|
|
|
|
|
defcompile |
|
|
|
END |
|
|
|
call writefile(file1, 'Xtest1.vim') |
|
|
|
|
|
|
|
let file2 =<< trim END |
|
|
|
vim9script |
|
|
|
|
|
|
|
def DoAThing(): number |
|
|
|
var a = 100 * 2 |
|
|
|
a += 3 |
|
|
|
return a |
|
|
|
enddef |
|
|
|
|
|
|
|
export def File2Function() |
|
|
|
DoAThing() |
|
|
|
enddef |
|
|
|
|
|
|
|
defcompile |
|
|
|
File2Function() |
|
|
|
END |
|
|
|
call writefile(file2, 'Xtest2.vim') |
|
|
|
|
|
|
|
let buf = RunVimInTerminal('-S Xtest1.vim', {}) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, |
|
|
|
\ ':debug call GlobalFunction()', |
|
|
|
\ ['cmd: call GlobalFunction()']) |
|
|
|
|
|
|
|
" FIXME: Vim9 lines are not debugged! |
|
|
|
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) |
|
|
|
|
|
|
|
" 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'], |
|
|
|
\ #{match: 'pattern'}) |
|
|
|
|
|
|
|
|
|
|
|
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()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 9: def File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 13: defcompile']) |
|
|
|
call RunDbgCmd(buf, 'step', ['line 14: File2Function()']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '\V>backtrace', |
|
|
|
\ '\V 3 function GlobalFunction[1]', |
|
|
|
\ '\V 2 <SNR>\.\*_CallAFunction[1]', |
|
|
|
\ '\V 1 <SNR>\.\*_SourceAnotherFile[1]', |
|
|
|
\ '\V->0 script ' .. getcwd() .. '/Xtest2.vim', |
|
|
|
\ '\Vline 14: File2Function()'], |
|
|
|
\ #{match: 'pattern'}) |
|
|
|
|
|
|
|
" Don't step into compiled functions... |
|
|
|
call RunDbgCmd(buf, 'step', ['line 15: End of sourced file']) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '\V>backtrace', |
|
|
|
\ '\V 3 function GlobalFunction[1]', |
|
|
|
\ '\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_debug_backtrace_level() |
|
|
|
CheckRunVimInTerminal |
|
|
|
CheckCWD |
|
|
|
let lines =<< trim END |
|
|
|
let s:file1_var = 'file1' |
|
|
|
let g:global_var = 'global' |
|
|
|
|
|
|
|
func s:File1Func( arg ) |
|
|
|
let s:file1_var .= a:arg |
|
|
|
let local_var = s:file1_var .. ' test1' |
|
|
|
let g:global_var .= local_var |
|
|
|
source Xtest2.vim |
|
|
|
endfunc |
|
|
|
|
|
|
|
call s:File1Func( 'arg1' ) |
|
|
|
END |
|
|
|
call writefile(lines, 'Xtest1.vim') |
|
|
|
|
|
|
|
let lines =<< trim END |
|
|
|
let s:file2_var = 'file2' |
|
|
|
|
|
|
|
func s:File2Func( arg ) |
|
|
|
let s:file2_var .= a:arg |
|
|
|
let local_var = s:file2_var .. ' test2' |
|
|
|
let g:global_var .= local_var |
|
|
|
endfunc |
|
|
|
|
|
|
|
call s:File2Func( 'arg2' ) |
|
|
|
END |
|
|
|
call writefile(lines, 'Xtest2.vim') |
|
|
|
|
|
|
|
let file1 = getcwd() .. '/Xtest1.vim' |
|
|
|
let file2 = getcwd() .. '/Xtest2.vim' |
|
|
|
|
|
|
|
" set a breakpoint and source file1.vim |
|
|
|
let buf = RunVimInTerminal( |
|
|
|
\ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim', |
|
|
|
\ #{ wait_for_ruler: 0 } ) |
|
|
|
|
|
|
|
call CheckDbgOutput(buf, [ |
|
|
|
\ 'Breakpoint in "' .. file1 .. '" line 1', |
|
|
|
\ 'Entering Debug mode. Type "cont" to continue.', |
|
|
|
\ 'command line..script ' .. file1, |
|
|
|
\ 'line 1: let s:file1_var = ''file1''' |
|
|
|
\ ]) |
|
|
|
|
|
|
|
" step throught the initial declarations |
|
|
|
call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] ) |
|
|
|
call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo global_var', [ 'global' ] ) |
|
|
|
|
|
|
|
" step in to the first function |
|
|
|
call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] ) |
|
|
|
call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] ) |
|
|
|
call RunDbgCmd(buf, |
|
|
|
\'echo global_var', |
|
|
|
\[ 'E121: Undefined variable: global_var' ] ) |
|
|
|
call RunDbgCmd(buf, |
|
|
|
\'echo local_var', |
|
|
|
\[ 'E121: Undefined variable: local_var' ] ) |
|
|
|
call RunDbgCmd(buf, |
|
|
|
\'echo l:local_var', |
|
|
|
\[ 'E121: Undefined variable: l:local_var' ] ) |
|
|
|
|
|
|
|
" backtrace up |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '\V>backtrace', |
|
|
|
\ '\V 2 command line', |
|
|
|
\ '\V 1 script ' .. file1 .. '[11]', |
|
|
|
\ '\V->0 function <SNR>\.\*_File1Func', |
|
|
|
\ '\Vline 1: let s:file1_var .= a:arg', |
|
|
|
\ ], |
|
|
|
\ #{ match: 'pattern' } ) |
|
|
|
call RunDbgCmd(buf, 'up', [ '>up' ] ) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '\V>backtrace', |
|
|
|
\ '\V 2 command line', |
|
|
|
\ '\V->1 script ' .. file1 .. '[11]', |
|
|
|
\ '\V 0 function <SNR>\.\*_File1Func', |
|
|
|
\ '\Vline 1: let s:file1_var .= a:arg', |
|
|
|
\ ], |
|
|
|
\ #{ match: 'pattern' } ) |
|
|
|
|
|
|
|
" Expression evaluation in the script frame (not the function frame) |
|
|
|
" FIXME: Unexpected in this scope (a: should not be visibnle) |
|
|
|
call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] ) |
|
|
|
" FIXME: Unexpected in this scope (global should be found) |
|
|
|
call RunDbgCmd(buf, |
|
|
|
\'echo global_var', |
|
|
|
\[ 'E121: Undefined variable: global_var' ] ) |
|
|
|
call RunDbgCmd(buf, |
|
|
|
\'echo local_var', |
|
|
|
\[ 'E121: Undefined variable: local_var' ] ) |
|
|
|
call RunDbgCmd(buf, |
|
|
|
\'echo l:local_var', |
|
|
|
\[ 'E121: Undefined variable: l:local_var' ] ) |
|
|
|
|
|
|
|
|
|
|
|
" step while backtraced jumps to the latest frame |
|
|
|
call RunDbgCmd(buf, 'step', [ |
|
|
|
\ 'line 2: let local_var = s:file1_var .. '' test1''' ] ) |
|
|
|
call RunDbgCmd(buf, 'backtrace', [ |
|
|
|
\ '\V>backtrace', |
|
|
|
\ '\V 2 command line', |
|
|
|
\ '\V 1 script ' .. file1 .. '[11]', |
|
|
|
\ '\V->0 function <SNR>\.\*_File1Func', |
|
|
|
\ '\Vline 2: let local_var = s:file1_var .. '' test1''', |
|
|
|
\ ], |
|
|
|
\ #{ match: 'pattern' } ) |
|
|
|
|
|
|
|
call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] ) |
|
|
|
call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] ) |
|
|
|
|
|
|
|
|