From f5a2a417fdcff5b4eb4a60f1f1e0bf29efd50979 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 27 Sep 2013 15:14:11 +0400 Subject: [PATCH] new X JavaBreakpoint works (except filters). Right now via adapter, it is enough for http://youtrack.jetbrains.com/issue/WEB-4429 and it is not hack (well, actually, it is hack because we use adapters, but in any case our JS Debug process (and Ruby in the future and any other clients) can work via XDebugger API and all low-level details are hidden. this feature in action only if java.debugger.xBreakpoint=true specified --- .../engine/requests/RequestManagerImpl.java | 22 +++- .../debugger/impl/DebuggerManagerImpl.java | 1 - .../ui/breakpoints/BreakpointManager.java | 104 ++++++--------- .../BreakpointWithHighlighter.java | 38 ++++-- .../ui/breakpoints/LineBreakpoint.java | 11 +- .../breakpoints/JavaBreakpointAdapter.java | 121 ++++++++++++++++++ .../JavaBreakpointAdapterBase.java | 62 +++++++++ .../intellij/util/containers/MultiMap.java | 6 +- 8 files changed, 277 insertions(+), 88 deletions(-) create mode 100644 java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java create mode 100644 java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java index 9491be456e1e..981841d14975 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java @@ -29,7 +29,9 @@ import com.intellij.debugger.settings.DebuggerSettings; import com.intellij.debugger.ui.breakpoints.Breakpoint; import com.intellij.debugger.ui.breakpoints.BreakpointManager; import com.intellij.debugger.ui.breakpoints.FilteredRequestor; +import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; @@ -37,10 +39,15 @@ import com.intellij.openapi.util.Key; import com.intellij.psi.PsiClass; import com.intellij.ui.classFilter.ClassFilter; import com.intellij.util.containers.HashMap; +import com.intellij.xdebugger.XDebuggerManager; +import com.intellij.xdebugger.breakpoints.XBreakpointProperties; +import com.intellij.xdebugger.breakpoints.XLineBreakpoint; import com.sun.jdi.*; import com.sun.jdi.event.ClassPrepareEvent; import com.sun.jdi.request.*; import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.debugger.breakpoints.JavaBreakpointAdapter; +import org.jetbrains.java.debugger.breakpoints.JavaBreakpointType; import java.util.Collections; import java.util.HashSet; @@ -390,10 +397,23 @@ public class RequestManagerImpl extends DebugProcessAdapterImpl implements Reque // invoke later, so that requests are for sure created only _after_ 'processAttached()' methods of other listeners are executed process.getManagerThread().schedule(new DebuggerCommandImpl() { protected void action() throws Exception { - final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myDebugProcess.getProject()).getBreakpointManager(); + Project project = myDebugProcess.getProject(); + final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager(); for (final Breakpoint breakpoint : breakpointManager.getBreakpoints()) { breakpoint.createRequest(myDebugProcess); } + + AccessToken token = ReadAction.start(); + try { + JavaBreakpointAdapter adapter = new JavaBreakpointAdapter(project); + for (XLineBreakpoint breakpoint : XDebuggerManager.getInstance(project).getBreakpointManager() + .getBreakpoints(JavaBreakpointType.class)) { + adapter.getOrCreate(breakpoint).createRequest(myDebugProcess); + } + } + finally { + token.finish(); + } } }); } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java index 549dc936fb6e..c60a3b220906 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java @@ -176,7 +176,6 @@ public class DebuggerManagerImpl extends DebuggerManagerEx implements Persistent myBreakpointManager.init(); } - @Nullable @Override public Element getState() { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java index 4ccbacc33c96..39722b7e5806 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java @@ -58,7 +58,11 @@ import com.intellij.psi.PsiFile; import com.intellij.util.Alarm; import com.intellij.util.EventDispatcher; import com.intellij.util.IJSwingUtilities; +import com.intellij.util.SystemProperties; +import com.intellij.util.containers.MultiMap; +import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XDebuggerUtil; +import com.intellij.xdebugger.breakpoints.XBreakpointType; import com.intellij.xdebugger.impl.DebuggerSupport; import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.sun.jdi.Field; @@ -72,6 +76,7 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.debugger.breakpoints.JavaBreakpointAdapter; import org.jetbrains.java.debugger.breakpoints.JavaBreakpointType; import javax.swing.*; @@ -93,7 +98,7 @@ public class BreakpointManager { private final List myBreakpoints = new ArrayList(); // breakpoints storage, access should be synchronized private final List myBreakpointRules = new ArrayList(); // breakpoint rules @Nullable private List myBreakpointsListForIteration = null; // another list for breakpoints iteration, unsynchronized access ok - private final Map> myDocumentBreakpoints = new THashMap>(); + private final MultiMap myDocumentBreakpoints = MultiMap.createSmartList(); private final Map myUIProperties = new LinkedHashMap(); private final Map, BreakpointDefaults> myBreakpointDefaults = new LinkedHashMap, BreakpointDefaults>(); @@ -101,19 +106,14 @@ public class BreakpointManager { private final StartupManager myStartupManager; - static final class State { - - } - private void update(@NotNull List breakpoints) { final TIntHashSet intHash = new TIntHashSet(); - for (BreakpointWithHighlighter breakpoint : breakpoints) { SourcePosition sourcePosition = breakpoint.getSourcePosition(); breakpoint.reload(); if (breakpoint.isValid()) { - if (breakpoint.getSourcePosition().getLine() != sourcePosition.getLine()) { + if (sourcePosition == null || breakpoint.getSourcePosition().getLine() != sourcePosition.getLine()) { fireBreakpointChanged(breakpoint); } @@ -130,25 +130,6 @@ public class BreakpointManager { } } - /* - // todo: not needed?? - private void setInvalid(final BreakpointWithHighlighter breakpoint) { - Collection sessions = DebuggerManagerEx.getInstanceEx(myProject).getSessions(); - - for (Iterator iterator = sessions.getSectionsIterator(); getSectionsIterator.hasNext();) { - DebuggerSession session = iterator.next(); - final DebugProcessImpl process = session.getProcess(); - process.getManagerThread().schedule(new DebuggerCommandImpl() { - protected void action() throws Exception { - process.getRequestsManager().deleteRequest(breakpoint); - process.getRequestsManager().setInvalid(breakpoint, "Source code changed"); - breakpoint.updateUI(); - } - }); - } - } - */ - private void remove(final BreakpointWithHighlighter breakpoint) { DebuggerInvocationUtil.invokeLater(myProject, new Runnable() { @Override @@ -172,11 +153,16 @@ public class BreakpointManager { } } }); + + if (!project.isDefault()) { + XDebuggerManager.getInstance(project).getBreakpointManager().addBreakpointListener( + XBreakpointType.EXTENSION_POINT_NAME.findExtension(JavaBreakpointType.class), new JavaBreakpointAdapter(project), project); + } } public void init() { EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster(); - EditorMouseAdapter myEditorMouseListener = new EditorMouseAdapter() { + eventMulticaster.addEditorMouseListener(new EditorMouseAdapter() { @Nullable private EditorMouseEvent myMousePressedEvent; @Nullable @@ -191,6 +177,12 @@ public class BreakpointManager { return null; } + if (SystemProperties.getBooleanProperty("java.debugger.xBreakpoint", false) && + XBreakpointType.EXTENSION_POINT_NAME.findExtension(JavaBreakpointType.class) + .canPutAt(psiFile.getVirtualFile(), line, myProject)) { + return null; + } + PsiDocumentManager.getInstance(myProject).commitDocument(document); int offset = editor.getCaretModel().getOffset(); @@ -339,11 +331,9 @@ public class BreakpointManager { }); } } - }; + }, myProject); - eventMulticaster.addEditorMouseListener(myEditorMouseListener, myProject); - - final DocumentListener myDocumentListener = new DocumentAdapter() { + eventMulticaster.addDocumentListener(new DocumentAdapter() { private final Alarm myUpdateAlarm = new Alarm(); @Override @@ -351,9 +341,8 @@ public class BreakpointManager { final Document document = e.getDocument(); //noinspection SynchronizeOnThis synchronized (BreakpointManager.this) { - List breakpoints = myDocumentBreakpoints.get(document); - - if(breakpoints != null) { + Collection breakpoints = myDocumentBreakpoints.get(document); + if (!breakpoints.isEmpty()) { myUpdateAlarm.cancelAllRequests(); // must create new array in order to avoid "concurrent modification" errors final List breakpointsToUpdate = new ArrayList(breakpoints); @@ -369,9 +358,7 @@ public class BreakpointManager { } } } - }; - - eventMulticaster.addDocumentListener(myDocumentListener, myProject); + }, myProject); } public void editBreakpoint(final Breakpoint breakpoint, final Editor editor) { @@ -501,7 +488,6 @@ public class BreakpointManager { @NotNull public List findBreakpoints(final Document document, final int offset) { LinkedList result = new LinkedList(); - ApplicationManager.getApplication().assertIsDispatchThread(); for (final Breakpoint breakpoint : getBreakpoints()) { if (breakpoint instanceof BreakpointWithHighlighter && ((BreakpointWithHighlighter)breakpoint).isAt(document, offset)) { @@ -530,15 +516,18 @@ public class BreakpointManager { } /** - * - * @param document - * @param offset - * @param category breakpoint's category, null if the category does not matter - * @return + * @param category breakpoint category, null if the category does not matter */ @Nullable public T findBreakpoint(final Document document, final int offset, @Nullable final Key category) { - ApplicationManager.getApplication().assertIsDispatchThread(); + for (BreakpointWithHighlighter breakpointWithHighlighter : myDocumentBreakpoints.get(document)) { + if (breakpointWithHighlighter.isAt(document, offset) && + (category == null || category.equals(breakpointWithHighlighter.getCategory()))) { + //noinspection unchecked + return (T)breakpointWithHighlighter; + } + } + for (final Breakpoint breakpoint : getBreakpoints()) { if (breakpoint instanceof BreakpointWithHighlighter && ((BreakpointWithHighlighter)breakpoint).isAt(document, offset)) { if (category == null || category.equals(breakpoint.getCategory())) { @@ -668,13 +657,7 @@ public class BreakpointManager { myBreakpointsListForIteration = null; if (breakpoint instanceof BreakpointWithHighlighter) { BreakpointWithHighlighter breakpointWithHighlighter = (BreakpointWithHighlighter)breakpoint; - Document document = breakpointWithHighlighter.getDocument(); - List breakpoints = myDocumentBreakpoints.get(document); - if (breakpoints == null) { - breakpoints = new ArrayList(); - myDocumentBreakpoints.put(document, breakpoints); - } - breakpoints.add(breakpointWithHighlighter); + myDocumentBreakpoints.putValue(breakpointWithHighlighter.getDocument(), breakpointWithHighlighter); } myDispatcher.getMulticaster().breakpointsChanged(); } @@ -688,16 +671,9 @@ public class BreakpointManager { if (myBreakpoints.remove(breakpoint)) { updateBreakpointRules(breakpoint); myBreakpointsListForIteration = null; - if(breakpoint instanceof BreakpointWithHighlighter) { - //breakpoint.saveToString() may be invalid - - for (final Document document : myDocumentBreakpoints.keySet()) { - final List documentBreakpoints = myDocumentBreakpoints.get(document); - final boolean reallyRemoved = documentBreakpoints.remove(breakpoint); - if (reallyRemoved) { - if (documentBreakpoints.isEmpty()) { - myDocumentBreakpoints.remove(document); - } + if (breakpoint instanceof BreakpointWithHighlighter) { + for (Document document : myDocumentBreakpoints.keySet()) { + if (myDocumentBreakpoints.removeValue(document, (BreakpointWithHighlighter)breakpoint)) { break; } } @@ -721,8 +697,10 @@ public class BreakpointManager { group.setAttribute(DEFAULT_SUSPEND_POLICY_ATTRIBUTE_NAME, String.valueOf(defaults.getSuspendPolicy())); group.setAttribute(DEFAULT_CONDITION_STATE_ATTRIBUTE_NAME, String.valueOf(defaults.isConditionEnabled())); } - for (final Breakpoint breakpoint : getBreakpoints()) { - if (breakpoint.isValid()) { + // don't store invisible breakpoints + for (Breakpoint breakpoint : getBreakpoints()) { + if (breakpoint.isValid() && + (!(breakpoint instanceof BreakpointWithHighlighter) || ((BreakpointWithHighlighter)breakpoint).isVisible())) { writeBreakpoint(getCategoryGroupElement(categoryToElementMap, breakpoint.getCategory(), parentNode), breakpoint); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java index 2da27531a951..68a4c68a50a6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java @@ -46,6 +46,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.jsp.JspFile; +import com.intellij.ui.AppUIUtil; import com.intellij.ui.classFilter.ClassFilter; import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.xdebugger.impl.DebuggerSupport; @@ -94,6 +95,7 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { return myIcon; } + @Nullable @Override public String getClassName() { return myClassName; @@ -111,13 +113,14 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { return super.getShortClassName(); } + @Nullable @Override public String getPackageName() { return myPackageName; } @Nullable - protected Breakpoint init() { + public BreakpointWithHighlighter init() { if (!isValid()) { myHighlighter.dispose(); return null; @@ -181,12 +184,16 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { public BreakpointWithHighlighter(@NotNull final Project project, @NotNull final RangeHighlighter highlighter) { super(project); myHighlighter = highlighter; - highlighter.setEditorFilter(MarkupEditorFilterFactory.createIsNotDiffFilter()); + setEditorFilter(highlighter); reload(); } + protected void setEditorFilter(RangeHighlighter highlighter) { + highlighter.setEditorFilter(MarkupEditorFilterFactory.createIsNotDiffFilter()); + } + public RangeHighlighter getHighlighter() { - ApplicationManager.getApplication().assertIsDispatchThread(); + ApplicationManager.getApplication().assertReadAccessAllowed(); return myHighlighter; } @@ -275,11 +282,12 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { @Override public final void reload() { - ApplicationManager.getApplication().assertIsDispatchThread(); - if (getHighlighter().isValid()) { - PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(getHighlighter().getDocument()); + ApplicationManager.getApplication().assertReadAccessAllowed(); + RangeHighlighter highlighter = myHighlighter; + if (highlighter != null && highlighter.isValid()) { + PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(highlighter.getDocument()); if (psiFile != null) { - mySourcePosition = SourcePosition.createFromOffset(psiFile, getHighlighter().getStartOffset()); + mySourcePosition = SourcePosition.createFromOffset(psiFile, highlighter.getStartOffset()); reload(psiFile); return; } @@ -319,7 +327,6 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { updateUI(); } - /** * updates the state of breakpoint and all the related UI widgets etc */ @@ -338,7 +345,6 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { DebuggerContextImpl context = DebuggerManagerEx.getInstanceEx(project).getContext(); final DebugProcessImpl debugProcess = context.getDebugProcess(); - if (debugProcess == null || !debugProcess.isAttached()) { updateCaches(null); updateGutter(); @@ -371,9 +377,16 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { private void updateGutter() { if (myVisible) { - RangeHighlighter highlighter = getHighlighter(); + RangeHighlighter highlighter = myHighlighter; if (highlighter != null && highlighter.isValid() && isValid()) { - setupGutterRenderer(highlighter); + AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() { + @Override + public void run() { + if (isValid()) { + setupGutterRenderer(myHighlighter); + } + } + }); } else { DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(this); @@ -430,8 +443,7 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { } private void setupGutterRenderer(@NotNull RangeHighlighter highlighter) { - MyGutterIconRenderer renderer = new MyGutterIconRenderer(getIcon(), getDescription()); - highlighter.setGutterIconRenderer(renderer); + highlighter.setGutterIconRenderer(new MyGutterIconRenderer(getIcon(), getDescription())); } @Override diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java index beacd1996b5f..5682ee5dd3dc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java @@ -35,7 +35,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.RangeHighlighter; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; @@ -60,6 +59,7 @@ import com.sun.jdi.*; import com.sun.jdi.event.LocatableEvent; import com.sun.jdi.request.BreakpointRequest; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; @@ -78,7 +78,7 @@ public class LineBreakpoint extends BreakpointWithHighlighter { super(project); } - protected LineBreakpoint(Project project, RangeHighlighter highlighter) { + public LineBreakpoint(Project project, RangeHighlighter highlighter) { super(project, highlighter); } @@ -471,12 +471,7 @@ public class LineBreakpoint extends BreakpointWithHighlighter { return ContextUtil.getContextElement(getSourcePosition()); } - protected static LineBreakpoint create(Project project, Document document, int lineIndex) { - VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); - if (virtualFile == null) { - return null; - } - + public static LineBreakpoint create(@NotNull Project project, @NotNull Document document, int lineIndex) { final RangeHighlighter highlighter = createHighlighter(project, document, lineIndex); if (highlighter == null) { return null; diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java new file mode 100644 index 000000000000..c9f573506579 --- /dev/null +++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java @@ -0,0 +1,121 @@ +package org.jetbrains.java.debugger.breakpoints; + +import com.intellij.debugger.engine.evaluation.CodeFragmentKind; +import com.intellij.debugger.engine.evaluation.TextWithImportsImpl; +import com.intellij.debugger.engine.requests.RequestManagerImpl; +import com.intellij.debugger.settings.DebuggerSettings; +import com.intellij.debugger.ui.breakpoints.LineBreakpoint; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.xdebugger.breakpoints.XBreakpointProperties; +import com.intellij.xdebugger.breakpoints.XLineBreakpoint; +import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl; +import org.jetbrains.annotations.NotNull; + +public class JavaBreakpointAdapter extends JavaBreakpointAdapterBase { + private static final Key OLD_JAVA_BREAKPOINT_KEY = Key.create("oldJavaBreakpoint"); + + public JavaBreakpointAdapter(Project project) { + super(project); + } + + @Override + protected void configureCreatedBreakpoint(LineBreakpoint oldBreakpoint, XLineBreakpoint breakpoint) { + oldBreakpoint.SUSPEND_POLICY = transformSuspendPolicy(breakpoint); + applyCondition(oldBreakpoint, breakpoint); + } + + private static void applyCondition(LineBreakpoint oldBreakpoint, XLineBreakpoint breakpoint) { + if (breakpoint.getCondition() != null) { + oldBreakpoint.CONDITION_ENABLED = true; + oldBreakpoint.setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, breakpoint.getCondition())); + } + else { + oldBreakpoint.CONDITION_ENABLED = false; + if (!StringUtil.isEmptyOrSpaces(oldBreakpoint.getCondition().getText())) { + oldBreakpoint.setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "")); + } + } + } + + @Override + protected void updateBreakpoint(LineBreakpoint jBreakpoint, XLineBreakpoint breakpoint) { + boolean changed = false; + if (jBreakpoint.ENABLED != breakpoint.isEnabled()) { + jBreakpoint.ENABLED = breakpoint.isEnabled(); + changed = true; + } + + String suspendPolicy = transformSuspendPolicy(breakpoint); + if (jBreakpoint.SUSPEND_POLICY != suspendPolicy) { + jBreakpoint.SUSPEND_POLICY = suspendPolicy; + changed = true; + } + + if (StringUtil.compare(breakpoint.getCondition(), jBreakpoint.getCondition().getText(), false) != 0) { + applyCondition(jBreakpoint, breakpoint); + changed = true; + } + + if (jBreakpoint.getSourcePosition().getLine() != breakpoint.getLine()) { + jBreakpoint.reload(); + changed = true; + } + + if (changed) { + RequestManagerImpl.updateRequests(jBreakpoint); + jBreakpoint.updateUI(); + } + } + + @Override + protected LineBreakpoint findBreakpoint(XLineBreakpoint breakpoint) { + return OLD_JAVA_BREAKPOINT_KEY.get(breakpoint); + } + + public LineBreakpoint getOrCreate(XLineBreakpoint breakpoint) { + LineBreakpoint oldBreakpoint = findBreakpoint(breakpoint); + if (oldBreakpoint == null) { + oldBreakpoint = createBreakpoint(breakpoint); + OLD_JAVA_BREAKPOINT_KEY.set(breakpoint, oldBreakpoint); + } + return oldBreakpoint; + } + + @Override + public void breakpointRemoved(@NotNull XLineBreakpoint breakpoint) { + LineBreakpoint jBreakpoint = findBreakpoint(breakpoint); + if (jBreakpoint != null) { + jBreakpoint.delete(); + } + } + + @Override + protected LineBreakpoint doCreateInstance(Project project, Document document, XLineBreakpoint breakpoint) { + LineBreakpoint lineBreakpoint = new LineBreakpoint(project, ((XLineBreakpointImpl)breakpoint).getHighlighter()) { + @Override + protected void setEditorFilter(RangeHighlighter highlighter) { + } + }; + + lineBreakpoint.init(); + return lineBreakpoint; + } + + private static String transformSuspendPolicy(XLineBreakpoint breakpoint) { + switch (breakpoint.getSuspendPolicy()) { + case ALL: + return DebuggerSettings.SUSPEND_ALL; + case THREAD: + return DebuggerSettings.SUSPEND_THREAD; + case NONE: + return DebuggerSettings.SUSPEND_NONE; + + default: + throw new IllegalArgumentException("unknown suspend policy"); + } + } +} diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java new file mode 100644 index 000000000000..12cdd53f4a28 --- /dev/null +++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java @@ -0,0 +1,62 @@ +package org.jetbrains.java.debugger.breakpoints; + +import com.intellij.debugger.ui.breakpoints.LineBreakpoint; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.xdebugger.breakpoints.XBreakpointAdapter; +import com.intellij.xdebugger.breakpoints.XBreakpointProperties; +import com.intellij.xdebugger.breakpoints.XLineBreakpoint; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class JavaBreakpointAdapterBase extends XBreakpointAdapter> { + protected final Project myProject; + + public JavaBreakpointAdapterBase(Project project) { + myProject = project; + } + + @Nullable + public LineBreakpoint createBreakpoint(XLineBreakpoint breakpoint) { + String url = breakpoint.getFileUrl(); + VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); + Document document = file != null ? FileDocumentManager.getInstance().getDocument(file) : null; + if (document == null) { + return null; + } + LineBreakpoint jBreakpoint = createInvisibleBreakpoint(myProject, document, breakpoint); + configureCreatedBreakpoint(jBreakpoint, breakpoint); + return jBreakpoint; + } + + protected void configureCreatedBreakpoint(LineBreakpoint oldBreakpoint, XLineBreakpoint breakpoint) { + oldBreakpoint.getHighlighter().dispose(); + } + + @Override + public final void breakpointChanged(@NotNull XLineBreakpoint breakpoint) { + LineBreakpoint jBreakpoint = findBreakpoint(breakpoint); + if (jBreakpoint != null) { + updateBreakpoint(jBreakpoint, breakpoint); + } + } + + protected abstract void updateBreakpoint(LineBreakpoint oldBreakpoint, XLineBreakpoint breakpoint); + + protected abstract LineBreakpoint findBreakpoint(XLineBreakpoint breakpoint); + + protected LineBreakpoint createInvisibleBreakpoint(Project project, Document document, XLineBreakpoint breakpoint) { + LineBreakpoint oldBreakpoint = doCreateInstance(project, document, breakpoint); + oldBreakpoint.setVisible(false); + oldBreakpoint.updateUI(); + oldBreakpoint.ENABLED = breakpoint.isEnabled(); + return oldBreakpoint; + } + + protected LineBreakpoint doCreateInstance(Project project, Document document, XLineBreakpoint breakpoint) { + return LineBreakpoint.create(project, document, breakpoint.getLine()); + } +} diff --git a/platform/util/src/com/intellij/util/containers/MultiMap.java b/platform/util/src/com/intellij/util/containers/MultiMap.java index ba8f8942e74a..c2465ca0f478 100644 --- a/platform/util/src/com/intellij/util/containers/MultiMap.java +++ b/platform/util/src/com/intellij/util/containers/MultiMap.java @@ -142,14 +142,16 @@ public class MultiMap implements Serializable { myMap.put(key, values); } - public void removeValue(final K key, final V value) { + public boolean removeValue(final K key, final V value) { final Collection values = myMap.get(key); if (values != null) { - values.remove(value); + boolean removed = values.remove(value); if (values.isEmpty()) { myMap.remove(key); } + return removed; } + return false; } public Collection values() {