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 65c2c546b0a0..66c4b23e1ba8 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
@@ -102,6 +102,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";
static {
ourClassIncompatibleModifiers.put(PsiModifier.ABSTRACT, Set.of(PsiModifier.FINAL));
@@ -509,7 +510,7 @@ public final class HighlightUtil {
}
return null;
}
-
+
static HighlightInfo.Builder checkVarTypeApplicability(@NotNull PsiVariable variable) {
if (variable instanceof PsiLocalVariable && variable.getTypeElement().isInferredType()) {
PsiElement parent = variable.getParent();
@@ -837,7 +838,7 @@ public final class HighlightUtil {
static HighlightInfo.Builder checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull LanguageLevel languageLevel) {
if ("_".equals(identifier.getText())) {
PsiElement parent = identifier.getParent();
- if (languageLevel.isAtLeast(LanguageLevel.JDK_1_9) && !(parent instanceof PsiUnnamedPattern) &&
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_9) && !(parent instanceof PsiUnnamedPattern) &&
!(parent instanceof PsiVariable var && var.isUnnamed())) {
String text = HighlightingFeature.UNNAMED_PATTERNS_AND_VARIABLES.isSufficient(languageLevel) ?
JavaErrorBundle.message("underscore.identifier.error.unnamed")
@@ -1140,8 +1141,8 @@ public final class HighlightUtil {
else {
if (PsiModifier.STATIC.equals(modifier) || privateOrProtected || PsiModifier.PACKAGE_LOCAL.equals(modifier)) {
isAllowed = modifierOwnerParent instanceof PsiClass &&
- (PsiModifier.STATIC.equals(modifier) ||
- PsiUtil.isLanguageLevel16OrHigher(modifierOwnerParent) ||
+ (PsiModifier.STATIC.equals(modifier) ||
+ PsiUtil.isLanguageLevel16OrHigher(modifierOwnerParent) ||
((PsiClass)modifierOwnerParent).getQualifiedName() != null) ||
FileTypeUtils.isInServerPageFile(modifierOwnerParent) ||
// non-physical dummy holder might not have FQN
@@ -1161,7 +1162,7 @@ public final class HighlightUtil {
isAllowed &= !PsiModifier.ABSTRACT.equals(modifier);
}
- if (aClass.getContainingClass() instanceof PsiAnonymousClass &&
+ if (aClass.getContainingClass() instanceof PsiAnonymousClass &&
privateOrProtected && !PsiUtil.isLanguageLevel16OrHigher(modifierOwnerParent)) {
isAllowed = false;
}
@@ -1809,8 +1810,8 @@ public final class HighlightUtil {
String message = JavaErrorBundle.message("exception.already.caught.warn", formatTypes(caughtCopy), caughtCopy.size());
HighlightInfo.Builder builder =
HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(catchSection).descriptionAndTooltip(message);
- IntentionAction action = isMultiCatch ?
- getFixFactory().createDeleteMultiCatchFix(catchTypeElement) :
+ IntentionAction action = isMultiCatch ?
+ getFixFactory().createDeleteMultiCatchFix(catchTypeElement) :
getFixFactory().createDeleteCatchFix(parameter);
builder.registerFix(action, null, null, null, null);
errorSink.accept(builder);
@@ -3172,19 +3173,26 @@ public final class HighlightUtil {
@NotNull TextRange textRange,
int navigationShift,
@NotNull String reason) {
- lType = PsiUtil.convertAnonymousToBaseType(lType);
- rType = rType == null ? null : PsiUtil.convertAnonymousToBaseType(rType);
+ PsiType baseLType = PsiUtil.convertAnonymousToBaseType(lType);
+ PsiType baseRType = rType == null ? null : PsiUtil.convertAnonymousToBaseType(rType);
String styledReason = reason.isEmpty() ? ""
: String
.format("
", reason);
- String toolTip = createIncompatibleTypesTooltip(lType, rType,
- (lRawType, lTypeArguments, rRawType, rTypeArguments) ->
- JavaErrorBundle
- .message("incompatible.types.html.tooltip", lRawType, lTypeArguments, rRawType,
+ 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())));
+ "#" + ColorUtil.toHex(UIUtil.getContextHelpForeground()));
+ });
+
+ 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", JavaHighlightUtil.formatType(lType), JavaHighlightUtil.formatType(rType));
+ "incompatible.types", result.lRawType(), result.rRawType());
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(textRange)
.description(description)
@@ -3192,6 +3200,38 @@ public final class HighlightUtil {
.navigationShift(navigationShift);
}
+ /**
+ * 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
+ */
+ @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;
+ }
+ }
+ return new PairTypeResult(lRawType, rRawType);
+ }
+
+ private record PairTypeResult(@NotNull String lRawType, @NotNull String rRawType) {
+ }
+
public static HighlightInfo.Builder checkArrayType(PsiTypeElement type) {
int dimensions = 0;
for (PsiElement child = type.getFirstChild(); child != null; child = child.getNextSibling()) {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeObject.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeObject.java
new file mode 100644
index 000000000000..f025784df631
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeObject.java
@@ -0,0 +1,6 @@
+class TypeObject {
+ void test() {
+ var x = new Object() {};
+ x = new Object();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaHighlightingTest.java
index 71290e64b55c..0644be49a047 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaHighlightingTest.java
@@ -16,8 +16,12 @@
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/";
@@ -34,6 +38,23 @@ 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 = "" +
+ "" +
+ "| Required type: | " +
+ "anonymous Object |
" +
+ "| Provided: | Object |
" +
+ "
" +
+ "";
+
+ 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(); }