Debugger: (EA-112731) Do not crash miserably if we don't know the anonymous class name
Continue to log the exception, avoid breaking UX
This commit is contained in:
@@ -95,23 +95,33 @@ public class CodegenBinding {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Type asmTypeForAnonymousClass(@NotNull BindingContext bindingContext, @NotNull KtElement expression) {
|
public static Type asmTypeForAnonymousClass(@NotNull BindingContext bindingContext, @NotNull KtElement expression) {
|
||||||
|
Type result = asmTypeForAnonymousClassOrNull(bindingContext, expression);
|
||||||
|
if (result == null) {
|
||||||
|
throw new IllegalStateException("Type must not be null: " + expression.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Type asmTypeForAnonymousClassOrNull(@NotNull BindingContext bindingContext, @NotNull KtElement expression) {
|
||||||
if (expression instanceof KtObjectLiteralExpression) {
|
if (expression instanceof KtObjectLiteralExpression) {
|
||||||
expression = ((KtObjectLiteralExpression) expression).getObjectDeclaration();
|
expression = ((KtObjectLiteralExpression) expression).getObjectDeclaration();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDescriptor descriptor = bindingContext.get(CLASS, expression);
|
ClassDescriptor descriptor = bindingContext.get(CLASS, expression);
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
return getAsmType(bindingContext, descriptor);
|
return bindingContext.get(ASM_TYPE, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleFunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
SimpleFunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
||||||
if (functionDescriptor != null) {
|
if (functionDescriptor != null) {
|
||||||
return asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
return asmTypeForAnonymousClassOrNull(bindingContext, functionDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||||
if (variableDescriptor != null) {
|
if (variableDescriptor != null) {
|
||||||
return asmTypeForAnonymousClass(bindingContext, variableDescriptor);
|
return asmTypeForAnonymousClassOrNull(bindingContext, variableDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new KotlinExceptionWithAttachments("Couldn't compute ASM type for expression")
|
throw new KotlinExceptionWithAttachments("Couldn't compute ASM type for expression")
|
||||||
@@ -120,7 +130,17 @@ public class CodegenBinding {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Type asmTypeForAnonymousClass(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor descriptor) {
|
public static Type asmTypeForAnonymousClass(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor descriptor) {
|
||||||
return getAsmType(bindingContext, anonymousClassForCallable(bindingContext, descriptor));
|
Type result = asmTypeForAnonymousClassOrNull(bindingContext, descriptor);
|
||||||
|
if (result == null) {
|
||||||
|
throw new IllegalStateException("Type must not be null: " + descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Type asmTypeForAnonymousClassOrNull(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor descriptor) {
|
||||||
|
return bindingContext.get(ASM_TYPE, anonymousClassForCallable(bindingContext, descriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canHaveOuter(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) {
|
public static boolean canHaveOuter(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) {
|
||||||
@@ -216,7 +236,9 @@ public class CodegenBinding {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static Type getAsmType(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor klass) {
|
public static Type getAsmType(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor klass) {
|
||||||
Type type = bindingContext.get(ASM_TYPE, klass);
|
Type type = bindingContext.get(ASM_TYPE, klass);
|
||||||
assert type != null : "Type is not yet recorded for " + klass;
|
if (type == null) {
|
||||||
|
throw new IllegalStateException("Type is not yet recorded for " + klass);
|
||||||
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.intellij.psi.util.PsiTreeUtil
|
|||||||
import com.sun.jdi.AbsentInformationException
|
import com.sun.jdi.AbsentInformationException
|
||||||
import com.sun.jdi.ReferenceType
|
import com.sun.jdi.ReferenceType
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClassOrNull
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny
|
import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
|
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
|
||||||
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.Computed
|
|||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.Cached
|
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.Cached
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.EMPTY
|
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.EMPTY
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.NonCached
|
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames.Companion.NonCached
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.evaluate.LOG
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
@@ -187,13 +189,20 @@ class DebuggerClassNameProvider(
|
|||||||
|
|
||||||
val classNamesOfContainingDeclaration = getOuterClassNamesForElement(element.relevantParentInReadAction)
|
val classNamesOfContainingDeclaration = getOuterClassNamesForElement(element.relevantParentInReadAction)
|
||||||
|
|
||||||
val nonInlineClasses: ComputedClassNames = if (runReadAction { element.name == null || element.isLocal }) {
|
val nonInlineClasses: ComputedClassNames =
|
||||||
classNamesOfContainingDeclaration + ComputedClassNames.Cached(
|
if (runReadAction { element.name == null || element.isLocal }) {
|
||||||
asmTypeForAnonymousClass(typeMapper.bindingContext, element).internalName.toJdiName())
|
val typeForAnonymousClass = asmTypeForAnonymousClassOrNull(typeMapper.bindingContext, element)
|
||||||
}
|
|
||||||
else {
|
if (typeForAnonymousClass == null) {
|
||||||
classNamesOfContainingDeclaration
|
val parentText = element.relevantParentInReadAction?.text ?: "<parent was null>"
|
||||||
}
|
LOG.error("Can not get type for ${element.text}, parent: $parentText")
|
||||||
|
classNamesOfContainingDeclaration
|
||||||
|
} else {
|
||||||
|
classNamesOfContainingDeclaration + ComputedClassNames.Cached(typeForAnonymousClass.internalName.toJdiName())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
classNamesOfContainingDeclaration
|
||||||
|
}
|
||||||
|
|
||||||
if (!findInlineUseSites || !element.isInlineInReadAction) {
|
if (!findInlineUseSites || !element.isInlineInReadAction) {
|
||||||
return NonCached(nonInlineClasses.classNames)
|
return NonCached(nonInlineClasses.classNames)
|
||||||
|
|||||||
Reference in New Issue
Block a user