WIP: First sort-of untested attempt at readmemory request

This commit is contained in:
Ben Jackson 2021-06-04 19:40:00 +01:00
commit ba9cb2f6d3
5 changed files with 88 additions and 4 deletions

View file

@ -223,6 +223,13 @@ function! vimspector#SetVariableValue( ... ) abort
endif
endfunction
function! vimspector#ReadMemory() abort
if !s:Enabled()
return
endif
py3 _vimspector_session.ReadMemory()
endfunction
function! vimspector#DeleteWatch() abort
if !s:Enabled()
return

View file

@ -16,6 +16,7 @@
import vim
import logging
import json
import os
from collections import defaultdict
from vimspector import utils, terminal, signs
@ -40,6 +41,7 @@ class CodeView( object ):
'breakpoints': []
}
self._current_frame = None
self._scratch_buffers = []
with utils.LetCurrentWindow( self._window ):
if utils.UseWinBar():
@ -173,6 +175,10 @@ class CodeView( object ):
self.ClearBreakpoints()
self.Clear()
for b in self._scratch_buffers:
utils.CleanUpHiddenBuffer( b )
self._scratch_buffers = []
def AddBreakpoints( self, source, breakpoints ):
for breakpoint in breakpoints:
source = breakpoint.get( 'source' ) or source
@ -287,3 +293,14 @@ class CodeView( object ):
# FIXME: Change this tor return the PID rather than having debug_session
# work that out
return self._terminal.buffer_number
def ShowMemory( self, memoryReference, msg ):
buf_name = os.path.join( '_vimspector_mem', memoryReference )
buf = utils.BufferForFile( buf_name )
self._scratch_buffers.append( buf )
utils.SetUpHiddenBuffer( buf, buf_name )
with utils.ModifiableScratchBuffer( buf ):
utils.SetBufferContents(
buf,
msg.get( 'body', {} ).get( 'data', 'Cannot read memory' ) )

View file

@ -535,6 +535,32 @@ class DebugSession( object ):
def SetVariableValue( self, new_value = None, buf = None, line_num = None ):
self._variablesView.SetVariableValue( new_value, buf, line_num )
@IfConnected()
def ReadMemory( self, buf = None, line_num = None ):
if not self._server_capabilities.get( 'supportsReadMemoryRequest' ):
utils.UserMessage( "Server does not support memory request",
error = True )
return
memoryReference = self._variablesView.GetMemoryReference( buf, line_num )
if memoryReference is None:
utils.UserMessage( "Cannot find memory reference for that",
error = True )
return
def handler( msg ):
self._codeView.ShowMemory( msg )
self._connection.DoRequest( handler, {
'command': 'readMemory',
'arguments': {
'memoryReference': memoryReference,
'count': 10 # TODO: What
}
} )
@IfConnected()
def AddWatch( self, expression ):
self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(),
@ -1163,7 +1189,8 @@ class DebugSession( object ):
'pathFormat': 'path',
'supportsVariableType': True,
'supportsVariablePaging': False,
'supportsRunInTerminalRequest': True
'supportsRunInTerminalRequest': True,
'supportsMemoryReferences': True
},
} )

View file

@ -54,7 +54,8 @@ DEFAULTS = {
'variables': {
'expand_collapse': [ '<CR>', '<2-LeftMouse>' ],
'delete': [ '<Del>' ],
'set_value': [ '<C-CR>', '<leader><CR>' ]
'set_value': [ '<C-CR>', '<leader><CR>' ],
'read_memory': [ '<leader>m' ],
},
'stack_trace': {
'expand_or_jump': [ '<CR>', '<2-LeftMouse>' ],

View file

@ -56,6 +56,11 @@ class Expandable:
def VariablesReference( self ):
assert False
@abc.abstractmethod
def MemoryReference( self ):
assert None
class Scope( Expandable ):
"""Holds an expandable scope (a DAP scope dict), with expand/collapse state"""
@ -66,6 +71,9 @@ class Scope( Expandable ):
def VariablesReference( self ):
return self.scope.get( 'variablesReference', 0 )
def MemoryReference( self ):
return None
def Update( self, scope ):
self.scope = scope
@ -81,6 +89,9 @@ class WatchResult( Expandable ):
def VariablesReference( self ):
return self.result.get( 'variablesReference', 0 )
def MemoryReference( self ):
return self.result.get( 'memoryReference' )
def Update( self, result ):
self.changed = False
if self.result[ 'result' ] != result[ 'result' ]:
@ -105,6 +116,9 @@ class Variable( Expandable ):
def VariablesReference( self ):
return self.variable.get( 'variablesReference', 0 )
def MemoryReference( self ):
return self.variable.get( 'memoryReference' )
def Update( self, variable ):
self.changed = False
if self.variable[ 'value' ] != variable[ 'value' ]:
@ -163,6 +177,10 @@ def AddExpandMappings( mappings = None ):
for mapping in utils.GetVimList( mappings, 'set_value' ):
vim.command( f'nnoremap <silent> <buffer> { mapping } '
':<C-u>call vimspector#SetVariableValue()<CR>' )
for mapping in utils.GetVimList( mappings, 'read_memory' ):
vim.command( f'nnoremap <silent> <buffer> { mapping } '
':<C-u>call vimspector#ReadMemory()<CR>' )
class VariablesView( object ):
@ -187,6 +205,8 @@ class VariablesView( object ):
if utils.UseWinBar():
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
':call vimspector#SetVariableValue()<CR>' )
vim.command( 'nnoremenu <silent> 1.2 WinBar.Memory '
':call vimspector#ReadMemory()<CR>' )
AddExpandMappings( mappings )
# Set up the "Watches" buffer in the watches_win (and create a WinBar in
@ -211,8 +231,10 @@ class VariablesView( object ):
':call vimspector#ExpandVariable()<CR>' )
vim.command( 'nnoremenu <silent> 1.3 WinBar.Delete '
':call vimspector#DeleteWatch()<CR>' )
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
vim.command( 'nnoremenu <silent> 1.4 WinBar.Set '
':call vimspector#SetVariableValue()<CR>' )
vim.command( 'nnoremenu <silent> 1.5 WinBar.Memory '
':call vimspector#ReadMemory()<CR>' )
# Set the (global!) balloon expr if supported
has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) )
@ -580,6 +602,14 @@ class VariablesView( object ):
}, failure_handler = failure_handler )
def GetMemoryReference( self, buf = None, line_num = None ):
# Get a memoryReference for use in a ReadMemory request
variable, _ = self._GetVariable( buf, line_num )
if variable is None:
return None
return variable.MemoryReference()
def _DrawVariables( self, view, variables, indent, is_short = False ):
assert indent > 0
@ -595,10 +625,12 @@ class VariablesView( object ):
value = variable.variable.get( 'value', '<unknown>' )
)
else:
marker = 'm' if variable.MemoryReference() is not None else ' '
marker += '*' if variable.changed else ' '
text = '{indent}{marker}{icon} {name} ({type_}): {value}'.format(
# We borrow 1 space of indent to draw the change marker
indent = ' ' * ( indent - 1 ),
marker = '*' if variable.changed else ' ',
marker = marker,
icon = '+' if ( variable.IsExpandable()
and not variable.IsExpanded() ) else '-',
name = variable.variable.get( 'name', '' ),