mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 20:39:40 +07:00
global inspections: try to get rid of long read lock (IDEA-226784)
GitOrigin-RevId: ed2c7e44b9f037d892379ab96d4732bedd10f51a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
960cc4c1fe
commit
3f5dd8da98
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.intellij.codeInspection;
|
package com.intellij.codeInspection;
|
||||||
|
|
||||||
|
import com.intellij.analysis.AnalysisScope;
|
||||||
import com.intellij.codeInspection.reference.RefManager;
|
import com.intellij.codeInspection.reference.RefManager;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -27,6 +28,11 @@ public abstract class GlobalJavaBatchInspectionTool extends GlobalInspectionTool
|
|||||||
return queryExternalUsagesRequests(globalContext.getRefManager(), globalContext.getExtension(GlobalJavaInspectionContext.CONTEXT), problemDescriptionsProcessor);
|
return queryExternalUsagesRequests(globalContext.getRefManager(), globalContext.getExtension(GlobalJavaInspectionContext.CONTEXT), problemDescriptionsProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadActionNeeded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean queryExternalUsagesRequests(@NotNull RefManager manager, @NotNull GlobalJavaInspectionContext globalContext, @NotNull ProblemDescriptionsProcessor processor) {
|
protected boolean queryExternalUsagesRequests(@NotNull RefManager manager, @NotNull GlobalJavaInspectionContext globalContext, @NotNull ProblemDescriptionsProcessor processor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,6 +250,11 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadActionNeeded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runInspection(@NotNull final AnalysisScope scope,
|
public void runInspection(@NotNull final AnalysisScope scope,
|
||||||
@NotNull InspectionManager manager,
|
@NotNull InspectionManager manager,
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ public class InconsistentLanguageLevelInspection extends GlobalInspectionTool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadActionNeeded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
|
public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ package com.intellij.codeInspection.unusedLibraries;
|
|||||||
import com.intellij.analysis.AnalysisScope;
|
import com.intellij.analysis.AnalysisScope;
|
||||||
import com.intellij.codeInsight.daemon.GroupNames;
|
import com.intellij.codeInsight.daemon.GroupNames;
|
||||||
import com.intellij.codeInspection.*;
|
import com.intellij.codeInspection.*;
|
||||||
import com.intellij.codeInspection.reference.RefEntity;
|
|
||||||
import com.intellij.codeInspection.reference.RefGraphAnnotator;
|
import com.intellij.codeInspection.reference.RefGraphAnnotator;
|
||||||
import com.intellij.codeInspection.reference.RefManager;
|
import com.intellij.codeInspection.reference.RefManager;
|
||||||
import com.intellij.codeInspection.reference.RefModule;
|
import com.intellij.codeInspection.reference.RefModule;
|
||||||
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.module.Module;
|
import com.intellij.openapi.module.Module;
|
||||||
|
import com.intellij.openapi.module.ModuleManager;
|
||||||
import com.intellij.openapi.module.ModuleUtilCore;
|
import com.intellij.openapi.module.ModuleUtilCore;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.roots.*;
|
import com.intellij.openapi.roots.*;
|
||||||
@@ -71,60 +71,75 @@ public class UnusedLibrariesInspection extends GlobalInspectionTool {
|
|||||||
return new UnusedLibraryGraphAnnotator(refManager);
|
return new UnusedLibraryGraphAnnotator(refManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
|
public boolean isReadActionNeeded() {
|
||||||
@NotNull AnalysisScope scope,
|
return false;
|
||||||
@NotNull InspectionManager manager,
|
}
|
||||||
@NotNull GlobalInspectionContext globalContext,
|
|
||||||
@NotNull ProblemDescriptionsProcessor processor) {
|
|
||||||
if (refEntity instanceof RefModule) {
|
|
||||||
final RefModule refModule = (RefModule)refEntity;
|
|
||||||
final Module module = refModule.getModule();
|
|
||||||
|
|
||||||
VirtualFile[] givenRoots =
|
|
||||||
OrderEnumerator.orderEntries(module).withoutSdk()
|
|
||||||
.withoutModuleSourceEntries()
|
|
||||||
.withoutDepModules()
|
|
||||||
.classes()
|
|
||||||
.getRoots();
|
|
||||||
|
|
||||||
if (givenRoots.length == 0) return null;
|
@Override
|
||||||
|
public void runInspection(@NotNull AnalysisScope scope,
|
||||||
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
@NotNull InspectionManager manager,
|
||||||
final Set<VirtualFile> usedRoots = refModule.getUserData(UnusedLibraryGraphAnnotator.USED_LIBRARY_ROOTS);
|
@NotNull GlobalInspectionContext globalContext,
|
||||||
|
@NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
|
||||||
if (usedRoots != null) {
|
RefManager refManager = globalContext.getRefManager();
|
||||||
appendUsedRootDependencies(usedRoots, givenRoots);
|
for (Module module : ModuleManager.getInstance(globalContext.getProject()).getModules()) {
|
||||||
}
|
if (scope.containsModule(module)) {
|
||||||
|
RefModule refModule = refManager.getRefModule(module);
|
||||||
final List<CommonProblemDescriptor> result = new ArrayList<>();
|
if (refModule != null) {
|
||||||
for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
|
CommonProblemDescriptor[] descriptors = getDescriptors(manager, refModule, module);
|
||||||
if (entry instanceof LibraryOrderEntry &&
|
if (descriptors != null) {
|
||||||
!((LibraryOrderEntry)entry).isExported() &&
|
problemDescriptionsProcessor.addProblemElement(refModule, descriptors);
|
||||||
((LibraryOrderEntry)entry).getScope() != DependencyScope.RUNTIME) {
|
|
||||||
final Set<VirtualFile> files = ContainerUtil.set(((LibraryOrderEntry)entry).getRootFiles(OrderRootType.CLASSES));
|
|
||||||
boolean allRootsUnused = usedRoots == null || !files.removeAll(usedRoots);
|
|
||||||
if (allRootsUnused) {
|
|
||||||
String message = InspectionsBundle.message("unused.library.problem.descriptor", entry.getPresentableName());
|
|
||||||
result.add(manager.createProblemDescriptor(message, module, new RemoveUnusedLibrary(entry.getPresentableName(), null)));
|
|
||||||
}
|
|
||||||
else if (!files.isEmpty() && !IGNORE_LIBRARY_PARTS) {
|
|
||||||
final String unusedLibraryRoots = StringUtil.join(files, file -> file.getPresentableName(), ",");
|
|
||||||
String message =
|
|
||||||
InspectionsBundle.message("unused.library.roots.problem.descriptor", unusedLibraryRoots, entry.getPresentableName());
|
|
||||||
CommonProblemDescriptor descriptor =
|
|
||||||
((LibraryOrderEntry)entry).isModuleLevel()
|
|
||||||
? manager.createProblemDescriptor(message, module, new RemoveUnusedLibrary(entry.getPresentableName(), files))
|
|
||||||
: manager.createProblemDescriptor(message);
|
|
||||||
result.add(descriptor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.isEmpty() ? null : result.toArray(CommonProblemDescriptor.EMPTY_ARRAY);
|
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private CommonProblemDescriptor[] getDescriptors(@NotNull InspectionManager manager,
|
||||||
|
RefModule refModule,
|
||||||
|
Module module) {
|
||||||
|
VirtualFile[] givenRoots =
|
||||||
|
OrderEnumerator.orderEntries(module).withoutSdk()
|
||||||
|
.withoutModuleSourceEntries()
|
||||||
|
.withoutDepModules()
|
||||||
|
.classes()
|
||||||
|
.getRoots();
|
||||||
|
|
||||||
|
if (givenRoots.length == 0) return null;
|
||||||
|
|
||||||
|
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
||||||
|
final Set<VirtualFile> usedRoots = refModule.getUserData(UnusedLibraryGraphAnnotator.USED_LIBRARY_ROOTS);
|
||||||
|
|
||||||
|
if (usedRoots != null) {
|
||||||
|
appendUsedRootDependencies(usedRoots, givenRoots);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<CommonProblemDescriptor> result = new ArrayList<>();
|
||||||
|
for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
|
||||||
|
if (entry instanceof LibraryOrderEntry &&
|
||||||
|
!((LibraryOrderEntry)entry).isExported() &&
|
||||||
|
((LibraryOrderEntry)entry).getScope() != DependencyScope.RUNTIME) {
|
||||||
|
final Set<VirtualFile> files = ContainerUtil.set(((LibraryOrderEntry)entry).getRootFiles(OrderRootType.CLASSES));
|
||||||
|
boolean allRootsUnused = usedRoots == null || !files.removeAll(usedRoots);
|
||||||
|
if (allRootsUnused) {
|
||||||
|
String message = InspectionsBundle.message("unused.library.problem.descriptor", entry.getPresentableName());
|
||||||
|
result.add(manager.createProblemDescriptor(message, module, new RemoveUnusedLibrary(entry.getPresentableName(), null)));
|
||||||
|
}
|
||||||
|
else if (!files.isEmpty() && !IGNORE_LIBRARY_PARTS) {
|
||||||
|
final String unusedLibraryRoots = StringUtil.join(files, file -> file.getPresentableName(), ",");
|
||||||
|
String message =
|
||||||
|
InspectionsBundle.message("unused.library.roots.problem.descriptor", unusedLibraryRoots, entry.getPresentableName());
|
||||||
|
CommonProblemDescriptor descriptor =
|
||||||
|
((LibraryOrderEntry)entry).isModuleLevel()
|
||||||
|
? manager.createProblemDescriptor(message, module, new RemoveUnusedLibrary(entry.getPresentableName(), files))
|
||||||
|
: manager.createProblemDescriptor(message);
|
||||||
|
result.add(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.toArray(CommonProblemDescriptor.EMPTY_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void appendUsedRootDependencies(@NotNull Set<VirtualFile> usedRoots,
|
private static void appendUsedRootDependencies(@NotNull Set<VirtualFile> usedRoots,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.intellij.codeInspection.ex.EntryPointsManager;
|
|||||||
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
|
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
|
||||||
import com.intellij.codeInspection.reference.*;
|
import com.intellij.codeInspection.reference.*;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
|
import com.intellij.openapi.application.ReadAction;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
@@ -501,7 +502,7 @@ public final class VisibilityInspection extends GlobalJavaBatchInspectionTool {
|
|||||||
final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager);
|
final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager);
|
||||||
for (RefElement entryPoint : entryPointsManager.getEntryPoints(manager)) {
|
for (RefElement entryPoint : entryPointsManager.getEntryPoints(manager)) {
|
||||||
//don't ignore entry points with explicit visibility requirements
|
//don't ignore entry points with explicit visibility requirements
|
||||||
if (entryPoint instanceof RefJavaElement && getMinVisibilityLevel((RefJavaElement)entryPoint) > 0) {
|
if (entryPoint instanceof RefJavaElement && ReadAction.compute(() -> getMinVisibilityLevel((RefJavaElement)entryPoint)) > 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ignoreElement(processor, entryPoint);
|
ignoreElement(processor, entryPoint);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package com.intellij.codeInspection;
|
|||||||
import com.intellij.analysis.AnalysisScope;
|
import com.intellij.analysis.AnalysisScope;
|
||||||
import com.intellij.codeInspection.ex.JobDescriptor;
|
import com.intellij.codeInspection.ex.JobDescriptor;
|
||||||
import com.intellij.codeInspection.reference.*;
|
import com.intellij.codeInspection.reference.*;
|
||||||
|
import com.intellij.openapi.application.ReadAction;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.SmartPsiElementPointer;
|
import com.intellij.psi.SmartPsiElementPointer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -136,6 +137,16 @@ public abstract class GlobalInspectionTool extends InspectionProfileEntry {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True by default to ensure third party plugins are not broken
|
||||||
|
*
|
||||||
|
* @return true if inspection should be started ({@link #runInspection(AnalysisScope, InspectionManager, GlobalInspectionContext, ProblemDescriptionsProcessor)}) in ReadAction,
|
||||||
|
* false if ReadAction is taken by inspection itself
|
||||||
|
*/
|
||||||
|
public boolean isReadActionNeeded() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabledByDefault() {
|
public boolean isEnabledByDefault() {
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ public abstract class GlobalSimpleInspectionTool extends GlobalInspectionTool {
|
|||||||
throw new IncorrectOperationException("You must override checkFile() instead");
|
throw new IncorrectOperationException("You must override checkFile() instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadActionNeeded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isGraphNeeded() {
|
public final boolean isGraphNeeded() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -740,14 +740,20 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ApplicationManager.getApplication().runReadAction(() -> {
|
ThrowableRunnable<RuntimeException> runnable = () -> {
|
||||||
tool.runInspection(scopeForState, inspectionManager, this, toolPresentation);
|
tool.runInspection(scopeForState, inspectionManager, this, toolPresentation);
|
||||||
//skip phase when we are sure that scope already contains everything, unused declaration though needs to proceed with its suspicious code
|
//skip phase when we are sure that scope already contains everything, unused declaration though needs to proceed with its suspicious code
|
||||||
if ((canBeExternalUsages || tool.getAdditionalJobs(this) != null) &&
|
if ((canBeExternalUsages || tool.getAdditionalJobs(this) != null) &&
|
||||||
tool.queryExternalUsagesRequests(inspectionManager, this, toolPresentation)) {
|
tool.queryExternalUsagesRequests(inspectionManager, this, toolPresentation)) {
|
||||||
needRepeatSearchRequest.add(toolWrapper);
|
needRepeatSearchRequest.add(toolWrapper);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
if (tool.isReadActionNeeded()) {
|
||||||
|
ReadAction.run(runnable);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ProcessCanceledException | IndexNotReadyException e) {
|
catch (ProcessCanceledException | IndexNotReadyException e) {
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class EmptyDirectoryInspection extends BaseGlobalInspection {
|
|||||||
@NotNull final ProblemDescriptionsProcessor processor) {
|
@NotNull final ProblemDescriptionsProcessor processor) {
|
||||||
final Project project = context.getProject();
|
final Project project = context.getProject();
|
||||||
final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
|
final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
|
||||||
final SearchScope searchScope = scope.toSearchScope();
|
final SearchScope searchScope = ReadAction.compute(() -> scope.toSearchScope());
|
||||||
if (!(searchScope instanceof GlobalSearchScope)) {
|
if (!(searchScope instanceof GlobalSearchScope)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user