WIP: First sort-of untested attempt at readmemory request
This commit is contained in:
parent
1cbb400d42
commit
ba9cb2f6d3
5 changed files with 88 additions and 4 deletions
|
|
@ -223,6 +223,13 @@ function! vimspector#SetVariableValue( ... ) abort
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#ReadMemory() abort
|
||||||
|
if !s:Enabled()
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
py3 _vimspector_session.ReadMemory()
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! vimspector#DeleteWatch() abort
|
function! vimspector#DeleteWatch() abort
|
||||||
if !s:Enabled()
|
if !s:Enabled()
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
import vim
|
import vim
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from vimspector import utils, terminal, signs
|
from vimspector import utils, terminal, signs
|
||||||
|
|
@ -40,6 +41,7 @@ class CodeView( object ):
|
||||||
'breakpoints': []
|
'breakpoints': []
|
||||||
}
|
}
|
||||||
self._current_frame = None
|
self._current_frame = None
|
||||||
|
self._scratch_buffers = []
|
||||||
|
|
||||||
with utils.LetCurrentWindow( self._window ):
|
with utils.LetCurrentWindow( self._window ):
|
||||||
if utils.UseWinBar():
|
if utils.UseWinBar():
|
||||||
|
|
@ -173,6 +175,10 @@ class CodeView( object ):
|
||||||
self.ClearBreakpoints()
|
self.ClearBreakpoints()
|
||||||
self.Clear()
|
self.Clear()
|
||||||
|
|
||||||
|
for b in self._scratch_buffers:
|
||||||
|
utils.CleanUpHiddenBuffer( b )
|
||||||
|
self._scratch_buffers = []
|
||||||
|
|
||||||
def AddBreakpoints( self, source, breakpoints ):
|
def AddBreakpoints( self, source, breakpoints ):
|
||||||
for breakpoint in breakpoints:
|
for breakpoint in breakpoints:
|
||||||
source = breakpoint.get( 'source' ) or source
|
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
|
# FIXME: Change this tor return the PID rather than having debug_session
|
||||||
# work that out
|
# work that out
|
||||||
return self._terminal.buffer_number
|
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' ) )
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,32 @@ class DebugSession( object ):
|
||||||
def SetVariableValue( self, new_value = None, buf = None, line_num = None ):
|
def SetVariableValue( self, new_value = None, buf = None, line_num = None ):
|
||||||
self._variablesView.SetVariableValue( new_value, buf, line_num )
|
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()
|
@IfConnected()
|
||||||
def AddWatch( self, expression ):
|
def AddWatch( self, expression ):
|
||||||
self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(),
|
self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(),
|
||||||
|
|
@ -1163,7 +1189,8 @@ class DebugSession( object ):
|
||||||
'pathFormat': 'path',
|
'pathFormat': 'path',
|
||||||
'supportsVariableType': True,
|
'supportsVariableType': True,
|
||||||
'supportsVariablePaging': False,
|
'supportsVariablePaging': False,
|
||||||
'supportsRunInTerminalRequest': True
|
'supportsRunInTerminalRequest': True,
|
||||||
|
'supportsMemoryReferences': True
|
||||||
},
|
},
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ DEFAULTS = {
|
||||||
'variables': {
|
'variables': {
|
||||||
'expand_collapse': [ '<CR>', '<2-LeftMouse>' ],
|
'expand_collapse': [ '<CR>', '<2-LeftMouse>' ],
|
||||||
'delete': [ '<Del>' ],
|
'delete': [ '<Del>' ],
|
||||||
'set_value': [ '<C-CR>', '<leader><CR>' ]
|
'set_value': [ '<C-CR>', '<leader><CR>' ],
|
||||||
|
'read_memory': [ '<leader>m' ],
|
||||||
},
|
},
|
||||||
'stack_trace': {
|
'stack_trace': {
|
||||||
'expand_or_jump': [ '<CR>', '<2-LeftMouse>' ],
|
'expand_or_jump': [ '<CR>', '<2-LeftMouse>' ],
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ class Expandable:
|
||||||
def VariablesReference( self ):
|
def VariablesReference( self ):
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def MemoryReference( self ):
|
||||||
|
assert None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Scope( Expandable ):
|
class Scope( Expandable ):
|
||||||
"""Holds an expandable scope (a DAP scope dict), with expand/collapse state"""
|
"""Holds an expandable scope (a DAP scope dict), with expand/collapse state"""
|
||||||
|
|
@ -66,6 +71,9 @@ class Scope( Expandable ):
|
||||||
def VariablesReference( self ):
|
def VariablesReference( self ):
|
||||||
return self.scope.get( 'variablesReference', 0 )
|
return self.scope.get( 'variablesReference', 0 )
|
||||||
|
|
||||||
|
def MemoryReference( self ):
|
||||||
|
return None
|
||||||
|
|
||||||
def Update( self, scope ):
|
def Update( self, scope ):
|
||||||
self.scope = scope
|
self.scope = scope
|
||||||
|
|
||||||
|
|
@ -81,6 +89,9 @@ class WatchResult( Expandable ):
|
||||||
def VariablesReference( self ):
|
def VariablesReference( self ):
|
||||||
return self.result.get( 'variablesReference', 0 )
|
return self.result.get( 'variablesReference', 0 )
|
||||||
|
|
||||||
|
def MemoryReference( self ):
|
||||||
|
return self.result.get( 'memoryReference' )
|
||||||
|
|
||||||
def Update( self, result ):
|
def Update( self, result ):
|
||||||
self.changed = False
|
self.changed = False
|
||||||
if self.result[ 'result' ] != result[ 'result' ]:
|
if self.result[ 'result' ] != result[ 'result' ]:
|
||||||
|
|
@ -105,6 +116,9 @@ class Variable( Expandable ):
|
||||||
def VariablesReference( self ):
|
def VariablesReference( self ):
|
||||||
return self.variable.get( 'variablesReference', 0 )
|
return self.variable.get( 'variablesReference', 0 )
|
||||||
|
|
||||||
|
def MemoryReference( self ):
|
||||||
|
return self.variable.get( 'memoryReference' )
|
||||||
|
|
||||||
def Update( self, variable ):
|
def Update( self, variable ):
|
||||||
self.changed = False
|
self.changed = False
|
||||||
if self.variable[ 'value' ] != variable[ 'value' ]:
|
if self.variable[ 'value' ] != variable[ 'value' ]:
|
||||||
|
|
@ -163,6 +177,10 @@ def AddExpandMappings( mappings = None ):
|
||||||
for mapping in utils.GetVimList( mappings, 'set_value' ):
|
for mapping in utils.GetVimList( mappings, 'set_value' ):
|
||||||
vim.command( f'nnoremap <silent> <buffer> { mapping } '
|
vim.command( f'nnoremap <silent> <buffer> { mapping } '
|
||||||
':<C-u>call vimspector#SetVariableValue()<CR>' )
|
':<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 ):
|
class VariablesView( object ):
|
||||||
|
|
@ -187,6 +205,8 @@ class VariablesView( object ):
|
||||||
if utils.UseWinBar():
|
if utils.UseWinBar():
|
||||||
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
|
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
|
||||||
':call vimspector#SetVariableValue()<CR>' )
|
':call vimspector#SetVariableValue()<CR>' )
|
||||||
|
vim.command( 'nnoremenu <silent> 1.2 WinBar.Memory '
|
||||||
|
':call vimspector#ReadMemory()<CR>' )
|
||||||
AddExpandMappings( mappings )
|
AddExpandMappings( mappings )
|
||||||
|
|
||||||
# Set up the "Watches" buffer in the watches_win (and create a WinBar in
|
# 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>' )
|
':call vimspector#ExpandVariable()<CR>' )
|
||||||
vim.command( 'nnoremenu <silent> 1.3 WinBar.Delete '
|
vim.command( 'nnoremenu <silent> 1.3 WinBar.Delete '
|
||||||
':call vimspector#DeleteWatch()<CR>' )
|
':call vimspector#DeleteWatch()<CR>' )
|
||||||
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
|
vim.command( 'nnoremenu <silent> 1.4 WinBar.Set '
|
||||||
':call vimspector#SetVariableValue()<CR>' )
|
':call vimspector#SetVariableValue()<CR>' )
|
||||||
|
vim.command( 'nnoremenu <silent> 1.5 WinBar.Memory '
|
||||||
|
':call vimspector#ReadMemory()<CR>' )
|
||||||
|
|
||||||
# Set the (global!) balloon expr if supported
|
# Set the (global!) balloon expr if supported
|
||||||
has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) )
|
has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) )
|
||||||
|
|
@ -580,6 +602,14 @@ class VariablesView( object ):
|
||||||
}, failure_handler = failure_handler )
|
}, 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 ):
|
def _DrawVariables( self, view, variables, indent, is_short = False ):
|
||||||
assert indent > 0
|
assert indent > 0
|
||||||
|
|
@ -595,10 +625,12 @@ class VariablesView( object ):
|
||||||
value = variable.variable.get( 'value', '<unknown>' )
|
value = variable.variable.get( 'value', '<unknown>' )
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
marker = 'm' if variable.MemoryReference() is not None else ' '
|
||||||
|
marker += '*' if variable.changed else ' '
|
||||||
text = '{indent}{marker}{icon} {name} ({type_}): {value}'.format(
|
text = '{indent}{marker}{icon} {name} ({type_}): {value}'.format(
|
||||||
# We borrow 1 space of indent to draw the change marker
|
# We borrow 1 space of indent to draw the change marker
|
||||||
indent = ' ' * ( indent - 1 ),
|
indent = ' ' * ( indent - 1 ),
|
||||||
marker = '*' if variable.changed else ' ',
|
marker = marker,
|
||||||
icon = '+' if ( variable.IsExpandable()
|
icon = '+' if ( variable.IsExpandable()
|
||||||
and not variable.IsExpanded() ) else '-',
|
and not variable.IsExpanded() ) else '-',
|
||||||
name = variable.variable.get( 'name', '' ),
|
name = variable.variable.get( 'name', '' ),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue