mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
method refs: check more specific by return type; check used method in test via unused symbol inspection
This commit is contained in:
@@ -679,10 +679,12 @@ public class LambdaUtil {
|
||||
assert conflict != method;
|
||||
final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict);
|
||||
if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) {
|
||||
if (TypeConversionUtil.isAssignable(interfaceReturnType, interfaceReturnType1)) {
|
||||
int moreSpecific = isMoreSpecific(interfaceReturnType, interfaceReturnType1);
|
||||
if (moreSpecific > 0) {
|
||||
conflicts.remove(method);
|
||||
break;
|
||||
} else if (TypeConversionUtil.isAssignable(interfaceReturnType1, interfaceReturnType)) {
|
||||
}
|
||||
else if (moreSpecific < 0) {
|
||||
conflicts.remove(conflict);
|
||||
}
|
||||
}
|
||||
@@ -690,6 +692,46 @@ public class LambdaUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static int isMoreSpecific(PsiType returnType, PsiType returnType1) {
|
||||
final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(returnType);
|
||||
final PsiClass rClass = r.getElement();
|
||||
final PsiClassType.ClassResolveResult r1 = PsiUtil.resolveGenericsClassInType(returnType1);
|
||||
final PsiClass rClass1 = r1.getElement();
|
||||
if (rClass != null && rClass1 != null) {
|
||||
if (rClass == rClass1) {
|
||||
int moreSpecific = 0;
|
||||
for (PsiTypeParameter parameter : rClass.getTypeParameters()) {
|
||||
final PsiType t = r.getSubstitutor().substituteWithBoundsPromotion(parameter);
|
||||
final PsiType t1 = r1.getSubstitutor().substituteWithBoundsPromotion(parameter);
|
||||
if (t == null || t1 == null) continue;
|
||||
if (t1.isAssignableFrom(t) && !GenericsUtil.eliminateWildcards(t1).equals(t)) {
|
||||
if (moreSpecific == 1) {
|
||||
return 0;
|
||||
}
|
||||
moreSpecific = -1;
|
||||
}
|
||||
else if (t.isAssignableFrom(t1) && !GenericsUtil.eliminateWildcards(t).equals(t1)) {
|
||||
if (moreSpecific == -1) {
|
||||
return 0;
|
||||
}
|
||||
moreSpecific = 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return moreSpecific;
|
||||
}
|
||||
else if (rClass1.isInheritor(rClass, true)) {
|
||||
return 1;
|
||||
}
|
||||
else if (rClass.isInheritor(rClass1, true)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType getReturnType(int functionalTypeIdx, CandidateInfo method) {
|
||||
final PsiParameter[] methodParameters = ((PsiMethod)method.getElement()).getParameterList().getParameters();
|
||||
|
||||
+87
-4
@@ -16,11 +16,94 @@ class MyTest {
|
||||
Object m(Foo<Integer> f);
|
||||
}
|
||||
|
||||
static void foo(I1 i) {}
|
||||
static void foo(I2 i) {}
|
||||
static void foo(I3 i) {}
|
||||
private static void <warning descr="Private method 'foo(MyTest.I1)' is never used">foo</warning>(I1 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
static {
|
||||
private static void foo(I2 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
private static void <warning descr="Private method 'foo(MyTest.I3)' is never used">foo</warning>(I3 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
foo(Foo::m);
|
||||
}
|
||||
}
|
||||
|
||||
class MyTest1 {
|
||||
|
||||
interface I1 {
|
||||
Foo<?> m(String s);
|
||||
}
|
||||
|
||||
|
||||
interface I2 {
|
||||
Foo<?> m(Integer i);
|
||||
}
|
||||
|
||||
interface I3 {
|
||||
Foo<Number> m(Integer i);
|
||||
}
|
||||
|
||||
static class Foo<T extends Number> {
|
||||
Foo(T t) {
|
||||
System.out.println(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static void <warning descr="Private method 'm(MyTest1.I1)' is never used">m</warning>(I1 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
private static void m(I2 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
private static void <warning descr="Private method 'm(MyTest1.I3)' is never used">m</warning>(I3 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
m(Foo::new);
|
||||
}
|
||||
}
|
||||
class MyTest2 {
|
||||
|
||||
interface I1 {
|
||||
Foo<?> m(String s);
|
||||
}
|
||||
|
||||
|
||||
interface I2 {
|
||||
Foo<Integer> m(Integer i);
|
||||
}
|
||||
|
||||
interface I3 {
|
||||
Foo<Number> m(Integer i);
|
||||
}
|
||||
|
||||
static class Foo<T extends Number> {
|
||||
Foo(T t) {
|
||||
System.out.println(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static void <warning descr="Private method 'm(MyTest2.I1)' is never used">m</warning>(I1 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
private static void m(I2 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
private static void <warning descr="Private method 'm(MyTest2.I3)' is never used">m</warning>(I3 i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
m(Foo::new);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -16,11 +16,20 @@
|
||||
package com.intellij.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/methodRef";
|
||||
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
return new LocalInspectionTool[]{
|
||||
new UnusedSymbolLocalInspection(),
|
||||
};
|
||||
}
|
||||
|
||||
public void testValidContext() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
@@ -82,10 +91,14 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
}
|
||||
|
||||
public void testReturnTypeSpecific() throws Exception {
|
||||
doTest();
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
private void doTest(final boolean warnings) throws Exception {
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", warnings, false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user