lambda: highlight containing method ambiguity on method name: this avoids lots of lines of lambda body to be highlighted and it would show errors even if lambda body contains errors actually caused by the ambiguity on the parent level (IDEA-141580)

This commit is contained in:
Anna Kozlova
2015-06-18 16:22:27 +03:00
parent 1b3a089335
commit 30a12275a2
22 changed files with 57 additions and 55 deletions

View File

@@ -569,12 +569,13 @@ public class HighlightMethodUtil {
@Nullable
static HighlightInfo checkAmbiguousMethodCallArguments(@NotNull PsiReferenceExpression referenceToMethod,
@NotNull JavaResolveResult[] resolveResults,
@NotNull PsiExpressionList list,
final PsiElement element,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiResolveHelper resolveHelper) {
@NotNull JavaResolveResult[] resolveResults,
@NotNull PsiExpressionList list,
final PsiElement element,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiResolveHelper resolveHelper,
@NotNull PsiElement elementToHighlight) {
MethodCandidateInfo methodCandidate1 = null;
MethodCandidateInfo methodCandidate2 = null;
for (JavaResolveResult result : resolveResults) {
@@ -594,7 +595,6 @@ public class HighlightMethodUtil {
String description;
String toolTip;
PsiElement elementToHighlight;
HighlightInfoType highlightInfoType = HighlightInfoType.ERROR;
if (methodCandidate2 != null) {
PsiMethod element1 = methodCandidate1.getElement();
@@ -617,7 +617,6 @@ public class HighlightMethodUtil {
}
description = JavaErrorMessages.message("ambiguous.method.call", m1, m2);
toolTip = createAmbiguousMethodHtmlTooltip(new MethodCandidateInfo[]{methodCandidate1, methodCandidate2});
elementToHighlight = list;
}
else {
if (element != null && !resolveResult.isAccessible()) {
@@ -632,9 +631,6 @@ public class HighlightMethodUtil {
if (candidates.length == 0) {
return null;
}
else {
elementToHighlight = list;
}
}
toolTip = XmlStringUtil.escapeString(description);
}

View File

@@ -553,7 +553,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
// this check is for fake expression from JspMethodCallImpl
referenceExpression.getParent() == expression) {
try {
myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallArguments(referenceExpression, results, list, resolved, result, expression, myResolveHelper));
if (PsiTreeUtil.findChildrenOfType(expression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallArguments(referenceExpression, results, list, resolved, result, expression, myResolveHelper, list));
}
}
catch (IndexNotReadyException ignored) {
}
@@ -1210,8 +1212,12 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
PsiExpressionList list = methodCallExpression.getArgumentList();
if (!HighlightMethodUtil.isDummyConstructorCall(methodCallExpression, myResolveHelper, list, expression)) {
try {
myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallIdentifier(expression, results, list, resolved, result,
methodCallExpression, myResolveHelper));
myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallIdentifier(expression, results, list, resolved, result, methodCallExpression, myResolveHelper));
if (!PsiTreeUtil.findChildrenOfType(methodCallExpression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
myHolder.add(HighlightMethodUtil
.checkAmbiguousMethodCallArguments(expression, results, list, resolved, result, methodCallExpression, myResolveHelper, expression.getReferenceNameElement()));
}
}
catch (IndexNotReadyException ignored) {
}

View File

@@ -22,6 +22,6 @@ class AmbiguityRawGenerics {
<Z> void foo(I3<Z> s) { }
void bar() {
foo<error descr="Ambiguous method call: both 'AmbiguityRawGenerics.foo(I1)' and 'AmbiguityRawGenerics.foo(I2)' match">(()-> { throw new RuntimeException(); })</error>;
<error descr="Ambiguous method call: both 'AmbiguityRawGenerics.foo(I1)' and 'AmbiguityRawGenerics.foo(I2)' match">foo</error>(()-> { throw new RuntimeException(); });
}
}

View File

@@ -1,6 +1,6 @@
public interface IDEA99969 {
default IntStream distinct(Stream s) {
return s.map(i -> <error descr="Inconvertible types; cannot cast '<lambda parameter>' to 'int'">(int) i</error>);
return s.<error descr="Ambiguous method call: both 'Stream.map(Function)' and 'Stream.map(IntFunction)' match">map</error>(i -> <error descr="Inconvertible types; cannot cast '<lambda parameter>' to 'int'">(int) i</error>);
}
}
interface Stream<T> {

View File

@@ -20,7 +20,7 @@ class Test {
void m(IL lm, II s) { }
{
m<error descr="Ambiguous method call: both 'Test.m(II, IL)' and 'Test.m(IL, II)' match">(() -> 1, () ->1)</error>;
<error descr="Ambiguous method call: both 'Test.m(II, IL)' and 'Test.m(IL, II)' match">m</error>(() -> 1, () ->1);
}
@@ -42,17 +42,17 @@ class Test {
{
mi (1);
m2();
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(()->1)</error>;
<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">m2</error>(()->1);
m2(()->1, ()->1);
m2(()->1, ()->1, ()->1);
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(null, null, null)</error>;
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(()->1, null, null)</error>;
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(null, ()->1, null)</error>;
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(null, null, ()->1)</error>;
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(()->1, ()->1, null)</error>;
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(null, ()->1, ()->1)</error>;
m2<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">(()->1, null, ()->1)</error>;
<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">m2</error>(()->1, null, null);
<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">m2</error>(null, ()->1, null);
<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">m2</error>(null, null, ()->1);
<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">m2</error>(()->1, ()->1, null);
<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">m2</error>(null, ()->1, ()->1);
<error descr="Ambiguous method call: both 'Test.m2(II, II...)' and 'Test.m2(IL...)' match">m2</error>(()->1, null, ()->1);
m2(()->1L, null, null);
m2(null, ()->1L, null);
@@ -73,8 +73,8 @@ class Test {
m3(() -> 1, () -> 1, () -> 1);
m3<error descr="Ambiguous method call: both 'Test.m3(II...)' and 'Test.m3(IL...)' match">(null, null)</error>;
m3<error descr="Ambiguous method call: both 'Test.m3(II...)' and 'Test.m3(IL...)' match">(() -> 1, null)</error>;
m3<error descr="Ambiguous method call: both 'Test.m3(II...)' and 'Test.m3(IL...)' match">(null, () -> 1)</error>;
<error descr="Ambiguous method call: both 'Test.m3(II...)' and 'Test.m3(IL...)' match">m3</error>(() -> 1, null);
<error descr="Ambiguous method call: both 'Test.m3(II...)' and 'Test.m3(IL...)' match">m3</error>(null, () -> 1);
m3(() -> 1L, null);
m3(null, () -> 1L);
}

View File

@@ -19,8 +19,8 @@ public class Test<A, B extends Number> {
public static void main(String[] args) {
Inner<Number, Double> inn = new Inner<>();
inn.m8<error descr="Ambiguous method call: both 'Inner.m8(IO<? extends Number>)' and 'Inner.m8(IN<? extends Double>)' match">(p -> 1.0)</error>;
new Test<Number, Integer>().foo<error descr="Cannot resolve method 'foo(<lambda expression>)'">(p -> 1.0)</error>;
inn.<error descr="Ambiguous method call: both 'Inner.m8(IO<? extends Number>)' and 'Inner.m8(IN<? extends Double>)' match">m8</error>(p -> 1.0);
new Test<Number, Integer>().<error descr="Cannot resolve method 'foo(<lambda expression>)'">foo</error>(p -> 1.0);
}
}

View File

@@ -8,8 +8,8 @@ class Test {
IntStream mi = sp.map(Inner::foo);
Stream<Integer> mI = sp.map(Inner::fooBoxed);
IntStream li = sp.map(inner->inner.<error descr="Cannot resolve method 'foo()'">foo</error>());
Stream<Integer> lI = sp.map(inner -> inner.<error descr="Cannot resolve method 'fooBoxed()'">fooBoxed</error>());
IntStream li = sp.<error descr="Ambiguous method call: both 'Stream.map(Function<? super Inner, ? extends R>)' and 'Stream.map(IntFunction<? super Inner>)' match">map</error>(inner->inner.<error descr="Cannot resolve method 'foo()'">foo</error>());
Stream<Integer> lI = sp.<error descr="Ambiguous method call: both 'Stream.map(Function<? super Inner, ? extends Integer>)' and 'Stream.map(IntFunction<? super Inner>)' match">map</error>(inner -> inner.<error descr="Cannot resolve method 'fooBoxed()'">fooBoxed</error>());
}
interface Stream<T> {

View File

@@ -1,8 +1,8 @@
class IntStream {
private void foo(IntStream s) {
s.map<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">(i -> 1 << i)</error>;
s.map<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">(i -> 1)</error>;
s.map<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">(i -> i)</error>;
s.<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">map</error>(i -> 1 << i);
s.<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">map</error>(i -> 1);
s.<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">map</error>(i -> i);
}
public static void main(String[] args) {

View File

@@ -22,7 +22,7 @@ class AmbiguityVarargs {
void test() {
foo(()->{});
foo<error descr="Ambiguous method call: both 'AmbiguityVarargs.foo(I1<String>)' and 'AmbiguityVarargs.foo(IV<String>)' match">((a1) -> {})</error>;
<error descr="Ambiguous method call: both 'AmbiguityVarargs.foo(I1<String>)' and 'AmbiguityVarargs.foo(IV<String>)' match">foo</error>((a1) -> {});
foo((a1, a2)->{});
}
}

View File

@@ -25,7 +25,7 @@ class ReturnTypeIncompatibility {
}
public static void main(String[] args) {
call<error descr="Cannot resolve method 'call(<lambda expression>)'">(i-> {return i;})</error>;
<error descr="Cannot resolve method 'call(<lambda expression>)'">call</error>(i-> {return i;});
}
}
@@ -57,7 +57,7 @@ class ReturnTypeCompatibility {
}
public static void main(String[] args) {
call<error descr="Cannot resolve method 'call(<lambda expression>)'">(i-> {return i;})</error>;
<error descr="Cannot resolve method 'call(<lambda expression>)'">call</error>(i-> {return i;});
}
}

View File

@@ -21,9 +21,9 @@ class Test {
}
void foo(Foo<String> as, final Foo<Character> ac) {
boolean b1 = as.forAll(s -> ac.forAll<error descr="Cannot resolve method 'forAll(<lambda expression>)'">(c -> false)</error>);
String s1 = as.forAll(s -> ac.forAll<error descr="Cannot resolve method 'forAll(<lambda expression>)'">(c -> "")</error>);
boolean b2 = as.forAll(s -> ac.forAll<error descr="Cannot resolve method 'forAll(<lambda expression>)'">(c -> "")</error>);
boolean b1 = as.<error descr="Ambiguous method call: both 'Foo.forAll(I<String, Boolean>)' and 'Foo.forAll(II<String, String>)' match">forAll</error>(s -> ac.<error descr="Cannot resolve method 'forAll(<lambda expression>)'">forAll</error>(c -> false));
String s1 = as.<error descr="Ambiguous method call: both 'Foo.forAll(I<String, Boolean>)' and 'Foo.forAll(II<String, String>)' match">forAll</error>(s -> ac.<error descr="Cannot resolve method 'forAll(<lambda expression>)'">forAll</error>(c -> ""));
boolean b2 = as.<error descr="Ambiguous method call: both 'Foo.forAll(I<String, Boolean>)' and 'Foo.forAll(II<String, String>)' match">forAll</error>(s -> ac.<error descr="Cannot resolve method 'forAll(<lambda expression>)'">forAll</error>(c -> ""));
String s2 = as.forAll2(s -> ac.forAll2(c -> <error descr="Bad return type in lambda expression: boolean cannot be converted to String">false</error>));
boolean b3 = as.forAll((I<String, Boolean>)s -> ac.forAll((I<Character, Boolean>)c -> <error descr="Bad return type in lambda expression: String cannot be converted to Boolean">""</error>));
String s3 = as.forAll((II<String, String>)s -> ac.forAll((II<Character, String>)c -> <error descr="Bad return type in lambda expression: boolean cannot be converted to String">false</error>));

View File

@@ -23,7 +23,7 @@ class Test {
void test() {
call(() -> { });
call<error descr="Ambiguous method call: both 'Test.call(I1)' and 'Test.call(IVarargs)' match">(p1 -> { })</error>;
<error descr="Ambiguous method call: both 'Test.call(I1)' and 'Test.call(IVarargs)' match">call</error>(p1 -> { });
call((p1, p2) -> {});
}
}

View File

@@ -7,6 +7,6 @@ class Test {
public static void call(I i) { }
public static void main(String[] args) {
call<error descr="Ambiguous method call: both 'Test.call(IStr)' and 'Test.call(I)' match">(()-> null)</error>;
<error descr="Ambiguous method call: both 'Test.call(IStr)' and 'Test.call(I)' match">call</error>(()-> null);
}
}

View File

@@ -12,7 +12,7 @@ class MS {
void test(boolean cond) {
m(cond ? () -> 26 : () -> 24);
m<error descr="Cannot resolve method 'm(?)'">(cond ? () -> 26 : () -> new Integer(42))</error>;
<error descr="Cannot resolve method 'm(?)'">m</error>(cond ? () -> 26 : () -> new Integer(42));
m(cond ? () -> new Integer(26) : () -> new Integer(42));
}
}

View File

@@ -22,7 +22,7 @@ class Test {
}
public void test() {
foo<error descr="Ambiguous method call: both 'Test.foo(RunnableX)' and 'Test.foo(Callable<List<?>>)' match">(()-> new ArrayList<Void>() )</error>;
<error descr="Ambiguous method call: both 'Test.foo(RunnableX)' and 'Test.foo(Callable<List<?>>)' match">foo</error>(()-> new ArrayList<Void>() );
}
}

View File

@@ -3,7 +3,7 @@ import java.util.function.Supplier;
class Test {
public static void main(String... args) {
c<error descr="Cannot resolve method 'c(<lambda expression>, <lambda expression>)'">(() -> 3, () -> 10)</error>;
<error descr="Cannot resolve method 'c(<lambda expression>, <lambda expression>)'">c</error>(() -> 3, () -> 10);
}
public static <T> void c(Supplier<T> s1, Supplier<T> s2) {}

View File

@@ -14,7 +14,7 @@ class Test {
void m1(ILong l, Object i) {}
void test() {
m<error descr="Ambiguous method call: both 'Test.m(IInt, Long)' and 'Test.m(ILong, Integer)' match">(() -> 1, null)</error>;
<error descr="Ambiguous method call: both 'Test.m(IInt, Long)' and 'Test.m(ILong, Integer)' match">m</error>(() -> 1, null);
m1(() -> 1, null);
}
}

View File

@@ -11,12 +11,12 @@ class Test {
}
void test(boolean cond) {
m<error descr="Cannot resolve method 'm(<lambda expression>)'">(() -> {
<error descr="Cannot resolve method 'm(<lambda expression>)'">m</error>(() -> {
if (cond)
return 42;
else
return foo();
})</error>;
});
m(() -> {
return foo();

View File

@@ -14,7 +14,7 @@ class Test {
}
void fooBar(IntStream1 instr){
Supplier<Stream<Integer>> si = () -> instr.map ((i) -> (( <error descr="Operator '%' cannot be applied to '<lambda parameter>', 'int'">i % 2</error>) == 0) ? i : -i).boxed();
Supplier<Stream<Integer>> si = () -> instr.<error descr="Ambiguous method call: both 'IntStream1.map(IntFunction<Integer>)' and 'IntStream1.map(IntUnaryOperator)' match">map</error> ((i) -> (( <error descr="Operator '%' cannot be applied to '<lambda parameter>', 'int'">i % 2</error>) == 0) ? i : -i).boxed();
System.out.println(si);
Supplier<Stream<Integer>> si1 = () -> instr.map <error descr="Ambiguous method call: both 'IntStream1.map(IntFunction<Integer>)' and 'IntStream1.map(IntUnaryOperator)' match">(null)</error>.boxed();
System.out.println(si1);

View File

@@ -12,6 +12,6 @@ abstract class PertinentToApplicabilityOfExplicitlyTypedLambdaTest {
abstract void foo(B b);
{
foo<error descr="Cannot resolve method 'foo(<lambda expression>)'">(x -> y -> 42)</error>;
<error descr="Cannot resolve method 'foo(<lambda expression>)'">foo</error>(x -> y -> 42);
}
}

View File

@@ -14,10 +14,10 @@ abstract class Test {
foo(x -> {
return x += 1;
});
foo<error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">(x -> x += 1)</error>;
<error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">foo</error>(x -> x += 1);
foo(x -> 1);
foo(x -> <error descr="Operator '!' cannot be applied to 'int'">!x</error>);
foo<error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">(x -> ++x)</error>;
<error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">foo</error>(x -> ++x);
foo(x -> o instanceof String ? 1 : 0);
}
}

View File

@@ -14,7 +14,7 @@ class Foo {
void foo(K k){}
void bar() {
foo((p) -> {
<error descr="Ambiguous method call: both 'Foo.foo(I)' and 'Foo.foo(K)' match">foo</error>((p) -> {
System.out.println<error descr="Cannot resolve method 'println(<lambda parameter>)'">(p)</error>;
});
@@ -26,9 +26,9 @@ class Foo {
System.out.println(s);
});
foo<error descr="Cannot resolve method 'foo(<lambda expression>)'">((String p, String k) -> {
<error descr="Cannot resolve method 'foo(<lambda expression>)'">foo</error>((String p, String k) -> {
System.out.println(p);
})</error>;
});
}
}
@@ -62,7 +62,7 @@ class WithTypeParams {
System.out.println(p);
});
foo<error descr="Cannot resolve method 'foo(<lambda expression>)'">((int k) -> {System.out.println(k);})</error>;
<error descr="Cannot resolve method 'foo(<lambda expression>)'">foo</error>((int k) -> {System.out.println(k);});
}
}
}