Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/org/rascalmpl/dap/RascalDebugAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public CompletableFuture<Capabilities> initialize(InitializeRequestArguments arg
capabilities.setSupportsSetVariable(false);
capabilities.setSupportsRestartRequest(false);
capabilities.setSupportsCompletionsRequest(true);
capabilities.setSupportsConditionalBreakpoints(true);

return capabilities;
}, ownExecutor);
Expand Down Expand Up @@ -208,7 +209,12 @@ public CompletableFuture<SetBreakpointsResponse> setBreakpoints(SetBreakpointsAr
ITree treeBreakableLocation = locateBreakableTree(parseTree, breakpoint.getLine());
if(treeBreakableLocation != null) {
ISourceLocation breakableLocation = TreeAdapter.getLocation(treeBreakableLocation);
breakpointsCollection.addBreakpoint(breakableLocation, args.getSource());
if(breakpoint.getCondition() != null){
breakpointsCollection.addBreakpoint(breakableLocation, args.getSource(), breakpoint.getCondition());
}
else {
breakpointsCollection.addBreakpoint(breakableLocation, args.getSource());
}
}
Breakpoint b = new Breakpoint();
b.setId(i);
Expand Down
7 changes: 7 additions & 0 deletions src/org/rascalmpl/dap/breakpoint/BreakpointsCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ public void addBreakpoint(ISourceLocation location, Source source){
debugHandler.processMessage(DebugMessageFactory.requestSetBreakpoint(location));
}

public void addBreakpoint(ISourceLocation location, Source source, String condition){
String path = location.getPath();
BreakpointInfo breakpoint = new BreakpointInfo(breakpointIDCounter.incrementAndGet(), source);
breakpoints.computeIfAbsent(path, k -> new HashMap<>()).put(location, breakpoint);
debugHandler.processMessage(DebugMessageFactory.requestSetConditionalBreakpoint(location, condition));
}

public int getBreakpointID(ISourceLocation location){
String path = location.getPath();
Map<ISourceLocation, BreakpointInfo> fileBreakpoints = breakpoints.get(path);
Expand Down
48 changes: 37 additions & 11 deletions src/org/rascalmpl/debug/DebugHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import static org.rascalmpl.debug.AbstractInterpreterEventTrigger.newNullEventTrigger;

import java.util.Set;
import java.util.Map;
import java.util.function.IntSupplier;

import org.rascalmpl.ast.AbstractAST;
Expand All @@ -27,15 +27,12 @@
import org.rascalmpl.interpreter.control_exceptions.InterruptException;
import org.rascalmpl.interpreter.control_exceptions.QuitException;
import org.rascalmpl.interpreter.env.Environment;
import org.rascalmpl.interpreter.env.Pair;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.repl.output.ICommandOutput;
import org.rascalmpl.repl.rascal.RascalValuePrinter;
import org.rascalmpl.values.functions.IFunction;
import java.util.function.Function;
import org.rascalmpl.semantics.dynamic.Statement.For;
import org.rascalmpl.semantics.dynamic.Statement.Switch;
import org.rascalmpl.semantics.dynamic.Statement.Visit;
import org.rascalmpl.semantics.dynamic.Statement.While;
import org.rascalmpl.exceptions.RascalStackOverflowError;
import org.rascalmpl.interpreter.staticErrors.StaticError;
import org.rascalmpl.exceptions.Throw;
Expand All @@ -56,7 +53,7 @@ public final class DebugHandler implements IDebugHandler, IRascalRuntimeEvaluati

private static final ISourceLocation DEBUGGER_PROMPT_LOCATION = URIUtil.rootLocation("debugger");

private final Set<ISourceLocation> breakpoints = new java.util.HashSet<>();
private final Map<ISourceLocation, String> breakpoints = new java.util.HashMap<>();

/**
* Indicates a manual suspend request from the debugger, e.g. caused by a pause action in the GUI.
Expand Down Expand Up @@ -106,11 +103,31 @@ public DebugHandler() {
}

private boolean hasBreakpoint(ISourceLocation b) {
return breakpoints.contains(b);
if(!breakpoints.containsKey(b)) {
return false;
}
if(breakpoints.get(b) == null) {
return true;
}
setSuspended(true);

try {
Result<IValue> condResult = this.evaluate(breakpoints.get(b), (Environment) evaluator.getCurrentStack().lastElement()).result;
setSuspended(false);
return condResult.isTrue();
}
catch (Throwable e) {
setSuspended(false);
return false;
}
}

private void addBreakpoint(ISourceLocation breakpointLocation) {
breakpoints.add(breakpointLocation);
breakpoints.put(breakpointLocation, null);
}

private void addBreakpoint(ISourceLocation breakpointLocation, String condition) {
breakpoints.put(breakpointLocation, condition);
}

private void removeBreakpoint(ISourceLocation breakpointLocation) {
Expand Down Expand Up @@ -278,6 +295,7 @@ protected Function<IValue, IValue> liftProviderFunction(IFunction func) {
// Save old state
AbstractInterpreterEventTrigger oldTrigger = evaluator.getEventTrigger();
Environment oldEnvironment = evaluator.getCurrentEnvt();
AbstractAST oldAST = evaluator.getCurrentAST();
try {
// disable suspend triggers while evaluating expressions from the debugger
evaluator.removeSuspendTriggerListener(this);
Expand Down Expand Up @@ -341,6 +359,7 @@ protected Function<IValue, IValue> liftProviderFunction(IFunction func) {
evaluator.setCurrentEnvt(oldEnvironment);
evaluator.setEventTrigger(oldTrigger);
evaluator.addSuspendTriggerListener(this);
evaluator.setCurrentAST(oldAST);
}
}
}
Expand All @@ -367,14 +386,21 @@ public void processMessage(IDebugMessage message) {
switch (message.getSubject()) {

case BREAKPOINT:
ISourceLocation breakpointLocation = (ISourceLocation) message.getPayload();

switch (message.getAction()) {
case SET:
addBreakpoint(breakpointLocation);
switch (message.getDetail()) {
case CONDITIONAL:
Pair<ISourceLocation, String> payload = (Pair<ISourceLocation, String>) message.getPayload();
addBreakpoint(payload.getFirst(), payload.getSecond());
break;
case UNKNOWN:
ISourceLocation breakpointLocation = (ISourceLocation) message.getPayload();
addBreakpoint(breakpointLocation);
}
break;

case DELETE:
ISourceLocation breakpointLocation = (ISourceLocation) message.getPayload();
removeBreakpoint(breakpointLocation);
break;
}
Expand Down
6 changes: 6 additions & 0 deletions src/org/rascalmpl/debug/DebugMessageFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
*******************************************************************************/
package org.rascalmpl.debug;

import org.rascalmpl.interpreter.env.Pair;

import io.usethesource.vallang.ISourceLocation;

/**
Expand Down Expand Up @@ -53,6 +55,10 @@ public static IDebugMessage requestSetBreakpoint(ISourceLocation location) {
return new DebugMessage(IDebugMessage.Action.SET, IDebugMessage.Subject.BREAKPOINT, IDebugMessage.Detail.UNKNOWN, location);
}

public static IDebugMessage requestSetConditionalBreakpoint(ISourceLocation location, String condition) {
return new DebugMessage(IDebugMessage.Action.SET, IDebugMessage.Subject.BREAKPOINT, IDebugMessage.Detail.CONDITIONAL, new Pair<ISourceLocation, String>(location, condition));
}

public static IDebugMessage requestDeleteBreakpoint(ISourceLocation location) {
return new DebugMessage(IDebugMessage.Action.DELETE, IDebugMessage.Subject.BREAKPOINT, IDebugMessage.Detail.UNKNOWN, location);
}
Expand Down
7 changes: 6 additions & 1 deletion src/org/rascalmpl/debug/IDebugMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ enum Detail {
* Indicates a continuation of the execution, caused by a step out
* request.
*/
STEP_OUT
STEP_OUT,

/**
* Indicates a conditional breakpoint.
*/
CONDITIONAL
}

Action getAction();
Expand Down
Loading