diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 12a8a36a030..a20598ccd35 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -386,6 +386,7 @@ + diff --git a/idea/src/org/jetbrains/kotlin/idea/ExtraSteppingFilter.kt b/idea/src/org/jetbrains/kotlin/idea/ExtraSteppingFilter.kt new file mode 100644 index 00000000000..ad52b721093 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/ExtraSteppingFilter.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2015 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.kotlin.idea + +import com.intellij.debugger.engine +import com.intellij.debugger.engine.SuspendContext +import org.jetbrains.kotlin.idea.debugger.JetPositionManager +import com.sun.jdi.Location +import org.jetbrains.kotlin.idea.util.application.runReadAction +import com.intellij.debugger.NoDataException +import com.sun.jdi.request.StepRequest +import java.util.regex.Pattern +import java.util.WeakHashMap +import com.intellij.openapi.extensions.Extensions +import com.intellij.ui.classFilter.DebuggerClassFilterProvider +import com.intellij.debugger.settings.DebuggerSettings + +public class ExtraSteppingFilter : engine.ExtraSteppingFilter { + + override fun isApplicable(context: SuspendContext?): Boolean { + if (context == null) { + return false; + } + + val debugProcess = context.getDebugProcess() + val positionManager = JetPositionManager(debugProcess) + val location = context.getFrameProxy().location() + return runReadAction { + shouldFilter(positionManager, location) + } + } + + + private fun shouldFilter(positionManager: JetPositionManager, location: Location): Boolean { + val defaultStrata = location.declaringType().defaultStratum() + if ("Kotlin" != defaultStrata) { + return false; + } + + val sourcePosition = + try { + positionManager.getSourcePosition(location) + } + catch(e: NoDataException) { + return false + } + + if (sourcePosition == null) return false + + val className = positionManager.classNameForPosition(sourcePosition)?.replace('/', '.') ?: return false + + val settings = DebuggerSettings.getInstance() + if (settings.TRACING_FILTERS_ENABLED) { + for (filter in settings.getSteppingFilters()) { + if (filter.isEnabled()) { + if (filter.matches(className)) { + return true; + } + } + } + } + + return false; + } + + override fun getStepRequestDepth(context: SuspendContext?): Int { + return StepRequest.STEP_INTO + } +} + diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt index f1f183fe96e..86478452b3f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt @@ -119,7 +119,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult continue } - val internalClassName = getClassNameForElement(literal.getFirstChild(), typeMapper, file, isInLibrary).className + val internalClassName = getInternalClassNameForElement(literal.getFirstChild(), typeMapper, file, isInLibrary).className if (internalClassName == currentLocationClassName) { return functionLiteral } @@ -191,7 +191,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult return result; } - private fun classNameForPosition(sourcePosition: SourcePosition): String? { + public fun classNameForPosition(sourcePosition: SourcePosition): String? { val psiElement = sourcePosition.getElementAt() if (psiElement == null) { return null @@ -204,7 +204,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult val file = element.getContainingFile() as JetFile val isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null val typeMapper = if (!isInLibrary) prepareTypeMapper(file) else createTypeMapperForLibraryFile(element, file) - getClassNameForElement(element, typeMapper, file, isInLibrary).className + getInternalClassNameForElement(element, typeMapper, file, isInLibrary).className } } @@ -293,13 +293,13 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult return state.getTypeMapper() } - public fun getClassNameForElement(notPositionedElement: PsiElement?, typeMapper: JetTypeMapper, file: JetFile, isInLibrary: Boolean): PositionedElement { + public fun getInternalClassNameForElement(notPositionedElement: PsiElement?, typeMapper: JetTypeMapper, file: JetFile, isInLibrary: Boolean): PositionedElement { val element = getElementToCalculateClassName(notPositionedElement) when { element is JetClassOrObject -> return PositionedElement(getJvmInternalNameForImpl(typeMapper, element), element) element is JetFunctionLiteral -> { if (isInlinedLambda(element, typeMapper.getBindingContext())) { - return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary) + return getInternalClassNameForElement(element.getParent(), typeMapper, file, isInLibrary) } else { val asmType = CodegenBinding.asmTypeForAnonymousClass(typeMapper.getBindingContext(), element) @@ -310,9 +310,9 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult val parent = getElementToCalculateClassName(element.getParent()) // Class-object initializer if (parent is JetObjectDeclaration && parent.isDefault()) { - return PositionedElement(getClassNameForElement(parent.getParent(), typeMapper, file, isInLibrary).className, parent) + return PositionedElement(getInternalClassNameForElement(parent.getParent(), typeMapper, file, isInLibrary).className, parent) } - return getClassNameForElement(element, typeMapper, file, isInLibrary) + return getInternalClassNameForElement(element, typeMapper, file, isInLibrary) } element is JetProperty && (!element.isTopLevel() || !isInLibrary) -> { if (isInPropertyAccessor(notPositionedElement)) { @@ -324,7 +324,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult val descriptor = typeMapper.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element) if (descriptor !is PropertyDescriptor) { - return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary) + return getInternalClassNameForElement(element.getParent(), typeMapper, file, isInLibrary) } return PositionedElement(getJvmInternalNameForPropertyOwner(typeMapper, descriptor), element) @@ -441,7 +441,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult if (element != null && jetFile is JetFile) { val isInLibrary = LibraryUtil.findLibraryEntry(jetFile.getVirtualFile(), jetFile.getProject()) != null val typeMapper = if (!isInLibrary) prepareTypeMapper(jetFile) else createTypeMapperForLibraryFile(element, jetFile) - val psiElement = getClassNameForElement(element, typeMapper, jetFile, isInLibrary).element; + val psiElement = getInternalClassNameForElement(element, typeMapper, jetFile, isInLibrary).element; if (psiElement is JetNamedFunction) { val descriptor = typeMapper.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement)