incompatible types tooltip: highlight generic type components in the multiple args mismatched tooltip

GitOrigin-RevId: a1b3fec553161841a559e45c2a76e9d46b12975f
This commit is contained in:
Anna.Kozlova
2019-10-11 10:50:45 +02:00
committed by intellij-monorepo-bot
parent 34a4e401a6
commit 4e4396b0c8
4 changed files with 85 additions and 8 deletions

View File

@@ -1038,8 +1038,8 @@ public class HighlightMethodUtil {
PsiExpression expression = i < expressions.length ? expressions[i] : null;
if (assignmentCompatible(i, parameters, expressions, substitutor)) continue;
boolean varargs = info != null && info.getApplicabilityLevel() == MethodCandidateInfo.ApplicabilityLevel.VARARGS;
PsiType parameterType = PsiTypesUtil.getParameterType(parameters, i, varargs);
boolean showShortType = HighlightUtil.showShortType(substitutor.substitute(parameterType),
PsiType parameterType = substitutor.substitute(PsiTypesUtil.getParameterType(parameters, i, varargs));
boolean showShortType = HighlightUtil.showShortType(parameterType,
expression != null ? expression.getType() : null);
s.append("<tr>");
if (parameter != null) {
@@ -1055,7 +1055,7 @@ public class HighlightMethodUtil {
if (expression != null) {
s.append("<td style='padding-right: 28px;'>")
.append(HighlightUtil.redIfNotMatch(expression.getType(), false, showShortType))
.append(mismatchedExpressionType(parameterType, expression))
.append("</td>");
}
else {
@@ -1076,6 +1076,25 @@ public class HighlightMethodUtil {
return s.toString();
}
@NotNull
static String mismatchedExpressionType(PsiType parameterType, PsiExpression expression) {
return HighlightUtil.createIncompatibleTypesTooltip(parameterType, expression.getType(), new HighlightUtil.IncompatibleTypesTooltipComposer() {
@NotNull
@Override
public String consume(@NotNull String lRawType,
@NotNull String lTypeArguments,
@NotNull String rRawType,
@NotNull String rTypeArguments) {
return rRawType + rTypeArguments;
}
@Override
public boolean skipTypeArgsColumns() {
return true;
}
});
}
private static boolean assignmentCompatible(int i,
@NotNull PsiParameter[] parameters,
@NotNull PsiExpression[] expressions,

View File

@@ -31,7 +31,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.PsiTypeElementImpl;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
@@ -2738,6 +2737,13 @@ public class HighlightUtil extends HighlightUtilBase {
interface IncompatibleTypesTooltipComposer {
@NotNull
String consume(@NotNull String lRawType, @NotNull String lTypeArguments, @NotNull String rRawType, @NotNull String rTypeArguments);
/**
* Override if expected/actual pair layout is a row
*/
default boolean skipTypeArgsColumns() {
return false;
}
}
@NotNull
@@ -2748,6 +2754,7 @@ public class HighlightUtil extends HighlightUtilBase {
PsiTypeParameter[] rTypeParams = rTypeData.second;
int typeParamColumns = Math.max(lTypeParams.length, rTypeParams.length);
boolean skipColumns = consumer.skipTypeArgsColumns();
StringBuilder requiredRow = new StringBuilder();
StringBuilder foundRow = new StringBuilder();
for (int i = 0; i < typeParamColumns; i++) {
@@ -2762,10 +2769,23 @@ public class HighlightUtil extends HighlightUtilBase {
String openBrace = i == 0 ? "&lt;" : "";
String closeBrace = i == typeParamColumns - 1 ? "&gt;" : ",";
boolean showShortType = showShortType(lSubstitutedType, rSubstitutedType);
requiredRow.append("<td style='padding: 0px 0px 8px 0px;'>").append(lTypeParams.length == 0 ? "" : openBrace).append(redIfNotMatch(lSubstitutedType, true, showShortType))
.append(i < lTypeParams.length ? closeBrace : "").append("</td>");
foundRow.append("<td style='padding: 0px 0px 0px 0px;'>").append(rTypeParams.length == 0 ? "" : openBrace).append(redIfNotMatch(rSubstitutedType, matches, showShortType))
.append(i < rTypeParams.length ? closeBrace : "").append("</td>");
requiredRow.append(skipColumns ? ""
: "<td style='padding: 0px 0px 8px 0px;'>")
.append(lTypeParams.length == 0 ? "" : openBrace)
.append(redIfNotMatch(lSubstitutedType, true, showShortType))
.append(i < lTypeParams.length ? closeBrace : "")
.append(skipColumns ? ""
: "</td>");
foundRow.append(skipColumns ? ""
: "<td style='padding: 0px 0px 0px 0px;'>")
.append(rTypeParams.length == 0 ? "" : openBrace)
.append(redIfNotMatch(rSubstitutedType, matches, showShortType))
.append(i < rTypeParams.length ? closeBrace : "")
.append(skipColumns ? ""
: "</td>");
}
PsiType lRawType = lType instanceof PsiClassType ? ((PsiClassType)lType).rawType() : lType;
PsiType rRawType = rType instanceof PsiClassType ? ((PsiClassType)rType).rawType() : rType;

View File

@@ -0,0 +1,8 @@
import java.util.List;
class MyTest {
void f(List<Integer> integerList, List<String> stringList) {}
void m(List<Integer> integerList, List<String> stringList) {
f<error descr="'f(java.util.List<java.lang.Integer>, java.util.List<java.lang.String>)' in 'MyTest' cannot be applied to '(java.util.List<java.lang.String>, java.util.List<java.lang.Integer>)'">(stringList, integerList)</error>;
}
}

View File

@@ -1096,6 +1096,36 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
.forEach(info -> Assert.assertEquals(expected, info.getToolTip()));
}
public void testTooltipComponents() {
doTest();
String toolTipForeground = ColorUtil.toHtmlColor(UIUtil.getToolTipForeground());
String greyed = ColorUtil.toHtmlColor(UIUtil.getContextHelpForeground());
String red = ColorUtil.toHtmlColor(DialogWrapper.ERROR_FOREGROUND_COLOR);
String paramBgColor = ColorUtil.toHtmlColor(EditorColorsUtil.getGlobalOrDefaultColorScheme()
.getAttributes(DefaultLanguageHighlighterColors.INLINE_PARAMETER_HINT)
.getBackgroundColor());
int fontSize = StartupUiUtil.getLabelFont().getSize() - (SystemInfo.isWindows ? 0 : 1);
String expected = "<html><body><table>" +
"<tr>" +
"<td/>" +
"<td style='color: " + greyed + "; padding-left: 16px; padding-right: 24px;'>Required type</td>" +
"<td style='color: " + greyed + "; padding-right: 28px;'>Provided</td></tr>" +
"<tr>" +
"<td><table><tr><td style='color: " + greyed + "; font-size:" + fontSize + "pt; padding:1px 4px 1px 4px;background-color: " + paramBgColor + ";'>integerList:</td></tr></table></td>" +
"<td style='padding-left: 16px; padding-right: 24px;'><font color='" + toolTipForeground + "'>List&lt;Integer&gt;</font></td>" +
"<td style='padding-right: 28px;'><font color='" + toolTipForeground + "'>List</font>&lt;<font color='" + red + "'>String</font>&gt;</td></tr>" +
"<tr>" +
"<td><table><tr><td style='color: " + greyed + "; font-size:" + fontSize + "pt; padding:1px 4px 1px 4px;background-color: " + paramBgColor + ";'>stringList:</td></tr></table></td>" +
"<td style='padding-left: 16px; padding-right: 24px;'><font color='" + toolTipForeground+ "'>List&lt;String&gt;</font></td>" +
"<td style='padding-right: 28px;'><font color='" + toolTipForeground + "'>List</font>&lt;<font color='" + red + "'>Integer</font>&gt;</td></tr>" +
"</table></body></html>";
doHighlighting()
.stream()
.filter(info -> info.type == HighlightInfoType.ERROR)
.forEach(info -> Assert.assertEquals(expected, info.getToolTip()));
}
public void testBridgeMethodOverriding() { doTest(); }
public void testNestedWildcardsWithImplicitBounds() { doTest(); }
public void testCallOnRawWithExplicitTypeArguments() { doTest(); }