Search in sources :

Example 6 with ISlapResponse

use of nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse in project magik-tools by StevenLooman.

the class ThreadManager method stackTrace.

/**
 * Get a stack trace for a given thread.
 * @param threadId Thread ID.
 * @return StackFrames for thread.
 * @throws IOException -
 * @throws InterruptedException -
 * @throws ExecutionException -
 */
List<StackFrame> stackTrace(final long threadId) throws IOException, InterruptedException, ExecutionException {
    final CompletableFuture<ISlapResponse> threadStackFuture = this.slapProtocol.getThreadStack(threadId);
    final ThreadStackResponse threadStack = (ThreadStackResponse) threadStackFuture.get();
    // Do conversion here due to filtering on language + getting source,
    // instead of Lsp4jConversion.
    final List<StackFrame> stackFrames = new ArrayList<>();
    for (final ThreadStackResponse.StackElement stackElement : threadStack.getStackFrames()) {
        if (!stackElement.getLanguage().equals(LANGUAGE_MAGIK) || stackElement.getName().equals(UNKNOWN_EXEMPLAR_UNKNOWN_METHOD) || stackElement.getName().equals(LOOPBODY)) {
            continue;
        }
        Path path = null;
        try {
            String method = stackElement.getName();
            if (!method.equals(UNNAMED_PROC)) {
                final int indexDot = method.indexOf(".");
                final int indexBracket = method.indexOf("[");
                final int index = indexDot != -1 ? indexDot + 1 : indexBracket;
                if (!method.contains(":") && index != -1) {
                    // Do some extra work to determine package.
                    final int level = stackElement.getLevel();
                    final String methodName = ":|" + method.substring(index) + "|";
                    final String expr = String.format(EVAL_EXEMPLAR_PACKAGE, methodName);
                    LOGGER.debug("Eval expression: {}", expr);
                    final EvalResponse eval = (EvalResponse) this.slapProtocol.evaluate(threadId, level, expr).get();
                    method = eval.getResult() + ":" + method;
                    // Bonus: update exemplar name with package.
                    stackElement.setName(method);
                }
                // Clear any spaces (before `<<`/`^<<`). Lazy approach...
                method = method.replace(" ", "");
                // Get source file for method.
                final CompletableFuture<ISlapResponse> sourceFileFuture = this.slapProtocol.getSourceFile(method);
                final SourceFileResponse sourceFile = (SourceFileResponse) sourceFileFuture.get();
                final String filename = sourceFile.getFilename();
                path = Path.of(filename);
            }
        } catch (ExecutionException exception) {
            final Throwable cause = exception.getCause();
            if (cause instanceof SlapErrorException && ((SlapErrorException) cause).getError().getErrorMessage() != ErrorMessage.METHOD_NOT_FOUND) {
                throw exception;
            }
        }
        // This sets the frameId to the given stack frames.
        final StackFrame stackFrame = Lsp4jConversion.toLsp4j(threadId, stackElement, path);
        stackFrames.add(stackFrame);
    }
    return stackFrames;
}
Also used : Path(java.nio.file.Path) ThreadStackResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.ThreadStackResponse) ArrayList(java.util.ArrayList) EvalResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.EvalResponse) SourceFileResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.SourceFileResponse) ISlapResponse(nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse) StackFrame(org.eclipse.lsp4j.debug.StackFrame) SlapErrorException(nl.ramsolutions.sw.magik.debugadapter.slap.SlapErrorException) ExecutionException(java.util.concurrent.ExecutionException)

Example 7 with ISlapResponse

use of nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse in project magik-tools by StevenLooman.

the class ThreadManager method threads.

/**
 * Get the Thread currently active.
 * @return {{Thread}}s
 * @throws IOException -
 * @throws InterruptedException -
 * @throws ExecutionException -
 */
List<Thread> threads() throws IOException, InterruptedException, ExecutionException {
    // Get all thread IDs.
    final CompletableFuture<ISlapResponse> futureThreadList = this.slapProtocol.getThreadList();
    final ThreadListResponse threadList = (ThreadListResponse) futureThreadList.get();
    // Get all thread info for each received thread ID.
    final List<Thread> threads = new ArrayList<>();
    for (long threadId : threadList.getThreadIds()) {
        final CompletableFuture<ISlapResponse> threadInfoFuture = this.slapProtocol.getThreadInfo(threadId);
        try {
            final ThreadInfoResponse threadInfo = (ThreadInfoResponse) threadInfoFuture.get();
            LOGGER.trace("Got thread, id: {}, thread info: {}", threadId, threadInfo);
            final Thread thread = Lsp4jConversion.toLsp4j(threadId, threadInfo);
            threads.add(thread);
        } catch (ExecutionException exception) {
            LOGGER.trace("Exception while getting thread, id: {}, exception: {}", threadId, exception.getMessage());
            final Throwable cause = exception.getCause();
            if (!(cause instanceof SlapErrorException && ((SlapErrorException) cause).getError().getErrorMessage() == ErrorMessage.UNKNOWN_ERROR)) {
                throw exception;
            }
        }
    }
    return threads;
}
Also used : ThreadInfoResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.ThreadInfoResponse) ThreadListResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.ThreadListResponse) ISlapResponse(nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse) ArrayList(java.util.ArrayList) SlapErrorException(nl.ramsolutions.sw.magik.debugadapter.slap.SlapErrorException) ExecutionException(java.util.concurrent.ExecutionException) Thread(org.eclipse.lsp4j.debug.Thread)

Example 8 with ISlapResponse

use of nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse in project magik-tools by StevenLooman.

the class BreakpointManager method sendSetBreakpoint.

private MagikBreakpoint sendSetBreakpoint(final String method, final int line) throws IOException, InterruptedException, ExecutionException {
    LOGGER.trace("Send set breakpoint: method: {}, line: {}", method, line);
    final MagikBreakpoint magikBreakpoint = new MagikBreakpoint(method, line);
    try {
        final CompletableFuture<ISlapResponse> breakpointSetFuture = this.slapProtocol.setBreakpoint(method, line);
        final BreakpointSetResponse breakpointSet = (BreakpointSetResponse) breakpointSetFuture.get();
        final long breakpointId = breakpointSet.getBreakpointId();
        magikBreakpoint.setBreakpointId(breakpointId);
    } catch (ExecutionException exception) {
        final Throwable cause = exception.getCause();
        if (cause instanceof SlapErrorException) {
            // Do nothing, verified will become false, error will be shown to user.
            final SlapErrorException slapErrorException = (SlapErrorException) cause;
            final String message = slapErrorException.getError().getErrorMessage().name();
            magikBreakpoint.setMessage(message);
        } else {
            throw exception;
        }
    }
    LOGGER.trace("Created breakpoint: {}", magikBreakpoint);
    return magikBreakpoint;
}
Also used : ISlapResponse(nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse) BreakpointSetResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.BreakpointSetResponse) SlapErrorException(nl.ramsolutions.sw.magik.debugadapter.slap.SlapErrorException) ExecutionException(java.util.concurrent.ExecutionException)

Example 9 with ISlapResponse

use of nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse in project magik-tools by StevenLooman.

the class BreakpointManagerTest method testAddBreakpointMethodNotFound.

@Test
void testAddBreakpointMethodNotFound() throws IOException, InterruptedException, ExecutionException {
    final TestSlapProtocol slapProtocol = new TestSlapProtocol() {

        @Override
        public CompletableFuture<ISlapResponse> setBreakpoint(String method, int line) {
            final ErrorResponse errorResponse = new ErrorResponse(RequestType.BREAKPOINT_SET, ErrorMessage.METHOD_NOT_FOUND);
            final SlapErrorException exception = new SlapErrorException(errorResponse);
            final CompletableFuture<ISlapResponse> future = new CompletableFuture<>();
            future.completeExceptionally(exception);
            return future;
        }
    };
    final BreakpointManager manager = new BreakpointManager(slapProtocol, null);
    final SourceBreakpoint sourceBreakpoint = new SourceBreakpoint();
    sourceBreakpoint.setLine(18);
    final Source source = new Source();
    source.setPath(getPath("magik-debug-adapter/src/test/resources/bpt.magik").toString());
    final BreakpointManager.MagikBreakpoint breakpoint = manager.addBreakpoint(source, sourceBreakpoint);
    assertThat(breakpoint.getMethodName()).isEqualTo("user:bpt.t()");
    assertThat(breakpoint.getMethodLine()).isEqualTo(18);
    assertThat(breakpoint.getCondition()).isNull();
    assertThat(breakpoint.getMessage()).isEqualTo("METHOD_NOT_FOUND");
    assertThat(breakpoint.getBreakpointId()).isEqualTo(ISlapProtocol.INVALID_BREAKPOINT_ID);
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) ISlapResponse(nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse) SlapErrorException(nl.ramsolutions.sw.magik.debugadapter.slap.SlapErrorException) SourceBreakpoint(org.eclipse.lsp4j.debug.SourceBreakpoint) Source(org.eclipse.lsp4j.debug.Source) ErrorResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.ErrorResponse) Test(org.junit.jupiter.api.Test)

Example 10 with ISlapResponse

use of nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse in project magik-tools by StevenLooman.

the class ThreadManagerTest method testStackTrace.

@Test
void testStackTrace() throws IOException, InterruptedException, ExecutionException {
    final TestSlapProtocol slapProtocol = new TestSlapProtocol() {

        @Override
        public CompletableFuture<ISlapResponse> getThreadStack(long threadId) throws IOException {
            final ThreadStackResponse response = new ThreadStackResponse(List.of(new ThreadStackResponse.StackElement(0, 0, "object.m1()", "Magik"), new ThreadStackResponse.StackElement(1, 100, "java/lang/Object;m2", "Java"), new ThreadStackResponse.StackElement(2, 30, "object.m2()", "Magik"), new ThreadStackResponse.StackElement(3, 200, "java/lang/Object;m1", "Java")));
            return CompletableFuture.completedFuture(response);
        }

        @Override
        public CompletableFuture<ISlapResponse> evaluate(final long threadId, final int level, final String expression) throws IOException {
            final EvalResponse response = new EvalResponse("sw");
            return CompletableFuture.completedFuture(response);
        }

        @Override
        public CompletableFuture<ISlapResponse> getSourceFile(final String method) throws IOException {
            String result = null;
            if ("sw:object.m1()".equals(method)) {
                result = "file1.magik";
            } else if ("sw:object.m2()".equals(method)) {
                result = "file2.magik";
            }
            final SourceFileResponse response = new SourceFileResponse(result);
            return CompletableFuture.completedFuture(response);
        }
    };
    final ThreadManager manager = new ThreadManager(slapProtocol, null);
    final List<StackFrame> stackFrames = manager.stackTrace(1);
    assertThat(stackFrames).hasSize(2);
    final StackFrame frame0 = stackFrames.get(0);
    assertThat(frame0.getId()).isEqualTo(Lsp4jConversion.threadIdLevelToFrameId(1, 0));
    assertThat(frame0.getName()).isEqualTo("sw:object.m1()");
    assertThat(frame0.getSource().getPath()).isEqualTo("file1.magik");
    final StackFrame frame1 = stackFrames.get(1);
    assertThat(frame1.getId()).isEqualTo(Lsp4jConversion.threadIdLevelToFrameId(1, 2));
    assertThat(frame1.getName()).isEqualTo("sw:object.m2()");
    assertThat(frame1.getSource().getPath()).isEqualTo("file2.magik");
}
Also used : ISlapResponse(nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse) StackFrame(org.eclipse.lsp4j.debug.StackFrame) ThreadStackResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.ThreadStackResponse) EvalResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.EvalResponse) SourceFileResponse(nl.ramsolutions.sw.magik.debugadapter.slap.responses.SourceFileResponse) Test(org.junit.jupiter.api.Test)

Aggregations

ISlapResponse (nl.ramsolutions.sw.magik.debugadapter.slap.ISlapResponse)10 SlapErrorException (nl.ramsolutions.sw.magik.debugadapter.slap.SlapErrorException)5 Test (org.junit.jupiter.api.Test)5 ArrayList (java.util.ArrayList)3 ExecutionException (java.util.concurrent.ExecutionException)3 EvalResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.EvalResponse)3 ThreadStackResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.ThreadStackResponse)3 CompletableFuture (java.util.concurrent.CompletableFuture)2 ErrorResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.ErrorResponse)2 SourceFileResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.SourceFileResponse)2 ThreadInfoResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.ThreadInfoResponse)2 ThreadListResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.ThreadListResponse)2 Source (org.eclipse.lsp4j.debug.Source)2 SourceBreakpoint (org.eclipse.lsp4j.debug.SourceBreakpoint)2 StackFrame (org.eclipse.lsp4j.debug.StackFrame)2 Thread (org.eclipse.lsp4j.debug.Thread)2 Path (java.nio.file.Path)1 MagikVariable (nl.ramsolutions.sw.magik.debugadapter.VariableManager.MagikVariable)1 BreakpointSetResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.BreakpointSetResponse)1 StackFrameLocalsResponse (nl.ramsolutions.sw.magik.debugadapter.slap.responses.StackFrameLocalsResponse)1