start to track individual thread state
This commit is contained in:
parent
e9e0e9e5b9
commit
2399a79cae
2 changed files with 68 additions and 54 deletions
|
|
@ -16,26 +16,22 @@
|
||||||
import vim
|
import vim
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
import typing
|
||||||
|
|
||||||
from vimspector import utils
|
from vimspector import utils
|
||||||
|
|
||||||
|
|
||||||
# TODO: Need to do something a bit like the Variables stuff
|
class Thread:
|
||||||
#
|
PAUSED = 0
|
||||||
# class Thread:
|
RUNNING = 1
|
||||||
# PAUSED = 0
|
state = RUNNING
|
||||||
# RUNNING = 1
|
|
||||||
# state = RUNNING
|
thread: typing.Dict
|
||||||
#
|
stacktrace: typing.List[ typing.Dict ]
|
||||||
# thread: dict
|
|
||||||
# stacktrace: list
|
def __init__( self, thread ):
|
||||||
#
|
self.thread = thread
|
||||||
# def __init__( self, thread ):
|
self.stacktrace = None
|
||||||
# self.thread = thread
|
|
||||||
# self.stacktrace = None
|
|
||||||
#
|
|
||||||
# def ShouldExpand( self, current_thread_id ):
|
|
||||||
# return self.thread[ 'id' ] == current_thread_id
|
|
||||||
|
|
||||||
|
|
||||||
class StackTraceView( object ):
|
class StackTraceView( object ):
|
||||||
|
|
@ -44,6 +40,9 @@ class StackTraceView( object ):
|
||||||
REQUESTING = 1
|
REQUESTING = 1
|
||||||
PENDING = 2
|
PENDING = 2
|
||||||
|
|
||||||
|
_threads: list[ Thread ]
|
||||||
|
_line_to_thread = dict[ int, Thread ]
|
||||||
|
|
||||||
def __init__( self, session, win ):
|
def __init__( self, session, win ):
|
||||||
self._logger = logging.getLogger( __name__ )
|
self._logger = logging.getLogger( __name__ )
|
||||||
utils.SetUpLogging( self._logger )
|
utils.SetUpLogging( self._logger )
|
||||||
|
|
@ -63,10 +62,11 @@ class StackTraceView( object ):
|
||||||
utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' )
|
utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' )
|
||||||
utils.SetUpUIWindow( win )
|
utils.SetUpUIWindow( win )
|
||||||
|
|
||||||
vim.command( 'nnoremap <silent> <buffer> <CR> '
|
with utils.LetCurrentWindow( win ):
|
||||||
':<C-U>call vimspector#GoToFrame()<CR>' )
|
vim.command( 'nnoremap <silent> <buffer> <CR> '
|
||||||
vim.command( 'nnoremap <silent> <buffer> <2-LeftMouse> '
|
':<C-U>call vimspector#GoToFrame()<CR>' )
|
||||||
':<C-U>call vimspector#GoToFrame()<CR>' )
|
vim.command( 'nnoremap <silent> <buffer> <2-LeftMouse> '
|
||||||
|
':<C-U>call vimspector#GoToFrame()<CR>' )
|
||||||
|
|
||||||
self._line_to_frame = {}
|
self._line_to_frame = {}
|
||||||
self._line_to_thread = {}
|
self._line_to_thread = {}
|
||||||
|
|
@ -85,7 +85,7 @@ class StackTraceView( object ):
|
||||||
self._current_frame = None
|
self._current_frame = None
|
||||||
self._current_thread = None
|
self._current_thread = None
|
||||||
self._current_syntax = ""
|
self._current_syntax = ""
|
||||||
self._threads = []
|
self._threads.clear()
|
||||||
self._sources = {}
|
self._sources = {}
|
||||||
with utils.ModifiableScratchBuffer( self._buf ):
|
with utils.ModifiableScratchBuffer( self._buf ):
|
||||||
utils.ClearBuffer( self._buf )
|
utils.ClearBuffer( self._buf )
|
||||||
|
|
@ -134,16 +134,18 @@ class StackTraceView( object ):
|
||||||
self._threads.clear()
|
self._threads.clear()
|
||||||
|
|
||||||
requesting = False
|
requesting = False
|
||||||
for thread in message[ 'body' ][ 'threads' ]:
|
for t in message[ 'body' ][ 'threads' ]:
|
||||||
|
thread = Thread( t )
|
||||||
self._threads.append( thread )
|
self._threads.append( thread )
|
||||||
|
|
||||||
if infer_current_frame and thread[ 'id' ] == self._current_thread:
|
if infer_current_frame:
|
||||||
self._LoadStackTrace( thread, True, reason )
|
if thread.thread[ 'id' ] == self._current_thread:
|
||||||
requesting = True
|
self._LoadStackTrace( thread, True, reason )
|
||||||
elif infer_current_frame and self._current_thread is None:
|
requesting = True
|
||||||
self._current_thread = thread[ 'id' ]
|
elif self._current_thread is None:
|
||||||
self._LoadStackTrace( thread, True, reason )
|
self._current_thread = thread.thread[ 'id' ]
|
||||||
requesting = True
|
self._LoadStackTrace( thread, True, reason )
|
||||||
|
requesting = True
|
||||||
|
|
||||||
if not requesting:
|
if not requesting:
|
||||||
self._DrawThreads()
|
self._DrawThreads()
|
||||||
|
|
@ -158,7 +160,7 @@ class StackTraceView( object ):
|
||||||
'command': 'threads',
|
'command': 'threads',
|
||||||
}, failure_handler )
|
}, failure_handler )
|
||||||
|
|
||||||
def _DrawThreads( self, running = False ):
|
def _DrawThreads( self ):
|
||||||
self._line_to_frame.clear()
|
self._line_to_frame.clear()
|
||||||
self._line_to_thread.clear()
|
self._line_to_thread.clear()
|
||||||
|
|
||||||
|
|
@ -167,32 +169,33 @@ class StackTraceView( object ):
|
||||||
utils.ClearBuffer( self._buf )
|
utils.ClearBuffer( self._buf )
|
||||||
|
|
||||||
for thread in self._threads:
|
for thread in self._threads:
|
||||||
if self._current_thread == thread[ 'id' ]:
|
if self._current_thread == thread.thread[ 'id' ]:
|
||||||
icon = '^' if '_frames' not in thread else '>'
|
icon = '^' if thread.stacktrace is None else '>'
|
||||||
else:
|
else:
|
||||||
icon = '+' if '_frames' not in thread else '-'
|
icon = '+' if thread.stacktrace is None else '-'
|
||||||
|
|
||||||
# FIXME: We probably need per-thread status here
|
# FIXME: We probably need per-thread status here
|
||||||
if running:
|
if thread.state == Thread.RUNNING:
|
||||||
status = ' (running)'
|
status = ' (running)'
|
||||||
else:
|
else:
|
||||||
status = ''
|
status = ''
|
||||||
|
|
||||||
line = utils.AppendToBuffer(
|
line = utils.AppendToBuffer(
|
||||||
self._buf,
|
self._buf,
|
||||||
f'{icon} Thread: {thread["name"]}{status}' )
|
f'{icon} Thread: {thread.thread["name"]}{status}' )
|
||||||
|
|
||||||
self._line_to_thread[ line ] = thread
|
self._line_to_thread[ line ] = thread
|
||||||
self._DrawStackTrace( thread )
|
self._DrawStackTrace( thread )
|
||||||
|
|
||||||
def _LoadStackTrace( self,
|
def _LoadStackTrace( self,
|
||||||
thread,
|
thread: Thread,
|
||||||
infer_current_frame,
|
infer_current_frame,
|
||||||
reason = '' ):
|
reason = '' ):
|
||||||
|
|
||||||
def consume_stacktrace( message ):
|
def consume_stacktrace( message ):
|
||||||
thread[ '_frames' ] = message[ 'body' ][ 'stackFrames' ]
|
thread.stacktrace = message[ 'body' ][ 'stackFrames' ]
|
||||||
if infer_current_frame:
|
if infer_current_frame:
|
||||||
for frame in thread[ '_frames' ]:
|
for frame in thread.stacktrace:
|
||||||
if self._JumpToFrame( frame, reason ):
|
if self._JumpToFrame( frame, reason ):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
@ -201,7 +204,7 @@ class StackTraceView( object ):
|
||||||
self._connection.DoRequest( consume_stacktrace, {
|
self._connection.DoRequest( consume_stacktrace, {
|
||||||
'command': 'stackTrace',
|
'command': 'stackTrace',
|
||||||
'arguments': {
|
'arguments': {
|
||||||
'threadId': thread[ 'id' ],
|
'threadId': thread.thread[ 'id' ],
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
|
@ -215,8 +218,8 @@ class StackTraceView( object ):
|
||||||
self._JumpToFrame( self._line_to_frame[ current_line ] )
|
self._JumpToFrame( self._line_to_frame[ current_line ] )
|
||||||
elif current_line in self._line_to_thread:
|
elif current_line in self._line_to_thread:
|
||||||
thread = self._line_to_thread[ current_line ]
|
thread = self._line_to_thread[ current_line ]
|
||||||
if '_frames' in thread:
|
if thread.stacktrace is not None:
|
||||||
del thread[ '_frames' ]
|
thread.stacktrace = None
|
||||||
self._DrawThreads()
|
self._DrawThreads()
|
||||||
else:
|
else:
|
||||||
self._LoadStackTrace( thread, False )
|
self._LoadStackTrace( thread, False )
|
||||||
|
|
@ -241,18 +244,29 @@ class StackTraceView( object ):
|
||||||
return do_jump()
|
return do_jump()
|
||||||
|
|
||||||
def OnContinued( self, threadId = None ):
|
def OnContinued( self, threadId = None ):
|
||||||
# FIXME: This tends to create a very flickery stack trace when steppping.
|
for thread in self._threads:
|
||||||
# Maybe we shouldn't remove the frames, but just update the running status?
|
if threadId is None:
|
||||||
# for thread in self._threads:
|
thread.state = Thread.RUNNING
|
||||||
# if threadId is None or thread[ 'id' ] == threadId:
|
elif thread.thread[ 'id' ] == threadId:
|
||||||
# thread.pop( '_frames', None )
|
thread.state = Thread.RUNNING
|
||||||
self._DrawThreads( running=True )
|
break
|
||||||
|
|
||||||
|
self._DrawThreads()
|
||||||
|
|
||||||
def OnStopped( self, event ):
|
def OnStopped( self, event ):
|
||||||
if 'threadId' in event:
|
if 'threadId' in event:
|
||||||
self._current_thread = event[ 'threadId' ]
|
self._current_thread = event[ 'threadId' ]
|
||||||
elif event.get( 'allThreadsStopped', False ) and self._threads:
|
|
||||||
self._current_thread = self._threads[ 0 ][ 'id' ]
|
for thread in self._threads:
|
||||||
|
if thread.thread[ 'id' ] == event[ 'threadId' ]:
|
||||||
|
thread.state = Thread.PAUSED
|
||||||
|
break
|
||||||
|
elif event.get( 'allThreadsStopped', False ):
|
||||||
|
if self._threads:
|
||||||
|
self._current_thread = self._threads[ 0 ].thread[ 'id' ]
|
||||||
|
|
||||||
|
for thread in self._threads:
|
||||||
|
thread.state = Thread.PAUSED
|
||||||
|
|
||||||
self.LoadThreads( True, 'stopped' )
|
self.LoadThreads( True, 'stopped' )
|
||||||
|
|
||||||
|
|
@ -263,13 +277,11 @@ class StackTraceView( object ):
|
||||||
else:
|
else:
|
||||||
self.LoadThreads( False )
|
self.LoadThreads( False )
|
||||||
|
|
||||||
def _DrawStackTrace( self, thread ):
|
def _DrawStackTrace( self, thread: Thread ):
|
||||||
if '_frames' not in thread:
|
if thread.stacktrace is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
stackFrames = thread[ '_frames' ]
|
for frame in thread.stacktrace:
|
||||||
|
|
||||||
for frame in stackFrames:
|
|
||||||
if frame.get( 'source' ):
|
if frame.get( 'source' ):
|
||||||
source = frame[ 'source' ]
|
source = frame[ 'source' ]
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -347,3 +347,5 @@ function! Test_Multiple_Threads_Step()
|
||||||
call vimspector#test#setup#Reset()
|
call vimspector#test#setup#Reset()
|
||||||
%bwipe!
|
%bwipe!
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" TODO: Set current frame while thread is running sets the PC
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue