Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ant.AntLaunchConfigurationType">
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/org.eclipse.epsilon.examples.eol.dap/build.xml"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.epsilon.examples.eol.dap"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_ANT_TARGETS" value="09-validate,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/org.eclipse.epsilon.examples.eol.dap/build.xml}"/>
<stringAttribute key="process_factory_id" value="org.eclipse.ant.ui.remoteAntProcessFactory"/>
</launchConfiguration>
13 changes: 13 additions & 0 deletions examples/org.eclipse.epsilon.examples.eol.dap/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@
<epsilon.disposeModel model="M" />
</target>

<target name="09-validate">
<epsilon.emf.loadModel name="M"
metamodelfile="epsilon/models/person.ecore"
modelfile="epsilon/models/invalidPerson.model"
read="true" store="true" />

<epsilon.evl src="epsilon/09-validate.evl" debug="true" debugPort="4040" failOnErrors="false" fix="true">
<model ref="M"/>
</epsilon.evl>

<epsilon.disposeModel model="M" />
</target>

<target name="start-server">
<epsilon.startDebugServer />
</target>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
context Person {
constraint HasFirstName {
check: self.firstName.isDefined()
message: 'Missing first name'
}
constraint HasLastName {
guard: self.firstName.isDefined()
check: self.lastName.isDefined()
message: 'Missing last name for ' + self.firstName
fix {
guard: true
title: 'Add placeholder last name'
do {
var newLastName = 'Unknown';
self.lastName = newLastName;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="ASCII"?>
<Model xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="http://eclipse.org/epsilon/examples/person" xmi:id="_q24fMEVLEfCmEN4rtoP3hA">
<people xmi:id="_rWjdwEVLEfCmEN4rtoP3hA" firstName="John" lastName=""/>
</Model>
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ protected boolean deleteElementInModel(Object instance) throws EolRuntimeExcepti

@Override
public boolean owns(Object instance) {
if (instance instanceof EObject) {
if (instance instanceof EObject && modelImpl != null) {
EObject eObject = (EObject) instance;
Resource eObjectResource = eObject.eResource();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.eclipse.epsilon.eol.execute.context.FrameType;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.context.SingleFrame;
import org.eclipse.epsilon.eol.execute.control.ExecutionController;
import org.eclipse.epsilon.eol.execute.control.IExecutionListener;
import org.eclipse.lsp4j.debug.Breakpoint;
import org.eclipse.lsp4j.debug.BreakpointEventArguments;
Expand Down Expand Up @@ -127,21 +128,25 @@ public class EpsilonDebugAdapter implements IDebugProtocolServer {
* be propagated across all scripts being launched (e.g. from EGX to EGL scripts).
*/
protected class ModuleCompletionListener implements IExecutionListener {
private ModuleElement topElement;
private IEolModule topModule;
private final Set<ModuleElement> runningRoots = new HashSet<>();

@Override
public void aboutToExecute(ModuleElement ast, IEolContext context) {
if (ast.getParent() == null) {
if (ast.getParent() == null || runningRoots.isEmpty()) {
runningRoots.add(ast);

if (topElement == null) {
IEolModule module = getModule(ast);
if (topModule == null && module != null) {
/*
* The very first node we will run is assumed to be the "top" element of our
* program. When this completes, the program will be assumed to have completed
* its execution.
* The very first module we will run is assumed to be the "main" module of our
* program. When this is considered "done", the debugging session will be considered
* completed.
*/
topElement = ast;
topModule = module;
while (topModule.getParentModule() != null) {
topModule = topModule.getParentModule();
}
}

/*
Expand All @@ -159,48 +164,48 @@ public void aboutToExecute(ModuleElement ast, IEolContext context) {
}
}

if (ast instanceof IEolModule) {
ThreadState threadState = attachTo((IEolModule) ast);
if (ast.getModule() instanceof IEolModule) {
ThreadState threadState = attachTo(module);
sendThreadEvent(threadState.getThreadId(), ThreadEventArgumentsReason.STARTED);
}
}
}

protected IEolModule getModule(ModuleElement ast) {
if (ast instanceof IEolModule) {
return (IEolModule) ast;
} else if (ast.getModule() instanceof IEolModule) {
return (IEolModule) ast.getModule();
}
return null;
}

@Override
public void finishedExecuting(ModuleElement ast, Object result, IEolContext context) {
if (ast.getParent() == null) {
runningRoots.remove(ast);
if (ast instanceof IEolModule) {
final IEolModule eolModule = (IEolModule) ast;
eolModule.getContext().getOutputStream().flush();
eolModule.getContext().getErrorStream().flush();
removeThreadFor((IEolModule) ast);
}
}
if (ast == topElement) {
sendTerminated();
sendExited(0);
topElement = null;
}
finishedExecutingWithException(ast, null, context);
}

@Override
public void finishedExecutingWithException(ModuleElement ast, EolRuntimeException exception, IEolContext context) {
if (ast.getParent() == null && ast instanceof IEolModule) {
final IEolModule eolModule = (IEolModule) ast;
IEolModule module = getModule(ast);
if (runningRoots.remove(ast) && module != null) {
module.getContext().getOutputStream().flush();
module.getContext().getErrorStream().flush();
removeThreadFor(module);

if (topModule != null && ast == topModule) {
if (exception != null) {
// Report the exception that was propagated to the top module
topModule.getContext().getErrorStream().println(exception.toString());
}

eolModule.getContext().getOutputStream().flush();
eolModule.getContext().getErrorStream().flush();
removeThreadFor(eolModule);
}
if (ast == topElement) {
if (ast instanceof IEolModule) {
// Report the exception that was propagated to the top module
((IEolModule) ast).getContext().getErrorStream().println(exception.toString());
ExecutionController execController = topModule.getContext().getExecutorFactory().getExecutionController();
if (execController instanceof IEolDebugger && ((IEolDebugger) execController).isDoneAfterModuleElement(ast)) {
sendTerminated();
sendExited(exception == null ? 0 : 1);
topModule = null;
}
}
sendTerminated();
sendExited(1);
topElement = null;
}
}

Expand Down Expand Up @@ -597,6 +602,8 @@ public CompletableFuture<Capabilities> initialize(InitializeRequestArguments arg
Capabilities caps = new Capabilities();
caps.setSupportsTerminateRequest(true);
caps.setSupportsConditionalBreakpoints(true);
caps.setSupportTerminateDebuggee(true);
caps.setSupportSuspendDebuggee(true);
return caps;
});
}
Expand Down Expand Up @@ -803,15 +810,29 @@ public CompletableFuture<Void> terminate(TerminateArguments args) {
return CompletableFuture.runAsync(() -> {
this.isTerminated = true;
resumeAllThreads();
sendTerminated();
sendExited(2);
});
}

@Override
public CompletableFuture<Void> disconnect(DisconnectArguments args) {
return CompletableFuture.runAsync(() -> {
this.isTerminated = true;
if (args.getTerminateDebuggee() == Boolean.TRUE) {
this.isTerminated = true;
resumeAllThreads();
sendTerminated();
sendExited(2);
} else if (args.getSuspendDebuggee() != Boolean.TRUE) {
lineBreakpointsByPath.clear();
synchronized (threads) {
for (ThreadState thread : threads.values()) {
thread.lineBreakpointsByURI.clear();
}
}
resumeAllThreads();
}
this.client = null;
resumeAllThreads();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ public void control(ModuleElement ast, IEolContext context) {
} catch (InterruptedException ex) {
ex.printStackTrace();
}

if (isTerminated()) return;
}

@Override
Expand Down Expand Up @@ -137,6 +135,12 @@ public void stepReturn() {
stopAfterFrameStackSizeDropsBelow = frameStackSize();
}

@Override
public boolean isDoneAfterModuleElement(ModuleElement ast) {
// Default behaviour: execution is done after running the module
return ast == getModule();
}

private boolean controls(ModuleElement ast) {
// Top level element or block
if (ast.getParent() == null || ast instanceof StatementBlock) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ public interface IEolDebugger extends ExecutionController {

Integer getStopAfterFrameStackSizeDropsBelow();

/**
* Returns true iff the execution will complete after the
* given module element completes (i.e. no further elements
* will be run from this execution).
*/
boolean isDoneAfterModuleElement(ModuleElement ast);
}
Loading
Loading