module content search scopes
[idea/community.git] / plugins / devkit / src / inspections / quickfix / RegisterInspectionFix.java
1 /*
2  * Copyright 2000-2012 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 package org.jetbrains.idea.devkit.inspections.quickfix;
17
18 import com.intellij.codeInsight.hint.HintManager;
19 import com.intellij.codeInsight.intention.IntentionAction;
20 import com.intellij.codeInspection.InspectionEP;
21 import com.intellij.ide.TypePresentationService;
22 import com.intellij.openapi.application.Result;
23 import com.intellij.openapi.command.WriteCommandAction;
24 import com.intellij.openapi.editor.Editor;
25 import com.intellij.openapi.extensions.ExtensionPointName;
26 import com.intellij.openapi.module.Module;
27 import com.intellij.openapi.module.ModuleUtil;
28 import com.intellij.openapi.project.Project;
29 import com.intellij.openapi.roots.ProjectRootManager;
30 import com.intellij.openapi.ui.popup.JBPopupFactory;
31 import com.intellij.openapi.ui.popup.PopupStep;
32 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
33 import com.intellij.openapi.util.Condition;
34 import com.intellij.openapi.vfs.VirtualFile;
35 import com.intellij.psi.PsiClass;
36 import com.intellij.psi.PsiFile;
37 import com.intellij.psi.xml.XmlTag;
38 import com.intellij.util.IncorrectOperationException;
39 import com.intellij.util.PsiNavigateUtil;
40 import com.intellij.util.containers.ContainerUtil;
41 import com.intellij.util.xml.DomFileElement;
42 import com.intellij.util.xml.DomService;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.idea.devkit.DevKitBundle;
45 import org.jetbrains.idea.devkit.dom.Extension;
46 import org.jetbrains.idea.devkit.dom.Extensions;
47 import org.jetbrains.idea.devkit.dom.IdeaPlugin;
48
49 import javax.swing.*;
50 import java.util.List;
51
52 /**
53 * @author Dmitry Avdeev
54 *         Date: 1/20/12
55 */
56 class RegisterInspectionFix implements IntentionAction {
57
58   private final PsiClass myPsiClass;
59   private final ExtensionPointName<? extends InspectionEP> myEp;
60
61   RegisterInspectionFix(PsiClass psiClass, ExtensionPointName<? extends InspectionEP> ep) {
62     myPsiClass = psiClass;
63     myEp = ep;
64   }
65
66   @NotNull
67   @Override
68   public String getText() {
69     return "Register inspection";
70   }
71
72   @NotNull
73   @Override
74   public String getFamilyName() {
75     return DevKitBundle.message("inspections.component.not.registered.quickfix.family");
76   }
77
78   @Override
79   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
80     return true;
81   }
82
83   @Override
84   public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
85     Module module = ModuleUtil.findModuleForPsiElement(file);
86     assert module != null;
87     List<DomFileElement<IdeaPlugin>> elements =
88       DomService.getInstance().getFileElements(IdeaPlugin.class, project, module.getModuleContentWithDependenciesScope());
89
90     elements = ContainerUtil.filter(elements, new Condition<DomFileElement<IdeaPlugin>>() {
91       @Override
92       public boolean value(DomFileElement<IdeaPlugin> element) {
93         VirtualFile virtualFile = element.getFile().getVirtualFile();
94         return virtualFile != null && ProjectRootManager.getInstance(project).getFileIndex().isInContent(virtualFile);
95       }
96     });
97
98     if (elements.isEmpty()) {
99       HintManager.getInstance().showErrorHint(editor, "Cannot find plugin descriptor");
100       return;
101     }
102
103     if (elements.size() == 1) {
104       doFix(elements.get(0), project, file);
105       return;
106     }
107
108     final BaseListPopupStep<DomFileElement<IdeaPlugin>> popupStep =
109       new BaseListPopupStep<DomFileElement<IdeaPlugin>>("Choose Plugin Descriptor", elements) {
110         @Override
111         public Icon getIconFor(DomFileElement<IdeaPlugin> aValue) {
112           return TypePresentationService.getService().getIcon(aValue);
113         }
114
115         @NotNull
116         @Override
117         public String getTextFor(DomFileElement<IdeaPlugin> value) {
118           return value.getFile().getName();
119         }
120
121         @Override
122         public PopupStep onChosen(DomFileElement<IdeaPlugin> selectedValue, boolean finalChoice) {
123           doFix(selectedValue, project, file);
124           return FINAL_CHOICE;
125         }
126       };
127     JBPopupFactory.getInstance().createListPopup(popupStep)
128       .showInBestPositionFor(editor);
129   }
130
131   private void doFix(DomFileElement<IdeaPlugin> selectedValue, final Project project, final PsiFile file) {
132     final IdeaPlugin plugin = selectedValue.getRootElement();
133     final List<Extensions> extensionsList = plugin.getExtensions();
134     Extension extension = new WriteCommandAction<Extension>(project, file) {
135
136       @Override
137       protected void run(Result<Extension> result) throws Throwable {
138         final Extensions extensions = getExtension(plugin, extensionsList);
139         Extension extension = extensions.addExtension(myEp.getName());
140         XmlTag tag = extension.getXmlTag();
141         tag.setAttribute("implementationClass", myPsiClass.getQualifiedName());
142         result.setResult(extension);
143       }
144     }.execute().throwException().getResultObject();
145     PsiNavigateUtil.navigate(extension.getXmlTag());
146   }
147
148   private Extensions getExtension(IdeaPlugin plugin, List<Extensions> extensionsList) {
149     Extensions extensions = null;
150     for (Extensions e : extensionsList) {
151       String s = e.getDefaultExtensionNs().getStringValue();
152       if (s != null && myEp.getName().startsWith(s)) {
153         extensions = e;
154         break;
155       }
156     }
157     if (extensions == null) {
158       extensions = plugin.addExtensions();
159       extensions.getDefaultExtensionNs().setStringValue("com.intellij");
160     }
161     return extensions;
162   }
163
164   @Override
165   public boolean startInWriteAction() {
166     return false;
167   }
168 }