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 f60d76fff483..e65ea35b04d0 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 @@ -339,11 +339,12 @@ public class BreakpointManager { if (breakpointElement != null) { XBreakpointManager manager = XDebuggerManager.getInstance(myProject).getBreakpointManager(); JavaExceptionBreakpointType type = XDebuggerUtil.getInstance().findBreakpointType(JavaExceptionBreakpointType.class); - XBreakpoint xBreakpoint = manager.getDefaultBreakpoint(type); - Breakpoint breakpoint = getJavaBreakpoint(xBreakpoint); - if (breakpoint != null) { - breakpoint.readExternal(breakpointElement); - addBreakpoint(breakpoint); + for (XBreakpoint defaultBreakpoint : manager.getDefaultBreakpoints(type)) { + Breakpoint breakpoint = getJavaBreakpoint(defaultBreakpoint); + if (breakpoint != null) { + breakpoint.readExternal(breakpointElement); + addBreakpoint(breakpoint); + } } } } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java index ee32e8fdf54c..8d8a69a26bed 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointManager.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Collection; +import java.util.Set; /** * Use {@link com.intellij.xdebugger.XDebuggerManager#getBreakpointManager()} to obtain instance of this service @@ -50,8 +51,8 @@ public interface XBreakpointManager { boolean isDefaultBreakpoint(@NotNull XBreakpoint breakpoint); - @Nullable - > B getDefaultBreakpoint(@NotNull XBreakpointType type); + @NotNull + > Set getDefaultBreakpoints(@NotNull XBreakpointType type); , P extends XBreakpointProperties> void addBreakpointListener(@NotNull XBreakpointType type, @NotNull XBreakpointListener listener); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java index 820c30b31717..969fa9f2c23c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.*; +import java.util.stream.Collectors; /** * @author nik @@ -34,9 +35,9 @@ public class XBreakpointManagerImpl implements XBreakpointManager { private static final Logger LOG = Logger.getInstance(XBreakpointManagerImpl.class); private final MultiValuesMap> myBreakpoints = new MultiValuesMap<>(true); - private final Map> myDefaultBreakpoints = new LinkedHashMap<>(); + private final Map>> myDefaultBreakpoints = new LinkedHashMap<>(); private final Map> myBreakpointsDefaults = new LinkedHashMap<>(); - private final Set> myAllBreakpoints = new HashSet<>(); + private final Set> myAllBreakpoints = new LinkedHashSet<>(); private final Map> myDispatchers = new HashMap<>(); private XBreakpointsDialogState myBreakpointsDialogSettings; private volatile EventDispatcher myAllBreakpointsDispatcher; @@ -117,9 +118,14 @@ public class XBreakpointManagerImpl implements XBreakpointManager { @Override @NotNull public XBreakpoint addBreakpoint(final XBreakpointType,T> type, @Nullable final T properties) { + return addBreakpoint(type, properties, false); + } + + @NotNull + public XBreakpoint addBreakpoint(final XBreakpointType,T> type, @Nullable final T properties, boolean defaultBreakpoint) { ApplicationManager.getApplication().assertWriteAccessAllowed(); - XBreakpointBase breakpoint = createBreakpoint(type, properties, true, false); - addBreakpoint(breakpoint, false, true); + XBreakpointBase breakpoint = createBreakpoint(type, properties, true, defaultBreakpoint); + addBreakpoint(breakpoint, defaultBreakpoint, true); return breakpoint; } @@ -138,8 +144,8 @@ public class XBreakpointManagerImpl implements XBreakpointManager { boolean initUI) { XBreakpointType type = breakpoint.getType(); if (defaultBreakpoint) { - LOG.assertTrue(!myDefaultBreakpoints.containsKey(type), "Cannot have more than one default breakpoint (type " + type.getId() + ")"); - myDefaultBreakpoints.put(type, breakpoint); + Set> typeDefaultBreakpoints = myDefaultBreakpoints.computeIfAbsent(type, k -> new LinkedHashSet<>()); + typeDefaultBreakpoints.add(breakpoint); } else { myBreakpoints.put(type, breakpoint); @@ -184,11 +190,16 @@ public class XBreakpointManagerImpl implements XBreakpointManager { @Override public void removeBreakpoint(@NotNull final XBreakpoint breakpoint) { ApplicationManager.getApplication().assertWriteAccessAllowed(); - doRemoveBreakpoint(breakpoint); + doRemoveBreakpoint(breakpoint, false); } - private void doRemoveBreakpoint(XBreakpoint breakpoint) { - if (isDefaultBreakpoint(breakpoint)) { + public void removeBreakpoint(XBreakpoint breakpoint, boolean forceRemoveDefaultBreakpoints) { + ApplicationManager.getApplication().assertWriteAccessAllowed(); + doRemoveBreakpoint(breakpoint, forceRemoveDefaultBreakpoints); + } + + private void doRemoveBreakpoint(XBreakpoint breakpoint, boolean forceRemoveDefaultBreakpoints) { + if (isDefaultBreakpoint(breakpoint) && !forceRemoveDefaultBreakpoints) { // removing default breakpoint should just disable it breakpoint.setEnabled(false); } @@ -249,11 +260,8 @@ public class XBreakpointManagerImpl implements XBreakpointManager { @NotNull public > Collection getBreakpoints(@NotNull final XBreakpointType type) { ApplicationManager.getApplication().assertReadAccessAllowed(); - List result = new ArrayList<>(); - B defaultBreakpoint = getDefaultBreakpoint(type); - if (defaultBreakpoint != null) { - result.add(defaultBreakpoint); - } + Set defaultBreakpoints = getDefaultBreakpoints(type); + List result = new ArrayList<>(defaultBreakpoints); Collection> breakpoints = myBreakpoints.get(type); if (breakpoints != null) { result.addAll((Collection)breakpoints); @@ -270,10 +278,14 @@ public class XBreakpointManagerImpl implements XBreakpointManager { } @Override - @Nullable - public > B getDefaultBreakpoint(@NotNull XBreakpointType type) { + @NotNull + public > Set getDefaultBreakpoints(@NotNull XBreakpointType type) { + Set> breakpointsSet = myDefaultBreakpoints.get(type); + if (breakpointsSet == null) { + return Collections.emptySet(); + } //noinspection unchecked - return (B)myDefaultBreakpoints.get(type); + return breakpointsSet.stream().map(breakpoint -> (B)breakpoint).collect(Collectors.toSet()); } @Override @@ -296,8 +308,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager { @Override public boolean isDefaultBreakpoint(@NotNull XBreakpoint breakpoint) { - //noinspection SuspiciousMethodCalls - return myDefaultBreakpoints.values().contains(breakpoint); + return getDefaultBreakpoints(breakpoint.getType()).contains(breakpoint); } private EventDispatcher getOrCreateDispatcher(final XBreakpointType type) { @@ -370,10 +381,12 @@ public class XBreakpointManagerImpl implements XBreakpointManager { myDependentBreakpointManager.saveState(); List> defaultBreakpoints = new SmartList<>(); - for (XBreakpointBase breakpoint : myDefaultBreakpoints.values()) { - final BreakpointState breakpointState = breakpoint.getState(); - if (differsFromDefault(breakpoint.getType(), breakpointState)) { - defaultBreakpoints.add(breakpointState); + for (Set> typeDefaultBreakpoints : myDefaultBreakpoints.values()) { + for (XBreakpointBase breakpoint : typeDefaultBreakpoints) { + final BreakpointState breakpointState = breakpoint.getState(); + if (differsFromDefault(breakpoint.getType(), breakpointState)) { + defaultBreakpoints.add(breakpointState); + } } } @@ -435,9 +448,9 @@ public class XBreakpointManagerImpl implements XBreakpointManager { ApplicationManager.getApplication().runReadAction(() -> { ContainerUtil.notNullize(state.getDefaultBreakpoints()).forEach(breakpointState -> loadBreakpoint(breakpointState, true)); - XBreakpointUtil.breakpointTypes().remove(myDefaultBreakpoints::containsKey).forEach(this::addDefaultBreakpoint); + loadDefaultBreakpointsFromType(); - myBreakpoints.values().forEach(this::doRemoveBreakpoint); + myBreakpoints.values().forEach(breakpoint -> doRemoveBreakpoint(breakpoint, false)); ContainerUtil.notNullize(state.getBreakpoints()).forEach(breakpointState -> loadBreakpoint(breakpointState, false)); @@ -457,6 +470,21 @@ public class XBreakpointManagerImpl implements XBreakpointManager { myDefaultGroup = state.getDefaultGroup(); } + @SuppressWarnings("unchecked") + private void loadDefaultBreakpointsFromType() { + for (XBreakpointType breakpointType : XBreakpointUtil.breakpointTypes()) { + XBreakpointBase defaultBreakpoint = (XBreakpointBase) createDefaultBreakpoint(breakpointType); + if (defaultBreakpoint == null) { + continue; + } + + BreakpointState defaultBreakpointState = defaultBreakpoint.getState(); + if (getDefaultBreakpoints(breakpointType).stream().allMatch(existingBreakpoint -> statesAreDifferent(defaultBreakpointState, ((XBreakpointBase) existingBreakpoint).getState(), false))) { + addBreakpoint(defaultBreakpoint, true, false); + } + } + } + private

void addDefaultBreakpoint(XBreakpointType type) { final XBreakpoint

breakpoint = createDefaultBreakpoint(type); if (breakpoint != null) { diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java index 34fed61b8905..4628feab8db6 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java @@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.List; +import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -22,26 +23,26 @@ import static org.assertj.core.api.Assertions.assertThat; public class XBreakpointManagerTest extends XBreakpointsTestCase { public void testAddRemove() { - XBreakpoint defaultBreakpoint = myBreakpointManager.getDefaultBreakpoint(MY_SIMPLE_BREAKPOINT_TYPE); - assertSameElements(getAllBreakpoints(), defaultBreakpoint); + Set> defaultBreakpoints = myBreakpointManager.getDefaultBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE); + assertSameElements(getAllBreakpoints(), defaultBreakpoints); XLineBreakpoint lineBreakpoint = addLineBreakpoint(myBreakpointManager, "url", 239, new MyBreakpointProperties("123")); XBreakpoint breakpoint = addBreakpoint(myBreakpointManager, new MyBreakpointProperties("abc")); - assertSameElements(getAllBreakpoints(), breakpoint, lineBreakpoint, defaultBreakpoint); + assertSameElements(getAllBreakpoints(), breakpoint, lineBreakpoint, defaultBreakpoints); assertSame(lineBreakpoint, assertOneElement(myBreakpointManager.getBreakpoints(MY_LINE_BREAKPOINT_TYPE))); - assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), breakpoint, defaultBreakpoint); + assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), breakpoint, defaultBreakpoints); removeBreakPoint(myBreakpointManager, lineBreakpoint); - assertSameElements(getAllBreakpoints(), breakpoint, defaultBreakpoint); + assertSameElements(getAllBreakpoints(), breakpoint, defaultBreakpoints); assertTrue(myBreakpointManager.getBreakpoints(MY_LINE_BREAKPOINT_TYPE).isEmpty()); - assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), breakpoint, defaultBreakpoint); + assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), breakpoint, defaultBreakpoints); removeBreakPoint(myBreakpointManager, breakpoint); - assertSameElements(getAllBreakpoints(), defaultBreakpoint); - assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), defaultBreakpoint); + assertSameElements(getAllBreakpoints(), defaultBreakpoints); + assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), defaultBreakpoints); } public void testSerialize() { diff --git a/platform/xdebugger-testFramework/src/com/intellij/xdebugger/XDebuggerTestUtil.java b/platform/xdebugger-testFramework/src/com/intellij/xdebugger/XDebuggerTestUtil.java index 37ee3683c401..a7f01fc27492 100644 --- a/platform/xdebugger-testFramework/src/com/intellij/xdebugger/XDebuggerTestUtil.java +++ b/platform/xdebugger-testFramework/src/com/intellij/xdebugger/XDebuggerTestUtil.java @@ -553,9 +553,9 @@ public class XDebuggerTestUtil { void setDefaultBreakpointEnabled(@NotNull final Project project, Class> bpTypeClass, boolean enabled) { final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager(); XBreakpointType bpType = XDebuggerUtil.getInstance().findBreakpointType(bpTypeClass); - XBreakpoint bp = breakpointManager.getDefaultBreakpoint(bpType); - if (bp != null) { - bp.setEnabled(enabled); + Set defaultBreakpoints = breakpointManager.getDefaultBreakpoints(bpType); + for (B defaultBreakpoint : defaultBreakpoints) { + defaultBreakpoint.setEnabled(enabled); } }