Debugger: Fix NPE in CFA during evaluation (KT-32830)
This commit is contained in:
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getEnclosingDescriptor
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
|
||||
@@ -471,7 +472,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
trace.get(BACKING_FIELD_REQUIRED, it)
|
||||
} ?: true
|
||||
if (variableDescriptor is PropertyDescriptor && variableDescriptor.isVar) {
|
||||
val descriptor = BindingContextUtils.getEnclosingDescriptor(trace.bindingContext, expression)
|
||||
val descriptor = getEnclosingDescriptor(trace.bindingContext, expression)
|
||||
val setterDescriptor = variableDescriptor.setter
|
||||
|
||||
val receiverValue = expression.getResolvedCall(trace.bindingContext)?.getDispatchReceiverWithSmartCast()
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getEnclosingFunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -916,8 +917,8 @@ class ControlFlowProcessor(
|
||||
private fun jumpDoesNotCrossFunctionBoundary(jumpExpression: KtExpressionWithLabel, jumpTarget: KtLoopExpression): Boolean {
|
||||
val bindingContext = trace.bindingContext
|
||||
|
||||
val labelExprEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpExpression)
|
||||
val labelTargetEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpTarget)
|
||||
val labelExprEnclosingFunc = getEnclosingFunctionDescriptor(bindingContext, jumpExpression)
|
||||
val labelTargetEnclosingFunc = getEnclosingFunctionDescriptor(bindingContext, jumpTarget)
|
||||
return if (labelExprEnclosingFunc !== labelTargetEnclosingFunc) {
|
||||
// Check to report only once
|
||||
if (builder.getLoopExitPoint(jumpTarget) != null ||
|
||||
|
||||
@@ -8,12 +8,12 @@ package org.jetbrains.kotlin.resolve;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
@@ -111,31 +111,6 @@ public class BindingContextUtils {
|
||||
return value;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DeclarationDescriptor getEnclosingDescriptor(@NotNull BindingContext context, @NotNull KtElement element) {
|
||||
KtNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, KtNamedDeclaration.class);
|
||||
if (declaration instanceof KtFunctionLiteral) {
|
||||
return getEnclosingDescriptor(context, declaration);
|
||||
}
|
||||
DeclarationDescriptor descriptor = context.get(DECLARATION_TO_DESCRIPTOR, declaration);
|
||||
assert descriptor != null : "No descriptor for named declaration: " + declaration.getText() + "\n(of type " + declaration.getClass() + ")";
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FunctionDescriptor getEnclosingFunctionDescriptor(@NotNull BindingContext context, @NotNull KtElement element) {
|
||||
KtElement functionOrClass = PsiTreeUtil.getParentOfType(element, KtFunction.class, KtClassOrObject.class);
|
||||
DeclarationDescriptor descriptor = context.get(DECLARATION_TO_DESCRIPTOR, functionOrClass);
|
||||
if (functionOrClass instanceof KtFunction) {
|
||||
if (descriptor instanceof FunctionDescriptor) return (FunctionDescriptor) descriptor;
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
if (descriptor instanceof ClassDescriptor) return ((ClassDescriptor) descriptor).getUnsubstitutedPrimaryConstructor();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void reportAmbiguousLabel(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull KtSimpleNameExpression targetLabel,
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.kotlin.resolve.bindingContextUtil
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
@@ -114,4 +116,38 @@ fun KtTypeElement.getAbbreviatedTypeOrType(context: BindingContext): KotlinType?
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : PsiElement> KtElement.getParentOfTypeCodeFragmentAware(vararg parentClasses: Class<out T>): T? {
|
||||
PsiTreeUtil.getParentOfType(this, *parentClasses)?.let { return it }
|
||||
|
||||
val containingFile = this.containingFile
|
||||
if (containingFile is KtCodeFragment) {
|
||||
val context = containingFile.context
|
||||
if (context != null) {
|
||||
return PsiTreeUtil.getParentOfType(context, *parentClasses)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun getEnclosingDescriptor(context: BindingContext, element: KtElement): DeclarationDescriptor {
|
||||
val declaration = element.getParentOfTypeCodeFragmentAware(KtNamedDeclaration::class.java)
|
||||
return if (declaration is KtFunctionLiteral) {
|
||||
getEnclosingDescriptor(context, declaration)
|
||||
} else {
|
||||
context.get(DECLARATION_TO_DESCRIPTOR, declaration)
|
||||
?: error("No descriptor for named declaration: " + declaration?.text + "\n(of type " + declaration?.javaClass + ")")
|
||||
}
|
||||
}
|
||||
|
||||
fun getEnclosingFunctionDescriptor(context: BindingContext, element: KtElement): FunctionDescriptor? {
|
||||
val functionOrClass = element.getParentOfTypeCodeFragmentAware(KtFunction::class.java, KtClassOrObject::class.java)
|
||||
val descriptor = context.get(DECLARATION_TO_DESCRIPTOR, functionOrClass)
|
||||
return if (functionOrClass is KtFunction) {
|
||||
if (descriptor is FunctionDescriptor) descriptor else null
|
||||
} else {
|
||||
if (descriptor is ClassDescriptor) descriptor.unsubstitutedPrimaryConstructor else null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user