Skip to content

Commit b00f6b3

Browse files
Enable stepInTarget feature on more use cases
1 parent b6e4df3 commit b00f6b3

File tree

8 files changed

+459
-228
lines changed

8 files changed

+459
-228
lines changed

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ISourceLookUpProvider.java

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
import com.microsoft.java.debug.core.JavaBreakpointLocation;
1919
import com.microsoft.java.debug.core.protocol.Types.SourceBreakpoint;
2020

21-
import com.sun.jdi.StackFrame;
22-
2321
public interface ISourceLookUpProvider extends IProvider {
2422
boolean supportsRealtimeBreakpointVerification();
2523

@@ -70,17 +68,19 @@ default String getJavaRuntimeVersion(String projectName) {
7068
* Return method invocation found in the statement as the given line number of
7169
* the source file.
7270
*
73-
* @param stackframe The stack frame where the invocation must be searched.
71+
* @param uri The source file where the invocation must be searched.
72+
* @param line The line number where the invocation must be searched.
7473
*
7574
* @return List of found method invocation or empty if not method invocations
7675
* can be found.
7776
*/
78-
List<MethodInvocation> findMethodInvocations(StackFrame stackframe);
77+
List<MethodInvocation> findMethodInvocations(String uri, int line);
7978

8079
public static class MethodInvocation {
8180
public String expression;
8281
public String methodName;
8382
public String methodSignature;
83+
public String methodGenericSignature;
8484
public String declaringTypeName;
8585
public int lineStart;
8686
public int lineEnd;
@@ -89,27 +89,24 @@ public static class MethodInvocation {
8989

9090
@Override
9191
public int hashCode() {
92-
return Objects.hash(columnEnd, columnStart, declaringTypeName, expression, lineEnd, lineStart, methodName,
93-
methodSignature);
92+
return Objects.hash(expression, methodName, methodSignature, methodGenericSignature, declaringTypeName,
93+
lineStart, lineEnd, columnStart, columnEnd);
9494
}
9595

9696
@Override
9797
public boolean equals(Object obj) {
9898
if (this == obj) {
9999
return true;
100100
}
101-
if (obj == null) {
102-
return false;
103-
}
104-
if (getClass() != obj.getClass()) {
101+
if (!(obj instanceof MethodInvocation)) {
105102
return false;
106103
}
107104
MethodInvocation other = (MethodInvocation) obj;
108-
return columnEnd == other.columnEnd && columnStart == other.columnStart
109-
&& Objects.equals(declaringTypeName, other.declaringTypeName)
110-
&& Objects.equals(expression, other.expression) && lineEnd == other.lineEnd
111-
&& lineStart == other.lineStart && Objects.equals(methodName, other.methodName)
112-
&& Objects.equals(methodSignature, other.methodSignature);
105+
return Objects.equals(expression, other.expression) && Objects.equals(methodName, other.methodName)
106+
&& Objects.equals(methodSignature, other.methodSignature)
107+
&& Objects.equals(methodGenericSignature, other.methodGenericSignature)
108+
&& Objects.equals(declaringTypeName, other.declaringTypeName) && lineStart == other.lineStart
109+
&& lineEnd == other.lineEnd && columnStart == other.columnStart && columnEnd == other.columnEnd;
113110
}
114111
}
115112
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StackTraceRequestHandler.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
8989
StackFrame[] frames = context.getStackFrameManager().reloadStackFrames(thread, stacktraceArgs.startFrame, count);
9090
List<StackFrameInfo> jdiFrames = resolveStackFrameInfos(frames, context.asyncJDWP());
9191
for (int i = 0; i < count; i++) {
92-
StackFrameReference stackframe = new StackFrameReference(thread, stacktraceArgs.startFrame + i);
93-
int frameId = context.getRecyclableIdPool().addObject(stacktraceArgs.threadId, stackframe);
92+
StackFrameReference frameReference = new StackFrameReference(thread, stacktraceArgs.startFrame + i);
93+
int frameId = context.getRecyclableIdPool().addObject(stacktraceArgs.threadId, frameReference);
9494
StackFrameInfo jdiFrame = jdiFrames.get(i);
95-
result.add(convertDebuggerStackFrameToClient(jdiFrame, frameId, i == 0, context));
95+
Types.StackFrame lspFrame = convertDebuggerStackFrameToClient(jdiFrame, frameId, i == 0, context);
96+
result.add(lspFrame);
97+
frameReference.setSource(lspFrame.source);
9698
}
9799
} catch (IncompatibleThreadStateException | IndexOutOfBoundsException | URISyntaxException
98100
| AbsentInformationException | ObjectCollectedException

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StepInTargetsRequestHandler.java

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@
1010
*******************************************************************************/
1111
package com.microsoft.java.debug.core.adapter.handler;
1212

13+
import java.io.File;
14+
import java.net.URISyntaxException;
1315
import java.util.ArrayList;
1416
import java.util.Arrays;
1517
import java.util.Collections;
1618
import java.util.List;
1719
import java.util.Optional;
1820
import 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;
2026
import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
2127
import com.microsoft.java.debug.core.adapter.IDebugRequestHandler;
2228
import com.microsoft.java.debug.core.adapter.ISourceLookUpProvider;
@@ -27,10 +33,14 @@
2733
import com.microsoft.java.debug.core.protocol.Requests.Command;
2834
import com.microsoft.java.debug.core.protocol.Requests.StepInTargetsArguments;
2935
import com.microsoft.java.debug.core.protocol.Responses.StepInTargetsResponse;
36+
import com.microsoft.java.debug.core.protocol.Types.Source;
3037
import com.microsoft.java.debug.core.protocol.Types.StepInTarget;
38+
import com.sun.jdi.AbsentInformationException;
39+
import com.sun.jdi.ReferenceType;
3140
import com.sun.jdi.StackFrame;
3241

3342
public 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 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+
}
81138
}

0 commit comments

Comments
 (0)