optimization
[fedora-idea.git] / plugins / devkit / src / inspections / DescriptionNotFoundInspection.java
bloba07f5364983448984c5c7c8f03ffd908a7189616
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.
17 package org.jetbrains.idea.devkit.inspections;
19 import com.intellij.codeInspection.InspectionManager;
20 import com.intellij.codeInspection.LocalQuickFix;
21 import com.intellij.codeInspection.ProblemDescriptor;
22 import com.intellij.codeInspection.ProblemHighlightType;
23 import com.intellij.openapi.module.Module;
24 import com.intellij.openapi.module.ModuleUtil;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.roots.ModuleRootManager;
27 import com.intellij.openapi.vfs.VirtualFile;
28 import com.intellij.psi.*;
29 import com.intellij.psi.search.GlobalSearchScope;
30 import org.jetbrains.annotations.Nls;
31 import org.jetbrains.annotations.NonNls;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
34 import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix;
35 import org.jetbrains.idea.devkit.util.PsiUtil;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.List;
41 /**
42 * @author Konstantin Bulenkov
44 public class DescriptionNotFoundInspection extends DevKitInspectionBase{
45 @NonNls private static final String INSPECTION_PROFILE_ENTRY = "com.intellij.codeInspection.InspectionProfileEntry";
46 @NonNls private static final String INSPECTION_DESCRIPTIONS = "inspectionDescriptions";
48 @Override
49 public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
50 final Project project = aClass.getProject();
51 final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
52 final Module module = ModuleUtil.findModuleForPsiElement(aClass);
54 if (nameIdentifier == null || module == null || !PsiUtil.isInstanciatable(aClass)) return null;
56 final PsiClass base = JavaPsiFacade.getInstance(project).findClass(INSPECTION_PROFILE_ENTRY, GlobalSearchScope.allScope(project));
58 if (base == null || ! aClass.isInheritor(base, true) || isPathMethodsAreOverriden(aClass)) return null;
60 final PsiMethod method = findNearestMethod("getShortName", aClass);
61 if (method == null) return null;
62 final String filename = PsiUtil.getReturnedLiteral(method, aClass);
63 if (filename == null) return null;
66 for (PsiDirectory description : getInspectionDescriptionsDirs(module)) {
67 if (description.getVirtualFile().getNameWithoutExtension().equals(filename)) {
68 return null;
73 final PsiElement problem = getProblemElement(aClass, method);
74 final ProblemDescriptor problemDescriptor = manager
75 .createProblemDescriptor(problem == null ? nameIdentifier : problem,
76 "Inspection does not have a description",
77 new LocalQuickFix[]{new CreateHtmlDescriptionFix(filename, module)},
78 ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
79 return new ProblemDescriptor[]{problemDescriptor};
82 @Nullable
83 private static PsiElement getProblemElement(PsiClass aClass, PsiMethod method) {
84 if (method.getContainingClass() == aClass) {
85 return PsiUtil.getReturnedExpression(method);
86 } else {
87 return aClass.getNameIdentifier();
91 private static boolean isPathMethodsAreOverriden(PsiClass aClass) {
92 return! ( isLastMethodDefinitionIn("getStaticDescription", INSPECTION_PROFILE_ENTRY, aClass)
93 && isLastMethodDefinitionIn("getDescriptionUrl", INSPECTION_PROFILE_ENTRY, aClass)
94 && isLastMethodDefinitionIn("getDescriptionContextClass", INSPECTION_PROFILE_ENTRY, aClass)
95 && isLastMethodDefinitionIn("getDescriptionFileName", INSPECTION_PROFILE_ENTRY, aClass));
98 private static boolean isLastMethodDefinitionIn(@NotNull String methodName, @NotNull String classFQN, PsiClass cls) {
99 if (cls == null) return false;
100 for (PsiMethod method : cls.getMethods()) {
101 if (method.getName().equals(methodName)) {
102 final PsiClass containingClass = method.getContainingClass();
103 if (containingClass == null) return false;
104 return classFQN.equals(containingClass.getQualifiedName());
107 return isLastMethodDefinitionIn(methodName, classFQN, cls.getSuperClass());
110 public static List<VirtualFile> getPotentialRoots(Module module) {
111 final PsiDirectory[] dirs = getInspectionDescriptionsDirs(module);
112 final List<VirtualFile> result = new ArrayList<VirtualFile>();
113 if (dirs.length != 0) {
114 for (PsiDirectory dir : dirs) {
115 final PsiDirectory parent = dir.getParentDirectory();
116 if (parent != null) result.add(parent.getVirtualFile());
118 } else {
119 result.addAll(Arrays.asList(ModuleRootManager.getInstance(module).getSourceRoots()));
121 return result;
124 public static PsiDirectory[] getInspectionDescriptionsDirs(Module module) {
125 final PsiPackage aPackage = JavaPsiFacade.getInstance(module.getProject()).findPackage(INSPECTION_DESCRIPTIONS);
126 if (aPackage != null) {
127 return aPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module));
128 } else {
129 return PsiDirectory.EMPTY_ARRAY;
133 @Nullable
134 private static PsiMethod findNearestMethod(String name, @Nullable PsiClass cls) {
135 if (cls == null) return null;
136 for (PsiMethod method : cls.getMethods()) {
137 if (method.getParameterList().getParametersCount() == 0 && method.getName().equals(name)) {
138 return method.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT) ? null : method;
141 return findNearestMethod(name, cls.getSuperClass());
144 @Nls
145 @NotNull
146 public String getDisplayName() {
147 return "Inspection Description Checker";
150 @NotNull
151 public String getShortName() {
152 return "DescriptionNotFoundInspection";
155 @Override
156 public boolean isEnabledByDefault() {
157 return true;