java: reject diamonds in anonymous classes with non-private methods (IDEA-248972;IDEA-248973)

GitOrigin-RevId: 5300c91c601dd59f3a020ac6a6627517aaca68c7
This commit is contained in:
Anna Kozlova
2020-08-27 12:00:15 +02:00
committed by intellij-monorepo-bot
parent d2a66b75c5
commit a2e3d7e5ab
10 changed files with 52 additions and 10 deletions

View File

@@ -7,6 +7,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixActionRegistrarImpl;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.core.JavaPsiBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbService;
@@ -112,6 +113,16 @@ public final class GenericsHighlightUtil {
return highlightInfo;
}
}
PsiElement parent = referenceParameterList.getParent().getParent();
if (parent instanceof PsiAnonymousClass) {
PsiAnonymousClass anonymousClass = (PsiAnonymousClass)parent;
if (ContainerUtil.exists(anonymousClass.getMethods(), method -> !method.hasModifierProperty(PsiModifier.PRIVATE) && method.findSuperMethods().length == 0)) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(referenceParameterList)
.descriptionAndTooltip(JavaPsiBundle.message("diamond.error.anonymous.inner.classes.non.private"))
.create();
}
}
}
}

View File

@@ -192,7 +192,8 @@ lambda.body.must.be.a.statement.expression=Lambda body must be a statement expre
diamond.error.explicit.type.parameters.for.constructor=Cannot use diamonds with explicit type parameters for constructor
diamond.error.cannot.infer.arguments=Cannot infer arguments
diamond.error.cannot.infer.arguments.unable.to.resolve.constructor=Cannot infer arguments (unable to resolve constructor)
diamond.error.anonymous.inner.classes=Cannot use ''<>'' with anonymous inner classes
diamond.error.anonymous.inner.classes=Cannot use '<>' with anonymous inner classes
diamond.error.anonymous.inner.classes.non.private=Cannot use '<>' due to non-private method which doesn't override or implement a method from a supertype
diamond.error.cannot.infer.type.arguments=Cannot infer type arguments for {0}
error.incompatible.type.no.type.variable=no instance(s) of type variable(s) exist so that {0}
error.incompatible.type.no.type.variable.0=no instance(s) of type variable(s) {0} exist so that {1}

View File

@@ -13,6 +13,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@@ -50,6 +51,12 @@ public final class PsiDiamondTypeUtil {
if (!skipDiamonds && typeElements.length == 1 && typeElements[0].getType() instanceof PsiDiamondType) return false;
final PsiDiamondTypeImpl.DiamondInferenceResult inferenceResult = PsiDiamondTypeImpl.resolveInferredTypes(expression, context);
if (inferenceResult.getErrorMessage() == null) {
PsiAnonymousClass anonymousClass = expression.getAnonymousClass();
if (anonymousClass != null &&
ContainerUtil.exists(anonymousClass.getMethods(),
method -> !method.hasModifierProperty(PsiModifier.PRIVATE) && method.findSuperMethods().length == 0)) {
return false;
}
final List<PsiType> types = inferenceResult.getInferredTypes();
PsiType[] typeArguments = null;
if (expectedType instanceof PsiClassType) {

View File

@@ -95,14 +95,14 @@ interface I<T> {
}
class FI1 {
I<? extends String> i1 = new I<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {
I<? extends String> i1 = new I<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {
@Override
public String m() {
return null;
}
};
I<?> i2 = new I<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {
I<?> i2 = new I<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {
@Override
public Object m() {
return null;

View File

@@ -4,12 +4,12 @@ class Neg09 {
static class Nested<X> {}
void testSimple() {
Member<?> m1 = new Member<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {};
Nested<?> m2 = new Nested<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {};
Member<?> m1 = new Member<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {};
Nested<?> m2 = new Nested<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {};
}
void testQualified() {
Member<?> m1 = this.new Member<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {};
Nested<?> m2 = new Neg09.Nested<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {};
Member<?> m1 = this.new Member<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {};
Nested<?> m2 = new Neg09.Nested<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {};
}
}

View File

@@ -8,4 +8,20 @@ class Outer {
}
};
}
interface I<T> {
void m();
}
{
I<String> i1 = new I<>() {
@Override
public void m() {}
};
I<String> i2 = new I<error descr="Cannot use '<>' due to non-private method which doesn't override or implement a method from a supertype"><></error>() {
@Override
public void m() {}
public void m1() {}
};
}
}

View File

@@ -1,6 +1,6 @@
class A<T> {}
class Foo<K extends A<K>> {
{
Foo foo = new Foo<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {};
Foo foo = new Foo<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {};
}
}

View File

@@ -4,6 +4,6 @@ class Foo<E extends List<String> & Runnable> {
Foo() {}
{
Foo foo = new Foo<error descr="Cannot use ''<>'' with anonymous inner classes"><></error>() {};
Foo foo = new Foo<error descr="Cannot use '<>' with anonymous inner classes"><></error>() {};
}
}

View File

@@ -10,6 +10,6 @@ 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()) {};
Foo foo = new Foo<error descr="Cannot use '<>' with anonymous inner classes"><></error>(new B.C(), new B.D()) {};
}
}

View File

@@ -0,0 +1,7 @@
// "Replace with <>" "false"
import java.util.*;
class Test {
List<String> l = new ArrayList<St<caret>ring>() {
void non_private_method() {}
};
}