mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
show breakpoint icon when debugger is suspended on non-line breakpoint (IDEA-70208)
This commit is contained in:
@@ -18,11 +18,11 @@ package com.intellij.xdebugger.breakpoints;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.xdebugger.XDebuggerUtil;
|
||||
import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
|
||||
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import com.intellij.xdebugger.XDebuggerUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -30,8 +30,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implement this class to support new type of breakpoints. An implementation should be registered in a plugin.xml:
|
||||
@@ -100,6 +100,11 @@ public abstract class XBreakpointType<B extends XBreakpoint<P>, P extends XBreak
|
||||
return DebuggerIcons.DISABLED_BREAKPOINT_ICON;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Icon getDisabledDependentIcon() {
|
||||
return DebuggerIcons.DISABLED_DEPENDENT_BREAKPOINT_ICON;
|
||||
}
|
||||
|
||||
public abstract String getDisplayText(B breakpoint);
|
||||
|
||||
@Nullable
|
||||
|
||||
+2
-9
@@ -19,19 +19,17 @@ package com.intellij.xdebugger.breakpoints;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XDebuggerUtil;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Implement this class to support new type of line breakpoints. An implementation should be registered in a plugin.xml:
|
||||
@@ -75,11 +73,6 @@ public abstract class XLineBreakpointType<P extends XBreakpointProperties> exten
|
||||
return XDebuggerBundle.message("xbreakpoint.default.display.text", breakpoint.getLine() + 1, breakpoint.getPresentableFilePath());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Icon getDisabledDependentIcon() {
|
||||
return DebuggerIcons.DISABLED_DEPENDENT_BREAKPOINT_ICON;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Comparator<XLineBreakpoint<P>> getBreakpointComparator() {
|
||||
return XDebuggerUtil.getInstance().getDefaultLineBreakpointComparator();
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
@@ -85,6 +86,7 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
private String mySessionName;
|
||||
private XDebugSessionTab mySessionTab;
|
||||
private XDebugSessionData mySessionData;
|
||||
private XBreakpoint<?> myActiveNonLineBreakpoint;
|
||||
private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class);
|
||||
private Project myProject;
|
||||
private @Nullable ExecutionEnvironment myEnvironment;
|
||||
@@ -307,7 +309,7 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CustomizedBreakpointPresentation getBreakpointPresentation(@NotNull XLineBreakpoint<?> breakpoint) {
|
||||
public CustomizedBreakpointPresentation getBreakpointPresentation(@NotNull XBreakpoint<?> breakpoint) {
|
||||
synchronized (myRegisteredBreakpoints) {
|
||||
return myRegisteredBreakpoints.get(breakpoint);
|
||||
}
|
||||
@@ -424,10 +426,11 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
|
||||
private void doResume() {
|
||||
myDispatcher.getMulticaster().beforeSessionResume();
|
||||
myDebuggerManager.setActiveSession(this, null, false);
|
||||
myDebuggerManager.setActiveSession(this, null, false, null);
|
||||
mySuspendContext = null;
|
||||
myCurrentStackFrame = null;
|
||||
myCurrentPosition = null;
|
||||
myActiveNonLineBreakpoint = null;
|
||||
myPaused = false;
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
@@ -442,7 +445,7 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
public void updateExecutionPosition() {
|
||||
XExecutionStack activeExecutionStack = mySuspendContext.getActiveExecutionStack();
|
||||
boolean isTopFrame = activeExecutionStack != null && activeExecutionStack.getTopFrame() == myCurrentStackFrame;
|
||||
myDebuggerManager.updateExecutionPoint(myCurrentStackFrame.getSourcePosition(), !isTopFrame);
|
||||
myDebuggerManager.updateExecutionPoint(myCurrentStackFrame.getSourcePosition(), !isTopFrame, isTopFrame ? getPositionIconRenderer() : null);
|
||||
}
|
||||
|
||||
|
||||
@@ -476,13 +479,25 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
if (position != null) {
|
||||
XExecutionStack activeExecutionStack = mySuspendContext.getActiveExecutionStack();
|
||||
boolean isTopFrame = activeExecutionStack != null && activeExecutionStack.getTopFrame() == myCurrentStackFrame;
|
||||
myDebuggerManager.setActiveSession(this, position, !isTopFrame);
|
||||
myDebuggerManager.setActiveSession(this, position, !isTopFrame, isTopFrame ? getPositionIconRenderer() : null);
|
||||
}
|
||||
else {
|
||||
myDebuggerManager.setActiveSession(this, null, false);
|
||||
myDebuggerManager.setActiveSession(this, null, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
public XBreakpoint<?> getActiveNonLineBreakpoint() {
|
||||
return myActiveNonLineBreakpoint;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GutterIconRenderer getPositionIconRenderer() {
|
||||
if (myActiveNonLineBreakpoint != null) {
|
||||
return ((XBreakpointBase<?,?,?>)myActiveNonLineBreakpoint).createGutterIconRenderer();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateBreakpointPresentation(@NotNull final XLineBreakpoint<?> breakpoint,
|
||||
@Nullable final Icon icon,
|
||||
@Nullable final String errorMessage) {
|
||||
@@ -544,6 +559,7 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
return false;
|
||||
}
|
||||
|
||||
myActiveNonLineBreakpoint = !(breakpoint instanceof XLineBreakpoint<?>) ? breakpoint : null;
|
||||
positionReached(suspendContext);
|
||||
return true;
|
||||
}
|
||||
@@ -591,7 +607,7 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
|
||||
myPaused = true;
|
||||
if (myCurrentPosition != null) {
|
||||
myDebuggerManager.setActiveSession(this, myCurrentPosition, false);
|
||||
myDebuggerManager.setActiveSession(this, myCurrentPosition, false, getPositionIconRenderer());
|
||||
}
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
@@ -634,7 +650,7 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
myCurrentPosition = null;
|
||||
myCurrentStackFrame = null;
|
||||
mySuspendContext = null;
|
||||
myDebuggerManager.setActiveSession(this, null, false);
|
||||
myDebuggerManager.setActiveSession(this, null, false, null);
|
||||
XBreakpointManagerImpl breakpointManager = myDebuggerManager.getBreakpointManager();
|
||||
breakpointManager.removeBreakpointListener(myBreakpointListener);
|
||||
breakpointManager.getDependentBreakpointManager().removeListener(myDependentBreakpointListener);
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||
@@ -40,6 +41,10 @@ import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.xmlb.annotations.Property;
|
||||
import com.intellij.xdebugger.*;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointAdapter;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
|
||||
import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase;
|
||||
import com.intellij.xdebugger.impl.breakpoints.XBreakpointManagerImpl;
|
||||
import com.intellij.xdebugger.impl.ui.ExecutionPointHighlighter;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionData;
|
||||
@@ -81,6 +86,19 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
|
||||
}
|
||||
}
|
||||
});
|
||||
myBreakpointManager.addBreakpointListener(new XBreakpointAdapter<XBreakpoint<?>>() {
|
||||
@Override
|
||||
public void breakpointChanged(@NotNull XBreakpoint<?> breakpoint) {
|
||||
if (!(breakpoint instanceof XLineBreakpoint)) {
|
||||
final XDebugSessionImpl session = getCurrentSession();
|
||||
if (session != null && breakpoint.equals(session.getActiveNonLineBreakpoint())) {
|
||||
final XBreakpointBase breakpointBase = (XBreakpointBase)breakpoint;
|
||||
breakpointBase.clearIcon();
|
||||
myExecutionPointHighlighter.updateGutterIcon(breakpointBase.createGutterIconRenderer());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
messageBus.connect().subscribe(RunContentManagerImpl.RUN_CONTENT_TOPIC, new RunContentWithExecutorListener() {
|
||||
@Override
|
||||
@@ -91,7 +109,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
|
||||
session.activateSession();
|
||||
}
|
||||
else {
|
||||
setActiveSession(null, null, false);
|
||||
setActiveSession(null, null, false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,18 +213,19 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
|
||||
}
|
||||
}
|
||||
|
||||
public void setActiveSession(@Nullable XDebugSessionImpl session, @Nullable XSourcePosition position, boolean useSelection) {
|
||||
public void setActiveSession(@Nullable XDebugSessionImpl session, @Nullable XSourcePosition position, boolean useSelection,
|
||||
final @Nullable GutterIconRenderer gutterIconRenderer) {
|
||||
boolean sessionChanged = myActiveSession != session;
|
||||
myActiveSession = session;
|
||||
updateExecutionPoint(position, useSelection);
|
||||
updateExecutionPoint(position, useSelection, gutterIconRenderer);
|
||||
if (sessionChanged) {
|
||||
onActiveSessionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateExecutionPoint(XSourcePosition position, boolean useSelection) {
|
||||
public void updateExecutionPoint(XSourcePosition position, boolean useSelection, @Nullable GutterIconRenderer gutterIconRenderer) {
|
||||
if (position != null) {
|
||||
myExecutionPointHighlighter.show(position, useSelection);
|
||||
myExecutionPointHighlighter.show(position, useSelection, gutterIconRenderer);
|
||||
}
|
||||
else {
|
||||
myExecutionPointHighlighter.hide();
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.breakpoints;
|
||||
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import com.intellij.util.xmlb.annotations.Property;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import com.intellij.xdebugger.breakpoints.SuspendPolicy;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointType;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
@Tag("breakpoint")
|
||||
public class BreakpointState<B extends XBreakpoint<P>, P extends XBreakpointProperties, T extends XBreakpointType<B,P>> {
|
||||
private String myTypeId;
|
||||
private boolean myEnabled;
|
||||
private Element myPropertiesElement;
|
||||
private SuspendPolicy mySuspendPolicy = SuspendPolicy.ALL;
|
||||
private boolean myLogMessage;
|
||||
private String myLogExpression;
|
||||
private String myCondition;
|
||||
private XBreakpointDependencyState myDependencyState;
|
||||
|
||||
public BreakpointState() {
|
||||
}
|
||||
|
||||
public BreakpointState(final boolean enabled, final String typeId) {
|
||||
myEnabled = enabled;
|
||||
myTypeId = typeId;
|
||||
}
|
||||
|
||||
@Attribute("enabled")
|
||||
public boolean isEnabled() {
|
||||
return myEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
myEnabled = enabled;
|
||||
}
|
||||
|
||||
@Attribute("type")
|
||||
public String getTypeId() {
|
||||
return myTypeId;
|
||||
}
|
||||
|
||||
public void setTypeId(final String typeId) {
|
||||
myTypeId = typeId;
|
||||
}
|
||||
|
||||
@Tag("properties")
|
||||
public Element getPropertiesElement() {
|
||||
return myPropertiesElement;
|
||||
}
|
||||
|
||||
public void setPropertiesElement(final Element propertiesElement) {
|
||||
myPropertiesElement = propertiesElement;
|
||||
}
|
||||
|
||||
@Attribute("suspend")
|
||||
public String getSuspendPolicyString() {
|
||||
return mySuspendPolicy.name();
|
||||
}
|
||||
|
||||
public void setSuspendPolicyString(final String suspendPolicy) {
|
||||
mySuspendPolicy = SuspendPolicy.valueOf(suspendPolicy);
|
||||
}
|
||||
|
||||
@Transient
|
||||
public SuspendPolicy getSuspendPolicy() {
|
||||
return mySuspendPolicy;
|
||||
}
|
||||
|
||||
public void setSuspendPolicy(SuspendPolicy suspendPolicy) {
|
||||
mySuspendPolicy = suspendPolicy;
|
||||
}
|
||||
|
||||
@Attribute("log-message")
|
||||
public boolean isLogMessage() {
|
||||
return myLogMessage;
|
||||
}
|
||||
|
||||
public void setLogMessage(final boolean logMessage) {
|
||||
myLogMessage = logMessage;
|
||||
}
|
||||
|
||||
@Tag("log-expression")
|
||||
public String getLogExpression() {
|
||||
return myLogExpression;
|
||||
}
|
||||
|
||||
public void setLogExpression(final String logExpression) {
|
||||
myLogExpression = logExpression;
|
||||
}
|
||||
|
||||
@Tag("condition")
|
||||
public String getCondition() {
|
||||
return myCondition;
|
||||
}
|
||||
|
||||
public void setCondition(final String condition) {
|
||||
myCondition = condition;
|
||||
}
|
||||
|
||||
@Property(surroundWithTag = false)
|
||||
public XBreakpointDependencyState getDependencyState() {
|
||||
return myDependencyState;
|
||||
}
|
||||
|
||||
public void setDependencyState(final XBreakpointDependencyState dependencyState) {
|
||||
myDependencyState = dependencyState;
|
||||
}
|
||||
|
||||
public XBreakpointBase<B,P,?> createBreakpoint(@NotNull T type, @NotNull XBreakpointManagerImpl breakpointManager) {
|
||||
return new XBreakpointBase<B, P, BreakpointState<B,P,?>>(type, breakpointManager, this);
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.breakpoints;
|
||||
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
@Tag("line-breakpoint")
|
||||
public class LineBreakpointState<P extends XBreakpointProperties> extends
|
||||
BreakpointState<XLineBreakpoint<P>, P, XLineBreakpointType<P>> {
|
||||
private String myFileUrl;
|
||||
private int myLine;
|
||||
|
||||
public LineBreakpointState() {
|
||||
}
|
||||
|
||||
public LineBreakpointState(final boolean enabled, final String typeId, final String fileUrl, final int line) {
|
||||
super(enabled, typeId);
|
||||
myFileUrl = fileUrl;
|
||||
myLine = line;
|
||||
}
|
||||
|
||||
@Tag("url")
|
||||
public String getFileUrl() {
|
||||
return myFileUrl;
|
||||
}
|
||||
|
||||
public void setFileUrl(final String fileUrl) {
|
||||
myFileUrl = fileUrl;
|
||||
}
|
||||
|
||||
@Tag("line")
|
||||
public int getLine() {
|
||||
return myLine;
|
||||
}
|
||||
|
||||
public void setLine(final int line) {
|
||||
myLine = line;
|
||||
}
|
||||
|
||||
public XBreakpointBase<XLineBreakpoint<P>,P, ?> createBreakpoint(@NotNull final XLineBreakpointType<P> type, @NotNull XBreakpointManagerImpl breakpointManager) {
|
||||
return new XLineBreakpointImpl<P>(type, breakpointManager, this);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.breakpoints;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XDebuggerUtil;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class RemoveBreakpointGutterIconAction<P extends XBreakpointProperties> extends AnAction {
|
||||
private XBreakpointBase<?,?,?> myBreakpoint;
|
||||
|
||||
RemoveBreakpointGutterIconAction(XBreakpointBase<?, ?, ?> breakpoint) {
|
||||
super(XDebuggerBundle.message("xdebugger.remove.line.breakpoint.action.text"));
|
||||
myBreakpoint = breakpoint;
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
XDebuggerUtil.getInstance().removeBreakpoint(myBreakpoint.getProject(), myBreakpoint);
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.breakpoints;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class ToggleBreakpointGutterIconAction extends AnAction {
|
||||
private XBreakpoint<?> myBreakpoint;
|
||||
|
||||
ToggleBreakpointGutterIconAction(XBreakpoint<?> breakpoint) {
|
||||
super(breakpoint.isEnabled() ? XDebuggerBundle.message("xdebugger.disable.breakpoint.action.text") : XDebuggerBundle.message("xdebugger.enable.breakpoint.action.text"));
|
||||
this.myBreakpoint = breakpoint;
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
myBreakpoint.setEnabled(!myBreakpoint.isEnabled());
|
||||
}
|
||||
}
|
||||
+227
-104
@@ -15,34 +15,52 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.breakpoints;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.actionSystem.Separator;
|
||||
import com.intellij.openapi.editor.markup.GutterDraggableObject;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import com.intellij.util.xmlb.annotations.Property;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
|
||||
import com.intellij.xdebugger.breakpoints.SuspendPolicy;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointType;
|
||||
import com.intellij.xdebugger.impl.actions.ViewBreakpointsAction;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointProperties, S extends XBreakpointBase.BreakpointState> extends UserDataHolderBase implements XBreakpoint<P> {
|
||||
public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointProperties, S extends BreakpointState> extends UserDataHolderBase implements XBreakpoint<P> {
|
||||
private static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTERS = new SkipDefaultValuesSerializationFilters();
|
||||
@NonNls private static final String BR_NBSP = "<br> ";
|
||||
private final XBreakpointType<Self, P> myType;
|
||||
private final @Nullable P myProperties;
|
||||
protected final S myState;
|
||||
private final XBreakpointManagerImpl myBreakpointManager;
|
||||
private Icon myIcon;
|
||||
private CustomizedBreakpointPresentation myCustomizedPresentation;
|
||||
|
||||
public XBreakpointBase(final XBreakpointType<Self, P> type, XBreakpointManagerImpl breakpointManager, final @Nullable P properties, final S state) {
|
||||
myState = state;
|
||||
@@ -101,12 +119,12 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
|
||||
@NotNull
|
||||
public SuspendPolicy getSuspendPolicy() {
|
||||
return myState.mySuspendPolicy;
|
||||
return myState.getSuspendPolicy();
|
||||
}
|
||||
|
||||
public void setSuspendPolicy(@NotNull SuspendPolicy policy) {
|
||||
if (myState.mySuspendPolicy != policy) {
|
||||
myState.mySuspendPolicy = policy;
|
||||
if (myState.getSuspendPolicy() != policy) {
|
||||
myState.setSuspendPolicy(policy);
|
||||
fireBreakpointChanged();
|
||||
}
|
||||
}
|
||||
@@ -148,7 +166,7 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nullable
|
||||
public P getProperties() {
|
||||
return myProperties;
|
||||
}
|
||||
@@ -175,104 +193,209 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Tag("breakpoint")
|
||||
public static class BreakpointState<B extends XBreakpoint<P>, P extends XBreakpointProperties, T extends XBreakpointType<B,P>> {
|
||||
private String myTypeId;
|
||||
private boolean myEnabled;
|
||||
private Element myPropertiesElement;
|
||||
private SuspendPolicy mySuspendPolicy = SuspendPolicy.ALL;
|
||||
private boolean myLogMessage;
|
||||
private String myLogExpression;
|
||||
private String myCondition;
|
||||
private XBreakpointDependencyState myDependencyState;
|
||||
|
||||
public BreakpointState() {
|
||||
}
|
||||
|
||||
public BreakpointState(final boolean enabled, final String typeId) {
|
||||
myEnabled = enabled;
|
||||
myTypeId = typeId;
|
||||
}
|
||||
|
||||
@Attribute("enabled")
|
||||
public boolean isEnabled() {
|
||||
return myEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
myEnabled = enabled;
|
||||
}
|
||||
|
||||
@Attribute("type")
|
||||
public String getTypeId() {
|
||||
return myTypeId;
|
||||
}
|
||||
|
||||
public void setTypeId(final String typeId) {
|
||||
myTypeId = typeId;
|
||||
}
|
||||
|
||||
@Tag("properties")
|
||||
public Element getPropertiesElement() {
|
||||
return myPropertiesElement;
|
||||
}
|
||||
|
||||
public void setPropertiesElement(final Element propertiesElement) {
|
||||
myPropertiesElement = propertiesElement;
|
||||
}
|
||||
|
||||
@Attribute("suspend")
|
||||
public String getSuspendPolicy() {
|
||||
return mySuspendPolicy.name();
|
||||
}
|
||||
|
||||
public void setSuspendPolicy(final String suspendPolicy) {
|
||||
mySuspendPolicy = SuspendPolicy.valueOf(suspendPolicy);
|
||||
}
|
||||
|
||||
@Attribute("log-message")
|
||||
public boolean isLogMessage() {
|
||||
return myLogMessage;
|
||||
}
|
||||
|
||||
public void setLogMessage(final boolean logMessage) {
|
||||
myLogMessage = logMessage;
|
||||
}
|
||||
|
||||
@Tag("log-expression")
|
||||
public String getLogExpression() {
|
||||
return myLogExpression;
|
||||
}
|
||||
|
||||
public void setLogExpression(final String logExpression) {
|
||||
myLogExpression = logExpression;
|
||||
}
|
||||
|
||||
@Tag("condition")
|
||||
public String getCondition() {
|
||||
return myCondition;
|
||||
}
|
||||
|
||||
public void setCondition(final String condition) {
|
||||
myCondition = condition;
|
||||
}
|
||||
|
||||
@Property(surroundWithTag = false)
|
||||
public XBreakpointDependencyState getDependencyState() {
|
||||
return myDependencyState;
|
||||
}
|
||||
|
||||
public void setDependencyState(final XBreakpointDependencyState dependencyState) {
|
||||
myDependencyState = dependencyState;
|
||||
}
|
||||
|
||||
public XBreakpointBase<B,P,?> createBreakpoint(@NotNull T type, @NotNull XBreakpointManagerImpl breakpointManager) {
|
||||
return new XBreakpointBase<B, P, BreakpointState<B,P,?>>(type, breakpointManager, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XBreakpointBase(type=" + myType + ")";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected GutterDraggableObject createBreakpointDraggableObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected List<? extends AnAction> getAdditionalPopupMenuActions(XDebugSession session) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
@NonNls StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
builder.append("<html><body>");
|
||||
builder.append(XBreakpointUtil.getDisplayText(this));
|
||||
|
||||
String errorMessage = getErrorMessage();
|
||||
if (errorMessage != null) {
|
||||
builder.append(BR_NBSP);
|
||||
builder.append("<font color=\"red\">");
|
||||
builder.append(errorMessage);
|
||||
builder.append("</font>");
|
||||
}
|
||||
|
||||
SuspendPolicy suspendPolicy = getSuspendPolicy();
|
||||
if (suspendPolicy == SuspendPolicy.THREAD) {
|
||||
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.thread"));
|
||||
}
|
||||
else if (suspendPolicy == SuspendPolicy.NONE) {
|
||||
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.none"));
|
||||
}
|
||||
|
||||
String condition = getCondition();
|
||||
if (condition != null) {
|
||||
builder.append(BR_NBSP);
|
||||
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.condition"));
|
||||
builder.append(" ");
|
||||
builder.append(condition);
|
||||
}
|
||||
|
||||
if (isLogMessage()) {
|
||||
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.log.message"));
|
||||
}
|
||||
String logExpression = getLogExpression();
|
||||
if (logExpression != null) {
|
||||
builder.append(BR_NBSP);
|
||||
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.log.expression"));
|
||||
builder.append(" ");
|
||||
builder.append(logExpression);
|
||||
}
|
||||
|
||||
XBreakpoint<?> masterBreakpoint = getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this);
|
||||
if (masterBreakpoint != null) {
|
||||
builder.append(BR_NBSP);
|
||||
String str = XDebuggerBundle.message("xbreakpoint.tooltip.depends.on");
|
||||
builder.append(str);
|
||||
builder.append(" ");
|
||||
builder.append(XBreakpointUtil.getDisplayText(masterBreakpoint));
|
||||
}
|
||||
|
||||
builder.append("</body><html");
|
||||
return builder.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateIcon() {
|
||||
myIcon = calculateIcon();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Icon calculateIcon() {
|
||||
if (!isEnabled()) {
|
||||
// disabled icon takes precedence to other to visually distinguish it and provide feedback then it is enabled/disabled
|
||||
// (e.g. in case of mute-mode we would like to differentiate muted but enabled breakpoints from simply disabled ones)
|
||||
return getType().getDisabledIcon();
|
||||
}
|
||||
|
||||
XDebugSessionImpl session = getBreakpointManager().getDebuggerManager().getCurrentSession();
|
||||
if (session == null) {
|
||||
if (getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this) != null) {
|
||||
return getType().getDisabledDependentIcon();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (session.areBreakpointsMuted()) {
|
||||
return DebuggerIcons.MUTED_BREAKPOINT_ICON;
|
||||
}
|
||||
if (session.isDisabledSlaveBreakpoint(this)) {
|
||||
return getType().getDisabledDependentIcon();
|
||||
}
|
||||
CustomizedBreakpointPresentation presentation = session.getBreakpointPresentation(this);
|
||||
if (presentation != null) {
|
||||
Icon icon = presentation.getIcon();
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myCustomizedPresentation != null) {
|
||||
final Icon icon = myCustomizedPresentation.getIcon();
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
return getType().getEnabledIcon();
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
if (myIcon == null) {
|
||||
updateIcon();
|
||||
}
|
||||
return myIcon;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getErrorMessage() {
|
||||
final XDebugSessionImpl currentSession = getBreakpointManager().getDebuggerManager().getCurrentSession();
|
||||
if (currentSession != null) {
|
||||
CustomizedBreakpointPresentation presentation = currentSession.getBreakpointPresentation(this);
|
||||
if (presentation != null) {
|
||||
final String message = presentation.getErrorMessage();
|
||||
if (message != null) return message;
|
||||
}
|
||||
}
|
||||
return myCustomizedPresentation != null ? myCustomizedPresentation.getErrorMessage() : null;
|
||||
}
|
||||
|
||||
public void setCustomizedPresentation(CustomizedBreakpointPresentation presentation) {
|
||||
myCustomizedPresentation = presentation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GutterIconRenderer createGutterIconRenderer() {
|
||||
return new BreakpointGutterIconRenderer();
|
||||
}
|
||||
|
||||
public void clearIcon() {
|
||||
myIcon = null;
|
||||
}
|
||||
|
||||
protected class BreakpointGutterIconRenderer extends GutterIconRenderer {
|
||||
@NotNull
|
||||
public Icon getIcon() {
|
||||
return XBreakpointBase.this.getIcon();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AnAction getClickAction() {
|
||||
return new RemoveBreakpointGutterIconAction(XBreakpointBase.this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AnAction getMiddleButtonClickAction() {
|
||||
return new ToggleBreakpointGutterIconAction(XBreakpointBase.this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ActionGroup getPopupMenuActions() {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
final XDebuggerManager debuggerManager = XDebuggerManager.getInstance(getProject());
|
||||
if (!debuggerManager.getBreakpointManager().isDefaultBreakpoint(XBreakpointBase.this)) {
|
||||
group.add(new RemoveBreakpointGutterIconAction(XBreakpointBase.this));
|
||||
}
|
||||
group.add(new ToggleBreakpointGutterIconAction(XBreakpointBase.this));
|
||||
for (AnAction action : getAdditionalPopupMenuActions(debuggerManager.getCurrentSession())) {
|
||||
group.add(action);
|
||||
}
|
||||
group.add(new Separator());
|
||||
group.add(new ViewBreakpointsAction(XDebuggerBundle.message("xdebugger.view.breakpoint.properties.action"), XBreakpointBase.this));
|
||||
return group;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTooltipText() {
|
||||
return getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GutterDraggableObject getDraggableObject() {
|
||||
return createBreakpointDraggableObject();
|
||||
}
|
||||
|
||||
private XBreakpointBase<?,?,?> getBreakpoint() {
|
||||
return XBreakpointBase.this;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof XLineBreakpointImpl.BreakpointGutterIconRenderer
|
||||
&& getBreakpoint() == ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getBreakpoint()
|
||||
&& Comparing.equal(getIcon(), ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getIcon())
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getBreakpoint().hashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -114,8 +114,8 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
|
||||
private <T extends XBreakpointProperties> XBreakpointBase<?, T, ?> createBreakpoint(XBreakpointType<XBreakpoint<T>, T> type,
|
||||
T properties, final boolean enabled) {
|
||||
XBreakpointBase.BreakpointState<?,T,?> state = new XBreakpointBase.BreakpointState<XBreakpoint<T>,T,XBreakpointType<XBreakpoint<T>,T>>(enabled, type.getId());
|
||||
return new XBreakpointBase<XBreakpoint<T>,T, XBreakpointBase.BreakpointState<?,T,?>>(type, this, properties, state);
|
||||
BreakpointState<?,T,?> state = new BreakpointState<XBreakpoint<T>,T,XBreakpointType<XBreakpoint<T>,T>>(enabled, type.getId());
|
||||
return new XBreakpointBase<XBreakpoint<T>,T, BreakpointState<?,T,?>>(type, this, properties, state);
|
||||
}
|
||||
|
||||
private <T extends XBreakpointProperties> void addBreakpoint(final XBreakpointBase<?, T, ?> breakpoint, final boolean defaultBreakpoint,
|
||||
@@ -286,7 +286,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
myDependentBreakpointManager.saveState();
|
||||
BreakpointManagerState state = new BreakpointManagerState();
|
||||
for (XBreakpointBase<?, ?, ?> breakpoint : myDefaultBreakpoints.values()) {
|
||||
final XBreakpointBase.BreakpointState breakpointState = breakpoint.getState();
|
||||
final BreakpointState breakpointState = breakpoint.getState();
|
||||
if (differsFromDefault(breakpoint.getType(), breakpointState)) {
|
||||
state.getDefaultBreakpoints().add(breakpointState);
|
||||
}
|
||||
@@ -301,13 +301,13 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
}
|
||||
|
||||
private <P extends XBreakpointProperties> boolean differsFromDefault(XBreakpointType<?, P> type,
|
||||
XBreakpointBase.BreakpointState state) {
|
||||
BreakpointState state) {
|
||||
final XBreakpoint<P> defaultBreakpoint = createDefaultBreakpoint(type);
|
||||
if (defaultBreakpoint == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
XBreakpointBase.BreakpointState defaultState = ((XBreakpointBase)defaultBreakpoint).getState();
|
||||
BreakpointState defaultState = ((XBreakpointBase)defaultBreakpoint).getState();
|
||||
Element defaultElement = XmlSerializer.serialize(defaultState, SERIALIZATION_FILTER);
|
||||
Element currentElement = XmlSerializer.serialize(state, SERIALIZATION_FILTER);
|
||||
return !JDOMUtil.areElementsEqual(defaultElement, currentElement);
|
||||
@@ -323,7 +323,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
}
|
||||
|
||||
myDefaultBreakpoints.clear();
|
||||
for (XBreakpointBase.BreakpointState breakpointState : state.getDefaultBreakpoints()) {
|
||||
for (BreakpointState breakpointState : state.getDefaultBreakpoints()) {
|
||||
loadBreakpoint(breakpointState, true);
|
||||
}
|
||||
for (XBreakpointType<?, ?> type : XBreakpointUtil.getBreakpointTypes()) {
|
||||
@@ -335,7 +335,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
for (XBreakpointBase<?,?,?> breakpoint : myBreakpoints.values()) {
|
||||
doRemoveBreakpoint(breakpoint);
|
||||
}
|
||||
for (XBreakpointBase.BreakpointState breakpointState : state.getBreakpoints()) {
|
||||
for (BreakpointState breakpointState : state.getBreakpoints()) {
|
||||
loadBreakpoint(breakpointState, false);
|
||||
}
|
||||
myDependentBreakpointManager.loadState();
|
||||
@@ -361,7 +361,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
});
|
||||
}
|
||||
|
||||
private void loadBreakpoint(XBreakpointBase.BreakpointState breakpointState, final boolean defaultBreakpoint) {
|
||||
private void loadBreakpoint(BreakpointState breakpointState, final boolean defaultBreakpoint) {
|
||||
XBreakpointBase<?,?,?> breakpoint = createBreakpoint(breakpointState);
|
||||
if (breakpoint != null) {
|
||||
addBreakpoint(breakpoint, defaultBreakpoint, false);
|
||||
@@ -378,7 +378,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private XBreakpointBase<?,?,?> createBreakpoint(final XBreakpointBase.BreakpointState breakpointState) {
|
||||
private XBreakpointBase<?,?,?> createBreakpoint(final BreakpointState breakpointState) {
|
||||
XBreakpointType<?,?> type = XBreakpointUtil.findType(breakpointState.getTypeId());
|
||||
if (type == null) return null;
|
||||
//noinspection unchecked
|
||||
@@ -388,20 +388,20 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
|
||||
@Tag("breakpoint-manager")
|
||||
public static class BreakpointManagerState {
|
||||
private List<XBreakpointBase.BreakpointState> myDefaultBreakpoints = new ArrayList<XBreakpointBase.BreakpointState>();
|
||||
private List<XBreakpointBase.BreakpointState> myBreakpoints = new ArrayList<XBreakpointBase.BreakpointState>();
|
||||
private List<BreakpointState> myDefaultBreakpoints = new ArrayList<BreakpointState>();
|
||||
private List<BreakpointState> myBreakpoints = new ArrayList<BreakpointState>();
|
||||
private Map<String, XBreakpointTypeDialogState> myBreakpointTypeDialogProperties = new HashMap<String, XBreakpointTypeDialogState>();
|
||||
|
||||
@Tag("default-breakpoints")
|
||||
@AbstractCollection(surroundWithTag = false)
|
||||
public List<XBreakpointBase.BreakpointState> getDefaultBreakpoints() {
|
||||
public List<BreakpointState> getDefaultBreakpoints() {
|
||||
return myDefaultBreakpoints;
|
||||
}
|
||||
|
||||
@Tag("breakpoints")
|
||||
@AbstractCollection(surroundWithTag = false,
|
||||
elementTypes = {XBreakpointBase.BreakpointState.class, XLineBreakpointImpl.LineBreakpointState.class})
|
||||
public List<XBreakpointBase.BreakpointState> getBreakpoints() {
|
||||
elementTypes = {BreakpointState.class, LineBreakpointState.class})
|
||||
public List<BreakpointState> getBreakpoints() {
|
||||
return myBreakpoints;
|
||||
}
|
||||
|
||||
@@ -412,11 +412,11 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
|
||||
return myBreakpointTypeDialogProperties;
|
||||
}
|
||||
|
||||
public void setBreakpoints(final List<XBreakpointBase.BreakpointState> breakpoints) {
|
||||
public void setBreakpoints(final List<BreakpointState> breakpoints) {
|
||||
myBreakpoints = breakpoints;
|
||||
}
|
||||
|
||||
public void setDefaultBreakpoints(List<XBreakpointBase.BreakpointState> defaultBreakpoints) {
|
||||
public void setDefaultBreakpoints(List<BreakpointState> defaultBreakpoints) {
|
||||
myDefaultBreakpoints = defaultBreakpoints;
|
||||
}
|
||||
|
||||
|
||||
+26
-267
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.breakpoints;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.Result;
|
||||
@@ -24,7 +24,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.markup.GutterDraggableObject;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
@@ -34,44 +33,37 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import com.intellij.xdebugger.XDebuggerUtil;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.breakpoints.*;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
|
||||
import com.intellij.xdebugger.impl.XSourcePositionImpl;
|
||||
import com.intellij.xdebugger.impl.actions.ViewBreakpointsAction;
|
||||
import com.intellij.xdebugger.ui.DebuggerColors;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.dnd.DragSource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreakpointBase<XLineBreakpoint<P>, P, XLineBreakpointImpl.LineBreakpointState<P>> implements XLineBreakpoint<P> {
|
||||
public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreakpointBase<XLineBreakpoint<P>, P, LineBreakpointState<P>> implements XLineBreakpoint<P> {
|
||||
@Nullable private RangeHighlighter myHighlighter;
|
||||
private final XLineBreakpointType<P> myType;
|
||||
private Icon myIcon;
|
||||
private XSourcePosition mySourcePosition;
|
||||
@NonNls private static final String BR_NBSP = "<br> ";
|
||||
private boolean myDisposed;
|
||||
private CustomizedBreakpointPresentation myCustomizedPresentation;
|
||||
|
||||
public XLineBreakpointImpl(final XLineBreakpointType<P> type, XBreakpointManagerImpl breakpointManager, String url, int line, @Nullable final P properties) {
|
||||
super(type, breakpointManager, properties, new LineBreakpointState<P>(true, type.getId(), url, line));
|
||||
myType = type;
|
||||
}
|
||||
|
||||
private XLineBreakpointImpl(final XLineBreakpointType<P> type, XBreakpointManagerImpl breakpointManager, final LineBreakpointState<P> breakpointState) {
|
||||
XLineBreakpointImpl(final XLineBreakpointType<P> type,
|
||||
XBreakpointManagerImpl breakpointManager,
|
||||
final LineBreakpointState<P> breakpointState) {
|
||||
super(type, breakpointManager, breakpointState);
|
||||
myType = type;
|
||||
}
|
||||
@@ -92,7 +84,7 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
|
||||
attributes);
|
||||
if (highlighter != null) {
|
||||
updateIcon();
|
||||
setupGutterRenderer(highlighter);
|
||||
highlighter.setGutterIconRenderer(createGutterIconRenderer());
|
||||
}
|
||||
myHighlighter = highlighter;
|
||||
}
|
||||
@@ -109,57 +101,11 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
|
||||
return VirtualFileManager.getInstance().findFileByUrl(getFileUrl());
|
||||
}
|
||||
|
||||
private void setupGutterRenderer(final RangeHighlighter highlighter) {
|
||||
highlighter.setGutterIconRenderer(new BreakpointGutterIconRenderer());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public XLineBreakpointType<P> getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
private void updateIcon() {
|
||||
myIcon = calculateIcon();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Icon calculateIcon() {
|
||||
if (!isEnabled()) {
|
||||
// disabled icon takes precedence to other to visually distinguish it and provide feedback then it is enabled/disabled
|
||||
// (e.g. in case of mute-mode we would like to differentiate muted but enabled breakpoints from simply disabled ones)
|
||||
return myType.getDisabledIcon();
|
||||
}
|
||||
|
||||
XDebugSessionImpl session = getBreakpointManager().getDebuggerManager().getCurrentSession();
|
||||
if (session == null) {
|
||||
if (getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this) != null) {
|
||||
return myType.getDisabledDependentIcon();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (session.areBreakpointsMuted()) {
|
||||
return DebuggerIcons.MUTED_BREAKPOINT_ICON;
|
||||
}
|
||||
if (session.isDisabledSlaveBreakpoint(this)) {
|
||||
return myType.getDisabledDependentIcon();
|
||||
}
|
||||
CustomizedBreakpointPresentation presentation = session.getBreakpointPresentation(this);
|
||||
if (presentation != null) {
|
||||
Icon icon = presentation.getIcon();
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myCustomizedPresentation != null) {
|
||||
final Icon icon = myCustomizedPresentation.getIcon();
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
return myType.getEnabledIcon();
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return myState.getLine();
|
||||
}
|
||||
@@ -208,88 +154,28 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
|
||||
}
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
if (myIcon == null) {
|
||||
updateIcon();
|
||||
}
|
||||
return myIcon;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
@NonNls StringBuilder builder = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
builder.append("<html><body>");
|
||||
builder.append(myType.getDisplayText(this));
|
||||
|
||||
String errorMessage = getErrorMessage();
|
||||
if (errorMessage != null) {
|
||||
builder.append(BR_NBSP);
|
||||
builder.append("<font color=\"red\">");
|
||||
builder.append(errorMessage);
|
||||
builder.append("</font>");
|
||||
@Override
|
||||
protected GutterDraggableObject createBreakpointDraggableObject() {
|
||||
return new GutterDraggableObject() {
|
||||
public boolean copy(int line, VirtualFile file) {
|
||||
if (canMoveTo(line, file)) {
|
||||
setFileUrl(file.getUrl());
|
||||
setLine(line);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SuspendPolicy suspendPolicy = getSuspendPolicy();
|
||||
if (suspendPolicy == SuspendPolicy.THREAD) {
|
||||
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.thread"));
|
||||
public Cursor getCursor(int line) {
|
||||
return canMoveTo(line, getFile()) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
|
||||
}
|
||||
else if (suspendPolicy == SuspendPolicy.NONE) {
|
||||
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.none"));
|
||||
}
|
||||
|
||||
String condition = getCondition();
|
||||
if (condition != null) {
|
||||
builder.append(BR_NBSP);
|
||||
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.condition"));
|
||||
builder.append(" ");
|
||||
builder.append(condition);
|
||||
}
|
||||
|
||||
if (isLogMessage()) {
|
||||
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.log.message"));
|
||||
}
|
||||
String logExpression = getLogExpression();
|
||||
if (logExpression != null) {
|
||||
builder.append(BR_NBSP);
|
||||
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.log.expression"));
|
||||
builder.append(" ");
|
||||
builder.append(logExpression);
|
||||
}
|
||||
|
||||
XBreakpoint<?> masterBreakpoint = getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this);
|
||||
if (masterBreakpoint != null) {
|
||||
builder.append(BR_NBSP);
|
||||
String str = XDebuggerBundle.message("xbreakpoint.tooltip.depends.on");
|
||||
builder.append(str);
|
||||
builder.append(" ");
|
||||
builder.append(XBreakpointUtil.getDisplayText(masterBreakpoint));
|
||||
}
|
||||
|
||||
builder.append("</body><html");
|
||||
return builder.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(builder);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private boolean canMoveTo(int line, VirtualFile file) {
|
||||
return file != null && myType.canPutAt(file, line, getProject()) && getBreakpointManager().findBreakpointAtLine(myType, file, line) == null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getErrorMessage() {
|
||||
final XDebugSessionImpl currentSession = getBreakpointManager().getDebuggerManager().getCurrentSession();
|
||||
if (currentSession != null) {
|
||||
CustomizedBreakpointPresentation presentation = currentSession.getBreakpointPresentation(this);
|
||||
if (presentation != null) {
|
||||
final String message = presentation.getErrorMessage();
|
||||
if (message != null) return message;
|
||||
}
|
||||
}
|
||||
return myCustomizedPresentation != null ? myCustomizedPresentation.getErrorMessage() : null;
|
||||
}
|
||||
|
||||
public void updatePosition() {
|
||||
if (myHighlighter != null && myHighlighter.isValid()) {
|
||||
Document document = myHighlighter.getDocument();
|
||||
@@ -313,134 +199,7 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
|
||||
}
|
||||
}
|
||||
|
||||
public void setCustomizedPresentation(CustomizedBreakpointPresentation presentation) {
|
||||
myCustomizedPresentation = presentation;
|
||||
protected List<? extends AnAction> getAdditionalPopupMenuActions(final XDebugSession session) {
|
||||
return getType().getAdditionalPopupMenuActions(this, session);
|
||||
}
|
||||
|
||||
@Tag("line-breakpoint")
|
||||
public static class LineBreakpointState<P extends XBreakpointProperties> extends XBreakpointBase.BreakpointState<XLineBreakpoint<P>, P, XLineBreakpointType<P>> {
|
||||
private String myFileUrl;
|
||||
private int myLine;
|
||||
|
||||
public LineBreakpointState() {
|
||||
}
|
||||
|
||||
public LineBreakpointState(final boolean enabled, final String typeId, final String fileUrl, final int line) {
|
||||
super(enabled, typeId);
|
||||
myFileUrl = fileUrl;
|
||||
myLine = line;
|
||||
}
|
||||
|
||||
@Tag("url")
|
||||
public String getFileUrl() {
|
||||
return myFileUrl;
|
||||
}
|
||||
|
||||
public void setFileUrl(final String fileUrl) {
|
||||
myFileUrl = fileUrl;
|
||||
}
|
||||
|
||||
@Tag("line")
|
||||
public int getLine() {
|
||||
return myLine;
|
||||
}
|
||||
|
||||
public void setLine(final int line) {
|
||||
myLine = line;
|
||||
}
|
||||
|
||||
public XBreakpointBase<XLineBreakpoint<P>,P, ?> createBreakpoint(@NotNull final XLineBreakpointType<P> type, @NotNull XBreakpointManagerImpl breakpointManager) {
|
||||
return new XLineBreakpointImpl<P>(type, breakpointManager, this);
|
||||
}
|
||||
}
|
||||
|
||||
private class BreakpointGutterIconRenderer extends GutterIconRenderer {
|
||||
@NotNull
|
||||
public Icon getIcon() {
|
||||
return XLineBreakpointImpl.this.getIcon();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AnAction getClickAction() {
|
||||
return new MyRemoveBreakpointAction();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AnAction getMiddleButtonClickAction() {
|
||||
return new MyToggleBreakpointAction();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ActionGroup getPopupMenuActions() {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new MyRemoveBreakpointAction());
|
||||
group.add(new MyToggleBreakpointAction());
|
||||
for (AnAction action : myType.getAdditionalPopupMenuActions(XLineBreakpointImpl.this, XDebuggerManager.getInstance(getProject()).getCurrentSession())) {
|
||||
group.add(action);
|
||||
}
|
||||
group.add(new Separator());
|
||||
group.add(new ViewBreakpointsAction(XDebuggerBundle.message("xdebugger.view.breakpoint.properties.action"), XLineBreakpointImpl.this));
|
||||
return group;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTooltipText() {
|
||||
return getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GutterDraggableObject getDraggableObject() {
|
||||
return new GutterDraggableObject() {
|
||||
public boolean copy(int line, VirtualFile file) {
|
||||
if (canMoveTo(line, file)) {
|
||||
setFileUrl(file.getUrl());
|
||||
setLine(line);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Cursor getCursor(int line) {
|
||||
return canMoveTo(line, getFile()) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private XLineBreakpointImpl getXLineBreakpoint() {
|
||||
return XLineBreakpointImpl.this;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj.getClass() == getClass()
|
||||
&& getXLineBreakpoint() == ((BreakpointGutterIconRenderer)obj).getXLineBreakpoint()
|
||||
&& Comparing.equal(getIcon(), ((BreakpointGutterIconRenderer)obj).getIcon())
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getXLineBreakpoint().hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private class MyRemoveBreakpointAction extends AnAction {
|
||||
private MyRemoveBreakpointAction() {
|
||||
super(XDebuggerBundle.message("xdebugger.remove.line.breakpoint.action.text"));
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
XDebuggerUtil.getInstance().removeBreakpoint(XLineBreakpointImpl.this.getProject(), XLineBreakpointImpl.this);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyToggleBreakpointAction extends AnAction {
|
||||
private MyToggleBreakpointAction() {
|
||||
super(isEnabled() ? XDebuggerBundle.message("xdebugger.disable.breakpoint.action.text") : XDebuggerBundle.message("xdebugger.enable.breakpoint.action.text"));
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
setEnabled(!isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-4
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
@@ -41,16 +42,18 @@ public class ExecutionPointHighlighter {
|
||||
private XSourcePosition mySourcePosition;
|
||||
private OpenFileDescriptor myOpenFileDescriptor;
|
||||
private boolean myUseSelection;
|
||||
private GutterIconRenderer myGutterIconRenderer;
|
||||
|
||||
public ExecutionPointHighlighter(final Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public void show(final @NotNull XSourcePosition position, final boolean useSelection) {
|
||||
public void show(final @NotNull XSourcePosition position, final boolean useSelection,
|
||||
@Nullable final GutterIconRenderer gutterIconRenderer) {
|
||||
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
|
||||
public void run() {
|
||||
if (!myProject.isDisposed()) {
|
||||
doShow(position, useSelection);
|
||||
doShow(position, useSelection, gutterIconRenderer);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -76,16 +79,28 @@ public class ExecutionPointHighlighter {
|
||||
}
|
||||
|
||||
public void update() {
|
||||
show(mySourcePosition, myUseSelection);
|
||||
show(mySourcePosition, myUseSelection, myGutterIconRenderer);
|
||||
}
|
||||
|
||||
private void doShow(@NotNull XSourcePosition position, final boolean useSelection) {
|
||||
public void updateGutterIcon(@NotNull final GutterIconRenderer renderer) {
|
||||
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myRangeHighlighter != null && myGutterIconRenderer != null) {
|
||||
myRangeHighlighter.setGutterIconRenderer(renderer);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doShow(@NotNull XSourcePosition position, final boolean useSelection, @Nullable GutterIconRenderer renderer) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
removeHighlighter();
|
||||
|
||||
mySourcePosition = position;
|
||||
myEditor = openEditor();
|
||||
myUseSelection = useSelection;
|
||||
myGutterIconRenderer = renderer;
|
||||
if (myEditor != null) {
|
||||
addHighlighter();
|
||||
}
|
||||
@@ -137,5 +152,6 @@ public class ExecutionPointHighlighter {
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
myRangeHighlighter = myEditor.getMarkupModel().addLineHighlighter(line, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER,
|
||||
scheme.getAttributes(DebuggerColors.EXECUTIONPOINT_ATTRIBUTES));
|
||||
myRangeHighlighter.setGutterIconRenderer(myGutterIconRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user