mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-218567 Wrong method is highlighted in smart step into
GitOrigin-RevId: 1f4752fd83b34c03a649423c27c6f7687011e72a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f5d795cecc
commit
19595c6296
+82
-43
@@ -32,6 +32,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.sun.jdi.Location;
|
||||
import com.sun.jdi.Method;
|
||||
import com.sun.jdi.ReferenceType;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -358,13 +359,14 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
return smart ? targets : Collections.emptyList();
|
||||
}
|
||||
// sanity check
|
||||
DebugProcessImpl debugProcess = suspendContext.getDebugProcess();
|
||||
try {
|
||||
List<MethodSmartStepTarget> methodTargets =
|
||||
StreamEx.of(targets)
|
||||
.select(MethodSmartStepTarget.class)
|
||||
.filter(target -> !target.needsBreakpointRequest())
|
||||
.toList();
|
||||
visitLinesMethods(frameProxy.location(), true, lines, false, (opcode, owner, name, desc, itf) -> {
|
||||
visitLinesMethods(frameProxy.location(), true, lines, (opcode, owner, name, desc, itf, ordinal) -> {
|
||||
if (name.startsWith("access$")) { // bridge method
|
||||
ReferenceType cls = ContainerUtil.getFirstItem(virtualMachine.classesByName(owner));
|
||||
if (cls != null) {
|
||||
@@ -376,14 +378,14 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
if ("java/lang/AbstractMethodError".equals(owner)) {
|
||||
return;
|
||||
}
|
||||
removeMatchingMethod(methodTargets, owner, name, desc, suspendContext.getDebugProcess());
|
||||
removeMatchingMethod(methodTargets, owner, name, desc, ordinal, debugProcess);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeMatchingMethod(methodTargets, owner, name, desc, suspendContext.getDebugProcess());
|
||||
removeMatchingMethod(methodTargets, owner, name, desc, ordinal, debugProcess);
|
||||
}
|
||||
});
|
||||
if (!methodTargets.isEmpty()) {
|
||||
@@ -395,34 +397,35 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
}
|
||||
|
||||
try {
|
||||
MethodInsnVisitor visitor = (opcode, owner, name, desc, itf) -> {
|
||||
Iterator<SmartStepTarget> iterator = targets.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SmartStepTarget e = iterator.next();
|
||||
if (e instanceof MethodSmartStepTarget &&
|
||||
DebuggerUtilsEx.methodMatches(((MethodSmartStepTarget)e).getMethod(),
|
||||
owner.replace("/", "."), name, desc,
|
||||
suspendContext.getDebugProcess())) {
|
||||
iterator.remove();
|
||||
MethodSmartStepTarget target = (MethodSmartStepTarget)e;
|
||||
// fix ordinals
|
||||
existingMethodCalls(targets, target.getMethod())
|
||||
.forEach(t -> {
|
||||
int ordinal = t.getOrdinal();
|
||||
if (ordinal > target.getOrdinal()) {
|
||||
t.setOrdinal(ordinal - 1);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
List<MethodSmartStepTarget> removed = new ArrayList<>();
|
||||
|
||||
// remove already executed
|
||||
visitLinesMethods(frameProxy.location(), false, lines, false, visitor);
|
||||
JumpsAndInsnVisitor visitor = new JumpsAndInsnVisitor(targets, debugProcess, removed);
|
||||
visitLinesMethods(frameProxy.location(), false, lines, visitor);
|
||||
int lastJump = visitor.myJumpCounter;
|
||||
|
||||
if (!smart) {
|
||||
// remove after jumps
|
||||
visitLinesMethods(frameProxy.location(), true, lines, true, visitor);
|
||||
visitor = new JumpsAndInsnVisitor(targets, debugProcess, removed) {
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf, int ordinal) {
|
||||
if (myJumpCounter > lastJump) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf, ordinal);
|
||||
}
|
||||
}
|
||||
};
|
||||
visitLinesMethods(frameProxy.location(), true, lines, visitor);
|
||||
}
|
||||
|
||||
// fix ordinals
|
||||
for (MethodSmartStepTarget target : removed) {
|
||||
existingMethodCalls(targets, target.getMethod())
|
||||
.forEach(t -> {
|
||||
int ordinal = t.getOrdinal();
|
||||
if (ordinal > target.getOrdinal()) {
|
||||
t.setOrdinal(ordinal - 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -440,10 +443,13 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
String owner,
|
||||
String name,
|
||||
String desc,
|
||||
int ordinal,
|
||||
DebugProcessImpl process) {
|
||||
Iterator<MethodSmartStepTarget> iterator = targets.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (DebuggerUtilsEx.methodMatches(iterator.next().getMethod(), owner.replace("/", "."), name, desc, process)) {
|
||||
MethodSmartStepTarget target = iterator.next();
|
||||
if (DebuggerUtilsEx.methodMatches(target.getMethod(), owner.replace("/", "."), name, desc, process) &&
|
||||
target.getOrdinal() == ordinal) {
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
@@ -451,38 +457,37 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
}
|
||||
|
||||
private interface MethodInsnVisitor {
|
||||
void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf);
|
||||
void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf, int ordinal);
|
||||
default void visitJumpInsn(int opcode, Label label) {}
|
||||
}
|
||||
|
||||
private static void visitLinesMethods(Location location, boolean full, Range<Integer> lines, boolean afterJumps, MethodInsnVisitor visitor) {
|
||||
private static void visitLinesMethods(Location location, boolean full, Range<Integer> lines, MethodInsnVisitor visitor) {
|
||||
TObjectIntHashMap<String> myCounter = new TObjectIntHashMap<>();
|
||||
|
||||
MethodBytecodeUtil.visit(location.method(), full ? Long.MAX_VALUE : location.codeIndex(), new MethodVisitor(Opcodes.API_VERSION) {
|
||||
boolean myLineMatch = false;
|
||||
boolean myAfterJump = false;
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(int opcode, Label label) {
|
||||
myAfterJump = true;
|
||||
if (myLineMatch) {
|
||||
visitor.visitJumpInsn(opcode, label);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(int line, Label start) {
|
||||
boolean within = lines.isWithin(line - 1);
|
||||
if (within != myLineMatch) {
|
||||
myAfterJump = false;
|
||||
}
|
||||
myLineMatch = within;
|
||||
myLineMatch = lines.isWithin(line - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
||||
if (isMatch()) {
|
||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
if (myLineMatch) {
|
||||
String key = owner + "." + name + desc;
|
||||
int currentCount = myCounter.get(key);
|
||||
myCounter.put(key, currentCount + 1);
|
||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf, currentCount);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isMatch() {
|
||||
return myLineMatch && (!afterJumps || myAfterJump);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -492,4 +497,38 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
.filter(target -> !target.needsBreakpointRequest())
|
||||
.filter(t -> t.getMethod().equals(psiMethod));
|
||||
}
|
||||
|
||||
private static class JumpsAndInsnVisitor implements MethodInsnVisitor {
|
||||
private final List<SmartStepTarget> myTargets;
|
||||
private final DebugProcessImpl myDebugProcess;
|
||||
private final List<MethodSmartStepTarget> myToRemove;
|
||||
int myJumpCounter;
|
||||
|
||||
JumpsAndInsnVisitor(List<SmartStepTarget> targets, DebugProcessImpl debugProcess, List<MethodSmartStepTarget> removed) {
|
||||
myTargets = targets;
|
||||
myDebugProcess = debugProcess;
|
||||
myToRemove = removed;
|
||||
myJumpCounter = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf, int ordinal) {
|
||||
Iterator<SmartStepTarget> iterator = myTargets.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SmartStepTarget e = iterator.next();
|
||||
if (e instanceof MethodSmartStepTarget &&
|
||||
DebuggerUtilsEx.methodMatches(((MethodSmartStepTarget)e).getMethod(), owner.replace("/", "."), name, desc, myDebugProcess) &&
|
||||
((MethodSmartStepTarget)e).getOrdinal() == ordinal) {
|
||||
iterator.remove();
|
||||
myToRemove.add((MethodSmartStepTarget)e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(int opcode, Label label) {
|
||||
myJumpCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user