import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInspection.CommonProblemDescriptor;
import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.reference.RefElement;
import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
}
if (!isProblemDescriptorsAcceptable() && tree.getSelectedElements().length > 0 ||
- isProblemDescriptorsAcceptable() && tree.getSelectedDescriptors(false).length > 0) {
+ isProblemDescriptorsAcceptable() && tree.getSelectedDescriptors().length > 0) {
e.getPresentation().setVisible(true);
e.getPresentation().setEnabled(true);
}
public void actionPerformed(final AnActionEvent e) {
final InspectionResultsView view = getInvoker(e);
final InspectionTree tree = view.getTree();
- final CommonProblemDescriptor[] descriptors;
try {
- view.setApplyingFix(true);
- if (isProblemDescriptorsAcceptable() && (descriptors = tree.getSelectedDescriptors(true)).length > 0) {
- doApplyFix(view.getProject(), descriptors, tree.getContext());
+ Ref<CommonProblemDescriptor[]> descriptors = Ref.create();
+ Set<VirtualFile> readOnlyFiles = new THashSet<>();
+ if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> ReadAction.run(() -> {
+ final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+ indicator.setText("Checking problem descriptors...");
+ descriptors.set(tree.getSelectedDescriptors(true, readOnlyFiles));
+ }), InspectionsBundle.message("preparing.for.apply.fix"), true, e.getProject())) {
+ return;
+ }
+ if (isProblemDescriptorsAcceptable() && descriptors.get().length > 0) {
+ doApplyFix(view.getProject(), descriptors.get(), readOnlyFiles, tree.getContext());
} else {
doApplyFix(getSelectedElements(e), view);
}
private void doApplyFix(@NotNull final Project project,
@NotNull final CommonProblemDescriptor[] descriptors,
+ @NotNull Set<VirtualFile> readOnlyFiles,
@NotNull final GlobalInspectionContextImpl context) {
- final Set<VirtualFile> readOnlyFiles = new THashSet<VirtualFile>();
- for (CommonProblemDescriptor descriptor : descriptors) {
- final PsiElement psiElement = descriptor instanceof ProblemDescriptor ? ((ProblemDescriptor)descriptor).getPsiElement() : null;
- if (psiElement != null && !psiElement.isWritable()) {
- readOnlyFiles.add(psiElement.getContainingFile().getVirtualFile());
- }
- }
-
if (!FileModificationService.getInstance().prepareVirtualFilesForWrite(project, readOnlyFiles)) return;
final RefManagerImpl refManager = (RefManagerImpl)context.getRefManager();
-
final boolean initial = refManager.isInProcess();
refManager.inspectionReadActionFinished();
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.reference.RefEntity;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionsConfigTreeComparator;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.treeStructure.Tree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
public class InspectionTree extends Tree {
+ private static final Logger LOG = Logger.getInstance(InspectionTree.class);
private static final Comparator<CommonProblemDescriptor> DESCRIPTOR_COMPARATOR = (c1, c2) -> {
if (c1 instanceof ProblemDescriptor && c2 instanceof ProblemDescriptor) {
return PsiUtilCore.compareElementsByPosition(((ProblemDescriptor)c2).getPsiElement(),
}
}
- public CommonProblemDescriptor[] getSelectedDescriptors(boolean sortedByPosition) {
+ public CommonProblemDescriptor[] getSelectedDescriptors() {
+ return getSelectedDescriptors(false, null);
+ }
+
+ public CommonProblemDescriptor[] getSelectedDescriptors(boolean sortedByPosition, @Nullable Set<VirtualFile> readOnlyFilesSink) {
final TreePath[] paths = getSelectionPaths();
if (paths == null) return CommonProblemDescriptor.EMPTY_ARRAY;
final TreePath[] selectionPaths = TreeUtil.selectMaximals(paths);
final LinkedHashSet<CommonProblemDescriptor> descriptors = new LinkedHashSet<CommonProblemDescriptor>();
- MultiMap<Object, CommonProblemDescriptor> parentToChildNode = new MultiMap<>();
+ MultiMap<Object, ProblemDescriptionNode> parentToChildNode = new MultiMap<>();
final List<InspectionTreeNode> nonDescriptorNodes = new SmartList<>();
for (TreePath path : selectionPaths) {
final Object[] pathAsArray = path.getPath();
final Object node = pathAsArray[length - 1];
if (node instanceof ProblemDescriptionNode) {
if (isNodeValidAndIncluded((ProblemDescriptionNode)node)) {
- final CommonProblemDescriptor descriptor = ((ProblemDescriptionNode)node).getDescriptor();
if (length >= 2) {
- parentToChildNode.putValue(pathAsArray[length - 2], descriptor);
+ parentToChildNode.putValue(pathAsArray[length - 2], (ProblemDescriptionNode)node);
} else {
- parentToChildNode.putValue(node, descriptor);
+ parentToChildNode.putValue(node, (ProblemDescriptionNode)node);
}
}
} else {
}
for (InspectionTreeNode node : nonDescriptorNodes) {
- processChildDescriptorsDeep(node, descriptors, sortedByPosition);
+ processChildDescriptorsDeep(node, descriptors, sortedByPosition, readOnlyFilesSink);
}
- for (Map.Entry<Object, Collection<CommonProblemDescriptor>> entry : parentToChildNode.entrySet()) {
- final Collection<CommonProblemDescriptor> siblings = entry.getValue();
+ for (Map.Entry<Object, Collection<ProblemDescriptionNode>> entry : parentToChildNode.entrySet()) {
+ final Collection<ProblemDescriptionNode> siblings = entry.getValue();
if (siblings.size() == 1) {
- @SuppressWarnings("ConstantConditions")
- final CommonProblemDescriptor descriptor = ContainerUtil.getFirstItem(siblings);
+ final ProblemDescriptionNode descriptorNode = ContainerUtil.getFirstItem(siblings);
+ LOG.assertTrue(descriptorNode != null);
+ CommonProblemDescriptor descriptor = descriptorNode.getDescriptor();
if (descriptor != null) {
descriptors.add(descriptor);
+ if (readOnlyFilesSink != null) {
+ checkDescriptorFileIsWritable(descriptor, readOnlyFilesSink);
+ }
}
} else {
+ Stream<CommonProblemDescriptor> descriptorStream = siblings.stream().map(ProblemDescriptionNode::getDescriptor);
if (sortedByPosition) {
- siblings.stream().sorted(DESCRIPTOR_COMPARATOR).forEach(descriptors::add);
- } else {
- descriptors.addAll(siblings);
+ descriptorStream = descriptorStream.sorted(DESCRIPTOR_COMPARATOR);
+ }
+ descriptorStream = descriptorStream.filter(descriptors::add);
+ if (readOnlyFilesSink != null) {
+ checkDescriptorsFileIsWritable(descriptorStream.collect(Collectors.toList()), readOnlyFilesSink);
}
}
}
private void processChildDescriptorsDeep(InspectionTreeNode node,
LinkedHashSet<CommonProblemDescriptor> descriptors,
- boolean sortedByPosition) {
+ boolean sortedByPosition,
+ @Nullable Set<VirtualFile> readOnlyFilesSink) {
List<CommonProblemDescriptor> descriptorChildren = null;
for (int i = 0; i < node.getChildCount(); i++) {
final TreeNode child = node.getChildAt(i);
}
}
else {
- processChildDescriptorsDeep((InspectionTreeNode)child, descriptors, sortedByPosition);
+ processChildDescriptorsDeep((InspectionTreeNode)child, descriptors, sortedByPosition, readOnlyFilesSink);
}
}
if (descriptorChildren.size() > 1) {
Collections.sort(descriptorChildren, DESCRIPTOR_COMPARATOR);
}
+ if (readOnlyFilesSink != null) {
+ checkDescriptorsFileIsWritable(descriptorChildren, readOnlyFilesSink);
+ }
+
descriptors.addAll(descriptorChildren);
}
}
public GlobalInspectionContextImpl getContext() {
return myContext;
}
+
+ private static void checkDescriptorsFileIsWritable(@NotNull Collection<CommonProblemDescriptor> descriptors, @NotNull Set<VirtualFile> readOnlySink) {
+ for (CommonProblemDescriptor descriptor : descriptors) {
+ if (checkDescriptorFileIsWritable(descriptor, readOnlySink)) {
+ return;
+ }
+ }
+ }
+
+ private static boolean checkDescriptorFileIsWritable(@NotNull CommonProblemDescriptor descriptor, @NotNull Set<VirtualFile> readOnlySink) {
+ if (descriptor instanceof ProblemDescriptor) {
+ PsiElement psiElement = ((ProblemDescriptor)descriptor).getPsiElement();
+ if (psiElement != null && !psiElement.isWritable()) {
+ readOnlySink.add(psiElement.getContainingFile().getVirtualFile());
+ return true;
+ }
+ }
+ return false;
+ }
}