mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
[java-inspection] IDEA-363979 Conflicts with on-demand and module imports
(cherry picked from commit 0857df90e3f9cc450b48b56186573a9a89b5b041) GitOrigin-RevId: 8e1474a59c687561ba5f00a13fecd4d2a9057b7a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6113015d06
commit
3348e7291f
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection.unusedImport;
|
||||
|
||||
import com.intellij.psi.PsiImportModuleStatement;
|
||||
import com.intellij.psi.PsiImportStatementBase;
|
||||
import com.siyeh.ig.psiutils.PsiElementOrderComparator;
|
||||
|
||||
@@ -20,11 +21,19 @@ final class ImportStatementComparator implements Comparator<PsiImportStatementBa
|
||||
|
||||
@Override
|
||||
public int compare(PsiImportStatementBase importStatementBase1, PsiImportStatementBase importStatementBase2) {
|
||||
final boolean onDemand = importStatementBase1.isOnDemand();
|
||||
if (onDemand != importStatementBase2.isOnDemand()) {
|
||||
return onDemand ? -1 : 1;
|
||||
final boolean onDemand1 = importStatementBase1.isOnDemand();
|
||||
final boolean onDemand2 = importStatementBase2.isOnDemand();
|
||||
if (onDemand1 != onDemand2) {
|
||||
return onDemand1 ? -1 : 1;
|
||||
}
|
||||
// just sort on demand imports first, and sort the rest in reverse file order.
|
||||
if (onDemand1) {
|
||||
boolean isModule1 = importStatementBase1 instanceof PsiImportModuleStatement;
|
||||
boolean isModule2 = importStatementBase2 instanceof PsiImportModuleStatement;
|
||||
if (isModule1 != isModule2) {
|
||||
return isModule1 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
// just sort on module import first, then on demand imports, and sort the rest in reverse file order.
|
||||
return -PsiElementOrderComparator.getInstance().compare(importStatementBase1, importStatementBase2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
if (memberPackageName == null) {
|
||||
return null;
|
||||
}
|
||||
final boolean hasOnDemandImportConflict = ImportUtils.hasOnDemandImportConflict(memberQualifiedName, myFile);
|
||||
ImportUtils.OnDemandImportConflicts conflicts = ImportUtils.findOnDemandImportConflict(memberQualifiedName, myFile);
|
||||
for (PsiImportStatementBase importStatement : importStatements) {
|
||||
if (!importStatement.isOnDemand()) {
|
||||
final PsiJavaCodeReferenceElement reference = importStatement.getImportReference();
|
||||
@@ -133,7 +133,12 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hasOnDemandImportConflict) {
|
||||
if (importStatement instanceof PsiImportModuleStatement && conflicts.conflictForModules()) {
|
||||
continue;
|
||||
}
|
||||
if (!(importStatement instanceof PsiImportModuleStatement) &&
|
||||
importStatement.isOnDemand() &&
|
||||
conflicts.conflictForOnDemand()) {
|
||||
continue;
|
||||
}
|
||||
if (importStatement instanceof PsiImportModuleStatement psiImportModuleStatement &&
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.siyeh.HardcodedMethodConstants;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.fixes.DeleteImportFix;
|
||||
import com.siyeh.ig.psiutils.ImportUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -81,7 +80,7 @@ public final class JavaLangImportInspection extends BaseInspection implements Cl
|
||||
if (!HardcodedMethodConstants.JAVA_LANG.equals(parentName)) {
|
||||
return;
|
||||
}
|
||||
if (ImportUtils.hasOnDemandImportConflict(text, statement)) {
|
||||
if (ImportUtils.findOnDemandImportConflict(text, statement).conflictForOnDemand()) {
|
||||
return;
|
||||
}
|
||||
registerError(statement);
|
||||
|
||||
@@ -20,16 +20,20 @@ import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaFileCodeStyleFacade;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.*;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -67,12 +71,26 @@ public final class ImportUtils {
|
||||
if (containingPackageName.equals(packageName) || importList.findSingleClassImportStatement(qualifiedName) != null) {
|
||||
return;
|
||||
}
|
||||
if ((createImplicitImportChecker(javaFile).isImplicitlyImported(qualifiedName, false) ||
|
||||
importList.findOnDemandImportStatement(packageName) != null ||
|
||||
ContainerUtil.exists(importList.getImportModuleStatements(),
|
||||
moduleStatement -> moduleStatement.findImportedPackage(packageName) != null))
|
||||
&& !hasOnDemandImportConflict(qualifiedName, javaFile)) {
|
||||
return;
|
||||
OnDemandImportConflicts conflict = null;
|
||||
ImplicitImportChecker implicitImportChecker = createImplicitImportChecker(javaFile);
|
||||
if (implicitImportChecker.isImplicitlyImported(qualifiedName, false)) {
|
||||
conflict = findOnDemandImportConflict(qualifiedName, javaFile);
|
||||
if (implicitImportChecker.isImplicitlyImported(qualifiedName, false, conflict)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (importList.findOnDemandImportStatement(packageName) != null) {
|
||||
if (conflict == null) {
|
||||
conflict = findOnDemandImportConflict(qualifiedName, javaFile);
|
||||
}
|
||||
if (!conflict.conflictForOnDemand()) 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 (hasExactImportConflict(qualifiedName, javaFile)) {
|
||||
return;
|
||||
@@ -131,7 +149,8 @@ public final class ImportUtils {
|
||||
if (hasExactImportConflict(fqName, file)) {
|
||||
return false;
|
||||
}
|
||||
if (hasOnDemandImportConflict(fqName, file, true) && !isAlreadyImported(file, fqName)
|
||||
if (findOnDemandImportConflict(fqName, file, true, true, true) &&
|
||||
!isAlreadyImported(file, fqName)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -222,17 +241,59 @@ public final class ImportUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasOnDemandImportConflict(@NotNull String fqName, @NotNull PsiElement context) {
|
||||
return hasOnDemandImportConflict(fqName, context, false);
|
||||
/**
|
||||
* 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) {}
|
||||
|
||||
/**
|
||||
* Finds conflicts related to on-demand imports in the context of a given fully qualified name.
|
||||
* This method checks for potential conflicts with existing imports in the specified context,
|
||||
* considering both class-level on-demand imports and module-related imports.
|
||||
*
|
||||
* @param fqName the fully qualified name of the class or package to check for import conflicts
|
||||
* @param context the PSI element representing the context within which to check for import conflicts
|
||||
* @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) {
|
||||
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 demandImportConflict = findOnDemandImportConflict(fqName, context, false, true, true);
|
||||
return new OnDemandImportConflicts(demandImportConflict, demandImportConflict) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ImportUtils#findOnDemandImportConflict(String, PsiElement)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static boolean hasOnDemandImportConflict(@NotNull String fqName, @NotNull PsiElement context) {
|
||||
OnDemandImportConflicts conflict = findOnDemandImportConflict(fqName, context);
|
||||
return conflict.conflictForOnDemand() || conflict.conflictForModules();
|
||||
}
|
||||
/**
|
||||
* @param strict if strict is true this method checks if the conflicting
|
||||
* class which is imported is actually used in the file. If it isn't the
|
||||
* on demand import can be overridden with an exact import for the fqName
|
||||
* without breaking stuff.
|
||||
*/
|
||||
private static boolean hasOnDemandImportConflict(@NotNull String fqName, @NotNull PsiElement context, boolean strict) {
|
||||
private static boolean findOnDemandImportConflict(@NotNull String fqName,
|
||||
@NotNull PsiElement context,
|
||||
boolean strict,
|
||||
boolean considerOnDemand,
|
||||
boolean considerModules) {
|
||||
final PsiFile containingFile = context.getContainingFile();
|
||||
if (!(containingFile instanceof PsiJavaFile javaFile)) {
|
||||
return false;
|
||||
@@ -243,9 +304,9 @@ public final class ImportUtils {
|
||||
}
|
||||
final List<PsiImportStatementBase> importStatements =
|
||||
ContainerUtil.append(getAllImplicitImports(javaFile), imports.getAllImportStatements());
|
||||
ThreeState state = hasOnDemandImportConflictWithImports(javaFile, importStatements, fqName, strict);
|
||||
ThreeState state = hasOnDemandImportConflictWithImports(javaFile, importStatements, fqName, strict, considerOnDemand, considerModules);
|
||||
if (state != ThreeState.UNSURE) return state.toBoolean();
|
||||
return hasDefaultImportConflict(fqName, javaFile);
|
||||
return considerOnDemand && hasDefaultImportConflict(fqName, javaFile);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,25 +316,31 @@ public final class ImportUtils {
|
||||
* @param javaFile the Java file to check for import conflicts.
|
||||
* @param importStatements the list of import statements to check against.
|
||||
* @param fqName the fully qualified name to check for conflicts.
|
||||
* @param checkOnDemand check conflicts for all on-demand statements, excluding module import statements.
|
||||
* @param checkModules check conflicts for module imports.
|
||||
* @return true if there is an on-demand import conflict, false otherwise.
|
||||
*/
|
||||
public static boolean hasOnDemandImportConflictWithImports(@NotNull PsiJavaFile javaFile,
|
||||
@NotNull List<? extends PsiImportStatementBase> importStatements,
|
||||
@NotNull String fqName) {
|
||||
return hasOnDemandImportConflictWithImports(javaFile, importStatements, fqName, false) == ThreeState.YES;
|
||||
@NotNull String fqName,
|
||||
boolean checkOnDemand,
|
||||
boolean checkModules) {
|
||||
return hasOnDemandImportConflictWithImports(javaFile, importStatements, fqName, false, checkOnDemand, checkModules) == ThreeState.YES;
|
||||
}
|
||||
|
||||
private static ThreeState hasOnDemandImportConflictWithImports(@NotNull PsiJavaFile javaFile,
|
||||
@NotNull List<? extends PsiImportStatementBase> importStatements,
|
||||
@NotNull String fqName,
|
||||
boolean strict) {
|
||||
boolean strict,
|
||||
boolean checkOnDemand,
|
||||
boolean checkModules) {
|
||||
final String shortName = ClassUtil.extractClassName(fqName);
|
||||
final String packageName = ClassUtil.extractPackageName(fqName);
|
||||
for (final PsiImportStatementBase importStatement : importStatements) {
|
||||
if (!importStatement.isOnDemand()) {
|
||||
continue;
|
||||
}
|
||||
if (importStatement instanceof PsiImportModuleStatement moduleStatement) {
|
||||
if (checkModules && importStatement instanceof PsiImportModuleStatement moduleStatement) {
|
||||
//can't process, let's assume that we have conflict because it is safe
|
||||
if (DumbService.isDumb(javaFile.getProject())) return ThreeState.YES;
|
||||
Ref<Boolean> result = new Ref<>(null);
|
||||
@@ -303,6 +370,7 @@ public final class ImportUtils {
|
||||
}, scope, null);
|
||||
if (result.get() != null) return ThreeState.fromBoolean(result.get());
|
||||
}
|
||||
if (!checkOnDemand) continue;
|
||||
final PsiJavaCodeReferenceElement importReference = importStatement.getImportReference();
|
||||
if (importReference == null) {
|
||||
continue;
|
||||
@@ -434,7 +502,9 @@ public final class ImportUtils {
|
||||
return false;
|
||||
}
|
||||
final PsiImportStaticStatement onDemandImportStatement = findOnDemandImportStaticStatement(importList, qualifierClass);
|
||||
if (onDemandImportStatement != null && !hasOnDemandImportConflict(qualifierClass + '.' + memberName, javaFile)) {
|
||||
if (onDemandImportStatement != null &&
|
||||
//check only on demands
|
||||
!findOnDemandImportConflict(qualifierClass + '.' + memberName, javaFile, false, true, false)) {
|
||||
return true;
|
||||
}
|
||||
final Project project = context.getProject();
|
||||
@@ -542,7 +612,7 @@ public final class ImportUtils {
|
||||
}
|
||||
final PsiImportStaticStatement onDemandImportStatement = findOnDemandImportStaticStatement(importList, memberClassName);
|
||||
if (onDemandImportStatement != null) {
|
||||
if (!hasOnDemandImportConflict(memberClassName + '.' + memberName, javaFile)) {
|
||||
if (!findOnDemandImportConflict(memberClassName + '.' + memberName, javaFile, false, true, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -593,29 +663,38 @@ public final class ImportUtils {
|
||||
}
|
||||
|
||||
public boolean isImplicitlyImported(String qName, boolean isStatic) {
|
||||
return isImplicitlyImported(qName, isStatic, null);
|
||||
}
|
||||
|
||||
public boolean isImplicitlyImported(String qName, boolean isStatic,
|
||||
@Nullable ImportUtils.OnDemandImportConflicts conflicts) {
|
||||
String packageOrClassName = StringUtil.getPackageName(qName);
|
||||
String className = ClassUtil.extractClassName(qName);
|
||||
if (!isStatic) {
|
||||
for (PsiImportModuleStatement psiImportModuleStatement : myModulesStatements) {
|
||||
PsiPackageAccessibilityStatement importedPackage = psiImportModuleStatement.findImportedPackage(packageOrClassName);
|
||||
if (importedPackage == null) continue;
|
||||
PsiJavaCodeReferenceElement reference = importedPackage.getPackageReference();
|
||||
if (reference == null) continue;
|
||||
PsiElement resolved = reference.resolve();
|
||||
if (resolved instanceof PsiPackage psiPackage) {
|
||||
if (psiPackage.containsClassNamed(className)) return true;
|
||||
if(conflicts==null || (!conflicts.conflictForModules() && !conflicts.conflictForOnDemand())){
|
||||
for (PsiImportModuleStatement psiImportModuleStatement : myModulesStatements) {
|
||||
PsiPackageAccessibilityStatement importedPackage = psiImportModuleStatement.findImportedPackage(packageOrClassName);
|
||||
if (importedPackage == null) continue;
|
||||
PsiJavaCodeReferenceElement reference = importedPackage.getPackageReference();
|
||||
if (reference == null) continue;
|
||||
PsiElement resolved = reference.resolve();
|
||||
if (resolved instanceof PsiPackage psiPackage) {
|
||||
if (psiPackage.containsClassNamed(className)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myPackageStatements.containsKey(packageOrClassName)) return true;
|
||||
if ((conflicts == null || !conflicts.conflictForOnDemand()) && myPackageStatements.containsKey(packageOrClassName)) return true;
|
||||
}
|
||||
else {
|
||||
PsiImportStaticStatement psiImportStaticStatement = myStaticImportStatements.get(packageOrClassName);
|
||||
if (psiImportStaticStatement != null) {
|
||||
if (psiImportStaticStatement.isOnDemand()) return true;
|
||||
PsiJavaCodeReferenceElement reference = psiImportStaticStatement.getImportReference();
|
||||
if (reference == null) return false;
|
||||
String qualifiedName = reference.getQualifiedName();
|
||||
return qName.equals(qualifiedName);
|
||||
if (conflicts == null || !conflicts.conflictForOnDemand()) {
|
||||
PsiImportStaticStatement psiImportStaticStatement = myStaticImportStatements.get(packageOrClassName);
|
||||
if (psiImportStaticStatement != null) {
|
||||
if (psiImportStaticStatement.isOnDemand()) return true;
|
||||
PsiJavaCodeReferenceElement reference = psiImportStaticStatement.getImportReference();
|
||||
if (reference == null) return false;
|
||||
String qualifiedName = reference.getQualifiedName();
|
||||
return qName.equals(qualifiedName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -203,7 +203,7 @@ public abstract class ImportClassFixBase<T extends PsiElement, R extends PsiRefe
|
||||
classList = new ArrayList<>(filtered);
|
||||
}
|
||||
|
||||
filerByPackageName(classList, psiFile);
|
||||
filterByPackageName(classList, psiFile);
|
||||
|
||||
filterAlreadyImportedButUnresolved(classList, psiFile);
|
||||
|
||||
@@ -232,7 +232,7 @@ public abstract class ImportClassFixBase<T extends PsiElement, R extends PsiRefe
|
||||
return false;
|
||||
}
|
||||
|
||||
private void filerByPackageName(@NotNull Collection<PsiClass> classList, @NotNull PsiFile file) {
|
||||
private void filterByPackageName(@NotNull Collection<PsiClass> classList, @NotNull PsiFile file) {
|
||||
String qualifiedName = getQualifiedName(myReferenceElement);
|
||||
String packageName = StringUtil.getPackageName(qualifiedName);
|
||||
if (!packageName.isEmpty() &&
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.Predicates;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
|
||||
@@ -341,7 +342,7 @@ public final class ImportHelper {
|
||||
if (implicitModuleImports.isEmpty() && conflicts.isEmpty()) return Collections.emptySet();
|
||||
|
||||
Set<String> result = new HashSet<>();
|
||||
String packageName = file.getPackageName();
|
||||
String filePackageName = file.getPackageName();
|
||||
ImportUtils.ImplicitImportChecker checker = ImportUtils.createImplicitImportChecker(file);
|
||||
for (PsiClass aClass : file.getClasses()) {
|
||||
// do not visit imports
|
||||
@@ -354,20 +355,30 @@ public final class ImportHelper {
|
||||
if (!(resolveResult.getElement() instanceof PsiClass psiClass)) return;
|
||||
String qualifiedName = psiClass.getQualifiedName();
|
||||
if (qualifiedName == null) return;
|
||||
String referencePackageName = StringUtil.getPackageName(qualifiedName);
|
||||
String referenceShortName = StringUtil.getShortName(qualifiedName);
|
||||
//conflict with packages
|
||||
boolean hasConflict = conflicts.contains(psiClass.getName());
|
||||
if (!hasConflict) {
|
||||
//conflict with implicit module imports
|
||||
hasConflict = !implicitModuleImports.isEmpty() &&
|
||||
ImportUtils.hasOnDemandImportConflictWithImports(file, implicitModuleImports, qualifiedName);
|
||||
|
||||
//check conflict only with implicit module imports
|
||||
//explicit module imports should be checked separately, right now it is not supported
|
||||
//if it is already imported by on demands, there is no conflict with modules
|
||||
if (!(PsiUtil.isAvailable(JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS, file) &&
|
||||
classNames.getOrDefault(referencePackageName, Collections.emptySet()).contains(referenceShortName))) {
|
||||
hasConflict = !implicitModuleImports.isEmpty() &&
|
||||
ImportUtils.hasOnDemandImportConflictWithImports(file, implicitModuleImports, qualifiedName, false, true);
|
||||
}
|
||||
}
|
||||
if (!hasConflict) return;
|
||||
//can be visible by inheritance
|
||||
if (!(resolveResult.getCurrentFileResolveScope() instanceof PsiImportStatementBase) &&
|
||||
!isImplicitlyImported(psiClass, checker)) {
|
||||
return;
|
||||
}
|
||||
//in the same package or in the same class
|
||||
if (PsiTreeUtil.isAncestor(file, psiClass, true) ||
|
||||
packageName.equals(StringUtil.getPackageName(qualifiedName))) {
|
||||
filePackageName.equals(referencePackageName)) {
|
||||
return;
|
||||
}
|
||||
result.add(qualifiedName);
|
||||
@@ -455,6 +466,8 @@ public final class ImportHelper {
|
||||
|
||||
boolean useOnDemand = !packageName.isEmpty();
|
||||
|
||||
//right now supports import on demand only for packages
|
||||
//it doesn't support add imports on module
|
||||
if (hasImportOnDemand(file, packageName)) {
|
||||
useOnDemand = false;
|
||||
}
|
||||
@@ -606,12 +619,12 @@ public final class ImportHelper {
|
||||
if (importedPackages.contains(packageNameToReimport)) {
|
||||
hasConflict = true;
|
||||
}
|
||||
else {
|
||||
for (PsiImportModuleStatement module : importedModules) {
|
||||
if (module.findImportedPackage(packageNameToReimport) != null) {
|
||||
hasConflict = true;
|
||||
break;
|
||||
}
|
||||
//shouldn't filter for demand over module, because it is necessary to check,
|
||||
//that class which is imported by module will not be shadowed by new on-demand package import
|
||||
for (PsiImportModuleStatement module : importedModules) {
|
||||
if (module.findImportedPackage(packageNameToReimport) != null) {
|
||||
hasConflict = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasConflict) {
|
||||
@@ -906,7 +919,7 @@ public final class ImportHelper {
|
||||
@NotNull String thisPackageName,
|
||||
@Nullable PsiFile context) {
|
||||
if (scope instanceof PsiImportList) return;
|
||||
ImportUtils.ImplicitImportChecker checker =
|
||||
ImportUtils.ImplicitImportChecker checker =
|
||||
scope.getContainingFile() instanceof PsiJavaFile javaFile ? ImportUtils.createImplicitImportChecker(javaFile) : null;
|
||||
|
||||
Queue<PsiElement> queue = new ArrayDeque<>();
|
||||
@@ -952,6 +965,7 @@ public final class ImportHelper {
|
||||
|
||||
PsiElement currentFileResolveScope = resolveResult.getCurrentFileResolveScope();
|
||||
if (!(currentFileResolveScope instanceof PsiImportStatementBase) && refElement != null) {
|
||||
//imported not with imports (implicit or explicit)
|
||||
if (!(refElement instanceof PsiClass psiClass && checker != null && isImplicitlyImported(psiClass, checker))) {
|
||||
continue;
|
||||
}
|
||||
@@ -1075,7 +1089,7 @@ public final class ImportHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* An imported element, e.g. a fully qualified class name.
|
||||
* An imported element, e.g. a fully qualified class name.
|
||||
* This is an implementation detail, unfortunately public because of JavaFX, don't expose it in public API.
|
||||
*
|
||||
* @param name the fully qualified name of the element that should be imported.
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2017 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ipp.fqnames;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.codeInsight.javadoc.JavaDocUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.psiutils.ImportUtils;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class FullyQualifiedNamePredicate implements PsiElementPredicate {
|
||||
|
||||
@Override
|
||||
public boolean satisfiedBy(PsiElement element) {
|
||||
if (!(element instanceof PsiJavaCodeReferenceElement referenceElement)) {
|
||||
return false;
|
||||
}
|
||||
if (!referenceElement.isQualified()) {
|
||||
return false;
|
||||
}
|
||||
final PsiElement parent = referenceElement.getParent();
|
||||
if (parent instanceof PsiMethodCallExpression || parent instanceof PsiAssignmentExpression || parent instanceof PsiVariable) {
|
||||
return false;
|
||||
}
|
||||
if (PsiTreeUtil.getParentOfType(element, PsiImportStatementBase.class, PsiPackageStatement.class, JavaCodeFragment.class) != null) {
|
||||
return false;
|
||||
}
|
||||
final CodeStyleSettings codeStyleSettings = CodeStyle.getSettings(element.getContainingFile());
|
||||
if (isInsideCommentInPackageInfo(referenceElement)) {
|
||||
return false;
|
||||
}
|
||||
final PsiFile file = element.getContainingFile();
|
||||
if ("module-info.java".equals(file.getName())) {
|
||||
return false;
|
||||
}
|
||||
final PsiElement qualifier = referenceElement.getQualifier();
|
||||
if (!(qualifier instanceof PsiJavaCodeReferenceElement qualifierReferenceElement)) {
|
||||
return false;
|
||||
}
|
||||
final PsiElement resolved = qualifierReferenceElement.resolve();
|
||||
if (!(resolved instanceof PsiPackage)) {
|
||||
if (!(resolved instanceof PsiClass)) {
|
||||
return false;
|
||||
}
|
||||
if (!codeStyleSettings.getCustomSettings(JavaCodeStyleSettings.class).INSERT_INNER_CLASS_IMPORTS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final PsiElement target = referenceElement.resolve();
|
||||
if (!(target instanceof PsiClass aClass)) {
|
||||
return false;
|
||||
}
|
||||
final String fqName = aClass.getQualifiedName();
|
||||
return fqName != null && ImportUtils.nameCanBeImported(fqName, element);
|
||||
}
|
||||
|
||||
private static boolean isInsideCommentInPackageInfo(@Nullable PsiJavaCodeReferenceElement referenceElement) {
|
||||
final PsiDocComment containingComment = PsiTreeUtil.getParentOfType(referenceElement, PsiDocComment.class);
|
||||
return JavaDocUtil.isInsidePackageInfo(containingComment);
|
||||
}
|
||||
}
|
||||
@@ -59,11 +59,10 @@ public abstract class JavaImportStatementElementType extends JavaStubElementType
|
||||
type == JavaElementType.MODULE_REFERENCE) {
|
||||
refText = JavaSourceUtil.getReferenceText(tree, child);
|
||||
}
|
||||
else if (type == JavaTokenType.DOT) {
|
||||
else if (type == JavaTokenType.DOT || type == JavaTokenType.MODULE_KEYWORD) {
|
||||
isOnDemand = true;
|
||||
}
|
||||
}
|
||||
|
||||
byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT,
|
||||
node.getTokenType() == JavaElementType.IMPORT_MODULE_STATEMENT);
|
||||
return new PsiImportStatementStubImpl(parentStub, refText, flags);
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> {
|
||||
public static final int STUB_VERSION = 60;
|
||||
public static final int STUB_VERSION = 61;
|
||||
|
||||
private static volatile int TEST_STUB_VERSION_MODIFIER = 0;
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>a.java</file>
|
||||
<line>1</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused import</problem_class>
|
||||
<description>Unused import <code>import java.util.*;</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Main.java</file>
|
||||
<line>2</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused import</problem_class>
|
||||
<description>Unused import <code>import java.util.*;/**/</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -4,6 +4,6 @@
|
||||
<file>Main.java</file>
|
||||
<line>1</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused import</problem_class>
|
||||
<description>Unused import <code>import module java.base;</code> #loc</description>
|
||||
<description>Unused import <code>import module java.base;/**/</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Main.java</file>
|
||||
<line>2</line>
|
||||
<problem_class id="UNUSED_IMPORT" severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused import</problem_class>
|
||||
<description>Unused import <code>import java.util.List;</code> #loc</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>Main.java</file>
|
||||
<line>3</line>
|
||||
<problem_class id="UNUSED_IMPORT" severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused import</problem_class>
|
||||
<description>Unused import <code>import java.util.ArrayList;</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,20 @@
|
||||
package p2;
|
||||
|
||||
import p1.A1;
|
||||
import p1.A2;
|
||||
import p1.A3;
|
||||
import p1.A4;
|
||||
import p1.A5;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package p2;
|
||||
|
||||
import p1.A1;
|
||||
import p1.A2;
|
||||
import p1.A3;
|
||||
import p1.A4;
|
||||
import p1.A5;
|
||||
import p1.List;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package p2;
|
||||
|
||||
import p1.*;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package p2;
|
||||
|
||||
import p1.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package p2;
|
||||
|
||||
import static p1.A1.foo1;
|
||||
import static p1.A1.foo2;
|
||||
import static p1.A1.foo3;
|
||||
import static p1.A1.foo4;
|
||||
import static p1.A1.foo5;
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
foo1();
|
||||
foo2();
|
||||
foo3();
|
||||
foo4();
|
||||
foo5();
|
||||
print("");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package p2;
|
||||
|
||||
import static java.io.IO.print;
|
||||
import static p1.A1.*;
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
foo1();
|
||||
foo2();
|
||||
foo3();
|
||||
foo4();
|
||||
foo5();
|
||||
print("");
|
||||
}
|
||||
|
||||
@@ -841,9 +841,7 @@ public class AddImportActionTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
}
|
||||
}
|
||||
""");
|
||||
myFixture.enableInspections(new UnnecessaryFullyQualifiedNameInspection());
|
||||
myFixture.launchAction(myFixture.findSingleIntention("Remove unnecessary qualification"));
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
removeUnnecessaryQualification();
|
||||
myFixture.checkResult("""
|
||||
|
||||
class Test {
|
||||
@@ -857,6 +855,12 @@ public class AddImportActionTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
""");
|
||||
}
|
||||
|
||||
private void removeUnnecessaryQualification() {
|
||||
myFixture.enableInspections(new UnnecessaryFullyQualifiedNameInspection());
|
||||
myFixture.launchAction(myFixture.findSingleIntention("Remove unnecessary qualification"));
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
}
|
||||
|
||||
public void testDoNotAllowToAddImportInPackageInfoFile() {
|
||||
myFixture.configureByText("package-info.java", """
|
||||
|
||||
@@ -1097,4 +1101,264 @@ public class AddImportActionTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
assertTrue(myFixture.filterAvailableIntentions("Import class").isEmpty());
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportClassUnnecessaryQualifier() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.addClass("package a; public class List {}");
|
||||
|
||||
myFixture.configureByText("Test.java", """
|
||||
import a.*;
|
||||
import module java.base;
|
||||
class Test{
|
||||
void main(){
|
||||
java.util.L<caret>ist x;
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
reimportClass();
|
||||
myFixture.checkResult("""
|
||||
import a.*;
|
||||
import module java.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class Test{
|
||||
void main(){
|
||||
List x;
|
||||
}
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportClassUnnecessaryQualifierAlreadyUsed() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.addClass("package a; public class List {}");
|
||||
|
||||
myFixture.configureByText("Test.java", """
|
||||
import a.*;
|
||||
import module java.base;
|
||||
class Test{
|
||||
void main(){
|
||||
java.util.L<caret>ist x;
|
||||
List y;
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
myFixture.enableInspections(new UnnecessaryFullyQualifiedNameInspection());
|
||||
assertTrue(myFixture.filterAvailableIntentions("Replace qualified name with import").isEmpty());
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportClassUnnecessaryQualifierImportFromDemand() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.addClass("package a; public class List {}");
|
||||
|
||||
myFixture.configureByText("Test.java", """
|
||||
import a.*;
|
||||
import module java.base;
|
||||
class Test{
|
||||
void main(){
|
||||
a.L<caret>ist x;
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
removeUnnecessaryQualification();
|
||||
myFixture.checkResult("""
|
||||
import a.*;
|
||||
import module java.base;
|
||||
class Test{
|
||||
void main(){
|
||||
List x;
|
||||
}
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportUnnecessaryQualifierAlreadyImported() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.configureByText("Test.java", """
|
||||
import module java.base;
|
||||
class Test{
|
||||
void main(){
|
||||
java.util.L<caret>ist x;
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
removeUnnecessaryQualification();
|
||||
myFixture.checkResult("""
|
||||
import module java.base;
|
||||
class Test{
|
||||
void main(){
|
||||
List x;
|
||||
}
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
public void testImplicitClassUnnecessaryQualifier() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.addClass("package a; public class List {}");
|
||||
|
||||
myFixture.configureByText("Test.java", """
|
||||
import a.*;
|
||||
|
||||
void main(){
|
||||
java.util.L<caret>ist x;
|
||||
}
|
||||
""");
|
||||
|
||||
reimportClass();
|
||||
myFixture.checkResult("""
|
||||
import a.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
void main(){
|
||||
List x;
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
public void testImplicitClassUnnecessaryQualifierAlreadyImported() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
|
||||
myFixture.configureByText("Test.java", """
|
||||
void main(){
|
||||
java.util.L<caret>ist x;
|
||||
}
|
||||
""");
|
||||
|
||||
removeUnnecessaryQualification();
|
||||
myFixture.checkResult("""
|
||||
void main(){
|
||||
List x;
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportFoldingWithConflictsToJavaBaseModuleImplicitClassDemandsOverModule() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.addClass("package p1; public class List {}");
|
||||
myFixture.addClass("package p1; public class A1 {}");
|
||||
myFixture.addClass("package p1; public class A2 {}");
|
||||
myFixture.addClass("package p1; public class A3 {}");
|
||||
myFixture.addClass("package p1; public class A4 {}");
|
||||
myFixture.addClass("package p1; public class A5 {}");
|
||||
|
||||
myFixture.configureByText("C.java",
|
||||
"""
|
||||
|
||||
import module java.base;
|
||||
import p1.A1;
|
||||
import p1.A2;
|
||||
import p1.A3;
|
||||
import p1.A4;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A<caret>5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main(){
|
||||
}
|
||||
""");
|
||||
importClass();
|
||||
|
||||
myFixture.checkResult(
|
||||
"""
|
||||
|
||||
import module java.base;
|
||||
import p1.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main(){
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportFoldingWithConflictsToJavaBaseModuleImplicitClassFromPackageDemandsOverModule() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.addClass("package p1; public class List {}");
|
||||
myFixture.addClass("package p1; public class A1 {}");
|
||||
myFixture.addClass("package p1; public class A2 {}");
|
||||
myFixture.addClass("package p1; public class A3 {}");
|
||||
myFixture.addClass("package p1; public class A4 {}");
|
||||
myFixture.addClass("package p1; public class A5 {}");
|
||||
|
||||
myFixture.configureByText("C.java",
|
||||
"""
|
||||
|
||||
import module java.base;
|
||||
import p1.A1;
|
||||
import p1.A2;
|
||||
import p1.A3;
|
||||
import p1.A4;
|
||||
import p1.List;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A<caret>5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main(){
|
||||
}
|
||||
""");
|
||||
importClass();
|
||||
|
||||
myFixture.checkResult(
|
||||
"""
|
||||
|
||||
import module java.base;
|
||||
import p1.*;
|
||||
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
A3 a3;
|
||||
A4 a4;
|
||||
A5 a5;
|
||||
|
||||
List myName;
|
||||
|
||||
void main(){
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,30 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testConflictModuleImportImplicitClassDemandOverModule() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
myFixture.addClass("package p1; public class List {}");
|
||||
myFixture.addClass("package p1; public class A1 {}");
|
||||
myFixture.addClass("package p1; public class A2 {}");
|
||||
myFixture.addClass("package p1; public class A3 {}");
|
||||
myFixture.addClass("package p1; public class A4 {}");
|
||||
myFixture.addClass("package p1; public class A5 {}");
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
public void testConflictModuleImportImplicitClassDemandOverModule2() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
myFixture.addClass("package p1; public class List {}");
|
||||
myFixture.addClass("package p1; public class A1 {}");
|
||||
myFixture.addClass("package p1; public class A2 {}");
|
||||
myFixture.addClass("package p1; public class A3 {}");
|
||||
myFixture.addClass("package p1; public class A4 {}");
|
||||
myFixture.addClass("package p1; public class A5 {}");
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
public void testConflictStaticImport(){
|
||||
myFixture.addClass(
|
||||
"""
|
||||
@@ -206,6 +230,34 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testConflictStaticImportWithImplicitClassDemandOverModule() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
|
||||
myFixture.addClass(
|
||||
"""
|
||||
package p1;
|
||||
public class A1 {
|
||||
public static void print(Object obj) {}
|
||||
public static void foo() {}
|
||||
public static void foo1() {}
|
||||
public static void foo2() {}
|
||||
public static void foo3() {}
|
||||
public static void foo4() {}
|
||||
public static void foo5() {}
|
||||
}
|
||||
""");
|
||||
myFixture.addClass("""
|
||||
package java.io;
|
||||
|
||||
public final class IO {
|
||||
public static void print(Object obj) {}
|
||||
}
|
||||
""");
|
||||
doTest();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void testConflictStaticImportWithImplicitClass(){
|
||||
myFixture.addClass(
|
||||
"""
|
||||
|
||||
@@ -29,9 +29,9 @@ public class JavaLangImportInspectionTest extends LightJavaInspectionTestCase {
|
||||
"class String {}");
|
||||
doTest("package a;" +
|
||||
"import java.lang.String;" +
|
||||
"class X {{" +
|
||||
"class X {" +
|
||||
" String s;" +
|
||||
"}}");
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testSimple() {
|
||||
@@ -42,6 +42,20 @@ public class JavaLangImportInspectionTest extends LightJavaInspectionTestCase {
|
||||
"}}");
|
||||
}
|
||||
|
||||
public void testPackageOnDemandConflict() {
|
||||
myFixture.addClass("""
|
||||
package b;
|
||||
class String {
|
||||
}""");
|
||||
doTest("""
|
||||
package a;
|
||||
import java.lang.String;
|
||||
import b.*;
|
||||
class X {
|
||||
String s;
|
||||
}""");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
|
||||
@@ -300,11 +300,11 @@ public class UnusedImportGlobalInspectionTest extends LightJavaCodeInsightFixtur
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRedundantModuleImport() {
|
||||
public void testSingleImportWithModuleImport() {
|
||||
doTest("""
|
||||
/*Unused import 'import module java.base;'*/import module java.base;/**/
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import module java.base;
|
||||
/*Unused import 'import java.util.List;'*/import java.util.List;/**/
|
||||
/*Unused import 'import java.util.ArrayList;'*/import java.util.ArrayList;/**/
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) {
|
||||
@@ -339,6 +339,58 @@ public class UnusedImportGlobalInspectionTest extends LightJavaCodeInsightFixtur
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportModuleWithRedundantPackage() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(),
|
||||
() -> {
|
||||
doTest("""
|
||||
import module java.base;
|
||||
/*Unused import 'import java.util.*;'*/import java.util.*;/**/
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) {
|
||||
List<String> a = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportImplicitModuleWithRedundantPackage() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(),
|
||||
() -> {
|
||||
doTest("""
|
||||
/*Unused import 'import java.util.*;'*/import java.util.*;/**/
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<String> a = new ArrayList<>();
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void testRedundantImportModuleWithNotRedundantPackage() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(),
|
||||
() -> {
|
||||
myFixture.addClass("""
|
||||
package a.b;
|
||||
|
||||
public final class List {
|
||||
}
|
||||
""");
|
||||
doTest("""
|
||||
/*Unused import 'import module java.base;'*/import module java.base;/**/
|
||||
import a.b.*;
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) {
|
||||
List a;
|
||||
}
|
||||
}
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
private void doTest(String classText) {
|
||||
myFixture.addClass(classText);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user