From 0cae65939b25421b84480b49b30b2cb970c05479 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 7 Feb 2024 17:17:06 +0100 Subject: [PATCH] Java: improve incompatible types reporting - only report type with "anonymous" prefix when the left side is anonymous - use short names in the tool tip when fq names would be identical as well - use error color for the entire type name, including the anonymous prefix GitOrigin-RevId: f1555687adb0ab9e7c5850719165a7a508ecf181 --- .../daemon/impl/analysis/HighlightUtil.java | 78 ++++++++----------- .../advLVTI/LeftSideNotAnonymous.java | 7 ++ .../TypeObjectWithAnotherInitializer.java | 13 ++-- .../daemon/LightAdvLVTIHighlightingTest.java | 13 +++- 4 files changed, 52 insertions(+), 59 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/LeftSideNotAnonymous.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 460c21b58206..8a2fae634419 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -144,7 +144,7 @@ public final class HighlightUtil { private static final String SERIAL_PERSISTENT_FIELDS_FIELD_NAME = "serialPersistentFields"; public static final TokenSet BRACKET_TOKENS = TokenSet.create(JavaTokenType.LBRACKET, JavaTokenType.RBRACKET); - private static final String ANONYMOUS = "anonymous"; + private static final @NlsSafe String ANONYMOUS = "anonymous "; private HighlightUtil() { } @@ -3208,26 +3208,24 @@ public final class HighlightUtil { @NotNull static HighlightInfo.Builder createIncompatibleTypeHighlightInfo(@NotNull PsiType lType, - @Nullable PsiType rType, - @NotNull TextRange textRange, - int navigationShift, - @NotNull String reason) { + @Nullable PsiType rType, + @NotNull TextRange textRange, + int navigationShift, + @NotNull String reason) { PsiType baseLType = PsiUtil.convertAnonymousToBaseType(lType); PsiType baseRType = rType == null ? null : PsiUtil.convertAnonymousToBaseType(rType); + boolean leftAnonymous = PsiUtil.resolveClassInClassTypeOnly(lType) instanceof PsiAnonymousClass; String styledReason = reason.isEmpty() ? "" : String.format("
%s
", reason); - IncompatibleTypesTooltipComposer tooltipComposer = (lTypeString, lTypeArguments, rTypeString, rTypeArguments) -> { - lTypeString = addAnonymousIfNecessary(lType, lTypeString); - rTypeString = addAnonymousIfNecessary(rType, rTypeString); - return JavaErrorBundle.message("incompatible.types.html.tooltip", - lTypeString, lTypeArguments, - rTypeString, rTypeArguments, - styledReason, "#" + ColorUtil.toHex(UIUtil.getContextHelpForeground())); - }; - String toolTip = createIncompatibleTypesTooltip(baseLType, baseRType, tooltipComposer); + IncompatibleTypesTooltipComposer tooltipComposer = (lTypeString, lTypeArguments, rTypeString, rTypeArguments) -> + JavaErrorBundle.message("incompatible.types.html.tooltip", + lTypeString, lTypeArguments, + rTypeString, rTypeArguments, + styledReason, "#" + ColorUtil.toHex(UIUtil.getContextHelpForeground())); + String toolTip = createIncompatibleTypesTooltip(leftAnonymous ? lType : baseLType, leftAnonymous ? rType : baseRType, tooltipComposer); - String lTypeString = JavaHighlightUtil.formatType(lType); - String rTypeString = JavaHighlightUtil.formatType(rType); + String lTypeString = JavaHighlightUtil.formatType(leftAnonymous ? lType : baseLType); + String rTypeString = JavaHighlightUtil.formatType(leftAnonymous ? rType : baseRType); String description = JavaErrorBundle.message("incompatible.types", lTypeString, rTypeString); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(textRange) @@ -3236,22 +3234,6 @@ public final class HighlightUtil { .navigationShift(navigationShift); } - /** - * - * @param type the type - * @param typeString the raw type (base type of anonymous type) - * @return String representation if `anonymous` is requried - */ - @NotNull - private static String addAnonymousIfNecessary(@Nullable PsiType type, - @NotNull String typeString) { - if (type instanceof PsiClassType lClassType && - lClassType.resolve() instanceof PsiAnonymousClass) { - typeString = ANONYMOUS + " " + typeString; - } - return typeString; - } - public static HighlightInfo.Builder checkArrayType(PsiTypeElement type) { int dimensions = 0; for (PsiElement child = type.getFirstChild(); child != null; child = child.getNextSibling()) { @@ -3321,21 +3303,17 @@ public final class HighlightUtil { String closeBrace = i == typeParamColumns - 1 ? ">" : ","; boolean showShortType = showShortType(lSubstitutedType, rSubstitutedType); - requiredRow.append(skipColumns ? "" - : "") + requiredRow.append(skipColumns ? "" : "") .append(lTypeParams.length == 0 ? "" : openBrace) .append(redIfNotMatch(lSubstitutedType, true, showShortType)) .append(i < lTypeParams.length ? closeBrace : "") - .append(skipColumns ? "" - : ""); + .append(skipColumns ? "" : ""); - foundRow.append(skipColumns ? "" - : "") + foundRow.append(skipColumns ? "" : "") .append(rTypeParams.length == 0 ? "" : openBrace) .append(redIfNotMatch(rSubstitutedType, matches, showShortType)) .append(i < rTypeParams.length ? closeBrace : "") - .append(skipColumns ? "" - : ""); + .append(skipColumns ? "" : ""); } PsiType lRawType = lType instanceof PsiClassType ? ((PsiClassType)lType).rawType() : lType; PsiType rRawType = rType instanceof PsiClassType ? ((PsiClassType)rType).rawType() : rType; @@ -3350,7 +3328,9 @@ public final class HighlightUtil { static boolean showShortType(@Nullable PsiType lType, @Nullable PsiType rType) { if (Comparing.equal(lType, rType)) return true; - return lType != null && rType != null && !Comparing.strEqual(lType.getPresentableText(), rType.getPresentableText()); + return lType != null && rType != null && + (!lType.getPresentableText().equals(rType.getPresentableText()) || + lType.getCanonicalText().equals(rType.getCanonicalText())); } private static @NotNull String getReasonForIncompatibleTypes(PsiType rType) { @@ -3385,15 +3365,19 @@ public final class HighlightUtil { @NotNull static @NlsSafe HtmlChunk redIfNotMatch(@Nullable PsiType type, boolean matches, boolean shortType) { if (type == null) return HtmlChunk.empty(); - Color color; - if (matches) { - color = ExperimentalUI.isNewUI() ? JBUI.CurrentTheme.Editor.Tooltip.FOREGROUND : UIUtil.getToolTipForeground(); + String typeText; + if (shortType || type instanceof PsiCapturedWildcardType) { + typeText = PsiUtil.resolveClassInClassTypeOnly(type) instanceof PsiAnonymousClass + ? ANONYMOUS + type.getPresentableText() + : type.getPresentableText(); } else { - color = NamedColorUtil.getErrorForeground(); + typeText = type.getCanonicalText(); } - return HtmlChunk.tag("font").attr("color", ColorUtil.toHtmlColor(color)) - .addText(shortType || type instanceof PsiCapturedWildcardType ? type.getPresentableText() : type.getCanonicalText()); + Color color = matches + ? ExperimentalUI.isNewUI() ? JBUI.CurrentTheme.Editor.Tooltip.FOREGROUND : UIUtil.getToolTipForeground() + : NamedColorUtil.getErrorForeground(); + return HtmlChunk.tag("font").attr("color", ColorUtil.toHtmlColor(color)).addText(typeText); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/LeftSideNotAnonymous.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/LeftSideNotAnonymous.java new file mode 100644 index 000000000000..72b624381155 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/LeftSideNotAnonymous.java @@ -0,0 +1,7 @@ +class X {} +class Y { + public void main(String[] args) { + var x = new X(); + x = new Y() {}; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/TypeObjectWithAnotherInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/TypeObjectWithAnotherInitializer.java index f3400f9ce022..eca707ee345d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/TypeObjectWithAnotherInitializer.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advLVTI/TypeObjectWithAnotherInitializer.java @@ -1,10 +1,7 @@ -class TypeObjectWithAnotherInitializer { - class X {} - class Y { - public void main(String[] args) { - var x = new X() {}; - x = new Y(); - } +class X {} +class Y { + public void main(String[] args) { + var x = new X() {}; + x = new Y(); } - } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvLVTIHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvLVTIHighlightingTest.java index d81f599143d2..b78a3a79746c 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvLVTIHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvLVTIHighlightingTest.java @@ -99,12 +99,14 @@ public class LightAdvLVTIHighlightingTest extends LightDaemonAnalyzerTestCase { public void testTypeObject() { doTest(); String toolTipForeground = ColorUtil.toHtmlColor(UIUtil.getToolTipForeground()); + String errorTipForeground = ColorUtil.toHtmlColor(UIUtil.getErrorForeground()); String greyed = ColorUtil.toHtmlColor(UIUtil.getContextHelpForeground()); String expected = "" + "" + "" + - "" + - "" + + "" + + "" + + "" + "
Required type:anonymous Object
Provided:Object
anonymous Object
Provided:Object
" + ""; @@ -122,8 +124,9 @@ public class LightAdvLVTIHighlightingTest extends LightDaemonAnalyzerTestCase { String expected = "" + "" + "" + - "" + - "" + + "" + + "" + + "" + "
Required type:anonymous X
Provided:Y
anonymous X
Provided:Y
" + ""; @@ -132,6 +135,8 @@ public class LightAdvLVTIHighlightingTest extends LightDaemonAnalyzerTestCase { .filter(info -> info.type == HighlightInfoType.ERROR) .forEach(info -> Assert.assertEquals(expected, info.getToolTip())); } + + public void testLeftSideNotAnonymous() { doTest(); } @Override protected Sdk getProjectJDK() {