[java-import] IJ-CR-163032 IDEA-369199 Preserve module imports even if they are not used

- always highlight unused imports in the hierarchy

GitOrigin-RevId: 26b7fb22931e4b37e45f7c5ee5940d1cfed2a03d
This commit is contained in:
Mikhail Pyltsin
2025-06-04 07:52:20 +02:00
committed by intellij-monorepo-bot
parent dea7732836
commit f79bb18278
8 changed files with 76 additions and 2 deletions

View File

@@ -176,6 +176,12 @@ class UnusedImportsVisitor extends JavaElementVisitor {
return false;
}
}
if (importStatement instanceof PsiImportModuleStatement moduleStatement) {
List<PsiImportModuleStatement> moduleStatements = ImportUtils.optimizeModuleImports(javaFile);
if (!moduleStatements.contains(moduleStatement)) {
return true;
}
}
return isRedundant;
}

View File

@@ -880,10 +880,11 @@ public final class ImportUtils {
Map<PsiImportModuleStatement, PsiJavaModule> modules = new HashMap<>();
Map<PsiJavaModule, Set<PsiJavaModule>> dependencies = new HashMap<>();
Set<PsiImportModuleStatement> toDelete = new HashSet<>();
List<PsiImportModuleStatement> allImports = ContainerUtil.concat(implicit, statements);
for (PsiImportModuleStatement current : statements) {
PsiJavaModule currentModule = modules.computeIfAbsent(current, m -> m.resolveTargetModule());
if (currentModule == null) continue;
for (PsiImportModuleStatement higher : ContainerUtil.concat(implicit, statements)) {
for (PsiImportModuleStatement higher : allImports) {
if(toDelete.contains(higher)) continue;
if (higher == current) continue;
PsiJavaModule higherModule = modules.computeIfAbsent(higher, m -> m.resolveTargetModule());

View File

@@ -0,0 +1,10 @@
<warning descr="Unused import statement">import module my.source.moduleC;</warning>
import module my.source.moduleB;
<warning descr="Unused import statement">import module my.source.moduleD;</warning>
final class Main {
public static void main(String[] args) {
new Sql();
new Transaction();
}
}

View File

@@ -0,0 +1,10 @@
import module my.source.moduleB;
<warning descr="Unused import statement">import module my.source.moduleC;</warning>
<warning descr="Unused import statement">import module my.source.moduleD;</warning>
final class Main {
public static void main(String[] args) {
new Sql();
new Transaction();
}
}

View File

@@ -0,0 +1,8 @@
import module my.source.moduleB;
final class Main {
public static void main(String[] args) {
new Sql();
new Transaction();
}
}

View File

@@ -0,0 +1,8 @@
import module my.source.moduleB;
final class Main {
public static void main(String[] args) {
new Sql();
new Transaction();
}
}

View File

@@ -99,6 +99,38 @@ public class OptimizeImportsWithModulesTest extends LightJava9ModulesCodeInsight
}
public void testHierarchy() {
IdeaTestUtil.withLevel(
getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
JavaCodeStyleSettings.getInstance(getProject()).setDeleteUnusedModuleImports(false);
addCode("my/source/moduleD/Sql.java", """
package my.source.moduleD;
public class Sql {}
""", M5);
addCode("my/source/moduleC/Transaction.java", """
package my.source.moduleC;
public class Transaction {}
""", M4);
doTest();
});
}
public void testHierarchy2() {
IdeaTestUtil.withLevel(
getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
JavaCodeStyleSettings.getInstance(getProject()).setDeleteUnusedModuleImports(false);
addCode("my/source/moduleD/Sql.java", """
package my.source.moduleD;
public class Sql {}
""", M5);
addCode("my/source/moduleC/Transaction.java", """
package my.source.moduleC;
public class Transaction {}
""", M4);
doTest();
});
}
public void testParentNotUsedChildUsed() {
IdeaTestUtil.withLevel(
getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {

View File

@@ -395,7 +395,6 @@ public class ResolveModuleImportTest extends LightJava9ModulesCodeInsightFixture
}
public void testOptimizeImportWithSimilarNames() {
JavaCodeStyleSettings.getInstance(getProject()).setDeleteUnusedModuleImports(false);
addCode("module-info.java", """
module my.source.moduleB {
exports my.source.moduleB;