mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-21 22:11:40 +07:00
poly conditional expression type = target type (IDEA-122401)
This commit is contained in:
@@ -37,6 +37,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.ControlFlowUtil;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTagValue;
|
||||
@@ -1460,4 +1461,25 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConditionalExpression(PsiConditionalExpression expression) {
|
||||
super.visitConditionalExpression(expression);
|
||||
if (PsiUtil.isLanguageLevel8OrHigher(expression) && PsiPolyExpressionUtil.isPolyExpression(expression)) {
|
||||
final PsiExpression thenExpression = expression.getThenExpression();
|
||||
final PsiExpression elseExpression = expression.getElseExpression();
|
||||
if (thenExpression != null && elseExpression != null) {
|
||||
final PsiType conditionalType = expression.getType();
|
||||
if (conditionalType != null) {
|
||||
final PsiExpression[] sides = new PsiExpression[] {thenExpression, elseExpression};
|
||||
for (PsiExpression side : sides) {
|
||||
final PsiType sideType = side.getType();
|
||||
if (sideType != null && !TypeConversionUtil.isAssignable(conditionalType, sideType)) {
|
||||
myHolder.add(HighlightUtil.checkAssignability(conditionalType, sideType, side, side));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,10 +346,7 @@ public class InferenceSession {
|
||||
if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method)) {
|
||||
PsiType returnType = method.getReturnType();
|
||||
if (!PsiType.VOID.equals(returnType) && returnType != null) {
|
||||
PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context);
|
||||
if (targetType == null) {
|
||||
targetType = getTargetType(context);
|
||||
}
|
||||
PsiType targetType = getTargetType(context);
|
||||
if (targetType != null) {
|
||||
registerConstraints(PsiUtil.isRawSubstitutor(method, mySiteSubstitutor) ? returnType : mySiteSubstitutor.substitute(returnType), targetType);
|
||||
}
|
||||
@@ -465,7 +462,11 @@ public class InferenceSession {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static PsiType getTargetType(final PsiExpression context) {
|
||||
public static PsiType getTargetType(final PsiExpression context) {
|
||||
PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context);
|
||||
if (targetType != null) {
|
||||
return targetType;
|
||||
}
|
||||
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent());
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
PsiElement gParent = parent.getParent();
|
||||
@@ -495,11 +496,7 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
} else if (parent instanceof PsiConditionalExpression) {
|
||||
PsiType targetType = PsiTypesUtil.getExpectedTypeByParent((PsiExpression)parent);
|
||||
if (targetType == null) {
|
||||
targetType = getTargetType((PsiExpression)parent);
|
||||
}
|
||||
return targetType;
|
||||
return getTargetType((PsiExpression)parent);
|
||||
}
|
||||
else if (parent instanceof PsiLambdaExpression) {
|
||||
if (PsiUtil.skipParenthesizedExprUp(parent.getParent()) instanceof PsiExpressionList) {
|
||||
|
||||
@@ -18,9 +18,12 @@ package com.intellij.psi.impl.source.tree.java;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
|
||||
import com.intellij.psi.impl.source.tree.ChildRole;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.tree.ChildRoleBase;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
@@ -83,6 +86,14 @@ public class PsiConditionalExpressionImpl extends ExpressionPsiElement implement
|
||||
if (TypeConversionUtil.isNullType(type1) && !(type2 instanceof PsiPrimitiveType)) return type2;
|
||||
if (TypeConversionUtil.isNullType(type2) && !(type1 instanceof PsiPrimitiveType)) return type1;
|
||||
|
||||
if (PsiUtil.isLanguageLevel8OrHigher(this) &&
|
||||
PsiPolyExpressionUtil.isPolyExpression(this) &&
|
||||
!MethodCandidateInfo.ourOverloadGuard.currentStack().contains(this.getParent())) {
|
||||
//15.25.3 Reference Conditional Expressions
|
||||
// The type of a poly reference conditional expression is the same as its target type.
|
||||
return InferenceSession.getTargetType(this);
|
||||
}
|
||||
|
||||
if (TypeConversionUtil.isAssignable(type1, type2, false)) return type1;
|
||||
if (TypeConversionUtil.isAssignable(type2, type1, false)) return type2;
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(this)) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import java.util.Comparator;
|
||||
|
||||
class NullComparator<T> {
|
||||
private final Comparator<T> real = null;
|
||||
private Comparator<? super T> other;
|
||||
private Comparator<T> another;
|
||||
|
||||
NullComparator(Comparator<? super T> real) {
|
||||
}
|
||||
|
||||
public NullComparator<T> thenComparing() {
|
||||
return new NullComparator<>(real == null ? other : another);
|
||||
}
|
||||
|
||||
Comparator<T> a() {
|
||||
return null;
|
||||
}
|
||||
|
||||
Comparator<? super T> b() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public NullComparator<T> thenComparing1() {
|
||||
return new NullComparator<>(real == null ? a() : b());
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,6 @@ interface B {}
|
||||
}
|
||||
|
||||
void bar (boolean a, A a1, B b1){
|
||||
<error descr="Incompatible types. Found: 'java.lang.Object', required: 'T'">T t = a ? a1 : b1;</error>
|
||||
T t = a ? <error descr="Incompatible types. Found: 'A', required: 'T'">a1</error> : <error descr="Incompatible types. Found: 'B', required: 'T'">b1</error>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class MS {
|
||||
|
||||
void test(boolean cond) {
|
||||
m(cond ? () -> 26 : () -> 24);
|
||||
m<error descr="Ambiguous method call: both 'MS.m(GetInt)' and 'MS.m(GetInteger)' match">(cond ? () -> 26 : () -> new Integer(42))</error>;
|
||||
m<error descr="Cannot resolve method 'm(?)'">(cond ? () -> 26 : () -> new Integer(42))</error>;
|
||||
m(cond ? () -> new Integer(26) : () -> new Integer(42));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// "Cast to 'B'" "true"
|
||||
class A {
|
||||
void f(B b) {
|
||||
B s = <caret>b == null ? (B) this : b;
|
||||
B s = b == null ? <caret>(B) this : b;
|
||||
}
|
||||
}
|
||||
class B extends A {}
|
||||
@@ -1,7 +1,7 @@
|
||||
// "Cast to 'B'" "true"
|
||||
class A {
|
||||
void f(B b) {
|
||||
B s = <caret>b == null ? this : b;
|
||||
B s = b == null ? <caret>this : b;
|
||||
}
|
||||
}
|
||||
class B extends A {}
|
||||
@@ -743,6 +743,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA122401() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user