Added 'getParameterForArgument' util function (using resolved call)

Removed similar util methods (using psi):
getParameterCorrespondingToValueArgumentPassedInCall
getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList
This commit is contained in:
Svetlana Isakova
2014-07-16 12:03:16 +04:00
parent 2ae87cae4a
commit b3ad725e8d
5 changed files with 77 additions and 129 deletions
@@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMapping; import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMapping;
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatch; import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatch;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.types.lang.InlineUtil; import org.jetbrains.jet.lang.types.lang.InlineUtil;
public class InlineDescriptorUtils { public class InlineDescriptorUtils {
@@ -54,7 +53,8 @@ public class InlineDescriptorUtils {
CallableDescriptor resultingDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); CallableDescriptor resultingDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
if (resultingDescriptor instanceof SimpleFunctionDescriptor && if (resultingDescriptor instanceof SimpleFunctionDescriptor &&
((SimpleFunctionDescriptor) resultingDescriptor).getInlineStrategy().isInline()) { ((SimpleFunctionDescriptor) resultingDescriptor).getInlineStrategy().isInline()) {
ValueArgument argument = getContainingArgument(containingFunction, call); ValueArgument argument = CallUtilPackage.getValueArgumentForExpression(
resolvedCall.getCall(), (JetFunctionLiteralExpression) containingFunction);
if (argument != null) { if (argument != null) {
ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument); ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument);
if (mapping instanceof ArgumentMatch) { if (mapping instanceof ArgumentMatch) {
@@ -77,22 +77,6 @@ public class InlineDescriptorUtils {
return fromFunction == containingFunctionDescriptor; return fromFunction == containingFunctionDescriptor;
} }
@Nullable
public static ValueArgument getContainingArgument(PsiElement expression, @NotNull JetExpression stopAtCall) {
if (expression instanceof JetValueArgument) {
return (JetValueArgument) expression;
}
while (expression != null && expression.getParent() != stopAtCall) {
PsiElement parent = expression.getParent();
if (parent instanceof JetValueArgument) {
return (JetValueArgument) parent;
}
expression = parent;
}
return expression != null ? CallMaker.makeValueArgument((JetExpression) expression) : null;
}
@Nullable @Nullable
public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) { public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) {
DeclarationDescriptor currentDescriptor = strict ? descriptor.getContainingDeclaration() : descriptor; DeclarationDescriptor currentDescriptor = strict ? descriptor.getContainingDeclaration() : descriptor;
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatch
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatchStatus import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatchStatus
import org.jetbrains.jet.lang.psi.Call import org.jetbrains.jet.lang.psi.Call
import org.jetbrains.jet.lang.psi.ValueArgument import org.jetbrains.jet.lang.psi.ValueArgument
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker
import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver
import org.jetbrains.jet.lang.psi.JetElement import org.jetbrains.jet.lang.psi.JetElement
@@ -48,6 +47,8 @@ import org.jetbrains.jet.lang.psi.psiUtil.getTextWithLocation
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lang.psi.JetCallExpression import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.psi.JetFunctionLiteralArgument import org.jetbrains.jet.lang.psi.JetFunctionLiteralArgument
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
// resolved call // resolved call
@@ -74,6 +75,10 @@ public fun <D : CallableDescriptor> ResolvedCall<D>.hasTypeMismatchErrorOnParame
} }
} }
public fun <D : CallableDescriptor> ResolvedCall<D>.getParameterForArgument(valueArgument: ValueArgument?): ValueParameterDescriptor? {
return (valueArgument?.let { getArgumentMapping(it) } as? ArgumentMatch)?.valueParameter
}
// call // call
public fun Call.hasUnresolvedArguments(context: BindingContext): Boolean { public fun Call.hasUnresolvedArguments(context: BindingContext): Boolean {
@@ -93,6 +98,20 @@ public fun JetCallExpression.getValueArgumentsInParentheses(): List<ValueArgumen
[suppress("UNCHECKED_CAST")] [suppress("UNCHECKED_CAST")]
private fun List<ValueArgument?>.filterArgsInParentheses() = filter { it !is JetFunctionLiteralArgument } as List<ValueArgument> private fun List<ValueArgument?>.filterArgsInParentheses() = filter { it !is JetFunctionLiteralArgument } as List<ValueArgument>
public fun Call.getValueArgumentForExpression(expression: JetExpression): ValueArgument? {
fun JetElement.deparenthesizeStructurally(): JetElement? {
val deparenthesized = if (this is JetExpression) JetPsiUtil.deparenthesizeOnce(this, false) else this
return when {
deparenthesized != this -> deparenthesized
this is JetFunctionLiteralExpression -> this.getFunctionLiteral()
this is JetFunctionLiteral -> this.getBodyExpression()
else -> null
}
}
fun JetElement.isParenthesizedExpression() = stream(this) { it.deparenthesizeStructurally() }.any { it == expression }
return getValueArguments().firstOrNull { it?.getArgumentExpression()?.isParenthesizedExpression() ?: false }
}
// Get call / resolved call from binding context // Get call / resolved call from binding context
public fun JetElement.getCalleeExpressionIfAny(): JetExpression? { public fun JetElement.getCalleeExpressionIfAny(): JetExpression? {
@@ -24,10 +24,13 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException; import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.TypeUtils;
@@ -47,13 +50,13 @@ public class ChangeFunctionLiteralReturnTypeFix extends JetIntentionAction<JetFu
private final JetTypeReference functionLiteralReturnTypeRef; private final JetTypeReference functionLiteralReturnTypeRef;
private IntentionAction appropriateQuickFix = null; private IntentionAction appropriateQuickFix = null;
public ChangeFunctionLiteralReturnTypeFix(@NotNull JetFunctionLiteralExpression element, @NotNull JetType type) { public ChangeFunctionLiteralReturnTypeFix(@NotNull JetFunctionLiteralExpression functionLiteralExpression, @NotNull JetType type) {
super(element); super(functionLiteralExpression);
renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type);
functionLiteralReturnTypeRef = element.getFunctionLiteral().getReturnTypeRef(); functionLiteralReturnTypeRef = functionLiteralExpression.getFunctionLiteral().getReturnTypeRef();
BindingContext context = ResolvePackage.getBindingContext(element.getContainingJetFile()); BindingContext context = ResolvePackage.getBindingContext(functionLiteralExpression.getContainingJetFile());
JetType functionLiteralType = context.get(BindingContext.EXPRESSION_TYPE, element); JetType functionLiteralType = context.get(BindingContext.EXPRESSION_TYPE, functionLiteralExpression);
assert functionLiteralType != null : "Type of function literal not available in binding context"; assert functionLiteralType != null : "Type of function literal not available in binding context";
ClassDescriptor functionClass = KotlinBuiltIns.getInstance().getFunction(functionLiteralType.getArguments().size() - 1); ClassDescriptor functionClass = KotlinBuiltIns.getInstance().getFunction(functionLiteralType.getArguments().size() - 1);
@@ -66,8 +69,8 @@ public class ChangeFunctionLiteralReturnTypeFix extends JetIntentionAction<JetFu
functionClassTypeParameters.add(type); functionClassTypeParameters.add(type);
JetType eventualFunctionLiteralType = TypeUtils.substituteParameters(functionClass, functionClassTypeParameters); JetType eventualFunctionLiteralType = TypeUtils.substituteParameters(functionClass, functionClassTypeParameters);
JetProperty correspondingProperty = PsiTreeUtil.getParentOfType(element, JetProperty.class); JetProperty correspondingProperty = PsiTreeUtil.getParentOfType(functionLiteralExpression, JetProperty.class);
if (correspondingProperty != null && QuickFixUtil.canEvaluateTo(correspondingProperty.getInitializer(), element)) { if (correspondingProperty != null && QuickFixUtil.canEvaluateTo(correspondingProperty.getInitializer(), functionLiteralExpression)) {
JetTypeReference correspondingPropertyTypeRef = correspondingProperty.getTypeRef(); JetTypeReference correspondingPropertyTypeRef = correspondingProperty.getTypeRef();
JetType propertyType = context.get(BindingContext.TYPE, correspondingPropertyTypeRef); JetType propertyType = context.get(BindingContext.TYPE, correspondingPropertyTypeRef);
if (propertyType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(eventualFunctionLiteralType, propertyType)) { if (propertyType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(eventualFunctionLiteralType, propertyType)) {
@@ -76,18 +79,24 @@ public class ChangeFunctionLiteralReturnTypeFix extends JetIntentionAction<JetFu
return; return;
} }
JetParameter correspondingParameter = QuickFixUtil.getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList(element); ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilPackage.getParentResolvedCall(
if (correspondingParameter != null) { functionLiteralExpression, context, true);
JetTypeReference correspondingParameterTypeRef = correspondingParameter.getTypeReference(); if (resolvedCall != null) {
JetType parameterType = context.get(BindingContext.TYPE, correspondingParameterTypeRef); ValueArgument valueArgument = CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), functionLiteralExpression);
if (parameterType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(eventualFunctionLiteralType, parameterType)) { JetParameter correspondingParameter = QuickFixUtil.getParameterDeclarationForValueArgument(resolvedCall, valueArgument);
appropriateQuickFix = new ChangeParameterTypeFix(correspondingParameter, eventualFunctionLiteralType); if (correspondingParameter != null) {
JetTypeReference correspondingParameterTypeRef = correspondingParameter.getTypeReference();
JetType parameterType = context.get(BindingContext.TYPE, correspondingParameterTypeRef);
if (parameterType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(eventualFunctionLiteralType, parameterType)) {
appropriateQuickFix = new ChangeParameterTypeFix(correspondingParameter, eventualFunctionLiteralType);
}
return;
} }
return;
} }
JetFunction parentFunction = PsiTreeUtil.getParentOfType(element, JetFunction.class, true);
if (parentFunction != null && QuickFixUtil.canFunctionOrGetterReturnExpression(parentFunction, element)) { JetFunction parentFunction = PsiTreeUtil.getParentOfType(functionLiteralExpression, JetFunction.class, true);
if (parentFunction != null && QuickFixUtil.canFunctionOrGetterReturnExpression(parentFunction, functionLiteralExpression)) {
JetTypeReference parentFunctionReturnTypeRef = parentFunction.getReturnTypeRef(); JetTypeReference parentFunctionReturnTypeRef = parentFunction.getReturnTypeRef();
JetType parentFunctionReturnType = context.get(BindingContext.TYPE, parentFunctionReturnTypeRef); JetType parentFunctionReturnType = context.get(BindingContext.TYPE, parentFunctionReturnTypeRef);
if (parentFunctionReturnType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(eventualFunctionLiteralType, parentFunctionReturnType)) { if (parentFunctionReturnType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(eventualFunctionLiteralType, parentFunctionReturnType)) {
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters2; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters2;
import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.diagnostics.Errors;
@@ -103,24 +104,15 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF
} }
} }
// Change type of a function parameter in case TYPE_MISMATCH is reported on expression passed as value argument of call. ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilPackage.getParentResolvedCall(expression, context, true);
// 1) When an argument is a dangling function literal: if (resolvedCall != null) {
JetFunctionLiteralArgument functionLiteralArgument = // to fix 'type mismatch' on 'if' branches
QuickFixUtil.getParentElementOfType(diagnostic, JetFunctionLiteralArgument.class); // todo: the same with 'when'
JetFunctionLiteralExpression functionLiteralExpression = functionLiteralArgument != null ? functionLiteralArgument.getFunctionLiteral() : null; JetExpression parentIf = QuickFixUtil.getParentIfForBranch(expression);
if (functionLiteralExpression != null && functionLiteralExpression.getBodyExpression() == expression) { JetExpression argumentExpression = (parentIf != null) ? parentIf : expression;
JetParameter correspondingParameter = ValueArgument valueArgument = CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), argumentExpression);
QuickFixUtil.getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList(functionLiteralExpression); if (valueArgument != null) {
JetType functionLiteralExpressionType = context.get(BindingContext.EXPRESSION_TYPE, functionLiteralExpression); JetParameter correspondingParameter = QuickFixUtil.getParameterDeclarationForValueArgument(resolvedCall, valueArgument);
if (correspondingParameter != null && functionLiteralExpressionType != null) {
actions.add(new ChangeParameterTypeFix(correspondingParameter, functionLiteralExpressionType));
}
}
// 2) When an argument is passed inside value argument list:
else {
JetValueArgument valueArgument = QuickFixUtil.getParentElementOfType(diagnostic, JetValueArgument.class);
if (valueArgument != null && QuickFixUtil.canEvaluateTo(valueArgument.getArgumentExpression(), expression)) {
JetParameter correspondingParameter = QuickFixUtil.getParameterCorrespondingToValueArgumentPassedInCall(valueArgument);
JetType valueArgumentType = context.get(BindingContext.EXPRESSION_TYPE, valueArgument.getArgumentExpression()); JetType valueArgumentType = context.get(BindingContext.EXPRESSION_TYPE, valueArgument.getArgumentExpression());
if (correspondingParameter != null && valueArgumentType != null) { if (correspondingParameter != null && valueArgumentType != null) {
actions.add(new ChangeParameterTypeFix(correspondingParameter, valueArgumentType)); actions.add(new ChangeParameterTypeFix(correspondingParameter, valueArgumentType));
@@ -132,7 +124,7 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF
@Nullable @Nullable
private static JetFunction getFunctionDeclaration(@NotNull ResolvedCall<?> resolvedCall) { private static JetFunction getFunctionDeclaration(@NotNull ResolvedCall<?> resolvedCall) {
PsiElement result = QuickFixUtil.safeGetDeclaration(resolvedCall); PsiElement result = QuickFixUtil.safeGetDeclaration(resolvedCall.getResultingDescriptor());
if (result instanceof JetFunction) { if (result instanceof JetFunction) {
return (JetFunction) result; return (JetFunction) result;
} }
@@ -23,7 +23,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.sun.codemodel.internal.JVar;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly; import org.jetbrains.annotations.ReadOnly;
@@ -45,7 +44,6 @@ import org.jetbrains.jet.plugin.references.BuiltInsReferenceResolver;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.util.List;
import java.util.Set; import java.util.Set;
public class QuickFixUtil { public class QuickFixUtil {
@@ -107,77 +105,16 @@ public class QuickFixUtil {
} }
@Nullable @Nullable
public static JetParameterList getParameterListOfCallee(@NotNull JetCallExpression callExpression) { public static PsiElement safeGetDeclaration(@Nullable CallableDescriptor descriptor) {
BindingContext context = ResolvePackage.getBindingContext(callExpression.getContainingJetFile());
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(callExpression, context);
if (resolvedCall == null) return null;
PsiElement declaration = safeGetDeclaration(resolvedCall);
if (declaration instanceof JetFunction) {
return ((JetFunction) declaration).getValueParameterList();
}
if (declaration instanceof JetClass) {
return ((JetClass) declaration).getPrimaryConstructorParameterList();
}
return null;
}
@Nullable
public static PsiElement safeGetDeclaration(@NotNull ResolvedCall<?> resolvedCall) {
List<PsiElement> declarations = DescriptorToSourceUtils.descriptorToDeclarations(resolvedCall.getResultingDescriptor());
//do not create fix if descriptor has more than one overridden declaration //do not create fix if descriptor has more than one overridden declaration
if (declarations.size() == 1) { if (descriptor == null || descriptor.getOverriddenDescriptors().size() > 1) return null;
return declarations.iterator().next(); return DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
}
return null;
}
//todo remove, use value argument to parameter map
@Nullable
public static JetParameter getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList(@NotNull JetFunctionLiteralExpression functionLiteralExpression) {
JetFunctionLiteralArgument functionLiteralArgument = PsiTreeUtil.getParentOfType(functionLiteralExpression, JetFunctionLiteralArgument.class);
if (functionLiteralArgument == null || functionLiteralArgument.getFunctionLiteral() != functionLiteralExpression) return null;
if (!(functionLiteralArgument.getParent() instanceof JetCallExpression)) {
return null;
}
JetCallExpression callExpression = (JetCallExpression) functionLiteralArgument.getParent();
JetParameterList parameterList = getParameterListOfCallee(callExpression);
if (parameterList == null) return null;
return parameterList.getParameters().get(parameterList.getParameters().size() - 1);
} }
@Nullable @Nullable
public static JetParameter getParameterCorrespondingToValueArgumentPassedInCall(@NotNull JetValueArgument valueArgument) { public static JetParameter getParameterDeclarationForValueArgument(@NotNull ResolvedCall<?> resolvedCall, @Nullable ValueArgument valueArgument) {
if (!(valueArgument.getParent() instanceof JetValueArgumentList)) { ValueParameterDescriptor parameterDescriptor = CallUtilPackage.getParameterForArgument(resolvedCall, valueArgument);
return null; return (JetParameter) safeGetDeclaration(parameterDescriptor);
}
JetValueArgumentList valueArgumentList = (JetValueArgumentList) valueArgument.getParent();
if (!(valueArgumentList.getParent() instanceof JetCallExpression)) {
return null;
}
JetCallExpression callExpression = (JetCallExpression) valueArgumentList.getParent();
JetParameterList parameterList = getParameterListOfCallee(callExpression);
if (parameterList == null) return null;
List<JetParameter> parameters = parameterList.getParameters();
int position = valueArgumentList.getArguments().indexOf(valueArgument);
if (position == -1) return null;
if (valueArgument.isNamed()) {
JetValueArgumentName valueArgumentName = valueArgument.getArgumentName();
JetSimpleNameExpression referenceExpression = valueArgumentName == null ? null : valueArgumentName.getReferenceExpression();
String valueArgumentNameAsString = referenceExpression == null ? null : referenceExpression.getReferencedName();
if (valueArgumentNameAsString == null) return null;
for (JetParameter parameter: parameters) {
if (valueArgumentNameAsString.equals(parameter.getName())) {
return parameter;
}
}
return null;
}
else {
if (position >= parameters.size()) return null;
return parameters.get(position);
}
} }
private static boolean equalOrLastInThenOrElse(JetExpression thenOrElse, JetExpression expression) { private static boolean equalOrLastInThenOrElse(JetExpression thenOrElse, JetExpression expression) {
@@ -186,6 +123,17 @@ public class QuickFixUtil {
PsiTreeUtil.getNextSiblingOfType(expression, JetExpression.class) == null; PsiTreeUtil.getNextSiblingOfType(expression, JetExpression.class) == null;
} }
@Nullable
public static JetIfExpression getParentIfForBranch(@Nullable JetExpression expression) {
JetIfExpression ifExpression = PsiTreeUtil.getParentOfType(expression, JetIfExpression.class, true);
if (ifExpression == null) return null;
if (equalOrLastInThenOrElse(ifExpression.getThen(), expression)
|| equalOrLastInThenOrElse(ifExpression.getElse(), expression)) {
return ifExpression;
}
return null;
}
public static boolean canEvaluateTo(JetExpression parent, JetExpression child) { public static boolean canEvaluateTo(JetExpression parent, JetExpression child) {
if (parent == null || child == null) { if (parent == null || child == null) {
return false; return false;
@@ -195,12 +143,8 @@ public class QuickFixUtil {
child = (JetExpression) child.getParent(); child = (JetExpression) child.getParent();
continue; continue;
} }
JetIfExpression jetIfExpression = PsiTreeUtil.getParentOfType(child, JetIfExpression.class, true); child = getParentIfForBranch(child);
if (jetIfExpression == null) return false; if (child == null) return false;
if (!equalOrLastInThenOrElse(jetIfExpression.getThen(), child) && !equalOrLastInThenOrElse(jetIfExpression.getElse(), child)) {
return false;
}
child = jetIfExpression;
} }
return true; return true;
} }