Properly report breakpoint hit event

This commit is contained in:
Alexey Andreev 2017-07-04 06:37:17 +03:00
parent b5fcd22a39
commit 1581345e17
8 changed files with 70 additions and 29 deletions

View File

@ -432,10 +432,14 @@ public class Debugger {
}
@Override
public void paused() {
public void paused(JavaScriptBreakpoint breakpoint) {
callStack = null;
Breakpoint javaBreakpoint = null;
if (breakpoint != null && !temporaryBreakpoints.contains(breakpoint)) {
javaBreakpoint = breakpointMap.get(breakpoint);
}
for (DebuggerListener listener : getListeners()) {
listener.paused();
listener.paused(javaBreakpoint);
}
}

View File

@ -18,7 +18,7 @@ package org.teavm.debugging;
public interface DebuggerListener {
void resumed();
void paused();
void paused(Breakpoint breakpoint);
void breakpointStatusChanged(Breakpoint breakpoint);

View File

@ -16,7 +16,7 @@
package org.teavm.debugging.javascript;
public interface JavaScriptDebuggerListener {
void paused();
void paused(JavaScriptBreakpoint breakpoint);
void resumed();

View File

@ -64,6 +64,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
private ConcurrentMap<JavaScriptDebuggerListener, Object> listeners = new ConcurrentHashMap<>();
private ConcurrentMap<JavaScriptLocation, RDPBreakpoint> breakpointLocationMap = new ConcurrentHashMap<>();
private ConcurrentMap<RDPBreakpoint, Object> breakpoints = new ConcurrentHashMap<>();
private ConcurrentMap<String, RDPBreakpoint> breakpointsByChromeId = new ConcurrentHashMap<>();
private volatile RDPCallFrame[] callStack = new RDPCallFrame[0];
private ConcurrentMap<String, String> scripts = new ConcurrentHashMap<>();
private ConcurrentMap<String, String> scriptIds = new ConcurrentHashMap<>();
@ -106,7 +107,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
}
}
private ChromeRDPExchangeListener exchangeListener = messageText -> receiveMessage(messageText);
private ChromeRDPExchangeListener exchangeListener = this::receiveMessage;
private void receiveMessage(final String messageText) {
new Thread(() -> {
@ -160,8 +161,14 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
callStack[i] = map(callFrameDTOs[i]);
}
this.callStack = callStack;
RDPBreakpoint breakpoint = null;
if (params.getHitBreakpoints() != null && !params.getHitBreakpoints().isEmpty()) {
breakpoint = breakpointsByChromeId.get(params.getHitBreakpoints().get(0));
}
for (JavaScriptDebuggerListener listener : getListeners()) {
listener.paused();
listener.paused(breakpoint);
}
}
@ -316,6 +323,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
breakpointLocationMap.remove(breakpoint.getLocation());
breakpoints.remove(breakpoint);
if (breakpoint.chromeId != null) {
breakpointsByChromeId.remove(breakpoint.chromeId);
if (logger.isInfoEnabled()) {
logger.info("Removing breakpoint at {}", breakpoint.getLocation());
}
@ -333,13 +341,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
}
}
void fireScriptAdded(String script) {
for (JavaScriptDebuggerListener listener : getListeners()) {
listener.scriptAdded(script);
}
}
void updateBreakpoint(final RDPBreakpoint breakpoint) {
private void updateBreakpoint(final RDPBreakpoint breakpoint) {
if (exchange == null || breakpoint.chromeId != null) {
return;
}
@ -353,9 +355,15 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
logger.info("Setting breakpoint at {}, message id is ", breakpoint.getLocation(), message.getId());
}
setResponseHandler(message.getId(), (node, out) -> {
if (breakpoint.chromeId != null) {
breakpointsByChromeId.remove(breakpoint.chromeId);
}
if (node != null) {
SetBreakpointResponse response = mapper.reader(SetBreakpointResponse.class).readValue(node);
breakpoint.chromeId = response.getBreakpointId();
if (breakpoint.chromeId != null) {
breakpointsByChromeId.put(breakpoint.chromeId, breakpoint);
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("Error setting breakpoint at {}, message id is {}",
@ -468,10 +476,10 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
}
}
private static class RepresentationWrapper {
static class RepresentationWrapper {
String repr;
public RepresentationWrapper(String repr) {
RepresentationWrapper(String repr) {
super();
this.repr = repr;
}
@ -523,7 +531,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
}
}
RDPCallFrame map(CallFrameDTO dto) {
private RDPCallFrame map(CallFrameDTO dto) {
String scopeId = null;
RDPValue thisObject = null;
RDPValue closure = null;
@ -546,11 +554,11 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
thisObject, closure);
}
JavaScriptLocation map(LocationDTO dto) {
private JavaScriptLocation map(LocationDTO dto) {
return new JavaScriptLocation(scripts.get(dto.getScriptId()), dto.getLineNumber(), dto.getColumnNumber());
}
LocationDTO unmap(JavaScriptLocation location) {
private LocationDTO unmap(JavaScriptLocation location) {
LocationDTO dto = new LocationDTO();
dto.setScriptId(scriptIds.get(location.getScript()));
dto.setLineNumber(location.getLine());

View File

@ -67,12 +67,15 @@ public final class ChromeRDPRunner {
}
@Override
public void paused() {
public void paused(Breakpoint breakpoint) {
CallFrame[] stack = debugger.getCallStack();
if (stack.length > 0) {
System.out.println();
System.out.println("Suspended at " + stack[0].getLocation());
}
if (breakpoint != null) {
System.out.println("Breakpoint #" + breakpointIds.get(breakpoint) + " hit");
}
currentFrame = 0;
if (suspendListener != null) {
suspendListener.run();

View File

@ -15,6 +15,7 @@
*/
package org.teavm.chromerdp.messages;
import java.util.List;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.teavm.chromerdp.data.CallFrameDTO;
@ -24,6 +25,7 @@ public class SuspendedNotification {
private CallFrameDTO[] callFrames;
private String reason;
private JsonNode data;
private List<String> hitBreakpoints;
public CallFrameDTO[] getCallFrames() {
return callFrames;
@ -48,4 +50,12 @@ public class SuspendedNotification {
public void setData(JsonNode data) {
this.data = data;
}
public List<String> getHitBreakpoints() {
return hitBreakpoints;
}
public void setHitBreakpoints(List<String> hitBreakpoints) {
this.hitBreakpoints = hitBreakpoints;
}
}

View File

@ -22,11 +22,16 @@ import com.intellij.openapi.util.Key;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XBreakpointHandler;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XSuspendContext;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.teavm.chromerdp.ChromeRDPDebugger;
import org.teavm.chromerdp.ChromeRDPServer;
import org.teavm.debugging.Breakpoint;
@ -41,6 +46,7 @@ public class TeaVMDebugProcess extends XDebugProcess {
private final List<TeaVMLineBreakpointHandler<?>> breakpointHandlers = new ArrayList<>();
private final int port;
private ChromeRDPServer debugServer;
ConcurrentMap<Breakpoint, XBreakpoint<?>> breakpointMap = new ConcurrentHashMap<>();
public TeaVMDebugProcess(@NotNull XDebugSession session, int port) {
super(session);
@ -52,8 +58,14 @@ public class TeaVMDebugProcess extends XDebugProcess {
}
@Override
public void paused() {
handlePaused();
public void paused(Breakpoint breakpoint) {
XBreakpoint<?> xBreakpoint = breakpoint != null ? breakpointMap.get(breakpoint) : null;
if (xBreakpoint != null) {
getSession().breakpointReached(xBreakpoint, null,
new TeaVMSuspendContext(innerDebugger, getSession().getProject()));
} else {
handlePaused();
}
}
@Override
@ -70,14 +82,14 @@ public class TeaVMDebugProcess extends XDebugProcess {
});
breakpointHandlers.add(new TeaVMLineBreakpointHandler<>(JavaLineBreakpointType.class, session.getProject(),
innerDebugger));
innerDebugger, this));
ExtensionPoint<TeaVMBreakpointProvider<?>> breakpointProvider = Extensions.getArea(
session.getProject()).getExtensionPoint("org.teavm.extensions.breakpointProvider");
if (breakpointProvider != null) {
for (TeaVMBreakpointProvider<?> provider : breakpointProvider.getExtensions()) {
breakpointHandlers.add(new TeaVMLineBreakpointHandler<>(provider.getBreakpointType(),
session.getProject(), innerDebugger));
session.getProject(), innerDebugger, this));
}
}
}
@ -100,22 +112,22 @@ public class TeaVMDebugProcess extends XDebugProcess {
}
@Override
public void startStepOver() {
public void startStepOver(@Nullable XSuspendContext context) {
innerDebugger.stepOver();
}
@Override
public void startStepInto() {
public void startStepInto(@Nullable XSuspendContext context) {
innerDebugger.stepInto();
}
@Override
public void startStepOut() {
public void startStepOut(@Nullable XSuspendContext context) {
innerDebugger.stepOut();
}
@Override
public void resume() {
public void resume(@Nullable XSuspendContext context) {
innerDebugger.resume();
}
@ -125,7 +137,7 @@ public class TeaVMDebugProcess extends XDebugProcess {
}
@Override
public void runToPosition(@NotNull XSourcePosition position) {
public void runToPosition(@NotNull XSourcePosition position, @Nullable XSuspendContext context) {
innerDebugger.continueToLocation(position.getFile().getPath(), position.getLine());
}

View File

@ -36,14 +36,16 @@ public class TeaVMLineBreakpointHandler<B extends XLineBreakpoint<?>> extends XB
private Debugger innerDebugger;
private VirtualFileManager vfs;
private ProjectFileIndex fileIndex;
private TeaVMDebugProcess debugProcess;
@SuppressWarnings("unchecked")
public TeaVMLineBreakpointHandler(Class<? extends XBreakpointType<B, ?>> breakpointType,
Project project, Debugger innerDebugger) {
Project project, Debugger innerDebugger, TeaVMDebugProcess debugProcess) {
super(breakpointType);
this.innerDebugger = innerDebugger;
vfs = VirtualFileManager.getInstance();
fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
this.debugProcess = debugProcess;
}
@Override
@ -63,6 +65,7 @@ public class TeaVMLineBreakpointHandler<B extends XLineBreakpoint<?>> extends XB
Breakpoint innerBreakpoint = innerDebugger.createBreakpoint(path, breakpoint.getLine() + 1);
breakpoint.putUserData(TeaVMDebugProcess.INNER_BREAKPOINT_KEY, innerBreakpoint);
debugProcess.breakpointMap.put(innerBreakpoint, breakpoint);
}
@Nullable
@ -86,6 +89,7 @@ public class TeaVMLineBreakpointHandler<B extends XLineBreakpoint<?>> extends XB
if (innerBreakpoint != null) {
breakpoint.putUserData(TeaVMDebugProcess.INNER_BREAKPOINT_KEY, null);
innerBreakpoint.destroy();
debugProcess.breakpointMap.remove(innerBreakpoint);
}
}
}