commit
7b048367f7
19 changed files with 790 additions and 241 deletions
|
|
@ -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
|
|||
* `<Plug>VimspectorStepOver`
|
||||
* `<Plug>VimspectorStepInto`
|
||||
* `<Plug>VimspectorStepOut`
|
||||
* `<Plug>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()` |
|
||||
| `<leader>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( '<cexpr>' )` |
|
||||
| `<leader>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 `<leader><F8>`: 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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -76,8 +88,43 @@ function! vimspector#ToggleBreakpoint( ... ) abort
|
|||
py3 _vimspector_session.ToggleBreakpoint( vim.eval( 'options' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#SetLineBreakpoint( file_name, line_num, ... ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 0
|
||||
let options = {}
|
||||
else
|
||||
let options = a:1
|
||||
endif
|
||||
py3 _vimspector_session.SetLineBreakpoint(
|
||||
\ vim.eval( 'a:file_name' ),
|
||||
\ int( vim.eval( 'a:line_num' ) ),
|
||||
\ vim.eval( 'options' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#ClearLineBreakpoint( file_name, line_num ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ClearLineBreakpoint(
|
||||
\ vim.eval( 'a:file_name' ),
|
||||
\ int( vim.eval( 'a:line_num' ) ) )
|
||||
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
|
||||
|
|
@ -90,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
|
||||
|
|
@ -170,7 +217,7 @@ function! vimspector#AddWatch( ... ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#AddWatchPrompt( expr ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
stopinsert
|
||||
|
|
@ -179,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' )
|
||||
|
|
@ -187,7 +234,7 @@ function! vimspector#Evaluate( expr ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#EvaluateConsole( expr ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
stopinsert
|
||||
|
|
@ -196,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
|
||||
|
|
@ -207,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',
|
||||
|
|
@ -217,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() '
|
||||
|
|
@ -262,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
|
||||
|
||||
|
|
@ -390,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()
|
||||
|
|
@ -402,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('
|
||||
|
|
@ -412,7 +459,7 @@ function! vimspector#CompleteInstall( ArgLead, CmdLine, CursorPos ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#Update( bang, ... ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
|
||||
|
|
@ -425,7 +472,7 @@ function! vimspector#Update( bang, ... ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#AbortInstall() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
|
||||
|
|
@ -434,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
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ nnoremap <silent> <Plug>VimspectorStepInto
|
|||
nnoremap <silent> <Plug>VimspectorStepOut
|
||||
\ :<c-u>call vimspector#StepOut()<CR>
|
||||
|
||||
nnoremap <silent> <Plug>VimspectorRunToCursor
|
||||
\ :<c-u>call vimspector#RunToCursor()<CR>
|
||||
|
||||
if s:mappings ==# 'VISUAL_STUDIO'
|
||||
nmap <F5> <Plug>VimspectorContinue
|
||||
nmap <S-F5> <Plug>VimspectorStop
|
||||
|
|
@ -80,6 +83,7 @@ elseif s:mappings ==# 'HUMAN'
|
|||
nmap <F9> <Plug>VimspectorToggleBreakpoint
|
||||
nmap <leader><F9> <Plug>VimspectorToggleConditionalBreakpoint
|
||||
nmap <F8> <Plug>VimspectorAddFunctionBreakpoint
|
||||
nmap <leader><F8> <Plug>VimspectorRunToCursor
|
||||
nmap <F10> <Plug>VimspectorStepOver
|
||||
nmap <F11> <Plug>VimspectorStepInto
|
||||
nmap <F12> <Plug>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( '<afile>' ) )
|
||||
augroup END
|
||||
|
||||
" boilerplate {{{
|
||||
|
|
|
|||
|
|
@ -141,50 +141,119 @@ class ProjectBreakpoints( object ):
|
|||
|
||||
self.UpdateUI()
|
||||
|
||||
def _FindLineBreakpoint( self, file_name, line ):
|
||||
file_name = os.path.abspath( file_name )
|
||||
for index, bp in enumerate( self._line_breakpoints[ file_name ] ):
|
||||
self._SignToLine( file_name, bp )
|
||||
if bp[ 'line' ] == line:
|
||||
return bp, index
|
||||
|
||||
return None, None
|
||||
|
||||
|
||||
def _PutLineBreakpoint( self, file_name, line, options ):
|
||||
self._line_breakpoints[ os.path.abspath( file_name ) ].append( {
|
||||
'state': 'ENABLED',
|
||||
'line': line,
|
||||
'options': options,
|
||||
# 'sign_id': <filled in when placed>,
|
||||
#
|
||||
# Used by other breakpoint types (specified in options):
|
||||
# 'condition': ...,
|
||||
# 'hitCondition': ...,
|
||||
# 'logMessage': ...
|
||||
} )
|
||||
|
||||
|
||||
def _DeleteLineBreakpoint( self, bp, file_name, index ):
|
||||
if 'sign_id' in bp:
|
||||
signs.UnplaceSign( bp[ 'sign_id' ], 'VimspectorBP' )
|
||||
del self._line_breakpoints[ os.path.abspath( file_name ) ][ index ]
|
||||
|
||||
|
||||
def ToggleBreakpoint( self, options ):
|
||||
line, column = vim.current.window.cursor
|
||||
line, _ = vim.current.window.cursor
|
||||
file_name = vim.current.buffer.name
|
||||
|
||||
if not file_name:
|
||||
return
|
||||
|
||||
found_bp = False
|
||||
action = 'New'
|
||||
for index, bp in enumerate( self._line_breakpoints[ file_name ] ):
|
||||
self._SignToLine( file_name, bp )
|
||||
if bp[ 'line' ] == line:
|
||||
found_bp = True
|
||||
if bp[ 'state' ] == 'ENABLED' and not self._connection:
|
||||
bp[ 'state' ] = 'DISABLED'
|
||||
action = 'Disable'
|
||||
else:
|
||||
if 'sign_id' in bp:
|
||||
signs.UnplaceSign( bp[ 'sign_id' ], 'VimspectorBP' )
|
||||
del self._line_breakpoints[ file_name ][ index ]
|
||||
action = 'Delete'
|
||||
break
|
||||
|
||||
self._logger.debug( "Toggle found bp at {}:{} ? {} ({})".format(
|
||||
file_name,
|
||||
line,
|
||||
found_bp,
|
||||
action ) )
|
||||
|
||||
if not found_bp:
|
||||
self._line_breakpoints[ file_name ].append( {
|
||||
'state': 'ENABLED',
|
||||
'line': line,
|
||||
'options': options,
|
||||
# 'sign_id': <filled in when placed>,
|
||||
#
|
||||
# Used by other breakpoint types (specified in options):
|
||||
# 'condition': ...,
|
||||
# 'hitCondition': ...,
|
||||
# 'logMessage': ...
|
||||
} )
|
||||
bp, index = self._FindLineBreakpoint( file_name, line )
|
||||
if bp is None:
|
||||
# ADD
|
||||
self._PutLineBreakpoint( file_name, line, options )
|
||||
elif bp[ 'state' ] == 'ENABLED' and not self._connection:
|
||||
# DISABLE
|
||||
bp[ 'state' ] = 'DISABLED'
|
||||
else:
|
||||
# DELETE
|
||||
self._DeleteLineBreakpoint( bp, file_name, index )
|
||||
|
||||
self.UpdateUI()
|
||||
|
||||
|
||||
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( then )
|
||||
|
||||
|
||||
def ClearLineBreakpoint( self, file_name, line_num ):
|
||||
bp, index = self._FindLineBreakpoint( file_name, line_num )
|
||||
if bp is None:
|
||||
return
|
||||
self._DeleteLineBreakpoint( bp, file_name, index )
|
||||
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',
|
||||
|
|
@ -200,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 ):
|
||||
|
|
@ -230,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()
|
||||
|
||||
|
||||
|
|
@ -243,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 )
|
||||
|
|
@ -259,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,
|
||||
|
|
@ -271,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': {
|
||||
|
|
@ -372,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:
|
||||
|
|
@ -386,17 +476,21 @@ class ProjectBreakpoints( object ):
|
|||
else 'vimspectorBPCond' if 'condition' in bp[ 'options' ]
|
||||
else 'vimspectorBP' )
|
||||
|
||||
signs.PlaceSign( bp[ 'sign_id' ],
|
||||
'VimspectorBP',
|
||||
sign,
|
||||
file_name,
|
||||
bp[ 'line' ] )
|
||||
if utils.BufferExists( file_name ):
|
||||
signs.PlaceSign( bp[ 'sign_id' ],
|
||||
'VimspectorBP',
|
||||
sign,
|
||||
file_name,
|
||||
bp[ 'line' ] )
|
||||
|
||||
|
||||
def _SignToLine( self, file_name, bp ):
|
||||
if 'sign_id' not in bp:
|
||||
return bp[ 'line' ]
|
||||
|
||||
if not utils.BufferExists( file_name ):
|
||||
return bp[ 'line' ]
|
||||
|
||||
signs = vim.eval( "sign_getplaced( '{}', {} )".format(
|
||||
utils.Escape( file_name ),
|
||||
json.dumps( { 'id': bp[ 'sign_id' ], 'group': 'VimspectorBP', } ) ) )
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,6 +1178,26 @@ class DebugSession( object ):
|
|||
def ToggleBreakpoint( self, options ):
|
||||
return self._breakpoints.ToggleBreakpoint( 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 )
|
||||
|
||||
def ClearBreakpoints( self ):
|
||||
if self._connection:
|
||||
self._codeView.ClearBreakpoints()
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ def DefineSign( name, text, double_text, texthl, col = 'right', **kwargs ):
|
|||
vim.command( cmd )
|
||||
|
||||
|
||||
def PlaceSign( sign_id, group, name, file, line ):
|
||||
def PlaceSign( sign_id, group, name, file_name, line ):
|
||||
priority = settings.Dict( 'sign_priority' )[ name ]
|
||||
|
||||
cmd = ( f'sign place { sign_id } '
|
||||
|
|
@ -37,7 +37,7 @@ def PlaceSign( sign_id, group, name, file, line ):
|
|||
f'name={ name } '
|
||||
f'priority={ priority } '
|
||||
f'line={ line } '
|
||||
f'file={ file }' )
|
||||
f'file={ file_name }' )
|
||||
|
||||
vim.command( cmd )
|
||||
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -45,14 +45,20 @@ _logger = logging.getLogger( __name__ )
|
|||
SetUpLogging( _logger )
|
||||
|
||||
|
||||
def BufferNumberForFile( file_name ):
|
||||
return int( vim.eval( "bufnr( '{0}', 1 )".format( Escape( file_name ) ) ) )
|
||||
def BufferNumberForFile( file_name, create = True ):
|
||||
return int( vim.eval( "bufnr( '{0}', {1} )".format(
|
||||
Escape( file_name ),
|
||||
int( create ) ) ) )
|
||||
|
||||
|
||||
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 )
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
9
support/test/python/simple_python/make_env.sh
Executable file
9
support/test/python/simple_python/make_env.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
cat <<"EOF"
|
||||
{
|
||||
"Something": "Value1",
|
||||
"SomethingElse": "Value2"
|
||||
}
|
||||
EOF
|
||||
|
||||
15
support/test/python/simple_python/print_env.py
Normal file
15
support/test/python/simple_python/print_env.py
Normal file
|
|
@ -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()
|
||||
|
||||
|
|
@ -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( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Disable the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBPDisabled',
|
||||
\ 9 )
|
||||
|
||||
" Delete the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
|
||||
" Add it again
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Here we go. Start Debugging
|
||||
call feedkeys( "\<F5>", '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( "\<F10>", '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( "\<F9>", '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( "\<F5>", '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( "\<F9>", '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'
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
\ } )
|
||||
|
|
|
|||
123
tests/mappings.test.vim
Normal file
123
tests/mappings.test.vim
Normal file
|
|
@ -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( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Disable the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBPDisabled',
|
||||
\ 9 )
|
||||
|
||||
" Delete the breakpoint
|
||||
call feedkeys( "\<F9>", '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( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Here we go. Start Debugging
|
||||
call feedkeys( "\<F5>", '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( "\<F10>", '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( "\\\<F8>", '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
|
||||
|
||||
200
tests/temporary_breakpoints.test.vim
Normal file
200
tests/temporary_breakpoints.test.vim
Normal file
|
|
@ -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
|
||||
22
tests/testdata/cpp/simple/.vimspector.json
vendored
22
tests/testdata/cpp/simple/.vimspector.json
vendored
|
|
@ -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": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue