1073c624995471b8bb8aba9d77c663150e6d12e2
[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.CommonProblemDescriptor;
21 import com.intellij.codeInspection.InspectionApplication;
22 import com.intellij.codeInspection.InspectionsBundle;
23 import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
24 import com.intellij.codeInspection.ex.InspectionToolWrapper;
25 import com.intellij.codeInspection.ex.ScopeToolState;
26 import com.intellij.codeInspection.ex.Tools;
27 import com.intellij.codeInspection.export.*;
28 import com.intellij.codeInspection.reference.RefEntity;
29 import com.intellij.codeInspection.ui.*;
30 import com.intellij.icons.AllIcons;
31 import com.intellij.ide.BrowserUtil;
32 import com.intellij.openapi.actionSystem.AnAction;
33 import com.intellij.openapi.actionSystem.AnActionEvent;
34 import com.intellij.openapi.application.ApplicationManager;
35 import com.intellij.openapi.application.PathManager;
36 import com.intellij.openapi.components.PathMacroManager;
37 import com.intellij.openapi.progress.ProcessCanceledException;
38 import com.intellij.openapi.progress.ProgressManager;
39 import com.intellij.openapi.project.DumbAware;
40 import com.intellij.openapi.ui.Messages;
41 import com.intellij.openapi.ui.popup.JBPopupFactory;
42 import com.intellij.openapi.ui.popup.ListPopup;
43 import com.intellij.openapi.ui.popup.PopupStep;
44 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
45 import com.intellij.openapi.util.Comparing;
46 import com.intellij.openapi.util.JDOMUtil;
47 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
48 import com.intellij.util.ui.tree.TreeUtil;
49 import org.jdom.Document;
50 import org.jdom.Element;
51 import org.jetbrains.annotations.NonNls;
52 import org.jetbrains.annotations.NotNull;
53
54 import java.io.File;
55 import java.io.IOException;
56 import java.util.*;
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             if (!toolNode.isExcluded(myView.getExcludedManager())) {
145               final Set<RefEntity> excludedEntities = new HashSet<>();
146               final Set<CommonProblemDescriptor> excludedDescriptors = new HashSet<>();
147               TreeUtil.traverse(toolNode, o -> {
148                 InspectionTreeNode n = (InspectionTreeNode)o;
149                 if (n.isExcluded(myView.getExcludedManager())) {
150                   if (n instanceof RefElementNode) {
151                     excludedEntities.add(((RefElementNode)n).getElement());
152                   }
153                   if (n instanceof ProblemDescriptionNode) {
154                     excludedDescriptors.add(((ProblemDescriptionNode)n).getDescriptor());
155                   }
156                 }
157                 return true;
158               });
159               presentation.exportResults(problems, excludedEntities, excludedDescriptors);
160             }
161           }
162           PathMacroManager.getInstance(myView.getProject()).collapsePaths(problems);
163           try {
164             if (problems.getContentSize() != 0) {
165               JDOMUtil.writeDocument(new Document(problems),
166                                      outputDirectoryName + File.separator + toolWrapper.getShortName() + InspectionApplication.XML_EXTENSION,
167                                      CodeStyleSettingsManager.getSettings(null).getLineSeparator());
168             }
169           }
170           catch (IOException e) {
171             ex[0] = e;
172           }
173         }
174         return true;
175       });
176       if (ex[0] != null) {
177         throw ex[0];
178       }
179       final Element element = new Element(InspectionApplication.INSPECTIONS_NODE);
180       final String profileName = myView.getCurrentProfileName();
181       if (profileName != null) {
182         element.setAttribute(InspectionApplication.PROFILE, profileName);
183       }
184       JDOMUtil.writeDocument(new Document(element),
185                              outputDirectoryName + File.separator + InspectionApplication.DESCRIPTIONS + InspectionApplication.XML_EXTENSION,
186                              CodeStyleSettingsManager.getSettings(null).getLineSeparator());
187     }
188     catch (final IOException e) {
189       ApplicationManager.getApplication().invokeLater(() -> Messages.showErrorDialog(myView, e.getMessage()));
190     }
191   }
192
193   @NotNull
194   private Set<InspectionToolWrapper> getWorkedTools(@NotNull InspectionNode node) {
195     final Set<InspectionToolWrapper> result = new HashSet<InspectionToolWrapper>();
196     final InspectionToolWrapper wrapper = node.getToolWrapper();
197     if (myView.getCurrentProfileName() != null){
198       result.add(wrapper);
199       return result;
200     }
201     final String shortName = wrapper.getShortName();
202     final GlobalInspectionContextImpl context = myView.getGlobalInspectionContext();
203     final Tools tools = context.getTools().get(shortName);
204     if (tools != null) {   //dummy entry points tool
205       for (ScopeToolState state : tools.getTools()) {
206         InspectionToolWrapper toolWrapper = state.getTool();
207         result.add(toolWrapper);
208       }
209     }
210     return result;
211   }
212 }