mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/ultimate
This commit is contained in:
+36
-113
@@ -1,5 +1,6 @@
|
||||
#IMPORTANT: pydevd_constants must be the 1st thing defined because it'll keep a reference to the original sys._getframe
|
||||
from pydevd_constants import * #@UnusedWildImport
|
||||
from pydevd_breakpoints import * #@UnusedWildImport
|
||||
|
||||
from pydevd_comm import CMD_CHANGE_VARIABLE, \
|
||||
CMD_EVALUATE_EXPRESSION, \
|
||||
@@ -52,6 +53,7 @@ import pydevd_tracing
|
||||
import pydevd_io
|
||||
from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
|
||||
import time
|
||||
|
||||
threadingEnumerate = threading.enumerate
|
||||
threadingCurrentThread = threading.currentThread
|
||||
|
||||
@@ -126,95 +128,6 @@ class PyDBCommandThread(PyDBDaemonThread):
|
||||
#only got this error in interpreter shutdown
|
||||
#PydevdLog(0, 'Finishing debug communication...(3)')
|
||||
|
||||
|
||||
_original_excepthook = None
|
||||
_handle_exceptions = None
|
||||
_exception_set = set()
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# excepthook
|
||||
#=======================================================================================================================
|
||||
def excepthook(exctype, value, tb):
|
||||
if _handle_exceptions is not None:
|
||||
if not issubclass(exctype, _handle_exceptions):
|
||||
return _original_excepthook(exctype, value, tb)
|
||||
|
||||
#Always call the original excepthook before going on to call the debugger post mortem to show it.
|
||||
_original_excepthook(exctype, value, tb)
|
||||
|
||||
frames = []
|
||||
|
||||
traceback = tb
|
||||
while tb:
|
||||
frames.append(tb.tb_frame)
|
||||
tb = tb.tb_next
|
||||
|
||||
thread = threadingCurrentThread()
|
||||
frames_byid = dict([(id(frame),frame) for frame in frames])
|
||||
frame = frames[-1]
|
||||
thread.additionalInfo.pydev_force_stop_at_exception = (frame, frames_byid)
|
||||
thread.additionalInfo.message = exctype.__name__
|
||||
#sys.exc_info = lambda : (exctype, value, traceback)
|
||||
debugger = GetGlobalDebugger()
|
||||
debugger.force_post_mortem_stop += 1
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# set_pm_excepthook
|
||||
#=======================================================================================================================
|
||||
def set_pm_excepthook(handle_exceptions=None):
|
||||
'''
|
||||
Should be called to register the excepthook to be used.
|
||||
|
||||
It's only useful for uncaucht exceptions. I.e.: exceptions that go up to the excepthook.
|
||||
|
||||
Can receive a parameter to stop only on some exceptions.
|
||||
|
||||
E.g.:
|
||||
register_excepthook((IndexError, ValueError))
|
||||
|
||||
or
|
||||
|
||||
register_excepthook(IndexError)
|
||||
|
||||
if passed without a parameter, will break on any exception
|
||||
|
||||
@param handle_exceptions: exception or tuple(exceptions)
|
||||
The exceptions that should be handled.
|
||||
'''
|
||||
global _handle_exceptions
|
||||
global _original_excepthook
|
||||
if sys.excepthook != excepthook:
|
||||
#Only keep the original if it's not our own excepthook (if called many times).
|
||||
_original_excepthook = sys.excepthook
|
||||
|
||||
_handle_exceptions = handle_exceptions
|
||||
sys.excepthook = excepthook
|
||||
|
||||
def restore_pm_excepthook():
|
||||
global _original_excepthook
|
||||
if (_original_excepthook):
|
||||
sys.excepthook = _original_excepthook
|
||||
_original_excepthook = None
|
||||
|
||||
|
||||
def update_exception_hook():
|
||||
if len(_exception_set) >0:
|
||||
set_pm_excepthook(tuple(_exception_set))
|
||||
else:
|
||||
restore_pm_excepthook()
|
||||
|
||||
def get_class( kls ):
|
||||
parts = kls.split('.')
|
||||
module = ".".join(parts[:-1])
|
||||
if (module == ""):
|
||||
module = "__builtin__"
|
||||
m = __import__( module )
|
||||
for comp in parts[-1:]:
|
||||
m = getattr(m, comp)
|
||||
return m
|
||||
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
@@ -437,7 +350,23 @@ class PyDB:
|
||||
|
||||
finally:
|
||||
self.release()
|
||||
|
||||
|
||||
def enable_tracing(self):
|
||||
#and enable the tracing for existing threads (because there may be frames being executed that
|
||||
#are currently untraced).
|
||||
threads = threadingEnumerate()
|
||||
for t in threads:
|
||||
if not t.getName().startswith('pydevd.'):
|
||||
#TODO: optimize so that we only actually add that tracing if it's in
|
||||
#the new breakpoint context.
|
||||
additionalInfo = getattr(t, 'additionalInfo', None)
|
||||
|
||||
if additionalInfo is not None:
|
||||
for frame in additionalInfo.IterFrames():
|
||||
frame.f_trace = self.trace_dispatch
|
||||
SetTraceForParents(frame, self.trace_dispatch)
|
||||
del frame
|
||||
|
||||
def processNetCommand(self, cmd_id, seq, text):
|
||||
'''Processes a command received from the Java side
|
||||
|
||||
@@ -628,25 +557,8 @@ class PyDB:
|
||||
|
||||
|
||||
self.breakpoints[file] = breakDict
|
||||
|
||||
#and enable the tracing for existing threads (because there may be frames being executed that
|
||||
#are currently untraced).
|
||||
threads = threadingEnumerate()
|
||||
for t in threads:
|
||||
if not t.getName().startswith('pydevd.'):
|
||||
#TODO: optimize so that we only actually add that tracing if it's in
|
||||
#the new breakpoint context.
|
||||
additionalInfo = None
|
||||
try:
|
||||
additionalInfo = t.additionalInfo
|
||||
except AttributeError:
|
||||
pass #that's ok, no info currently set
|
||||
|
||||
if additionalInfo is not None:
|
||||
for frame in additionalInfo.IterFrames():
|
||||
frame.f_trace = self.trace_dispatch
|
||||
SetTraceForParents(frame, self.trace_dispatch)
|
||||
del frame
|
||||
|
||||
self.enable_tracing()
|
||||
|
||||
elif cmd_id == CMD_REMOVE_BREAK:
|
||||
#command to remove some breakpoint
|
||||
@@ -685,17 +597,28 @@ class PyDB:
|
||||
self.postInternalCommand(int_cmd, thread_id)
|
||||
|
||||
elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
|
||||
exception = text
|
||||
global exception_set
|
||||
exception, notify_always, notify_on_terminate = text.split('\t', 2)
|
||||
exc_type = get_class(exception)
|
||||
is_notify_always = int(notify_always) == 1
|
||||
is_notify_on_terminate = int(notify_on_terminate) == 1
|
||||
|
||||
if exc_type is not None:
|
||||
_exception_set.add(exc_type)
|
||||
update_exception_hook()
|
||||
exception_set.add(ExceptionBreakpoint(exc_type, is_notify_always, is_notify_on_terminate))
|
||||
|
||||
if is_notify_on_terminate:
|
||||
update_exception_hook()
|
||||
if is_notify_always:
|
||||
global always_exception_set
|
||||
always_exception_set.add(exc_type)
|
||||
self.enable_tracing()
|
||||
|
||||
elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
|
||||
exception = text
|
||||
exc_type = get_class(exception)
|
||||
if exc_type is not None:
|
||||
_exception_set.remove(exc_type)
|
||||
exception_set.remove(exc_type)
|
||||
always_exception_set.remove(exc_type)
|
||||
update_exception_hook()
|
||||
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import sys
|
||||
|
||||
_original_excepthook = None
|
||||
_handle_exceptions = None
|
||||
exception_set = set()
|
||||
always_exception_set = set()
|
||||
|
||||
NOTIFY_ALWAYS="NOTIFY_ALWAYS"
|
||||
NOTIFY_ON_TERMINATE="NOTIFY_ON_TERMINATE"
|
||||
|
||||
import threading
|
||||
threadingCurrentThread = threading.currentThread
|
||||
|
||||
from pydevd_comm import GetGlobalDebugger
|
||||
|
||||
class ExceptionBreakpoint:
|
||||
def __init__(self, exctype, notify_always, notify_on_terminate):
|
||||
self.name = exctype.__name__
|
||||
self.type = exctype
|
||||
self.notify = {NOTIFY_ALWAYS: notify_always, NOTIFY_ON_TERMINATE: notify_on_terminate}
|
||||
|
||||
def get_exception_breakpoint(exctype, exceptions, notify_class):
|
||||
exc = None
|
||||
if exceptions is not None:
|
||||
for e in exceptions:
|
||||
if e.notify[notify_class] and issubclass(exctype, e.type):
|
||||
if exc is None or issubclass(e.type, exc.type):
|
||||
exc = e
|
||||
return exc
|
||||
|
||||
#=======================================================================================================================
|
||||
# excepthook
|
||||
#=======================================================================================================================
|
||||
def excepthook(exctype, value, tb):
|
||||
global _handle_exceptions
|
||||
if _handle_exceptions is not None:
|
||||
exception_breakpoint = get_exception_breakpoint(exctype, _handle_exceptions, NOTIFY_ON_TERMINATE)
|
||||
else:
|
||||
exception_breakpoint = None
|
||||
|
||||
if exception_breakpoint is None:
|
||||
return _original_excepthook(exctype, value, tb)
|
||||
|
||||
#Always call the original excepthook before going on to call the debugger post mortem to show it.
|
||||
_original_excepthook(exctype, value, tb)
|
||||
|
||||
frames = []
|
||||
|
||||
traceback = tb
|
||||
while tb:
|
||||
frames.append(tb.tb_frame)
|
||||
tb = tb.tb_next
|
||||
|
||||
thread = threadingCurrentThread()
|
||||
frames_byid = dict([(id(frame),frame) for frame in frames])
|
||||
frame = frames[-1]
|
||||
thread.additionalInfo.pydev_force_stop_at_exception = (frame, frames_byid)
|
||||
thread.additionalInfo.message = exception_breakpoint.name
|
||||
#sys.exc_info = lambda : (exctype, value, traceback)
|
||||
debugger = GetGlobalDebugger()
|
||||
debugger.force_post_mortem_stop += 1
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# set_pm_excepthook
|
||||
#=======================================================================================================================
|
||||
def set_pm_excepthook(handle_exceptions_arg=None):
|
||||
'''
|
||||
Should be called to register the excepthook to be used.
|
||||
|
||||
It's only useful for uncaucht exceptions. I.e.: exceptions that go up to the excepthook.
|
||||
|
||||
Can receive a parameter to stop only on some exceptions.
|
||||
|
||||
E.g.:
|
||||
register_excepthook((IndexError, ValueError))
|
||||
|
||||
or
|
||||
|
||||
register_excepthook(IndexError)
|
||||
|
||||
if passed without a parameter, will break on any exception
|
||||
|
||||
@param handle_exceptions: exception or tuple(exceptions)
|
||||
The exceptions that should be handled.
|
||||
'''
|
||||
global _handle_exceptions
|
||||
global _original_excepthook
|
||||
if sys.excepthook != excepthook:
|
||||
#Only keep the original if it's not our own excepthook (if called many times).
|
||||
_original_excepthook = sys.excepthook
|
||||
|
||||
_handle_exceptions = handle_exceptions_arg
|
||||
sys.excepthook = excepthook
|
||||
|
||||
def restore_pm_excepthook():
|
||||
global _original_excepthook
|
||||
if (_original_excepthook):
|
||||
sys.excepthook = _original_excepthook
|
||||
_original_excepthook = None
|
||||
|
||||
|
||||
def update_exception_hook():
|
||||
if len(exception_set) >0:
|
||||
set_pm_excepthook(tuple(exception_set))
|
||||
else:
|
||||
restore_pm_excepthook()
|
||||
|
||||
def get_class( kls ):
|
||||
parts = kls.split('.')
|
||||
module = ".".join(parts[:-1])
|
||||
if (module == ""):
|
||||
module = "__builtin__"
|
||||
m = __import__( module )
|
||||
for comp in parts[-1:]:
|
||||
m = getattr(m, comp)
|
||||
return m
|
||||
@@ -1,8 +1,10 @@
|
||||
from pydevd_comm import * #@UnusedWildImport
|
||||
from pydevd_constants import * #@UnusedWildImport
|
||||
from pydevd_breakpoints import * #@UnusedWildImport
|
||||
import traceback #@Reimport
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
basename = os.path.basename
|
||||
|
||||
#=======================================================================================================================
|
||||
@@ -28,64 +30,70 @@ class PyDBFrame:
|
||||
def trace_dispatch(self, frame, event, arg):
|
||||
if event not in ('line', 'call', 'return', 'exception'):
|
||||
return None
|
||||
|
||||
|
||||
mainDebugger, filename, info, thread = self._args
|
||||
|
||||
breakpoint = mainDebugger.breakpoints.get(filename)
|
||||
|
||||
if info.pydev_state == STATE_RUN:
|
||||
#we can skip if:
|
||||
#- we have no stop marked
|
||||
#- we should make a step return/step over and we're not in the current frame
|
||||
can_skip = (info.pydev_step_cmd is None and info.pydev_step_stop is None)\
|
||||
or (info.pydev_step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and info.pydev_step_stop is not frame)
|
||||
else:
|
||||
if event is not 'exception':
|
||||
breakpoint = mainDebugger.breakpoints.get(filename)
|
||||
|
||||
can_skip = False
|
||||
|
||||
# Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint,
|
||||
# we will return nothing for the next trace
|
||||
#also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway,
|
||||
#so, that's why the additional checks are there.
|
||||
if not breakpoint:
|
||||
if can_skip:
|
||||
return None
|
||||
if len(always_exception_set) == 0:
|
||||
if info.pydev_state == STATE_RUN:
|
||||
#we can skip if:
|
||||
#- we have no stop marked
|
||||
#- we should make a step return/step over and we're not in the current frame
|
||||
can_skip = (info.pydev_step_cmd is None and info.pydev_step_stop is None)\
|
||||
or (info.pydev_step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and info.pydev_step_stop is not frame)
|
||||
|
||||
else:
|
||||
#checks the breakpoint to see if there is a context match in some function
|
||||
curr_func_name = frame.f_code.co_name
|
||||
|
||||
#global context is set with an empty name
|
||||
if curr_func_name in ('?', '<module>'):
|
||||
curr_func_name = ''
|
||||
|
||||
for _b, condition, func_name, expression in breakpoint.values(): #jython does not support itervalues()
|
||||
#will match either global or some function
|
||||
if func_name in ('None', curr_func_name):
|
||||
break
|
||||
|
||||
else: # if we had some break, it won't get here (so, that's a context that we want to skip)
|
||||
|
||||
# Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint,
|
||||
# we will return nothing for the next trace
|
||||
#also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway,
|
||||
#so, that's why the additional checks are there.
|
||||
if not breakpoint:
|
||||
if can_skip:
|
||||
#print 'skipping', frame.f_lineno, info.pydev_state, info.pydev_step_stop, info.pydev_step_cmd
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
else:
|
||||
#checks the breakpoint to see if there is a context match in some function
|
||||
curr_func_name = frame.f_code.co_name
|
||||
|
||||
#global context is set with an empty name
|
||||
if curr_func_name in ('?', '<module>'):
|
||||
curr_func_name = ''
|
||||
|
||||
for _b, condition, func_name, expression in breakpoint.values(): #jython does not support itervalues()
|
||||
#will match either global or some function
|
||||
if func_name in ('None', curr_func_name):
|
||||
break
|
||||
|
||||
else: # if we had some break, it won't get here (so, that's a context that we want to skip)
|
||||
if can_skip:
|
||||
#print 'skipping', frame.f_lineno, info.pydev_state, info.pydev_step_stop, info.pydev_step_cmd
|
||||
return None
|
||||
else:
|
||||
breakpoint = None
|
||||
|
||||
#We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame
|
||||
#print 'NOT skipped', frame.f_lineno, frame.f_code.co_name
|
||||
#print 'NOT skipped', frame.f_lineno, frame.f_code.co_name, event
|
||||
|
||||
|
||||
try:
|
||||
line = frame.f_lineno
|
||||
|
||||
#if event == 'exception' and info.pydev_state != STATE_SUSPEND and breakpoint is not None:
|
||||
# (exception, value, traceback) = arg
|
||||
# print exception
|
||||
# curr_func_name = frame.f_code.co_name
|
||||
# if curr_func_name in ('?', '<module>'):
|
||||
# self.setSuspend(thread, CMD_SET_BREAK)
|
||||
# self.doWaitSuspend(thread, frame, event, arg)
|
||||
if event == 'exception' and info.pydev_state != STATE_SUSPEND: #and breakpoint is not None:
|
||||
(exception, value, traceback) = arg
|
||||
global exception_set
|
||||
|
||||
exception_breakpoint = get_exception_breakpoint(exception, tuple(exception_set), NOTIFY_ALWAYS)
|
||||
if exception_breakpoint is not None:
|
||||
curr_func_name = frame.f_code.co_name
|
||||
self.setSuspend(thread, CMD_ADD_EXCEPTION_BREAK)
|
||||
thread.additionalInfo.message = exception_breakpoint.name
|
||||
#self.doWaitSuspend(thread, frame, event, arg)
|
||||
|
||||
#return is not taken into account for breakpoint hit because we'd have a double-hit in this case
|
||||
#(one for the line and the other for the return).
|
||||
if event != 'return' and info.pydev_state != STATE_SUSPEND and breakpoint is not None \
|
||||
elif event != 'return' and info.pydev_state != STATE_SUSPEND and breakpoint is not None \
|
||||
and DictContains(breakpoint, line):
|
||||
|
||||
#ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
|
||||
|
||||
@@ -39,7 +39,13 @@ public abstract class AbstractCommand {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract String getPayload();
|
||||
public final String getPayload() {
|
||||
Payload payload = new Payload();
|
||||
buildPayload(payload);
|
||||
return payload.getText();
|
||||
}
|
||||
|
||||
protected abstract void buildPayload(Payload payload);
|
||||
|
||||
public boolean isResponseExpected() {
|
||||
return false;
|
||||
@@ -69,4 +75,40 @@ public abstract class AbstractCommand {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class Payload {
|
||||
private final StringBuilder myBuilder = new StringBuilder();
|
||||
private static final char SEPARATOR = '\t';
|
||||
|
||||
|
||||
public Payload add(boolean flag) {
|
||||
return doAdd(flag ? "1" : "0");
|
||||
}
|
||||
|
||||
public Payload add(String text) {
|
||||
return doAdd(text);
|
||||
}
|
||||
|
||||
private Payload doAdd(String text) {
|
||||
if (myBuilder.length() > 0) {
|
||||
return separator().append(text);
|
||||
}
|
||||
else {
|
||||
return append(text);
|
||||
}
|
||||
}
|
||||
|
||||
private Payload append(String text) {
|
||||
myBuilder.append(ProtocolParser.encodeExpression(text));
|
||||
return this;
|
||||
}
|
||||
|
||||
private Payload separator() {
|
||||
myBuilder.append(SEPARATOR);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return myBuilder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,4 +10,9 @@ public abstract class AbstractFrameCommand extends AbstractThreadCommand {
|
||||
myFrameId = frameId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add(myFrameId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.jetbrains.python.debugger.pydev;
|
||||
|
||||
|
||||
public abstract class AbstractThreadCommand extends AbstractCommand {
|
||||
|
||||
protected final String myThreadId;
|
||||
|
||||
protected AbstractThreadCommand(final RemoteDebugger debugger, final int commandCode, final String threadId) {
|
||||
@@ -10,6 +9,11 @@ public abstract class AbstractThreadCommand extends AbstractCommand {
|
||||
myThreadId = threadId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
payload.add(myThreadId);
|
||||
}
|
||||
|
||||
public static boolean isThreadCommand(int command) {
|
||||
return command == CREATE_THREAD ||
|
||||
command == KILL_THREAD ||
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.jetbrains.python.debugger.pydev;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author traff
|
||||
*/
|
||||
public class AddExceptionBreakpointCommand extends ExceptionBreakpointCommand {
|
||||
final ExceptionBreakpointNotifyPolicy myNotifyPolicy;
|
||||
|
||||
public AddExceptionBreakpointCommand(@NotNull final RemoteDebugger debugger,
|
||||
@NotNull String exception, @NotNull ExceptionBreakpointNotifyPolicy notifyPolicy) {
|
||||
super(debugger, ADD_EXCEPTION_BREAKPOINT, exception);
|
||||
myNotifyPolicy = notifyPolicy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add(myNotifyPolicy.isNotifyAlways()).add(myNotifyPolicy.isNotifyOnTerminate());
|
||||
}
|
||||
|
||||
public static class ExceptionBreakpointNotifyPolicy {
|
||||
private final boolean myNotifyAlways;
|
||||
private final boolean myNotifyOnTerminate;
|
||||
|
||||
public ExceptionBreakpointNotifyPolicy(boolean notifyAlways, boolean notifyOnTerminate) {
|
||||
myNotifyAlways = notifyAlways;
|
||||
myNotifyOnTerminate = notifyOnTerminate;
|
||||
}
|
||||
|
||||
public boolean isNotifyAlways() {
|
||||
return myNotifyAlways;
|
||||
}
|
||||
|
||||
public boolean isNotifyOnTerminate() {
|
||||
return myNotifyOnTerminate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,10 @@ public class ChangeVariableCommand extends AbstractFrameCommand {
|
||||
myDebugProcess = debugger.getDebugProcess();
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myThreadId).append('\t').append(myFrameId).append('\t').append("FRAME\t").append(myVariableName)
|
||||
.append('\t').append(ProtocolParser.encodeExpression(myValue)).toString();
|
||||
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
payload.add("FRAME").add(myVariableName).add(myValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,9 +13,10 @@ public class ConsoleExecCommand extends AbstractFrameCommand {
|
||||
myExpression = expression;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myThreadId).append('\t').append(myFrameId).append('\t').append("FRAME\t")
|
||||
.append(ProtocolParser.encodeExpression(myExpression)).toString();
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add(myThreadId).add(myFrameId).add("FRAME").add(myExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,9 +23,11 @@ public class EvaluateCommand extends AbstractFrameCommand {
|
||||
myTrimResult = trimResult;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myThreadId).append('\t').append(myFrameId).append('\t').append("FRAME\t")
|
||||
.append(ProtocolParser.encodeExpression(myExpression)).append('\t').append(myTrimResult ? "1" : "0").toString();
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add("FRAME").add(myExpression).add(myTrimResult);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
-6
@@ -7,20 +7,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class ExceptionBreakpointCommand extends AbstractCommand {
|
||||
|
||||
protected String myException;
|
||||
@NotNull
|
||||
protected final String myException;
|
||||
|
||||
private ExceptionBreakpointCommand(@NotNull final RemoteDebugger debugger, final int commandCode, String exception) {
|
||||
|
||||
protected ExceptionBreakpointCommand(@NotNull final RemoteDebugger debugger,
|
||||
final int commandCode,
|
||||
@NotNull String exception) {
|
||||
super(debugger, commandCode);
|
||||
myException = exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myException).toString();
|
||||
protected void buildPayload(Payload payload) {
|
||||
payload.add(myException);
|
||||
}
|
||||
|
||||
public static ExceptionBreakpointCommand addExceptionBreakpointCommand(@NotNull final RemoteDebugger debugger, String exception) {
|
||||
return new ExceptionBreakpointCommand(debugger, ADD_EXCEPTION_BREAKPOINT, exception);
|
||||
public static ExceptionBreakpointCommand addExceptionBreakpointCommand(@NotNull final RemoteDebugger debugger, String exception, AddExceptionBreakpointCommand.ExceptionBreakpointNotifyPolicy notifyPolicy) {
|
||||
return new AddExceptionBreakpointCommand(debugger, exception, notifyPolicy);
|
||||
}
|
||||
|
||||
public static ExceptionBreakpointCommand removeExceptionBreakpointCommand(@NotNull final RemoteDebugger debugger, String exception) {
|
||||
|
||||
@@ -40,10 +40,11 @@ public class GetCompletionsCommand extends AbstractFrameCommand {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myThreadId).append('\t').append(myFrameId).append('\t').append("FRAME\t")
|
||||
.append(myActionToken).toString();
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add("FRAME").add(myActionToken);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -22,8 +22,10 @@ public class GetFrameCommand extends AbstractFrameCommand {
|
||||
myDebugProcess = debugger.getDebugProcess();
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myThreadId).append('\t').append(myFrameId).append('\t').append("FRAME").toString();
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add("FRAME");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,9 +18,10 @@ public class GetVariableCommand extends GetFrameCommand {
|
||||
myParent = parent;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myThreadId).append('\t').append(myFrameId).append('\t').append("FRAME\t").append(myVariableName)
|
||||
.toString();
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add(myVariableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,4 +17,9 @@ public abstract class LineBreakpointCommand extends AbstractCommand {
|
||||
myFile = file;
|
||||
myLine = line;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
payload.add(myFile).add(Integer.toString(myLine));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ public class ProtocolFrame {
|
||||
|
||||
private final int myCommand;
|
||||
private final int mySequence;
|
||||
private final String myPayload;
|
||||
private @NotNull final String myPayload;
|
||||
|
||||
public ProtocolFrame(final int command, final int sequence, final String payload) throws PyDebuggerException {
|
||||
public ProtocolFrame(final int command, final int sequence, @NotNull final String payload) throws PyDebuggerException {
|
||||
myCommand = command;
|
||||
mySequence = sequence;
|
||||
myPayload = payload;
|
||||
@@ -26,7 +26,7 @@ public class ProtocolFrame {
|
||||
|
||||
myCommand = Integer.parseInt(parts[0]);
|
||||
mySequence = Integer.parseInt(parts[1]);
|
||||
myPayload = (parts.length == 3 && !"".equals(parts[2]) ? ProtocolParser.decode(parts[2]) : null);
|
||||
myPayload = (parts.length == 3 && !"".equals(parts[2]) ? ProtocolParser.decode(parts[2]) : "");
|
||||
}
|
||||
|
||||
public int getCommand() {
|
||||
@@ -37,6 +37,7 @@ public class ProtocolFrame {
|
||||
return mySequence;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPayload() {
|
||||
return myPayload;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,4 @@ public class RemoveBreakpointCommand extends LineBreakpointCommand {
|
||||
public RemoveBreakpointCommand(final RemoteDebugger debugger, final String file, final int line) {
|
||||
super(debugger, REMOVE_BREAKPOINT, file, line);
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myFile).append('\t').append(Integer.toString(myLine)).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,9 +20,4 @@ public class ResumeCommand extends AbstractThreadCommand {
|
||||
public String getThreadId() {
|
||||
return myThreadId;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return myThreadId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ public class RunCommand extends AbstractCommand {
|
||||
super(debugger, RUN);
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return null;
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ public class SetBreakpointCommand extends LineBreakpointCommand {
|
||||
myLogExpression = logExpression;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return new StringBuilder().append(myFile).append('\t').append(Integer.toString(myLine)).append("\t").append(buildCondition(myCondition)).append("\t").append(buildCondition(myLogExpression)).toString();
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add(buildCondition(myCondition)).add(buildCondition(myLogExpression));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -7,9 +7,4 @@ public class SuspendCommand extends AbstractThreadCommand {
|
||||
protected SuspendCommand(final RemoteDebugger debugger, final String threadId) {
|
||||
super(debugger, SUSPEND_THREAD, threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPayload() {
|
||||
return myThreadId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ public class VersionCommand extends AbstractCommand {
|
||||
myVersion = version;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return myVersion;
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
payload.add(myVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -285,7 +285,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess {
|
||||
myRegisteredExceptionBreakpoints.put(breakpoint.getProperties().getException(), breakpoint);
|
||||
if (myDebugger.isConnected()) {
|
||||
final ExceptionBreakpointCommand command =
|
||||
ExceptionBreakpointCommand.addExceptionBreakpointCommand(myDebugger, breakpoint.getProperties().getException());
|
||||
ExceptionBreakpointCommand.addExceptionBreakpointCommand(myDebugger, breakpoint.getProperties().getException(), new AddExceptionBreakpointCommand.ExceptionBreakpointNotifyPolicy(breakpoint.getProperties().isNotifyAlways(), breakpoint.getProperties().isNotifyOnTerminate()));
|
||||
myDebugger.execute(command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author traff
|
||||
*/
|
||||
public class PyExceptionBreakpointProperties extends XBreakpointProperties<PyExceptionBreakpointProperties>{
|
||||
public class PyExceptionBreakpointProperties extends XBreakpointProperties<PyExceptionBreakpointProperties> {
|
||||
@Attribute("exception")
|
||||
public String myException;
|
||||
@Attribute("notifyAlways")
|
||||
public boolean myNotifyAlways;
|
||||
@Attribute("notifyOnTerminate")
|
||||
public boolean myNotifyOnTerminate;
|
||||
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public PyExceptionBreakpointProperties() {
|
||||
@@ -27,9 +32,27 @@ public class PyExceptionBreakpointProperties extends XBreakpointProperties<PyExc
|
||||
@Override
|
||||
public void loadState(final PyExceptionBreakpointProperties state) {
|
||||
myException = state.myException;
|
||||
myNotifyAlways = state.myNotifyAlways;
|
||||
myNotifyOnTerminate = state.myNotifyOnTerminate;
|
||||
}
|
||||
|
||||
public String getException() {
|
||||
return myException;
|
||||
}
|
||||
|
||||
public boolean isNotifyOnTerminate() {
|
||||
return myNotifyOnTerminate;
|
||||
}
|
||||
|
||||
public void setNotifyOnTerminate(boolean notifyOnTerminate) {
|
||||
myNotifyOnTerminate = notifyOnTerminate;
|
||||
}
|
||||
|
||||
public boolean isNotifyAlways() {
|
||||
return myNotifyAlways;
|
||||
}
|
||||
|
||||
public void setNotifyAlways(boolean notifyAlways) {
|
||||
myNotifyAlways = notifyAlways;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,16 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointType;
|
||||
import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
|
||||
import com.jetbrains.python.debugger.ui.PyClassTreeChooserDialog;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -24,15 +28,17 @@ import java.util.HashMap;
|
||||
public class PyExceptionBreakpointType
|
||||
extends XBreakpointType<XBreakpoint<PyExceptionBreakpointProperties>, PyExceptionBreakpointProperties> {
|
||||
|
||||
private static final String BASE_EXCEPTION = "BaseException";
|
||||
|
||||
public PyExceptionBreakpointType() {
|
||||
super("python-exception", "Python Exception Breakpoint", false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PyExceptionBreakpointProperties createProperties() {
|
||||
return new PyExceptionBreakpointProperties("BaseException");
|
||||
}
|
||||
return p();
|
||||
}private PyExceptionBreakpointProperties p() {
|
||||
return new PyExceptionBreakpointProperties(BASE_EXCEPTION);}
|
||||
|
||||
@Override
|
||||
public boolean isAddBreakpointButtonVisible() {
|
||||
@@ -48,7 +54,6 @@ public class PyExceptionBreakpointType
|
||||
|
||||
dialog.showDialog();
|
||||
|
||||
|
||||
// on ok
|
||||
final PyClass pyClass = dialog.getSelected();
|
||||
if (pyClass != null) {
|
||||
@@ -96,8 +101,94 @@ public class PyExceptionBreakpointType
|
||||
public String getDisplayText(XBreakpoint<PyExceptionBreakpointProperties> breakpoint) {
|
||||
PyExceptionBreakpointProperties properties = breakpoint.getProperties();
|
||||
if (properties != null) {
|
||||
return properties.getException();
|
||||
String exception = properties.getException();
|
||||
if (BASE_EXCEPTION.equals(exception)) {
|
||||
return "All exceptions";
|
||||
}
|
||||
return exception;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public XBreakpoint<PyExceptionBreakpointProperties> createDefaultBreakpoint(@NotNull XBreakpointCreator<PyExceptionBreakpointProperties> creator) {
|
||||
final XBreakpoint<PyExceptionBreakpointProperties> breakpoint = creator.createBreakpoint(createDefaultBreakpointProperties());
|
||||
breakpoint.setEnabled(true);
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
private static PyExceptionBreakpointProperties createDefaultBreakpointProperties() {
|
||||
PyExceptionBreakpointProperties p = new PyExceptionBreakpointProperties(BASE_EXCEPTION);
|
||||
p.setNotifyOnTerminate(true);
|
||||
p.setNotifyAlways(false);
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XBreakpointCustomPropertiesPanel<XBreakpoint<PyExceptionBreakpointProperties>> createCustomPropertiesPanel() {
|
||||
return new PyExceptionBreakpointPropertiesPanel();
|
||||
}
|
||||
|
||||
|
||||
private static class PyExceptionBreakpointPropertiesPanel
|
||||
extends XBreakpointCustomPropertiesPanel<XBreakpoint<PyExceptionBreakpointProperties>> {
|
||||
private JCheckBox myNotifyOnTerminateCheckBox;
|
||||
private JCheckBox myNotifyAlwaysCheckBox;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
myNotifyOnTerminateCheckBox = new JCheckBox("On terminate");
|
||||
myNotifyAlwaysCheckBox = new JCheckBox("Always");
|
||||
|
||||
Box notificationsBox = Box.createVerticalBox();
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(myNotifyOnTerminateCheckBox, BorderLayout.NORTH);
|
||||
notificationsBox.add(panel);
|
||||
panel = new JPanel(new BorderLayout());
|
||||
panel.add(myNotifyAlwaysCheckBox, BorderLayout.NORTH);
|
||||
notificationsBox.add(panel);
|
||||
|
||||
panel = new JPanel(new BorderLayout());
|
||||
JPanel innterPanel = new JPanel(new BorderLayout());
|
||||
innterPanel.add(notificationsBox, BorderLayout.CENTER);
|
||||
innterPanel.add(Box.createHorizontalStrut(3), BorderLayout.WEST);
|
||||
innterPanel.add(Box.createHorizontalStrut(3), BorderLayout.EAST);
|
||||
panel.add(innterPanel, BorderLayout.NORTH);
|
||||
panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Notifications"));
|
||||
|
||||
ActionListener listener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!myNotifyOnTerminateCheckBox.isSelected() && !myNotifyAlwaysCheckBox.isSelected()) {
|
||||
Object source = e.getSource();
|
||||
JCheckBox toCheck = null;
|
||||
if (myNotifyOnTerminateCheckBox.equals(source)) {
|
||||
toCheck = myNotifyAlwaysCheckBox;
|
||||
}
|
||||
else if (myNotifyAlwaysCheckBox.equals(source)) {
|
||||
toCheck = myNotifyOnTerminateCheckBox;
|
||||
}
|
||||
if (toCheck != null) {
|
||||
toCheck.setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
myNotifyOnTerminateCheckBox.addActionListener(listener);
|
||||
myNotifyAlwaysCheckBox.addActionListener(listener);
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveTo(@NotNull XBreakpoint<PyExceptionBreakpointProperties> breakpoint) {
|
||||
breakpoint.getProperties().setNotifyAlways(myNotifyAlwaysCheckBox.isSelected());
|
||||
breakpoint.getProperties().setNotifyOnTerminate(myNotifyOnTerminateCheckBox.isSelected());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFrom(@NotNull XBreakpoint<PyExceptionBreakpointProperties> breakpoint) {
|
||||
myNotifyAlwaysCheckBox.setSelected(breakpoint.getProperties().isNotifyAlways());
|
||||
myNotifyOnTerminateCheckBox.setSelected(breakpoint.getProperties().isNotifyOnTerminate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ public class PyStringLiteralExpressionImpl extends PyElementImpl implements PySt
|
||||
|
||||
@NotNull
|
||||
public PsiReference[] getReferences() {
|
||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this, PyStringLiteralExpression.class);
|
||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiReferenceService.Hints.NO_HINTS);
|
||||
}
|
||||
|
||||
public List<Pair<PsiElement, TextRange>> getInjectedPsi() {
|
||||
|
||||
Reference in New Issue
Block a user