CODENVY-257: GDB (#1016)
parent
1bb4896c47
commit
66173e07f1
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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<DebuggerObserver> 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<DebuggerEventList> 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<VirtualFile>() {
|
||||
|
|
@ -249,7 +250,7 @@ public abstract class AbstractDebugger implements Debugger, DebuggerObservable {
|
|||
* <li>etc</li>
|
||||
*/
|
||||
private void onBreakpointActivated(Location location) {
|
||||
List<String> filePaths = resolveFilePathByLocation(location);
|
||||
List<String> 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<Void> promise = connect.then(new Function<DebuggerInfo, Void>() {
|
||||
@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<PromiseError>() {
|
||||
|
|
@ -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<PromiseError>() {
|
||||
@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<String> resolveFilePathByLocation(@NotNull Location location);
|
||||
abstract protected List<String> fqnToPath(@NotNull Location location);
|
||||
|
||||
/**
|
||||
* Transforms file path to FQN>
|
||||
*/
|
||||
@Nullable
|
||||
abstract protected String pathToFqn(VirtualFile file);
|
||||
|
||||
abstract protected DebuggerDescriptor toDescriptor(Map<String, String> connectionProperties);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<DebuggerVariable> debuggerVariables = getDebuggerVariables(variables);
|
||||
|
||||
view.setVariables(debuggerVariables);
|
||||
if (!debuggerVariables.isEmpty()) {
|
||||
view.setExecutionPoint(variables.get(0).isExistInformation(), executionPoint);
|
||||
}
|
||||
|
||||
DebuggerPresenter.this.variables = debuggerVariables;
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
|
|
|
|||
|
|
@ -45,12 +45,10 @@ public interface DebuggerView extends View<DebuggerView.ActionDelegate> {
|
|||
/**
|
||||
* 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.
|
||||
|
|
|
|||
|
|
@ -209,17 +209,12 @@ public class DebuggerViewImpl extends BaseView<DebuggerView.ActionDelegate> 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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ################
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<String, String> 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<String> resolveFilePathByLocation(@NotNull Location location) {
|
||||
protected List<String> fqnToPath(@NotNull Location location) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String pathToFqn(VirtualFile file) {
|
||||
return FQN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DebuggerDescriptor toDescriptor(Map<String, String> connectionProperties) {
|
||||
return debuggerDescriptor;
|
||||
|
|
|
|||
|
|
@ -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<String> resolveFilePathByLocation(@NotNull Location location) {
|
||||
Collections.singleton(location.getClassName());
|
||||
return Collections.singletonList(location.getClassName());
|
||||
protected List<String> 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<String, String> 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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<DebuggerInfo> connect(@NotNull Map<String, String> 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));
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import java.util.Map;
|
|||
@Singleton
|
||||
public class GdbConfigurationPagePresenter implements GdbConfigurationPageView.ActionDelegate, DebugConfigurationPage<DebugConfiguration> {
|
||||
|
||||
public static final String BIN_PATH_CONNECTION_PROPERTY = "binary-path";
|
||||
public static final String BIN_PATH_CONNECTION_PROPERTY = "BINARY";
|
||||
|
||||
private final GdbConfigurationPageView view;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<Variable> variables = new ArrayList<>();
|
||||
for (Map.Entry<String, String> 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <main()+17> and ends at 0x4008ca <main()+45>.\n");
|
||||
|
||||
GdbInfoLine gdbInfoLine = GdbInfoLine.parse(gdbOutput);
|
||||
|
|
@ -30,4 +30,17 @@ public class GdbInfoLineTest {
|
|||
assertEquals(location.getClassName(), "h.cpp");
|
||||
assertEquals(location.getLineNumber(), 6);
|
||||
}
|
||||
}
|
||||
|
||||
@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::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>\n" +
|
||||
" and ends at 0x3e8ba94e6c <std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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<String> resolveFilePathByLocation(@NotNull Location location) {
|
||||
protected List<String> 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<String> 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<String, String> connectionProperties) {
|
||||
String address = connectionProperties.get(HOST.toString()) + ":" + connectionProperties.get(PORT.toString());
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
Loading…
Reference in New Issue