ExtraSteppingFilter: do not compute classNames for inline

This commit is contained in:
Natalia Ukhorskaya
2016-01-21 10:41:51 +03:00
parent 876e458c04
commit f28f7eaa3b
3 changed files with 47 additions and 49 deletions
@@ -56,16 +56,13 @@ class ExtraSteppingFilter : com.intellij.debugger.engine.ExtraSteppingFilter {
if (sourcePosition == null) return false if (sourcePosition == null) return false
val classNames = positionManager.classNamesForPosition(sourcePosition, false).map { it.replace('/', '.') } val settings = DebuggerSettings.getInstance()
if (settings.TRACING_FILTERS_ENABLED) {
classNames.forEach { className -> val className = positionManager.originalClassNameForPosition(sourcePosition)?.replace('/', '.') ?: return false
val settings = DebuggerSettings.getInstance() for (filter in settings.steppingFilters) {
if (settings.TRACING_FILTERS_ENABLED) { if (filter.isEnabled) {
for (filter in settings.steppingFilters) { if (filter.matches(className)) {
if (filter.isEnabled) { return true
if (filter.matches(className)) {
return true
}
} }
} }
} }
@@ -229,7 +229,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
if (!ProjectRootsUtil.isInProjectOrLibSource(psiFile)) return result if (!ProjectRootsUtil.isInProjectOrLibSource(psiFile)) return result
val names = classNamesForPositionAndInlinedOnes(sourcePosition) val names = classNamesForPosition(sourcePosition)
for (name in names) { for (name in names) {
result.addAll(myDebugProcess.virtualMachineProxy.classesByName(name)) result.addAll(myDebugProcess.virtualMachineProxy.classesByName(name))
} }
@@ -248,38 +248,26 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
throw NoDataException.INSTANCE throw NoDataException.INSTANCE
} }
private fun classNamesForPositionAndInlinedOnes(sourcePosition: SourcePosition): List<String> { fun originalClassNameForPosition(sourcePosition: SourcePosition): String? {
val result = hashSetOf<String>() return classNamesForPosition(sourcePosition).firstOrNull()
val names = classNamesForPosition(sourcePosition) }
result.addAll(names)
private fun classNamesForPosition(sourcePosition: SourcePosition): List<String> {
val element = runReadAction { sourcePosition.elementAt } ?: return emptyList()
val names = classNamesForPosition(element)
val lambdas = findLambdas(sourcePosition) val lambdas = findLambdas(sourcePosition)
result.addAll(lambdas) if (lambdas.isEmpty()) {
return names
return result.toReadOnlyList();
}
private fun findLambdas(sourcePosition: SourcePosition): Collection<String> {
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)
}
} }
return names + lambdas
} }
fun classNamesForPosition(sourcePosition: SourcePosition): Collection<String> { private fun classNamesForPosition(element: PsiElement): List<String> {
val psiElement = runReadAction { sourcePosition.elementAt } ?: return emptyList()
return classNamesForPosition(psiElement)
}
private fun classNamesForPosition(element: PsiElement): Collection<String> {
return runReadAction { return runReadAction {
if (DumbService.getInstance(element.project).isDumb) { if (DumbService.getInstance(element.project).isDumb) {
emptySet() emptyList()
} }
else { else {
KotlinPositionManagerCache.getOrComputeClassNames(element) { KotlinPositionManagerCache.getOrComputeClassNames(element) {
@@ -294,6 +282,18 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
} }
} }
private fun findLambdas(sourcePosition: SourcePosition): Collection<String> {
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<Location> { override fun locationsOfLine(type: ReferenceType, position: SourcePosition): List<Location> {
if (position.file !is KtFile) { if (position.file !is KtFile) {
throw NoDataException.INSTANCE throw NoDataException.INSTANCE
@@ -322,27 +322,28 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
throw NoDataException.INSTANCE throw NoDataException.INSTANCE
} }
return classNamesForPositionAndInlinedOnes(position).mapNotNull { return classNamesForPosition(position).mapNotNull {
className -> myDebugProcess.requestsManager.createClassPrepareRequest(requestor, className.replace('/', '.')) className -> myDebugProcess.requestsManager.createClassPrepareRequest(requestor, className.replace('/', '.'))
} }
} }
// The order is used in ExtraSteppingFilter: original className should be the first
private fun getInternalClassNameForElement( private fun getInternalClassNameForElement(
notPositionedElement: PsiElement?, notPositionedElement: PsiElement?,
typeMapper: JetTypeMapper, typeMapper: JetTypeMapper,
file: KtFile, file: KtFile,
isInLibrary: Boolean isInLibrary: Boolean
): Collection<String> { ): List<String> {
val element = getElementToCalculateClassName(notPositionedElement) val element = getElementToCalculateClassName(notPositionedElement)
when (element) { when (element) {
is KtClassOrObject -> return getJvmInternalNameForImpl(typeMapper, element).toSet() is KtClassOrObject -> return getJvmInternalNameForImpl(typeMapper, element).toList()
is KtFunction -> { is KtFunction -> {
val descriptor = InlineUtil.getInlineArgumentDescriptor(element, typeMapper.bindingContext) val descriptor = InlineUtil.getInlineArgumentDescriptor(element, typeMapper.bindingContext)
if (descriptor != null) { if (descriptor != null) {
val classNamesForParent = getInternalClassNameForElement(element.parent, typeMapper, file, isInLibrary) val classNamesForParent = getInternalClassNameForElement(element.parent, typeMapper, file, isInLibrary)
if (descriptor.isCrossinline) { if (descriptor.isCrossinline) {
return findCrossInlineArguments(element, descriptor, typeMapper.bindingContext) + classNamesForParent return classNamesForParent + findCrossInlineArguments(element, descriptor, typeMapper.bindingContext)
} }
return classNamesForParent return classNamesForParent
} }
@@ -351,13 +352,13 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
val crossInlineParameterUsages = element?.containsCrossInlineParameterUsages(typeMapper.bindingContext) val crossInlineParameterUsages = element?.containsCrossInlineParameterUsages(typeMapper.bindingContext)
if (crossInlineParameterUsages != null && crossInlineParameterUsages.isNotEmpty()) { if (crossInlineParameterUsages != null && crossInlineParameterUsages.isNotEmpty()) {
return classNamesForCrossInlineParameters(crossInlineParameterUsages, typeMapper.bindingContext) return classNamesForCrossInlineParameters(crossInlineParameterUsages, typeMapper.bindingContext).toList()
} }
when { when {
element is KtFunctionLiteral -> { element is KtFunctionLiteral -> {
val asmType = CodegenBinding.asmTypeForAnonymousClass(typeMapper.bindingContext, element) val asmType = CodegenBinding.asmTypeForAnonymousClass(typeMapper.bindingContext, element)
return asmType.internalName.toSet() return asmType.internalName.toList()
} }
element is KtAnonymousInitializer -> { element is KtAnonymousInitializer -> {
val parent = getElementToCalculateClassName(element.parent) val parent = getElementToCalculateClassName(element.parent)
@@ -371,7 +372,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
if (isInPropertyAccessor(notPositionedElement)) { if (isInPropertyAccessor(notPositionedElement)) {
val classOrObject = PsiTreeUtil.getParentOfType(element, KtClassOrObject::class.java) val classOrObject = PsiTreeUtil.getParentOfType(element, KtClassOrObject::class.java)
if (classOrObject != null) { 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 getInternalClassNameForElement(element.parent, typeMapper, file, isInLibrary)
} }
return getJvmInternalNameForPropertyOwner(typeMapper, descriptor).toSet() return getJvmInternalNameForPropertyOwner(typeMapper, descriptor).toList()
} }
element is KtNamedFunction -> { element is KtNamedFunction -> {
val parent = getElementToCalculateClassName(element.parent) val parent = getElementToCalculateClassName(element.parent)
@@ -396,11 +397,11 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
} }
val inlinedCalls = findInlinedCalls(element, typeMapper.bindingContext) 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<Class<out KtElement>> = private val TYPES_TO_CALCULATE_CLASSNAME: Array<Class<out KtElement>> =
@@ -537,5 +538,5 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
private fun ReferenceType.containsKotlinStrata() = availableStrata().contains("Kotlin") 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)
} }
@@ -38,7 +38,7 @@ class KotlinPositionManagerCache(private val project: Project) {
private val cachedClassNames = CachedValuesManager.getManager(project).createCachedValue( private val cachedClassNames = CachedValuesManager.getManager(project).createCachedValue(
{ {
CachedValueProvider.Result<HashMap<PsiElement, Collection<String>>>( CachedValueProvider.Result<HashMap<PsiElement, List<String>>>(
hashMapOf(), PsiModificationTracker.MODIFICATION_COUNT) hashMapOf(), PsiModificationTracker.MODIFICATION_COUNT)
}, false) }, false)
@@ -49,7 +49,7 @@ class KotlinPositionManagerCache(private val project: Project) {
}, false) }, false)
companion object { companion object {
fun getOrComputeClassNames(psiElement: PsiElement, create: (PsiElement) -> Collection<String>): Collection<String> { fun getOrComputeClassNames(psiElement: PsiElement, create: (PsiElement) -> List<String>): List<String> {
val cache = getInstance(psiElement.project) val cache = getInstance(psiElement.project)
synchronized(cache.cachedClassNames) { synchronized(cache.cachedClassNames) {
val classNamesCache = cache.cachedClassNames.value val classNamesCache = cache.cachedClassNames.value