Skip to content

Add support for StepInTarget request #434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 27, 2022

Conversation

gayanper
Copy link
Contributor

@gayanper gayanper commented Aug 9, 2022

The change implement the StepInTarget request and also update the
StepRequestHandler to support StepInTarget as well.

@gayanper
Copy link
Contributor Author

@testforstephen WDYT ? specially on the target label, I will also see if i can add some tests. I really miss adding integration tests like in Eclipse JDT projects. may be we should spend some time to see if there is a possibility to do that.

any reason we split the UI and LS parts in to separate repo ?

@testforstephen
Copy link
Contributor

I will try to find some time to review this PR as soon as possible.

any reason we split the UI and LS parts in to separate repo ?

No special reason, just we chose two repos at day 1. Yes, integration tests are the missing engineering debt, and we will eventually resolve this technical debt at some day.

Since the debugger is request-response based, one rough idea is we could write a mock client on Java side, and use it to simulate the behavior of VS Code to send DAP requests and verify how the debugger responds.

@gayanper
Copy link
Contributor Author

I think i need to handle unloaded classes as well which I will look when I get time.

@gayanper gayanper marked this pull request as ready for review August 24, 2022 19:09
@gayanper
Copy link
Contributor Author

gayanper commented Sep 6, 2022

@testforstephen i fixed the conflicts and adapt to new changes, let me know what you think ?

@testforstephen testforstephen self-requested a review September 7, 2022 01:25
@testforstephen
Copy link
Contributor

@testforstephen i fixed the conflicts and adapt to new changes, let me know what you think ?

Yes, this PR is on my plan list of Sep.

@testforstephen testforstephen added this to the September milestone Sep 7, 2022
@testforstephen
Copy link
Contributor

Had a try on this PR, it threw NPE.

image

!ENTRY java-debug 4 0 2022-09-09 15:48:23.606
!MESSAGE [error response][stepIn]: Failed to step because of the error 'Cannot invoke "com.sun.jdi.StackFrame.location()" because "threadState.topFrame" is null'
!STACK 0
com.microsoft.java.debug.core.DebugException: Failed to step because of the error 'Cannot invoke "com.sun.jdi.StackFrame.location()" because "threadState.topFrame" is null'
	at com.microsoft.java.debug.core.adapter.AdapterUtils.createCompletionException(AdapterUtils.java:264)
	at com.microsoft.java.debug.core.adapter.handler.StepRequestHandler.handle(StepRequestHandler.java:216)
	at com.microsoft.java.debug.core.adapter.DebugAdapter.lambda$dispatchRequest$0(DebugAdapter.java:92)
	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(Unknown Source)
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(Unknown Source)
	at com.microsoft.java.debug.core.adapter.DebugAdapter.dispatchRequest(DebugAdapter.java:91)
	at com.microsoft.java.debug.core.adapter.ProtocolServer.dispatchRequest(ProtocolServer.java:118)
	at com.microsoft.java.debug.core.protocol.AbstractProtocolServer.lambda$new$0(AbstractProtocolServer.java:78)
	at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:63)
	at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:201)
	at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:255)
	at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
	at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException: Cannot invoke "com.sun.jdi.StackFrame.location()" because "threadState.topFrame" is null
	at com.microsoft.java.debug.core.adapter.handler.StepRequestHandler.handle(StepRequestHandler.java:177)
	... 16 more

@gayanper
Copy link
Contributor Author

@testforstephen will check it next week. seems like after merging the async support something is off.

@gayanper
Copy link
Contributor Author

@testforstephen I manage to fix the issues with cause not to step in to any method at all after synching with master, But i think still it will only work with concrete methods. Any method that is overridden or any dynamic receiver type like List.stream will not work unless we first try to resolve expression to find the actual receiver at runtime.

I will check how we do this in JDT Debug and may be it would be good to see if that can be leverage to support headless through jdt core.

@testforstephen
Copy link
Contributor

Recently I'm working on improving inline breakpoint user experience, and haven't looked into StepInTarget deeply yet.
Could you fix the error first and let me have a try on the user experience of StepInTarget feature?

@testforstephen testforstephen modified the milestones: September, October Oct 12, 2022
The change implement the StepInTarget request and also update the
StepRequestHandler to support StepInTarget as well.
Improve to only show valid targets within an expression, also added
support for stepin into unloaded classes by delaying the stepin.
@testforstephen
Copy link
Contributor

@testforstephen I manage to fix the issues with cause not to step in to any method at all after synching with master, But i think still it will only work with concrete methods. Any method that is overridden or any dynamic receiver type like List.stream will not work unless we first try to resolve expression to find the actual receiver at runtime.

I will check how we do this in JDT Debug and may be it would be good to see if that can be leverage to support headless through jdt core.

@gayanper I have fixed all issues I known based on your branch. Feel free to have a try.

  • Convert the line/column number format between client and server.
  • Support stepInto the overridden methods (e.g. stream chain call)
  • Support stepInto constructors
  • Reuse the cached ASTNode as possible.
  • Use the original MethodBinding instead of the instantiated MethodBinding like ParameterizedGenericMethodBinding. The method signature from the original method declaration is more consistent with the signature from JVM.

@gayanper
Copy link
Contributor Author

@testforstephen LGTM, may be the caching AST can be moved for reuse later in other places as well if needed. But for now the change looks good even with out it. I think you have made some good improvements over my initial changes.

@gayanper
Copy link
Contributor Author

I tried to run your changes with the following code

package org.gap.demo;

import java.util.Arrays;

public class Debug {
    public static void main(String[] args) {
        Object[] array = Arrays.asList(1, 2, 3).stream().map(i -> i * 2).filter(i -> i > 1).toArray();
        foo(boo());
    }

    private static String boo() {
        return "x";
    }

    private static void foo(String p) {
        System.out.println(p);
    }
}

But on both the stream expression and the other expression it says no targets available.

@testforstephen
Copy link
Contributor

I tried to run your changes with the following code

package org.gap.demo;

import java.util.Arrays;

public class Debug {
    public static void main(String[] args) {
        Object[] array = Arrays.asList(1, 2, 3).stream().map(i -> i * 2).filter(i -> i > 1).toArray();
        foo(boo());
    }

    private static String boo() {
        return "x";
    }

    private static void foo(String p) {
        System.out.println(p);
    }
}

But on both the stream expression and the other expression it says no targets available.

It works for me. With the latest changes, you can hover on the target method name and then click "Step Into Target" menu.

stepInTarget.mp4

Maybe your extesnion cache is still using the old debug jar. I packaged a private bits with the latest changes, you can have a try on it. https://github.com/testforstephen/vscode-test/raw/master/vscode-java-debug-0.45.1.vsix

@testforstephen testforstephen merged commit a6ca87a into microsoft:main Oct 27, 2022
@gayanper
Copy link
Contributor Author

Sorry couldn’t post the results yesterday, it was working as expected. Thanks for completing the feature jinbo

@testforstephen
Copy link
Contributor

It's a good feature, I'm happy to merge it. It has been in pre-release version of debugger extension. Thank you for the initial contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants