mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-imports] IDEA-370756 Optimize Imports adds unused import
GitOrigin-RevId: e14b210b781a3134d03c988d27f7ddb7a5e65f63
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ac7d0aad0a
commit
294d6bb6c9
@@ -683,6 +683,7 @@ public final class ImportUtils {
|
||||
private final @NotNull Set<PsiImportModuleStatement> myModulesStatements = new HashSet<>();
|
||||
private final @NotNull Map<String, PsiImportStatement> myPackageStatements = new HashMap<>();
|
||||
|
||||
private final @NotNull Map<ImplicitCacheItem, Boolean> myCache = new HashMap<>();
|
||||
private ImplicitImportChecker(@NotNull PsiJavaFile file) {
|
||||
for (PsiImportStatementBase anImport : getAllImplicitImports(file)) {
|
||||
if(anImport instanceof PsiImportStaticStatement staticStatement) {
|
||||
@@ -703,12 +704,18 @@ public final class ImportUtils {
|
||||
}
|
||||
}
|
||||
|
||||
record ImplicitCacheItem(String qName, boolean isStatic,
|
||||
@NotNull ImportUtils.OnDemandImportConflict conflicts) { }
|
||||
|
||||
public boolean isImplicitlyImported(String qName, boolean isStatic) {
|
||||
return isImplicitlyImported(qName, isStatic, OnDemandImportConflict.NO_CONFLICTS);
|
||||
}
|
||||
|
||||
public boolean isImplicitlyImported(String qName, boolean isStatic,
|
||||
@NotNull ImportUtils.OnDemandImportConflict conflicts) {
|
||||
ImplicitCacheItem cacheItem = new ImplicitCacheItem(qName, isStatic, conflicts);
|
||||
Boolean result = myCache.get(cacheItem);
|
||||
if (result != null) return result;
|
||||
String packageOrClassName = StringUtil.getPackageName(qName);
|
||||
String className = ClassUtil.extractClassName(qName);
|
||||
if (!isStatic) {
|
||||
@@ -720,24 +727,39 @@ public final class ImportUtils {
|
||||
if (reference == null) continue;
|
||||
PsiElement resolved = reference.resolve();
|
||||
if (resolved instanceof PsiPackage psiPackage) {
|
||||
if (psiPackage.containsClassNamed(className)) return true;
|
||||
if (psiPackage.containsClassNamed(className)) {
|
||||
myCache.put(cacheItem, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!conflicts.hasConflictForOnDemand() && myPackageStatements.containsKey(packageOrClassName)) return true;
|
||||
if (!conflicts.hasConflictForOnDemand() && myPackageStatements.containsKey(packageOrClassName)) {
|
||||
myCache.put(cacheItem, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!conflicts.hasConflictForOnDemand()) {
|
||||
PsiImportStaticStatement psiImportStaticStatement = myStaticImportStatements.get(packageOrClassName);
|
||||
if (psiImportStaticStatement != null) {
|
||||
if (psiImportStaticStatement.isOnDemand()) return true;
|
||||
if (psiImportStaticStatement.isOnDemand()) {
|
||||
myCache.put(cacheItem, true);
|
||||
return true;
|
||||
}
|
||||
PsiJavaCodeReferenceElement reference = psiImportStaticStatement.getImportReference();
|
||||
if (reference == null) return false;
|
||||
if (reference == null) {
|
||||
myCache.put(cacheItem, false);
|
||||
return false;
|
||||
}
|
||||
String qualifiedName = reference.getQualifiedName();
|
||||
return qName.equals(qualifiedName);
|
||||
boolean equals = qName.equals(qualifiedName);
|
||||
myCache.put(cacheItem, equals);
|
||||
return equals;
|
||||
}
|
||||
}
|
||||
}
|
||||
myCache.put(cacheItem, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +128,8 @@ public final class ImportHelper extends ImportHelperBase {
|
||||
moduleStatementMap.keySet());
|
||||
classesToUseSingle.addAll(toReimport);
|
||||
|
||||
deleteOnDemandIfAllIsSingle(classesOrPackagesToImportOnDemand, resultList, classesToUseSingle, checker);
|
||||
|
||||
try {
|
||||
boolean onDemandFirst = mySettings.isLayoutOnDemandImportFromSamePackageFirst();
|
||||
StringBuilder text =
|
||||
@@ -159,6 +161,33 @@ public final class ImportHelper extends ImportHelperBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes on-demand imports from the given map if all corresponding elements are present in the singles set
|
||||
* (individually imported) or implicitly imported.
|
||||
*
|
||||
* @param onDemand a map of package or class names (keys) and boolean values associating them with on-demand imports.
|
||||
* @param allList a list of Import objects representing all current imports in the file.
|
||||
* @param singles a set of individual imports to retain.
|
||||
* @param checker an ImplicitImportChecker used to determine if a name is implicitly imported.
|
||||
*/
|
||||
private static void deleteOnDemandIfAllIsSingle(@NotNull Map<String, Boolean> onDemand,
|
||||
@NotNull List<Import> allList,
|
||||
@NotNull Set<String> singles,
|
||||
@NotNull ImportUtils.ImplicitImportChecker checker) {
|
||||
Set<String> save = new HashSet<>();
|
||||
if (singles.isEmpty()) return;
|
||||
for (Import anImport : allList) {
|
||||
String name = anImport.name();
|
||||
boolean isStatic = anImport.isStatic();
|
||||
String packageOrClassName = StringUtil.getPackageName(name);
|
||||
boolean implicitlyImported = checker.isImplicitlyImported(name, isStatic);
|
||||
if (!singles.contains(name) && !implicitlyImported && onDemand.containsKey(packageOrClassName)) {
|
||||
save.add(packageOrClassName);
|
||||
}
|
||||
}
|
||||
onDemand.keySet().retainAll(save);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the names of classes that are imported by modules specified implicitly in the given Java file and in the import list.
|
||||
*
|
||||
@@ -168,8 +197,8 @@ public final class ImportHelper extends ImportHelperBase {
|
||||
* @return a map of class names and used module imports.
|
||||
*/
|
||||
private static @NotNull Map<String, PsiImportModuleStatement> collectNamesImportedByModules(@NotNull PsiJavaFile file,
|
||||
@NotNull List<PsiImportModuleStatement> statements,
|
||||
@NotNull List<Import> list) {
|
||||
@NotNull List<PsiImportModuleStatement> statements,
|
||||
@NotNull List<Import> list) {
|
||||
List<PsiImportStatementBase> implicitImports = ImportsUtil.getAllImplicitImports(file);
|
||||
List<PsiImportModuleStatement> moduleImports =
|
||||
new ArrayList<>(ContainerUtil.filterIsInstance(implicitImports, PsiImportModuleStatement.class));
|
||||
@@ -986,11 +1015,11 @@ public final class ImportHelper extends ImportHelperBase {
|
||||
}
|
||||
|
||||
private static boolean isOnDemandStaticImported(@NotNull PsiJavaFile file, @NotNull Import anImport) {
|
||||
if(!anImport.isStatic()) return false;
|
||||
if (!anImport.isStatic()) return false;
|
||||
PsiImportList importList = file.getImportList();
|
||||
if(importList==null)return false;
|
||||
if (importList == null) return false;
|
||||
for (PsiImportStaticStatement statement : importList.getImportStaticStatements()) {
|
||||
if(!statement.isOnDemand()) return false;
|
||||
if (!statement.isOnDemand()) return false;
|
||||
String packageName = StringUtil.getPackageName(anImport.name);
|
||||
if (statement.getImportReference() != null &&
|
||||
packageName.equals(statement.getImportReference().getQualifiedName())) {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package p3;
|
||||
|
||||
import p2.*;
|
||||
import p1.List;
|
||||
|
||||
public class A {
|
||||
public static void main(String[] args) {
|
||||
List<Something> frameList = List.of();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package p3;
|
||||
|
||||
import p1.List;
|
||||
import p2.*;
|
||||
|
||||
public class A {
|
||||
public static void main(String[] args) {
|
||||
List<Something> frameList = List.of();
|
||||
}
|
||||
}
|
||||
+4
@@ -15,6 +15,7 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
|
||||
|
||||
public void testLayoutOnDemandImportsFromTheSamePackageFirst() {
|
||||
myFixture.addClass("package a.a; public class A {}");
|
||||
myFixture.addClass("package a.a; public class C {}");
|
||||
myFixture.addClass("package a.b; public class A {}");
|
||||
myFixture.addClass("package a.b; public class B {}");
|
||||
myFixture.addClass("package a.b; public class Boolean {}");
|
||||
@@ -22,12 +23,14 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
|
||||
package a;
|
||||
|
||||
import a.a.A;
|
||||
import a.a.C;
|
||||
import a.b.B;
|
||||
import a.b.Boolean;
|
||||
|
||||
class Main {
|
||||
A a;
|
||||
B b;
|
||||
C c;
|
||||
Boolean bool;
|
||||
}""";
|
||||
myFixture.configureByText(JavaFileType.INSTANCE, code);
|
||||
@@ -48,6 +51,7 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
|
||||
class Main {
|
||||
A a;
|
||||
B b;
|
||||
C c;
|
||||
Boolean bool;
|
||||
}""";
|
||||
myFixture.checkResult(result);
|
||||
|
||||
@@ -63,11 +63,15 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
boolean preserveModuleImports = javaSettings.isPreserveModuleImports();
|
||||
PackageEntryTable table = javaSettings.IMPORT_LAYOUT_TABLE;
|
||||
int classOnDemand = javaSettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND;
|
||||
int NamesOnDemand = javaSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND;
|
||||
Disposer.register(getTestRootDisposable(), new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
javaSettings.setPreserveModuleImports(preserveModuleImports);
|
||||
javaSettings.IMPORT_LAYOUT_TABLE = table;
|
||||
javaSettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = classOnDemand;
|
||||
javaSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = NamesOnDemand;
|
||||
}
|
||||
});
|
||||
myFixture.enableInspections(new UnusedDeclarationInspection());
|
||||
@@ -220,6 +224,17 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void testDontShowOnDemandIfAllSingles() {
|
||||
myFixture.addClass("package p1; public class List<T> {}");
|
||||
myFixture.addClass("package p2; public class List<T> {}");
|
||||
myFixture.addClass("package p2; public class Something {}");
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = 1;
|
||||
javaSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = 1;
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testConflictStaticImport(){
|
||||
myFixture.addClass(
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user