diff --git a/docs/configuration.md b/docs/configuration.md index 199ebe9..97418e1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -24,7 +24,6 @@ things like: Along with optional additional configuration for things like: -- Function breakpoints - Exception breakpoints ### Debug adapter configuration @@ -109,6 +108,12 @@ But for now, consider the following example snippet: "--test-identifier", "${TestIdentifier}", "--secret-token", "${SecretToken}" ] + }, + "breakpoints": { + "exception": { + "caught": "", + "uncaught": "Y" + } } } } diff --git a/python3/vimspector/breakpoints.py b/python3/vimspector/breakpoints.py index a24d1de..01da54d 100644 --- a/python3/vimspector/breakpoints.py +++ b/python3/vimspector/breakpoints.py @@ -87,6 +87,7 @@ class ProjectBreakpoints( object ): else: for file_name, breakpoints in self._line_breakpoints.items(): for bp in breakpoints: + self._SignToLine( file_name, bp ) qf.append( { 'filename': file_name, 'lnum': bp[ 'line' ], @@ -113,6 +114,7 @@ class ProjectBreakpoints( object ): # These are the user-entered breakpoints. for file_name, breakpoints in self._line_breakpoints.items(): for bp in breakpoints: + self._SignToLine( file_name, bp ) if 'sign_id' in bp: vim.command( 'sign unplace {0} group=VimspectorBP'.format( bp[ 'sign_id' ] ) ) @@ -132,6 +134,7 @@ class ProjectBreakpoints( object ): 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: @@ -143,7 +146,7 @@ class ProjectBreakpoints( object ): bp[ 'sign_id' ] ) ) del self._line_breakpoints[ file_name ][ index ] action = 'Delete' - break + break self._logger.debug( "Toggle found bp at {}:{} ? {} ({})".format( file_name, @@ -215,6 +218,7 @@ class ProjectBreakpoints( object ): for file_name, line_breakpoints in self._line_breakpoints.items(): breakpoints = [] for bp in line_breakpoints: + self._SignToLine( file_name, bp ) if 'sign_id' in bp: vim.command( 'sign unplace {0} group=VimspectorBP'.format( bp[ 'sign_id' ] ) ) @@ -301,7 +305,7 @@ class ProjectBreakpoints( object ): if isinstance( result, bool ): result = 'Y' if result else 'N' - if not isinstance( result, str) or result not in ( 'Y', 'N', '' ): + if not isinstance( result, str ) or result not in ( 'Y', 'N', '' ): raise ValueError( f"Invalid value for exception breakpoint filter '{f}': " f"'{result}'. Must be boolean, 'Y', 'N' or '' (default)" ) @@ -330,6 +334,7 @@ class ProjectBreakpoints( object ): def _ShowBreakpoints( self ): for file_name, line_breakpoints in self._line_breakpoints.items(): for bp in line_breakpoints: + self._SignToLine( file_name, bp ) if 'sign_id' in bp: vim.command( 'sign unplace {0} group=VimspectorBP '.format( bp[ 'sign_id' ] ) ) @@ -344,3 +349,17 @@ class ProjectBreakpoints( object ): 'vimspectorBP' if bp[ 'state' ] == 'ENABLED' else 'vimspectorBPDisabled', file_name ) ) + + + def _SignToLine( self, file_name, bp ): + if 'sign_id' not in bp: + return bp[ 'line' ] + + signs = vim.eval( "sign_getplaced( '{}', {} )".format( + utils.Escape( file_name ), + json.dumps( { 'id': file_name, 'group': 'VimspectorBP', } ) ) ) + + if len( signs ) == 1 and len( signs[ 0 ][ 'signs' ] ) == 1: + bp[ 'line' ] = int( signs[ 0 ][ 'signs' ][ 0 ][ 'lnum' ] ) + + return bp[ 'line' ] diff --git a/run_tests b/run_tests index f2f8022..f216c58 100755 --- a/run_tests +++ b/run_tests @@ -4,9 +4,9 @@ RUN_VIM="vim --clean --not-a-term" RUN_TEST="${RUN_VIM} -S lib/run_test.vim" if [ -z "$VIMSPECTOR_MIMODE" ]; then - if which -s lldb; then + if which lldb >/dev/null 2>&1; then export VIMSPECTOR_MIMODE=lldb - elif which -s gdb; then + elif which gdb >/dev/null 2>&1; then export VIMSPECTOR_MIMODE=gdb else echo "Couldn't guess VIMSPECTOR_MIMODE. Need lldb or gdb in path" diff --git a/support/test/python/simple_python/.vimspector.json b/support/test/python/simple_python/.vimspector.json index 600295c..3de14d8 100644 --- a/support/test/python/simple_python/.vimspector.json +++ b/support/test/python/simple_python/.vimspector.json @@ -9,6 +9,12 @@ "program": "${file}", "stopOnEntry": true, "console": "integratedTerminal" + }, + "breakpoints": { + "exception": { + "raised": "N", + "uncaught": "" + } } }, "attach": { @@ -18,6 +24,12 @@ "type": "python", "host": "localhost", "port": "5678" + }, + "breakpoints": { + "exception": { + "raised": "N", + "uncaught": "" + } } } } diff --git a/tests/breakpoints.test.vim b/tests/breakpoints.test.vim index 9faf08e..1c36c08 100644 --- a/tests/breakpoints.test.vim +++ b/tests/breakpoints.test.vim @@ -246,3 +246,52 @@ function Test_DisableBreakpointWhileDebugging() lcd - %bwipeout! endfunction + +function! SetUp_Test_Insert_Code_Above_Breakpoint() + let g:vimspector_enable_mappings = 'HUMAN' +endfunction + +function! Test_Insert_Code_Above_Breakpoint() + let fn='main.py' + lcd ../support/test/python/simple_python + exe 'edit ' . fn + call setpos( '.', [ 0, 25, 5 ] ) + + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 25, 5 ) + call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 25 ) + + " Add the breakpoint + call feedkeys( "\", 'xt' ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', + \ 25, + \ 'vimspectorBP' ) + + " Insert a line above the breakpoint + call append( 22, ' # Test' ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 5 ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', + \ 26, + \ 'vimspectorBP' ) + + " CHeck that we break at the right point + call setpos( '.', [ 0, 1, 1 ] ) + call vimspector#LaunchWithSettings( { "configuration": "run" } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 ) + call vimspector#Reset() + call vimspector#test#setup#WaitForReset() + + " Toggle the breakpoint + call setpos( '.', [ 0, 26, 1 ] ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', + \ 26, + \ 'vimspectorBP' ) + call feedkeys( "\", 'xt' ) + call vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorBP', + \ 26, + \ 'vimspectorBPDisabled' ) + " Delete it + call feedkeys( "\", 'xt' ) + call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 26 ) + +endfunction diff --git a/tests/language_python.test.vim b/tests/language_python.test.vim index 5240fac..7bf95a8 100644 --- a/tests/language_python.test.vim +++ b/tests/language_python.test.vim @@ -6,11 +6,11 @@ function! ClearDown() call vimspector#test#setup#ClearDown() endfunction -function! SetUp_Test_Go_Simple() +function! SetUp_Test_Python_Simple() let g:vimspector_enable_mappings = 'HUMAN' endfunction -function! Test_Go_Simple() +function! Test_Python_Simple() let fn='main.py' lcd ../support/test/python/simple_python exe 'edit ' . fn @@ -28,16 +28,8 @@ function! Test_Go_Simple() call setpos( '.', [ 0, 1, 1 ] ) " Here we go. Start Debugging - pyx << EOF -from unittest.mock import patch -with patch( 'vimspector.utils.SelectFromList', - return_value=None ) as p: - with patch( 'vimspector.utils.AskForInput', - return_value=None ) as p: - vim.eval( 'vimspector#LaunchWithSettings( { "configuration": "run" } )' ) - vim.eval( 'vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 6, 1 )' ) - p.assert_called() -EOF + call vimspector#LaunchWithSettings( { "configuration": "run" } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 6, 1 ) " Step call feedkeys( "\", 'xt' ) diff --git a/tests/lib/autoload/vimspector/test/setup.vim b/tests/lib/autoload/vimspector/test/setup.vim index a1df8d5..6610647 100644 --- a/tests/lib/autoload/vimspector/test/setup.vim +++ b/tests/lib/autoload/vimspector/test/setup.vim @@ -16,8 +16,7 @@ endfunction function! vimspector#test#setup#ClearDown() abort endfunction -function! vimspector#test#setup#Reset() abort - call vimspector#Reset() +function! vimspector#test#setup#WaitForReset() abort call WaitForAssert( {-> \ assert_true( pyxeval( '_vimspector_session._connection is None' ) ) \ } ) @@ -26,6 +25,12 @@ function! vimspector#test#setup#Reset() abort \ }, 10000 ) call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorCode' ) +endfunction + +function! vimspector#test#setup#Reset() abort + call vimspector#Reset() + call vimspector#test#setup#WaitForReset() + call vimspector#ClearBreakpoints() call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorBP' )