diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/AsyncStacksUtils.java b/java/debugger/impl/src/com/intellij/debugger/engine/AsyncStacksUtils.java index 8aee10081028..6983cd4960c4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/AsyncStacksUtils.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/AsyncStacksUtils.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.engine; import com.intellij.debugger.engine.evaluation.EvaluateException; @@ -6,10 +6,7 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.requests.RequestManagerImpl; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.impl.DebuggerUtilsImpl; -import com.intellij.debugger.jdi.ClassesByNameProvider; -import com.intellij.debugger.jdi.GeneratedLocation; -import com.intellij.debugger.jdi.StackFrameProxyImpl; -import com.intellij.debugger.jdi.VirtualMachineProxyImpl; +import com.intellij.debugger.jdi.*; import com.intellij.debugger.memory.utils.StackFrameItem; import com.intellij.debugger.requests.ClassPrepareRequestor; import com.intellij.debugger.settings.CaptureSettingsProvider; @@ -111,18 +108,13 @@ public final class AsyncStacksUtils { ClassesByNameProvider classesByName = ClassesByNameProvider.createCache(virtualMachineProxy.allClasses()); try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(value.getBytes(StandardCharsets.ISO_8859_1)))) { while (dis.available() > 0) { - ProcessStackFrameItem item = null; + StackFrameItem item = null; if (dis.readBoolean()) { String className = dis.readUTF(); String methodName = dis.readUTF(); int line = dis.readInt(); - ReferenceType classType = ContainerUtil.getFirstItem(classesByName.get(className)); - if (classType == null) { - LOG.error("Unable to find loaded class " + className); - return null; - } - Location location = findLocation(process, classType, methodName, line); - item = new ProcessStackFrameItem(location, className, methodName); + Location location = findLocation(process, classesByName, className, methodName, line); + item = new StackFrameItem(location, null); } res.add(item); } @@ -201,44 +193,25 @@ public final class AsyncStacksUtils { } } - private static class ProcessStackFrameItem extends StackFrameItem { - final String myClass; - final String myMethod; - - ProcessStackFrameItem(Location location, String aClass, String method) { - super(location, null); - myClass = aClass; - myMethod = method; + @NotNull + private static Location findLocation(DebugProcessImpl debugProcess, + @NotNull ClassesByNameProvider classesByName, + @NotNull String className, + @NotNull String methodName, + int line) { + ReferenceType classType = ContainerUtil.getFirstItem(classesByName.get(className)); + if (classType == null) { + classType = new GeneratedReferenceType(debugProcess.getVirtualMachineProxy().getVirtualMachine(), className); } - - @NotNull - @Override - public String path() { - return myClass; - } - - @NotNull - @Override - public String method() { - return myMethod; - } - - @Override - public String toString() { - return myClass + "." + myMethod + ":" + line(); - } - } - - private static Location findLocation(DebugProcessImpl debugProcess, @NotNull ReferenceType type, String methodName, int line) { - if (line >= 0) { - for (Method method : DebuggerUtilsEx.declaredMethodsByName(type, methodName)) { + else if (line >= 0) { + for (Method method : DebuggerUtilsEx.declaredMethodsByName(classType, methodName)) { List locations = DebuggerUtilsEx.locationsOfLine(method, line); if (!locations.isEmpty()) { return locations.get(0); } } } - return new GeneratedLocation(debugProcess, type, methodName, line); + return new GeneratedLocation(classType, methodName, line); } public static void addAgentCapturePoints(EvaluationContextImpl evalContext, Properties properties) { diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java index eabb638d604f..515acc7d369e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java @@ -14,6 +14,7 @@ import com.intellij.debugger.engine.evaluation.*; import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; import com.intellij.debugger.engine.evaluation.expression.UnBoxingEvaluator; import com.intellij.debugger.engine.requests.RequestManagerImpl; +import com.intellij.debugger.jdi.GeneratedLocation; import com.intellij.debugger.jdi.JvmtiError; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.debugger.requests.Requestor; @@ -884,10 +885,14 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { if (type != null) { res.append(type.name()).append('.'); } - res.append(location.method().name()); + res.append(getLocationMethodName(location)); return res.toString(); } + public static String getLocationMethodName(@NotNull Location location) { + return location instanceof GeneratedLocation ? ((GeneratedLocation)location).methodName() : location.method().name(); + } + private static PsiElement getNextElement(PsiElement element) { PsiElement sibling = element.getNextSibling(); if (sibling != null) return sibling; diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/GeneratedLocation.java b/java/debugger/impl/src/com/intellij/debugger/jdi/GeneratedLocation.java index 4cb92df4e7db..af3779493477 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/GeneratedLocation.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/GeneratedLocation.java @@ -1,23 +1,23 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.jdi; -import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.DebuggerUtils; import com.sun.jdi.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Objects; public class GeneratedLocation implements Location { - private final VirtualMachine myVirtualMachine; private final int myLineNumber; - private final ReferenceType myReferenceType; - private final Method myMethod; + private final @NotNull ReferenceType myReferenceType; + private final @Nullable Method myMethod; + private final @NotNull String myMethodName; - public GeneratedLocation(DebugProcessImpl debugProcess, @NotNull ReferenceType type, String methodName, int lineNumber) { - myVirtualMachine = debugProcess.getVirtualMachineProxy().getVirtualMachine(); + public GeneratedLocation(@NotNull ReferenceType type, @NotNull String methodName, int lineNumber) { myLineNumber = lineNumber; myReferenceType = type; + myMethodName = methodName; myMethod = DebuggerUtils.findMethod(myReferenceType, methodName, null); } @@ -31,6 +31,11 @@ public class GeneratedLocation implements Location { return myMethod; } + @NotNull + public String methodName() { + return myMethodName; + } + @Override public long codeIndex() { return -2; // to be never equal to any LocationImpl @@ -68,22 +73,23 @@ public class GeneratedLocation implements Location { @Override public VirtualMachine virtualMachine() { - return myVirtualMachine; + return myReferenceType.virtualMachine(); } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GeneratedLocation location = (GeneratedLocation)o; - return Objects.equals(myMethod, location.myMethod) && - myLineNumber == location.myLineNumber && - Objects.equals(myVirtualMachine, location.myVirtualMachine); + public boolean equals(Object other) { + if (this == other) return true; + if (other == null || getClass() != other.getClass()) return false; + GeneratedLocation location = (GeneratedLocation)other; + return myLineNumber == location.myLineNumber && + myReferenceType.equals(location.myReferenceType) && + myMethodName.equals(location.myMethodName) && + Objects.equals(virtualMachine(), location.virtualMachine()); } @Override public int hashCode() { - return Objects.hash(myMethod, myLineNumber); + return Objects.hash(myMethodName, myLineNumber); } // Same as in LocationImpl @@ -97,6 +103,6 @@ public class GeneratedLocation implements Location { } public String toString() { - return myReferenceType.name() + ":" + myLineNumber; + return myReferenceType.name() + "." + myMethodName + ":" + myLineNumber; } } diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/GeneratedReferenceType.java b/java/debugger/impl/src/com/intellij/debugger/jdi/GeneratedReferenceType.java new file mode 100644 index 000000000000..e6cd19647e61 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/GeneratedReferenceType.java @@ -0,0 +1,264 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.debugger.jdi; + +import com.jetbrains.jdi.JNITypeParser; +import com.sun.jdi.*; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class GeneratedReferenceType implements ReferenceType { + private final @NotNull VirtualMachine myVm; + private final @NotNull String myName; + + public GeneratedReferenceType(@NotNull VirtualMachine vm, @NotNull String name) { + myVm = vm; + myName = name; + } + + @Override + public String name() { + return myName; + } + + @Override + public String genericSignature() { + return null; + } + + @Override + public ClassLoaderReference classLoader() { + return null; + } + + @Override + public String sourceName() throws AbsentInformationException { + throw new AbsentInformationException(); + } + + @Override + public List sourceNames(String stratum) throws AbsentInformationException { + throw new AbsentInformationException(); + } + + @Override + public List sourcePaths(String stratum) throws AbsentInformationException { + throw new AbsentInformationException(); + } + + @Override + public String sourceDebugExtension() throws AbsentInformationException { + throw new AbsentInformationException(); + } + + @Override + public boolean isStatic() { + return false; + } + + @Override + public boolean isAbstract() { + return false; + } + + @Override + public boolean isFinal() { + return false; + } + + @Override + public boolean isPrepared() { + return false; + } + + @Override + public boolean isVerified() { + return false; + } + + @Override + public boolean isInitialized() { + return false; + } + + @Override + public boolean failedToInitialize() { + return false; + } + + @Override + public List fields() { + return Collections.emptyList(); + } + + @Override + public List visibleFields() { + return Collections.emptyList(); + } + + @Override + public List allFields() { + return Collections.emptyList(); + } + + @Override + public Field fieldByName(String fieldName) { + return null; + } + + @Override + public List methods() { + return Collections.emptyList(); + } + + @Override + public List visibleMethods() { + return Collections.emptyList(); + } + + @Override + public List allMethods() { + return Collections.emptyList(); + } + + @Override + public List methodsByName(String name) { + return Collections.emptyList(); + } + + @Override + public List methodsByName(String name, String signature) { + return Collections.emptyList(); + } + + @Override + public List nestedTypes() { + return Collections.emptyList(); + } + + @Override + public Value getValue(Field field) { + return null; + } + + @Override + public Map getValues(List fields) { + return Collections.emptyMap(); + } + + @Override + public ClassObjectReference classObject() { + return null; + } + + @Override + public List allLineLocations() throws AbsentInformationException { + return Collections.emptyList(); + } + + @Override + public List allLineLocations(String stratum, String sourceName) throws AbsentInformationException { + return Collections.emptyList(); + } + + @Override + public List locationsOfLine(int lineNumber) throws AbsentInformationException { + return Collections.emptyList(); + } + + @Override + public List locationsOfLine(String stratum, String sourceName, int lineNumber) throws AbsentInformationException { + return Collections.emptyList(); + } + + @Override + public List availableStrata() { + return List.of(myVm.getDefaultStratum()); + } + + @Override + public String defaultStratum() { + return myVm.getDefaultStratum(); + } + + @Override + public List instances(long maxInstances) { + return Collections.emptyList(); + } + + @Override + public int majorVersion() { + return 0; + } + + @Override + public int minorVersion() { + return 0; + } + + @Override + public int constantPoolCount() { + return 0; + } + + @Override + public byte[] constantPool() { + return new byte[0]; + } + + @Override + public int modifiers() { + return 0; + } + + @Override + public boolean isPrivate() { + return false; + } + + @Override + public boolean isPackagePrivate() { + return false; + } + + @Override + public boolean isProtected() { + return false; + } + + @Override + public boolean isPublic() { + return false; + } + + @Override + public String signature() { + return JNITypeParser.typeNameToSignature(myName); + } + + @Override + public VirtualMachine virtualMachine() { + return myVm; + } + + @Override + public int compareTo(@NotNull ReferenceType o) { + return 0; + } + + @Override + public boolean equals(Object other) { + if (this == other) return true; + if (other == null || getClass() != other.getClass()) return false; + GeneratedReferenceType type = (GeneratedReferenceType)other; + return myName.equals(type.myName) && myVm.equals(type.myVm); + } + + @Override + public int hashCode() { + return Objects.hash(myName); + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/utils/StackFrameItem.java b/java/debugger/impl/src/com/intellij/debugger/memory/utils/StackFrameItem.java index 7e09123a6617..db83770b8659 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/utils/StackFrameItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/utils/StackFrameItem.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.memory.utils; import com.intellij.debugger.JavaDebuggerBundle; @@ -82,7 +82,7 @@ public class StackFrameItem { @NotNull public String method() { - return myLocation.method().name(); + return DebuggerUtilsEx.getLocationMethodName(myLocation); } public int line() { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java index f1a6f2fc2481..c588048ba323 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.ui.breakpoints; import com.intellij.debugger.JavaDebuggerBundle; @@ -10,6 +10,7 @@ import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl; import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluatorImpl; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.jdi.DecompiledLocalVariable; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; @@ -163,7 +164,7 @@ public class StackCapturingLineBreakpoint extends SyntheticMethodBreakpoint { try { Location location = frame.location(); String className = location.declaringType().name(); - String methodName = location.method().name(); + String methodName = DebuggerUtilsEx.getLocationMethodName(location); for (StackCapturingLineBreakpoint b : captureBreakpoints) { String insertClassName = b.myCapturePoint.myInsertClassName; diff --git a/plugins/kotlin/jvm-debugger/coroutines/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LocationCache.kt b/plugins/kotlin/jvm-debugger/coroutines/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LocationCache.kt index cab8e84b20db..a6705aee20fe 100644 --- a/plugins/kotlin/jvm-debugger/coroutines/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LocationCache.kt +++ b/plugins/kotlin/jvm-debugger/coroutines/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LocationCache.kt @@ -32,6 +32,6 @@ class LocationCache(val context: DefaultExecutionContext) { } catch (ignored: AbsentInformationException) { } } - return GeneratedLocation(context.debugProcess, type, methodName, line) + return GeneratedLocation(type, methodName, line) } } \ No newline at end of file