export html action: do not traverse tree for excluded elements
[idea/community.git] / platform / lang-impl / src / com / intellij / codeInspection / ui / actions / ExportHTMLAction.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.intellij.codeInspection.ui.actions;
18
19 import com.intellij.codeEditor.printing.ExportToHTMLSettings;
20 import com.intellij.codeInspection.InspectionApplication;
21 import com.intellij.codeInspection.InspectionsBundle;
22 import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
23 import com.intellij.codeInspection.ex.InspectionToolWrapper;
24 import com.intellij.codeInspection.ex.ScopeToolState;
25 import com.intellij.codeInspection.ex.Tools;
26 import com.intellij.codeInspection.export.ExportToHTMLDialog;
27 import com.intellij.codeInspection.export.InspectionTreeHtmlWriter;
28 import com.intellij.codeInspection.ui.*;
29 import com.intellij.icons.AllIcons;
30 import com.intellij.ide.BrowserUtil;
31 import com.intellij.openapi.actionSystem.AnAction;
32 import com.intellij.openapi.actionSystem.AnActionEvent;
33 import com.intellij.openapi.application.ApplicationManager;
34 import com.intellij.openapi.application.PathManager;
35 import com.intellij.openapi.components.PathMacroManager;
36 import com.intellij.openapi.progress.ProcessCanceledException;
37 import com.intellij.openapi.progress.ProgressManager;
38 import com.intellij.openapi.project.DumbAware;
39 import com.intellij.openapi.ui.Messages;
40 import com.intellij.openapi.ui.popup.JBPopupFactory;
41 import com.intellij.openapi.ui.popup.ListPopup;
42 import com.intellij.openapi.ui.popup.PopupStep;
43 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
44 import com.intellij.openapi.util.Comparing;
45 import com.intellij.openapi.util.JDOMUtil;
46 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
47 import com.intellij.util.ui.tree.TreeUtil;
48 import org.jdom.Document;
49 import org.jdom.Element;
50 import org.jetbrains.annotations.NonNls;
51 import org.jetbrains.annotations.NotNull;
52
53 import java.io.File;
54 import java.io.IOException;
55 import java.util.HashSet;
56 import java.util.Set;
57
58 /**
59  * User: anna
60  * Date: 11-Jan-2006
61  */
62 public class ExportHTMLAction extends AnAction implements DumbAware {
63   private final InspectionResultsView myView;
64   @NonNls private static final String PROBLEMS = "problems";
65   @NonNls private static final String HTML = "HTML";
66   @NonNls private static final String XML = "XML";
67
68   public ExportHTMLAction(final InspectionResultsView view) {
69     super(InspectionsBundle.message("inspection.action.export.html"), null, AllIcons.Actions.Export);
70     myView = view;
71   }
72
73   @Override
74   public void actionPerformed(AnActionEvent e) {
75     final ListPopup popup = JBPopupFactory.getInstance().createListPopup(
76       new BaseListPopupStep<String>(InspectionsBundle.message("inspection.action.export.popup.title"), HTML, XML) {
77         @Override
78         public PopupStep onChosen(final String selectedValue, final boolean finalChoice) {
79           return doFinalStep(() -> exportHTML(Comparing.strEqual(selectedValue, HTML)));
80         }
81       });
82     InspectionResultsView.showPopup(e, popup);
83   }
84
85   private void exportHTML(final boolean exportToHTML) {
86     ExportToHTMLDialog exportToHTMLDialog = new ExportToHTMLDialog(myView.getProject(), exportToHTML);
87     final ExportToHTMLSettings exportToHTMLSettings = ExportToHTMLSettings.getInstance(myView.getProject());
88     if (exportToHTMLSettings.OUTPUT_DIRECTORY == null) {
89       exportToHTMLSettings.OUTPUT_DIRECTORY = PathManager.getHomePath() + File.separator + "inspections";
90     }
91     exportToHTMLDialog.reset();
92     if (!exportToHTMLDialog.showAndGet()) {
93       return;
94     }
95     exportToHTMLDialog.apply();
96
97     final String outputDirectoryName = exportToHTMLSettings.OUTPUT_DIRECTORY;
98     ApplicationManager.getApplication().invokeLater(() -> {
99       final Runnable exportRunnable = () -> ApplicationManager.getApplication().runReadAction(() -> {
100         if (!exportToHTML) {
101           dump2xml(outputDirectoryName);
102         }
103         else {
104           try {
105             new InspectionTreeHtmlWriter(myView.getTree(), outputDirectoryName);
106           }
107           catch (ProcessCanceledException e) {
108             // Do nothing here.
109           }
110         }
111       });
112
113       if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(exportRunnable,
114                                                                              InspectionsBundle.message(exportToHTML
115                                                                                                        ? "inspection.generating.html.progress.title"
116                                                                                                        : "inspection.generating.xml.progress.title"), true,
117                                                                              myView.getProject())) {
118         return;
119       }
120
121       if (exportToHTML && exportToHTMLSettings.OPEN_IN_BROWSER) {
122         BrowserUtil.browse(new File(exportToHTMLSettings.OUTPUT_DIRECTORY, "index.html"));
123       }
124     });
125   }
126
127   private void dump2xml(final String outputDirectoryName) {
128     try {
129       final File outputDir = new File(outputDirectoryName);
130       if (!outputDir.exists() && !outputDir.mkdirs()) {
131         throw new IOException("Cannot create \'" + outputDir + "\'");
132       }
133       final InspectionTreeNode root = myView.getTree().getRoot();
134       final IOException[] ex = new IOException[1];
135       TreeUtil.traverse(root, node -> {
136         if (node instanceof InspectionNode) {
137           InspectionNode toolNode = (InspectionNode)node;
138           Element problems = new Element(PROBLEMS);
139           InspectionToolWrapper toolWrapper = toolNode.getToolWrapper();
140
141           final Set<InspectionToolWrapper> toolWrappers = getWorkedTools(toolNode);
142           for (InspectionToolWrapper wrapper : toolWrappers) {
143             InspectionToolPresentation presentation = myView.getGlobalInspectionContext().getPresentation(wrapper);
144             final ExcludedInspectionTreeNodesManager excludedManager = myView.getExcludedManager();
145             if (!toolNode.isExcluded(excludedManager)) {
146               presentation.exportResults(problems, excludedManager::containsRefEntity, excludedManager::containsProblemDescriptor);
147             }
148           }
149           PathMacroManager.getInstance(myView.getProject()).collapsePaths(problems);
150           try {
151             if (problems.getContentSize() != 0) {
152               JDOMUtil.writeDocument(new Document(problems),
153                                      outputDirectoryName + File.separator + toolWrapper.getShortName() + InspectionApplication.XML_EXTENSION,
154                                      CodeStyleSettingsManager.getSettings(null).getLineSeparator());
155             }
156           }
157           catch (IOException e) {
158             ex[0] = e;
159           }
160         }
161         return true;
162       });
163       if (ex[0] != null) {
164         throw ex[0];
165       }
166       final Element element = new Element(InspectionApplication.INSPECTIONS_NODE);
167       final String profileName = myView.getCurrentProfileName();
168       if (profileName != null) {
169         element.setAttribute(InspectionApplication.PROFILE, profileName);
170       }
171       JDOMUtil.writeDocument(new Document(element),
172                              outputDirectoryName + File.separator + InspectionApplication.DESCRIPTIONS + InspectionApplication.XML_EXTENSION,
173                              CodeStyleSettingsManager.getSettings(null).getLineSeparator());
174     }
175     catch (final IOException e) {
176       ApplicationManager.getApplication().invokeLater(() -> Messages.showErrorDialog(myView, e.getMessage()));
177     }
178   }
179
180   @NotNull
181   private Set<InspectionToolWrapper> getWorkedTools(@NotNull InspectionNode node) {
182     final Set<InspectionToolWrapper> result = new HashSet<InspectionToolWrapper>();
183     final InspectionToolWrapper wrapper = node.getToolWrapper();
184     if (myView.getCurrentProfileName() != null){
185       result.add(wrapper);
186       return result;
187     }
188     final String shortName = wrapper.getShortName();
189     final GlobalInspectionContextImpl context = myView.getGlobalInspectionContext();
190     final Tools tools = context.getTools().get(shortName);
191     if (tools != null) {   //dummy entry points tool
192       for (ScopeToolState state : tools.getTools()) {
193         InspectionToolWrapper toolWrapper = state.getTool();
194         result.add(toolWrapper);
195       }
196     }
197     return result;
198   }
199 }