diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 956515a11e4d..453593713657 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -540,7 +540,7 @@ public final class AnnotationsHighlightUtil { PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement(); if (nameReferenceElement != null) { PsiElement resolved = nameReferenceElement.resolve(); - if (!(resolved instanceof PsiClass) || !((PsiClass)resolved).isAnnotationType()) { + if (resolved != null && (!(resolved instanceof PsiClass psiClass) || !psiClass.isAnnotationType())) { String description = JavaErrorBundle.message("annotation.annotation.type.expected"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(nameReferenceElement).descriptionAndTooltip(description); } 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 219adcfdb554..ee7cd6ac5562 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 @@ -211,6 +211,10 @@ public final class HighlightUtil { boolean convertible = TypeConversionUtil.areTypesConvertible(operandType, checkType); boolean primitiveInPatternsEnabled = PsiUtil.isAvailable(JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS, expression); if (((operandIsPrimitive || checkIsPrimitive) && !primitiveInPatternsEnabled) || !convertible) { + if (!convertible && IncompleteModelUtil.isIncompleteModel(expression) && + IncompleteModelUtil.isPotentiallyConvertible(checkType, operand)) { + return; + } String message = JavaErrorBundle.message("inconvertible.type.cast", JavaHighlightUtil.formatType(operandType), JavaHighlightUtil .formatType(checkType)); HighlightInfo.Builder info = @@ -328,6 +332,9 @@ public final class HighlightUtil { if (operandType != null && !TypeConversionUtil.areTypesConvertible(operandType, castType, PsiUtil.getLanguageLevel(expression)) && !RedundantCastUtil.isInPolymorphicCall(expression)) { + if (IncompleteModelUtil.isIncompleteModel(expression) && IncompleteModelUtil.isPotentiallyConvertible(castType, operand)) { + return null; + } String message = JavaErrorBundle.message("inconvertible.type.cast", JavaHighlightUtil.formatType(operandType), JavaHighlightUtil .formatType(castType)); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncompleteModelUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncompleteModelUtil.java index d1bdfcd8618b..07d9e085f512 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncompleteModelUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncompleteModelUtil.java @@ -179,6 +179,9 @@ final class IncompleteModelUtil { if (expression instanceof PsiReferenceExpression ref && canBePendingReference(ref)) { return true; } + if (expression instanceof PsiArrayAccessExpression accessExpression) { + return mayHaveUnknownTypeDueToPendingReference(accessExpression.getArrayExpression()); + } return false; } @@ -194,7 +197,7 @@ final class IncompleteModelUtil { if (qualifier == null) { PsiClass psiClass = ClassUtils.getContainingClass(ref); while (psiClass != null) { - if (isHierarchyResolved(psiClass)) return true; + if (!isHierarchyResolved(psiClass)) return true; psiClass = ClassUtils.getContainingClass(psiClass); } boolean call = ref.getParent() instanceof PsiMethodCallExpression; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index c580c1f95364..df70541641e4 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -221,6 +221,9 @@ final class ModuleHighlightUtil { PsiJavaModule target = ref.resolve(); if (target == null) { if (ref.multiResolve(true).length == 0) { + if (IncompleteModelUtil.isIncompleteModel(statement)) { + return IncompleteModelUtil.getPendingReferenceHighlightInfo(refElement); + } String message = JavaErrorBundle.message("module.not.found", refElement.getReferenceText()); return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refElement).descriptionAndTooltip(message); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java index fe6e0904ff0f..52fbd4fba1aa 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java @@ -1,3 +1,8 @@ +import java.util.Map; +import my.unknown.pkg.Anno; +import my.unknown.pkg.MyInterface; +import my.unknown.pkg.Cls; + public class Simple { int test() { test().run(); @@ -37,4 +42,28 @@ public class Simple { method(u, "Hello"); method(u, u); } + + @Anno + void annotated(MapAnno String> map) {} + + void cast(String s, Unknown u) { + Unknown2 u2 = (Unknown)u; + String s2 = (String)u; + } + + void instanceOf(String s, Unknown u) { + if (u instanceof Unknown2) {} + if (u instanceof String) {} + if (s instanceof Unknown) {} + } + + void callOnArray(Unknown u) { + u.foo()[0].blah(); + } + + static class Clss implements MyInterface { + void run() { + foo(bar); + } + } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/module-info.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/module-info.java new file mode 100644 index 000000000000..80527b8d2287 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/module-info.java @@ -0,0 +1,5 @@ +module myModule { + requires my.unknown.mod; + + exports my.unknown.pkg; +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java index 2556da93e663..0b38acef122c 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/incomplete/IncompleteModelHighlightingTest.java @@ -9,9 +9,13 @@ public final class IncompleteModelHighlightingTest extends LightDaemonAnalyzerTe static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/incompleteHighlighting"; private void doTest() { + doTest(getTestName(false) + ".java"); + } + + private void doTest(String fileName) { var ignored = WriteAction.compute(() -> getProject().getService(IncompleteDependenciesService.class).enterIncompleteState()); try { - doTest(BASE_PATH + "/" + getTestName(false) + ".java", true, true); + doTest(BASE_PATH + "/" + fileName, true, true); } finally { WriteAction.run(ignored::close); @@ -19,6 +23,8 @@ public final class IncompleteModelHighlightingTest extends LightDaemonAnalyzerTe } public void testSimple() { doTest(); } + + public void testModuleInfo() { doTest("module-info.java"); } public void testDefaultLoaderFactory() { doTest(); }