From 0d4fa46cfa6d7a55e5824134eb9569ea99d95b79 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Mon, 4 Apr 2016 16:31:18 +0300 Subject: [PATCH] Debugger: correct scope for runtime type calculation --- ChangeLog.md | 1 + .../kotlin/idea/debugger/evaluate/FrameVisitor.kt | 7 +++---- .../debugger/evaluate/KotlinCodeFragmentFactory.kt | 2 +- .../idea/debugger/evaluate/KotlinDebuggerCaches.kt | 2 +- .../debugger/evaluate/KotlinEvaluationBuilder.kt | 5 ++--- .../debugger/evaluate/KotlinRuntimeTypeEvaluator.kt | 12 ++++++------ 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 7401a0c2bf3..b8ced29c2f5 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -189,6 +189,7 @@ Issues fixed: - [KT-6805](https://youtrack.jetbrains.com/issue/KT-6805) Convert Java expression to Kotlin when opening Evaluate Expression from Variables view - Show error message when debug info for some local variable is corrupted - Avoid 1s delay in completion in debugger fields if session is not stopped on a breakpoint +- Avoid cast to runtime type unavailable in current scope ### Java to Kotlin converter diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/FrameVisitor.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/FrameVisitor.kt index 9908ff913ec..a48cbdbe21b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/FrameVisitor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/FrameVisitor.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.org.objectweb.asm.Type class FrameVisitor(context: EvaluationContextImpl) { - private val project = context.debugProcess.project + private val scope = context.debugProcess.searchScope private val frame = context.frameProxy companion object { @@ -177,7 +177,6 @@ class FrameVisitor(context: EvaluationContextImpl) { private fun isValueOfCorrectType(value: Value, asmType: Type?, shouldCheckType: Boolean): Boolean { if (!shouldCheckType || asmType == null || value.asmType == asmType) return true - if (project == null) return false if (asmType == OBJECT_TYPE) return true @@ -185,8 +184,8 @@ class FrameVisitor(context: EvaluationContextImpl) { return true } - val thisDesc = value.asmType.getClassDescriptor(project) - val expDesc = asmType.getClassDescriptor(project) + val thisDesc = value.asmType.getClassDescriptor(scope) + val expDesc = asmType.getClassDescriptor(scope) return thisDesc != null && expDesc != null && runReadAction { DescriptorUtils.isSubclass(thisDesc, expDesc) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt index cb772895e08..f758a7fd46d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt @@ -262,7 +262,7 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() { } private fun createKotlinProperty(project: Project, variableName: String, variableTypeName: String, value: Value): String? { - val actualClassDescriptor = value.asValue().asmType.getClassDescriptor(project) + val actualClassDescriptor = value.asValue().asmType.getClassDescriptor(GlobalSearchScope.allScope(project)) if (actualClassDescriptor != null && actualClassDescriptor.defaultType.arguments.isEmpty()) { val renderedType = IdeDescriptorRenderers.SOURCE_CODE.renderType(actualClassDescriptor.defaultType.makeNullable()) return "val ${variableName.quoteIfNeeded()}: $renderedType = null" diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerCaches.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerCaches.kt index e848dee1152..5575921d168 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerCaches.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerCaches.kt @@ -187,7 +187,7 @@ class KotlinDebuggerCaches(private val project: Project) { val value = frameVisitor.findValue(name, asmType = null, checkType = false, failIfNotFound = false) if (value == null) return@all false - val thisDescriptor = value.asmType.getClassDescriptor(project) + val thisDescriptor = value.asmType.getClassDescriptor(context.debugProcess.searchScope) val superClassDescriptor = jetType.constructor.declarationDescriptor as? ClassDescriptor return@all thisDescriptor != null && superClassDescriptor != null && runReadAction { DescriptorUtils.isSubclass(thisDescriptor, superClassDescriptor) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt index e0c370940e0..192fefa0fb2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -26,7 +26,6 @@ import com.intellij.diagnostic.LogMessageEx import com.intellij.openapi.diagnostic.Attachment import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.progress.ProcessCanceledException -import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiDocumentManager @@ -552,7 +551,7 @@ private fun SuspendContext.getInvokePolicy(): Int { return if (suspendPolicy == EventRequest.SUSPEND_EVENT_THREAD) ObjectReference.INVOKE_SINGLE_THREADED else 0 } -fun Type.getClassDescriptor(project: Project): ClassDescriptor? { +fun Type.getClassDescriptor(scope: GlobalSearchScope): ClassDescriptor? { if (AsmUtil.isPrimitive(this)) return null val jvmName = JvmClassName.byInternalName(internalName).fqNameForClassNameWithoutDollars @@ -561,7 +560,7 @@ fun Type.getClassDescriptor(project: Project): ClassDescriptor? { if (platformClasses.isNotEmpty()) return platformClasses.first() return runReadAction { - val classes = JavaPsiFacade.getInstance(project).findClasses(jvmName.asString(), GlobalSearchScope.allScope(project)) + val classes = JavaPsiFacade.getInstance(scope.project).findClasses(jvmName.asString(), scope) if (classes.isEmpty()) null else { classes.first().getJavaClassDescriptor() diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinRuntimeTypeEvaluator.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinRuntimeTypeEvaluator.kt index 46073f1ada6..4e687de2653 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinRuntimeTypeEvaluator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinRuntimeTypeEvaluator.kt @@ -29,8 +29,8 @@ import com.intellij.debugger.ui.EditorEvaluationCommand import com.intellij.openapi.editor.Editor import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.project.Project import com.intellij.psi.CommonClassNames +import com.intellij.psi.search.GlobalSearchScope import com.sun.jdi.ClassType import com.sun.jdi.Value import org.jetbrains.eval4j.jdi.asValue @@ -73,16 +73,16 @@ abstract class KotlinRuntimeTypeEvaluator( val value = evaluator.evaluate(evaluationContext) if (value != null) { - return getCastableRuntimeType(project, value) + return getCastableRuntimeType(evaluationContext.debugProcess.searchScope, value) } throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.surrounded.expression.null")) } companion object { - private fun getCastableRuntimeType(project: Project, value: Value): KotlinType? { + private fun getCastableRuntimeType(scope: GlobalSearchScope, value: Value): KotlinType? { val myValue = value.asValue() - var psiClass = myValue.asmType.getClassDescriptor(project) + var psiClass = myValue.asmType.getClassDescriptor(scope) if (psiClass != null) { return psiClass.defaultType } @@ -91,14 +91,14 @@ abstract class KotlinRuntimeTypeEvaluator( if (type is ClassType) { val superclass = type.superclass() if (superclass != null && CommonClassNames.JAVA_LANG_OBJECT != superclass.name()) { - psiClass = AsmType.getType(superclass.signature()).getClassDescriptor(project) + psiClass = AsmType.getType(superclass.signature()).getClassDescriptor(scope) if (psiClass != null) { return psiClass.defaultType } } for (interfaceType in type.interfaces()) { - psiClass = AsmType.getType(interfaceType.signature()).getClassDescriptor(project) + psiClass = AsmType.getType(interfaceType.signature()).getClassDescriptor(scope) if (psiClass != null) { return psiClass.defaultType }