mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-21 22:11:40 +07:00
inference: propagate variable renames through the call hierarchy; calculate tooltips in tests (IDEA-151948)
This commit is contained in:
@@ -24,7 +24,6 @@ import com.intellij.codeInsight.daemon.impl.quickfix.*;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
@@ -398,7 +397,7 @@ public class HighlightMethodUtil {
|
||||
String description = JavaErrorMessages.message("wrong.method.arguments", methodName, containerName, argTypes);
|
||||
final Ref<PsiElement> elementToHighlight = new Ref<PsiElement>(list);
|
||||
String toolTip;
|
||||
if (parent instanceof PsiClass && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (parent instanceof PsiClass) {
|
||||
toolTip = buildOneLineMismatchDescription(list, candidateInfo, elementToHighlight);
|
||||
if (toolTip == null) {
|
||||
toolTip = createMismatchedArgumentsHtmlTooltip(candidateInfo, list);
|
||||
|
||||
@@ -1175,6 +1175,13 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
public void registerIncompatibleErrorMessage(Collection<InferenceVariable> variables, String incompatibleTypesMessage) {
|
||||
variables = new ArrayList<InferenceVariable>(variables);
|
||||
Collections.sort((ArrayList<InferenceVariable>)variables, new Comparator<InferenceVariable>() {
|
||||
@Override
|
||||
public int compare(InferenceVariable v1, InferenceVariable v2) {
|
||||
return Comparing.compare(v1.getName(), v2.getName());
|
||||
}
|
||||
});
|
||||
final String variablesEnumeration = StringUtil.join(variables, new Function<InferenceVariable, String>() {
|
||||
@Override
|
||||
public String fun(InferenceVariable variable) {
|
||||
@@ -1814,8 +1821,9 @@ public class InferenceSession {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
public void propagateVariables(Collection<InferenceVariable> variables) {
|
||||
public void propagateVariables(Collection<InferenceVariable> variables, PsiSubstitutor substitution) {
|
||||
myInferenceVariables.addAll(variables);
|
||||
myRestoreNameSubstitution = myRestoreNameSubstitution.putAll(substitution);
|
||||
}
|
||||
|
||||
public PsiType substituteWithInferenceVariables(PsiType type) {
|
||||
@@ -1826,6 +1834,10 @@ public class InferenceSession {
|
||||
return myInferenceSubstitution;
|
||||
}
|
||||
|
||||
public PsiSubstitutor getRestoreNameSubstitution() {
|
||||
return myRestoreNameSubstitution;
|
||||
}
|
||||
|
||||
public InferenceSessionContainer getInferenceSessionContainer() {
|
||||
return myInferenceSessionContainer;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
}
|
||||
if (callSession != session) {
|
||||
session.getInferenceSessionContainer().registerNestedSession(callSession);
|
||||
session.propagateVariables(callSession.getInferenceVariables());
|
||||
session.propagateVariables(callSession.getInferenceVariables(), callSession.getRestoreNameSubstitution());
|
||||
if (callSession.isErased()) {
|
||||
session.setErased();
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
if (typeParams != null) {
|
||||
PsiSubstitutor siteSubstitutor = InferenceSession.chooseSiteSubstitutor(candidateProperties, resolveResult, method);
|
||||
final InferenceSession callSession = new InferenceSession(typeParams, siteSubstitutor, expression.getManager(), expression);
|
||||
callSession.propagateVariables(session.getInferenceVariables());
|
||||
callSession.propagateVariables(session.getInferenceVariables(), session.getRestoreNameSubstitution());
|
||||
if (method != null) {
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
@@ -2,6 +2,6 @@ class A {{
|
||||
String.valueOf(<error descr="Cannot resolve symbol 'chars'">chars</error>, 0, 10); // all arguments are highlighted when only chars has a problemij
|
||||
new String(<error descr="Cannot resolve symbol 'chars'">chars</error>, 0, 10); // highlighting is good here.
|
||||
|
||||
String.valueOf<error descr="'valueOf(char[], int, int)' in 'java.lang.String' cannot be applied to '(int, int, int)'">(0, 0, 10)</error>;
|
||||
String.valueOf(<error descr="'valueOf(char[], int, int)' in 'java.lang.String' cannot be applied to '(int, int, int)'">0</error>, 0, 10);
|
||||
new String<error descr="Cannot resolve constructor 'String(int, int, int)'">(0, 0, 10)</error>;
|
||||
}}
|
||||
|
||||
@@ -3,7 +3,7 @@ import java.util.List;
|
||||
|
||||
class IdeaBugTest {
|
||||
public void foo(List<Base> base) {
|
||||
MyCollection.fun<error descr="'fun(java.util.List<? extends Base>, java.util.Comparator<? super Base>)' in 'MyCollection' cannot be applied to '(java.util.List<Base>, SubComparator)'">(base, new SubComparator())</error>;
|
||||
MyCollection.fun(base, <error descr="'fun(java.util.List<? extends Base>, java.util.Comparator<? super Base>)' in 'MyCollection' cannot be applied to '(java.util.List<Base>, SubComparator)'">new SubComparator()</error>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import java.util.Set;
|
||||
class Test {
|
||||
|
||||
public static void test(Set foo, Matcher<Iterable<String>> matcher) {
|
||||
assertThat<error descr="'assertThat(Test.Matcher<? super java.util.Set>, java.util.Set)' in 'Test' cannot be applied to '(Test.Matcher<java.lang.Iterable<java.lang.String>>, java.util.Set)'">(matcher, foo)</error>;
|
||||
assertThat(<error descr="'assertThat(Test.Matcher<? super java.util.Set>, java.util.Set)' in 'Test' cannot be applied to '(Test.Matcher<java.lang.Iterable<java.lang.String>>, java.util.Set)'">matcher</error>, foo);
|
||||
|
||||
Matcher<Iterable<String>> b = null;
|
||||
<error descr="Incompatible types. Found: 'Test.Matcher<java.lang.Iterable<java.lang.String>>', required: 'Test.Matcher<? super java.util.Set>'">Matcher<? super Set> a = b;</error>
|
||||
|
||||
@@ -5,6 +5,6 @@ abstract class X {
|
||||
abstract <T> void copy(List<T> dest, List<? extends T> src);
|
||||
|
||||
void foo(List<?> x, List<?> y){
|
||||
copy<error descr="'copy(java.util.List<capture<?>>, java.util.List<? extends capture<?>>)' in 'X' cannot be applied to '(java.util.List<capture<?>>, java.util.List<capture<?>>)'">(x, y)</error>;
|
||||
copy(x, <error descr="'copy(java.util.List<capture<?>>, java.util.List<? extends capture<?>>)' in 'X' cannot be applied to '(java.util.List<capture<?>>, java.util.List<capture<?>>)'">y</error>);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ class Test {
|
||||
|
||||
public void doesNotCompile() {
|
||||
Container<String> container = new Container<String>();
|
||||
assertThat<error descr="'assertThat(Test.Container<java.lang.String>, Test.Matcher<? super Test.Container<java.lang.String>>)' in 'Test' cannot be applied to '(Test.Container<java.lang.String>, Test.Matcher<Test.Container<capture<? super java.lang.String>>>)'">(container, hasSomething(is("foo")))</error>;
|
||||
assertThat(container, <error descr="'assertThat(Test.Container<java.lang.String>, Test.Matcher<? super Test.Container<java.lang.String>>)' in 'Test' cannot be applied to '(Test.Container<java.lang.String>, Test.Matcher<Test.Container<capture<? super java.lang.String>>>)'">hasSomething(is("foo"))</error>);
|
||||
}
|
||||
|
||||
public static class Container<T> {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class D<T> {
|
||||
void foo(D<?> x){
|
||||
bar<error descr="'bar(D<?>, D<? super java.lang.Object>)' in 'D' cannot be applied to '(D<capture<?>>, D<capture<?>>)'">(x,x)</error>;
|
||||
bar(x,<error descr="'bar(D<?>, D<? super java.lang.Object>)' in 'D' cannot be applied to '(D<capture<?>>, D<capture<?>>)'">x</error>);
|
||||
}
|
||||
<T> void bar(D<? extends T> x, D<? super T> y){}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ class NestedGenericGoodCodeIsRed {
|
||||
Number num = null;
|
||||
satisfiesAllOf(isPositive(), isEqualTo(num));
|
||||
|
||||
this.<Number>satisfiesAllOf<error descr="'satisfiesAllOf(NestedGenericGoodCodeIsRed.Predicate<? super java.lang.Number>, NestedGenericGoodCodeIsRed.Predicate<? super java.lang.Number>)' in 'NestedGenericGoodCodeIsRed' cannot be applied to '(NestedGenericGoodCodeIsRed.Predicate<java.lang.Number>, NestedGenericGoodCodeIsRed.Predicate<java.lang.Integer>)'">(isPositive(), isEqualTo(10))</error>;
|
||||
this.<Number>satisfiesAllOf(isPositive(), <error descr="'satisfiesAllOf(NestedGenericGoodCodeIsRed.Predicate<? super java.lang.Number>, NestedGenericGoodCodeIsRed.Predicate<? super java.lang.Number>)' in 'NestedGenericGoodCodeIsRed' cannot be applied to '(NestedGenericGoodCodeIsRed.Predicate<java.lang.Number>, NestedGenericGoodCodeIsRed.Predicate<java.lang.Integer>)'">isEqualTo(10)</error>);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class VarianceTesting {
|
||||
|
||||
class SuperTester <U> {
|
||||
void go(Acceptor<? super U> acceptor, U u) {
|
||||
acceptor.accept<error descr="'accept(SuperTester<capture<? super U>>, capture<? super U>)' in 'SuperTester.Acceptor' cannot be applied to '(SuperTester<U>, U)'">(this, u)</error>;
|
||||
acceptor.accept(<error descr="'accept(SuperTester<capture<? super U>>, capture<? super U>)' in 'SuperTester.Acceptor' cannot be applied to '(SuperTester<U>, U)'">this</error>, u);
|
||||
}
|
||||
|
||||
static class Acceptor <V> {
|
||||
@@ -142,7 +142,7 @@ class S1 {
|
||||
}
|
||||
|
||||
void bar(List<? extends S1> k) {
|
||||
f<error descr="'f(java.util.List<capture<? extends S1>>, capture<? extends S1>)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, S1)'">(k, k.get(0))</error>;
|
||||
f(k, <error descr="'f(java.util.List<capture<? extends S1>>, capture<? extends S1>)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, S1)'">k.get(0)</error>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ class S2 {
|
||||
}
|
||||
|
||||
void bar(List<? extends S2> k) {
|
||||
f<error descr="'f(java.util.List<capture<? extends S2>>, java.util.List<capture<? extends S2>>)' in 'S2' cannot be applied to '(java.util.List<capture<? extends S2>>, java.util.List<capture<? extends S2>>)'">(k, k)</error>;
|
||||
f(k, <error descr="'f(java.util.List<capture<? extends S2>>, java.util.List<capture<? extends S2>>)' in 'S2' cannot be applied to '(java.util.List<capture<? extends S2>>, java.util.List<capture<? extends S2>>)'">k</error>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ public static void foo(List<? extends Foo> foos) {
|
||||
class OtherBug1 {
|
||||
public static void foo(List<? super Foo> foos) {
|
||||
final Comparator<Foo> comparator = createComparator();
|
||||
Collections.sort<error descr="'sort(java.util.List<capture<? super OtherBug1.Foo>>, java.util.Comparator<? super capture<? super OtherBug1.Foo>>)' in 'java.util.Collections' cannot be applied to '(java.util.List<capture<? super OtherBug1.Foo>>, java.util.Comparator<OtherBug1.Foo>)'">(foos, comparator)</error>;
|
||||
Collections.sort(foos, <error descr="'sort(java.util.List<capture<? super OtherBug1.Foo>>, java.util.Comparator<? super capture<? super OtherBug1.Foo>>)' in 'java.util.Collections' cannot be applied to '(java.util.List<capture<? super OtherBug1.Foo>>, java.util.Comparator<OtherBug1.Foo>)'">comparator</error>);
|
||||
}
|
||||
|
||||
private static Comparator<Foo> createComparator() {
|
||||
|
||||
@@ -61,7 +61,7 @@ class VarianceTesting {
|
||||
|
||||
class SuperTester <U> {
|
||||
void go(Acceptor<? super U> acceptor, U u) {
|
||||
acceptor.accept<error descr="'accept(SuperTester<capture<? super U>>, capture<? super U>)' in 'SuperTester.Acceptor' cannot be applied to '(SuperTester<U>, U)'">(this, u)</error>;
|
||||
acceptor.accept(<error descr="'accept(SuperTester<capture<? super U>>, capture<? super U>)' in 'SuperTester.Acceptor' cannot be applied to '(SuperTester<U>, U)'">this</error>, u);
|
||||
}
|
||||
|
||||
static class Acceptor <V> {
|
||||
@@ -87,7 +87,7 @@ class CaptureTest {
|
||||
}
|
||||
|
||||
void foo (Class<? extends Emum<CaptureTest>> clazz) {
|
||||
Emum.valueOf<error descr="'valueOf(java.lang.Class<T>, java.lang.String)' in 'CaptureTest.Emum' cannot be applied to '(java.lang.Class<capture<? extends CaptureTest.Emum<CaptureTest>>>, java.lang.String)'">(clazz, "CCC")</error>;
|
||||
Emum.valueOf(<error descr="'valueOf(java.lang.Class<T>, java.lang.String)' in 'CaptureTest.Emum' cannot be applied to '(java.lang.Class<capture<? extends CaptureTest.Emum<CaptureTest>>>, java.lang.String)'">clazz</error>, "CCC");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class BigNumber {
|
||||
public <U, V> void toTypeMap(Stream<U> p) {
|
||||
Function<U, V> map2 = p.collect(Collectors.toMap(Function.identity(<caret>), Function.identity()));
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,17 @@
|
||||
package com.intellij.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/graphInference";
|
||||
|
||||
@@ -399,6 +405,34 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testVariableNamesOfNestedCalls() throws Exception {
|
||||
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
|
||||
String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
|
||||
configureByFile(filePath);
|
||||
Collection<HighlightInfo> infos = doHighlighting();
|
||||
|
||||
List<String> tooltips = new ArrayList<>();
|
||||
|
||||
for (HighlightInfo info : infos) {
|
||||
if (info.getSeverity() == HighlightSeverity.ERROR) {
|
||||
tooltips.add(info.getToolTip());
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(tooltips.contains("<html><body><table border=0><tr><td>" +
|
||||
"<b>identity( ) </b></td><td colspan=1>in <b>Function</b> cannot be applied</td></tr><tr><td>to</td><td><b>()</b> " +
|
||||
|
||||
"</td></tr></table><br/>" +
|
||||
"reason: no instance(s) of type variable(s) K, U exist so that Map<K, U> conforms to Function<U, V>" +
|
||||
"</body></html>"));
|
||||
assertTrue(tooltips.contains(
|
||||
"<html><body><table border=0><tr><td>" +
|
||||
"<b>identity( ) </b></td><td colspan=1>in <b>Function</b> cannot be applied</td></tr><tr><td>to</td><td><b>()</b> " +
|
||||
"</td></tr></table><br/>" +
|
||||
"reason: no instance(s) of type variable(s) K, U exist so that Map<K, U> conforms to Function<U, V>" +
|
||||
"</body></html>"));
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user