don't show error on method reference if functional expression is located inside invalid context without target functional type

This commit is contained in:
Anna Kozlova
2015-12-10 19:52:16 +01:00
parent b21cde7b47
commit 132bb137a1
19 changed files with 38 additions and 32 deletions

View File

@@ -1339,7 +1339,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
if (!myHolder.hasErrorResults()) {
if (results.length == 0 || results[0] instanceof MethodCandidateInfo && !((MethodCandidateInfo)results[0]).isApplicable()) {
if (results.length == 0 || results[0] instanceof MethodCandidateInfo &&
!((MethodCandidateInfo)results[0]).isApplicable() &&
expression.getFunctionalInterfaceType() != null) {
String description = null;
if (expression.isConstructor()) {
final PsiClass containingClass = PsiMethodReferenceUtil.getQualifierResolveResult(expression).getContainingClass();
@@ -1359,7 +1361,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (description != null) {
final PsiElement referenceNameElement = expression.getReferenceNameElement();
final HighlightInfo highlightInfo =
HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).descriptionAndTooltip(description).range(referenceNameElement).create();
HighlightInfo.newHighlightInfo(results.length == 0 ? HighlightInfoType.WRONG_REF
: HighlightInfoType.ERROR)
.descriptionAndTooltip(description).range(referenceNameElement).create();
myHolder.add(highlightInfo);
final TextRange fixRange = HighlightMethodUtil.getFixRange(referenceNameElement);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QuickFixFactory.getInstance().createCreateMethodFromUsageFix(expression));

View File

@@ -25,6 +25,7 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
@@ -119,7 +120,8 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
map.put(methodReferenceExpression, functionalInterfaceType);
final JavaResolveResult result = methodReferenceExpression.advancedResolve(false);
final PsiElement element = result.getElement();
if (element != null && result.isAccessible()) {
if (element != null && result.isAccessible() &&
!(result instanceof MethodCandidateInfo && !((MethodCandidateInfo)result).isApplicable())) {
if (element instanceof PsiMethod && !isSimpleCall(parameters, callExpression, (PsiMethod)element)) {
return null;
}

View File

@@ -40,6 +40,6 @@ class AAmbiguous {
}
public static void main(Promise<String> helloWorld) {
helloWorld.then(AAmbiguous::<error descr="Cannot resolve method 'calculateLength'">calculateLength</error>);
helloWorld.then<error descr="Ambiguous method call: both 'Promise.then(Function<? super String, Promise<Integer>>)' and 'Promise.then(AsyncFunction<? super String, Promise<Integer>>)' match">(AAmbiguous::calculateLength)</error>;
}
}

View File

@@ -29,7 +29,7 @@ class MyTest {
{
Bar1 b1 = MyTest :: foo;
bar(MyTest :: <error descr="Cannot resolve method 'foo'">foo</error>);
bar<error descr="Ambiguous method call: both 'MyTest.bar(Bar1)' and 'MyTest.bar(Bar2)' match">(MyTest :: foo)</error>;
}
}

View File

@@ -71,7 +71,7 @@ class StaticInner1 {
static void call3(I2 s) {}
static {
call3(StaticInner1.Inner :: <error descr="Cannot resolve constructor 'Inner'">new</error>);
call3<error descr="Ambiguous method call: both 'StaticInner1.call3(I1)' and 'StaticInner1.call3(I2)' match">(StaticInner1.Inner :: new)</error>;
}
}

View File

@@ -49,7 +49,7 @@ class MyTestConstructor {
private static void <warning descr="Private method 'foo(MyTestConstructor.I3)' is never used">foo</warning>(I3 i) {System.out.println(i);}
static {
foo(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
foo<error descr="Ambiguous method call: both 'MyTestConstructor.foo(I1)' and 'MyTestConstructor.foo(I2)' match">(Foo::new)</error>;
}
}
@@ -78,6 +78,6 @@ class MyTestMethod {
private static void <warning descr="Private method 'foo(MyTestMethod.I3)' is never used">foo</warning>(I3 i) {System.out.println(i);}
static {
foo(MyTestMethod::<error descr="Cannot resolve method 'm'">m</error>);
foo<error descr="Ambiguous method call: both 'MyTestMethod.foo(I1)' and 'MyTestMethod.foo(I2)' match">(MyTestMethod::m)</error>;
}
}

View File

@@ -38,7 +38,7 @@ class MyTest1 {
}
public static void main(String[] args) {
call(1, MyTest1::<error descr="Cannot resolve method 'm'">m</error>);
call<error descr="Ambiguous method call: both 'MyTest1.call(int, I1)' and 'MyTest1.call(int, I2)' match">(1, MyTest1::m)</error>;
}
}
@@ -192,6 +192,6 @@ class MyTest9 {
void test() {
g1(MyTest9::m);
g2(MyTest9::<error descr="Cannot resolve method 'm'">m</error>);
g2<error descr="Ambiguous method call: both 'MyTest9.g2(I1)' and 'MyTest9.g2(I2)' match">(MyTest9::m)</error>;
}
}

View File

@@ -20,8 +20,8 @@ class MyTest {
static void foo(I3 i) {}
static {
foo(MyTest::<error descr="Cannot resolve method 'm'">m</error>);
foo(MyTest::<error descr="Cannot resolve method 'm1'">m1</error>);
foo<error descr="Ambiguous method call: both 'MyTest.foo(I1)' and 'MyTest.foo(I2)' match">(MyTest::m)</error>;
foo<error descr="Ambiguous method call: both 'MyTest.foo(I1)' and 'MyTest.foo(I2)' match">(MyTest::m1)</error>;
}
}
@@ -44,9 +44,9 @@ class MyTest1 {
static {
foo1(MyTest1::m);
foo2(MyTest1::<error descr="Cannot resolve method 'm'">m</error>);
foo2<error descr="Ambiguous method call: both 'MyTest1.foo2(I1)' and 'MyTest1.foo2(I2)' match">(MyTest1::m)</error>;
foo1(MyTest1::m1);
foo2(MyTest1::<error descr="Cannot resolve method 'm1'">m1</error>);
foo2<error descr="Ambiguous method call: both 'MyTest1.foo2(I1)' and 'MyTest1.foo2(I2)' match">(MyTest1::m1)</error>;
}
}

View File

@@ -39,6 +39,6 @@ class MyTest1 {
static void foo(I3 i) {}
static {
foo(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
foo<error descr="Ambiguous method call: both 'MyTest1.foo(I1)' and 'MyTest1.foo(I2)' match">(Foo::new)</error>;
}
}

View File

@@ -29,7 +29,7 @@ class MyTest {
}
public static void main(String[] args) {
foo(Foo::<error descr="Cannot resolve method 'm'">m</error>);
foo<error descr="Ambiguous method call: both 'MyTest.foo(I1)' and 'MyTest.foo(I2)' match">(Foo::m)</error>;
}
}
@@ -67,7 +67,7 @@ class MyTest1 {
}
public static void main(String[] args) {
m(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
m<error descr="Ambiguous method call: both 'MyTest1.m(I1)' and 'MyTest1.m(I2)' match">(Foo::new)</error>;
}
}
class MyTest2 {
@@ -104,6 +104,6 @@ class MyTest2 {
}
public static void main(String[] args) {
m(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
m<error descr="Ambiguous method call: both 'MyTest2.m(I1)' and 'MyTest2.m(I2)' match">(Foo::new)</error>;
}
}

View File

@@ -2,7 +2,7 @@ import java.util.*;
class LambdaTest {
public void testR() {
new ArrayList<String>() :: <error descr="Cannot resolve method 'size'">size</error> = "";
<error descr="Incompatible types. Found: 'java.lang.String', required: '<method reference>'">new ArrayList<String>() :: size = ""</error>;
}
}

View File

@@ -116,7 +116,7 @@ class MyTest2 {
static void call3(I2 s) {}
static {
call3(MyTest2::m1);
call3(MyTest2::<error descr="Cannot resolve method 'm2'">m2</error>);
call3<error descr="Ambiguous method call: both 'MyTest2.call3(I1)' and 'MyTest2.call3(I2)' match">(MyTest2::m2)</error>;
call3(MyTest2::m3);
call3<error descr="'call3(MyTest2.I2)' in 'MyTest2' cannot be applied to '(<method reference>)'">(MyTest2::m4)</error>;
}

View File

@@ -1,6 +1,6 @@
public class Test {
{
if (Test::<error descr="Cannot resolve method 'length'">length</error> instanceof String) {
if (<error descr="Method reference expression is not expected here">Test::length instanceof String</error>) {
}
bar(Test::length);
}

View File

@@ -28,6 +28,6 @@ class Test2 {
static void call(I2 i2) { System.out.println(i2); }
static {
call(Test2::<error descr="Cannot resolve method 'm'">m</error>);
call<error descr="Ambiguous method call: both 'Test2.call(I1)' and 'Test2.call(I2)' match">(Test2::m)</error>;
}
}

View File

@@ -12,7 +12,7 @@ class Test {
void m(LongMapper... lm) { }
{
m(this ::<error descr="Cannot resolve method 'ii'">ii</error>);
m<error descr="Ambiguous method call: both 'Test.m(IntMapper, IntMapper...)' and 'Test.m(LongMapper...)' match">(this ::ii)</error>;
}
int ii() {return 0;}

View File

@@ -32,12 +32,12 @@ class Test {
meth1(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
meth2(Foo::new);
meth3(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
meth4(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
meth4<error descr="Ambiguous method call: both 'Test.meth4(I1)' and 'Test.meth4(I2)' match">(Foo::new)</error>;
meth1(Test::<error descr="Cannot resolve method 'foo'">foo</error>);
meth2(Test::foo);
meth3(Test::<error descr="Cannot resolve method 'foo'">foo</error>);
meth4(Test::<error descr="Cannot resolve method 'foo'">foo</error>);
meth4<error descr="Ambiguous method call: both 'Test.meth4(I1)' and 'Test.meth4(I2)' match">(Test::foo)</error>;
}

View File

@@ -31,8 +31,8 @@ class Test {
String i1 = instanceCall(this::m0);
String i2 = instanceCall(this::m1);
String i3 = instanceCall(this::m2);
String i4 = instanceCall(this::<error descr="Cannot resolve method 'm01'">m01</error>);
String i5 = instanceCall(this::<error descr="Cannot resolve method 'm012'">m012</error>);
String i4 = instanceCall<error descr="Ambiguous method call: both 'Test.instanceCall(I0)' and 'Test.instanceCall(I1<String>)' match">(this::m01)</error>;
String i5 = instanceCall<error descr="Ambiguous method call: both 'Test.instanceCall(I0)' and 'Test.instanceCall(I1<String>)' match">(this::m012)</error>;
}
void n0() { }
@@ -52,8 +52,8 @@ class Test {
static {
Test s1 = staticCall(Test::n0);
Test s2 = staticCall(Test::n1);
Test s3 = <error descr="Cannot resolve method 'staticCall(<method reference>)'">staticCall</error>(Test::<error descr="Cannot resolve method 'n2'">n2</error>);
Test s4 = staticCall(Test::<error descr="Cannot resolve method 'n01'">n01</error>);
Test s5 = staticCall(Test::<error descr="Cannot resolve method 'n012'">n012</error>);
Test s3 = <error descr="Cannot resolve method 'staticCall(<method reference>)'">staticCall</error>(Test::n2);
Test s4 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test, String>)' match">(Test::n01)</error>;
Test s5 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test, String>)' match">(Test::n012)</error>;
}
}

View File

@@ -34,7 +34,7 @@ class Test {
{
Set<String> m = replyWith(this::query);
System.out.println(m);
Set<String> m1 = replyWith(this::<error descr="Cannot resolve method 'query1'">query1</error>);
Set<String> m1 = replyWith<error descr="Ambiguous method call: both 'Test.replyWith(Function<String, List<String>>)' and 'Test.replyWith(Callable<List<String>>)' match">(this::query1)</error>;
System.out.println(m1);
}
}

View File

@@ -19,7 +19,7 @@ class Test {
private void <warning descr="Private method 'm1(I3)' is never used">m1</warning>(I3 i2) {System.out.println(i2);}
void test() {
m (this::<error descr="Cannot resolve method 'bar'">bar</error>);
m <error descr="Ambiguous method call: both 'Test.m(I1)' and 'Test.m(I2)' match">(this::bar)</error>;
m1(this::bar);
}