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 b45b27d5a80b..fc0e15cb00e3 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 @@ -187,6 +187,35 @@ final class IncompleteModelUtil { return false; } + /** + * @param ref unresolved reference to find potential imports for + * @return list of import statements that potentially import the given unresolved reference + */ + static List getPotentialImports(@NotNull PsiJavaCodeReferenceElement ref) { + if (ref.getParent() instanceof PsiImportStatementBase) return List.of(); + boolean call = ref.getParent() instanceof PsiMethodCallExpression; + if (!(ref.getContainingFile() instanceof PsiJavaFile file)) return List.of(); + PsiImportList list = file.getImportList(); + List imports = new ArrayList<>(); + if (list != null) { + for (PsiImportStatementBase statement : list.getAllImportStatements()) { + if (statement instanceof PsiImportStaticStatement staticImport && staticImport.resolveTargetClass() != null) continue; + if (!statement.isOnDemand()) { + PsiJavaCodeReferenceElement reference = statement.getImportReference(); + if (reference == null) continue; + String name = reference.getReferenceName(); + if (name == null || !name.equals(ref.getReferenceName())) continue; + if (reference.resolve() != null) continue; + } + // Unqualified method call cannot be imported using non-static import + if (statement instanceof PsiImportStaticStatement || !call) { + imports.add(statement); + } + } + } + return imports; + } + /** * @param ref reference to check * @return true if the reference can be pending. A pending reference is an unresolved reference that can be potentially resolved @@ -202,24 +231,7 @@ final class IncompleteModelUtil { if (!isHierarchyResolved(psiClass)) return true; psiClass = ClassUtils.getContainingClass(psiClass); } - boolean call = ref.getParent() instanceof PsiMethodCallExpression; - PsiImportList list = ((PsiJavaFile)ref.getContainingFile()).getImportList(); - if (list != null) { - for (PsiImportStatementBase statement : list.getAllImportStatements()) { - if (statement instanceof PsiImportStaticStatement staticImport && staticImport.resolveTargetClass() != null) continue; - if (!statement.isOnDemand()) { - PsiJavaCodeReferenceElement reference = statement.getImportReference(); - if (reference == null) continue; - String name = reference.getReferenceName(); - if (name == null || !name.equals(ref.getReferenceName())) continue; - } - // Unqualified method call cannot be imported using non-static import - if (statement instanceof PsiImportStaticStatement || !call) { - return true; - } - } - } - return false; + return !getPotentialImports(ref).isEmpty(); } if (qualifier instanceof PsiReferenceExpression qualifierRef) { PsiElement qualifierTarget = qualifierRef.resolve(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LocalRefUseInfo.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LocalRefUseInfo.java index 1136dc3c69b5..078e9a6e6eb8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LocalRefUseInfo.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LocalRefUseInfo.java @@ -360,10 +360,17 @@ public final class LocalRefUseInfo { registerImportStatement(ref, importStatement); } else if (refElement == null && ref instanceof PsiJavaReference javaReference) { - for (JavaResolveResult result : javaReference.multiResolve(true)) { - if (result.getCurrentFileResolveScope() instanceof PsiImportStatementBase importStatement) { - registerImportStatement(ref, importStatement); - break; + JavaResolveResult[] results = javaReference.multiResolve(true); + if (results.length > 0) { + for (JavaResolveResult result : results) { + if (result.getCurrentFileResolveScope() instanceof PsiImportStatementBase importStatement) { + registerImportStatement(ref, importStatement); + break; + } + } + } else if (ref instanceof PsiJavaCodeReferenceElement javaRef) { + for (PsiImportStatementBase potentialImport : IncompleteModelUtil.getPotentialImports(javaRef)) { + registerImportStatement(ref, potentialImport); } } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/DefaultLoaderFactory.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/DefaultLoaderFactory.java index a7db0c285865..b58e103c53c4 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/DefaultLoaderFactory.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/DefaultLoaderFactory.java @@ -5,6 +5,7 @@ import com.< import java.util.HashMap; import java.util.Map; +import java.util.TreeMap; public class DefaultLoaderFactory implements ReportLoaderFactory { public static final String GROOVY_DATA_LOADER = "groovy"; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java index 52fbd4fba1aa..15eae549b517 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/incompleteHighlighting/Simple.java @@ -1,4 +1,5 @@ import java.util.Map; +import java.io.IOException; import my.unknown.pkg.Anno; import my.unknown.pkg.MyInterface; import my.unknown.pkg.Cls; @@ -37,6 +38,10 @@ public class Simple { void method(String s, Object obj) {} + private void methodThrows() throws IOException { + System.out.println(); + } + void methodCall(Unknown u) { method("Hello", u); method(u, "Hello"); 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 2a36a14093ee..7644b6aaf9ca 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 @@ -2,6 +2,8 @@ package com.intellij.java.codeInsight.daemon.incomplete; import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; +import com.intellij.codeInspection.unneededThrows.RedundantThrowsDeclarationLocalInspection; +import com.intellij.codeInspection.unusedImport.UnusedImportInspection; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.project.IncompleteDependenciesService; @@ -15,6 +17,7 @@ public final class IncompleteModelHighlightingTest extends LightDaemonAnalyzerTe } private void doTest(String fileName) { + enableInspectionTools(new UnusedImportInspection(), new RedundantThrowsDeclarationLocalInspection()); IncompleteDependenciesService service = getProject().getService(IncompleteDependenciesService.class); try (var ignored = asAutoCloseable(WriteAction.compute(() -> service.enterIncompleteState()))) { doTest(BASE_PATH + "/" + fileName, true, true);