From 741f55d89ccb1fa98b5df2f87ae5f3965d5d9594 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Fri, 29 Aug 2014 14:04:21 +0400 Subject: [PATCH] Debugger: Add filter for Kotlin specific classes #KT-2076 Fixed --- .../intellij/ui/classFilter/annotations.xml | 8 +++ .../xdebugger/settings/annotations.xml | 9 +++ .../jetbrains/jet/plugin/JetBundle.properties | 3 + idea/src/META-INF/plugin.xml | 3 + .../plugin/debugger/KotlinDebuggerSettings.kt | 63 +++++++++++++++++++ .../KotlinSteppingConfigurableUi.form | 27 ++++++++ .../KotlinSteppingConfigurableUi.java | 50 +++++++++++++++ ...inDebuggerInternalClassesFilterProvider.kt | 35 +++++++++++ .../tinyApp/outs/allFilesPresentInFilters.out | 0 .../debugger/tinyApp/outs/checkNotNull.out | 10 +++ .../debugger/tinyApp/outs/javaFun.out | 2 +- idea/testData/debugger/tinyApp/outs/npe.out | 8 +++ .../debugger/tinyApp/outs/reflectKClass.out | 8 +++ .../tinyApp/src/filters/checkNotNull.kt | 12 ++++ .../debugger/tinyApp/src/filters/npe.kt | 12 ++++ .../tinyApp/src/filters/reflectKClass.kt | 9 +++ .../tinyApp/src/stepInto/MyJavaClass.java | 7 +++ .../debugger/AbstractKotlinSteppingTest.kt | 7 ++- .../debugger/KotlinSteppingTestGenerated.java | 15 +++++ 19 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 annotations/com/intellij/ui/classFilter/annotations.xml create mode 100644 annotations/com/intellij/xdebugger/settings/annotations.xml create mode 100644 idea/src/org/jetbrains/jet/plugin/debugger/KotlinDebuggerSettings.kt create mode 100644 idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.form create mode 100644 idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.java create mode 100644 idea/src/org/jetbrains/jet/plugin/debugger/filter/KotlinDebuggerInternalClassesFilterProvider.kt create mode 100644 idea/testData/debugger/tinyApp/outs/allFilesPresentInFilters.out create mode 100644 idea/testData/debugger/tinyApp/outs/checkNotNull.out create mode 100644 idea/testData/debugger/tinyApp/outs/npe.out create mode 100644 idea/testData/debugger/tinyApp/outs/reflectKClass.out create mode 100644 idea/testData/debugger/tinyApp/src/filters/checkNotNull.kt create mode 100644 idea/testData/debugger/tinyApp/src/filters/npe.kt create mode 100644 idea/testData/debugger/tinyApp/src/filters/reflectKClass.kt diff --git a/annotations/com/intellij/ui/classFilter/annotations.xml b/annotations/com/intellij/ui/classFilter/annotations.xml new file mode 100644 index 00000000000..0fc23f66db4 --- /dev/null +++ b/annotations/com/intellij/ui/classFilter/annotations.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/annotations/com/intellij/xdebugger/settings/annotations.xml b/annotations/com/intellij/xdebugger/settings/annotations.xml new file mode 100644 index 00000000000..c18942d0d39 --- /dev/null +++ b/annotations/com/intellij/xdebugger/settings/annotations.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties index 2829928802b..18788da21ac 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -429,3 +429,6 @@ kotlin.compiler.js.option.output.prefix=Output file &prefix: kotlin.compiler.js.option.output.postfix=Output file p&ostfix: kotlin.compiler.js.option.output.prefix.browse.title=Choose output file prefix kotlin.compiler.js.option.output.postfix.browse.title=Choose output file postfix + +# Debugger +debugger.filter.ignore.internal.classes=Do not step into specific Kotlin classes diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 73e803dda25..9ada4b55fe0 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -334,6 +334,9 @@ + + + diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/KotlinDebuggerSettings.kt b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinDebuggerSettings.kt new file mode 100644 index 00000000000..4e7f89e27df --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinDebuggerSettings.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.debugger + + +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.openapi.components.StoragePathMacros +import com.intellij.openapi.options.Configurable +import com.intellij.openapi.options.SimpleConfigurable +import com.intellij.openapi.util.Getter +import com.intellij.util.xmlb.XmlSerializerUtil +import com.intellij.xdebugger.settings.DebuggerSettingsCategory +import com.intellij.xdebugger.settings.XDebuggerSettings + +import com.intellij.xdebugger.XDebuggerUtil +import com.intellij.ui.classFilter.ClassFilter +import com.intellij.debugger.settings.DebuggerSettings +import java.util.Arrays + +State(name = "KotlinDebuggerSettings", storages = array(Storage(file = StoragePathMacros.APP_CONFIG + "/kotlin_debug.xml"))) +public class KotlinDebuggerSettings : XDebuggerSettings("kotlin_debugger"), Getter { + public var DEBUG_DISABLE_KOTLIN_INTERNAL_CLASSES: Boolean = true + + class object { + public fun getInstance(): KotlinDebuggerSettings { + return XDebuggerUtil.getInstance()?.getDebuggerSettings(javaClass())!! + } + } + + override fun createConfigurables(category: DebuggerSettingsCategory): Collection { + return when (category) { + DebuggerSettingsCategory.STEPPING -> + listOf(SimpleConfigurable.create( + "reference.idesettings.debugger.kotlin", + "Kotlin", + javaClass(), + this)) + else -> listOf() + } + } + + override fun getState() = this + override fun get() = this + + override fun loadState(state: KotlinDebuggerSettings?) { + if (state != null) XmlSerializerUtil.copyBean(state, this) + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.form b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.form new file mode 100644 index 00000000000..67eedf758a0 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.form @@ -0,0 +1,27 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.java b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.java new file mode 100644 index 00000000000..5e674cfd6ca --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/debugger/KotlinSteppingConfigurableUi.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.debugger; + + +import com.intellij.openapi.options.ConfigurableUi; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public class KotlinSteppingConfigurableUi implements ConfigurableUi { + private JCheckBox ignoreKotlinMethods; + private JPanel myPanel; + + @Override + public void reset(@NotNull KotlinDebuggerSettings settings) { + boolean flag = settings.getDEBUG_DISABLE_KOTLIN_INTERNAL_CLASSES(); + ignoreKotlinMethods.setSelected(flag); + } + + @Override + public boolean isModified(@NotNull KotlinDebuggerSettings settings) { + return settings.getDEBUG_DISABLE_KOTLIN_INTERNAL_CLASSES() != ignoreKotlinMethods.isSelected(); + } + + @Override + public void apply(@NotNull KotlinDebuggerSettings settings) { + settings.setDEBUG_DISABLE_KOTLIN_INTERNAL_CLASSES(ignoreKotlinMethods.isSelected()); + } + + @NotNull + @Override + public JComponent getComponent() { + return myPanel; + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/filter/KotlinDebuggerInternalClassesFilterProvider.kt b/idea/src/org/jetbrains/jet/plugin/debugger/filter/KotlinDebuggerInternalClassesFilterProvider.kt new file mode 100644 index 00000000000..0de948da62f --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/debugger/filter/KotlinDebuggerInternalClassesFilterProvider.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.debugger.filter + +import com.intellij.ui.classFilter.DebuggerClassFilterProvider +import com.intellij.ui.classFilter.ClassFilter +import org.jetbrains.jet.plugin.debugger.KotlinDebuggerSettings + +private val FILTERS = listOf( + ClassFilter("kotlin.jvm*"), + ClassFilter("kotlin.reflect*"), + ClassFilter("kotlin.NoWhenBranchMatchedException"), + ClassFilter("kotlin.TypeCastException"), + ClassFilter("kotlin.KotlinNullPointerException") +) + +public class KotlinDebuggerInternalClassesFilterProvider : DebuggerClassFilterProvider { + override fun getFilters(): List? { + return if (KotlinDebuggerSettings.getInstance().DEBUG_DISABLE_KOTLIN_INTERNAL_CLASSES) FILTERS else listOf() + } +} diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInFilters.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInFilters.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/debugger/tinyApp/outs/checkNotNull.out b/idea/testData/debugger/tinyApp/outs/checkNotNull.out new file mode 100644 index 00000000000..291fbd5c16e --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/checkNotNull.out @@ -0,0 +1,10 @@ +LineBreakpoint created at checkNotNull.kt:8 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! checkNotNull.CheckNotNullPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +checkNotNull.kt:7 +MyJavaClass.java:11 +checkNotNull.kt:7 +checkNotNull.kt:8 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/javaFun.out b/idea/testData/debugger/tinyApp/outs/javaFun.out index 2f73ea18759..1b21f69a076 100644 --- a/idea/testData/debugger/tinyApp/outs/javaFun.out +++ b/idea/testData/debugger/tinyApp/outs/javaFun.out @@ -2,7 +2,7 @@ LineBreakpoint created at javaFun.kt:8 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! javaFun.JavaFunPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' javaFun.kt:7 -MyJavaClass.java:4 +MyJavaClass.java:6 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/npe.out b/idea/testData/debugger/tinyApp/outs/npe.out new file mode 100644 index 00000000000..560f81c2ba2 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/npe.out @@ -0,0 +1,8 @@ +LineBreakpoint created at npe.kt:7 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! npe.NpePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +npe.kt:6 +npe.kt:9 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/reflectKClass.out b/idea/testData/debugger/tinyApp/outs/reflectKClass.out new file mode 100644 index 00000000000..65930a9e8bc --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/reflectKClass.out @@ -0,0 +1,8 @@ +LineBreakpoint created at reflectKClass.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! reflectKClass.ReflectKClassPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +reflectKClass.kt:4 +reflectKClass.kt:5 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/filters/checkNotNull.kt b/idea/testData/debugger/tinyApp/src/filters/checkNotNull.kt new file mode 100644 index 00000000000..bf5f5f7580e --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/filters/checkNotNull.kt @@ -0,0 +1,12 @@ +package checkNotNull + +import stepInto.MyJavaClass + +fun main(args: Array) { + val myClass = MyJavaClass() + //Breakpoint! + val a: String = myClass.testNotNullFun() + val b = 1 +} + +// REPEAT: 3 diff --git a/idea/testData/debugger/tinyApp/src/filters/npe.kt b/idea/testData/debugger/tinyApp/src/filters/npe.kt new file mode 100644 index 00000000000..88939f2771c --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/filters/npe.kt @@ -0,0 +1,12 @@ +package npe + +fun main(args: Array) { + val a = null + try { + //Breakpoint! + a!! + } + catch (e: Exception) { + val b = 1 + } +} diff --git a/idea/testData/debugger/tinyApp/src/filters/reflectKClass.kt b/idea/testData/debugger/tinyApp/src/filters/reflectKClass.kt new file mode 100644 index 00000000000..88678fbde9e --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/filters/reflectKClass.kt @@ -0,0 +1,9 @@ +package reflectKClass + +fun main(args: Array) { + //Breakpoint! + val a = A() + val b = 1 +} + +class A diff --git a/idea/testData/debugger/tinyApp/src/stepInto/MyJavaClass.java b/idea/testData/debugger/tinyApp/src/stepInto/MyJavaClass.java index df0ea610358..de970cae48f 100644 --- a/idea/testData/debugger/tinyApp/src/stepInto/MyJavaClass.java +++ b/idea/testData/debugger/tinyApp/src/stepInto/MyJavaClass.java @@ -1,7 +1,14 @@ package stepInto; +import org.jetbrains.annotations.NotNull; + public class MyJavaClass { public void testFun() { int i = 1; } + + @NotNull + public String testNotNullFun() { + return "a"; + } } diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractKotlinSteppingTest.kt b/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractKotlinSteppingTest.kt index e35194bd1b7..0b30488c8ff 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractKotlinSteppingTest.kt +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractKotlinSteppingTest.kt @@ -51,7 +51,12 @@ public abstract class AbstractKotlinSteppingTest : KotlinDebuggerTestCase() { configureSettings(fileText) createDebugProcess(path) - onBreakpoint { stepInto() } + val count = findStringWithPrefixes(fileText, "// REPEAT: ")?.toInt() ?: 1 + + for (i in 1..count) { + onBreakpoint { stepInto() } + } + finish() } diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/KotlinSteppingTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/debugger/KotlinSteppingTestGenerated.java index 830e1b8aa65..f497675b75d 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/KotlinSteppingTestGenerated.java @@ -181,6 +181,21 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/filters"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("checkNotNull.kt") + public void testCheckNotNull() throws Exception { + doStepIntoTest("idea/testData/debugger/tinyApp/src/filters/checkNotNull.kt"); + } + + @TestMetadata("npe.kt") + public void testNpe() throws Exception { + doStepIntoTest("idea/testData/debugger/tinyApp/src/filters/npe.kt"); + } + + @TestMetadata("reflectKClass.kt") + public void testReflectKClass() throws Exception { + doStepIntoTest("idea/testData/debugger/tinyApp/src/filters/reflectKClass.kt"); + } + @TestMetadata("skipClassloader.kt") public void testSkipClassloader() throws Exception { doStepIntoTest("idea/testData/debugger/tinyApp/src/filters/skipClassloader.kt");