Merge branch 'master' of git.labs.intellij.net:idea/ultimate

This commit is contained in:
Ekaterina Tuzova
2010-11-25 12:32:59 +03:00
26 changed files with 474 additions and 216 deletions
+36 -113
View File
@@ -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:
+117
View File
@@ -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
+53 -45
View File
@@ -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 ||
@@ -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
@@ -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() {