10
10
*******************************************************************************/
11
11
package com .microsoft .java .debug .core .adapter .handler ;
12
12
13
+ import java .io .File ;
14
+ import java .net .URISyntaxException ;
13
15
import java .util .ArrayList ;
14
16
import java .util .Arrays ;
15
17
import java .util .Collections ;
16
18
import java .util .List ;
17
19
import java .util .Optional ;
18
20
import java .util .concurrent .CompletableFuture ;
21
+ import java .util .logging .Level ;
22
+ import java .util .logging .Logger ;
19
23
24
+ import com .microsoft .java .debug .core .Configuration ;
25
+ import com .microsoft .java .debug .core .adapter .AdapterUtils ;
20
26
import com .microsoft .java .debug .core .adapter .IDebugAdapterContext ;
21
27
import com .microsoft .java .debug .core .adapter .IDebugRequestHandler ;
22
28
import com .microsoft .java .debug .core .adapter .ISourceLookUpProvider ;
27
33
import com .microsoft .java .debug .core .protocol .Requests .Command ;
28
34
import com .microsoft .java .debug .core .protocol .Requests .StepInTargetsArguments ;
29
35
import com .microsoft .java .debug .core .protocol .Responses .StepInTargetsResponse ;
36
+ import com .microsoft .java .debug .core .protocol .Types .Source ;
30
37
import com .microsoft .java .debug .core .protocol .Types .StepInTarget ;
38
+ import com .sun .jdi .AbsentInformationException ;
39
+ import com .sun .jdi .ReferenceType ;
31
40
import com .sun .jdi .StackFrame ;
32
41
33
42
public class StepInTargetsRequestHandler implements IDebugRequestHandler {
43
+ private static final Logger logger = Logger .getLogger (Configuration .LOGGER_NAME );
34
44
35
45
@ Override
36
46
public List <Command > getTargetCommands () {
@@ -45,37 +55,84 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
45
55
final int frameId = stepInTargetsArguments .frameId ;
46
56
return CompletableFuture .supplyAsync (() -> {
47
57
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 ))
49
59
.orElse (Collections .emptyList ()).toArray (StepInTarget []::new ));
50
60
return response ;
51
61
});
52
62
}
53
63
54
- private Optional <StackFrame > findFrame (int frameId , IDebugAdapterContext context ) {
64
+ private Optional <StackFrameReference > findFrame (int frameId , IDebugAdapterContext context ) {
55
65
Object object = context .getRecyclableIdPool ().getObjectById (frameId );
56
66
if (object instanceof StackFrameReference ) {
57
- return Optional .of (context . getStackFrameManager (). getStackFrame (( StackFrameReference ) object ) );
67
+ return Optional .of (( StackFrameReference ) object );
58
68
}
59
69
return Optional .empty ();
60
70
}
61
71
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
+
63
88
ISourceLookUpProvider sourceLookUpProvider = context .getProvider (ISourceLookUpProvider .class );
64
- List <MethodInvocation > invocations = sourceLookUpProvider .findMethodInvocations (stackframe );
89
+ List <MethodInvocation > invocations = sourceLookUpProvider .findMethodInvocations (sourceUri , stackframe . location (). lineNumber () );
65
90
if (invocations .isEmpty ()) {
66
91
return Collections .emptyList ();
67
92
}
68
93
94
+ long threadId = stackframe .thread ().uniqueID ();
69
95
List <StepInTarget > targets = new ArrayList <>(invocations .size ());
70
96
for (MethodInvocation methodInvocation : invocations ) {
71
97
int id = context .getRecyclableIdPool ().addObject (threadId , methodInvocation );
72
98
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 ());
77
107
targets .add (target );
78
108
}
109
+
110
+ // TODO remove the executed method calls.
79
111
return targets ;
80
112
}
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 Location#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
+ }
81
138
}
0 commit comments