mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-01 02:38:59 +07:00
conditional expression type: check poly expression first (IDEA-148965)
This commit is contained in:
@@ -178,8 +178,12 @@ public class PsiPolyExpressionUtil {
|
||||
type = method.getReturnType();
|
||||
}
|
||||
}
|
||||
if (TypeConversionUtil.isNumericType(type)) return ConditionalKind.NUMERIC;
|
||||
if (TypeConversionUtil.isBooleanType(type)) return ConditionalKind.BOOLEAN;
|
||||
|
||||
final ConditionalKind kind = isBooleanOrNumericType(type);
|
||||
if (kind != null) {
|
||||
return kind;
|
||||
}
|
||||
|
||||
if (expr instanceof PsiConditionalExpression) {
|
||||
final PsiExpression thenExpression = ((PsiConditionalExpression)expr).getThenExpression();
|
||||
final PsiExpression elseExpression = ((PsiConditionalExpression)expr).getElseExpression();
|
||||
@@ -190,4 +194,21 @@ public class PsiPolyExpressionUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ConditionalKind isBooleanOrNumericType(PsiType type) {
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(type);
|
||||
if (TypeConversionUtil.isNumericType(type)) return ConditionalKind.NUMERIC;
|
||||
if (TypeConversionUtil.isBooleanType(type)) return ConditionalKind.BOOLEAN;
|
||||
|
||||
if (psiClass instanceof PsiTypeParameter) {
|
||||
for (PsiClassType classType : psiClass.getExtendsListTypes()) {
|
||||
final ConditionalKind kind = isBooleanOrNumericType(classType);
|
||||
if (kind != null) {
|
||||
return kind;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,15 @@ public class PsiConditionalExpressionImpl extends ExpressionPsiElement implement
|
||||
if (type2 == null) return type1;
|
||||
|
||||
if (type1.equals(type2)) return type1;
|
||||
|
||||
if (PsiUtil.isLanguageLevel8OrHigher(this) &&
|
||||
PsiPolyExpressionUtil.isPolyExpression(this) &&
|
||||
!MethodCandidateInfo.ourOverloadGuard.currentStack().contains(PsiUtil.skipParenthesizedExprUp(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);
|
||||
}
|
||||
|
||||
final int typeRank1 = TypeConversionUtil.getTypeRank(type1);
|
||||
final int typeRank2 = TypeConversionUtil.getTypeRank(type2);
|
||||
|
||||
@@ -90,14 +99,6 @@ 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(PsiUtil.skipParenthesizedExprUp(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 @@
|
||||
|
||||
class Conditional {
|
||||
void m(Object p, boolean b) {
|
||||
int a = b ? <error descr="Incompatible types. Found: 'null', required: 'int'">null</error> : ((Getter<Integer>) p).get();
|
||||
int a1 = b ? <error descr="Incompatible types. Found: 'null', required: 'int'">null</error> : Conditional.<Integer>f();
|
||||
int a2 = b ? null : 1;
|
||||
int a3 = b ? null : f1();
|
||||
int a4 = b ? null : f2();
|
||||
}
|
||||
|
||||
private static <T> T f() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int f1() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static <T extends Integer, S extends T> S f2() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface Getter<A> {
|
||||
A get();
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// "Cast to 'B'" "true"
|
||||
class A {
|
||||
void f(B b) {
|
||||
B s = <caret>b == null ? null : (B) this;
|
||||
B s =b == null ? null : <caret>(B) this;
|
||||
}
|
||||
}
|
||||
class B extends A {}
|
||||
@@ -1,7 +1,7 @@
|
||||
// "Cast to 'B'" "true"
|
||||
class A {
|
||||
void f(B b) {
|
||||
B s = <caret>b == null ? null : this;
|
||||
B s =b == null ? null : <caret>this;
|
||||
}
|
||||
}
|
||||
class B extends A {}
|
||||
@@ -343,6 +343,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPolyConditionalExpressionWithTargetPrimitive() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user