quick fixes
[idea/community.git] / plugins / devkit / src / inspections / InspectionMappingConsistencyInspection.java
1 /*
2  * Copyright 2000-2011 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;
17
18 import com.intellij.codeInsight.daemon.impl.analysis.InsertRequiredAttributeFix;
19 import com.intellij.codeInspection.LocalInspectionToolSession;
20 import com.intellij.codeInspection.LocalQuickFix;
21 import com.intellij.codeInspection.ProblemsHolder;
22 import com.intellij.openapi.util.Pair;
23 import com.intellij.openapi.util.TextRange;
24 import com.intellij.psi.PsiElement;
25 import com.intellij.psi.PsiElementVisitor;
26 import com.intellij.psi.XmlElementVisitor;
27 import com.intellij.psi.util.InheritanceUtil;
28 import com.intellij.psi.util.PsiTreeUtil;
29 import com.intellij.psi.xml.XmlTag;
30 import com.intellij.util.Function;
31 import com.intellij.util.containers.ContainerUtil;
32 import com.intellij.util.xml.DomElement;
33 import com.intellij.util.xml.DomUtil;
34 import org.jetbrains.annotations.Nls;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.idea.devkit.dom.Extension;
37 import org.jetbrains.idea.devkit.dom.ExtensionPoint;
38 import org.jetbrains.idea.devkit.dom.IdeaPlugin;
39
40 import java.text.MessageFormat;
41
42 /**
43  * @author Dmitry Avdeev
44  *         Date: 10/10/11
45  */
46 public class InspectionMappingConsistencyInspection extends DevKitInspectionBase {
47
48   @NotNull
49   @Override
50   public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder,
51                                         boolean isOnTheFly,
52                                         @NotNull LocalInspectionToolSession session) {
53     return new XmlElementVisitor()  {
54       @Override
55       public void visitXmlTag(XmlTag tag) {
56         DomElement element = DomUtil.getDomElement(tag);
57         if (element instanceof Extension) {
58           ExtensionPoint extensionPoint = ((Extension)element).getExtensionPoint();
59           if (extensionPoint != null && InheritanceUtil.isInheritor(extensionPoint.getBeanClass().getValue(), "com.intellij.codeInspection.InspectionEP")) {
60             boolean key = tag.getAttribute("key") != null;
61             boolean groupKey = tag.getAttribute("groupKey") != null;
62             if (key) {
63               if (tag.getAttribute("bundle") == null) {
64                 checkDefaultBundle(element, holder);
65               }
66             }
67             else if (tag.getAttribute("displayName") == null) {
68               registerProblem(element, holder, "displayName or key should be specified", "displayName", "key");
69             }
70             if (groupKey) {
71               if (tag.getAttribute("bundle") == null && tag.getAttribute("groupBundle") == null) {
72                 checkDefaultBundle(element, holder);
73               }
74             }
75             else if (tag.getAttribute("groupName") == null) {
76               registerProblem(element, holder, "groupName or groupKey should be specified", "groupName", "groupKey");
77             }
78           }
79         }
80       }
81     };
82   }
83
84   private static void checkDefaultBundle(DomElement element, ProblemsHolder holder) {
85     IdeaPlugin plugin = DomUtil.getParentOfType(element, IdeaPlugin.class, true);
86     if (plugin != null && plugin.getResourceBundles().isEmpty()) {
87       registerProblem(element, holder, "Bundle should be specified");
88     }
89   }
90
91   private static void registerProblem(DomElement element, ProblemsHolder holder, String message, String... createAttrs) {
92     final Pair<TextRange,PsiElement> range = DomUtil.getProblemRange(element.getXmlTag());
93     holder.registerProblem(range.second, range.first, message, ContainerUtil.map(createAttrs, new Function<String, LocalQuickFix>() {
94       @Override
95       public LocalQuickFix fun(final String s) {
96         return new InsertRequiredAttributeFix(PsiTreeUtil.getParentOfType(range.second, XmlTag.class, false), s, null) {
97           @NotNull
98           @Override
99           public String getText() {
100             return MessageFormat.format("Insert ''{0}'' attribute", s);
101           }
102         };
103       }
104     }, new LocalQuickFix[createAttrs.length]));
105   }
106
107   @Nls
108   @NotNull
109   @Override
110   public String getDisplayName() {
111     return "<inspection> tag consistency";
112   }
113
114   @NotNull
115   @Override
116   public String getShortName() {
117     return "InspectionMappingConsistency";
118   }
119 }