2 * Copyright 2000-2013 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.codeInspection.actions;
19 import com.intellij.codeInsight.FileModificationService;
20 import com.intellij.codeInsight.hint.HintManager;
21 import com.intellij.codeInsight.intention.EmptyIntentionAction;
22 import com.intellij.codeInsight.intention.HighPriorityAction;
23 import com.intellij.codeInsight.intention.IntentionAction;
24 import com.intellij.codeInspection.*;
25 import com.intellij.codeInspection.ex.InspectionToolWrapper;
26 import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
27 import com.intellij.codeInspection.ex.PerformFixesModalTask;
28 import com.intellij.openapi.command.CommandProcessor;
29 import com.intellij.openapi.editor.Editor;
30 import com.intellij.openapi.progress.EmptyProgressIndicator;
31 import com.intellij.openapi.progress.ProgressManager;
32 import com.intellij.openapi.project.Project;
33 import com.intellij.openapi.util.Computable;
34 import com.intellij.psi.PsiElement;
35 import com.intellij.psi.PsiFile;
36 import com.intellij.util.IncorrectOperationException;
37 import com.intellij.util.SequentialModalProgressTask;
38 import org.jetbrains.annotations.NotNull;
40 import java.util.Collections;
41 import java.util.Comparator;
42 import java.util.List;
48 public class CleanupInspectionIntention implements IntentionAction, HighPriorityAction {
49 private final InspectionToolWrapper myToolWrapper;
50 private final Class myQuickfixClass;
51 private final String myText;
53 public CleanupInspectionIntention(@NotNull InspectionToolWrapper toolWrapper, @NotNull Class quickFixClass, String text) {
54 myToolWrapper = toolWrapper;
55 myQuickfixClass = quickFixClass;
61 public String getText() {
62 return InspectionsBundle.message("fix.all.inspection.problems.in.file", myToolWrapper.getDisplayName());
67 public String getFamilyName() {
72 public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
73 if (!FileModificationService.getInstance().preparePsiElementForWrite(file)) return;
74 final List<ProblemDescriptor> descriptions =
75 ProgressManager.getInstance().runProcess(new Computable<List<ProblemDescriptor>>() {
77 public List<ProblemDescriptor> compute() {
78 InspectionManager inspectionManager = InspectionManager.getInstance(project);
79 return InspectionEngine.runInspectionOnFile(file, myToolWrapper, inspectionManager.createNewGlobalContext(false));
81 }, new EmptyProgressIndicator());
83 Collections.sort(descriptions, new Comparator<CommonProblemDescriptor>() {
85 public int compare(final CommonProblemDescriptor o1, final CommonProblemDescriptor o2) {
86 final ProblemDescriptorBase d1 = (ProblemDescriptorBase)o1;
87 final ProblemDescriptorBase d2 = (ProblemDescriptorBase)o2;
88 return d2.getTextRange().getStartOffset() - d1.getTextRange().getStartOffset();
92 final String templatePresentationText = "Apply Fixes";
93 final SequentialModalProgressTask progressTask =
94 new SequentialModalProgressTask(project, templatePresentationText, true);
95 final PerformFixesTask fixesTask = new PerformFixesTask(project, descriptions.toArray(new CommonProblemDescriptor[descriptions.size()]), progressTask);
96 CommandProcessor.getInstance().executeCommand(project, new Runnable() {
99 CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
100 progressTask.setMinIterationTime(200);
101 progressTask.setTask(fixesTask);
102 ProgressManager.getInstance().run(progressTask);
104 }, templatePresentationText, null);
106 if (!fixesTask.isApplicableFixFound()) {
107 HintManager.getInstance().showErrorHint(editor, "Unfortunately '" + myText + "' is currently not available for batch mode");
112 public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
113 return myQuickfixClass != EmptyIntentionAction.class &&
114 !(myToolWrapper instanceof LocalInspectionToolWrapper && ((LocalInspectionToolWrapper)myToolWrapper).isUnfair());
118 public boolean startInWriteAction() {
122 private class PerformFixesTask extends PerformFixesModalTask {
123 private boolean myApplicableFixFound = false;
125 public PerformFixesTask(@NotNull Project project,
126 @NotNull CommonProblemDescriptor[] descriptors,
127 @NotNull SequentialModalProgressTask task) {
128 super(project, descriptors, task);
132 protected void applyFix(Project project, CommonProblemDescriptor descriptor) {
133 final QuickFix[] fixes = descriptor.getFixes();
134 if (fixes != null && fixes.length > 0) {
135 for (final QuickFix<CommonProblemDescriptor> fix : fixes) {
136 if (fix != null && fix.getClass().isAssignableFrom(myQuickfixClass)) {
137 final PsiElement element = ((ProblemDescriptor)descriptor).getPsiElement();
138 if (element != null && element.isValid()) {
139 fix.applyFix(project, descriptor);
140 myApplicableFixFound = true;
148 public boolean isApplicableFixFound() {
149 return myApplicableFixFound;