Explicitly check for the callable class availability

'@NotNull' annotation generates a not-null assertion that caused exceptions to throw from 'asmTypeForAnonymousClassOrNull()'.
This commit is contained in:
Yan Zhulanow
2019-03-05 20:39:35 +03:00
parent 77c2a5c87c
commit 3f92451fde
4 changed files with 34 additions and 20 deletions
@@ -3145,7 +3145,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull VariableDescriptor target,
@Nullable StackValue receiverValue
) {
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, variableDescriptor);
if (classDescriptor == null) {
throw new IllegalStateException(
"Property reference class was not found: " + variableDescriptor +
"\nTried to generate: " + element.getText());
}
ClassBuilder classBuilder = state.getFactory().newVisitor(
JvmDeclarationOriginKt.OtherOrigin(element),
@@ -112,15 +112,6 @@ public class CodegenBinding {
return Boolean.TRUE.equals(bindingContext.get(ENUM_ENTRY_CLASS_NEED_SUBCLASS, classDescriptor));
}
@NotNull
public static ClassDescriptor anonymousClassForCallable(
@NotNull BindingContext bindingContext,
@NotNull CallableDescriptor descriptor
) {
//noinspection ConstantConditions
return bindingContext.get(CLASS_FOR_CALLABLE, descriptor);
}
@NotNull
public static Type asmTypeForAnonymousClass(@NotNull BindingContext bindingContext, @NotNull KtElement expression) {
Type result = asmTypeForAnonymousClassOrNull(bindingContext, expression);
@@ -168,7 +159,11 @@ public class CodegenBinding {
@Nullable
public static Type asmTypeForAnonymousClassOrNull(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor descriptor) {
return bindingContext.get(ASM_TYPE, anonymousClassForCallable(bindingContext, descriptor));
ClassDescriptor classForCallable = bindingContext.get(CLASS_FOR_CALLABLE, descriptor);
if (classForCallable == null) {
return null;
}
return bindingContext.get(ASM_TYPE, classForCallable);
}
public static boolean canHaveOuter(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) {
@@ -19,11 +19,11 @@ package org.jetbrains.kotlin.codegen.context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.OwnerKind;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.anonymousClassForCallable;
public class ClosureContext extends ClassContext {
private final FunctionDescriptor functionDescriptor;
private final FunctionDescriptor originalSuspendLambdaDescriptor;
@@ -37,14 +37,27 @@ public class ClosureContext extends ClassContext {
@Nullable FunctionDescriptor originalSuspendLambdaDescriptor
) {
super(typeMapper,
anonymousClassForCallable(
typeMapper.getBindingContext(), originalSuspendLambdaDescriptor != null ? originalSuspendLambdaDescriptor : functionDescriptor),
getClassForCallable(typeMapper, functionDescriptor, originalSuspendLambdaDescriptor),
OwnerKind.IMPLEMENTATION, parentContext, localLookup);
this.functionDescriptor = functionDescriptor;
this.originalSuspendLambdaDescriptor = originalSuspendLambdaDescriptor;
}
@NotNull
private static ClassDescriptor getClassForCallable(
@NotNull KotlinTypeMapper typeMapper,
@NotNull FunctionDescriptor functionDescriptor,
@Nullable FunctionDescriptor originalSuspendLambdaDescriptor
) {
FunctionDescriptor callable = originalSuspendLambdaDescriptor != null ? originalSuspendLambdaDescriptor : functionDescriptor;
ClassDescriptor classDescriptor = typeMapper.getBindingContext().get(CodegenBinding.CLASS_FOR_CALLABLE, callable);
if (classDescriptor == null) {
throw new IllegalStateException("Class for callable is not found: " + functionDescriptor);
}
return classDescriptor;
}
public ClosureContext(
@NotNull KotlinTypeMapper typeMapper,
@NotNull FunctionDescriptor functionDescriptor,
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.*
import org.jetbrains.kotlin.codegen.binding.MutableClosure
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
@@ -227,7 +226,7 @@ class PsiExpressionLambda(
private val labels: Set<String>
private lateinit var closure: CalculatedClosure
private var closure: CalculatedClosure
init {
val bindingContext = typeMapper.bindingContext
@@ -236,8 +235,9 @@ class PsiExpressionLambda(
if (function == null && expression is KtCallableReferenceExpression) {
val variableDescriptor =
bindingContext.get(BindingContext.VARIABLE, functionWithBodyOrCallableReference) as? VariableDescriptorWithAccessors
?: throw AssertionError("""Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}""")
classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor)
?: throw AssertionError("Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}")
classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, variableDescriptor)
?: throw IllegalStateException("Class for callable not found: $variableDescriptor\n${expression.text}")
lambdaClassType = typeMapper.mapClass(classDescriptor)
val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor)
invokeMethodDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor)
@@ -248,7 +248,8 @@ class PsiExpressionLambda(
} else {
propertyReferenceInfo = null
invokeMethodDescriptor = function ?: throw AssertionError("Function is not resolved to descriptor: " + expression.text)
classDescriptor = anonymousClassForCallable(bindingContext, invokeMethodDescriptor)
classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, invokeMethodDescriptor)
?: throw IllegalStateException("Class for invoke method not found: $invokeMethodDescriptor\n${expression.text}")
lambdaClassType = asmTypeForAnonymousClass(bindingContext, invokeMethodDescriptor)
}