/* * Copyright 2000-2016 JetBrains s.r.o. * * 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.intellij.codeInspection.ui.actions.suppress; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.GlobalInspectionContextImpl; import com.intellij.codeInspection.ex.InspectionManagerEx; import com.intellij.codeInspection.ex.InspectionToolWrapper; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; import com.intellij.codeInspection.ui.ProblemDescriptionNode; import com.intellij.codeInspection.ui.SuppressableInspectionTreeNode; import com.intellij.openapi.application.ApplicationManager; 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.Pair; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SequentialTask; import com.intellij.util.containers.Queue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; import java.util.Set; /** * @author Dmitry Batkovich */ public class SuppressActionSequentialTask implements SequentialTask { private static final Logger LOG = Logger.getInstance(SuppressActionSequentialTask.class); private SuppressableInspectionTreeNode[] myNodesToSuppress; @NotNull private final SuppressIntentionAction mySuppressAction; @NotNull private final InspectionToolWrapper myWrapper; @NotNull private final GlobalInspectionContextImpl myContext; private int myCount = 0; public SuppressActionSequentialTask(@NotNull SuppressableInspectionTreeNode[] nodesToSuppress, @NotNull SuppressIntentionAction suppressAction, @NotNull InspectionToolWrapper wrapper, @NotNull GlobalInspectionContextImpl context) { myNodesToSuppress = nodesToSuppress; mySuppressAction = suppressAction; myWrapper = wrapper; myContext = context; } @Override public boolean iteration() { final SuppressableInspectionTreeNode node = myNodesToSuppress[myCount++]; final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); if (indicator != null) { indicator.setFraction((double)myCount / myNodesToSuppress.length); } final Pair<PsiElement, CommonProblemDescriptor> content = node.getSuppressContent(); if (content.first != null) { final PsiElement element = content.first; RefEntity refEntity = node.getElement(); LOG.assertTrue(refEntity != null); suppress(element, content.second, mySuppressAction, refEntity, myWrapper, node); } return false; } @Override public boolean isDone() { return myCount > myNodesToSuppress.length - 1; } @Override public void stop() { } @Override public void prepare() { final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); if (indicator != null) { indicator.setText(InspectionsBundle.message("inspection.action.suppress", myWrapper.getDisplayName())); } } private void suppress(@NotNull final PsiElement element, @Nullable final CommonProblemDescriptor descriptor, @NotNull final SuppressIntentionAction action, @NotNull final RefEntity refEntity, InspectionToolWrapper wrapper, @NotNull final SuppressableInspectionTreeNode node) { if (action instanceof SuppressIntentionActionFromFix && !(descriptor instanceof ProblemDescriptor)) { LOG.info("local suppression fix for specific problem descriptor: " + wrapper.getTool().getClass().getName()); } final Project project = element.getProject(); ApplicationManager.getApplication().runWriteAction(() -> { PsiDocumentManager.getInstance(project).commitAllDocuments(); try { PsiElement container = null; if (action instanceof SuppressIntentionActionFromFix) { container = ((SuppressIntentionActionFromFix)action).getContainer(element); } if (container == null) { container = element; } if (action.isAvailable(project, null, element)) { action.invoke(project, null, element); } final Set<GlobalInspectionContextImpl> globalInspectionContexts = ((InspectionManagerEx)InspectionManager.getInstance(element.getProject())).getRunningContexts(); for (GlobalInspectionContextImpl context : globalInspectionContexts) { context.ignoreElement(wrapper.getTool(), container); if (descriptor != null) { context.getPresentation(wrapper).ignoreCurrentElementProblem(refEntity, descriptor); } } final RefElement containerRef = refEntity.getRefManager().getReference(container); final Set<Object> suppressedNodes = myContext.getView().getSuppressedNodes(wrapper.getShortName()); if (containerRef != null) { Queue<RefEntity> toIgnoreInView = new Queue<>(1); toIgnoreInView.addLast(containerRef); while (!toIgnoreInView.isEmpty()) { final RefEntity entity = toIgnoreInView.pullFirst(); if (node instanceof ProblemDescriptionNode) { final CommonProblemDescriptor[] descriptors = myContext.getPresentation(wrapper).getIgnoredElements().get(entity); if (descriptors != null) { Collections.addAll(suppressedNodes, descriptors); } } else { suppressedNodes.add(entity); } final List<RefEntity> children = entity.getChildren(); for (RefEntity child : children) { toIgnoreInView.addLast(child); } } } if (node instanceof ProblemDescriptionNode) { suppressedNodes.add(descriptor); } } catch (IncorrectOperationException e1) { LOG.error(e1); } }); node.removeSuppressActionFromAvailable(mySuppressAction); } }