mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Fix set next statement with DAP. Fixes #1163
This commit is contained in:
parent
6a785aba08
commit
fcf8cf6503
5 changed files with 34 additions and 42 deletions
|
|
@ -1265,10 +1265,16 @@ class PyDB(object):
|
|||
from_this_thread.append(frame_custom_thread_id)
|
||||
|
||||
with self._threads_suspended_single_notification.notify_thread_suspended(thread_id, stop_reason):
|
||||
self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker)
|
||||
keep_suspended = self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker)
|
||||
|
||||
if keep_suspended:
|
||||
# This means that we should pause again after a set next statement.
|
||||
self._threads_suspended_single_notification.increment_suspend_time()
|
||||
self.do_wait_suspend(thread, frame, event, arg, is_unhandled_exception)
|
||||
|
||||
def _do_wait_suspend(self, thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker):
|
||||
info = thread.additional_info
|
||||
keep_suspended = False
|
||||
|
||||
if info.pydev_state == STATE_SUSPEND and not self._finish_debugging_session:
|
||||
in_main_thread = is_current_thread_main_thread()
|
||||
|
|
@ -1324,8 +1330,8 @@ class PyDB(object):
|
|||
self.writer.add_command(cmd)
|
||||
info.pydev_state = STATE_SUSPEND
|
||||
thread.stop_reason = CMD_SET_NEXT_STATEMENT
|
||||
self.do_wait_suspend(thread, frame, event, arg)
|
||||
return
|
||||
keep_suspended = True
|
||||
|
||||
else:
|
||||
# Set next did not work...
|
||||
info.pydev_step_cmd = -1
|
||||
|
|
@ -1333,8 +1339,7 @@ class PyDB(object):
|
|||
thread.stop_reason = CMD_THREAD_SUSPEND
|
||||
# return to the suspend state and wait for other command (without sending any
|
||||
# additional notification to the client).
|
||||
self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker)
|
||||
return
|
||||
return self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker)
|
||||
|
||||
elif info.pydev_step_cmd in (CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE):
|
||||
back_frame = frame.f_back
|
||||
|
|
@ -1370,6 +1375,8 @@ class PyDB(object):
|
|||
# print('Removing created frame: %s' % (frame_id,))
|
||||
self.writer.add_command(self.cmd_factory.make_thread_killed_message(frame_id))
|
||||
|
||||
return keep_suspended
|
||||
|
||||
def do_stop_on_unhandled_exception(self, thread, frame, frames_byid, arg):
|
||||
pydev_log.debug("We are stopping in post-mortem\n")
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -820,6 +820,7 @@ def test_hex_variables(case_setup):
|
|||
writer.finished_ok = True
|
||||
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Flaky on Jython.')
|
||||
def test_pause_and_continue(case_setup):
|
||||
with case_setup.test_file('_debugger_case_pause_continue.py') as writer:
|
||||
json_facade = JsonFacade(writer)
|
||||
|
|
@ -852,14 +853,13 @@ def test_pause_and_continue(case_setup):
|
|||
scope = pydevd_schema.Scope(**next(iter(scopes_response.body.scopes)))
|
||||
frame_variables_reference = scope.variablesReference
|
||||
|
||||
if not IS_JYTHON:
|
||||
set_variable_request = json_facade.write_request(
|
||||
pydevd_schema.SetVariableRequest(pydevd_schema.SetVariableArguments(
|
||||
frame_variables_reference, 'loop', 'False'
|
||||
)))
|
||||
set_variable_response = json_facade.wait_for_response(set_variable_request)
|
||||
set_variable_response_as_dict = set_variable_response.to_dict()['body']
|
||||
assert set_variable_response_as_dict == {'value': "False", 'type': 'bool'}
|
||||
set_variable_request = json_facade.write_request(
|
||||
pydevd_schema.SetVariableRequest(pydevd_schema.SetVariableArguments(
|
||||
frame_variables_reference, 'loop', 'False'
|
||||
)))
|
||||
set_variable_response = json_facade.wait_for_response(set_variable_request)
|
||||
set_variable_response_as_dict = set_variable_response.to_dict()['body']
|
||||
assert set_variable_response_as_dict == {'value': "False", 'type': 'bool'}
|
||||
|
||||
continue_request = json_facade.write_request(
|
||||
pydevd_schema.ContinueRequest(pydevd_schema.ContinueArguments('*')))
|
||||
|
|
|
|||
|
|
@ -1000,7 +1000,7 @@ INITIALIZE_RESPONSE = dict(
|
|||
supportsSetVariable=True,
|
||||
supportsValueFormattingOptions=True,
|
||||
supportTerminateDebuggee=True,
|
||||
supportsGotoTargetsRequest=False, # https://github.com/Microsoft/ptvsd/issues/1163
|
||||
supportsGotoTargetsRequest=True,
|
||||
exceptionBreakpointFilters=[
|
||||
{
|
||||
'filter': 'raised',
|
||||
|
|
@ -1244,6 +1244,10 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
self.internals_filter = InternalsFilter()
|
||||
self.new_thread_lock = threading.Lock()
|
||||
|
||||
# goto
|
||||
self.goto_target_map = IDMap()
|
||||
self.current_goto_request = None
|
||||
|
||||
# adapter state
|
||||
self._detached = False
|
||||
self._path_mappings_received = False
|
||||
|
|
@ -2085,30 +2089,11 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
@pydevd_events.handler(pydevd_comm.CMD_THREAD_SUSPEND)
|
||||
@async_handler
|
||||
def on_pydevd_thread_suspend(self, seq, args):
|
||||
xml = self.parse_xml_response(args)
|
||||
reason = int(xml.thread['stop_reason'])
|
||||
|
||||
# Normally, we rely on CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION instead,
|
||||
# but we only get this one in response to CMD_SET_NEXT_STATEMENT.
|
||||
if reason == pydevd_comm.CMD_SET_NEXT_STATEMENT:
|
||||
pyd_tid = xml.thread['id']
|
||||
vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
|
||||
self.send_event(
|
||||
'stopped',
|
||||
reason='pause',
|
||||
threadId=vsc_tid,
|
||||
allThreadsStopped=True)
|
||||
pass # We only care about the thread suspend single notification.
|
||||
|
||||
@pydevd_events.handler(pydevd_comm.CMD_THREAD_RUN)
|
||||
def on_pydevd_thread_run(self, seq, args):
|
||||
pyd_tid, reason = args.split('\t', 2)
|
||||
reason = int(reason)
|
||||
vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
|
||||
|
||||
# Normally, we rely on CMD_THREAD_RESUME_SINGLE_NOTIFICATION instead,
|
||||
# but we only get this one in response to CMD_SET_NEXT_STATEMENT.
|
||||
if reason == pydevd_comm.CMD_SET_NEXT_STATEMENT:
|
||||
self.send_event('continued', threadId=vsc_tid)
|
||||
pass # We only care about the thread suspend single notification.
|
||||
|
||||
@pydevd_events.handler(pydevd_comm_constants.CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION)
|
||||
@async_handler
|
||||
|
|
|
|||
|
|
@ -12,17 +12,18 @@ from tests.helpers.timeline import Event
|
|||
from tests.helpers.pattern import ANY
|
||||
|
||||
|
||||
@pytest.mark.skip(reason='https://github.com/Microsoft/ptvsd/issues/1163')
|
||||
def test_set_next_statement(pyfile, run_as, start_method):
|
||||
|
||||
@pyfile
|
||||
def code_to_debug():
|
||||
from dbgimporter import import_and_enable_debugger
|
||||
import_and_enable_debugger()
|
||||
|
||||
def func():
|
||||
print(1) #@inner1
|
||||
print(2) #@inner2
|
||||
print(3) #@outer3
|
||||
print(1) # @inner1
|
||||
print(2) # @inner2
|
||||
|
||||
print(3) # @outer3
|
||||
func()
|
||||
|
||||
line_numbers = get_marked_line_numbers(code_to_debug)
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ import threading
|
|||
import time
|
||||
import traceback
|
||||
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
clock = time.monotonic
|
||||
else:
|
||||
clock = time.clock
|
||||
|
||||
|
||||
timestamp_zero = clock()
|
||||
|
||||
|
||||
def timestamp():
|
||||
return clock() - timestamp_zero
|
||||
|
||||
|
|
@ -83,7 +82,7 @@ def get_marked_line_numbers(path):
|
|||
with open(path) as f:
|
||||
lines = {}
|
||||
for i, line in enumerate(f):
|
||||
match = re.search(r'#@\s*(.*?)\s*$', line)
|
||||
match = re.search(r'#\s*@\s*(.*?)\s*$', line)
|
||||
if match:
|
||||
marker = match.group(1)
|
||||
lines[marker] = i + 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue