diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index c4a1756..39af248 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -220,6 +220,14 @@ function! vimspector#SetVariableValue( ... ) abort endif endfunction +function! vimspector#AddDataBreakpoint( ... ) abort + if !s:Enabled() + return + endif + " TODO: how to set options? + py3 _vimspector_session.AddDataBreakpoint( {} ) +endfunction + function! vimspector#DeleteWatch() abort if !s:Enabled() return diff --git a/python3/vimspector/breakpoints.py b/python3/vimspector/breakpoints.py index 7aa50ce..5c21140 100644 --- a/python3/vimspector/breakpoints.py +++ b/python3/vimspector/breakpoints.py @@ -45,6 +45,7 @@ class ProjectBreakpoints( object ): self._func_breakpoints = [] self._exception_breakpoints = None self._configured_breakpoints = {} + self._data_breakponts = [] # FIXME: Remove this. Remove breakpoints nonesense from code.py self._breakpoints_handler = None @@ -270,6 +271,18 @@ class ProjectBreakpoints( object ): # TODO: We don't really have aanything to update here, but if we're going to # have a UI list of them we should update that at this point + # but note that while debugging, this is when we actually _send_ the + # breakpoints. + self.UpdateUI() + + + def AddDataBreakpoint( self, dataId, options ): + self._data_breakponts.append( { + 'state': 'ENABLED', + 'dataId': dataId, + 'options': options, + } ) + self.UpdateUI() @@ -402,6 +415,27 @@ class ProjectBreakpoints( object ): failure_handler = response_received ) + if self._data_breakponts and self._server_capabilities[ + 'supportsDataBreakpoints' ]: + awaiting += 1 + breakpoints = [] + for bp in self._data_breakponts: + if bp[ 'state' ] != 'ENABLED': + continue + data_bp = {} + data_bp.update( bp[ 'options' ] ) + data_bp[ 'dataId' ] = bp[ 'dataId' ] + breakpoints.append( data_bp ) + + self._connection.DoRequest( + lambda msg: response_handler( None, None ), + { + 'command': 'setDataBreakpoints', + 'arguments': breakpoints, + }, + failure_handler = response_received + ) + if self._exception_breakpoints: awaiting = awaiting + 1 self._connection.DoRequest( @@ -494,6 +528,11 @@ class ProjectBreakpoints( object ): file_name, bp[ 'line' ] ) + # TODO could/should we show a sign in the variables view when there's a data + # brakpoint on the variable? Not sure how best to actually do that, but + # maybe the variable view can pass that info when calling AddDataBreakpoint, + # such as the variablesReference/name + def _SignToLine( self, file_name, bp ): if 'sign_id' not in bp: diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 03874f3..80fe75f 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -535,6 +535,21 @@ class DebugSession( object ): def SetVariableValue( self, new_value = None, buf = None, line_num = None ): self._variablesView.SetVariableValue( new_value, buf, line_num ) + @IfConnected() + def AddDataBreakpoint( self, opts, buf = None, line_num = None ): + def add_bp( breakpoint_info ): + if breakpoint_info[ 'dataId' ] is None: + utils.UserMessage( + "Can't set data breakpoint here: { breakpoint_info[ 'description' ] }" + ) + return + + # TODO: Ask the user about the possible DataBreakpointAccessType's and add + # that in to opts here + self._breakpoints.AddDataBreakpoint( breakpoint_info[ 'dataId' ], opts ) + + self._variablesView.GetDataBreakpointInfo( add_bp, buf, line_num ) + @IfConnected() def AddWatch( self, expression ): self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(), diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 8dcb493..8d8498a 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -580,6 +580,33 @@ class VariablesView( object ): }, failure_handler = failure_handler ) + def GetDataBreakpointInfo( self, + then, + buf = None, + line_num = None ): + variable: Variable + view: View + + if not self._server_capabilities.get( 'supportsDataBreakpoints' ): + return None + + variable, view = self._GetVariable( buf, line_num ) + if variable is None: + return None + + arguments = { + 'name': variable.variable[ 'name' ], + } + if variable.IsContained(): + arguments[ 'variablesReference' ] = ( + variable.container.VariablesReference() ) + + self._connection.DoRequest( lambda msg: then( msg[ 'body' ] ), { + 'command': 'dataBreakpointInfo', + 'arguments': arguments, + } ) + + def _DrawVariables( self, view, variables, indent, is_short = False ): assert indent > 0 diff --git a/support/test/go/hello_world/hello-world.go b/support/test/go/hello_world/hello-world.go index 673d1b2..efff2c0 100644 --- a/support/test/go/hello_world/hello-world.go +++ b/support/test/go/hello_world/hello-world.go @@ -1,6 +1,25 @@ package main import "fmt" + +type Toaster struct { + Power int + Colour string +} + +type Test struct { + Test string + Toast Toaster +} + func main() { var v = "test" + test := Test{ + Test: "This is\na\ntest", + Toast: Toaster{ + Power: 10, + Colour: "green", + }, + } fmt.Println("hello world: " + v) + fmt.Println("Hi " + test.Test) }