update copyright
[fedora-idea.git] / plugins / devkit / src / inspections / DevKitInspectionBase.java
blobcc2964147aaac79d5f0cc4cfda47fe44205f23ba
1 /*
2 * Copyright 2000-2009 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.
16 package org.jetbrains.idea.devkit.inspections;
18 import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
19 import com.intellij.openapi.actionSystem.ActionGroup;
20 import com.intellij.openapi.actionSystem.AnAction;
21 import com.intellij.openapi.module.Module;
22 import com.intellij.openapi.module.ModuleUtil;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.vfs.VirtualFile;
25 import com.intellij.psi.*;
26 import com.intellij.psi.search.GlobalSearchScope;
27 import com.intellij.psi.xml.*;
28 import gnu.trove.THashSet;
29 import gnu.trove.TObjectHashingStrategy;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
32 import org.jetbrains.idea.devkit.DevKitBundle;
33 import org.jetbrains.idea.devkit.module.PluginModuleType;
34 import org.jetbrains.idea.devkit.util.ActionType;
35 import org.jetbrains.idea.devkit.util.ComponentType;
36 import org.jetbrains.idea.devkit.util.DescriptorUtil;
38 import java.util.List;
39 import java.util.Set;
41 /**
42 * @author swr
44 public abstract class DevKitInspectionBase extends BaseJavaLocalInspectionTool {
46 @NotNull
47 public String getGroupDisplayName() {
48 return DevKitBundle.message("inspections.group.name");
51 @Nullable
52 protected static Set<PsiClass> getRegistrationTypes(PsiClass psiClass, boolean includeActions) {
53 final Project project = psiClass.getProject();
54 final PsiFile psiFile = psiClass.getContainingFile();
56 assert psiFile != null;
58 final VirtualFile virtualFile = psiFile.getVirtualFile();
59 if (virtualFile == null) return null;
60 final Module module = ModuleUtil.findModuleForFile(virtualFile, project);
62 if (module == null) return null;
64 if (PluginModuleType.isOfType(module)) {
65 return checkModule(module, psiClass, null, includeActions);
66 } else {
67 Set<PsiClass> types = null;
68 final List<Module> modules = PluginModuleType.getCandidateModules(module);
69 for (Module m : modules) {
70 types = checkModule(m, psiClass, types, includeActions);
72 return types;
76 private static Set<PsiClass> checkModule(Module module, PsiClass psiClass, Set<PsiClass> types, boolean includeActions) {
77 final XmlFile pluginXml = PluginModuleType.getPluginXml(module, false);
78 if (!isPluginXml(pluginXml)) return types;
79 assert pluginXml != null;
81 final XmlDocument document = pluginXml.getDocument();
82 assert document != null;
84 final XmlTag rootTag = document.getRootTag();
85 assert rootTag != null;
87 final String qualifiedName = psiClass.getQualifiedName();
88 if (qualifiedName != null) {
89 final RegistrationTypeFinder finder = new RegistrationTypeFinder(psiClass, types);
91 DescriptorUtil.processComponents(rootTag, finder);
93 if (includeActions) {
94 DescriptorUtil.processActions(rootTag, finder);
97 types = finder.getTypes();
100 return types;
103 protected static boolean isPluginXml(PsiFile file) {
104 if (!(file instanceof XmlFile)) return false;
105 final XmlFile pluginXml = (XmlFile)file;
107 final XmlDocument document = pluginXml.getDocument();
108 if (document == null) return false;
109 final XmlTag rootTag = document.getRootTag();
110 return rootTag != null && "idea-plugin".equals(rootTag.getLocalName());
114 @Nullable
115 protected static PsiElement getAttValueToken(@NotNull XmlAttribute attribute) {
116 final XmlAttributeValue valueElement = attribute.getValueElement();
117 if (valueElement == null) return null;
119 final PsiElement[] children = valueElement.getChildren();
120 if (children.length == 3 && children[1] instanceof XmlToken) {
121 return children[1];
123 return valueElement;
126 protected static boolean isAbstract(PsiModifierListOwner checkedClass) {
127 return checkedClass.hasModifierProperty(PsiModifier.ABSTRACT);
130 protected static boolean isPublic(PsiModifierListOwner checkedClass) {
131 return checkedClass.hasModifierProperty(PsiModifier.PUBLIC);
134 protected static boolean isActionRegistered(PsiClass psiClass) {
135 final Set<PsiClass> registrationTypes = getRegistrationTypes(psiClass, true);
136 if (registrationTypes != null) {
137 for (PsiClass type : registrationTypes) {
138 if (AnAction.class.getName().equals(type.getQualifiedName())) return true;
139 if (ActionGroup.class.getName().equals(type.getQualifiedName())) return true;
142 return false;
145 static class RegistrationTypeFinder implements ComponentType.Processor, ActionType.Processor {
146 private Set<PsiClass> myTypes;
147 private final String myQualifiedName;
148 private final PsiManager myManager;
149 private final GlobalSearchScope myScope;
151 public RegistrationTypeFinder(PsiClass psiClass, Set<PsiClass> types) {
152 myTypes = types;
153 myQualifiedName = psiClass.getQualifiedName();
154 myManager = psiClass.getManager();
155 myScope = psiClass.getResolveScope();
158 public boolean process(ComponentType type, XmlTag component, XmlTagValue impl, XmlTagValue intf) {
159 if (impl != null && myQualifiedName.equals(impl.getTrimmedText())) {
160 final PsiClass clazz = JavaPsiFacade.getInstance(myManager.getProject()).findClass(type.myClassName, myScope);
161 if (clazz != null) {
162 addType(clazz);
165 return true;
168 public boolean process(ActionType type, XmlTag action) {
169 final String actionClass = action.getAttributeValue("class");
170 if (actionClass != null) {
171 if (actionClass.trim().equals(myQualifiedName)) {
172 final PsiClass clazz = JavaPsiFacade.getInstance(myManager.getProject()).findClass(type.myClassName, myScope);
173 if (clazz != null) {
174 addType(clazz);
175 return false;
179 return true;
182 private void addType(PsiClass clazz) {
183 if (myTypes == null) {
184 //noinspection unchecked
185 myTypes = new THashSet<PsiClass>(2, TObjectHashingStrategy.IDENTITY);
187 myTypes.add(clazz);
190 public Set<PsiClass> getTypes() {
191 return myTypes;