Fix evaluation for static interface methods declared in Java (KT-23585)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.eval4j.jdi
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.sun.jdi.*
|
||||
import org.jetbrains.eval4j.*
|
||||
import org.jetbrains.eval4j.Value
|
||||
@@ -48,6 +49,8 @@ class JDIEval(
|
||||
Type.DOUBLE_TYPE.className to vm.mirrorOf(1.0).type()
|
||||
)
|
||||
|
||||
private val isJava8OrLater = StringUtil.compareVersionNumbers(vm.version(), "1.8") >= 0
|
||||
|
||||
override fun loadClass(classType: Type): Value {
|
||||
return loadClass(classType, defaultClassLoader)
|
||||
}
|
||||
@@ -251,17 +254,33 @@ class JDIEval(
|
||||
if (!method.isStatic) {
|
||||
throwBrokenCodeException(NoSuchMethodError("Method is not static: $methodDesc"))
|
||||
}
|
||||
val _class = method.declaringType()
|
||||
if (_class !is ClassType) throwBrokenCodeException(NoSuchMethodError("Static method is a non-class type: $method"))
|
||||
|
||||
val declaringType = method.declaringType()
|
||||
val args = mapArguments(arguments, method.safeArgumentTypes())
|
||||
|
||||
if (shouldInvokeMethodWithReflection(method, args)) {
|
||||
return invokeMethodWithReflection(_class.asType(), NULL_VALUE, args, methodDesc)
|
||||
return invokeMethodWithReflection(declaringType.asType(), NULL_VALUE, args, methodDesc)
|
||||
}
|
||||
|
||||
args.disableCollection()
|
||||
val result = mayThrow { _class.invokeMethod(thread, method, args, invokePolicy) }.ifFail(method)
|
||||
|
||||
val result = mayThrow {
|
||||
when (declaringType) {
|
||||
is ClassType -> declaringType.invokeMethod(thread, method, args, invokePolicy)
|
||||
is InterfaceType -> {
|
||||
if (!isJava8OrLater) {
|
||||
val message = "Calling interface static methods is not supported in JVM ${vm.version()} ($method)"
|
||||
throwBrokenCodeException(NoSuchMethodError(message))
|
||||
}
|
||||
|
||||
declaringType.invokeMethod(thread, method, args, invokePolicy)
|
||||
}
|
||||
else -> {
|
||||
val message = "Calling static methods is only supported for classes and interfaces ($method)"
|
||||
throwBrokenCodeException(NoSuchMethodError(message))
|
||||
}
|
||||
}
|
||||
}.ifFail(method)
|
||||
|
||||
args.enableCollection()
|
||||
return result.asValue()
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package javaStaticMethods
|
||||
|
||||
import forTests.javaContext.JavaClass.JavaStatic
|
||||
|
||||
fun main() {
|
||||
//Breakpoint!
|
||||
val a = 5
|
||||
}
|
||||
|
||||
// EXPRESSION: JavaStatic.state()
|
||||
// RESULT: 1: I
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
LineBreakpoint created at javaStaticMethods.kt:7
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
javaStaticMethods.kt:7
|
||||
Compile bytecode for JavaStatic.state()
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
@@ -46,4 +46,8 @@ public class JavaClass {
|
||||
public void property() {
|
||||
int breakpoint = 1;
|
||||
}
|
||||
|
||||
public interface JavaStatic {
|
||||
static int state() { return 1; }
|
||||
}
|
||||
}
|
||||
@@ -41,11 +41,15 @@ import com.intellij.testFramework.EdtTestUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.io.FilesKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.asJava.classes.FakeLightClassForFileOfPackage;
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade;
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder;
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil;
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
@@ -89,6 +93,9 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
protected static final String KOTLIN_LIBRARY_NAME = "KotlinLibrary";
|
||||
private static final String CUSTOM_LIBRARY_NAME = "CustomLibrary";
|
||||
|
||||
@Nullable
|
||||
private String oldJvmTarget = null;
|
||||
|
||||
@Override
|
||||
protected OutputChecker initOutputChecker() {
|
||||
return new KotlinOutputChecker(
|
||||
@@ -128,6 +135,12 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(true);
|
||||
}
|
||||
super.setUp();
|
||||
|
||||
Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(myProject).update(s -> {
|
||||
oldJvmTarget = s.getJvmTarget();
|
||||
s.setJvmTarget("1.8");
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
|
||||
private static void deleteLocalCacheDirectory(boolean assertDeleteSuccess) {
|
||||
@@ -215,6 +228,11 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(myProject).update(s -> {
|
||||
s.setJvmTarget(oldJvmTarget);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
||||
if (DexLikeBytecodePatchKt.needDexPatch(getTestName(true))) {
|
||||
NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(false);
|
||||
}
|
||||
@@ -233,7 +251,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
protected void setUpModule() {
|
||||
super.setUpModule();
|
||||
|
||||
IdeaTestUtil.setModuleLanguageLevel(myModule, LanguageLevel.JDK_1_6);
|
||||
IdeaTestUtil.setModuleLanguageLevel(myModule, LanguageLevel.JDK_1_8);
|
||||
|
||||
String outputDirPath = getAppOutputPath();
|
||||
File outDir = new File(outputDirPath);
|
||||
@@ -249,7 +267,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
|
||||
String sourcesDir = modulePath + File.separator + "src";
|
||||
|
||||
MockLibraryUtil.compileKotlin(sourcesDir, outDir, CUSTOM_LIBRARY_JAR.getPath());
|
||||
MockLibraryUtil.compileKotlin(sourcesDir, outDir, CollectionsKt.listOf("-jvm-target", "1.8"), CUSTOM_LIBRARY_JAR.getPath());
|
||||
|
||||
List<String> options =
|
||||
Arrays.asList("-d", outputDirPath, "-classpath",
|
||||
|
||||
@@ -41,11 +41,15 @@ import com.intellij.testFramework.EdtTestUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.io.FilesKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.asJava.classes.FakeLightClassForFileOfPackage;
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade;
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder;
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil;
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
@@ -89,6 +93,9 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
protected static final String KOTLIN_LIBRARY_NAME = "KotlinLibrary";
|
||||
private static final String CUSTOM_LIBRARY_NAME = "CustomLibrary";
|
||||
|
||||
@Nullable
|
||||
private String oldJvmTarget = null;
|
||||
|
||||
@Override
|
||||
protected OutputChecker initOutputChecker() {
|
||||
return new KotlinOutputChecker(
|
||||
@@ -128,6 +135,12 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(true);
|
||||
}
|
||||
super.setUp();
|
||||
|
||||
Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(myProject).update(s -> {
|
||||
oldJvmTarget = s.getJvmTarget();
|
||||
s.setJvmTarget("1.8");
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -245,6 +258,11 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(myProject).update(s -> {
|
||||
s.setJvmTarget(oldJvmTarget);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
||||
if (DexLikeBytecodePatchKt.needDexPatch(getTestName(true))) {
|
||||
NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(false);
|
||||
}
|
||||
@@ -263,7 +281,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
protected void setUpModule() {
|
||||
super.setUpModule();
|
||||
|
||||
IdeaTestUtil.setModuleLanguageLevel(myModule, LanguageLevel.JDK_1_6);
|
||||
IdeaTestUtil.setModuleLanguageLevel(myModule, LanguageLevel.JDK_1_8);
|
||||
|
||||
String outputDirPath = getAppOutputPath();
|
||||
File outDir = new File(outputDirPath);
|
||||
@@ -279,7 +297,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
|
||||
String sourcesDir = modulePath + File.separator + "src";
|
||||
|
||||
MockLibraryUtil.compileKotlin(sourcesDir, outDir, CUSTOM_LIBRARY_JAR.getPath());
|
||||
MockLibraryUtil.compileKotlin(sourcesDir, outDir, CollectionsKt.listOf("-jvm-target", "1.8"), CUSTOM_LIBRARY_JAR.getPath());
|
||||
|
||||
List<String> options =
|
||||
Arrays.asList("-d", outputDirPath, "-classpath",
|
||||
|
||||
Generated
+5
@@ -206,6 +206,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/internalProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaStaticMethods.kt")
|
||||
public void testJavaStaticMethods() throws Exception {
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/javaStaticMethods.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt12206BasePropertyWithoutBackingField.kt")
|
||||
public void testKt12206BasePropertyWithoutBackingField() throws Exception {
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt12206BasePropertyWithoutBackingField.kt");
|
||||
|
||||
Reference in New Issue
Block a user