From d3278187fb379a352b66f2c56265ac43b4e8a548 Mon Sep 17 00:00:00 2001 From: Anatoliy Bazko Date: Wed, 18 Oct 2017 11:46:00 +0000 Subject: [PATCH] CHE-6545: Add condition for breakpoints (#6763) (#6786) --- .../che/ide/api/debug/BreakpointManager.java | 3 + .../che/ide/api/debug/BreakpointRenderer.java | 22 +++- .../che/ide/api/debug/BreakpointStorage.java | 7 ++ .../che/ide/debug/BreakpointManagerImpl.java | 41 +++++-- .../che/ide/debug/BreakpointRendererImpl.java | 77 ++++++++---- .../che/ide/debug/BreakpointResources.java | 3 + .../che/ide/debug/BreakpointStorageImpl.java | 25 ++-- .../org/eclipse/che/ide/debug/Debugger.java | 6 +- .../org/eclipse/che/ide/debug/breakpoint.css | 63 +++++----- .../orion/client/OrionBreakpointRuler.java | 1 + .../orion/client/orion-codenvy-theme.css | 4 +- .../eclipse/che/ide/ui/list/SimpleList.java | 40 +++++-- .../debugger/ide/DebuggerExtension.java | 15 ++- .../ide/DebuggerLocalizationConstant.java | 20 ++++ .../debugger/ide/debug/AbstractDebugger.java | 11 +- .../debugger/ide/debug/DebuggerPresenter.java | 14 ++- .../debugger/ide/debug/DebuggerView.java | 3 + .../debugger/ide/debug/DebuggerViewImpl.java | 8 +- .../breakpoint/BreakpointActionGroup.java | 30 +++++ .../BreakpointConfigurationAction.java | 57 +++++++++ .../BreakpointConfigurationPresenter.java | 53 +++++++++ .../BreakpointConfigurationView.java | 36 ++++++ .../BreakpointConfigurationViewImpl.java | 101 ++++++++++++++++ .../BreakpointConfigurationViewImpl.ui.xml | 36 ++++++ .../breakpoint/BreakpointContextMenu.java | 53 +++++++++ .../BreakpointContextMenuFactory.java | 29 +++++ .../ide/inject/DebuggerGinModule.java | 6 + .../DebuggerLocalizationConstant.properties | 8 ++ .../ide/debug/DebuggerPresenterTest.java | 5 +- .../debugger/ide/debug/DebuggerTest.java | 7 +- .../che/plugin/gdb/ide/GdbDebugger.java | 5 +- .../jdb/server/BreakpointConditionTest.java | 101 ++++++++++++++++ .../test/resources/JavaDebuggerTestsSuite.xml | 1 + .../src/test/resources/docker/assembly.xml | 4 + .../src/test/resources/docker/entrypoint.sh | 2 + .../eclipse/BreakpointsByConditionTest.java | 22 ++++ .../che/selenium/core/SeleniumWebDriver.java | 4 + .../selenium/pageobject/CodenvyEditor.java | 23 ++-- .../selenium/pageobject/debug/DebugPanel.java | 110 ++++++++++++----- .../debugger/ConditionalBreakpointsTest.java | 111 ++++++++++++++++++ .../hello-world/src/HelloWorld.java | 18 +++ .../src/test/resources/suites/CheSuite.xml | 1 + .../api/debug/shared/model/Breakpoint.java | 2 + .../shared/model/impl/BreakpointImpl.java | 9 +- 44 files changed, 1039 insertions(+), 158 deletions(-) create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointActionGroup.java create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationAction.java create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationPresenter.java create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationView.java create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.java create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.ui.xml create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenu.java create mode 100644 plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenuFactory.java create mode 100644 plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/BreakpointConditionTest.java create mode 100644 plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/workspace/test/src/org/eclipse/BreakpointsByConditionTest.java create mode 100644 selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/debugger/ConditionalBreakpointsTest.java create mode 100644 selenium/che-selenium-test/src/test/resources/projects/plugins/DebuggerPlugin/hello-world/src/HelloWorld.java diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointManager.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointManager.java index ba5d0b55cd..38bf05d196 100644 --- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointManager.java +++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointManager.java @@ -28,4 +28,7 @@ public interface BreakpointManager extends BreakpointManagerObservable { /** Removes all breakpoints. */ void deleteAllBreakpoints(); + + /** Updates the given breakpoint. */ + void update(Breakpoint breakpoint); } diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointRenderer.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointRenderer.java index cdf68c4eb0..0bdfd07995 100644 --- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointRenderer.java +++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointRenderer.java @@ -10,20 +10,21 @@ */ package org.eclipse.che.ide.api.debug; +import org.eclipse.che.api.debug.shared.model.Breakpoint; import org.eclipse.che.ide.api.resources.VirtualFile; /** Component that handles breakpoints display. */ public interface BreakpointRenderer { /** - * Add a breakpoint mark in the gutter on the given line. + * Adds inactive breakpoint mark in the given line. * * @param lineNumber the line where the breakpoint is set */ void addBreakpointMark(int lineNumber); /** - * Add a breakpoint mark in the gutter on the given line. + * Adds inactive breakpoint mark in the given line. * * @param lineNumber the line where the breakpoint is set * @param action to line numbering changes @@ -31,8 +32,18 @@ public interface BreakpointRenderer { void addBreakpointMark(int lineNumber, LineChangeAction action); /** - * Removes the breakpoint mark in the gutter on the given line.
- * Does nothing if there is no breakpoint on this line. + * Adds a breakpoint mark of the given breakpoint. If the mark exists then it will be changed + * depending on {@code active} state and {@link Breakpoint#getCondition()}. + * + * @param breakpoint the given breakpoint + * @param active indicates if breakpoint is active or isn't + * @param action to line numbering changes + */ + default void setBreakpointMark(Breakpoint breakpoint, boolean active, LineChangeAction action) {} + + /** + * Removes the breakpoint mark in the gutter on the given line. Does nothing if there is no + * breakpoint on this line. * * @param lineNumber the line where the breakpoint is set */ @@ -42,8 +53,7 @@ public interface BreakpointRenderer { void clearBreakpointMarks(); /** - * Changes appearance of the breakpoint on the line to active/inactive.
- * Does nothing if there is no breakpoint of this line. + * Adds {@code active} breakpoint mark in the given line. * * @param lineNumber the line where the breakpoint is set */ diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointStorage.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointStorage.java index 98129298d6..edc9dc8325 100644 --- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointStorage.java +++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/debug/BreakpointStorage.java @@ -49,6 +49,13 @@ public interface BreakpointStorage { */ void deleteAll(List breakpoints); + /** + * Updates breakpoint. + * + * @param breakpoint + */ + void update(Breakpoint breakpoint); + /** Clears storage. */ void clear(); diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointManagerImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointManagerImpl.java index d73ef13e2a..b36437f195 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointManagerImpl.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointManagerImpl.java @@ -134,7 +134,7 @@ public class BreakpointManagerImpl Debugger debugger = debuggerManager.getActiveDebugger(); if (debugger != null) { - debugger.deleteBreakpoint(activeFile, breakpoint); + debugger.deleteBreakpoint(breakpoint); } } @@ -147,8 +147,7 @@ public class BreakpointManagerImpl final BreakpointRenderer renderer = getBreakpointRendererForFile(file.getLocation().toString()); if (renderer != null) { - renderer.addBreakpointMark( - breakpoint.getLocation().getLineNumber() - 1, BreakpointManagerImpl.this::onLineChange); + renderer.setBreakpointMark(breakpoint, false, BreakpointManagerImpl.this::onLineChange); } for (BreakpointManagerObserver observer : observers) { @@ -157,7 +156,7 @@ public class BreakpointManagerImpl Debugger debugger = debuggerManager.getActiveDebugger(); if (debugger != null) { - debugger.addBreakpoint(file, breakpoint); + debugger.addBreakpoint(breakpoint); } } @@ -218,6 +217,23 @@ public class BreakpointManagerImpl } } + @Override + public void update(Breakpoint breakpoint) { + breakpointStorage.update(breakpoint); + + BreakpointRenderer renderer = + getBreakpointRendererForFile(breakpoint.getLocation().getTarget()); + if (renderer != null) { + renderer.setBreakpointMark(breakpoint, false, BreakpointManagerImpl.this::onLineChange); + } + + Debugger debugger = debuggerManager.getActiveDebugger(); + if (debugger != null) { + debugger.deleteBreakpoint(breakpoint); + debugger.addBreakpoint(breakpoint); + } + } + private void deleteBreakpoints(String parentPath) { List breakpoints2delete = breakpointStorage @@ -417,9 +433,8 @@ public class BreakpointManagerImpl .getByPath(filePath) .forEach( breakpoint -> - renderer.addBreakpointMark( - breakpoint.getLocation().getLineNumber() - 1, - BreakpointManagerImpl.this::onLineChange)); + renderer.setBreakpointMark( + breakpoint, false, BreakpointManagerImpl.this::onLineChange)); Debugger debugger = debuggerManager.getActiveDebugger(); if (debugger != null) { @@ -428,8 +443,10 @@ public class BreakpointManagerImpl .then( breakpoints -> { for (Breakpoint breakpoint : breakpoints) { - renderer.setBreakpointActive( - breakpoint.getLocation().getLineNumber() - 1, true); + if (breakpoint.getLocation().getTarget().equals(filePath)) { + renderer.setBreakpointMark( + breakpoint, true, BreakpointManagerImpl.this::onLineChange); + } } }); } @@ -457,7 +474,8 @@ public class BreakpointManagerImpl BreakpointRenderer renderer = getBreakpointRendererForFile(breakpoint.getLocation().getTarget()); if (renderer != null) { - renderer.setBreakpointActive(breakpoint.getLocation().getLineNumber() - 1, false); + renderer.setBreakpointMark( + breakpoint, false, BreakpointManagerImpl.this::onLineChange); } }); @@ -476,7 +494,8 @@ public class BreakpointManagerImpl BreakpointRenderer renderer = getBreakpointRendererForFile(breakpoint.getLocation().getTarget()); if (renderer != null) { - renderer.setBreakpointActive(breakpoint.getLocation().getLineNumber() - 1, true); + renderer.setBreakpointMark( + breakpoint, true, BreakpointManagerImpl.this::onLineChange); } }); } diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointRendererImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointRendererImpl.java index d5ffb7172a..5be44c86be 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointRendererImpl.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointRendererImpl.java @@ -12,13 +12,14 @@ package org.eclipse.che.ide.debug; import static org.eclipse.che.ide.api.editor.gutter.Gutters.BREAKPOINTS_GUTTER; +import com.google.common.base.Strings; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; import elemental.dom.Element; +import org.eclipse.che.api.debug.shared.model.Breakpoint; import org.eclipse.che.ide.api.debug.BreakpointRenderer; import org.eclipse.che.ide.api.editor.document.Document; import org.eclipse.che.ide.api.editor.gutter.Gutter; -import org.eclipse.che.ide.api.editor.gutter.Gutter.LineNumberingChangeCallback; import org.eclipse.che.ide.api.editor.texteditor.EditorResources; import org.eclipse.che.ide.api.editor.texteditor.LineStyler; import org.eclipse.che.ide.util.dom.Elements; @@ -42,7 +43,9 @@ public class BreakpointRendererImpl implements BreakpointRenderer { private Document document; private Element activeBreakpointMark; + private Element activeConditionBreakpointMark; private Element inactiveBreakpointMark; + private Element inactiveConditionBreakpointMark; @AssistedInject public BreakpointRendererImpl( @@ -63,26 +66,57 @@ public class BreakpointRendererImpl implements BreakpointRenderer { } @Override - public void addBreakpointMark(final int lineNumber) { + public void addBreakpointMark(int lineNumber) { + addBreakpointMark(lineNumber, (file, firstLine, linesAdded, linesRemoved) -> {}); + } + + @Override + public void addBreakpointMark(int lineNumber, LineChangeAction action) { if (hasGutter != null) { - this.hasGutter.addGutterItem(lineNumber, BREAKPOINTS_GUTTER, inactiveBreakpointMark); + Element newElement = inactiveBreakpointMark; + + Element existedElement = hasGutter.getGutterItem(lineNumber, BREAKPOINTS_GUTTER); + if (existedElement != null) { + hasGutter.setGutterItem(lineNumber, BREAKPOINTS_GUTTER, newElement); + } else { + hasGutter.addGutterItem( + lineNumber, + BREAKPOINTS_GUTTER, + newElement, + (fromLine, linesRemoved, linesAdded) -> + action.onLineChange(document.getFile(), fromLine, linesAdded, linesRemoved)); + } } } @Override - public void addBreakpointMark(final int lineNumber, final LineChangeAction action) { + public void setBreakpointMark( + final Breakpoint breakpoint, final boolean active, final LineChangeAction action) { + if (hasGutter != null) { - this.hasGutter.addGutterItem( - lineNumber, - BREAKPOINTS_GUTTER, - inactiveBreakpointMark, - new LineNumberingChangeCallback() { - @Override - public void onLineNumberingChange( - final int fromLine, final int linesRemoved, final int linesAdded) { - action.onLineChange(document.getFile(), fromLine, linesAdded, linesRemoved); - } - }); + int lineNumber = breakpoint.getLocation().getLineNumber() - 1; + boolean hasCondition = !Strings.isNullOrEmpty(breakpoint.getCondition()); + + Element newElement = + active + ? (hasCondition ? activeConditionBreakpointMark : activeBreakpointMark) + : (hasCondition ? inactiveConditionBreakpointMark : inactiveBreakpointMark); + if (hasCondition) { + newElement.setTitle("Condition: " + breakpoint.getCondition()); + } + + Element existedElement = hasGutter.getGutterItem(lineNumber, BREAKPOINTS_GUTTER); + + if (existedElement != null) { + hasGutter.setGutterItem(lineNumber, BREAKPOINTS_GUTTER, newElement); + } else { + hasGutter.addGutterItem( + lineNumber, + BREAKPOINTS_GUTTER, + newElement, + (fromLine, linesRemoved, linesAdded) -> + action.onLineChange(document.getFile(), fromLine, linesAdded, linesRemoved)); + } } } @@ -101,12 +135,11 @@ public class BreakpointRendererImpl implements BreakpointRenderer { } @Override - public void setBreakpointActive(final int lineNumber, final boolean active) { + public void setBreakpointActive(int lineNumber, boolean active) { if (hasGutter != null) { - final Element mark = this.hasGutter.getGutterItem(lineNumber, BREAKPOINTS_GUTTER); - if (mark != null) { - Element element = active ? activeBreakpointMark : inactiveBreakpointMark; - this.hasGutter.setGutterItem(lineNumber, BREAKPOINTS_GUTTER, element); + Element existedElement = hasGutter.getGutterItem(lineNumber, BREAKPOINTS_GUTTER); + if (existedElement != null) { + hasGutter.setGutterItem(lineNumber, BREAKPOINTS_GUTTER, activeBreakpointMark); } } } @@ -123,7 +156,11 @@ public class BreakpointRendererImpl implements BreakpointRenderer { private void initBreakpointMarks() { BreakpointResources.Css css = breakpointResources.getCss(); activeBreakpointMark = Elements.createDivElement(css.breakpoint(), css.active()); + activeConditionBreakpointMark = + Elements.createDivElement(css.breakpoint(), css.active(), css.condition()); inactiveBreakpointMark = Elements.createDivElement(css.breakpoint(), css.inactive()); + inactiveConditionBreakpointMark = + Elements.createDivElement(css.breakpoint(), css.inactive(), css.condition()); } @Override diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointResources.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointResources.java index 4c77194dc2..4fde5c3384 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointResources.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointResources.java @@ -27,6 +27,9 @@ public interface BreakpointResources extends ClientBundle { /** Returns the CSS class name for inactive breakpoint mark */ String inactive(); + /** Returns the CSS class name for condition breakpoint mark */ + String condition(); + String breakpoint(); } } diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointStorageImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointStorageImpl.java index 16602caf5c..aeb7ea835b 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointStorageImpl.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/BreakpointStorageImpl.java @@ -84,25 +84,31 @@ public class BreakpointStorageImpl implements BreakpointStorage { @Override public void delete(final Breakpoint breakpoint) { - breakpoints.removeIf( - b -> - b.getLocation().getLineNumber() == breakpoint.getLocation().getLineNumber() - && b.getLocation().getTarget().equals(breakpoint.getLocation().getTarget())); + breakpoints.removeIf(b -> isSameBreakpointLocation(breakpoint, b)); preserve(); } @Override public void deleteAll(final List breakpoints) { for (Breakpoint breakpoint : breakpoints) { - breakpoints.removeIf( - b -> - b.getLocation().getLineNumber() == breakpoint.getLocation().getLineNumber() - && b.getLocation().getTarget().equals(breakpoint.getLocation().getTarget())); + breakpoints.removeIf(b -> isSameBreakpointLocation(breakpoint, b)); } preserve(); } + @Override + public void update(Breakpoint breakpoint) { + breakpoints.removeIf(b -> isSameBreakpointLocation(breakpoint, b)); + breakpoints.add(breakpoint); + preserve(); + } + + private boolean isSameBreakpointLocation(Breakpoint b1, Breakpoint b2) { + return b2.getLocation().getLineNumber() == b1.getLocation().getLineNumber() + && b2.getLocation().getTarget().equals(b1.getLocation().getTarget()); + } + @Override public void clear() { breakpoints.clear(); @@ -189,7 +195,8 @@ public class BreakpointStorageImpl implements BreakpointStorage { .withTarget(location.getTarget()) .withLineNumber(location.getLineNumber()) .withExternalResourceId(location.getExternalResourceId()) - .withExternalResource(location.isExternalResource()); + .withExternalResource(location.isExternalResource()) + .withResourceProjectPath(location.getResourceProjectPath()); return dtoFactory .createDto(BreakpointDto.class) diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/Debugger.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/Debugger.java index 71c75f24f3..1891bab3e7 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/Debugger.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/debug/Debugger.java @@ -39,18 +39,16 @@ public interface Debugger extends DebuggerObservable { /** * Adds new breakpoint. * - * @param file the file where breakpoint will be added * @param breakpoint the breakpoint to add */ - void addBreakpoint(VirtualFile file, Breakpoint breakpoint); + void addBreakpoint(Breakpoint breakpoint); /** * Deletes the given breakpoint on server. * - * @param file the file where breakpoint will be removed from * @param breakpoint the breakpoint to delete */ - void deleteBreakpoint(VirtualFile file, Breakpoint breakpoint); + void deleteBreakpoint(Breakpoint breakpoint); /** Deletes all breakpoints. */ void deleteAllBreakpoints(); diff --git a/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/debug/breakpoint.css b/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/debug/breakpoint.css index b90767c646..9797d4250c 100644 --- a/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/debug/breakpoint.css +++ b/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/debug/breakpoint.css @@ -10,53 +10,48 @@ */ @external *; -.breakpoint:before { - content: ""; - position: absolute; - top: 0; - left: -16px; - right: -13px; - height: 15px; -} - -.breakpoint:after { - content: ""; - position: absolute; - right: -19px; - z-index: 1; - width: 0; - height: 0; - border-bottom: 7px solid transparent; - border-top: 8px solid transparent; -} - .breakpoint { position: relative; font-family: "DejaVu Sans Mono", alternativeFontFamily; - font-size: 11px; color: editorGutterLineNumberColor; - line-height: 15px; -} - -.breakpoint.inactive:before { - background-color: rgba(144, 144, 144, 0.4); -} - -.breakpoint.inactive:after { - border-left: 8px solid rgba(144, 144, 144, 0.4); + border-radius: 3px; + line-height: 13px; + font-size: fontSize; + border: 1px solid editorGutterLineNumberBackgroundColor; + box-sizing: border-box; } .breakpoint.inactive { + background-color: rgba(144, 144, 144, 0.4); } -.breakpoint.active:before { - background-color: rgba(78, 171, 255, 0.4); +.breakpoint.inactive.condition { + background-color: rgba(144, 144, 144, 0.4); } -.breakpoint.active:after { - border-left: 8px solid rgba(78, 171, 255, 0.4); +.breakpoint.inactive.condition:after { + content: "?"; + position: absolute; + bottom: 0px; + left: 0px; + line-height: 7px; + font-size: 7px; } .breakpoint.active { + background-color: rgba(78, 171, 255, 0.4); +} + +.breakpoint.active.condition { + background-color: rgba(78, 171, 255, 0.4); +} + +.breakpoint.active.condition:after { + content: "?"; + position: absolute; + bottom: 0px; + left: 0px; + line-height: 7px; + font-size: 7px; } diff --git a/ide/che-core-orion-editor/src/main/java/org/eclipse/che/ide/editor/orion/client/OrionBreakpointRuler.java b/ide/che-core-orion-editor/src/main/java/org/eclipse/che/ide/editor/orion/client/OrionBreakpointRuler.java index 13db3367a4..5a5b84dc81 100644 --- a/ide/che-core-orion-editor/src/main/java/org/eclipse/che/ide/editor/orion/client/OrionBreakpointRuler.java +++ b/ide/che-core-orion-editor/src/main/java/org/eclipse/che/ide/editor/orion/client/OrionBreakpointRuler.java @@ -171,6 +171,7 @@ public class OrionBreakpointRuler implements Gutter { annotation.setType(CHE_BREAKPOINT); annotation.setStart(lineStart); annotation.setEnd(lineStart); + annotation.setTitle(element.getTitle()); return annotation; } diff --git a/ide/che-core-orion-editor/src/main/resources/org/eclipse/che/ide/editor/orion/client/orion-codenvy-theme.css b/ide/che-core-orion-editor/src/main/resources/org/eclipse/che/ide/editor/orion/client/orion-codenvy-theme.css index b334f3ca17..aa860353f3 100644 --- a/ide/che-core-orion-editor/src/main/resources/org/eclipse/che/ide/editor/orion/client/orion-codenvy-theme.css +++ b/ide/che-core-orion-editor/src/main/resources/org/eclipse/che/ide/editor/orion/client/orion-codenvy-theme.css @@ -131,7 +131,9 @@ font-family: "DejaVu Sans Mono", alternativeFontFamily; font-size: 11px; color: editorGutterLineNumberColor; - line-height: 15px; + line-height: 13px; + border: 1px solid editorGutterLineNumberBackgroundColor; + box-sizing: border-box; } .orionCodenvy .rulerZoomWindow { diff --git a/ide/commons-gwt/src/main/java/org/eclipse/che/ide/ui/list/SimpleList.java b/ide/commons-gwt/src/main/java/org/eclipse/che/ide/ui/list/SimpleList.java index a8812bc7b9..920abee265 100644 --- a/ide/commons-gwt/src/main/java/org/eclipse/che/ide/ui/list/SimpleList.java +++ b/ide/commons-gwt/src/main/java/org/eclipse/che/ide/ui/list/SimpleList.java @@ -23,6 +23,7 @@ import com.google.gwt.user.client.ui.Widget; import elemental.dom.Element; import elemental.events.Event; import elemental.events.EventListener; +import elemental.events.MouseEvent; import elemental.js.dom.JsElement; import java.util.ArrayList; import java.util.List; @@ -95,18 +96,11 @@ public class SimpleList extends UiComponent implements IsWid /** Receives events fired on items in the list. */ public interface ListEventDelegate { - void onListItemClicked(Element listItemBase, M itemData); + default void onListItemClicked(Element listItemBase, M itemData) {} - void onListItemDoubleClicked(Element listItemBase, M itemData); - } + default void onListItemDoubleClicked(Element listItemBase, M itemData) {} - /** A {@link ListEventDelegate} which performs no action. */ - public static class NoOpListEventDelegate implements ListEventDelegate { - @Override - public void onListItemClicked(Element listItemBase, M itemData) {} - - @Override - public void onListItemDoubleClicked(Element listItemBase, M itemData) {} + default void onListItemContextMenu(int clientX, int clientY, M itemData) {} } /** Item style selectors for a simple list item. */ @@ -442,6 +436,32 @@ public class SimpleList extends UiComponent implements IsWid } }, false); + + getView() + .addEventListener( + Event.CONTEXTMENU, + new EventListener() { + @Override + public void handleEvent(Event evt) { + MouseEvent mouseEvt = (MouseEvent) evt; + Element listItemElem = + CssUtils.getAncestorOrSelfWithClassName( + (Element) evt.getTarget(), css.listItem()); + + if (listItemElem == null) { + Log.warn( + SimpleList.class, + "Unable to find an ancestor that was a list item for a click on: ", + evt.getTarget()); + return; + } + + ListItem listItem = ListItem.cast(listItemElem); + eventDelegate.onListItemContextMenu( + mouseEvt.getClientX(), mouseEvt.getClientY(), listItem.getData()); + } + }, + false); } public M get(int i) { diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerExtension.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerExtension.java index 522febabab..6bf7e4b6f7 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerExtension.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerExtension.java @@ -39,6 +39,8 @@ import org.eclipse.che.plugin.debugger.ide.actions.StepOverAction; import org.eclipse.che.plugin.debugger.ide.actions.SuspendAction; import org.eclipse.che.plugin.debugger.ide.configuration.DebugConfigurationsGroup; import org.eclipse.che.plugin.debugger.ide.debug.DebuggerPresenter; +import org.eclipse.che.plugin.debugger.ide.debug.breakpoint.BreakpointActionGroup; +import org.eclipse.che.plugin.debugger.ide.debug.breakpoint.BreakpointConfigurationAction; /** * Extension allows debug applications. @@ -64,6 +66,10 @@ public class DebuggerExtension { public static final String EVALUATE_EXPRESSION_ID = "evaluateExpression"; public static final String CHANGE_VARIABLE_VALUE_ID = "changeVariableValue"; public static final String SHOW_HIDE_DEBUGGER_PANEL_ID = "showHideDebuggerPanel"; + public static final String BREAKPOINT_CONFIGURATION_ID = "breakpointSettings"; + public static final String BREAKPOINT_CONTEXT_MENU = "breakpointContextMenu"; + + public static final String BREAKPOINT = "breakpoint"; @Inject public DebuggerExtension( @@ -82,9 +88,11 @@ public class DebuggerExtension { ChangeVariableValueAction changeVariableValueAction, ShowHideDebuggerPanelAction showHideDebuggerPanelAction, EditConfigurationsAction editConfigurationsAction, + BreakpointConfigurationAction breakpointConfigurationAction, DebugConfigurationsGroup configurationsGroup, DebuggerPresenter debuggerPresenter, - KeyBindingAgent keyBinding) { + KeyBindingAgent keyBinding, + BreakpointActionGroup breakpointActionGroup) { debuggerResources.getCss().ensureInjected(); final DefaultActionGroup runMenu = (DefaultActionGroup) actionManager.getAction(GROUP_RUN); @@ -101,6 +109,7 @@ public class DebuggerExtension { actionManager.registerAction(EVALUATE_EXPRESSION_ID, evaluateExpressionAction); actionManager.registerAction(CHANGE_VARIABLE_VALUE_ID, changeVariableValueAction); actionManager.registerAction(SHOW_HIDE_DEBUGGER_PANEL_ID, showHideDebuggerPanelAction); + actionManager.registerAction(BREAKPOINT_CONFIGURATION_ID, breakpointConfigurationAction); // create group for selecting (changing) debug configurations final DefaultActionGroup debugActionGroup = @@ -109,6 +118,10 @@ public class DebuggerExtension { debugActionGroup.addSeparator(); debugActionGroup.add(configurationsGroup); + // breakpoint context menu + breakpointActionGroup.add(breakpointConfigurationAction); + actionManager.registerAction(BREAKPOINT_CONTEXT_MENU, breakpointActionGroup); + // add actions in main menu runMenu.addSeparator(); runMenu.add(debugActionGroup, LAST); diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.java index d721f14487..8eaa85ba0f 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.java @@ -66,6 +66,9 @@ public interface DebuggerLocalizationConstant extends com.google.gwt.i18n.client @Key("showHideDebuggerPanel") String showHideDebuggerPanel(); + @Key("breakpointConfiguration") + String breakpointConfiguration(); + /* actions descriptions */ @Key("editDebugConfigurationsActionDescription") String editDebugConfigurationsActionDescription(); @@ -103,6 +106,9 @@ public interface DebuggerLocalizationConstant extends com.google.gwt.i18n.client @Key("showHideDebuggerPanelDescription") String showHideDebuggerPanelDescription(); + @Key("breakpointConfigurationDescription") + String breakpointConfigurationDescription(); + /* messages */ @Key("debugger.connecting.title") String debuggerConnectingTitle(String address); @@ -128,6 +134,10 @@ public interface DebuggerLocalizationConstant extends com.google.gwt.i18n.client @Key("failed.to.get.variable.value.title") String failedToGetVariableValueTitle(); + /* ChangeValueView */ + @Key("view.breakpoint.configuration.title") + String breakpointConfigurationTitle(); + /* ChangeValueView */ @Key("view.changeValue.title") String changeValueViewTitle(); @@ -202,4 +212,14 @@ public interface DebuggerLocalizationConstant extends com.google.gwt.i18n.client @Key("debugger.frames.title") String debuggerFramesTitle(); + + /* Breakpoint Configuration */ + @Key("view.breakpointConfiguration.condition") + String viewBreakpointConfigurationCondition(); + + @Key("view.breakpointConfiguration.hitCount") + String viewBreakpointConfigurationHitCount(); + + @Key("view.breakpointConfiguration.applyButton") + String viewBreakpointConfigurationApplyButton(); } diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/AbstractDebugger.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/AbstractDebugger.java index 47a2cd78f4..839ab6ca23 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/AbstractDebugger.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/AbstractDebugger.java @@ -352,7 +352,7 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { } @Override - public void addBreakpoint(final VirtualFile file, final Breakpoint breakpoint) { + public void addBreakpoint(final Breakpoint breakpoint) { if (isConnected()) { Location location = breakpoint.getLocation(); @@ -362,7 +362,11 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { locationDto.setResourceProjectPath(location.getResourceProjectPath()); BreakpointDto breakpointDto = - dtoFactory.createDto(BreakpointDto.class).withLocation(locationDto).withEnabled(true); + dtoFactory + .createDto(BreakpointDto.class) + .withLocation(locationDto) + .withEnabled(true) + .withCondition(breakpoint.getCondition()); Promise promise = service.addBreakpoint(debugSessionDto.getId(), breakpointDto); promise @@ -380,7 +384,7 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { } @Override - public void deleteBreakpoint(final VirtualFile file, final Breakpoint breakpoint) { + public void deleteBreakpoint(final Breakpoint breakpoint) { if (!isConnected()) { return; } @@ -489,6 +493,7 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { BreakpointDto breakpointDto = dtoFactory.createDto(BreakpointDto.class); breakpointDto.setLocation(locationDto); breakpointDto.setEnabled(true); + breakpointDto.setCondition(breakpoint.getCondition()); breakpoints.add(breakpointDto); } diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenter.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenter.java index a5c2b7db6b..913bf3d9df 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenter.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenter.java @@ -17,6 +17,7 @@ import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAI import static org.eclipse.che.ide.api.notification.StatusNotification.Status.PROGRESS; import static org.eclipse.che.ide.api.notification.StatusNotification.Status.SUCCESS; +import com.google.gwt.core.client.Scheduler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.gwt.user.client.ui.IsWidget; @@ -51,6 +52,7 @@ import org.eclipse.che.ide.ui.toolbar.ToolbarPresenter; import org.eclipse.che.ide.util.loging.Log; import org.eclipse.che.plugin.debugger.ide.DebuggerLocalizationConstant; import org.eclipse.che.plugin.debugger.ide.DebuggerResources; +import org.eclipse.che.plugin.debugger.ide.debug.breakpoint.BreakpointContextMenuFactory; import org.vectomatic.dom.svg.ui.SVGResource; /** @@ -77,6 +79,7 @@ public class DebuggerPresenter extends BasePresenter private final DebuggerManager debuggerManager; private final WorkspaceAgent workspaceAgent; private final DebuggerResourceHandlerFactory resourceHandlerManager; + private final BreakpointContextMenuFactory breakpointContextMenuFactory; private List variables; private List threadDump; @@ -93,7 +96,8 @@ public class DebuggerPresenter extends BasePresenter final @DebuggerToolbar ToolbarPresenter debuggerToolbar, final DebuggerManager debuggerManager, final WorkspaceAgent workspaceAgent, - final DebuggerResourceHandlerFactory resourceHandlerManager) { + final DebuggerResourceHandlerFactory resourceHandlerManager, + final BreakpointContextMenuFactory breakpointContextMenuFactory) { this.view = view; this.debuggerResources = debuggerResources; this.debuggerToolbar = debuggerToolbar; @@ -104,6 +108,7 @@ public class DebuggerPresenter extends BasePresenter this.view.setTitle(TITLE); this.constant = constant; this.breakpointManager = breakpointManager; + this.breakpointContextMenuFactory = breakpointContextMenuFactory; this.notificationManager = notificationManager; this.addRule(ProjectPerspective.PROJECT_PERSPECTIVE_ID); @@ -417,4 +422,11 @@ public class DebuggerPresenter extends BasePresenter public boolean isDebuggerPanelOpened() { return partStack.getActivePart() == this; } + + @Override + public void onBreakpointContextMenu(int clientX, int clientY, Breakpoint breakpoint) { + Scheduler.get() + .scheduleDeferred( + () -> breakpointContextMenuFactory.newContextMenu(breakpoint).show(clientX, clientY)); + } } diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerView.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerView.java index 953ef8053f..c586ace844 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerView.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerView.java @@ -50,6 +50,9 @@ public interface DebuggerView extends View { * @param frameIndex the frame index inside a thread */ void onSelectedFrame(int frameIndex); + + /** Breakpoint context menu is invoked. */ + void onBreakpointContextMenu(int clientX, int clientY, Breakpoint breakpoint); } /** diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerViewImpl.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerViewImpl.java index 9ab8262b25..80609c1bd1 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerViewImpl.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerViewImpl.java @@ -158,7 +158,6 @@ public class DebuggerViewImpl extends BaseView @Override public void onKeyboard(@NotNull KeyboardEvent event) {} }); - this.variablesPanel.add(variables); } @@ -294,7 +293,10 @@ public class DebuggerViewImpl extends BaseView breakpoints.getSelectionModel().setSelectedItem(itemData); } - public void onListItemDoubleClicked(Element listItemBase, Breakpoint itemData) {} + @Override + public void onListItemContextMenu(int clientX, int clientY, Breakpoint itemData) { + delegate.onBreakpointContextMenu(clientX, clientY, itemData); + } }; return SimpleList.create( @@ -314,8 +316,6 @@ public class DebuggerViewImpl extends BaseView frames.getSelectionModel().setSelectedItem(itemData); delegate.onSelectedFrame(frames.getSelectionModel().getSelectedIndex()); } - - public void onListItemDoubleClicked(Element listItemBase, StackFrameDump itemData) {} }; return SimpleList.create( diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointActionGroup.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointActionGroup.java new file mode 100644 index 0000000000..b88c1dcedc --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointActionGroup.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.debugger.ide.debug.breakpoint; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.eclipse.che.ide.api.action.ActionManager; +import org.eclipse.che.ide.api.action.DefaultActionGroup; + +/** + * Groups actions that can be applied upon a breakpoint. + * + * @author Anatolii Bazko + */ +@Singleton +public class BreakpointActionGroup extends DefaultActionGroup { + + @Inject + public BreakpointActionGroup(ActionManager actionManager) { + super("breakpointConfiguration", false, actionManager); + } +} diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationAction.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationAction.java new file mode 100644 index 0000000000..8495d0a9c7 --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationAction.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.debugger.ide.debug.breakpoint; + +import static org.eclipse.che.ide.workspace.perspectives.project.ProjectPerspective.PROJECT_PERSPECTIVE_ID; +import static org.eclipse.che.plugin.debugger.ide.DebuggerExtension.BREAKPOINT; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.util.Collections; +import org.eclipse.che.api.debug.shared.model.Breakpoint; +import org.eclipse.che.ide.api.action.AbstractPerspectiveAction; +import org.eclipse.che.ide.api.action.ActionEvent; +import org.eclipse.che.plugin.debugger.ide.DebuggerLocalizationConstant; + +/** + * Actions allows to configure breakpoint. + * + * @author Mykola Morhun + */ +@Singleton +public class BreakpointConfigurationAction extends AbstractPerspectiveAction { + + private final BreakpointConfigurationPresenter breakpointConfigurationPresenter; + + @Inject + public BreakpointConfigurationAction( + DebuggerLocalizationConstant locale, + BreakpointConfigurationPresenter breakpointConfigurationPresenter) { + super( + Collections.singletonList(PROJECT_PERSPECTIVE_ID), + locale.breakpointConfiguration(), + locale.breakpointConfiguration(), + null, + null); + this.breakpointConfigurationPresenter = breakpointConfigurationPresenter; + } + + @Override + public void actionPerformed(ActionEvent e) { + Breakpoint breakpoint = (Breakpoint) getTemplatePresentation().getClientProperty(BREAKPOINT); + breakpointConfigurationPresenter.showDialog(breakpoint); + } + + @Override + public void updateInPerspective(ActionEvent event) { + event.getPresentation().setEnabled(true); + } +} diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationPresenter.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationPresenter.java new file mode 100644 index 0000000000..df730bac7a --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationPresenter.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.debugger.ide.debug.breakpoint; + +import com.google.common.base.Strings; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.eclipse.che.api.debug.shared.model.Breakpoint; +import org.eclipse.che.ide.api.debug.BreakpointManager; + +/** @author Anatolii Bazko */ +@Singleton +public class BreakpointConfigurationPresenter + implements BreakpointConfigurationView.ActionDelegate { + + private final BreakpointConfigurationView view; + private final BreakpointManager breakpointManager; + + private Breakpoint breakpoint; + + @Inject + public BreakpointConfigurationPresenter( + BreakpointConfigurationView view, BreakpointManager breakpointManager) { + this.view = view; + this.breakpointManager = breakpointManager; + this.view.setDelegate(this); + } + + public void showDialog(Breakpoint breakpoint) { + this.breakpoint = breakpoint; + view.setBreakpoint(breakpoint); + view.showDialog(); + } + + @Override + public void onApplyClicked() { + view.close(); + + breakpoint.setCondition( + Strings.isNullOrEmpty(view.getBreakpointCondition()) + ? null + : view.getBreakpointCondition()); + breakpointManager.update(breakpoint); + } +} diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationView.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationView.java new file mode 100644 index 0000000000..7a4f0a0faa --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationView.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.debugger.ide.debug.breakpoint; + +import org.eclipse.che.api.debug.shared.model.Breakpoint; +import org.eclipse.che.ide.api.mvp.View; + +/** + * Provides methods which allow to change view representation of breakpoint configuration window. + * + * @author Anatolii Bazko + */ +public interface BreakpointConfigurationView + extends View { + + interface ActionDelegate { + /** Apply changes. */ + void onApplyClicked(); + } + + void showDialog(); + + void close(); + + void setBreakpoint(Breakpoint breakpoint); + + String getBreakpointCondition(); +} diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.java new file mode 100644 index 0000000000..a0dbe793b7 --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.debugger.ide.debug.breakpoint; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.TextArea; +import com.google.gwt.user.client.ui.UIObject; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.eclipse.che.api.debug.shared.model.Breakpoint; +import org.eclipse.che.api.debug.shared.model.Location; +import org.eclipse.che.ide.resource.Path; +import org.eclipse.che.ide.ui.window.Window; +import org.eclipse.che.plugin.debugger.ide.DebuggerLocalizationConstant; + +/** @author Anatolii Bazko */ +@Singleton +public class BreakpointConfigurationViewImpl extends Window implements BreakpointConfigurationView { + + interface BreakpointConfigurationViewImplUiBinder + extends UiBinder {} + + private static BreakpointConfigurationViewImpl.BreakpointConfigurationViewImplUiBinder uiBinder = + GWT.create(BreakpointConfigurationViewImpl.BreakpointConfigurationViewImplUiBinder.class); + + @UiField Label breakpointLocation; + @UiField TextArea breakpointCondition; + + private final Button applyButton; + + private ActionDelegate delegate; + + @Inject + public BreakpointConfigurationViewImpl(DebuggerLocalizationConstant locale) { + Widget widget = uiBinder.createAndBindUi(this); + + this.setWidget(widget); + this.setTitle(locale.breakpointConfigurationTitle()); + + applyButton = + createButton( + locale.viewBreakpointConfigurationApplyButton(), + UIObject.DEBUG_ID_PREFIX + "apply-btn", + clickEvent -> delegate.onApplyClicked()); + + ensureDebugId("breakpoint-configuration-window"); + addButtonToFooter(applyButton); + } + + @Override + public void setDelegate(ActionDelegate delegate) { + this.delegate = delegate; + } + + @Override + public void showDialog() { + this.show(); + breakpointCondition.setFocus(true); + } + + @Override + public void close() { + this.hide(); + } + + @Override + public void setBreakpoint(Breakpoint breakpoint) { + Location location = breakpoint.getLocation(); + + StringBuilder labelText = new StringBuilder(); + labelText + .append(Path.valueOf(location.getTarget()).lastSegment()) + .append(":") + .append(location.getLineNumber()); + breakpointLocation.setText(labelText.toString()); + + if (breakpoint.getCondition() != null) { + breakpointCondition.setText(breakpoint.getCondition()); + } else { + breakpointCondition.setText(""); + } + } + + @Override + public String getBreakpointCondition() { + return breakpointCondition.getText(); + } +} diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.ui.xml b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.ui.xml new file mode 100644 index 0000000000..374f989a29 --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointConfigurationViewImpl.ui.xml @@ -0,0 +1,36 @@ + + + + + + + .location { + font-weight: bold; + } + + + + + + + + + + + + + + + diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenu.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenu.java new file mode 100644 index 0000000000..3ddf20ad19 --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenu.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.debugger.ide.debug.breakpoint; + +import static org.eclipse.che.plugin.debugger.ide.DebuggerExtension.BREAKPOINT; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.assistedinject.Assisted; +import org.eclipse.che.api.debug.shared.model.Breakpoint; +import org.eclipse.che.ide.api.action.Action; +import org.eclipse.che.ide.api.action.ActionManager; +import org.eclipse.che.ide.api.action.Presentation; +import org.eclipse.che.ide.api.keybinding.KeyBindingAgent; +import org.eclipse.che.ide.api.parts.PerspectiveManager; +import org.eclipse.che.ide.menu.ContextMenu; +import org.eclipse.che.plugin.debugger.ide.DebuggerExtension; + +/** @author Anatolii Bazko */ +public class BreakpointContextMenu extends ContextMenu { + + private final Breakpoint breakpoint; + + @Inject + public BreakpointContextMenu( + @Assisted Breakpoint breakpoint, + ActionManager actionManager, + KeyBindingAgent keyBindingAgent, + Provider managerProvider) { + super(actionManager, keyBindingAgent, managerProvider); + this.breakpoint = breakpoint; + } + + @Override + protected String getGroupMenu() { + return DebuggerExtension.BREAKPOINT_CONTEXT_MENU; + } + + @Override + public void onActionSelected(Action action) { + Presentation presentation = action.getTemplatePresentation(); + presentation.putClientProperty(BREAKPOINT, breakpoint); + super.onActionSelected(action); + } +} diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenuFactory.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenuFactory.java new file mode 100644 index 0000000000..a39abb872c --- /dev/null +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/debug/breakpoint/BreakpointContextMenuFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.debugger.ide.debug.breakpoint; + +import org.eclipse.che.api.debug.shared.model.Breakpoint; + +/** + * Breakpoint context menu factory. + * + * @author Anatolii Bazko + */ +public interface BreakpointContextMenuFactory { + + /** + * Creates new context menu for a given breakpoint. + * + * @param breakpoint the breakpoint + * @return new context menu + */ + BreakpointContextMenu newContextMenu(Breakpoint breakpoint); +} diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/inject/DebuggerGinModule.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/inject/DebuggerGinModule.java index 775b3f030d..f1b0a0e01d 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/inject/DebuggerGinModule.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/plugin/debugger/ide/inject/DebuggerGinModule.java @@ -25,6 +25,9 @@ import org.eclipse.che.plugin.debugger.ide.configuration.EditDebugConfigurations import org.eclipse.che.plugin.debugger.ide.debug.DebuggerToolbar; import org.eclipse.che.plugin.debugger.ide.debug.DebuggerView; import org.eclipse.che.plugin.debugger.ide.debug.DebuggerViewImpl; +import org.eclipse.che.plugin.debugger.ide.debug.breakpoint.BreakpointConfigurationView; +import org.eclipse.che.plugin.debugger.ide.debug.breakpoint.BreakpointConfigurationViewImpl; +import org.eclipse.che.plugin.debugger.ide.debug.breakpoint.BreakpointContextMenuFactory; import org.eclipse.che.plugin.debugger.ide.debug.changevalue.ChangeValueView; import org.eclipse.che.plugin.debugger.ide.debug.changevalue.ChangeValueViewImpl; import org.eclipse.che.plugin.debugger.ide.debug.expression.EvaluateExpressionView; @@ -44,6 +47,7 @@ public class DebuggerGinModule extends AbstractGinModule { bind(DebuggerView.class).to(DebuggerViewImpl.class).in(Singleton.class); bind(EvaluateExpressionView.class).to(EvaluateExpressionViewImpl.class).in(Singleton.class); bind(ChangeValueView.class).to(ChangeValueViewImpl.class).in(Singleton.class); + bind(BreakpointConfigurationView.class).to(BreakpointConfigurationViewImpl.class); bind(EditDebugConfigurationsView.class) .to(EditDebugConfigurationsViewImpl.class) .in(Singleton.class); @@ -60,5 +64,7 @@ public class DebuggerGinModule extends AbstractGinModule { .annotatedWith(DebuggerToolbar.class) .to(ToolbarPresenter.class) .in(Singleton.class); + + install(new GinFactoryModuleBuilder().build(BreakpointContextMenuFactory.class)); } } diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.properties b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.properties index 56091b9458..fc58fe6c2e 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.properties +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/plugin/debugger/ide/DebuggerLocalizationConstant.properties @@ -30,6 +30,7 @@ deleteAllBreakpoints = Remove All Breakpoints changeVariableValue = Change Value evaluateExpression = Evaluate Expression showHideDebuggerPanel=Show/Hide Debugger Panel +breakpointConfiguration=Configuration ##### Descriptions ##### editDebugConfigurationsActionDescription = Edit debug configurations @@ -44,6 +45,7 @@ deleteAllBreakpointsDescription = Remove All Breakpoints changeVariableValueDescription = Change Value evaluateExpressionDescription = Evaluate Expression showHideDebuggerPanelDescription=Show/Hide Debugger Panel +breakpointConfigurationDescription=Breakpoint Configuration ############### Messages ################ debugger.connecting.title = Connecting to {0} @@ -60,6 +62,7 @@ view.changeValue.title = Change variable value view.changeValue.expressionField.title = Enter a new value for {0}: view.changeValue.changeButton.title = Change view.changeValue.cancelButton.title = Cancel +view.breakpoint.configuration.title = Configuration ############### EvaluateExpressionView ################ view.evaluateExpression.title = Evaluate expression @@ -69,6 +72,11 @@ view.evaluateExpression.evaluateButton.title = Evaluate view.evaluateExpression.closeButton.title = Close evaluateExpressionFailed = Error: Failed to evaluate an expression.\r\nReason: {0} +############### BreakpointConfigurationView ################# +view.breakpointConfiguration.condition = Condition: +view.breakpointConfiguration.hitCount = Hit Count: +view.breakpointConfiguration.applyButton = Apply + # EditConfigurations view.editConfigurations.placeholder=Filter view.editConfigurations.title=Debug Configurations diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenterTest.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenterTest.java index fb59c804af..bc2b31e888 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenterTest.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerPresenterTest.java @@ -43,6 +43,7 @@ import org.eclipse.che.ide.ui.toolbar.ToolbarPresenter; import org.eclipse.che.plugin.debugger.ide.BaseTest; import org.eclipse.che.plugin.debugger.ide.DebuggerLocalizationConstant; import org.eclipse.che.plugin.debugger.ide.DebuggerResources; +import org.eclipse.che.plugin.debugger.ide.debug.breakpoint.BreakpointContextMenuFactory; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -74,6 +75,7 @@ public class DebuggerPresenterTest extends BaseTest { @Mock private DebuggerManager debuggerManager; @Mock private WorkspaceAgent workspaceAgent; @Mock private DebuggerResourceHandlerFactory debuggerResourceHandlerFactory; + @Mock private BreakpointContextMenuFactory breakpointContextMenuFactory; @Mock private Debugger debugger; @Mock private MutableVariable selectedVariable; @@ -108,7 +110,8 @@ public class DebuggerPresenterTest extends BaseTest { debuggerToolbar, debuggerManager, workspaceAgent, - debuggerResourceHandlerFactory)); + debuggerResourceHandlerFactory, + breakpointContextMenuFactory)); Mockito.reset(view); when(view.getSelectedThreadId()).thenReturn(THREAD_ID); diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerTest.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerTest.java index c8dc3b8089..231228ad68 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerTest.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/plugin/debugger/ide/debug/DebuggerTest.java @@ -421,8 +421,9 @@ public class DebuggerTest extends BaseTest { when(breakpointDto.getLocation().getLineNumber()).thenReturn(LINE_NUMBER); when(breakpointDto.withLocation(locationDto)).thenReturn(breakpointDto); when(breakpointDto.withEnabled(true)).thenReturn(breakpointDto); + when(breakpointDto.withCondition(any())).thenReturn(breakpointDto); - debugger.addBreakpoint(virtualFile, breakpointDto); + debugger.addBreakpoint(breakpointDto); verify(service).addBreakpoint(SESSION_ID, breakpointDto); verify(promiseVoid).then(operationVoidCaptor.capture()); @@ -440,7 +441,7 @@ public class DebuggerTest extends BaseTest { doReturn(promiseVoid).when(service).deleteBreakpoint(SESSION_ID, locationDto); doReturn(promiseVoid).when(promiseVoid).then((Operation) any()); - debugger.deleteBreakpoint(file, breakpointDto); + debugger.deleteBreakpoint(breakpointDto); verify(promiseVoid).then(operationVoidCaptor.capture()); operationVoidCaptor.getValue().apply(null); @@ -455,7 +456,7 @@ public class DebuggerTest extends BaseTest { @Test public void testDeleteBreakpointWithoutConnection() throws Exception { debugger.setDebugSession(null); - debugger.deleteBreakpoint(file, breakpointDto); + debugger.deleteBreakpoint(breakpointDto); verify(service, never()).deleteBreakpoint(any(), any()); } diff --git a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/plugin/gdb/ide/GdbDebugger.java b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/plugin/gdb/ide/GdbDebugger.java index d838ac97b8..ea0e235451 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/plugin/gdb/ide/GdbDebugger.java +++ b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/plugin/gdb/ide/GdbDebugger.java @@ -26,7 +26,6 @@ import org.eclipse.che.ide.api.app.AppContext; import org.eclipse.che.ide.api.debug.BreakpointManager; import org.eclipse.che.ide.api.debug.DebuggerServiceClient; import org.eclipse.che.ide.api.notification.NotificationManager; -import org.eclipse.che.ide.api.resources.VirtualFile; import org.eclipse.che.ide.debug.DebuggerDescriptor; import org.eclipse.che.ide.debug.DebuggerManager; import org.eclipse.che.ide.dto.DtoFactory; @@ -79,12 +78,12 @@ public class GdbDebugger extends AbstractDebugger { } @Override - public void addBreakpoint(final VirtualFile file, final Breakpoint breakpoint) { + public void addBreakpoint(final Breakpoint breakpoint) { if (isConnected() && !isSuspended()) { notificationManager.notify(locale.messageSuspendToActivateBreakpoints(), FAIL, FLOAT_MODE); } - super.addBreakpoint(file, breakpoint); + super.addBreakpoint(breakpoint); } @Override diff --git a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/BreakpointConditionTest.java b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/BreakpointConditionTest.java new file mode 100644 index 0000000000..fe2bef8658 --- /dev/null +++ b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/BreakpointConditionTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.plugin.jdb.server; + +import static org.eclipse.che.plugin.jdb.server.util.JavaDebuggerUtils.ensureSuspendAtDesiredLocation; +import static org.eclipse.che.plugin.jdb.server.util.JavaDebuggerUtils.startJavaDebugger; +import static org.eclipse.che.plugin.jdb.server.util.JavaDebuggerUtils.terminateVirtualMachineQuietly; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import org.eclipse.che.api.debug.shared.model.Breakpoint; +import org.eclipse.che.api.debug.shared.model.Location; +import org.eclipse.che.api.debug.shared.model.event.BreakpointActivatedEvent; +import org.eclipse.che.api.debug.shared.model.event.DebuggerEvent; +import org.eclipse.che.api.debug.shared.model.event.DisconnectEvent; +import org.eclipse.che.api.debug.shared.model.event.SuspendEvent; +import org.eclipse.che.api.debug.shared.model.impl.BreakpointImpl; +import org.eclipse.che.api.debug.shared.model.impl.LocationImpl; +import org.eclipse.che.api.debug.shared.model.impl.action.ResumeActionImpl; +import org.eclipse.che.plugin.jdb.server.util.ProjectApiUtils; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** @author Anatolii Bazko */ +public class BreakpointConditionTest { + + private JavaDebugger debugger; + private BlockingQueue events; + + @BeforeClass + public void setUp() throws Exception { + ProjectApiUtils.ensure(); + + Location location = + new LocationImpl( + "/test/src/org/eclipse/BreakpointsByConditionTest.java", + 17, + false, + -1, + "/test", + null, + -1); + + events = new ArrayBlockingQueue<>(10); + debugger = startJavaDebugger(new BreakpointImpl(location), events); + + ensureSuspendAtDesiredLocation(location, events); + } + + @AfterClass + public void tearDown() throws Exception { + if (debugger != null) { + terminateVirtualMachineQuietly(debugger); + } + } + + @Test + public void shouldStopByCondition() throws Exception { + Breakpoint breakpoint = + new BreakpointImpl( + new LocationImpl( + "/test/src/org/eclipse/BreakpointsByConditionTest.java", + 19, + false, + -1, + "/test", + null, + -1), + true, + "i==5"); + + debugger.addBreakpoint(breakpoint); + + DebuggerEvent debuggerEvent = events.take(); + assertTrue(debuggerEvent instanceof BreakpointActivatedEvent); + + debugger.resume(new ResumeActionImpl()); + + debuggerEvent = events.take(); + assertTrue(debuggerEvent instanceof SuspendEvent); + + assertEquals("5", debugger.evaluate("i")); + assertEquals("4", debugger.evaluate("k")); + + debugger.resume(new ResumeActionImpl()); + + debuggerEvent = events.take(); + assertTrue(debuggerEvent instanceof DisconnectEvent); + } +} diff --git a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/JavaDebuggerTestsSuite.xml b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/JavaDebuggerTestsSuite.xml index 1c7960410b..de72bcecc2 100644 --- a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/JavaDebuggerTestsSuite.xml +++ b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/JavaDebuggerTestsSuite.xml @@ -16,6 +16,7 @@ + diff --git a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/assembly.xml b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/assembly.xml index 7fa126ff35..79fad20045 100644 --- a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/assembly.xml +++ b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/assembly.xml @@ -37,6 +37,10 @@ ${project.build.testOutputDirectory}/workspace/test/src/org/eclipse/BreakpointsTest.java ./org/eclipse + + ${project.build.testOutputDirectory}/workspace/test/src/org/eclipse/BreakpointsByConditionTest.java + ./org/eclipse + ${project.build.testOutputDirectory}/workspace/test/src/com/HelloWorld.java ./com diff --git a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/entrypoint.sh b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/entrypoint.sh index d380d58bf5..711b9a73a1 100644 --- a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/entrypoint.sh +++ b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/docker/entrypoint.sh @@ -18,10 +18,12 @@ javac -g org/eclipse/GetValueTest1.java javac -g org/eclipse/EvaluateExpressionTest1.java javac -g com/HelloWorld.java javac -g org/eclipse/BreakpointsTest.java +javac -g org/eclipse/BreakpointsByConditionTest.java DEBUG_OPT="-Xdebug -Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=y" java ${DEBUG_OPT} org.eclipse.BreakpointsTest +java ${DEBUG_OPT} org.eclipse.BreakpointsByConditionTest java ${DEBUG_OPT} org.eclipse.ThreadDumpTest1 java ${DEBUG_OPT} org.eclipse.ThreadDumpTest2 java ${DEBUG_OPT} org.eclipse.StackFrameDumpTest1 diff --git a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/workspace/test/src/org/eclipse/BreakpointsByConditionTest.java b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/workspace/test/src/org/eclipse/BreakpointsByConditionTest.java new file mode 100644 index 0000000000..aa6595d893 --- /dev/null +++ b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/resources/workspace/test/src/org/eclipse/BreakpointsByConditionTest.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse; + +/** @author Anatolii Bazko */ +public class BreakpointsByConditionTest { + + public static void main(String[] args) { + int k = 0; + for (int i = 0; i < 10; i++) { + k = i; + } + } +} diff --git a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/SeleniumWebDriver.java b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/SeleniumWebDriver.java index 5fd9923d8d..654048eeb7 100644 --- a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/SeleniumWebDriver.java +++ b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/SeleniumWebDriver.java @@ -316,4 +316,8 @@ public class SeleniumWebDriver new WebDriverWait(this, timeout) .until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("ide-application-iframe"))); } + + public WebDriverWait wait(int timeOutInSeconds) { + return new WebDriverWait(this, timeOutInSeconds); + } } diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java index 5198659a57..1108b81f99 100644 --- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/CodenvyEditor.java @@ -25,7 +25,6 @@ import static org.openqa.selenium.support.ui.ExpectedConditions.textToBePresentI import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOf; import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfAllElementsLocatedBy; import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated; -import static org.testng.Assert.fail; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -194,6 +193,8 @@ public class CodenvyEditor { "//div[@class='breakpoint inactive' and text()='%d']"; public static final String DEBUGGER_BREAK_POINT_ACTIVE = "//div[@class='breakpoint active' and text()='%d']"; + public static final String DEBUGGER_BREAKPOINT_CONDITION = + "//div[@class='breakpoint %s condition' and text()='%d']"; public static final String JAVA_DOC_POPUP = "//div[@class='gwt-PopupPanel']//iframe"; public static final String AUTOCOMPLETE_PROPOSAL_JAVA_DOC_POPUP = "//div//iframe[contains(@src, 'api/java/code-assist/compute/info?')]"; @@ -1190,18 +1191,14 @@ public class CodenvyEditor { By.xpath(String.format(Locators.DEBUGGER_BREAK_POINT_INACTIVE, position)))); } - public void waitBreakpointRemoved(int position) { - try { - waitInactiveBreakpoint(position); - fail("Breakpoint should be removed at " + position); - } catch (Exception e) { - } - - try { - waitActiveBreakpoint(position); - fail("Breakpoint should be removed at " + position); - } catch (Exception e) { - } + public void waitConditionalBreakpoint(int lineNumber, boolean active) { + redrawDriverWait.until( + visibilityOfElementLocated( + By.xpath( + String.format( + Locators.DEBUGGER_BREAKPOINT_CONDITION, + active ? "active" : "inactive", + lineNumber)))); } /** wait while editor will be empty */ diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/debug/DebugPanel.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/debug/DebugPanel.java index 836d22874f..a82164b5a8 100644 --- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/debug/DebugPanel.java +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/pageobject/debug/DebugPanel.java @@ -10,15 +10,20 @@ */ package org.eclipse.che.selenium.pageobject.debug; +import static java.lang.String.format; import static org.eclipse.che.selenium.core.constant.TestTimeoutsConstants.LOAD_PAGE_TIMEOUT_SEC; import static org.eclipse.che.selenium.core.constant.TestTimeoutsConstants.MINIMUM_SEC; import static org.eclipse.che.selenium.core.constant.TestTimeoutsConstants.REDRAW_UI_ELEMENTS_TIMEOUT_SEC; +import static org.openqa.selenium.By.id; +import static org.openqa.selenium.By.xpath; +import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated; import com.google.common.base.Function; import com.google.inject.Inject; import com.google.inject.Singleton; import java.util.List; import org.eclipse.che.selenium.core.SeleniumWebDriver; +import org.eclipse.che.selenium.core.action.ActionsFactory; import org.eclipse.che.selenium.pageobject.CodenvyEditor; import org.eclipse.che.selenium.pageobject.Loader; import org.eclipse.che.selenium.pageobject.intelligent.CommandsExplorer; @@ -41,26 +46,28 @@ public class DebugPanel { private static final Logger LOG = LoggerFactory.getLogger(DebugPanel.class); - @Inject private SeleniumWebDriver seleniumWebDriver; - @Inject private Loader loader; - @Inject private CodenvyEditor editor; - @Inject private CommandsExplorer commandsExplorer; + private SeleniumWebDriver seleniumWebDriver; + private Loader loader; + private CodenvyEditor editor; + private CommandsExplorer commandsExplorer; + private ActionsFactory actionsFactory; @Inject public DebugPanel( SeleniumWebDriver seleniumWebDriver, Loader loader, CodenvyEditor editor, - CommandsExplorer commandsExplorer) { + CommandsExplorer commandsExplorer, + ActionsFactory actionsFactory) { this.seleniumWebDriver = seleniumWebDriver; this.loader = loader; this.editor = editor; this.commandsExplorer = commandsExplorer; + this.actionsFactory = actionsFactory; PageFactory.initElements(seleniumWebDriver, this); } private interface Locators { - String DEBUGGER_BREAKPOINTS_PANEL_ID = "gwt-debug-debugger-breakpointsPanel"; String DEBUGGER_PANEL_TAB = "gwt-debug-partButton-Debug"; String FRAMES_LIST_ID = "gwt-debug-debugger-frames-list"; String THREADS_LIST_ID = "gwt-debug-debugger-threads-list"; @@ -87,8 +94,21 @@ public class DebugPanel { String EVALUATE_EXPRESSIONS = "gwt-debug-ActionButton/evaluateExpression-true"; } - @FindBy(id = Locators.DEBUGGER_BREAKPOINTS_PANEL_ID) - WebElement debuggerBreakPointPanel; + private interface BreakpointsPanel { + String ID = "gwt-debug-debugger-breakpointsPanel"; + String BREAKPOINT_ITEM = "//div[@id='gwt-debug-debugger-breakpointsPanel']//td[text()='%s']"; + String CONTEXT_MENU = "gwt-debug-contextMenu/breakpointSettings"; + } + + private interface BreakpointConfigurationWindow { + String BREAKPOINT_CONDITION_TEXT = + "//div[@id='gwt-debug-breakpoint-configuration-window']//textarea[@id='gwt-debug-breakpoint-condition-text']"; + String APPLY_BTN = + "//div[@id='gwt-debug-breakpoint-configuration-window']//button[@id='gwt-debug-apply-btn']"; + } + + @FindBy(id = BreakpointsPanel.ID) + WebElement breakpointPanel; @FindBy(id = Locators.DEBUGGER_PANEL_TAB) WebElement debuggerTab; @@ -126,16 +146,15 @@ public class DebugPanel { new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) .until( (WebDriver webDriver) -> { - return debuggerBreakPointPanel.getText().contains(content); + return breakpointPanel.getText().contains(content); }); } - /** Wait disappearance any breakpoints from debugger breakpoints panel */ public void waitBreakPointsPanelIsEmpty() { new WebDriverWait(seleniumWebDriver, REDRAW_UI_ELEMENTS_TIMEOUT_SEC) .until( (WebDriver webDriver) -> { - return debuggerBreakPointPanel.getText().isEmpty(); + return breakpointPanel.getText().isEmpty(); }); } @@ -163,10 +182,10 @@ public class DebugPanel { public void selectVarInVariablePanel(String variable) { new WebDriverWait(seleniumWebDriver, REDRAW_UI_ELEMENTS_TIMEOUT_SEC) .until( - ExpectedConditions.visibilityOfElementLocated( - By.xpath(String.format(Locators.VARIABLE_PANEL_SELECT_VAL, variable)))); + visibilityOfElementLocated( + xpath(format(Locators.VARIABLE_PANEL_SELECT_VAL, variable)))); seleniumWebDriver - .findElement(By.xpath(String.format(Locators.VARIABLE_PANEL_SELECT_VAL, variable))) + .findElement(xpath(format(Locators.VARIABLE_PANEL_SELECT_VAL, variable))) .click(); } @@ -178,8 +197,8 @@ public class DebugPanel { public void clickOnButton(String buttonIdLocator) { loader.waitOnClosed(); new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) - .until(ExpectedConditions.visibilityOfElementLocated(By.id(buttonIdLocator))); - seleniumWebDriver.findElement(By.id(buttonIdLocator)).click(); + .until(visibilityOfElementLocated(id(buttonIdLocator))); + seleniumWebDriver.findElement(id(buttonIdLocator)).click(); loader.waitOnClosed(); } @@ -194,7 +213,7 @@ public class DebugPanel { new WebDriverWait(seleniumWebDriver, 20) .until( ExpectedConditions.invisibilityOfElementLocated( - By.xpath(LocatorsChangeVariable.TEXTAREA))); + xpath(LocatorsChangeVariable.TEXTAREA))); } /** @@ -229,10 +248,10 @@ public class DebugPanel { String exprFieldLocator = "//div[text()='Enter an expression:']/parent::div/following-sibling::div/input"; new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) - .until(ExpectedConditions.visibilityOfElementLocated(By.xpath(exprFieldLocator))) + .until(visibilityOfElementLocated(xpath(exprFieldLocator))) .clear(); new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) - .until(ExpectedConditions.visibilityOfElementLocated(By.xpath(exprFieldLocator))) + .until(visibilityOfElementLocated(xpath(exprFieldLocator))) .sendKeys(expression); } @@ -248,7 +267,7 @@ public class DebugPanel { (ExpectedCondition) webDriver -> { return seleniumWebDriver - .findElement(By.xpath(locator)) + .findElement(xpath(locator)) .getAttribute("value") .equals(expVal); }); @@ -258,7 +277,7 @@ public class DebugPanel { public void clickEvaluateBtn() { String locator = "//button[text()='Evaluate']"; new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) - .until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator))) + .until(visibilityOfElementLocated(xpath(locator))) .click(); } @@ -266,10 +285,10 @@ public class DebugPanel { public void clickCloseEvaluateBtn() { String locator = "//button[text()='Evaluate']/preceding-sibling::button"; new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) - .until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator))) + .until(visibilityOfElementLocated(xpath(locator))) .click(); new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) - .until(ExpectedConditions.invisibilityOfElementLocated(By.xpath(locator))); + .until(ExpectedConditions.invisibilityOfElementLocated(xpath(locator))); } /** @@ -281,7 +300,7 @@ public class DebugPanel { try { return seleniumWebDriver - .findElement(By.id(DebuggerButtonsPanel.REMOVE_ALL_BREAKPOINTS)) + .findElement(id(DebuggerButtonsPanel.REMOVE_ALL_BREAKPOINTS)) .isDisplayed(); } catch (Exception ex) { return false; @@ -301,7 +320,7 @@ public class DebugPanel { new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) .until( ExpectedConditions.presenceOfAllElementsLocatedBy( - By.xpath(locatorWithHiglightedText))); + xpath(locatorWithHiglightedText))); for (WebElement hilightedElement : hilightedElements) { highLightedText.append(hilightedElement.getText()); } @@ -322,7 +341,7 @@ public class DebugPanel { editor.waitActiveEditor(); List editorLines = seleniumWebDriver.findElements( - By.xpath( + xpath( "//div[@id='gwt-debug-editorPartStack-contentPanel']//div[@active]//div[@class='textviewContent' and @contenteditable='true']/div")); new WebDriverWait(seleniumWebDriver, LOAD_PAGE_TIMEOUT_SEC) .until( @@ -415,9 +434,7 @@ public class DebugPanel { waitFramesListPanelReady(); new WebDriverWait(seleniumWebDriver, REDRAW_UI_ELEMENTS_TIMEOUT_SEC) - .until( - ExpectedConditions.visibilityOfElementLocated( - By.xpath("//td[text()='" + getFrames()[frameIndex] + "']"))) + .until(visibilityOfElementLocated(xpath("//td[text()='" + getFrames()[frameIndex] + "']"))) .click(); } @@ -444,10 +461,39 @@ public class DebugPanel { threads.click(); new WebDriverWait(seleniumWebDriver, REDRAW_UI_ELEMENTS_TIMEOUT_SEC) - .until( - ExpectedConditions.visibilityOfElementLocated( - By.xpath("//*[contains(text(),'\"" + threadName + "\"@')]"))) + .until(visibilityOfElementLocated(xpath("//*[contains(text(),'\"" + threadName + "\"@')]"))) .click(); threads.click(); } + + public void makeBreakpointConditional(String fileName, int lineNumber, String condition) { + String breakpointItem = format(BreakpointsPanel.BREAKPOINT_ITEM, fileName + ":" + lineNumber); + + seleniumWebDriver + .wait(REDRAW_UI_ELEMENTS_TIMEOUT_SEC) + .until(visibilityOfElementLocated(xpath(breakpointItem))); + + actionsFactory + .createAction(seleniumWebDriver) + .contextClick(seleniumWebDriver.findElement(xpath(breakpointItem))) + .build() + .perform(); + + seleniumWebDriver + .wait(REDRAW_UI_ELEMENTS_TIMEOUT_SEC) + .until(visibilityOfElementLocated(id(BreakpointsPanel.CONTEXT_MENU))) + .click(); + + seleniumWebDriver + .wait(REDRAW_UI_ELEMENTS_TIMEOUT_SEC) + .until( + visibilityOfElementLocated( + xpath(BreakpointConfigurationWindow.BREAKPOINT_CONDITION_TEXT))) + .sendKeys(condition); + + seleniumWebDriver + .wait(REDRAW_UI_ELEMENTS_TIMEOUT_SEC) + .until(visibilityOfElementLocated(xpath(BreakpointConfigurationWindow.APPLY_BTN))) + .click(); + } } diff --git a/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/debugger/ConditionalBreakpointsTest.java b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/debugger/ConditionalBreakpointsTest.java new file mode 100644 index 0000000000..c7dec6fa9d --- /dev/null +++ b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/debugger/ConditionalBreakpointsTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.selenium.debugger; + +import static org.eclipse.che.selenium.core.constant.TestCommandsConstants.CUSTOM; +import static org.eclipse.che.selenium.core.constant.TestMenuCommandsConstants.Run.EDIT_DEBUG_CONFIGURATION; +import static org.eclipse.che.selenium.core.constant.TestMenuCommandsConstants.Run.RUN_MENU; +import static org.eclipse.che.selenium.core.project.ProjectTemplates.PLAIN_JAVA; +import static org.eclipse.che.selenium.pageobject.debug.DebugPanel.DebuggerButtonsPanel.RESUME_BTN_ID; + +import com.google.inject.Inject; +import java.nio.file.Paths; +import org.eclipse.che.commons.lang.NameGenerator; +import org.eclipse.che.selenium.core.client.TestCommandServiceClient; +import org.eclipse.che.selenium.core.client.TestProjectServiceClient; +import org.eclipse.che.selenium.core.constant.TestBuildConstants; +import org.eclipse.che.selenium.core.constant.TestMenuCommandsConstants; +import org.eclipse.che.selenium.core.workspace.TestWorkspace; +import org.eclipse.che.selenium.pageobject.CodenvyEditor; +import org.eclipse.che.selenium.pageobject.Consoles; +import org.eclipse.che.selenium.pageobject.Ide; +import org.eclipse.che.selenium.pageobject.Menu; +import org.eclipse.che.selenium.pageobject.NotificationsPopupPanel; +import org.eclipse.che.selenium.pageobject.ProjectExplorer; +import org.eclipse.che.selenium.pageobject.debug.DebugPanel; +import org.eclipse.che.selenium.pageobject.debug.JavaDebugConfig; +import org.eclipse.che.selenium.pageobject.intelligent.CommandsPalette; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** @author Musienko Maxim */ +public class ConditionalBreakpointsTest { + private static final String PROJECT = NameGenerator.generate("project", 2); + + @Inject private TestWorkspace ws; + @Inject private Ide ide; + + @Inject private ProjectExplorer projectExplorer; + @Inject private CodenvyEditor editor; + @Inject private DebugPanel debugPanel; + @Inject private TestProjectServiceClient testProjectServiceClient; + @Inject private TestCommandServiceClient testCommandServiceClient; + @Inject private CommandsPalette commandsPalette; + @Inject private Consoles consoles; + @Inject private Menu menu; + @Inject private NotificationsPopupPanel notifications; + @Inject private JavaDebugConfig debugConfig; + + @BeforeClass + public void setUp() throws Exception { + testProjectServiceClient.importProject( + ws.getId(), + Paths.get(getClass().getResource("/projects/plugins/DebuggerPlugin/hello-world").toURI()), + PROJECT, + PLAIN_JAVA); + + testCommandServiceClient.createCommand( + "cd ${current.project.path}/src/ && javac -g HelloWorld.java &&" + + " java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y HelloWorld", + "debug", + CUSTOM, + ws.getId()); + + ide.open(ws); + projectExplorer.waitItem(PROJECT); + projectExplorer.quickExpandWithJavaScript(); + debugPanel.openDebugPanel(); + + projectExplorer.openItemByPath(PROJECT + "/src/HelloWorld.java"); + } + + @Test + public void shouldAddConditionalBreakpoint() throws Exception { + editor.setBreakpoint(14); + editor.setBreakpoint(15); + editor.waitInactiveBreakpoint(15); + debugPanel.makeBreakpointConditional("HelloWorld.java", 15, "i == 3"); + editor.waitConditionalBreakpoint(15, false); + + projectExplorer.selectItem(PROJECT); + + startDebug(); + + editor.waitConditionalBreakpoint(15, true); + debugPanel.clickOnButton(RESUME_BTN_ID); + debugPanel.waitTextInVariablesPanel("i=3"); + } + + private void startDebug() { + menu.runCommand(RUN_MENU, EDIT_DEBUG_CONFIGURATION); + debugConfig.createConfig(PROJECT); + + commandsPalette.openCommandPalette(); + commandsPalette.startCommandByDoubleClick("debug"); + consoles.waitExpectedTextIntoConsole(TestBuildConstants.LISTENING_AT_ADDRESS_8000); + + menu.runCommandByXpath( + TestMenuCommandsConstants.Run.RUN_MENU, + TestMenuCommandsConstants.Run.DEBUG, + debugConfig.getXpathToІRunDebugCommand(PROJECT)); + notifications.waitExpectedMessageOnProgressPanelAndClosed("Remote debugger connected"); + } +} diff --git a/selenium/che-selenium-test/src/test/resources/projects/plugins/DebuggerPlugin/hello-world/src/HelloWorld.java b/selenium/che-selenium-test/src/test/resources/projects/plugins/DebuggerPlugin/hello-world/src/HelloWorld.java new file mode 100644 index 0000000000..864bd2a4df --- /dev/null +++ b/selenium/che-selenium-test/src/test/resources/projects/plugins/DebuggerPlugin/hello-world/src/HelloWorld.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2012-2017 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +public class HelloWorld { + + public static void main(String[] arg) { + for (int i = 0; i < 10; i++) { + System.out.println(i); + } + } +} diff --git a/selenium/che-selenium-test/src/test/resources/suites/CheSuite.xml b/selenium/che-selenium-test/src/test/resources/suites/CheSuite.xml index d210d46870..6a8a706dd2 100644 --- a/selenium/che-selenium-test/src/test/resources/suites/CheSuite.xml +++ b/selenium/che-selenium-test/src/test/resources/suites/CheSuite.xml @@ -85,6 +85,7 @@ + diff --git a/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/Breakpoint.java b/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/Breakpoint.java index 378ef01cdc..2c928663da 100644 --- a/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/Breakpoint.java +++ b/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/Breakpoint.java @@ -20,4 +20,6 @@ public interface Breakpoint { /** The condition. */ String getCondition(); + + void setCondition(String condition); } diff --git a/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/impl/BreakpointImpl.java b/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/impl/BreakpointImpl.java index 49b642e2ca..5ae47eff68 100644 --- a/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/impl/BreakpointImpl.java +++ b/wsagent/che-core-api-debug-shared/src/main/java/org/eclipse/che/api/debug/shared/model/impl/BreakpointImpl.java @@ -16,8 +16,8 @@ import org.eclipse.che.api.debug.shared.model.Location; /** @author Anatoliy Bazko */ public class BreakpointImpl implements Breakpoint { private final Location location; - private final boolean enabled; - private final String condition; + private boolean enabled; + private String condition; public BreakpointImpl(Location location, boolean enabled, String condition) { this.location = location; @@ -44,6 +44,11 @@ public class BreakpointImpl implements Breakpoint { return condition; } + @Override + public void setCondition(String condition) { + this.condition = condition; + } + @Override public boolean equals(Object o) { if (this == o) return true;