Debugger: Fix function breakpoints for libraries (KT-36403)
This commit is contained in:
+43
-15
@@ -13,7 +13,6 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
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.impl.PositionUtil;
|
||||
import com.intellij.debugger.jdi.ClassesByNameProvider;
|
||||
import com.intellij.debugger.jdi.MethodBytecodeUtil;
|
||||
@@ -22,7 +21,6 @@ import com.intellij.debugger.ui.breakpoints.*;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.progress.*;
|
||||
@@ -54,7 +52,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.java.debugger.breakpoints.properties.JavaMethodBreakpointProperties;
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtilsKt;
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass;
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin;
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod;
|
||||
import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile;
|
||||
import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper;
|
||||
import org.jetbrains.kotlin.idea.debugger.KotlinDebuggerCoreBundle;
|
||||
import org.jetbrains.kotlin.psi.KtClass;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
@@ -543,20 +544,22 @@ public class KotlinFunctionBreakpoint extends BreakpointWithHighlighter<JavaMeth
|
||||
MethodDescriptor descriptor = DumbService.getInstance(project).runReadActionInSmartMode(() -> {
|
||||
// MODIFICATION: Start Kotlin implementation
|
||||
PsiMethod method = resolveJvmMethodFromKotlinDeclaration(project, sourcePosition);
|
||||
// MODIFICATION: End Kotlin implementation
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
int methodOffset = method.getTextOffset();
|
||||
if (!DocumentUtil.isValidOffset(methodOffset, document) || document.getLineNumber(methodOffset) < sourcePosition.getLine()) {
|
||||
return null;
|
||||
|
||||
KtDeclaration kotlinOrigin = getSourceOrigin(method);
|
||||
|
||||
if (kotlinOrigin != null) {
|
||||
int offset = kotlinOrigin.getTextOffset();
|
||||
if (!DocumentUtil.isValidOffset(offset, document) || document.getLineNumber(offset) < sourcePosition.getLine()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
PsiIdentifier identifier = method.getNameIdentifier();
|
||||
int methodNameOffset = identifier != null? identifier.getTextOffset() : methodOffset;
|
||||
MethodDescriptor res =
|
||||
new MethodDescriptor();
|
||||
MethodDescriptor res = new MethodDescriptor();
|
||||
res.methodName = JVMNameUtil.getJVMMethodName(method);
|
||||
|
||||
try {
|
||||
res.methodSignature = JVMNameUtil.getJVMSignature(method);
|
||||
res.isStatic = method.hasModifierProperty(PsiModifier.STATIC);
|
||||
@@ -564,8 +567,9 @@ public class KotlinFunctionBreakpoint extends BreakpointWithHighlighter<JavaMeth
|
||||
catch (IndexNotReadyException ignored) {
|
||||
return null;
|
||||
}
|
||||
res.methodLine = document.getLineNumber(methodNameOffset);
|
||||
|
||||
return res;
|
||||
// MODIFICATION: End Kotlin implementation
|
||||
});
|
||||
if (descriptor == null || descriptor.methodName == null || descriptor.methodSignature == null) {
|
||||
return null;
|
||||
@@ -574,6 +578,30 @@ public class KotlinFunctionBreakpoint extends BreakpointWithHighlighter<JavaMeth
|
||||
}
|
||||
|
||||
// MODIFICATION: Start Kotlin implementation
|
||||
@Nullable
|
||||
private static KtDeclaration getSourceOrigin(PsiMethod method) {
|
||||
if (method instanceof KtLightMethod) {
|
||||
KtLightMethod lightMethod = (KtLightMethod) method;
|
||||
LightMemberOrigin lightMemberOrigin = lightMethod.getLightMemberOrigin();
|
||||
if (lightMemberOrigin != null) {
|
||||
KtDeclaration originalElement = lightMemberOrigin.getAuxiliaryOriginalElement();
|
||||
if (originalElement == null) {
|
||||
originalElement = lightMemberOrigin.getOriginalElement();
|
||||
}
|
||||
|
||||
if (originalElement != null) {
|
||||
KtDeclaration sourceOrigin = SourceNavigationHelper.INSTANCE.getNavigationElement(originalElement);
|
||||
if (sourceOrigin.getContainingFile() instanceof KtClsFile) {
|
||||
return null;
|
||||
}
|
||||
return sourceOrigin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiMethod resolveJvmMethodFromKotlinDeclaration(@NotNull Project project, @NotNull SourcePosition sourcePosition) {
|
||||
KtDeclaration declaration = PositionUtil.getPsiElementAt(project, KtDeclaration.class, sourcePosition);
|
||||
@@ -583,7 +611,7 @@ public class KotlinFunctionBreakpoint extends BreakpointWithHighlighter<JavaMeth
|
||||
if (constructor != null) {
|
||||
declaration = constructor;
|
||||
} else {
|
||||
KtLightClass lightClass = LightClassUtilsKt.toLightClass((KtClassOrObject) declaration);
|
||||
PsiClass lightClass = LightClassUtilsKt.toLightClass((KtClassOrObject) declaration);
|
||||
if (lightClass != null) {
|
||||
PsiMethod[] constructors = lightClass.getConstructors();
|
||||
if (constructors.length > 0) {
|
||||
@@ -599,7 +627,8 @@ public class KotlinFunctionBreakpoint extends BreakpointWithHighlighter<JavaMeth
|
||||
return null;
|
||||
}
|
||||
|
||||
for (PsiElement element : LightClassUtilsKt.toLightElements(declaration)) {
|
||||
KtDeclaration originalDeclaration = SourceNavigationHelper.INSTANCE.getOriginalElement(declaration);
|
||||
for (PsiElement element : LightClassUtilsKt.toLightElements(originalDeclaration)) {
|
||||
if (element instanceof PsiMethod) {
|
||||
// TODO handle all light methods
|
||||
return (PsiMethod) element;
|
||||
@@ -672,7 +701,6 @@ public class KotlinFunctionBreakpoint extends BreakpointWithHighlighter<JavaMeth
|
||||
String methodName;
|
||||
JVMName methodSignature;
|
||||
boolean isStatic;
|
||||
int methodLine;
|
||||
}
|
||||
|
||||
private static void processPreparedSubTypes(ReferenceType classType,
|
||||
|
||||
+5
@@ -1053,6 +1053,11 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
||||
runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/custom/funLiteral.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionBreakpointInStdlib.kt")
|
||||
public void testFunctionBreakpointInStdlib() throws Exception {
|
||||
runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/custom/functionBreakpointInStdlib.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionBreakpoints.kt")
|
||||
public void testFunctionBreakpoints() throws Exception {
|
||||
runTest("idea/jvm-debugger/jvm-debugger-test/testData/stepping/custom/functionBreakpoints.kt");
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
import java.io.StringReader
|
||||
|
||||
fun main() {
|
||||
val reader = StringReader("test")
|
||||
reader.readText()
|
||||
}
|
||||
|
||||
// ADDITIONAL_BREAKPOINT: ReadWrite.kt / public fun Reader.readText() / fun
|
||||
// STEP_OVER: 1
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
FunctionBreakpoint created at ReadWrite.kt:105
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
ReadWrite.!EXT!
|
||||
ReadWrite.!EXT!
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
Reference in New Issue
Block a user