IJ-CR-119726 [java-highlighting] S IDEA-306108 Assignment to a variable with non-denotable type: confusing error message

- fix for quickfix
- refactoring

GitOrigin-RevId: aedc118f2dd67bf56391792e7cd3042a8f7f33a8
This commit is contained in:
Mikhail Pyltsin
2024-01-25 14:37:04 +01:00
committed by intellij-monorepo-bot
parent 874e9d5be8
commit 82abbe2dbb
6 changed files with 75 additions and 62 deletions

View File

@@ -3200,24 +3200,21 @@ public final class HighlightUtil {
@NotNull String reason) {
PsiType baseLType = PsiUtil.convertAnonymousToBaseType(lType);
PsiType baseRType = rType == null ? null : PsiUtil.convertAnonymousToBaseType(rType);
String styledReason = reason.isEmpty() ? ""
: String
.format("<table><tr><td style=''padding-top: 10px; padding-left: 4px;''>%s</td></tr></table>", reason);
String toolTip = createIncompatibleTypesTooltip(baseLType, baseRType,
(lRawType, lTypeArguments, rRawType, rTypeArguments) -> {
PairTypeResult result = getDifferentAnonymousTypes(lType, rType, lRawType, rRawType, baseLType, baseRType);
return JavaErrorBundle
.message("incompatible.types.html.tooltip", result.lRawType(), lTypeArguments,
result.rRawType(),
rTypeArguments, styledReason,
"#" + ColorUtil.toHex(UIUtil.getContextHelpForeground()));
});
String styledReason = reason.isEmpty() ? "" :
String.format("<table><tr><td style=''padding-top: 10px; padding-left: 4px;''>%s</td></tr></table>", 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);
String lRawType = JavaHighlightUtil.formatType(baseLType);
String rRawType = JavaHighlightUtil.formatType(baseRType);
PairTypeResult result = getDifferentAnonymousTypes(lType, rType, lRawType, rRawType, baseLType, baseRType);
String description = JavaErrorBundle.message(
"incompatible.types", result.lRawType(), result.rRawType());
String lTypeString = JavaHighlightUtil.formatType(lType);
String rTypeString = JavaHighlightUtil.formatType(rType);
String description = JavaErrorBundle.message("incompatible.types", lTypeString, rTypeString);
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(textRange)
.description(description)
@@ -3226,35 +3223,19 @@ public final class HighlightUtil {
}
/**
* Gets the different types if they are equal and one of them or both is anonymous types
*
* @param lType the left type
* @param rType the right type
* @param lRawType the left raw type (base type of anonymous type)
* @param rRawType the right raw type (base type of anonymous type)
* @param baseLType the base left type (text representation)
* @param baseRType the base right type (text representation)
* @return a PairTypeResult object representing the different types
* @param type the type
* @param typeString the raw type (base type of anonymous type)
* @return String representation if `anonymous` is requried
*/
@NotNull
private static PairTypeResult getDifferentAnonymousTypes(@NotNull PsiType lType,
@Nullable PsiType rType,
@NotNull String lRawType,
@NotNull String rRawType,
@NotNull PsiType baseLType,
@Nullable PsiType baseRType) {
if (lRawType.equals(rRawType)) {
if (!lType.equals(baseLType)) {
lRawType = ANONYMOUS + " " + lRawType;
}
if (rType != null && !rType.equals(baseRType)) {
rRawType = ANONYMOUS + " " + rRawType;
}
private static String addAnonymousIfNecessary(@Nullable PsiType type,
@NotNull String typeString) {
if (type instanceof PsiClassType lClassType &&
lClassType.resolve() instanceof PsiAnonymousClass) {
typeString = ANONYMOUS + " " + typeString;
}
return new PairTypeResult(lRawType, rRawType);
}
private record PairTypeResult(@NotNull String lRawType, @NotNull String rRawType) {
return typeString;
}
public static HighlightInfo.Builder checkArrayType(PsiTypeElement type) {

View File

@@ -123,6 +123,7 @@ public final class ChangeNewOperatorTypeFix extends PsiUpdateModCommandAction<Ps
}
public static void register(@NotNull HighlightInfo.Builder highlightInfo, PsiExpression expression, PsiType lType) {
if (lType instanceof PsiClassType lClassType && lClassType.resolve() instanceof PsiAnonymousClass) return;
expression = PsiUtil.deparenthesizeExpression(expression);
if (!(expression instanceof PsiNewExpression newExpression)) return;
final PsiType rType = expression.getType();

View File

@@ -0,0 +1,10 @@
class TypeObjectWithAnotherInitializer {
class X {}
class Y {
public void main(String[] args) {
var x = new X() {};
<error descr="Incompatible types. Found: 'TypeObjectWithAnotherInitializer.Y', required: 'anonymous TypeObjectWithAnotherInitializer.X'">x = new Y()</error>;
}
}
}

View File

@@ -2,6 +2,7 @@
package com.intellij.java.codeInsight.daemon;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
import com.intellij.codeInspection.AnonymousCanBeLambdaInspection;
import com.intellij.codeInspection.redundantCast.RedundantCastInspection;
@@ -15,7 +16,10 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.ui.ColorUtil;
import com.intellij.util.IdempotenceChecker;
import com.intellij.util.ui.UIUtil;
import org.junit.Assert;
public class LightAdvLVTIHighlightingTest extends LightDaemonAnalyzerTestCase {
private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/advLVTI";
@@ -89,6 +93,43 @@ public class LightAdvLVTIHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testTypeObject() {
doTest();
String toolTipForeground = ColorUtil.toHtmlColor(UIUtil.getToolTipForeground());
String greyed = ColorUtil.toHtmlColor(UIUtil.getContextHelpForeground());
String expected = "<html><table>" +
"<tr>" +
"<td style='padding: 0px 16px 8px 4px;color: "+greyed+"'>Required type:</td>" +
"<td style='padding: 0px 4px 8px 0px;'>anonymous <font color=\""+toolTipForeground+"\">Object</font></td></tr>" +
"<tr><td style='padding: 0px 16px 0px 4px;color: "+greyed+"'>Provided:</td><td style='padding: 0px 4px 0px 0px;'><font color=\""+toolTipForeground+"\">Object</font></td></tr>" +
"</table>" +
"</html>";
doHighlighting()
.stream()
.filter(info -> info.type == HighlightInfoType.ERROR)
.forEach(info -> Assert.assertEquals(expected, info.getToolTip()));
}
public void testTypeObjectWithAnotherInitializer() {
doTest();
String toolTipForeground = ColorUtil.toHtmlColor(UIUtil.getToolTipForeground());
String errorTipForeground = ColorUtil.toHtmlColor(UIUtil.getErrorForeground());
String greyed = ColorUtil.toHtmlColor(UIUtil.getContextHelpForeground());
String expected = "<html><table>" +
"<tr>" +
"<td style='padding: 0px 16px 8px 4px;color: "+greyed+"'>Required type:</td>" +
"<td style='padding: 0px 4px 8px 0px;'>anonymous <font color=\""+toolTipForeground+"\">X</font></td></tr>" +
"<tr><td style='padding: 0px 16px 0px 4px;color: "+greyed+"'>Provided:</td><td style='padding: 0px 4px 0px 0px;'><font color=\""+errorTipForeground+"\">Y</font></td></tr>" +
"</table>" +
"</html>";
doHighlighting()
.stream()
.filter(info -> info.type == HighlightInfoType.ERROR)
.forEach(info -> Assert.assertEquals(expected, info.getToolTip()));
}
@Override
protected Sdk getProjectJDK() {
return IdeaTestUtil.getMockJdk9();

View File

@@ -16,12 +16,8 @@
package com.intellij.java.codeInsight.daemon.lambda;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.ui.ColorUtil;
import com.intellij.util.ui.UIUtil;
import org.junit.Assert;
public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/highlighting/";
@@ -38,23 +34,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testReassignUsedVars() { doTest(); }
public void testLambdaContext() { doTest(); }
public void testReturnTypeCompatibility() { doTest(); }
public void testTypeObject() {
doTest();
String toolTipForeground = ColorUtil.toHtmlColor(UIUtil.getToolTipForeground());
String greyed = ColorUtil.toHtmlColor(UIUtil.getContextHelpForeground());
String expected = "<html><table>" +
"<tr>" +
"<td style='padding: 0px 16px 8px 4px;color: "+greyed+"'>Required type:</td>" +
"<td style='padding: 0px 4px 8px 0px;'>anonymous <font color=\""+toolTipForeground+"\">Object</font></td></tr>" +
"<tr><td style='padding: 0px 16px 0px 4px;color: "+greyed+"'>Provided:</td><td style='padding: 0px 4px 0px 0px;'><font color=\""+toolTipForeground+"\">Object</font></td></tr>" +
"</table>" +
"</html>";
doHighlighting()
.stream()
.filter(info -> info.type == HighlightInfoType.ERROR)
.forEach(info -> Assert.assertEquals(expected, info.getToolTip()));
}
public void testTypeArgsConsistency() { doTest(); }
public void testTypeArgsConsistencyMisc1() { doTest(); }
public void testTypeArgsConsistencyMisc2() { doTest(); }