mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
diamonds with anonymous: reject cases according to JDK-8062373
This commit is contained in:
@@ -26,6 +26,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.scope.PsiConflictResolver;
|
||||
@@ -133,7 +134,17 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
return DiamondInferenceResult.EXPLICIT_CONSTRUCTOR_TYPE_ARGS;
|
||||
}
|
||||
|
||||
return resolveInferredTypesNoCheck(newExpression, context);
|
||||
final DiamondInferenceResult inferenceResult = resolveInferredTypesNoCheck(newExpression, context);
|
||||
if (anonymousClass != null && PsiUtil.isLanguageLevel9OrHigher(newExpression)) {
|
||||
final InferredAnonymTypeVisitor anonymTypeVisitor = new InferredAnonymTypeVisitor(context);
|
||||
for (PsiType type : inferenceResult.getInferredTypes()) {
|
||||
final Boolean accepted = type.accept(anonymTypeVisitor);
|
||||
if (accepted != null && !accepted.booleanValue()) {
|
||||
return PsiDiamondTypeImpl.DiamondInferenceResult.ANONYMOUS_INNER_RESULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return inferenceResult;
|
||||
}
|
||||
|
||||
public static DiamondInferenceResult resolveInferredTypesNoCheck(final PsiNewExpression newExpression, final PsiElement context) {
|
||||
@@ -457,4 +468,64 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* from JDK-8062373 Allow diamond to be used with anonymous classes
|
||||
* It is a compile-time error if the superclass or superinterface type of the anonymous class, T, or any subexpression of T, has one of the following forms:
|
||||
* - A type variable (4.4) that was not declared as a type parameter (such as a type variable produced by capture conversion (5.1.10))
|
||||
* - An intersection type (4.9)
|
||||
* - A class or interface type, where the class or interface declaration is not accessible from the class or interface in which the expression appears.
|
||||
*
|
||||
* The term "subexpression" includes type arguments of parameterized types (4.5), bounds of wildcards (4.5.1), and element types of array types (10.1).
|
||||
* It excludes bounds of type variables.
|
||||
*/
|
||||
private static class InferredAnonymTypeVisitor extends PsiTypeVisitor<Boolean> {
|
||||
private final PsiElement myExpression;
|
||||
|
||||
public InferredAnonymTypeVisitor(PsiElement expression) {
|
||||
myExpression = expression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitType(PsiType type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitIntersectionType(PsiIntersectionType intersectionType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitClassType(PsiClassType classType) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
if (psiClass != null) {
|
||||
if (psiClass instanceof PsiTypeParameter && InferenceSession.isFreshVariable((PsiTypeParameter)psiClass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PsiUtil.isAccessible(psiClass, myExpression, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (PsiType psiType : resolveResult.getSubstitutor().getSubstitutionMap().values()) {
|
||||
final Boolean accepted = psiType.accept(this);
|
||||
if (accepted != null && !accepted.booleanValue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -1628,6 +1628,10 @@ public class InferenceSession {
|
||||
final PsiElement originalContext = p1.getUserData(ORIGINAL_CONTEXT);
|
||||
return originalContext != null && originalContext == p2.getUserData(ORIGINAL_CONTEXT);
|
||||
}
|
||||
|
||||
public static boolean isFreshVariable(PsiTypeParameter typeParameter) {
|
||||
return typeParameter.getUserData(ORIGINAL_CONTEXT) != null;
|
||||
}
|
||||
|
||||
public static PsiClass findParameterizationOfTheSameGenericClass(List<PsiType> upperBounds,
|
||||
Processor<Pair<PsiType, PsiType>> processor) {
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class PsiPolyExpressionUtil {
|
||||
return isPolyExpression(((PsiParenthesizedExpression)expression).getExpression());
|
||||
}
|
||||
else if (expression instanceof PsiNewExpression) {
|
||||
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)expression).getClassReference();
|
||||
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)expression).getClassOrAnonymousClassReference();
|
||||
if (classReference != null) {
|
||||
final PsiReferenceParameterList parameterList = classReference.getParameterList();
|
||||
if (parameterList != null) {
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class A<T> {}
|
||||
class Foo<K extends A<K>> {
|
||||
{
|
||||
Foo foo = new Foo<<error descr="Cannot use ''<>'' with anonymous inner classes"></error>>() {};
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.List;
|
||||
|
||||
class Foo<E extends List<String> & Runnable> {
|
||||
Foo() {}
|
||||
|
||||
{
|
||||
Foo foo = new Foo<<error descr="Cannot use ''<>'' with anonymous inner classes"></error>>() {};
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
class B {
|
||||
private static class A {}
|
||||
|
||||
public static class C extends A {}
|
||||
public static class D extends A {}
|
||||
}
|
||||
|
||||
class Foo<E> {
|
||||
Foo(E e, E e1) {}
|
||||
|
||||
{
|
||||
Foo foo = new Foo<<error descr="Cannot use ''<>'' with anonymous inner classes"></error>>(new B.C(), new B.D()) {};
|
||||
}
|
||||
}
|
||||
+3
@@ -49,6 +49,9 @@ public class LightAdvHighlightingJdk9Test extends LightDaemonAnalyzerTestCase {
|
||||
public void testTryWithResources() { doTest(false, false); }
|
||||
|
||||
public void testDiamondsWithAnonymous() { doTest(false, false);}
|
||||
public void testDiamondsWithAnonymousRejectInferredFreshVariables() { doTest(false, false);}
|
||||
public void testDiamondsWithAnonymousRejectNotAccessibleType() { doTest(false, false);}
|
||||
public void testDiamondsWithAnonymousRejectIntersectionType() { doTest(false, false);}
|
||||
|
||||
public void testValueTypes() { setLanguageLevel(LanguageLevel.JDK_X); doTest(false, false); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user