1010*******************************************************************************/
1111package com .microsoft .java .debug .core .adapter .handler ;
1212
13+ import java .io .File ;
14+ import java .net .URISyntaxException ;
1315import java .util .ArrayList ;
1416import java .util .Arrays ;
1517import java .util .Collections ;
1618import java .util .List ;
1719import java .util .Optional ;
1820import java .util .concurrent .CompletableFuture ;
21+ import java .util .logging .Level ;
22+ import java .util .logging .Logger ;
1923
24+ import com .microsoft .java .debug .core .Configuration ;
25+ import com .microsoft .java .debug .core .adapter .AdapterUtils ;
2026import com .microsoft .java .debug .core .adapter .IDebugAdapterContext ;
2127import com .microsoft .java .debug .core .adapter .IDebugRequestHandler ;
2228import com .microsoft .java .debug .core .adapter .ISourceLookUpProvider ;
2733import com .microsoft .java .debug .core .protocol .Requests .Command ;
2834import com .microsoft .java .debug .core .protocol .Requests .StepInTargetsArguments ;
2935import com .microsoft .java .debug .core .protocol .Responses .StepInTargetsResponse ;
36+ import com .microsoft .java .debug .core .protocol .Types .Source ;
3037import com .microsoft .java .debug .core .protocol .Types .StepInTarget ;
38+ import com .sun .jdi .AbsentInformationException ;
39+ import com .sun .jdi .ReferenceType ;
3140import com .sun .jdi .StackFrame ;
3241
3342public class StepInTargetsRequestHandler implements IDebugRequestHandler {
43+ private static final Logger logger = Logger .getLogger (Configuration .LOGGER_NAME );
3444
3545 @ Override
3646 public List <Command > getTargetCommands () {
@@ -45,37 +55,84 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
4555 final int frameId = stepInTargetsArguments .frameId ;
4656 return CompletableFuture .supplyAsync (() -> {
4757 response .body = new StepInTargetsResponse (
48- findFrame (frameId , context ).map (f -> findTargets (f . thread (). uniqueID (), f , context ))
58+ findFrame (frameId , context ).map (f -> findTargets (f , context ))
4959 .orElse (Collections .emptyList ()).toArray (StepInTarget []::new ));
5060 return response ;
5161 });
5262 }
5363
54- private Optional <StackFrame > findFrame (int frameId , IDebugAdapterContext context ) {
64+ private Optional <StackFrameReference > findFrame (int frameId , IDebugAdapterContext context ) {
5565 Object object = context .getRecyclableIdPool ().getObjectById (frameId );
5666 if (object instanceof StackFrameReference ) {
57- return Optional .of (context . getStackFrameManager (). getStackFrame (( StackFrameReference ) object ) );
67+ return Optional .of (( StackFrameReference ) object );
5868 }
5969 return Optional .empty ();
6070 }
6171
62- private List <StepInTarget > findTargets (long threadId , StackFrame stackframe , IDebugAdapterContext context ) {
72+ private List <StepInTarget > findTargets (StackFrameReference frameReference , IDebugAdapterContext context ) {
73+ StackFrame stackframe = context .getStackFrameManager ().getStackFrame (frameReference );
74+ if (stackframe == null ) {
75+ return Collections .emptyList ();
76+ }
77+
78+ Source source = frameReference .getSource () == null ? findSource (stackframe , context ) : frameReference .getSource ();
79+ if (source == null ) {
80+ return Collections .emptyList ();
81+ }
82+
83+ String sourceUri = AdapterUtils .convertPath (source .path , AdapterUtils .isUri (source .path ), true );
84+ if (sourceUri == null ) {
85+ return Collections .emptyList ();
86+ }
87+
6388 ISourceLookUpProvider sourceLookUpProvider = context .getProvider (ISourceLookUpProvider .class );
64- List <MethodInvocation > invocations = sourceLookUpProvider .findMethodInvocations (stackframe );
89+ List <MethodInvocation > invocations = sourceLookUpProvider .findMethodInvocations (sourceUri , stackframe . location (). lineNumber () );
6590 if (invocations .isEmpty ()) {
6691 return Collections .emptyList ();
6792 }
6893
94+ long threadId = stackframe .thread ().uniqueID ();
6995 List <StepInTarget > targets = new ArrayList <>(invocations .size ());
7096 for (MethodInvocation methodInvocation : invocations ) {
7197 int id = context .getRecyclableIdPool ().addObject (threadId , methodInvocation );
7298 StepInTarget target = new StepInTarget (id , methodInvocation .expression );
73- target .column = methodInvocation .columnStart ;
74- target .endColumn = methodInvocation .columnEnd ;
75- target .line = methodInvocation .lineStart ;
76- target .endLine = methodInvocation .lineEnd ;
99+ target .column = AdapterUtils .convertColumnNumber (methodInvocation .columnStart ,
100+ context .isDebuggerColumnsStartAt1 (), context .isClientColumnsStartAt1 ());
101+ target .endColumn = AdapterUtils .convertColumnNumber (methodInvocation .columnEnd ,
102+ context .isDebuggerColumnsStartAt1 (), context .isClientColumnsStartAt1 ());
103+ target .line = AdapterUtils .convertLineNumber (methodInvocation .lineStart ,
104+ context .isDebuggerLinesStartAt1 (), context .isClientLinesStartAt1 ());
105+ target .endLine = AdapterUtils .convertLineNumber (methodInvocation .lineEnd ,
106+ context .isDebuggerLinesStartAt1 (), context .isClientLinesStartAt1 ());
77107 targets .add (target );
78108 }
109+
110+ // TODO remove the executed method calls.
79111 return targets ;
80112 }
113+
114+ private Source findSource (StackFrame frame , IDebugAdapterContext context ) {
115+ ReferenceType declaringType = frame .location ().declaringType ();
116+ String typeName = declaringType .name ();
117+ String sourceName = null ;
118+ String sourcePath = null ;
119+ try {
120+ // When the .class file doesn't contain source information in meta data,
121+ // invoking ReferenceType#sourceName() would throw AbsentInformationException.
122+ sourceName = declaringType .sourceName ();
123+ sourcePath = declaringType .sourcePaths (null ).get (0 );
124+ } catch (AbsentInformationException e ) {
125+ String enclosingType = AdapterUtils .parseEnclosingType (typeName );
126+ sourceName = enclosingType .substring (enclosingType .lastIndexOf ('.' ) + 1 ) + ".java" ;
127+ sourcePath = enclosingType .replace ('.' , File .separatorChar ) + ".java" ;
128+ }
129+
130+ try {
131+ return StackTraceRequestHandler .convertDebuggerSourceToClient (typeName , sourceName , sourcePath , context );
132+ } catch (URISyntaxException e ) {
133+ logger .log (Level .SEVERE , "Failed to resolve the source info of the stack frame." , e );
134+ }
135+
136+ return null ;
137+ }
81138}
0 commit comments