IJ-CR-140943 [java-inspections] IDEA-356672 Support JEP 477. Incorrect intentions and actions with implicit imports

- added javadocs
- rework checking modules

GitOrigin-RevId: 57d41cc28ce57ef7dd59c578217482b75a0a3d11
This commit is contained in:
Mikhail Pyltsin
2024-08-01 12:29:33 +00:00
committed by intellij-monorepo-bot
parent 1c6e73ad39
commit 8e4ac5ef4b
5 changed files with 33 additions and 37 deletions
@@ -21,6 +21,7 @@ import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.PsiJavaModuleModificationTracker;
import com.intellij.psi.impl.java.stubs.index.JavaModuleNameIndex;
import com.intellij.psi.impl.light.LightJavaModule;
@@ -643,22 +644,25 @@ public final class JavaModuleGraphUtil {
}
public static class JavaModuleScope extends GlobalSearchScope {
@NotNull private final Set<PsiJavaModule> myModules;
@NotNull private final MultiMap<String, VirtualFile> myModules;
private final boolean myIncludeLibraries;
private final boolean myIsInTests;
private JavaModuleScope(@NotNull Project project, @NotNull Set<PsiJavaModule> modules) {
super(project);
myModules = modules;
myModules = new MultiMap<>();
for (PsiJavaModule module : modules) {
myModules.putValue(module.getName(), PsiImplUtil.getModuleVirtualFile(module));
}
ProjectFileIndex fileIndex = ProjectFileIndex.getInstance(project);
myIncludeLibraries = ContainerUtil.or(myModules, m -> {
myIncludeLibraries = ContainerUtil.or(modules, m -> {
PsiFile containingFile = m.getContainingFile();
if (containingFile == null) return true;
VirtualFile moduleFile = containingFile.getVirtualFile();
if (moduleFile == null) return true;
return fileIndex.isInLibrary(moduleFile);
});
myIsInTests = !myIncludeLibraries && ContainerUtil.or(myModules, m -> {
myIsInTests = !myIncludeLibraries && ContainerUtil.or(modules, m -> {
PsiFile containingFile = m.getContainingFile();
if (containingFile == null) return true;
VirtualFile moduleFile = containingFile.getVirtualFile();
@@ -669,7 +673,7 @@ public final class JavaModuleGraphUtil {
@Override
public boolean isSearchInModuleContent(@NotNull Module aModule) {
return myModules.contains(findDescriptorByModule(aModule, myIsInTests));
return contains(findDescriptorByModule(aModule, myIsInTests));
}
@Override
@@ -683,9 +687,16 @@ public final class JavaModuleGraphUtil {
if (project == null) return false;
if (!isJvmLanguageFile(file)) return false;
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
if (index.isInLibrary(file)) return myIncludeLibraries && myModules.contains(findDescriptorInLibrary(project, index, file));
if (index.isInLibrary(file)) return myIncludeLibraries && contains(findDescriptorInLibrary(project, index, file));
Module module = index.getModuleForFile(file);
return myModules.contains(findDescriptorByModule(module, myIsInTests));
return contains(findDescriptorByModule(module, myIsInTests));
}
private boolean contains(@Nullable PsiJavaModule module) {
if (module == null || !module.isValid()) return false;
Collection<VirtualFile> myFiles = myModules.get(module.getName());
VirtualFile file = PsiImplUtil.getModuleVirtualFile(module);
return myFiles.contains(file);
}
private static boolean isJvmLanguageFile(@NotNull VirtualFile file) {
@@ -711,9 +722,13 @@ public final class JavaModuleGraphUtil {
return new JavaModuleScope(module.getProject(), Set.of(module));
}
/**
* Creates a JavaModuleScope that includes the given module and all transitive modules.
*
* @param module the base PsiJavaModule for which to create the scope, must not be null
* @return a new JavaModuleScope including all transitive modules of the given module, or null if the moduleFile is null or no transitive modules are found
*/
public static @Nullable JavaModuleScope moduleWithTransitiveScope(@NotNull PsiJavaModule module) {
PsiFile moduleFile = module.getContainingFile();
if (moduleFile == null) return null;
Set<PsiJavaModule> allModules = JavaResolveUtil.getAllTransitiveModulesIncludeCurrent(module);
if (allModules.isEmpty()) return null;
return new JavaModuleScope(module.getProject(), allModules);
@@ -458,7 +458,7 @@ public final class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl impleme
PsiImportModuleStatement[] statements = importList.getImportModuleStatements();
if (statements.length != 1) throw new IncorrectOperationException("Created more than one module with name: " + moduleName);
PsiImportModuleStatement statement = statements[0];
GeneratedMarkerVisitor.markGenerated(statement);
GeneratedMarkerVisitor.markGenerated(statement); //Don't reformat because there is a chance of infinite recursion
return statement;
}
@@ -554,7 +554,7 @@ public final class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl impleme
PsiJavaFile aFile = createDummyJavaFile("import " + aClass.getQualifiedName() + ";");
PsiImportStatementBase statement = extractImport(aFile, false);
GeneratedMarkerVisitor.markGenerated(statement);
GeneratedMarkerVisitor.markGenerated(statement); //Don't reformat because there is a chance of infinite recursion
return (PsiImportStatement)statement;
}
@@ -569,7 +569,7 @@ public final class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl impleme
PsiJavaFile aFile = createDummyJavaFile("import " + packageName + ".*;");
PsiImportStatementBase statement = extractImport(aFile, false);
GeneratedMarkerVisitor.markGenerated(statement);
GeneratedMarkerVisitor.markGenerated(statement); //Don't reformat because there is a chance of infinite recursion
return (PsiImportStatement)statement;
}
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub> implements PsiJavaModule {
private final PsiJavaModuleReferenceElement myReference;
@@ -175,15 +174,4 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub
@NotNull PsiElement place) {
return JavaResolveUtil.processJavaModuleExports(this, processor, state, lastParent, place);
}
public boolean equals(Object o) {
if (!(o instanceof ClsJavaModuleImpl)) return false;
ClsJavaModuleImpl other = (ClsJavaModuleImpl)o;
return getName().equals(other.getName()) &&
Objects.equals(getContainingFile(), other.getContainingFile());
}
public int hashCode() {
return getName().hashCode();
}
}
@@ -23,8 +23,6 @@ import com.intellij.util.containers.JBIterable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import static com.intellij.psi.SyntaxTraverser.psiTraverser;
public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> implements PsiJavaModule {
@@ -180,15 +178,4 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> imp
public String toString() {
return "PsiJavaModule:" + getName();
}
public boolean equals(Object o) {
if (!(o instanceof PsiJavaModuleImpl)) return false;
PsiJavaModuleImpl other = (PsiJavaModuleImpl)o;
return getName().equals(other.getName()) &&
Objects.equals(getContainingFile(), other.getContainingFile());
}
public int hashCode() {
return getName().hashCode();
}
}
@@ -371,6 +371,12 @@ public final class JavaResolveUtil {
return results;
}
/**
* Retrieves all transitive modules required by the given module, including the module itself.
*
* @param module the module for which transitive dependencies are being collected; must not be null
* @return a set of transitive modules required by the given module, including the module itself
*/
public static Set<PsiJavaModule> getAllTransitiveModulesIncludeCurrent(@NotNull PsiJavaModule module){
return CachedValuesManager.getCachedValue(module, ()->{
Project project = module.getProject();