Merge pull request #206 from puremourning/bugfixes
A number of Bugfixes
This commit is contained in:
commit
05b855e605
10 changed files with 96 additions and 46 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -17,3 +17,5 @@ README.md.toc.*
|
||||||
support/test/csharp/*.exe*
|
support/test/csharp/*.exe*
|
||||||
.neomake.log
|
.neomake.log
|
||||||
configurations/
|
configurations/
|
||||||
|
venv/
|
||||||
|
test-base/
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ function! s:SetUpHiddenBuffer( buffer ) abort
|
||||||
call setbufvar( a:buffer, '&bufhidden', 'hide' )
|
call setbufvar( a:buffer, '&bufhidden', 'hide' )
|
||||||
call setbufvar( a:buffer, '&wrap', 0 )
|
call setbufvar( a:buffer, '&wrap', 0 )
|
||||||
call setbufvar( a:buffer, '&swapfile', 0 )
|
call setbufvar( a:buffer, '&swapfile', 0 )
|
||||||
|
call setbufvar( a:buffer, '&textwidth', 0 )
|
||||||
call s:MakeBufferReadOnly( a:buffer )
|
call s:MakeBufferReadOnly( a:buffer )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,6 @@ class CodeView( object ):
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
'vertical': 1,
|
'vertical': 1,
|
||||||
'term_cols': 80,
|
|
||||||
'norestore': 1,
|
'norestore': 1,
|
||||||
'cwd': cwd,
|
'cwd': cwd,
|
||||||
'env': env,
|
'env': env,
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,13 @@ class DebugSession( object ):
|
||||||
|
|
||||||
self._run_on_server_exit = None
|
self._run_on_server_exit = None
|
||||||
|
|
||||||
|
self._configuration = None
|
||||||
|
self._adapter = None
|
||||||
|
|
||||||
self._ResetServerState()
|
self._ResetServerState()
|
||||||
|
|
||||||
def _ResetServerState( self ):
|
def _ResetServerState( self ):
|
||||||
self._connection = None
|
self._connection = None
|
||||||
self._configuration = None
|
|
||||||
self._init_complete = False
|
self._init_complete = False
|
||||||
self._launch_complete = False
|
self._launch_complete = False
|
||||||
self._on_init_complete_handlers = []
|
self._on_init_complete_handlers = []
|
||||||
|
|
@ -278,11 +280,7 @@ class DebugSession( object ):
|
||||||
start()
|
start()
|
||||||
|
|
||||||
def Restart( self ):
|
def Restart( self ):
|
||||||
# TODO: There is a restart message but isn't always supported.
|
if self._configuration is None or self._adapter is None:
|
||||||
# FIXME: For some reason this doesn't work when run from the WinBar. It just
|
|
||||||
# beeps and doesn't display the config selector. One option is to just not
|
|
||||||
# display the selector and restart with the same opitons.
|
|
||||||
if not self._configuration or not self._adapter:
|
|
||||||
return self.Start()
|
return self.Start()
|
||||||
|
|
||||||
self._StartWithConfiguration( self._configuration, self._adapter )
|
self._StartWithConfiguration( self._configuration, self._adapter )
|
||||||
|
|
@ -294,7 +292,8 @@ class DebugSession( object ):
|
||||||
if not self._connection:
|
if not self._connection:
|
||||||
utils.UserMessage(
|
utils.UserMessage(
|
||||||
'Vimspector not connected, start a debug session first',
|
'Vimspector not connected, start a debug session first',
|
||||||
persist=True, error=True )
|
persist=True,
|
||||||
|
error=True )
|
||||||
return
|
return
|
||||||
return fct( self, *args, **kwargs )
|
return fct( self, *args, **kwargs )
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
@ -595,6 +594,9 @@ class DebugSession( object ):
|
||||||
"Shutting down debug adapter..." )
|
"Shutting down debug adapter..." )
|
||||||
|
|
||||||
def handler( *args ):
|
def handler( *args ):
|
||||||
|
self._splash_screen = utils.HideSplash( self._api_prefix,
|
||||||
|
self._splash_screen )
|
||||||
|
|
||||||
if callback:
|
if callback:
|
||||||
self._logger.debug( "Setting server exit handler before disconnect" )
|
self._logger.debug( "Setting server exit handler before disconnect" )
|
||||||
assert not self._run_on_server_exit
|
assert not self._run_on_server_exit
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ class StackTraceView( object ):
|
||||||
|
|
||||||
self._threads = []
|
self._threads = []
|
||||||
self._sources = {}
|
self._sources = {}
|
||||||
|
self._scratch_buffers = []
|
||||||
|
|
||||||
utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' )
|
utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' )
|
||||||
|
|
||||||
|
|
@ -82,6 +83,11 @@ class StackTraceView( object ):
|
||||||
def Reset( self ):
|
def Reset( self ):
|
||||||
self.Clear()
|
self.Clear()
|
||||||
utils.CleanUpHiddenBuffer( self._buf )
|
utils.CleanUpHiddenBuffer( self._buf )
|
||||||
|
for b in self._scratch_buffers:
|
||||||
|
utils.CleanUpHiddenBuffer( b )
|
||||||
|
|
||||||
|
self._scratch_buffers = []
|
||||||
|
self._buf = None
|
||||||
|
|
||||||
def LoadThreads( self, infer_current_frame ):
|
def LoadThreads( self, infer_current_frame ):
|
||||||
pending_request = False
|
pending_request = False
|
||||||
|
|
@ -290,7 +296,8 @@ class StackTraceView( object ):
|
||||||
self._logger.debug( "Received source %s: %s", buf_name, msg )
|
self._logger.debug( "Received source %s: %s", buf_name, msg )
|
||||||
|
|
||||||
buf = utils.BufferForFile( buf_name )
|
buf = utils.BufferForFile( buf_name )
|
||||||
utils.SetUpScratchBuffer( buf, buf_name )
|
self._scratch_buffers.append( buf )
|
||||||
|
utils.SetUpHiddenBuffer( buf, buf_name )
|
||||||
source[ 'path' ] = buf_name
|
source[ 'path' ] = buf_name
|
||||||
with utils.ModifiableScratchBuffer( buf ):
|
with utils.ModifiableScratchBuffer( buf ):
|
||||||
utils.SetBufferContents( buf, msg[ 'body' ][ 'content' ] )
|
utils.SetBufferContents( buf, msg[ 'body' ][ 'content' ] )
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,14 @@ def BufferForFile( file_name ):
|
||||||
return vim.buffers[ BufferNumberForFile( file_name ) ]
|
return vim.buffers[ BufferNumberForFile( file_name ) ]
|
||||||
|
|
||||||
|
|
||||||
|
def WindowForBuffer( buf ):
|
||||||
|
for w in vim.current.tabpage.windows:
|
||||||
|
if w.buffer == buf:
|
||||||
|
return w
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def OpenFileInCurrentWindow( file_name ):
|
def OpenFileInCurrentWindow( file_name ):
|
||||||
buffer_number = BufferNumberForFile( file_name )
|
buffer_number = BufferNumberForFile( file_name )
|
||||||
try:
|
try:
|
||||||
|
|
@ -136,6 +144,7 @@ def SetUpPromptBuffer( buf, name, prompt, callback ):
|
||||||
def SetUpUIWindow( win ):
|
def SetUpUIWindow( win ):
|
||||||
win.options[ 'wrap' ] = False
|
win.options[ 'wrap' ] = False
|
||||||
win.options[ 'number' ] = False
|
win.options[ 'number' ] = False
|
||||||
|
win.options[ 'relativenumber' ] = False
|
||||||
win.options[ 'signcolumn' ] = 'no'
|
win.options[ 'signcolumn' ] = 'no'
|
||||||
win.options[ 'spell' ] = False
|
win.options[ 'spell' ] = False
|
||||||
win.options[ 'list' ] = False
|
win.options[ 'list' ] = False
|
||||||
|
|
@ -190,6 +199,18 @@ def RestoreCurrentBuffer( window ):
|
||||||
vim.current.buffer = old_buffer
|
vim.current.buffer = old_buffer
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def AnyWindowForBuffer( buf ):
|
||||||
|
# Only checks the current tab page, which is what we want
|
||||||
|
current_win = WindowForBuffer( buf )
|
||||||
|
if current_win is not None:
|
||||||
|
with LetCurrentWindow( current_win ):
|
||||||
|
yield
|
||||||
|
else:
|
||||||
|
with LetCurrentBuffer( buf ):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def LetCurrentWindow( window ):
|
def LetCurrentWindow( window ):
|
||||||
with RestoreCurrentWindow():
|
with RestoreCurrentWindow():
|
||||||
|
|
@ -566,11 +587,11 @@ def SetSyntax( current_syntax, syntax, *args ):
|
||||||
if current_syntax == syntax:
|
if current_syntax == syntax:
|
||||||
return
|
return
|
||||||
|
|
||||||
for buf in args:
|
|
||||||
with LetCurrentBuffer( buf ):
|
|
||||||
# We use set syn= because just setting vim.Buffer.options[ 'syntax' ]
|
# We use set syn= because just setting vim.Buffer.options[ 'syntax' ]
|
||||||
# doesn't actually trigger the Syntax autocommand, and i'm not sure that
|
# doesn't actually trigger the Syntax autocommand, and i'm not sure that
|
||||||
# 'doautocmd Syntax' is the right solution or not
|
# 'doautocmd Syntax' is the right solution or not
|
||||||
|
for buf in args:
|
||||||
|
with AnyWindowForBuffer( buf ):
|
||||||
vim.command( 'set syntax={}'.format( Escape( syntax ) ) )
|
vim.command( 'set syntax={}'.format( Escape( syntax ) ) )
|
||||||
|
|
||||||
return syntax
|
return syntax
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@ from vimspector import utils
|
||||||
|
|
||||||
|
|
||||||
class Expandable:
|
class Expandable:
|
||||||
|
EXPANDED_BY_USER = 2
|
||||||
|
EXPANDED_BY_US = 1
|
||||||
|
COLLAPSED_BY_USER = 0
|
||||||
|
COLLAPSED_BY_DEFAULT = None
|
||||||
|
|
||||||
"""Base for anything which might contain a hierarchy of values represented by
|
"""Base for anything which might contain a hierarchy of values represented by
|
||||||
a 'variablesReference' to be resolved by the 'variables' request. Records the
|
a 'variablesReference' to be resolved by the 'variables' request. Records the
|
||||||
current state expanded/collapsed. Implementations just implement
|
current state expanded/collapsed. Implementations just implement
|
||||||
|
|
@ -32,16 +37,13 @@ class Expandable:
|
||||||
# None is Falsy and represents collapsed _by default_. WHen set to False,
|
# None is Falsy and represents collapsed _by default_. WHen set to False,
|
||||||
# this means the user explicitly collapsed it. When True, the user expanded
|
# this means the user explicitly collapsed it. When True, the user expanded
|
||||||
# it (or we expanded it by default).
|
# it (or we expanded it by default).
|
||||||
self.expanded: bool = None
|
self.expanded: int = Expandable.COLLAPSED_BY_DEFAULT
|
||||||
|
|
||||||
def IsCollapsedByUser( self ):
|
def IsExpanded( self ):
|
||||||
return self.expanded is False
|
return bool( self.expanded )
|
||||||
|
|
||||||
def IsExpandedByUser( self ):
|
|
||||||
return self.expanded is True
|
|
||||||
|
|
||||||
def ShouldDrawDrillDown( self ):
|
def ShouldDrawDrillDown( self ):
|
||||||
return self.IsExpandedByUser() and self.variables is not None
|
return self.IsExpanded() and self.variables is not None
|
||||||
|
|
||||||
def IsExpandable( self ):
|
def IsExpandable( self ):
|
||||||
return self.VariablesReference() > 0
|
return self.VariablesReference() > 0
|
||||||
|
|
@ -205,6 +207,7 @@ class VariablesView( object ):
|
||||||
def LoadScopes( self, frame ):
|
def LoadScopes( self, frame ):
|
||||||
def scopes_consumer( message ):
|
def scopes_consumer( message ):
|
||||||
new_scopes = []
|
new_scopes = []
|
||||||
|
expanded_some_scope = False
|
||||||
for scope_body in message[ 'body' ][ 'scopes' ]:
|
for scope_body in message[ 'body' ][ 'scopes' ]:
|
||||||
# Find it in the scopes list
|
# Find it in the scopes list
|
||||||
found = False
|
found = False
|
||||||
|
|
@ -221,11 +224,17 @@ class VariablesView( object ):
|
||||||
|
|
||||||
new_scopes.append( scope )
|
new_scopes.append( scope )
|
||||||
|
|
||||||
if not scope.scope.get( 'expensive' ) and not scope.IsCollapsedByUser():
|
# Expand the first non-expensive scope which is not manually collapsed
|
||||||
# Expand any non-expensive scope which is not manually collapsed
|
if ( not expanded_some_scope
|
||||||
scope.expanded = True
|
and not scope.scope.get( 'expensive' )
|
||||||
|
and scope.expanded is not Expandable.COLLAPSED_BY_USER ):
|
||||||
|
scope.expanded = Expandable.EXPANDED_BY_US
|
||||||
|
expanded_some_scope = True
|
||||||
|
elif ( expanded_some_scope and scope.expanded is
|
||||||
|
Expandable.EXPANDED_BY_US ):
|
||||||
|
scope.expanded = Expandable.COLLAPSED_BY_DEFAULT
|
||||||
|
|
||||||
if scope.IsExpandedByUser():
|
if scope.IsExpanded():
|
||||||
self._connection.DoRequest( partial( self._ConsumeVariables,
|
self._connection.DoRequest( partial( self._ConsumeVariables,
|
||||||
self._DrawScopes,
|
self._DrawScopes,
|
||||||
scope ), {
|
scope ), {
|
||||||
|
|
@ -293,7 +302,7 @@ class VariablesView( object ):
|
||||||
watch.result = WatchResult( message[ 'body' ] )
|
watch.result = WatchResult( message[ 'body' ] )
|
||||||
|
|
||||||
if ( watch.result.IsExpandable() and
|
if ( watch.result.IsExpandable() and
|
||||||
watch.result.IsExpandedByUser() ):
|
watch.result.IsExpanded() ):
|
||||||
self._connection.DoRequest( partial( self._ConsumeVariables,
|
self._connection.DoRequest( partial( self._ConsumeVariables,
|
||||||
self._watch.draw,
|
self._watch.draw,
|
||||||
watch.result ), {
|
watch.result ), {
|
||||||
|
|
@ -319,16 +328,16 @@ class VariablesView( object ):
|
||||||
|
|
||||||
variable = view.lines[ current_line ]
|
variable = view.lines[ current_line ]
|
||||||
|
|
||||||
if variable.expanded:
|
if variable.IsExpanded():
|
||||||
# Collapse
|
# Collapse
|
||||||
variable.expanded = False
|
variable.expanded = Expandable.COLLAPSED_BY_USER
|
||||||
view.draw()
|
view.draw()
|
||||||
return
|
return
|
||||||
|
|
||||||
if not variable.IsExpandable():
|
if not variable.IsExpandable():
|
||||||
return
|
return
|
||||||
|
|
||||||
variable.expanded = True
|
variable.expanded = Expandable.EXPANDED_BY_USER
|
||||||
self._connection.DoRequest( partial( self._ConsumeVariables,
|
self._connection.DoRequest( partial( self._ConsumeVariables,
|
||||||
view.draw,
|
view.draw,
|
||||||
variable ), {
|
variable ), {
|
||||||
|
|
@ -348,11 +357,11 @@ class VariablesView( object ):
|
||||||
indent = ' ' * ( indent - 1 ),
|
indent = ' ' * ( indent - 1 ),
|
||||||
marker = '*' if variable.changed else ' ',
|
marker = '*' if variable.changed else ' ',
|
||||||
icon = '+' if ( variable.IsExpandable()
|
icon = '+' if ( variable.IsExpandable()
|
||||||
and not variable.IsExpandedByUser() ) else '-',
|
and not variable.IsExpanded() ) else '-',
|
||||||
name = variable.variable[ 'name' ],
|
name = variable.variable[ 'name' ],
|
||||||
type_ = variable.variable.get( 'type', '<unknown type>' ),
|
type_ = variable.variable.get( 'type', '' ),
|
||||||
value = variable.variable.get( 'value',
|
value = variable.variable.get( 'value',
|
||||||
'<unknown value>' ) ).split( '\n' ) )
|
'<unknown>' ) ).split( '\n' ) )
|
||||||
view.lines[ line ] = variable
|
view.lines[ line ] = variable
|
||||||
|
|
||||||
if variable.ShouldDrawDrillDown():
|
if variable.ShouldDrawDrillDown():
|
||||||
|
|
@ -386,7 +395,7 @@ class VariablesView( object ):
|
||||||
self._DrawWatchResult( 2, watch )
|
self._DrawWatchResult( 2, watch )
|
||||||
|
|
||||||
def _DrawScope( self, indent, scope ):
|
def _DrawScope( self, indent, scope ):
|
||||||
icon = '+' if scope.IsExpandable() and not scope.IsExpandedByUser() else '-'
|
icon = '+' if scope.IsExpandable() and not scope.IsExpanded() else '-'
|
||||||
|
|
||||||
line = utils.AppendToBuffer( self._vars.buf,
|
line = utils.AppendToBuffer( self._vars.buf,
|
||||||
'{0}{1} Scope: {2}'.format(
|
'{0}{1} Scope: {2}'.format(
|
||||||
|
|
@ -405,7 +414,7 @@ class VariablesView( object ):
|
||||||
|
|
||||||
assert indent > 0
|
assert indent > 0
|
||||||
icon = '+' if ( watch.result.IsExpandable() and
|
icon = '+' if ( watch.result.IsExpandable() and
|
||||||
not watch.result.IsExpandedByUser() ) else '-'
|
not watch.result.IsExpanded() ) else '-'
|
||||||
|
|
||||||
line = '{indent}{marker}{icon} Result: {result}'.format(
|
line = '{indent}{marker}{icon} Result: {result}'.format(
|
||||||
# We borrow 1 space of indent to draw the change marker
|
# We borrow 1 space of indent to draw the change marker
|
||||||
|
|
@ -442,7 +451,7 @@ class VariablesView( object ):
|
||||||
|
|
||||||
new_variables.append( variable )
|
new_variables.append( variable )
|
||||||
|
|
||||||
if variable.IsExpandable() and variable.IsExpandedByUser():
|
if variable.IsExpandable() and variable.IsExpanded():
|
||||||
self._connection.DoRequest( partial( self._ConsumeVariables,
|
self._connection.DoRequest( partial( self._ConsumeVariables,
|
||||||
draw,
|
draw,
|
||||||
variable ), {
|
variable ), {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
package com.vimspector.test;
|
package com.vimspector.test;
|
||||||
|
|
||||||
class Base {
|
public class Base
|
||||||
|
{
|
||||||
public String DoSomething()
|
public String DoSomething()
|
||||||
{
|
{
|
||||||
return "";
|
String s = new String();
|
||||||
|
s.replace( "A", "B" );
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,6 @@ public class TestApplication {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TestGeneric<T extends Base > {
|
|
||||||
T t;
|
|
||||||
public TestGeneric( T t ) {
|
|
||||||
this.t = t;
|
|
||||||
}
|
|
||||||
public void DoSomethingUseful() {
|
|
||||||
System.out.println( t.DoSomething() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T extends Base> void DoGeneric( T b ) {
|
private static <T extends Base> void DoGeneric( T b ) {
|
||||||
TestGeneric<T> foo = new TestGeneric<>( b );
|
TestGeneric<T> foo = new TestGeneric<>( b );
|
||||||
foo.DoSomethingUseful();
|
foo.DoSomethingUseful();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.vimspector.test;
|
||||||
|
|
||||||
|
class TestGeneric<T extends Base> {
|
||||||
|
T base;
|
||||||
|
|
||||||
|
public TestGeneric( T b )
|
||||||
|
{
|
||||||
|
this.base = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String DoSomethingUseful() {
|
||||||
|
String s = "A B C" + base.DoSomething();
|
||||||
|
|
||||||
|
return s.replace( "B", "C" );
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue