From f28f7eaa3ba01babb2a3a081def7f33db7b01247 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Thu, 21 Jan 2016 10:41:51 +0300 Subject: [PATCH] ExtraSteppingFilter: do not compute classNames for inline --- .../kotlin/idea/ExtraSteppingFilter.kt | 17 ++--- .../idea/debugger/KotlinPositionManager.kt | 75 ++++++++++--------- .../debugger/KotlinPositionManagerCache.kt | 4 +- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/ExtraSteppingFilter.kt b/idea/src/org/jetbrains/kotlin/idea/ExtraSteppingFilter.kt index a5ea51a5859..c80d1ed0906 100644 --- a/idea/src/org/jetbrains/kotlin/idea/ExtraSteppingFilter.kt +++ b/idea/src/org/jetbrains/kotlin/idea/ExtraSteppingFilter.kt @@ -56,16 +56,13 @@ class ExtraSteppingFilter : com.intellij.debugger.engine.ExtraSteppingFilter { if (sourcePosition == null) return false - val classNames = positionManager.classNamesForPosition(sourcePosition, false).map { it.replace('/', '.') } - - classNames.forEach { className -> - val settings = DebuggerSettings.getInstance() - if (settings.TRACING_FILTERS_ENABLED) { - for (filter in settings.steppingFilters) { - if (filter.isEnabled) { - if (filter.matches(className)) { - return true - } + val settings = DebuggerSettings.getInstance() + if (settings.TRACING_FILTERS_ENABLED) { + val className = positionManager.originalClassNameForPosition(sourcePosition)?.replace('/', '.') ?: return false + for (filter in settings.steppingFilters) { + if (filter.isEnabled) { + if (filter.matches(className)) { + return true } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt index 04d302765f8..98557c9d2a7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt @@ -229,7 +229,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq if (!ProjectRootsUtil.isInProjectOrLibSource(psiFile)) return result - val names = classNamesForPositionAndInlinedOnes(sourcePosition) + val names = classNamesForPosition(sourcePosition) for (name in names) { result.addAll(myDebugProcess.virtualMachineProxy.classesByName(name)) } @@ -248,38 +248,26 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq throw NoDataException.INSTANCE } - private fun classNamesForPositionAndInlinedOnes(sourcePosition: SourcePosition): List { - val result = hashSetOf() - val names = classNamesForPosition(sourcePosition) - result.addAll(names) + fun originalClassNameForPosition(sourcePosition: SourcePosition): String? { + return classNamesForPosition(sourcePosition).firstOrNull() + } + + private fun classNamesForPosition(sourcePosition: SourcePosition): List { + val element = runReadAction { sourcePosition.elementAt } ?: return emptyList() + val names = classNamesForPosition(element) val lambdas = findLambdas(sourcePosition) - result.addAll(lambdas) - - return result.toReadOnlyList(); - } - - private fun findLambdas(sourcePosition: SourcePosition): Collection { - return runReadAction { - val lambdas = getLambdasAtLineIfAny(sourcePosition) - val file = sourcePosition.file.containingFile as KtFile - val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != null - lambdas.flatMap { - val typeMapper = KotlinPositionManagerCache.getOrCreateTypeMapper(it) - getInternalClassNameForElement(it, typeMapper, file, isInLibrary) - } + if (lambdas.isEmpty()) { + return names } + + return names + lambdas } - fun classNamesForPosition(sourcePosition: SourcePosition): Collection { - val psiElement = runReadAction { sourcePosition.elementAt } ?: return emptyList() - return classNamesForPosition(psiElement) - } - - private fun classNamesForPosition(element: PsiElement): Collection { + private fun classNamesForPosition(element: PsiElement): List { return runReadAction { if (DumbService.getInstance(element.project).isDumb) { - emptySet() + emptyList() } else { KotlinPositionManagerCache.getOrComputeClassNames(element) { @@ -294,6 +282,18 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq } } + private fun findLambdas(sourcePosition: SourcePosition): Collection { + return runReadAction { + val lambdas = getLambdasAtLineIfAny(sourcePosition) + val file = sourcePosition.file.containingFile as KtFile + val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != null + lambdas.flatMap { + val typeMapper = KotlinPositionManagerCache.getOrCreateTypeMapper(it) + getInternalClassNameForElement(it, typeMapper, file, isInLibrary) + } + } + } + override fun locationsOfLine(type: ReferenceType, position: SourcePosition): List { if (position.file !is KtFile) { throw NoDataException.INSTANCE @@ -322,27 +322,28 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq throw NoDataException.INSTANCE } - return classNamesForPositionAndInlinedOnes(position).mapNotNull { + return classNamesForPosition(position).mapNotNull { className -> myDebugProcess.requestsManager.createClassPrepareRequest(requestor, className.replace('/', '.')) } } + // The order is used in ExtraSteppingFilter: original className should be the first private fun getInternalClassNameForElement( notPositionedElement: PsiElement?, typeMapper: JetTypeMapper, file: KtFile, isInLibrary: Boolean - ): Collection { + ): List { val element = getElementToCalculateClassName(notPositionedElement) when (element) { - is KtClassOrObject -> return getJvmInternalNameForImpl(typeMapper, element).toSet() + is KtClassOrObject -> return getJvmInternalNameForImpl(typeMapper, element).toList() is KtFunction -> { val descriptor = InlineUtil.getInlineArgumentDescriptor(element, typeMapper.bindingContext) if (descriptor != null) { val classNamesForParent = getInternalClassNameForElement(element.parent, typeMapper, file, isInLibrary) if (descriptor.isCrossinline) { - return findCrossInlineArguments(element, descriptor, typeMapper.bindingContext) + classNamesForParent + return classNamesForParent + findCrossInlineArguments(element, descriptor, typeMapper.bindingContext) } return classNamesForParent } @@ -351,13 +352,13 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq val crossInlineParameterUsages = element?.containsCrossInlineParameterUsages(typeMapper.bindingContext) if (crossInlineParameterUsages != null && crossInlineParameterUsages.isNotEmpty()) { - return classNamesForCrossInlineParameters(crossInlineParameterUsages, typeMapper.bindingContext) + return classNamesForCrossInlineParameters(crossInlineParameterUsages, typeMapper.bindingContext).toList() } when { element is KtFunctionLiteral -> { val asmType = CodegenBinding.asmTypeForAnonymousClass(typeMapper.bindingContext, element) - return asmType.internalName.toSet() + return asmType.internalName.toList() } element is KtAnonymousInitializer -> { val parent = getElementToCalculateClassName(element.parent) @@ -371,7 +372,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq if (isInPropertyAccessor(notPositionedElement)) { val classOrObject = PsiTreeUtil.getParentOfType(element, KtClassOrObject::class.java) if (classOrObject != null) { - return getJvmInternalNameForImpl(typeMapper, classOrObject).toSet() + return getJvmInternalNameForImpl(typeMapper, classOrObject).toList() } } @@ -380,7 +381,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq return getInternalClassNameForElement(element.parent, typeMapper, file, isInLibrary) } - return getJvmInternalNameForPropertyOwner(typeMapper, descriptor).toSet() + return getJvmInternalNameForPropertyOwner(typeMapper, descriptor).toList() } element is KtNamedFunction -> { val parent = getElementToCalculateClassName(element.parent) @@ -396,11 +397,11 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq } val inlinedCalls = findInlinedCalls(element, typeMapper.bindingContext) - return inlinedCalls + parentInternalName.toSet() + return parentInternalName.toList() + inlinedCalls } } - return NoResolveFileClassesProvider.getFileClassInternalName(file).toSet() + return NoResolveFileClassesProvider.getFileClassInternalName(file).toList() } private val TYPES_TO_CALCULATE_CLASSNAME: Array> = @@ -537,5 +538,5 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq private fun ReferenceType.containsKotlinStrata() = availableStrata().contains("Kotlin") - private fun String?.toSet() = if (this == null) emptySet() else setOf(this) + private fun String?.toList() = if (this == null) emptyList() else listOf(this) } diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManagerCache.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManagerCache.kt index 047a10dd9f1..1f16b7667f7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManagerCache.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManagerCache.kt @@ -38,7 +38,7 @@ class KotlinPositionManagerCache(private val project: Project) { private val cachedClassNames = CachedValuesManager.getManager(project).createCachedValue( { - CachedValueProvider.Result>>( + CachedValueProvider.Result>>( hashMapOf(), PsiModificationTracker.MODIFICATION_COUNT) }, false) @@ -49,7 +49,7 @@ class KotlinPositionManagerCache(private val project: Project) { }, false) companion object { - fun getOrComputeClassNames(psiElement: PsiElement, create: (PsiElement) -> Collection): Collection { + fun getOrComputeClassNames(psiElement: PsiElement, create: (PsiElement) -> List): List { val cache = getInstance(psiElement.project) synchronized(cache.cachedClassNames) { val classNamesCache = cache.cachedClassNames.value