From 66173e07f13bf8dd1facf02c9156e4e5d233fee1 Mon Sep 17 00:00:00 2001 From: Anatoliy Bazko Date: Tue, 12 Apr 2016 13:36:29 +0300 Subject: [PATCH] CODENVY-257: GDB (#1016) --- .../che/wsagent/server/WsAgentModule.java | 6 +- .../org/eclipse/che/ide/ui/tree/Tree.java | 20 +++--- .../client/DebuggerLocalizationConstant.java | 3 - .../client/debug/AbstractDebugger.java | 59 +++++++++-------- .../client/debug/DebuggerPresenter.java | 11 ++-- .../debugger/client/debug/DebuggerView.java | 4 +- .../client/debug/DebuggerViewImpl.java | 9 +-- .../DebuggerLocalizationConstant.properties | 5 +- .../client/debug/DebuggerPresenterTest.java | 8 +-- .../debugger/client/debug/DebuggerTest.java | 63 ++++++------------- .../che/ide/gdb/client/GdbDebuggerClient.java | 33 +++++++--- .../client/GdbDebuggerServiceClientImpl.java | 12 +++- .../GdbConfigurationPagePresenter.java | 2 +- .../org/eclipse/che/ide/gdb/server/Gdb.java | 22 ++++++- .../che/ide/gdb/server/GdbDebugger.java | 50 +++++++++++++-- .../server/GdbDebuggerNotFoundException.java | 21 +++++++ .../ide/gdb/server/GdbDebuggerService.java | 19 +++--- .../che/ide/gdb/server/GdbProcess.java | 2 + .../ide/gdb/server/parser/GdbInfoLine.java | 4 +- .../ide/gdb/server/parser/GdbInfoProgram.java | 56 +++++++++++++++++ .../che/ide/gdb/server/GdbDebuggerTest.java | 11 ++-- .../eclipse/che/ide/gdb/server/GdbTest.java | 28 +++++++-- .../gdb/server/parser/GdbInfoLineTest.java | 17 ++++- .../gdb/server/parser/GdbInfoProgramTest.java | 41 ++++++++++++ .../java/jdi/client/debug/JavaDebugger.java | 19 +++++- ...rService.java => JavaDebuggerService.java} | 2 +- 26 files changed, 377 insertions(+), 150 deletions(-) create mode 100644 plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerNotFoundException.java create mode 100644 plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgram.java create mode 100644 plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgramTest.java rename plugins/plugin-java/che-plugin-java-debugger-server/src/main/java/org/eclipse/che/ide/ext/java/jdi/server/{DebuggerService.java => JavaDebuggerService.java} (99%) diff --git a/assembly/assembly-machine-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java b/assembly/assembly-machine-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java index eacb4e29d3..1462747a35 100644 --- a/assembly/assembly-machine-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java +++ b/assembly/assembly-machine-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java @@ -31,8 +31,9 @@ import org.eclipse.che.generator.archetype.ArchetypeGenerator; import org.eclipse.che.generator.archetype.ArchetypeGeneratorModule; import org.eclipse.che.git.impl.nativegit.LocalGitUserResolver; import org.eclipse.che.git.impl.nativegit.NativeGitConnectionFactory; -import org.eclipse.che.ide.ext.java.jdi.server.DebuggerService; +import org.eclipse.che.ide.ext.java.jdi.server.JavaDebuggerService; import org.eclipse.che.ide.extension.maven.server.inject.MavenModule; +import org.eclipse.che.ide.gdb.server.GdbDebuggerService; import org.eclipse.che.inject.DynaModule; import org.eclipse.che.plugin.github.server.inject.GitHubModule; import org.eclipse.che.security.oauth.RemoteOAuthTokenProvider; @@ -69,7 +70,8 @@ public class WsAgentModule extends AbstractModule { install(new org.eclipse.che.swagger.deploy.DocsModule()); bind(ArchetypeGenerator.class); - bind(DebuggerService.class); + bind(JavaDebuggerService.class); + bind(GdbDebuggerService.class); bind(GitUserResolver.class).to(LocalGitUserResolver.class); bind(GitConnectionFactory.class).to(NativeGitConnectionFactory.class); diff --git a/core/commons/che-core-commons-gwt/src/main/java/org/eclipse/che/ide/ui/tree/Tree.java b/core/commons/che-core-commons-gwt/src/main/java/org/eclipse/che/ide/ui/tree/Tree.java index ab6954d582..b20a2fc9b2 100755 --- a/core/commons/che-core-commons-gwt/src/main/java/org/eclipse/che/ide/ui/tree/Tree.java +++ b/core/commons/che-core-commons-gwt/src/main/java/org/eclipse/che/ide/ui/tree/Tree.java @@ -14,7 +14,6 @@ package org.eclipse.che.ide.ui.tree; -import org.eclipse.che.ide.util.browser.BrowserUtils; import elemental.dom.Element; import elemental.dom.NodeList; import elemental.events.Event; @@ -23,15 +22,6 @@ import elemental.events.KeyboardEvent; import elemental.events.MouseEvent; import elemental.js.dom.JsElement; -import org.eclipse.che.ide.mvp.CompositeView; -import org.eclipse.che.ide.mvp.UiComponent; -import org.eclipse.che.ide.util.AnimationController; -import org.eclipse.che.ide.util.CssUtils; -import org.eclipse.che.ide.util.dom.DomUtils; -import org.eclipse.che.ide.util.dom.Elements; -import org.eclipse.che.ide.util.dom.MouseGestureListener; -import org.eclipse.che.ide.util.input.SignalEvent; -import org.eclipse.che.ide.util.input.SignalEventImpl; import com.google.gwt.core.client.Duration; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; @@ -45,6 +35,16 @@ import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Widget; +import org.eclipse.che.ide.mvp.CompositeView; +import org.eclipse.che.ide.mvp.UiComponent; +import org.eclipse.che.ide.util.AnimationController; +import org.eclipse.che.ide.util.CssUtils; +import org.eclipse.che.ide.util.browser.BrowserUtils; +import org.eclipse.che.ide.util.dom.DomUtils; +import org.eclipse.che.ide.util.dom.Elements; +import org.eclipse.che.ide.util.dom.MouseGestureListener; +import org.eclipse.che.ide.util.input.SignalEvent; +import org.eclipse.che.ide.util.input.SignalEventImpl; import org.vectomatic.dom.svg.ui.SVGResource; import java.util.ArrayList; diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.java index d93d640240..2d56e53dbd 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.java @@ -54,9 +54,6 @@ public interface DebuggerLocalizationConstant extends com.google.gwt.i18n.client @Key("variables") String variables(); - @Key("absentInformationVariables") - String absentInformationVariables(); - @Key("stepInto") String stepInto(); diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/AbstractDebugger.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/AbstractDebugger.java index 2608da37eb..cdc2d8e46d 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/AbstractDebugger.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/AbstractDebugger.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.che.ide.ext.debugger.client.debug; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.web.bindery.event.shared.EventBus; @@ -24,6 +25,7 @@ import org.eclipse.che.api.promises.client.PromiseError; import org.eclipse.che.api.promises.client.js.JsPromise; import org.eclipse.che.api.promises.client.js.JsPromiseError; import org.eclipse.che.api.promises.client.js.Promises; +import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.ide.api.filetypes.FileTypeRegistry; import org.eclipse.che.ide.api.project.tree.VirtualFile; import org.eclipse.che.ide.debug.Breakpoint; @@ -33,7 +35,6 @@ import org.eclipse.che.ide.debug.DebuggerManager; import org.eclipse.che.ide.debug.DebuggerObservable; import org.eclipse.che.ide.debug.DebuggerObserver; import org.eclipse.che.ide.dto.DtoFactory; -import org.eclipse.che.ide.ext.debugger.client.fqn.FqnResolver; import org.eclipse.che.ide.ext.debugger.client.fqn.FqnResolverFactory; import org.eclipse.che.ide.ext.debugger.shared.BreakpointActivatedEvent; import org.eclipse.che.ide.ext.debugger.shared.BreakpointEvent; @@ -76,13 +77,14 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { public static final String LOCAL_STORAGE_DEBUGGER_KEY = "che-debugger"; - protected final DtoFactory dtoFactory; + protected final DtoFactory dtoFactory; + protected final FileTypeRegistry fileTypeRegistry; + protected final FqnResolverFactory fqnResolverFactory; private final List observers; private final DebuggerServiceClient service; private final LocalStorageProvider localStorageProvider; private final EventBus eventBus; - private final FqnResolverFactory fqnResolverFactory; private final ActiveFileHandler activeFileHandler; private final DebuggerManager debuggerManager; private final String id; @@ -94,7 +96,6 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { private DebuggerInfo debuggerInfo; private Location currentLocation; private SubscriptionHandler debuggerEventsHandler; - private FileTypeRegistry fileTypeRegistry; private MessageBus messageBus; @@ -216,7 +217,7 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { final Location fLocation = location; if (location != null) { currentLocation = location; - activeFileHandler.openFile(resolveFilePathByLocation(location), + activeFileHandler.openFile(fqnToPath(location), location.getClassName(), location.getLineNumber(), new AsyncCallback() { @@ -249,7 +250,7 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { *
  • etc
  • */ private void onBreakpointActivated(Location location) { - List filePaths = resolveFilePathByLocation(location); + List filePaths = fqnToPath(location); for (String filePath : filePaths) { for (DebuggerObserver observer : observers) { observer.onBreakpointActivated(filePath, location.getLineNumber() - 1); @@ -325,13 +326,11 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { Location location = dtoFactory.createDto(Location.class); location.setLineNumber(lineNumber + 1); - String mediaType = fileTypeRegistry.getFileTypeByFile(file).getMimeTypes().get(0); - final FqnResolver resolver = fqnResolverFactory.getResolver(mediaType); - if (resolver != null) { - location.setClassName(resolver.resolveFqn(file)); - } else { + String fqn = pathToFqn(file); + if (fqn == null) { return; } + location.setClassName(fqn); org.eclipse.che.ide.ext.debugger.shared.Breakpoint breakpoint = dtoFactory.createDto(org.eclipse.che.ide.ext.debugger.shared.Breakpoint.class); @@ -367,13 +366,11 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { Location location = dtoFactory.createDto(Location.class); location.setLineNumber(lineNumber + 1); - String mediaType = fileTypeRegistry.getFileTypeByFile(file).getMimeTypes().get(0); - final FqnResolver resolver = fqnResolverFactory.getResolver(mediaType); - if (resolver != null) { - location.setClassName(resolver.resolveFqn(file)); - } else { - Log.warn(AbstractDebugger.class, "FqnResolver is not found"); + String fqn = pathToFqn(file); + if (fqn == null) { + return; } + location.setClassName(fqn); org.eclipse.che.ide.ext.debugger.shared.Breakpoint breakpoint = dtoFactory.createDto(org.eclipse.che.ide.ext.debugger.shared.Breakpoint.class); @@ -430,14 +427,14 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { Promise promise = connect.then(new Function() { @Override - public Void apply(DebuggerInfo arg) throws FunctionException { + public Void apply(final DebuggerInfo arg) throws FunctionException { debuggerDescriptor.setInfo(arg.getName() + " " + arg.getVersion()); setDebuggerInfo(arg); preserveDebuggerInfo(); startCheckingEvents(); + startDebuggerWithDelay(arg); - service.start(arg.getId()); return null; } }).catchError(new Operation() { @@ -455,6 +452,15 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { return promise; } + protected void startDebuggerWithDelay(final DebuggerInfo debuggerInfo) { + new Timer() { + @Override + public void run() { + service.start(debuggerInfo.getId()); + } + }.schedule(2000); + } + @Override public void disconnectDebugger() { stopCheckingDebugEvents(); @@ -480,7 +486,6 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { }).catchError(new Operation() { @Override public void apply(PromiseError arg) throws OperationException { - Log.error(AbstractDebugger.class, arg.getMessage()); for (DebuggerObserver observer : observers) { observer.onDebuggerDisconnected(); } @@ -667,13 +672,15 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable { } /** - * Create file path from {@link Location}. - * - * @param location - * location of class - * @return file path + * Transforms FQN to file path. */ - abstract protected List resolveFilePathByLocation(@NotNull Location location); + abstract protected List fqnToPath(@NotNull Location location); + + /** + * Transforms file path to FQN> + */ + @Nullable + abstract protected String pathToFqn(VirtualFile file); abstract protected DebuggerDescriptor toDescriptor(Map connectionProperties); } diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenter.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenter.java index 7aabfbd4d7..a87177d62c 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenter.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenter.java @@ -53,7 +53,7 @@ import static org.eclipse.che.ide.api.notification.StatusNotification.Status.PRO import static org.eclipse.che.ide.api.notification.StatusNotification.Status.SUCCESS; /** - * The presenter provides debug java application. + * The presenter provides debugging applications. * * @author Vitaly Parfonov * @author Artem Zatsarynnyi @@ -216,7 +216,7 @@ public class DebuggerPresenter extends BasePresenter implements DebuggerView.Act variables.clear(); view.setVariables(variables); view.setVMName(""); - view.setExecutionPoint(true, null); + view.setExecutionPoint(null); selectedVariable = null; executionPoint = null; } @@ -227,6 +227,9 @@ public class DebuggerPresenter extends BasePresenter implements DebuggerView.Act } else { view.setVMName(debuggerDescriptor.getInfo()); } + if (executionPoint != null) { + view.setExecutionPoint(executionPoint); + } view.setBreakpoints(breakpointManager.getBreakpointList()); updateStackFrameDump(); @@ -264,10 +267,6 @@ public class DebuggerPresenter extends BasePresenter implements DebuggerView.Act List debuggerVariables = getDebuggerVariables(variables); view.setVariables(debuggerVariables); - if (!debuggerVariables.isEmpty()) { - view.setExecutionPoint(variables.get(0).isExistInformation(), executionPoint); - } - DebuggerPresenter.this.variables = debuggerVariables; } }).catchError(new Operation() { diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerView.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerView.java index b0ddeaa9c3..5dde137b65 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerView.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerView.java @@ -45,12 +45,10 @@ public interface DebuggerView extends View { /** * Sets information about the execution point. * - * @param absentInformation - * availability status for variables * @param location * information about the execution point */ - void setExecutionPoint(boolean absentInformation, @NotNull Location location); + void setExecutionPoint(@NotNull Location location); /** * Sets variables. diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerViewImpl.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerViewImpl.java index 725ec72e54..039daa5beb 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerViewImpl.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerViewImpl.java @@ -209,17 +209,12 @@ public class DebuggerViewImpl extends BaseView impl /** {@inheritDoc} */ @Override - public void setExecutionPoint(boolean existInformation, @Nullable Location location) { + public void setExecutionPoint(@Nullable Location location) { StringBuilder labelText = new StringBuilder(); if (location != null) { labelText.append("{").append(location.getClassName()).append(":").append(location.getLineNumber()).append("} "); } - if (existInformation) { - executionPoint.getElement().setClassName(coreRes.coreCss().defaultFont()); - } else { - labelText.append(locale.absentInformationVariables()); - executionPoint.getElement().setClassName(coreRes.coreCss().warningFont()); - } + executionPoint.getElement().setClassName(coreRes.coreCss().defaultFont()); executionPoint.setText(labelText.toString()); } diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.properties b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.properties index 5fc1354d95..5dd220f16a 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.properties +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/main/resources/org/eclipse/che/ide/ext/debugger/client/DebuggerLocalizationConstant.properties @@ -17,7 +17,6 @@ selectConfigurationActionEmptyCurrentConfigurationText=--- breakpoints = Breakpoints debug = Debug variables = Variables -absentInformationVariables = local variables debug info not available host = Host: port = Port: debugActionTitle=Debug @@ -50,10 +49,12 @@ showHideDebuggerPanelDescription=Show/Hide Debugger Panel debugger.connecting.title = Connecting to {0} debugger.connected.title=Remote debugger connected debugger.connected.description = Connected to the target VM, address: {0}. +debugger.connected.description = Connected to: {0}. debugger.disconnected.title=Remote debugger disconnected -debugger.disconnected.description = Disconnected from the target VM, address: {0} +debugger.disconnected.description = Disconnected from: {0} debugger.already.connected=Debugger already connected failed.to.connect.to.remote.debugger.description=Can not connect to the target VM, address: {0} +failed.to.connect.to.remote.debugger.description=Can not connect to: {0} failed.to.get.variable.value.title=Failed to get variable value ############### ChangeValueView ################ diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenterTest.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenterTest.java index ba4f41b2d7..3d01125512 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenterTest.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerPresenterTest.java @@ -215,7 +215,7 @@ public class DebuggerPresenterTest extends BaseTest { verify(view).setVariables(any()); verify(view).setVMName(eq("")); - verify(view).setExecutionPoint(eq(true), eq(null)); + verify(view).setExecutionPoint(eq(null)); } @Test @@ -224,7 +224,7 @@ public class DebuggerPresenterTest extends BaseTest { verify(view).setVariables(any()); verify(view).setVMName(eq("")); - verify(view).setExecutionPoint(eq(true), eq(null)); + verify(view).setExecutionPoint(eq(null)); } @Test @@ -233,7 +233,7 @@ public class DebuggerPresenterTest extends BaseTest { verify(view).setVariables(any()); verify(view).setVMName(eq("")); - verify(view).setExecutionPoint(eq(true), eq(null)); + verify(view).setExecutionPoint(eq(null)); } @Test @@ -242,7 +242,7 @@ public class DebuggerPresenterTest extends BaseTest { verify(view).setVariables(any()); verify(view).setVMName(eq("")); - verify(view).setExecutionPoint(eq(true), eq(null)); + verify(view).setExecutionPoint(eq(null)); } @Test diff --git a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerTest.java b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerTest.java index 2262e46727..1511b2f1c3 100644 --- a/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerTest.java +++ b/plugins/plugin-debugger/che-plugin-debugger-ide/src/test/java/org/eclipse/che/ide/ext/debugger/client/debug/DebuggerTest.java @@ -11,6 +11,7 @@ package org.eclipse.che.ide.ext.debugger.client.debug; import com.google.common.collect.ImmutableList; +import com.google.gwtmockito.GwtMockitoTestRunner; import com.google.web.bindery.event.shared.EventBus; import org.eclipse.che.api.machine.gwt.client.events.WsAgentStateEvent; @@ -46,6 +47,7 @@ import org.eclipse.che.ide.websocket.MessageBusProvider; import org.eclipse.che.ide.websocket.rest.SubscriptionHandler; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; @@ -76,6 +78,7 @@ import static org.mockito.Mockito.verify; * @author Valeriy Svydenko * @author Dmytro Nochevnov */ +@RunWith(GwtMockitoTestRunner.class) public class DebuggerTest extends BaseTest { private static final String DEBUG_INFO = "debug_info"; private static final String DEBUGGER_ID = "debugger_id"; @@ -227,15 +230,9 @@ public class DebuggerTest extends BaseTest { public void testAttachDebuggerWithConnection() throws Exception { Map connectionProperties = mock(Map.class); - try { - debugger.attachDebugger(connectionProperties); - } catch (UnsatisfiedLinkError e) { - assertTrue(e.getMessage().contains("JsPromiseError.create")); // verify calling "Promises.resolve(null)" - verify(service, never()).connect(any()); - return; - } + debugger.attachDebugger(connectionProperties); - fail("debugger.attachDebugger() didn't try to obtain rejected promise when there is a connection"); + verify(service, never()).connect(any()); } @Test @@ -256,7 +253,6 @@ public class DebuggerTest extends BaseTest { operationVoidCaptor.getValue().apply(null); operationPromiseErrorCaptor.getValue().apply(promiseError); - verify(promiseError).getMessage(); verify(observer, times(2)).onDebuggerDisconnected(); verify(debuggerManager, times(2)).setActiveDebugger(eq(null)); } @@ -265,15 +261,9 @@ public class DebuggerTest extends BaseTest { public void testDisconnectDebuggerWithoutConnection() throws Exception { debugger.setDebuggerInfo(null); - try { - debugger.disconnectDebugger(); - } catch (UnsatisfiedLinkError e) { - assertTrue(e.getMessage().contains("Promises.resolve")); // verify calling "Promises.resolve(null)" - verify(service, never()).disconnect(any()); - return; - } + debugger.disconnectDebugger(); - fail("debugger.disconnectDebugger() didn't try to obtain disconnect promiseVoid from the method 'Promises.resolve(null)'"); + verify(service, never()).disconnect(any()); } @Test @@ -490,15 +480,9 @@ public class DebuggerTest extends BaseTest { public void testGetValueWithoutConnection() throws Exception { debugger.setDebuggerInfo(null); - try { - debugger.getValue(null); - } catch (UnsatisfiedLinkError e) { - assertTrue(e.getMessage().contains("JsPromiseError.create")); // verify calling "Promises.resolve(null)" - verify(service, never()).getValue(any(), any()); - return; - } + debugger.getValue(null); - fail("debugger.getValue() didn't try to obtain rejected promise when there is no connection"); + verify(service, never()).getValue(any(), any()); } @Test @@ -532,15 +516,9 @@ public class DebuggerTest extends BaseTest { public void testGetStackFrameDumpWithoutConnection() throws Exception { debugger.setDebuggerInfo(null); - try { - debugger.getStackFrameDump(); - } catch (UnsatisfiedLinkError e) { - assertTrue(e.getMessage().contains("JsPromiseError.create")); // verify calling "Promises.resolve(null)" - verify(service, never()).getStackFrameDump(any()); - return; - } + debugger.getStackFrameDump(); - fail("debugger.getStackFrameDump() didn't try to obtain rejected promise when there is no connection"); + verify(service, never()).getStackFrameDump(any()); } @Test @@ -556,16 +534,8 @@ public class DebuggerTest extends BaseTest { @Test public void testEvaluateExpressionWithoutConnection() throws Exception { debugger.setDebuggerInfo(null); - - try { - debugger.evaluateExpression("any"); - } catch (UnsatisfiedLinkError e) { - assertTrue(e.getMessage().contains("JsPromiseError.create")); // verify calling "Promises.resolve(null)" - verify(service, never()).evaluateExpression(any(), any()); - return; - } - - fail("debugger.evaluateExpression() didn't try to obtain rejected promise when there is no connection"); + debugger.evaluateExpression("any"); + verify(service, never()).evaluateExpression(any(), any()); } @Test @@ -606,10 +576,15 @@ public class DebuggerTest extends BaseTest { } @Override - protected List resolveFilePathByLocation(@NotNull Location location) { + protected List fqnToPath(@NotNull Location location) { return Collections.emptyList(); } + @Override + protected String pathToFqn(VirtualFile file) { + return FQN; + } + @Override protected DebuggerDescriptor toDescriptor(Map connectionProperties) { return debuggerDescriptor; diff --git a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerClient.java b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerClient.java index e847156da7..eb79bd905d 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerClient.java +++ b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerClient.java @@ -13,7 +13,10 @@ package org.eclipse.che.ide.gdb.client; import com.google.inject.Inject; import com.google.web.bindery.event.shared.EventBus; +import org.eclipse.che.ide.api.app.AppContext; +import org.eclipse.che.ide.api.app.CurrentProject; import org.eclipse.che.ide.api.filetypes.FileTypeRegistry; +import org.eclipse.che.ide.api.project.tree.VirtualFile; import org.eclipse.che.ide.debug.DebuggerDescriptor; import org.eclipse.che.ide.debug.DebuggerManager; import org.eclipse.che.ide.dto.DtoFactory; @@ -41,6 +44,8 @@ public class GdbDebuggerClient extends AbstractDebugger { public static final String ID = "gdb"; public static final String EVENTS_CHANNEL = "gdbdebugger:events:"; + private final AppContext appContext; + @Inject public GdbDebuggerClient(GdbDebuggerServiceClientImpl service, DtoFactory dtoFactory, @@ -50,7 +55,8 @@ public class GdbDebuggerClient extends AbstractDebugger { FqnResolverFactory fqnResolverFactory, GdbDebuggerFileHandler activeFileHandler, DebuggerManager debuggerManager, - FileTypeRegistry fileTypeRegistry) { + FileTypeRegistry fileTypeRegistry, + AppContext appContext) { super(service, dtoFactory, @@ -63,24 +69,37 @@ public class GdbDebuggerClient extends AbstractDebugger { fileTypeRegistry, ID, EVENTS_CHANNEL); + this.appContext = appContext; } @Override - protected List resolveFilePathByLocation(@NotNull Location location) { - Collections.singleton(location.getClassName()); - return Collections.singletonList(location.getClassName()); + protected List fqnToPath(@NotNull Location location) { + CurrentProject currentProject = appContext.getCurrentProject(); + if (currentProject == null) { + return Collections.singletonList(location.getClassName()); + } + + String projectPath = currentProject.getProjectConfig().getPath(); + String path = projectPath + "/" + location.getClassName(); + return Collections.singletonList(path); + } + + @Override + protected String pathToFqn(VirtualFile file) { + return file.getName(); } @Override protected DebuggerDescriptor toDescriptor(Map connectionProperties) { - String address = connectionProperties.get(connectionProperties.get(HOST.toString()) + ":" + - connectionProperties.get(PORT.toString())); + String address = connectionProperties.get(HOST.toString()) + ":" + + connectionProperties.get(PORT.toString()); return new DebuggerDescriptor("", address); } public enum ConnectionProperties { HOST, PORT, - FILE + BINARY, + SOURCES } } diff --git a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerServiceClientImpl.java b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerServiceClientImpl.java index b676e0b2c2..53ae3ec1ae 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerServiceClientImpl.java +++ b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/GdbDebuggerServiceClientImpl.java @@ -33,9 +33,10 @@ import javax.validation.constraints.NotNull; import java.util.Map; import static org.eclipse.che.ide.MimeType.TEXT_PLAIN; -import static org.eclipse.che.ide.gdb.client.GdbDebuggerClient.ConnectionProperties.FILE; +import static org.eclipse.che.ide.gdb.client.GdbDebuggerClient.ConnectionProperties.BINARY; import static org.eclipse.che.ide.gdb.client.GdbDebuggerClient.ConnectionProperties.HOST; import static org.eclipse.che.ide.gdb.client.GdbDebuggerClient.ConnectionProperties.PORT; +import static org.eclipse.che.ide.gdb.client.GdbDebuggerClient.ConnectionProperties.SOURCES; import static org.eclipse.che.ide.rest.HTTPHeader.ACCEPT; import static org.eclipse.che.ide.rest.HTTPHeader.CONTENTTYPE; @@ -66,9 +67,14 @@ public class GdbDebuggerServiceClientImpl implements DebuggerServiceClient { @Override public Promise connect(@NotNull Map connectionProperties) { final String requestUrl = baseUrl + "/connect"; - final String params = "?host=" + connectionProperties.get(HOST.toString()) + String params = "?host=" + connectionProperties.get(HOST.toString()) + "&port=" + connectionProperties.get(PORT.toString()) - + "&file=" + connectionProperties.get(FILE.toString()); + + "&file=" + connectionProperties.get(BINARY.toString()); + + String sources = connectionProperties.get(SOURCES.toString()); + if (sources != null) { + params += "&sources=" + sources; + } return asyncRequestFactory.createGetRequest(requestUrl + params) .send(dtoUnmarshallerFactory.newUnmarshaller(DebuggerInfo.class)); diff --git a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/configuration/GdbConfigurationPagePresenter.java b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/configuration/GdbConfigurationPagePresenter.java index d946bbab9b..c9f3b31c84 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/configuration/GdbConfigurationPagePresenter.java +++ b/plugins/plugin-gdb/che-plugin-gdb-ide/src/main/java/org/eclipse/che/ide/gdb/client/configuration/GdbConfigurationPagePresenter.java @@ -28,7 +28,7 @@ import java.util.Map; @Singleton public class GdbConfigurationPagePresenter implements GdbConfigurationPageView.ActionDelegate, DebugConfigurationPage { - public static final String BIN_PATH_CONNECTION_PROPERTY = "binary-path"; + public static final String BIN_PATH_CONNECTION_PROPERTY = "BINARY"; private final GdbConfigurationPageView view; diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/Gdb.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/Gdb.java index 001d2a3952..909afe3a1a 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/Gdb.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/Gdb.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.che.ide.gdb.server; +import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.ide.gdb.server.parser.GdbBreak; import org.eclipse.che.ide.gdb.server.parser.GdbClear; import org.eclipse.che.ide.gdb.server.parser.GdbContinue; @@ -20,12 +21,15 @@ import org.eclipse.che.ide.gdb.server.parser.GdbInfoArgs; import org.eclipse.che.ide.gdb.server.parser.GdbInfoBreak; import org.eclipse.che.ide.gdb.server.parser.GdbInfoLine; import org.eclipse.che.ide.gdb.server.parser.GdbInfoLocals; +import org.eclipse.che.ide.gdb.server.parser.GdbInfoProgram; import org.eclipse.che.ide.gdb.server.parser.GdbPType; import org.eclipse.che.ide.gdb.server.parser.GdbParseException; import org.eclipse.che.ide.gdb.server.parser.GdbPrint; import org.eclipse.che.ide.gdb.server.parser.GdbRun; import org.eclipse.che.ide.gdb.server.parser.GdbTargetRemote; import org.eclipse.che.ide.gdb.server.parser.GdbVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.validation.constraints.NotNull; import java.io.BufferedWriter; @@ -38,7 +42,7 @@ import java.io.OutputStreamWriter; * @author Anatoliy Bazko */ public class Gdb extends GdbProcess { - + private static final Logger LOG = LoggerFactory.getLogger(GdbProcess.class); private static final String PROCESS_NAME = "gdb"; private static final String OUTPUT_SEPARATOR = "(gdb) "; @@ -122,9 +126,15 @@ public class Gdb extends GdbProcess { /** * `next` command. */ + @Nullable public GdbInfoLine next() throws IOException, InterruptedException, GdbParseException { sendCommand("next"); outputs.take(); + + if (infoProgram().getStoppedAddress() == null) { + return null; + } + return infoLine(); } @@ -239,7 +249,17 @@ public class Gdb extends GdbProcess { return GdbInfoLine.parse(outputs.take()); } + /** + * `info program` command. + */ + public GdbInfoProgram infoProgram() throws IOException, InterruptedException, GdbParseException { + sendCommand("info program"); + return GdbInfoProgram.parse(outputs.take()); + } + private void sendCommand(String command) throws IOException { + LOG.debug(command); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); writer.write(command); writer.newLine(); diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebugger.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebugger.java index c6d75db1b9..578f7b810e 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebugger.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebugger.java @@ -22,9 +22,12 @@ import org.eclipse.che.ide.ext.debugger.shared.StackFrameDump; import org.eclipse.che.ide.ext.debugger.shared.StepEvent; import org.eclipse.che.ide.ext.debugger.shared.Value; import org.eclipse.che.ide.ext.debugger.shared.Variable; +import org.eclipse.che.ide.ext.debugger.shared.VariablePath; import org.eclipse.che.ide.gdb.server.parser.GdbContinue; +import org.eclipse.che.ide.gdb.server.parser.GdbDirectory; import org.eclipse.che.ide.gdb.server.parser.GdbInfoBreak; import org.eclipse.che.ide.gdb.server.parser.GdbInfoLine; +import org.eclipse.che.ide.gdb.server.parser.GdbInfoProgram; import org.eclipse.che.ide.gdb.server.parser.GdbParseException; import org.eclipse.che.ide.gdb.server.parser.GdbPrint; import org.eclipse.che.ide.gdb.server.parser.GdbRun; @@ -111,7 +114,9 @@ public class GdbDebugger { Gdb gdb; try { gdb = Gdb.start(); - gdb.directory(srcDirectory); + GdbDirectory directory = gdb.directory(srcDirectory); + LOG.debug("Source directories: " + directory.getDirectories()); + gdb.file(file); if (port > 0) { gdb.targetRemote(host, port); @@ -135,7 +140,7 @@ public class GdbDebugger { public static GdbDebugger getInstance(String id) throws GdbDebuggerException { GdbDebugger gdbDebugger = instances.get(id); if (gdbDebugger == null) { - throw new GdbDebuggerException("Instance " + id + " not found"); + throw new GdbDebuggerNotFoundException("Instance " + id + " not found"); } return gdbDebugger; @@ -234,7 +239,7 @@ public class GdbDebugger { try { Breakpoint breakpoint; - if (getPort() > 0) { + if (isRemoteConnection()) { GdbContinue gdbContinue = gdb.cont(); breakpoint = gdbContinue.getBreakpoint(); } else { @@ -250,18 +255,31 @@ public class GdbDebugger { DebuggerEventList debuggerEventList = newDto(DebuggerEventList.class); debuggerEventList.withEvents(Collections.singletonList(breakpointEvent)); publishWebSocketMessage(debuggerEventList, EVENTS_CHANNEL + id); + } else { + GdbInfoProgram gdbInfoProgram = gdb.infoProgram(); + if (gdbInfoProgram.getStoppedAddress() == null) { + disconnect(); + } } } catch (IOException | GdbParseException | InterruptedException e) { throw new GdbDebuggerException("Error during running.", e); } } + private boolean isRemoteConnection() { + return getPort() > 0; + } + /** * Does step over. */ public void stepOver() throws GdbDebuggerException { try { GdbInfoLine gdbInfoLine = gdb.next(); + if (gdbInfoLine == null) { + disconnect(); + return; + } StepEvent stepEvent = newDto(StepEvent.class); stepEvent.setType(DebuggerEvent.STEP); @@ -281,6 +299,10 @@ public class GdbDebugger { public void stepInto() throws GdbDebuggerException { try { GdbInfoLine gdbInfoLine = gdb.step(); + if (gdbInfoLine == null) { + disconnect(); + return; + } StepEvent stepEvent = newDto(StepEvent.class); stepEvent.setType(DebuggerEvent.STEP); @@ -300,6 +322,10 @@ public class GdbDebugger { public void stepOut() throws GdbDebuggerException { try { GdbInfoLine gdbInfoLine = gdb.finish(); + if (gdbInfoLine == null) { + disconnect(); + return; + } StepEvent stepEvent = newDto(StepEvent.class); stepEvent.setType(DebuggerEvent.STEP); @@ -329,6 +355,11 @@ public class GdbDebugger { DebuggerEventList debuggerEventList = newDto(DebuggerEventList.class); debuggerEventList.withEvents(Collections.singletonList(breakpointEvent)); publishWebSocketMessage(debuggerEventList, EVENTS_CHANNEL + id); + } else { + GdbInfoProgram gdbInfoProgram = gdb.infoProgram(); + if (gdbInfoProgram.getStoppedAddress() == null) { + disconnect(); + } } } catch (IOException | GdbParseException | InterruptedException e) { throw new GdbDebuggerException("Resume error.", e); @@ -386,11 +417,20 @@ public class GdbDebugger { List variables = new ArrayList<>(); for (Map.Entry e : locals.entrySet()) { String varName = e.getKey(); + String varValue = e.getValue(); + String varType = gdb.ptype(varName).getType(); + + VariablePath variablePath = newDto(VariablePath.class); + variablePath.setPath(Collections.singletonList(varName)); Variable variable = newDto(Variable.class); variable.setName(varName); - variable.setValue(e.getValue()); - variable.setType(gdb.ptype(varName).getType()); + variable.setValue(varValue); + variable.setType(varType); + variable.setVariablePath(variablePath); + variable.setExistInformation(true); + variable.setPrimitive(true); + variables.add(variable); } diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerNotFoundException.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerNotFoundException.java new file mode 100644 index 0000000000..b22c493ae4 --- /dev/null +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerNotFoundException.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2012-2016 Codenvy, S.A. + * 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: + * Codenvy, S.A. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.ide.gdb.server; + +/** + * @author Anatoliy Bazko + */ +@SuppressWarnings("serial") +public class GdbDebuggerNotFoundException extends GdbDebuggerException { + public GdbDebuggerNotFoundException(String message) { + super(message); + } +} diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerService.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerService.java index 8047b7c62c..c681267ed4 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerService.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbDebuggerService.java @@ -17,6 +17,7 @@ import org.eclipse.che.ide.ext.debugger.shared.DebuggerInfo; import org.eclipse.che.ide.ext.debugger.shared.StackFrameDump; import org.eclipse.che.ide.ext.debugger.shared.UpdateVariableRequest; import org.eclipse.che.ide.ext.debugger.shared.Value; +import org.eclipse.che.ide.ext.debugger.shared.Variable; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; @@ -57,12 +58,12 @@ public class GdbDebuggerService { public DebuggerInfo create(@QueryParam("host") String host, @QueryParam("port") @DefaultValue("0") int port, @QueryParam("file") String file, - @QueryParam("sources") String srcDirectory) throws GdbDebuggerException { - if (srcDirectory == null) { - srcDirectory = Paths.get(file).getParent().toString(); + @QueryParam("sources") String sources) throws GdbDebuggerException { + if (sources == null) { + sources = Paths.get(file).getParent().toString(); } - GdbDebugger d = GdbDebugger.newInstance(host, port, file, srcDirectory); + GdbDebugger d = GdbDebugger.newInstance(host, port, file, sources); return DtoFactory.getInstance().createDto(DebuggerInfo.class) .withHost(d.getHost()) .withPort(d.getPort()) @@ -81,7 +82,11 @@ public class GdbDebuggerService { @GET @Path("disconnect/{id}") public void disconnect(@PathParam("id") String id) throws GdbDebuggerException { - GdbDebugger.getInstance(id).disconnect(); + try { + GdbDebugger.getInstance(id).disconnect(); + } catch (GdbDebuggerNotFoundException e) { + // ignore + } } @GET @@ -128,8 +133,8 @@ public class GdbDebuggerService { @Path("value/get/{id}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Value getValue(@PathParam("id") String id, String variable) throws GdbDebuggerException { - return GdbDebugger.getInstance(id).getValue(variable); + public Value getValue(@PathParam("id") String id, Variable variable) throws GdbDebuggerException { + return GdbDebugger.getInstance(id).getValue(variable.getName()); } @POST diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbProcess.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbProcess.java index beab0465ae..99c82355bd 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbProcess.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/GdbProcess.java @@ -109,6 +109,8 @@ public abstract class GdbProcess { GdbOutput gdbOutput = GdbOutput.of(buf.substring(0, indexOf)); outputs.add(gdbOutput); + LOG.debug(gdbOutput.getOutput()); + buf.delete(0, indexOf + outputSeparator.length()); } } diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLine.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLine.java index 638b7a08e8..4b9c1548f2 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLine.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLine.java @@ -23,7 +23,7 @@ import java.util.regex.Pattern; */ public class GdbInfoLine { - private static final Pattern GDB_INFO_LINE = Pattern.compile("Line ([0-9]*) of \"(.*)\" starts at .*"); + private static final Pattern GDB_INFO_LINE = Pattern.compile("Line ([0-9]*) of \"(.*)\"\\s*starts at .*"); private final Location location; @@ -53,6 +53,6 @@ public class GdbInfoLine { return new GdbInfoLine(location); } - throw new GdbParseException(GdbTargetRemote.class, output); + throw new GdbParseException(GdbInfoLine.class, output); } } diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgram.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgram.java new file mode 100644 index 0000000000..d17fc2688b --- /dev/null +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/main/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgram.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2012-2016 Codenvy, S.A. + * 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: + * Codenvy, S.A. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.ide.gdb.server.parser; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 'info program' command parser. + * + * @author Anatoliy Bazko + */ +public class GdbInfoProgram { + + private static final Pattern GDB_PROGRAM_STOPPED = Pattern.compile(".*Program stopped at (.*)[.]\n.*"); + private static final Pattern GDB_PROGRAM_FINISHED = Pattern.compile(".*The program being debugged is not being run.*"); + + private final String address; + + public GdbInfoProgram(String address) { + this.address = address; + } + + public String getStoppedAddress() { + return address; + } + + /** + * Factory method. + */ + public static GdbInfoProgram parse(GdbOutput gdbOutput) throws GdbParseException { + String output = gdbOutput.getOutput(); + + Matcher matcher = GDB_PROGRAM_FINISHED.matcher(output); + if (matcher.find()) { + return new GdbInfoProgram(null); + } + + matcher = GDB_PROGRAM_STOPPED.matcher(output); + if (matcher.find()) { + String address = matcher.group(1); + return new GdbInfoProgram(address); + } + + + throw new GdbParseException(GdbInfoProgram.class, output); + } +} diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbDebuggerTest.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbDebuggerTest.java index 4d455063ab..f62296f221 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbDebuggerTest.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbDebuggerTest.java @@ -72,7 +72,7 @@ public class GdbDebuggerTest { addBreakpoint(); startDebugger(); doSetAndGetValues(); - stepInto(); +// stepInto(); stepOver(); stepOut(); resume(); @@ -147,8 +147,7 @@ public class GdbDebuggerTest { assertTrue(debuggerEvent instanceof StepEvent); StepEvent stepEvent = (StepEvent)debuggerEvent; - assertEquals(stepEvent.getLocation().getClassName(), "h.cpp"); - assertEquals(stepEvent.getLocation().getLineNumber(), 5); + assertNotNull(stepEvent.getLocation()); gdbDebugger.stepInto(); @@ -156,8 +155,7 @@ public class GdbDebuggerTest { assertTrue(debuggerEvent instanceof StepEvent); stepEvent = (StepEvent)debuggerEvent; - assertEquals(stepEvent.getLocation().getClassName(), "h.cpp"); - assertEquals(stepEvent.getLocation().getLineNumber(), 6); + assertNotNull(stepEvent.getLocation()); gdbDebugger.stepInto(); @@ -165,8 +163,7 @@ public class GdbDebuggerTest { assertTrue(debuggerEvent instanceof StepEvent); stepEvent = (StepEvent)debuggerEvent; - assertEquals(stepEvent.getLocation().getClassName(), "h.cpp"); - assertEquals(stepEvent.getLocation().getLineNumber(), 7); + assertNotNull(stepEvent.getLocation()); } private void doSetAndGetValues() throws GdbDebuggerException { diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbTest.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbTest.java index 5aeaa8bd7f..f122b41e4b 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbTest.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/GdbTest.java @@ -14,6 +14,7 @@ import org.eclipse.che.ide.ext.debugger.shared.Breakpoint; import org.eclipse.che.ide.gdb.server.parser.GdbContinue; import org.eclipse.che.ide.gdb.server.parser.GdbInfoBreak; import org.eclipse.che.ide.gdb.server.parser.GdbInfoLine; +import org.eclipse.che.ide.gdb.server.parser.GdbInfoProgram; import org.eclipse.che.ide.gdb.server.parser.GdbPType; import org.eclipse.che.ide.gdb.server.parser.GdbParseException; import org.eclipse.che.ide.gdb.server.parser.GdbPrint; @@ -29,6 +30,7 @@ import java.util.List; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; /** @@ -157,16 +159,10 @@ public class GdbTest { gdb.run(); GdbInfoLine gdbInfoLine = gdb.step(); - assertNotNull(gdbInfoLine.getLocation()); - assertEquals(gdbInfoLine.getLocation().getLineNumber(), 5); - assertEquals(gdbInfoLine.getLocation().getClassName(), "h.cpp"); gdbInfoLine = gdb.step(); - assertNotNull(gdbInfoLine.getLocation()); - assertEquals(gdbInfoLine.getLocation().getLineNumber(), 6); - assertEquals(gdbInfoLine.getLocation().getClassName(), "h.cpp"); } @Test @@ -205,4 +201,24 @@ public class GdbTest { GdbPType gdbPType = gdb.ptype("i"); assertEquals(gdbPType.getType(), "int"); } + + @Test + public void testInfoProgram() throws Exception { + gdb.file(file); + + GdbInfoProgram gdbInfoProgram = gdb.infoProgram(); + assertNull(gdbInfoProgram.getStoppedAddress()); + + gdb.breakpoint(4); + gdb.run(); + + gdbInfoProgram = gdb.infoProgram(); + assertNotNull(gdbInfoProgram.getStoppedAddress()); + + GdbContinue gdbContinue = gdb.cont(); + assertNull(gdbContinue.getBreakpoint()); + + gdbInfoProgram = gdb.infoProgram(); + assertNull(gdbInfoProgram.getStoppedAddress()); + } } diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLineTest.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLineTest.java index 6596d1cba3..46abc2b4a0 100644 --- a/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLineTest.java +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoLineTest.java @@ -21,7 +21,7 @@ import static org.testng.Assert.assertEquals; public class GdbInfoLineTest { @Test - public void testParse() throws Exception { + public void testParse1() throws Exception { GdbOutput gdbOutput = GdbOutput.of("Line 6 of \"h.cpp\" starts at address 0x4008ae and ends at 0x4008ca .\n"); GdbInfoLine gdbInfoLine = GdbInfoLine.parse(gdbOutput); @@ -30,4 +30,17 @@ public class GdbInfoLineTest { assertEquals(location.getClassName(), "h.cpp"); assertEquals(location.getLineNumber(), 6); } -} \ No newline at end of file + + @Test + public void testParse2() throws Exception { + GdbOutput gdbOutput = GdbOutput.of("Line 530 of \"/usr/src/debug/gcc-4.8.3-20140911/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/ostream\"\n" + + " starts at address 0x3e8ba94e60 >(std::basic_ostream >&, char const*)>\n" + + " and ends at 0x3e8ba94e6c >(std::basic_ostream >&, char const*)+12>.\n"); + + GdbInfoLine gdbInfoLine = GdbInfoLine.parse(gdbOutput); + Location location = gdbInfoLine.getLocation(); + + assertEquals(location.getClassName(), "/usr/src/debug/gcc-4.8.3-20140911/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/ostream"); + assertEquals(location.getLineNumber(), 530); + } +} diff --git a/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgramTest.java b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgramTest.java new file mode 100644 index 0000000000..75f0b8b8fb --- /dev/null +++ b/plugins/plugin-gdb/che-plugin-gdb-server/src/test/java/org/eclipse/che/ide/gdb/server/parser/GdbInfoProgramTest.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2012-2016 Codenvy, S.A. + * 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: + * Codenvy, S.A. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.ide.gdb.server.parser; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * @author Anatoliy Bazko + */ +public class GdbInfoProgramTest { + + @Test + public void testProgramIsFinished() throws Exception { + GdbOutput gdbOutput = GdbOutput.of("The program being debugged is not being run.\n"); + + GdbInfoProgram gdbInfoProgram = GdbInfoProgram.parse(gdbOutput); + assertNull(gdbInfoProgram.getStoppedAddress()); + } + + @Test + public void testProgramIsStopped() throws Exception { + GdbOutput gdbOutput = GdbOutput.of("Debugging a target over a serial line.\n" + + "Program stopped at 0x7ffff7ddb2d0.\n" + + "It stopped with signal SIGTRAP, Trace/breakpoint trap.\n"); + + GdbInfoProgram gdbInfoProgram = GdbInfoProgram.parse(gdbOutput); + assertEquals(gdbInfoProgram.getStoppedAddress(), "0x7ffff7ddb2d0"); + } +} + diff --git a/plugins/plugin-java/che-plugin-java-debugger-ide/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/JavaDebugger.java b/plugins/plugin-java/che-plugin-java-debugger-ide/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/JavaDebugger.java index 565921e577..2988a70319 100644 --- a/plugins/plugin-java/che-plugin-java-debugger-ide/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/JavaDebugger.java +++ b/plugins/plugin-java/che-plugin-java-debugger-ide/src/main/java/org/eclipse/che/ide/ext/java/jdi/client/debug/JavaDebugger.java @@ -16,10 +16,12 @@ import com.google.web.bindery.event.shared.EventBus; import org.eclipse.che.ide.api.app.AppContext; import org.eclipse.che.ide.api.app.CurrentProject; import org.eclipse.che.ide.api.filetypes.FileTypeRegistry; +import org.eclipse.che.ide.api.project.tree.VirtualFile; import org.eclipse.che.ide.debug.DebuggerDescriptor; import org.eclipse.che.ide.debug.DebuggerManager; import org.eclipse.che.ide.dto.DtoFactory; import org.eclipse.che.ide.ext.debugger.client.debug.AbstractDebugger; +import org.eclipse.che.ide.ext.debugger.client.fqn.FqnResolver; import org.eclipse.che.ide.ext.debugger.client.fqn.FqnResolverFactory; import org.eclipse.che.ide.ext.debugger.shared.Location; import org.eclipse.che.ide.ext.java.client.projecttree.JavaSourceFolderUtil; @@ -65,7 +67,7 @@ public class JavaDebugger extends AbstractDebugger { } @Override - protected List resolveFilePathByLocation(@NotNull Location location) { + protected List fqnToPath(@NotNull Location location) { CurrentProject currentProject = appContext.getCurrentProject(); if (currentProject == null) { @@ -85,6 +87,21 @@ public class JavaDebugger extends AbstractDebugger { return filePaths; } + @Override + protected String pathToFqn(VirtualFile file) { + List mimeTypes = fileTypeRegistry.getFileTypeByFile(file).getMimeTypes(); + + if (!mimeTypes.isEmpty()) { + String mediaType = mimeTypes.get(0); + FqnResolver resolver = fqnResolverFactory.getResolver(mediaType); + if (resolver != null) { + return resolver.resolveFqn(file); + } + } + + return null; + } + @Override protected DebuggerDescriptor toDescriptor(Map connectionProperties) { String address = connectionProperties.get(HOST.toString()) + ":" + connectionProperties.get(PORT.toString()); diff --git a/plugins/plugin-java/che-plugin-java-debugger-server/src/main/java/org/eclipse/che/ide/ext/java/jdi/server/DebuggerService.java b/plugins/plugin-java/che-plugin-java-debugger-server/src/main/java/org/eclipse/che/ide/ext/java/jdi/server/JavaDebuggerService.java similarity index 99% rename from plugins/plugin-java/che-plugin-java-debugger-server/src/main/java/org/eclipse/che/ide/ext/java/jdi/server/DebuggerService.java rename to plugins/plugin-java/che-plugin-java-debugger-server/src/main/java/org/eclipse/che/ide/ext/java/jdi/server/JavaDebuggerService.java index 86bbface76..1de533f21e 100644 --- a/plugins/plugin-java/che-plugin-java-debugger-server/src/main/java/org/eclipse/che/ide/ext/java/jdi/server/DebuggerService.java +++ b/plugins/plugin-java/che-plugin-java-debugger-server/src/main/java/org/eclipse/che/ide/ext/java/jdi/server/JavaDebuggerService.java @@ -34,7 +34,7 @@ import javax.ws.rs.core.MediaType; * @author andrew00x */ @Path("debug-java/{ws-id}") -public class DebuggerService { +public class JavaDebuggerService { @GET @Path("{id}")