diff --git a/README.md b/README.md index ba72b14..38bd320 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ And a couple of brief demos: - breakpoints (function, line and exception breakpoints) - conditional breakpoints (function, line) - step in/out/over/up, stop, restart +- run to cursor - launch and attach - remote launch, remote attach - locals and globals display @@ -552,6 +553,7 @@ features to set your own mappings. To that end, Vimspector defines the following * `VimspectorStepOver` * `VimspectorStepInto` * `VimspectorStepOut` +* `VimspectorRunToCursor` These map roughly 1-1 with the API functions below. @@ -612,6 +614,7 @@ let g:vimspector_enable_mappings = 'HUMAN' | `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | | `F9` | Toggle conditional line breakpoint on the current line. | `vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )` | | `F8` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '' )` | +| `F8` | Run to Cursor | `vimspector#RunToCursor()` | | `F10` | Step Over | `vimspector#StepOver()` | | `F11` | Step Into | `vimspector#StepInto()` | | `F12` | Step out of current function scope | `vimspector#StepOut()` | @@ -710,6 +713,12 @@ You can configure your choices in the `.vimspector.json`. See * Use `vimspector#ClearBreakpoints()` to clear all breakpoints including the memory of exception breakpoint choices. +### Run to Cursor + +* Use `vimspector#RunToCursor` or ``: this creates a temporary + breakpoint on the current line, then continues execution, clearing the + breakpiont when it is hit. + ## Stepping * Step in/out, finish, continue, pause etc. using the WinBar, or mappings. diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index f4d2f58..410fd2d 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -27,45 +27,57 @@ EOF endfunction -let s:enabled = vimspector#internal#state#Reset() +let s:enabled = v:null + +function! s:Initialised() abort + return s:enabled != v:null +endfunction + +function! s:Enabled() abort + if !s:Initialised() + let s:enabled = vimspector#internal#state#Reset() + endif + + return s:enabled +endfunction function! vimspector#Launch() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.Start() endfunction function! vimspector#LaunchWithSettings( settings ) abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.Start( launch_variables = vim.eval( 'a:settings' ) ) endfunction function! vimspector#Reset() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.Reset() endfunction function! vimspector#Restart() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.Restart() endfunction function! vimspector#ClearBreakpoints() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.ClearBreakpoints() endfunction function! vimspector#ToggleBreakpoint( ... ) abort - if !s:enabled + if !s:Enabled() return endif if a:0 == 0 @@ -77,7 +89,7 @@ function! vimspector#ToggleBreakpoint( ... ) abort endfunction function! vimspector#SetLineBreakpoint( file_name, line_num, ... ) abort - if !s:enabled + if !s:Enabled() return endif if a:0 == 0 @@ -92,7 +104,7 @@ function! vimspector#SetLineBreakpoint( file_name, line_num, ... ) abort endfunction function! vimspector#ClearLineBreakpoint( file_name, line_num ) abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.ClearLineBreakpoint( @@ -101,8 +113,18 @@ function! vimspector#ClearLineBreakpoint( file_name, line_num ) abort endfunction +function! vimspector#RunToCursor() abort + if !s:Enabled() + return + endif + py3 _vimspector_session.RunTo( + \ vim.eval( "expand( '%' )" ), + \ int( vim.eval( "line( '.' )" ) ) ) +endfunction + + function! vimspector#AddFunctionBreakpoint( function, ... ) abort - if !s:enabled + if !s:Enabled() return endif if a:0 == 0 @@ -115,70 +137,70 @@ function! vimspector#AddFunctionBreakpoint( function, ... ) abort endfunction function! vimspector#StepOver() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.StepOver() endfunction function! vimspector#StepInto() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.StepInto() endfunction function! vimspector#StepOut() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.StepOut() endfunction function! vimspector#Continue() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.Continue() endfunction function! vimspector#Pause() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.Pause() endfunction function! vimspector#Stop() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.Stop() endfunction function! vimspector#ExpandVariable() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.ExpandVariable() endfunction function! vimspector#DeleteWatch() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.DeleteWatch() endfunction function! vimspector#GoToFrame() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.ExpandFrameOrThread() endfunction function! vimspector#AddWatch( ... ) abort - if !s:enabled + if !s:Enabled() return endif if a:0 == 0 @@ -195,7 +217,7 @@ function! vimspector#AddWatch( ... ) abort endfunction function! vimspector#AddWatchPrompt( expr ) abort - if !s:enabled + if !s:Enabled() return endif stopinsert @@ -204,7 +226,7 @@ function! vimspector#AddWatchPrompt( expr ) abort endfunction function! vimspector#Evaluate( expr ) abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.ShowOutput( 'Console' ) @@ -212,7 +234,7 @@ function! vimspector#Evaluate( expr ) abort endfunction function! vimspector#EvaluateConsole( expr ) abort - if !s:enabled + if !s:Enabled() return endif stopinsert @@ -221,7 +243,7 @@ function! vimspector#EvaluateConsole( expr ) abort endfunction function! vimspector#ShowOutput( ... ) abort - if !s:enabled + if !s:Enabled() return endif if a:0 == 1 @@ -232,7 +254,7 @@ function! vimspector#ShowOutput( ... ) abort endfunction function! vimspector#ShowOutputInWindow( win_id, category ) abort - if !s:enabled + if !s:Enabled() return endif py3 __import__( 'vimspector', @@ -242,21 +264,21 @@ function! vimspector#ShowOutputInWindow( win_id, category ) abort endfunction function! vimspector#ToggleLog() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.ToggleLog() endfunction function! vimspector#ListBreakpoints() abort - if !s:enabled + if !s:Enabled() return endif py3 _vimspector_session.ListBreakpoints() endfunction function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort - if !s:enabled + if !s:Enabled() return endif let buffers = py3eval( '_vimspector_session.GetOutputBuffers() ' @@ -287,7 +309,7 @@ def _vimspector_GetExprCompletions( ArgLead, prev_non_keyword_char ): EOF function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort - if !s:enabled + if !s:Enabled() return endif @@ -415,7 +437,7 @@ function! vimspector#OmniFuncConsole( find_start, query ) abort endfunction function! vimspector#Install( bang, ... ) abort - if !s:enabled + if !s:Enabled() return endif let prefix = vimspector#internal#state#GetAPIPrefix() @@ -427,7 +449,7 @@ function! vimspector#Install( bang, ... ) abort endfunction function! vimspector#CompleteInstall( ArgLead, CmdLine, CursorPos ) abort - if !s:enabled + if !s:Enabled() return endif return py3eval( '"\n".join(' @@ -437,7 +459,7 @@ function! vimspector#CompleteInstall( ArgLead, CmdLine, CursorPos ) abort endfunction function! vimspector#Update( bang, ... ) abort - if !s:enabled + if !s:Enabled() return endif @@ -450,7 +472,7 @@ function! vimspector#Update( bang, ... ) abort endfunction function! vimspector#AbortInstall() abort - if !s:enabled + if !s:Enabled() return endif @@ -459,6 +481,25 @@ function! vimspector#AbortInstall() abort endfunction +function! vimspector#OnBufferCreated( file_name ) abort + if len( a:file_name ) == 0 + return + endif + + " Don't actually load up vimsepctor python in autocommands that trigger + " regularly. We'll only create the session obkect in s:Enabled() + if !s:Initialised() + return + endif + + if !s:Enabled() + return + endif + + py3 _vimspector_session.RefreshSigns( vim.eval( 'a:file_name' ) ) +endfunction + + " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index b1e9481..2dbbd82 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -62,6 +62,9 @@ nnoremap VimspectorStepInto nnoremap VimspectorStepOut \ :call vimspector#StepOut() +nnoremap VimspectorRunToCursor + \ :call vimspector#RunToCursor() + if s:mappings ==# 'VISUAL_STUDIO' nmap VimspectorContinue nmap VimspectorStop @@ -80,6 +83,7 @@ elseif s:mappings ==# 'HUMAN' nmap VimspectorToggleBreakpoint nmap VimspectorToggleConditionalBreakpoint nmap VimspectorAddFunctionBreakpoint + nmap VimspectorRunToCursor nmap VimspectorStepOver nmap VimspectorStepInto nmap VimspectorStepOut @@ -116,9 +120,14 @@ command! -bar -nargs=0 " Dummy autocommands so that we can call this whenever augroup VimspectorUserAutoCmds - au! - au User VimspectorUICreated silent - au User VimspectorTerminalOpened silent + autocmd! + autocmd User VimspectorUICreated silent + autocmd User VimspectorTerminalOpened silent +augroup END + +augroup Vimspector + autocmd! + autocmd BufNew * call vimspector#OnBufferCreated( expand( '' ) ) augroup END " boilerplate {{{ diff --git a/python3/vimspector/breakpoints.py b/python3/vimspector/breakpoints.py index f5999c3..19075ae 100644 --- a/python3/vimspector/breakpoints.py +++ b/python3/vimspector/breakpoints.py @@ -192,13 +192,13 @@ class ProjectBreakpoints( object ): self.UpdateUI() - def SetLineBreakpoint( self, file_name, line_num, options ): + def SetLineBreakpoint( self, file_name, line_num, options, then = None ): bp, _ = self._FindLineBreakpoint( file_name, line_num ) if bp is not None: bp[ 'options' ] = options return self._PutLineBreakpoint( file_name, line_num, options ) - self.UpdateUI() + self.UpdateUI( then ) def ClearLineBreakpoint( self, file_name, line_num ): @@ -209,6 +209,51 @@ class ProjectBreakpoints( object ): self.UpdateUI() + def ClearTemporaryBreakpoint( self, file_name, line_num ): + bp, index = self._FindLineBreakpoint( file_name, line_num ) + if bp is None: + return + if bp[ 'options' ].get( 'temporary' ): + self._DeleteLineBreakpoint( bp, file_name, index ) + self.UpdateUI() + + + def ClearTemporaryBreakpoints( self ): + for file_name, breakpoints in self._line_breakpoints.items(): + self._line_breakpoints[ file_name ] = list( filter( + lambda bp: not bp[ 'options' ].get( 'temporary' ), + breakpoints ) ) + + + def _UpdateTemporaryBreakpoints( self, breakpoints, temp_idxs ): + # adjust any temporary breakpoints to match the server result + # TODO: Maybe now is the time to ditch the split breakpoints nonesense + for temp_idx, user_bp in temp_idxs: + if temp_idx >= len( breakpoints ): + # Just can't trust servers ? + self._logger.debug( "Server Error - invalid breakpoints list did not " + "contain entry for temporary breakpoint at index " + f"{ temp_idx } i.e. { user_bp }" ) + continue + + bp = breakpoints[ temp_idx ] + + if 'line' not in bp or not bp[ 'verified' ]: + utils.UserMessage( + "Unable to set temporary breakpoint at line " + f"{ user_bp[ 'line' ] } execution will continue...", + persist = True, + error = True ) + + self._logger.debug( f"Updating temporary breakpoint { user_bp } line " + f"{ user_bp[ 'line' ] } to { bp[ 'line' ] }" ) + + # if it was moved, update the user-breakpoint so that we unset it + # again properly + user_bp[ 'line' ] = bp[ 'line' ] + + + def AddFunctionBreakpoint( self, function, options ): self._func_breakpoints.append( { 'state': 'ENABLED', @@ -224,11 +269,13 @@ class ProjectBreakpoints( object ): self.UpdateUI() - def UpdateUI( self ): + def UpdateUI( self, then = None ): if self._connection: - self.SendBreakpoints() + self.SendBreakpoints( then ) else: self._ShowBreakpoints() + if then: + then() def SetBreakpointsHandler( self, handler ): @@ -254,9 +301,12 @@ class ProjectBreakpoints( object ): if awaiting == 0 and doneHandler: doneHandler() - def response_handler( source, msg ): + def response_handler( source, msg, temp_idxs = [] ): if msg: self._breakpoints_handler.AddBreakpoints( source, msg ) + + breakpoints = ( msg.get( 'body' ) or {} ).get( 'breakpoints' ) or [] + self._UpdateTemporaryBreakpoints( breakpoints, temp_idxs ) response_received() @@ -267,9 +317,9 @@ class ProjectBreakpoints( object ): # TODO: add the _configured_breakpoints to line_breakpoints - # TODO: the line numbers might have changed since pressing the F9 key! for file_name, line_breakpoints in self._line_breakpoints.items(): + temp_idxs = [] breakpoints = [] for bp in line_breakpoints: self._SignToLine( file_name, bp ) @@ -283,8 +333,15 @@ class ProjectBreakpoints( object ): dap_bp = {} dap_bp.update( bp[ 'options' ] ) dap_bp.update( { 'line': bp[ 'line' ] } ) + + dap_bp.pop( 'temporary', None ) + + if bp[ 'options' ].get( 'temporary' ): + temp_idxs.append( [ len( breakpoints ), bp ] ) + breakpoints.append( dap_bp ) + source = { 'name': os.path.basename( file_name ), 'path': file_name, @@ -295,7 +352,10 @@ class ProjectBreakpoints( object ): # The source=source here is critical to ensure that we capture each # source in the iteration, rather than ending up passing the same source # to each callback. - lambda msg, source=source: response_handler( source, msg ), + lambda msg, source=source, temp_idxs=temp_idxs: response_handler( + source, + msg, + temp_idxs = temp_idxs ), { 'command': 'setBreakpoints', 'arguments': { @@ -396,6 +456,12 @@ class ProjectBreakpoints( object ): # pay any attention to them anyway. self._exception_breakpoints[ 'exceptionOptions' ] = [] + + def Refresh( self, file_name ): + # TODO: Just this file ? + self._ShowBreakpoints() + + def _ShowBreakpoints( self ): for file_name, line_breakpoints in self._line_breakpoints.items(): for bp in line_breakpoints: @@ -410,7 +476,7 @@ class ProjectBreakpoints( object ): else 'vimspectorBPCond' if 'condition' in bp[ 'options' ] else 'vimspectorBP' ) - if utils.BufferNumberForFile( file_name, False ) > 0: + if utils.BufferExists( file_name ): signs.PlaceSign( bp[ 'sign_id' ], 'VimspectorBP', sign, @@ -422,7 +488,7 @@ class ProjectBreakpoints( object ): if 'sign_id' not in bp: return bp[ 'line' ] - if utils.BufferNumberForFile( file_name, False ) <= 0: + if not utils.BufferExists( file_name ): return bp[ 'line' ] signs = vim.eval( "sign_getplaced( '{}', {} )".format( diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index afd8c03..e1b7f59 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -93,16 +93,12 @@ class CodeView( object ): sign = 'vimspectorPCBP' break - try: + if utils.BufferExists( frame[ 'source' ][ 'path' ] ): signs.PlaceSign( self._signs[ 'vimspectorPC' ], 'VimspectorCode', sign, frame[ 'source' ][ 'path' ], frame[ 'line' ] ) - except vim.error as e: - # Ignore 'invalid buffer name' - if 'E158' not in str( e ): - raise def SetCurrentFrame( self, frame ): @@ -215,6 +211,11 @@ class CodeView( object ): return + def Refresh( self, file_name ): + # TODO: jsut the file ? + self.ShowBreakpoints() + + def _UndisplaySigns( self ): for sign_id in self._signs[ 'breakpoints' ]: signs.UnplaceSign( sign_id, 'VimspectorCode' ) @@ -236,12 +237,13 @@ class CodeView( object ): sign_id = self._next_sign_id self._next_sign_id += 1 self._signs[ 'breakpoints' ].append( sign_id ) - signs.PlaceSign( sign_id, - 'VimspectorCode', - 'vimspectorBP' if breakpoint[ 'verified' ] - else 'vimspectorBPDisabled', - file_name, - breakpoint[ 'line' ] ) + if utils.BufferExists( file_name ): + signs.PlaceSign( sign_id, + 'VimspectorCode', + 'vimspectorBP' if breakpoint[ 'verified' ] + else 'vimspectorBPDisabled', + file_name, + breakpoint[ 'line' ] ) # We need to also check if there's a breakpoint on this PC line and chnge # the PC diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 85f32da..42b6340 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -77,6 +77,7 @@ class DebugSession( object ): self._launch_complete = False self._on_init_complete_handlers = [] self._server_capabilities = {} + self.ClearTemporaryBreakpoints() def Start( self, launch_variables = None ): # We mutate launch_variables, so don't mutate the default argument. @@ -560,6 +561,13 @@ class DebugSession( object ): return response[ 'body' ][ 'targets' ] + def RefreshSigns( self, file_name ): + if self._connection: + self._codeView.Refresh( file_name ) + else: + self._breakpoints.Refresh( file_name ) + + def _SetUpUI( self ): vim.command( 'tab split' ) self._uiTab = vim.current.tabpage @@ -622,7 +630,7 @@ class DebugSession( object ): self.SetCurrentFrame( None ) @RequiresUI() - def SetCurrentFrame( self, frame ): + def SetCurrentFrame( self, frame, reason = '' ): if not frame: self._stackTraceView.Clear() self._variablesView.Clear() @@ -630,11 +638,16 @@ class DebugSession( object ): if not self._codeView.SetCurrentFrame( frame ): return False - if frame: - self._variablesView.SetSyntax( self._codeView.current_syntax ) - self._stackTraceView.SetSyntax( self._codeView.current_syntax ) - self._variablesView.LoadScopes( frame ) - self._variablesView.EvaluateWatches() + # the codeView.SetCurrentFrame already checked the frame was valid and + # countained a valid source + self._variablesView.SetSyntax( self._codeView.current_syntax ) + self._stackTraceView.SetSyntax( self._codeView.current_syntax ) + self._variablesView.LoadScopes( frame ) + self._variablesView.EvaluateWatches() + + if reason == 'stopped': + self._breakpoints.ClearTemporaryBreakpoint( frame[ 'source' ][ 'path' ], + frame[ 'line' ] ) return True @@ -1165,8 +1178,22 @@ class DebugSession( object ): def ToggleBreakpoint( self, options ): return self._breakpoints.ToggleBreakpoint( options ) - def SetLineBreakpoint( self, file_name, line_num, options ): - return self._breakpoints.SetLineBreakpoint( file_name, line_num, options ) + def RunTo( self, file_name, line ): + self.ClearTemporaryBreakpoints() + self.SetLineBreakpoint( file_name, + line, + { 'temporary': True }, + lambda: self.Continue() ) + + + def ClearTemporaryBreakpoints( self ): + return self._breakpoints.ClearTemporaryBreakpoints() + + def SetLineBreakpoint( self, file_name, line_num, options, then = None ): + return self._breakpoints.SetLineBreakpoint( file_name, + line_num, + options, + then ) def ClearLineBreakpoint( self, file_name, line_num ): return self._breakpoints.ClearLineBreakpoint( file_name, line_num ) diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index 8af6536..584370f 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -149,12 +149,15 @@ class StackTraceView( object ): self._DrawStackTrace( thread ) - def _LoadStackTrace( self, thread, infer_current_frame ): + def _LoadStackTrace( self, + thread, + infer_current_frame, + reason = '' ): def consume_stacktrace( message ): thread[ '_frames' ] = message[ 'body' ][ 'stackFrames' ] if infer_current_frame: for frame in thread[ '_frames' ]: - if self._JumpToFrame( frame ): + if self._JumpToFrame( frame, reason ): break self._DrawThreads() @@ -183,11 +186,11 @@ class StackTraceView( object ): else: self._LoadStackTrace( thread, False ) - def _JumpToFrame( self, frame ): + def _JumpToFrame( self, frame, reason = '' ): def do_jump(): if 'line' in frame and frame[ 'line' ] > 0: self._current_frame = frame - return self._session.SetCurrentFrame( self._current_frame ) + return self._session.SetCurrentFrame( self._current_frame, reason ) return False source = frame.get( 'source' ) or {} @@ -211,7 +214,7 @@ class StackTraceView( object ): if self._current_thread is not None: for thread in self._threads: if thread[ 'id' ] == self._current_thread: - self._LoadStackTrace( thread, True ) + self._LoadStackTrace( thread, True, 'stopped' ) return self.LoadThreads( True ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 4ce387d..66f8d40 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -55,6 +55,10 @@ def BufferForFile( file_name ): return vim.buffers[ BufferNumberForFile( file_name ) ] +def BufferExists( file_name ): + return bool( int ( vim.eval( f"bufexists( '{ Escape( file_name ) }' )" ) ) ) + + def NewEmptyBuffer(): bufnr = int( vim.eval( 'bufadd("")' ) ) Call( 'bufload', bufnr ) diff --git a/support/test/python/simple_python/.vimspector.json b/support/test/python/simple_python/.vimspector.json index 044c669..aba0578 100644 --- a/support/test/python/simple_python/.vimspector.json +++ b/support/test/python/simple_python/.vimspector.json @@ -52,6 +52,11 @@ }, "run - default": { "adapter": "debugpy", + "variables": { + "MAKE_ENV_OUTPUT": { + "shell": "${workspaceRoot}/make_env.sh" + } + }, "configuration": { "request": "launch", "type": "python", @@ -60,8 +65,8 @@ "stopOnEntry#json": "${StopOnEntry:true}", "console": "integratedTerminal", "args#json": "${args:[]}", - "env#json": "${env:{\\}}", - "igored#json#s": "string not json" + "igored#json#s": "string not json", + "env#json": "${MAKE_ENV_OUTPUT}" }, "breakpoints": { "exception": { diff --git a/support/test/python/simple_python/make_env.sh b/support/test/python/simple_python/make_env.sh new file mode 100755 index 0000000..a4da8ca --- /dev/null +++ b/support/test/python/simple_python/make_env.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +cat <<"EOF" +{ + "Something": "Value1", + "SomethingElse": "Value2" +} +EOF + diff --git a/support/test/python/simple_python/print_env.py b/support/test/python/simple_python/print_env.py new file mode 100644 index 0000000..4b88f2d --- /dev/null +++ b/support/test/python/simple_python/print_env.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os + + +def Main(): + print( os.environ.get( 'Something', 'ERROR' ) ) + print( os.environ.get( 'SomethingElse', 'ERROR' ) ) + + for k, v in os.environ: + print( f'{ k } = "{ v }"' ) + + +Main() + diff --git a/tests/breakpoints.test.vim b/tests/breakpoints.test.vim index f6cafa5..e6a1357 100644 --- a/tests/breakpoints.test.vim +++ b/tests/breakpoints.test.vim @@ -6,38 +6,6 @@ function! ClearDown() call vimspector#test#setup#ClearDown() endfunction -function! SetUp_Test_Mappings_Are_Added_HUMAN() - let g:vimspector_enable_mappings = 'HUMAN' -endfunction - -function! Test_Mappings_Are_Added_HUMAN() - call assert_true( hasmapto( 'vimspector#Continue()' ) ) - call assert_false( hasmapto( 'vimspector#Launch()' ) ) - call assert_true( hasmapto( 'vimspector#Stop()' ) ) - call assert_true( hasmapto( 'vimspector#Restart()' ) ) - call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) ) - call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) ) - call assert_true( hasmapto( 'vimspector#StepOver()' ) ) - call assert_true( hasmapto( 'vimspector#StepInto()' ) ) - call assert_true( hasmapto( 'vimspector#StepOut()' ) ) -endfunction - -function! SetUp_Test_Mappings_Are_Added_VISUAL_STUDIO() - let g:vimspector_enable_mappings = 'VISUAL_STUDIO' -endfunction - -function! Test_Mappings_Are_Added_VISUAL_STUDIO() - call assert_true( hasmapto( 'vimspector#Continue()' ) ) - call assert_false( hasmapto( 'vimspector#Launch()' ) ) - call assert_true( hasmapto( 'vimspector#Stop()' ) ) - call assert_true( hasmapto( 'vimspector#Restart()' ) ) - call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) ) - call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) ) - call assert_true( hasmapto( 'vimspector#StepOver()' ) ) - call assert_true( hasmapto( 'vimspector#StepInto()' ) ) - call assert_true( hasmapto( 'vimspector#StepOut()' ) ) -endfunction - function! SetUp_Test_Signs_Placed_Using_API_Are_Shown() let g:vimspector_enable_mappings = 'VISUAL_STUDIO' endfunction @@ -78,68 +46,6 @@ function! Test_Signs_Placed_Using_API_Are_Shown() %bwipeout! endfunction -function! SetUp_Test_Use_Mappings_HUMAN() - let g:vimspector_enable_mappings = 'HUMAN' -endfunction - -function! Test_Use_Mappings_HUMAN() - lcd testdata/cpp/simple - edit simple.cpp - call setpos( '.', [ 0, 15, 1 ] ) - - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 ) - call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 ) - - " Add the breakpoint - call feedkeys( "\", 'xt' ) - call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', - \ 15, - \ 'vimspectorBP', - \ 9 ) - - " Disable the breakpoint - call feedkeys( "\", 'xt' ) - call vimspector#test#signs#AssertSignGroupSingletonAtLine( - \ 'VimspectorBP', - \ 15, - \ 'vimspectorBPDisabled', - \ 9 ) - - " Delete the breakpoint - call feedkeys( "\", 'xt' ) - call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 ) - - " Add it again - call feedkeys( "\", 'xt' ) - call vimspector#test#signs#AssertSignGroupSingletonAtLine( - \ 'VimspectorBP', - \ 15, - \ 'vimspectorBP', - \ 9 ) - - " Here we go. Start Debugging - call feedkeys( "\", 'xt' ) - - call assert_equal( 2, len( gettabinfo() ) ) - let cur_tabnr = tabpagenr() - call assert_equal( 5, len( gettabinfo( cur_tabnr )[ 0 ].windows ) ) - - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 ) - - " Step - call feedkeys( "\", 'xt' ) - - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) - call WaitForAssert( {-> - \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cp', 16 ) - \ } ) - - call vimspector#test#setup#Reset() - - lcd - - %bwipeout! -endfunction - function! SetUp_Test_StopAtEntry() let g:vimspector_enable_mappings = 'HUMAN' endfunction @@ -200,8 +106,8 @@ function Test_DisableBreakpointWhileDebugging() \ 16 ) \ } ) - " Add the breakpoint - call feedkeys( "\", 'xt' ) + call setpos( '.', [ 0, 1, 1 ] ) + call vimspector#SetLineBreakpoint( 'simple.cpp', 16 ) call WaitForAssert( {-> \ vimspector#test#signs#AssertSignGroupSingletonAtLine( \ 'VimspectorCode', @@ -211,7 +117,6 @@ function Test_DisableBreakpointWhileDebugging() \ } ) " Run to breakpoint - call setpos( '.', [ 0, 15, 1 ] ) call feedkeys( "\", 'xt' ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) call WaitForAssert( {-> @@ -258,6 +163,58 @@ function Test_DisableBreakpointWhileDebugging() %bwipeout! endfunction +function! Test_Add_Breakpoints_In_File_Then_Open() + lcd testdata/cpp/simple + + " Set and clear without file open + call vimspector#SetLineBreakpoint( 'simple.cpp', 16 ) + call vimspector#ClearLineBreakpoint( 'simple.cpp', 16 ) + + " Clear non-set breakpoint + call vimspector#ClearLineBreakpoint( 'simple.cpp', 1 ) + + " Re-add + call vimspector#SetLineBreakpoint( 'simple.cpp', 16 ) + + " Open and expect sign to be added + edit simple.cpp + call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', + \ 16, + \ 'vimspectorBP', + \ 9 ) + call vimspector#LaunchWithSettings( { 'configuration': 'run-to-breakpoint' } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) + + call vimspector#test#setup#Reset() + lcd - + %bwipeout! +endfunction + +function! Test_Add_Breakpoints_In_NonOpenedFile_RunToBreak() + lcd testdata/cpp/simple + + " add + call vimspector#SetLineBreakpoint( 'simple.cpp', 16 ) + + call vimspector#LaunchWithSettings( { + \ 'configuration': 'run-to-breakpoint-specify-file', + \ 'prog': 'simple' + \ } ) + call WaitFor( {-> bufexists( 'simple.cpp' ) } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 ) + + call vimspector#test#signs#AssertSignAtLine( + \ 'VimspectorCode', + \ 16, + \ 'vimspectorPCBP', + \ 200 ) + + call vimspector#test#setup#Reset() + lcd - + %bwipeout! +endfunction + function! SetUp_Test_Insert_Code_Above_Breakpoint() let g:vimspector_enable_mappings = 'HUMAN' endfunction @@ -308,7 +265,6 @@ function! Test_Insert_Code_Above_Breakpoint() " Delete it call feedkeys( "\", 'xt' ) call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 26 ) - endfunction function! SetUp_Test_Conditional_Line_Breakpoint() @@ -360,8 +316,11 @@ function! Test_Conditional_Line_Breakpoint() \ 'vimspectorBP', \ 9 ) - call setpos( '.', [ 0, 17, 1 ] ) - call vimspector#ToggleBreakpoint( { 'condition': 'argc == 1' } ) + call setpos( '.', [ 0, 1, 1 ] ) + call vimspector#SetLineBreakpoint( + \ 'simple.cpp', + \ 17, + \ { 'condition': 'argc == 1' } ) call vimspector#test#signs#AssertSignGroupSingletonAtLine( \ 'VimspectorBP', \ 17, @@ -724,7 +683,6 @@ function! Test_Custom_Breakpoint_Priority_Partial() unlet! g:vimspector_sign_priority endfunction - function! Test_Add_Line_BP_In_Other_File_While_Debugging() let moo = 'moo.py' let cow = 'cow.py' diff --git a/tests/breakpoints_doublewidth.test.vim b/tests/breakpoints_doublewidth.test.vim index 8ab35bb..cfd4e6c 100644 --- a/tests/breakpoints_doublewidth.test.vim +++ b/tests/breakpoints_doublewidth.test.vim @@ -7,38 +7,6 @@ function! ClearDown() call vimspector#test#setup#ClearDown() endfunction -function! SetUp_Test_Mappings_Are_Added_HUMAN() - let g:vimspector_enable_mappings = 'HUMAN' -endfunction - -function! Test_Mappings_Are_Added_HUMAN() - call assert_true( hasmapto( 'vimspector#Continue()' ) ) - call assert_false( hasmapto( 'vimspector#Launch()' ) ) - call assert_true( hasmapto( 'vimspector#Stop()' ) ) - call assert_true( hasmapto( 'vimspector#Restart()' ) ) - call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) ) - call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) ) - call assert_true( hasmapto( 'vimspector#StepOver()' ) ) - call assert_true( hasmapto( 'vimspector#StepInto()' ) ) - call assert_true( hasmapto( 'vimspector#StepOut()' ) ) -endfunction - -function! SetUp_Test_Mappings_Are_Added_VISUAL_STUDIO() - let g:vimspector_enable_mappings = 'VISUAL_STUDIO' -endfunction - -function! Test_Mappings_Are_Added_VISUAL_STUDIO() - call assert_true( hasmapto( 'vimspector#Continue()' ) ) - call assert_false( hasmapto( 'vimspector#Launch()' ) ) - call assert_true( hasmapto( 'vimspector#Stop()' ) ) - call assert_true( hasmapto( 'vimspector#Restart()' ) ) - call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) ) - call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) ) - call assert_true( hasmapto( 'vimspector#StepOver()' ) ) - call assert_true( hasmapto( 'vimspector#StepInto()' ) ) - call assert_true( hasmapto( 'vimspector#StepOut()' ) ) -endfunction - function! SetUp_Test_Signs_Placed_Using_API_Are_Shown() let g:vimspector_enable_mappings = 'VISUAL_STUDIO' endfunction @@ -132,7 +100,7 @@ function! Test_Use_Mappings_HUMAN() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) call WaitForAssert( {-> - \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cp', 16 ) + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 ) \ } ) call vimspector#test#setup#Reset() diff --git a/tests/language_go.test.vim b/tests/language_go.test.vim index b6a7da4..200d5d6 100644 --- a/tests/language_go.test.vim +++ b/tests/language_go.test.vim @@ -45,3 +45,28 @@ function! Test_Go_Simple() lcd - %bwipeout! endfunction + + +function! Test_Run_To_Cursor() + let fn='hello-world.go' + lcd ../support/test/go/hello_world + exe 'edit ' . fn + + call vimspector#SetLineBreakpoint( fn, 4 ) + call vimspector#Launch() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 4, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 4 ) + \ } ) + + call cursor( 5, 1 ) + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 5, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 5 ) + \ } ) + + call vimspector#test#setup#Reset() + lcd - + %bwipeout! +endfunction diff --git a/tests/lib/autoload/vimspector/test/signs.vim b/tests/lib/autoload/vimspector/test/signs.vim index a6bb698..cf64520 100644 --- a/tests/lib/autoload/vimspector/test/signs.vim +++ b/tests/lib/autoload/vimspector/test/signs.vim @@ -1,6 +1,7 @@ function! vimspector#test#signs#AssertCursorIsAtLineInBuffer( buffer, \ line, \ column ) abort + call WaitFor( {-> bufexists( a:buffer ) } ) call WaitForAssert( {-> \ assert_equal( fnamemodify( a:buffer, ':p' ), \ fnamemodify( bufname( '%' ), ':p' ), @@ -15,6 +16,7 @@ function! vimspector#test#signs#AssertCursorIsAtLineInBuffer( buffer, endfunction function! vimspector#test#signs#AssertPCIsAtLineInBuffer( buffer, line ) abort + call WaitFor( {-> bufexists( a:buffer ) } ) let signs = sign_getplaced( a:buffer, { \ 'group': 'VimspectorCode', \ } ) diff --git a/tests/mappings.test.vim b/tests/mappings.test.vim new file mode 100644 index 0000000..fcd19fe --- /dev/null +++ b/tests/mappings.test.vim @@ -0,0 +1,123 @@ +function! SetUp() + call vimspector#test#setup#SetUpWithMappings( v:none ) +endfunction + +function! ClearDown() + call vimspector#test#setup#ClearDown() +endfunction + +function! SetUp_Test_Mappings_Are_Added_HUMAN() + let g:vimspector_enable_mappings = 'HUMAN' +endfunction + +function! Test_Mappings_Are_Added_HUMAN() + call assert_true( hasmapto( 'vimspector#Continue()' ) ) + call assert_false( hasmapto( 'vimspector#Launch()' ) ) + call assert_true( hasmapto( 'vimspector#Stop()' ) ) + call assert_true( hasmapto( 'vimspector#Restart()' ) ) + call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) ) + call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) ) + call assert_true( hasmapto( 'vimspector#StepOver()' ) ) + call assert_true( hasmapto( 'vimspector#StepInto()' ) ) + call assert_true( hasmapto( 'vimspector#StepOut()' ) ) + call assert_true( hasmapto( 'vimspector#RunToCursor()' ) ) +endfunction + +function! SetUp_Test_Mappings_Are_Added_VISUAL_STUDIO() + let g:vimspector_enable_mappings = 'VISUAL_STUDIO' +endfunction + +function! Test_Mappings_Are_Added_VISUAL_STUDIO() + call assert_true( hasmapto( 'vimspector#Continue()' ) ) + call assert_false( hasmapto( 'vimspector#Launch()' ) ) + call assert_true( hasmapto( 'vimspector#Stop()' ) ) + call assert_true( hasmapto( 'vimspector#Restart()' ) ) + call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) ) + call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) ) + call assert_true( hasmapto( 'vimspector#StepOver()' ) ) + call assert_true( hasmapto( 'vimspector#StepInto()' ) ) + call assert_true( hasmapto( 'vimspector#StepOut()' ) ) +endfunction + +function! SetUp_Test_Use_Mappings_HUMAN() + let g:vimspector_enable_mappings = 'HUMAN' +endfunction + +function! Test_Use_Mappings_HUMAN() + call ThisTestIsFlaky() + lcd testdata/cpp/simple + edit simple.cpp + call setpos( '.', [ 0, 15, 1 ] ) + + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 ) + call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 ) + + " Add the breakpoint + call feedkeys( "\", 'xt' ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', + \ 15, + \ 'vimspectorBP', + \ 9 ) + + " Disable the breakpoint + call feedkeys( "\", 'xt' ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorBP', + \ 15, + \ 'vimspectorBPDisabled', + \ 9 ) + + " Delete the breakpoint + call feedkeys( "\", 'xt' ) + call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 ) + + " Add and clear using API + call vimspector#SetLineBreakpoint( 'simple.cpp', 15 ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', + \ 15, + \ 'vimspectorBP', + \ 9 ) + + call vimspector#ClearLineBreakpoint( 'simple.cpp', 15 ) + call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 ) + + " Add it again + call feedkeys( "\", 'xt' ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorBP', + \ 15, + \ 'vimspectorBP', + \ 9 ) + + " Here we go. Start Debugging + call feedkeys( "\", 'xt' ) + + call assert_equal( 2, len( gettabinfo() ) ) + let cur_tabnr = tabpagenr() + call assert_equal( 5, len( gettabinfo( cur_tabnr )[ 0 ].windows ) ) + + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 ) + + " Step + call feedkeys( "\", 'xt' ) + + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 ) + \ } ) + + " Run to cursor + call cursor( 9, 1 ) + call feedkeys( "\\\", 'xt' ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 9, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 9 ) + \ } ) + + + call vimspector#test#setup#Reset() + + lcd - + %bwipeout! +endfunction + diff --git a/tests/temporary_breakpoints.test.vim b/tests/temporary_breakpoints.test.vim new file mode 100644 index 0000000..7bcad55 --- /dev/null +++ b/tests/temporary_breakpoints.test.vim @@ -0,0 +1,200 @@ +function! SetUp() + call vimspector#test#setup#SetUpWithMappings( v:none ) +endfunction + +function! ClearDown() + call vimspector#test#setup#ClearDown() +endfunction + +function s:Start() + call vimspector#SetLineBreakpoint( 'moo.py', 13 ) + call vimspector#Launch() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 1, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 1 ) + call vimspector#Continue() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 13, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 13 ) +endfunction + +function Test_Run_To_Cursor_Simple() + " Run to a position that will certainly be executed + lcd ../support/test/python/multiple_files + call vimspector#SetLineBreakpoint( 'moo.py', 13 ) + call s:Start() + + call cursor( 8, 27 ) + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 8, 27 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 8 ) + \ } ) + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 9, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 9 ) + " Check there is no breakpoint set on line 8 + call WaitForAssert( {-> + \ vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 8 ) + \ } ) + call vimspector#test#setup#Reset() + lcd - + %bwipe! +endfunction + +function Test_Run_To_Cursor_On_NonBreaking_Line() + " Run to a position that will certainly be executed, but is not a real line + lcd ../support/test/python/multiple_files + call vimspector#SetLineBreakpoint( 'moo.py', 13 ) + call s:Start() + + call cursor( 7, 1 ) + " Interestingly, debugpy moves the breakpoint to the previous line, which is + " kinda annoying + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 6, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 6 ) + \ } ) + call vimspector#StepOver() + " It's a loop, so we go up a line + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 5, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 5 ) + + " Check there is no breakpoint set on lines 7 and 6: + " 7 - where we put the 'temporary' breakpoint + " 6 - where it got placed + " + " FIXME: This is broken, we don't _know_ that the breakpoint that was hit was + " the temporary one, and there's no way to know. + " + " I wonder if the relocated breakpoint can be matched with the _original_ + " breakpoint + call WaitForAssert( {-> + \ vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 7 ) + \ } ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 6 ) + \ } ) + call vimspector#test#setup#Reset() + lcd - + %bwipe! +endfunction + +function Test_Run_To_Cursor_Different_File() + " Run into a different file + " Run to a position that will certainly be executed, but is not a real line + lcd ../support/test/python/multiple_files + call vimspector#SetLineBreakpoint( 'moo.py', 13 ) + call s:Start() + + edit cow.py + call cursor( 2, 1 ) + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'cow.py', 2, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'cow.py', 2 ) + \ } ) + + bu moo.py + call cursor( 9, 12 ) + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 9, 12 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 9 ) + \ } ) + + call vimspector#test#setup#Reset() + lcd - + %bwipe! +endfunction + +function Test_Run_To_Cursor_Hit_Another_Breakpoint() + " Run to cursor, but hit a non-temporary breakpoint + lcd ../support/test/python/multiple_files + call vimspector#SetLineBreakpoint( 'moo.py', 13 ) + call s:Start() + + call vimspector#SetLineBreakpoint( 'moo.py', 5 ) + call cursor( 6, 1 ) + + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 5, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 5 ) + \ } ) + + " The temporary breakpoint is still there + call vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorCode', + \ 6, + \ 'vimspectorBP', + \ 9 ) + + call vimspector#ClearLineBreakpoint( 'moo.py', 5 ) + + call cursor( 8, 1 ) + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 8, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 8 ) + \ } ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 6 ) + \ } ) + + call vimspector#test#setup#Reset() + lcd - + %bwipe! +endfunction + +function! Test_InvalidBreakpoint() + " Run to cursor, but hit a non-temporary breakpoint + lcd ../support/test/python/multiple_files + call vimspector#SetLineBreakpoint( 'moo.py', 13 ) + call s:Start() + + call vimspector#SetLineBreakpoint( 'moo.py', 9 ) + + edit .vimspector.json + call cursor( 1, 1 ) + call vimspector#RunToCursor() + + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 9, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 9 ) + \ } ) + + call vimspector#test#setup#Reset() + lcd - + %bwipe! +endfunction + +function! Test_StartDebuggingWithRunToCursor() + lcd ../support/test/python/multiple_files + edit moo.py + call cursor( 9, 1 ) + call vimspector#RunToCursor() + " Stop on entry is still hit + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 1, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 1 ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorCode', + \ 9, + \ 'vimspectorBP', + \ 9 ) + + call vimspector#Continue() + " Runs to cursor + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 9, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 9 ) + + call vimspector#StepOver() + " And claers the temp breakpoint + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 8, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 8 ) + + call WaitForAssert( {-> + \ vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 9 ) + \ } ) + + lcd - +endfunction diff --git a/tests/testdata/cpp/simple/.vimspector.json b/tests/testdata/cpp/simple/.vimspector.json index 176a44d..0dca061 100644 --- a/tests/testdata/cpp/simple/.vimspector.json +++ b/tests/testdata/cpp/simple/.vimspector.json @@ -46,6 +46,28 @@ } } }, + "run-to-breakpoint-specify-file": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/${prog}", + "cwd": "${workspaceRoot}", + "externalConsole": false, + "stopAtEntry": false, + "stopOnEntry": false, + "MImode": "${VIMSPECTOR_MIMODE}" + }, + "breakpoints": { + "exception": { + "cpp_catch": "", + "cpp_throw": "", + "objc_catch": "", + "objc_throw": "", + "swift_catch": "", + "swift_throw": "" + } + } + }, "calculate-some-variable": { "adapter": "vscode-cpptools", "variables": {