diff --git a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt index 7aacadc89ec..c5bf9aee51b 100644 --- a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt +++ b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt @@ -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() } diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/javaStaticMethods.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/javaStaticMethods.kt new file mode 100644 index 00000000000..aace99113b0 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/javaStaticMethods.kt @@ -0,0 +1,11 @@ +package javaStaticMethods + +import forTests.javaContext.JavaClass.JavaStatic + +fun main() { + //Breakpoint! + val a = 5 +} + +// EXPRESSION: JavaStatic.state() +// RESULT: 1: I diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/javaStaticMethods.out b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/javaStaticMethods.out new file mode 100644 index 00000000000..dc31802b5ad --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/javaStaticMethods.out @@ -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 diff --git a/idea/testData/debugger/tinyApp/src/forTests/javaContext/JavaClass.java b/idea/testData/debugger/tinyApp/src/forTests/javaContext/JavaClass.java index 4d36b3a827d..63bb9e0618f 100644 --- a/idea/testData/debugger/tinyApp/src/forTests/javaContext/JavaClass.java +++ b/idea/testData/debugger/tinyApp/src/forTests/javaContext/JavaClass.java @@ -46,4 +46,8 @@ public class JavaClass { public void property() { int breakpoint = 1; } + + public interface JavaStatic { + static int state() { return 1; } + } } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java index e88e8037051..4a6e7d96656 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java @@ -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 options = Arrays.asList("-d", outputDirPath, "-classpath", diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java.173 b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java.173 index f9df9b06f07..b021517f724 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java.173 +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java.173 @@ -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 options = Arrays.asList("-d", outputDirPath, "-classpath", diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index e4861e6cd15..d39ea12965a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -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");