From 19692be6041c1199217de3f1555955cd52a222ff Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Tue, 10 Dec 2024 10:59:15 +0100 Subject: [PATCH] IJ-CR-151018 [java-inspection] IDEA-363979 Conflicts with on-demand and module imports - introduce enum for conflicts - add annotations - direct implementation isOnDemand for PsiImportModuleStatementImpl GitOrigin-RevId: a116b4952b6498e98740d115cace170512d0d59a --- .../unusedImport/ImportsAreUsedVisitor.java | 6 +- .../ig/imports/JavaLangImportInspection.java | 2 +- .../com/siyeh/ig/psiutils/ImportUtils.java | 101 ++++++++++++------ .../source/PsiImportModuleStatementImpl.java | 5 + 4 files changed, 78 insertions(+), 36 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedImport/ImportsAreUsedVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedImport/ImportsAreUsedVisitor.java index fb40cabfeb72..bccef0028b28 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedImport/ImportsAreUsedVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedImport/ImportsAreUsedVisitor.java @@ -118,7 +118,7 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementWalkingVisitor { if (memberPackageName == null) { return null; } - ImportUtils.OnDemandImportConflicts conflicts = ImportUtils.findOnDemandImportConflict(memberQualifiedName, myFile); + ImportUtils.OnDemandImportConflict conflicts = ImportUtils.findOnDemandImportConflict(memberQualifiedName, myFile); for (PsiImportStatementBase importStatement : importStatements) { if (!importStatement.isOnDemand()) { final PsiJavaCodeReferenceElement reference = importStatement.getImportReference(); @@ -133,12 +133,12 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementWalkingVisitor { } } else { - if (importStatement instanceof PsiImportModuleStatement && conflicts.conflictForModules()) { + if (importStatement instanceof PsiImportModuleStatement && conflicts.hasConflictForModules()) { continue; } if (!(importStatement instanceof PsiImportModuleStatement) && importStatement.isOnDemand() && - conflicts.conflictForOnDemand()) { + conflicts.hasConflictForOnDemand()) { continue; } if (importStatement instanceof PsiImportModuleStatement psiImportModuleStatement && diff --git a/java/java-analysis-impl/src/com/siyeh/ig/imports/JavaLangImportInspection.java b/java/java-analysis-impl/src/com/siyeh/ig/imports/JavaLangImportInspection.java index 4029ba2e7f5a..402cad543aba 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/imports/JavaLangImportInspection.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/imports/JavaLangImportInspection.java @@ -80,7 +80,7 @@ public final class JavaLangImportInspection extends BaseInspection implements Cl if (!HardcodedMethodConstants.JAVA_LANG.equals(parentName)) { return; } - if (ImportUtils.findOnDemandImportConflict(text, statement).conflictForOnDemand()) { + if (ImportUtils.findOnDemandImportConflict(text, statement).hasConflictForOnDemand()) { return; } registerError(statement); diff --git a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ImportUtils.java b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ImportUtils.java index 6323625415d0..e18469be2ce2 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ImportUtils.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ImportUtils.java @@ -71,7 +71,7 @@ public final class ImportUtils { if (containingPackageName.equals(packageName) || importList.findSingleClassImportStatement(qualifiedName) != null) { return; } - OnDemandImportConflicts conflict = null; + OnDemandImportConflict conflict = null; ImplicitImportChecker implicitImportChecker = createImplicitImportChecker(javaFile); if (implicitImportChecker.isImplicitlyImported(qualifiedName, false)) { conflict = findOnDemandImportConflict(qualifiedName, javaFile); @@ -83,14 +83,14 @@ public final class ImportUtils { if (conflict == null) { conflict = findOnDemandImportConflict(qualifiedName, javaFile); } - if (!conflict.conflictForOnDemand()) return; + if (!conflict.hasConflictForOnDemand()) return; } if (ContainerUtil.exists(importList.getImportModuleStatements(), moduleStatement -> moduleStatement.findImportedPackage(packageName) != null)) { if (conflict == null) { conflict = findOnDemandImportConflict(qualifiedName, javaFile); } - if (!conflict.conflictForModules() && !conflict.conflictForOnDemand()) return; + if (conflict== OnDemandImportConflict.NO_CONFLICTS) return; } if (hasExactImportConflict(qualifiedName, javaFile)) { return; @@ -149,7 +149,7 @@ public final class ImportUtils { if (hasExactImportConflict(fqName, file)) { return false; } - if (findOnDemandImportConflict(fqName, file, true, true, true) && + if (hasOnDemandImportConflict(fqName, file, true, true, true) && !isAlreadyImported(file, fqName) ) { return false; @@ -245,15 +245,51 @@ public final class ImportUtils { * Represents the conflicts that can occur with on-demand imports in a Java file. * This record captures whether there is a conflict with on-demand imports involving * class names and module imports. - * The `conflictForOnDemand` indicates if there is a conflict when importing classes - * using on-demand imports, such as `import package.*;`. - * The `conflictForModules` indicates if there is a conflict when considering module-related - * imports. - * - * @param conflictForOnDemand true if there is a conflict with on-demand imports, false otherwise - * @param conflictForModules true if there is a conflict related to modules, false otherwise */ - public record OnDemandImportConflicts(boolean conflictForOnDemand, boolean conflictForModules) {} + public enum OnDemandImportConflict { + NO_CONFLICTS(false, false), + ON_DEMAND_IMPORT_CONFLICTS(true, false), + MODULE_CONFLICTS(false, true), + ON_DEMAND_AND_MODULE_CONFLICT(true, true); + + private final boolean myConflictForOnDemand; + private final boolean myConflictForModules; + + OnDemandImportConflict(boolean conflictForOnDemand, boolean conflictForModules) { + myConflictForOnDemand = conflictForOnDemand; + myConflictForModules = conflictForModules; + } + + /** + * @return true if there is a conflict related to on-demand imports, false otherwise. + */ + public boolean hasConflictForOnDemand() { + return myConflictForOnDemand; + } + + /** + * @return true if there is a conflict related to module imports, false otherwise. + */ + public boolean hasConflictForModules() { + return myConflictForModules; + } + + private static OnDemandImportConflict from(boolean conflictForOnDemand, boolean conflictForModules) { + if (conflictForOnDemand && conflictForModules) { + return ON_DEMAND_AND_MODULE_CONFLICT; + } + else if (conflictForOnDemand) { + return ON_DEMAND_IMPORT_CONFLICTS; + } + else if (conflictForModules) { + return MODULE_CONFLICTS; + } + else { + return NO_CONFLICTS; + } + } + } + /** * Finds conflicts related to on-demand imports in the context of a given fully qualified name. @@ -265,14 +301,15 @@ public final class ImportUtils { * @return an OnDemandImportConflicts object that contains information about whether there are * conflicts for on-demand imports and module imports */ - public static OnDemandImportConflicts findOnDemandImportConflict(@NotNull String fqName, @NotNull PsiElement context) { + @NotNull + public static ImportUtils.OnDemandImportConflict findOnDemandImportConflict(@NotNull String fqName, @NotNull PsiElement context) { if(PsiUtil.isAvailable(JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS, context)) { - boolean onDemandConflict = findOnDemandImportConflict(fqName, context, false, true, false); - boolean moduleConflict = findOnDemandImportConflict(fqName, context, false, false, true); - return new OnDemandImportConflicts(onDemandConflict, moduleConflict); + boolean onDemandConflict = hasOnDemandImportConflict(fqName, context, false, true, false); + boolean moduleConflict = hasOnDemandImportConflict(fqName, context, false, false, true); + return OnDemandImportConflict.from(onDemandConflict, moduleConflict); } - boolean demandImportConflict = findOnDemandImportConflict(fqName, context, false, true, true); - return new OnDemandImportConflicts(demandImportConflict, demandImportConflict) ; + boolean demandImportConflict = hasOnDemandImportConflict(fqName, context, false, true, true); + return OnDemandImportConflict.from(demandImportConflict, demandImportConflict) ; } /** @@ -280,8 +317,8 @@ public final class ImportUtils { */ @Deprecated(forRemoval = true) public static boolean hasOnDemandImportConflict(@NotNull String fqName, @NotNull PsiElement context) { - OnDemandImportConflicts conflict = findOnDemandImportConflict(fqName, context); - return conflict.conflictForOnDemand() || conflict.conflictForModules(); + OnDemandImportConflict conflict = findOnDemandImportConflict(fqName, context); + return conflict != OnDemandImportConflict.NO_CONFLICTS; } /** * @param strict if strict is true this method checks if the conflicting @@ -289,11 +326,11 @@ public final class ImportUtils { * on demand import can be overridden with an exact import for the fqName * without breaking stuff. */ - private static boolean findOnDemandImportConflict(@NotNull String fqName, - @NotNull PsiElement context, - boolean strict, - boolean considerOnDemand, - boolean considerModules) { + private static boolean hasOnDemandImportConflict(@NotNull String fqName, + @NotNull PsiElement context, + boolean strict, + boolean considerOnDemand, + boolean considerModules) { final PsiFile containingFile = context.getContainingFile(); if (!(containingFile instanceof PsiJavaFile javaFile)) { return false; @@ -504,7 +541,7 @@ public final class ImportUtils { final PsiImportStaticStatement onDemandImportStatement = findOnDemandImportStaticStatement(importList, qualifierClass); if (onDemandImportStatement != null && //check only on demands - !findOnDemandImportConflict(qualifierClass + '.' + memberName, javaFile, false, true, false)) { + !hasOnDemandImportConflict(qualifierClass + '.' + memberName, javaFile, false, true, false)) { return true; } final Project project = context.getProject(); @@ -612,7 +649,7 @@ public final class ImportUtils { } final PsiImportStaticStatement onDemandImportStatement = findOnDemandImportStaticStatement(importList, memberClassName); if (onDemandImportStatement != null) { - if (!findOnDemandImportConflict(memberClassName + '.' + memberName, javaFile, false, true, false)) { + if (!hasOnDemandImportConflict(memberClassName + '.' + memberName, javaFile, false, true, false)) { return true; } } @@ -663,15 +700,15 @@ public final class ImportUtils { } public boolean isImplicitlyImported(String qName, boolean isStatic) { - return isImplicitlyImported(qName, isStatic, null); + return isImplicitlyImported(qName, isStatic, OnDemandImportConflict.NO_CONFLICTS); } public boolean isImplicitlyImported(String qName, boolean isStatic, - @Nullable ImportUtils.OnDemandImportConflicts conflicts) { + @NotNull ImportUtils.OnDemandImportConflict conflicts) { String packageOrClassName = StringUtil.getPackageName(qName); String className = ClassUtil.extractClassName(qName); if (!isStatic) { - if(conflicts==null || (!conflicts.conflictForModules() && !conflicts.conflictForOnDemand())){ + if (conflicts == OnDemandImportConflict.NO_CONFLICTS) { for (PsiImportModuleStatement psiImportModuleStatement : myModulesStatements) { PsiPackageAccessibilityStatement importedPackage = psiImportModuleStatement.findImportedPackage(packageOrClassName); if (importedPackage == null) continue; @@ -683,10 +720,10 @@ public final class ImportUtils { } } } - if ((conflicts == null || !conflicts.conflictForOnDemand()) && myPackageStatements.containsKey(packageOrClassName)) return true; + if (!conflicts.hasConflictForOnDemand() && myPackageStatements.containsKey(packageOrClassName)) return true; } else { - if (conflicts == null || !conflicts.conflictForOnDemand()) { + if (!conflicts.hasConflictForOnDemand()) { PsiImportStaticStatement psiImportStaticStatement = myStaticImportStatements.get(packageOrClassName); if (psiImportStaticStatement != null) { if (psiImportStaticStatement.isOnDemand()) return true; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportModuleStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportModuleStatementImpl.java index 94d297003238..f1d7aac1adf0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportModuleStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportModuleStatementImpl.java @@ -118,6 +118,11 @@ public class PsiImportModuleStatementImpl extends PsiImportStatementBaseImpl imp return ref != null ? ref.resolve() : null; } + @Override + public boolean isOnDemand() { + return true; + } + @Override public String toString() { return "PsiImportModuleStatement";