package com.maxifier.guice.jpa; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.IntentionAndQuickFixAction; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiElementFilter; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import static com.maxifier.guice.jpa.GuiceJPAInspection.*; /** * Created by: Aleksey Didik * Date: 3/16/11 * Time: 4:30 PM * <p/> * Copyright (c) 1999-2011 Maxifier Ltd. All Rights Reserved. * Code proprietary and confidential. * Use is subject to license terms. * * @author Aleksey Didik */ public class DBClassesInspection extends AbstractDBInspection { @NotNull @Override public String getID() { return "DBClassesInspection"; } @Override public String getAlternativeID() { return "DBClassesInspection"; } @Nls @NotNull @Override public String getGroupDisplayName() { return INSPECTIONS_GROUP_NAME; } @Nls @NotNull @Override public String getDisplayName() { return "Classes with methods annotated with @DB"; } @NotNull @Override public String getShortName() { return "db-classes-modifiers"; } @Override public boolean isEnabledByDefault() { return true; } @NotNull @Override public HighlightDisplayLevel getDefaultLevel() { return HighlightDisplayLevel.ERROR; } @Override public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) { List<ProblemDescriptor> problemDescriptors = new ArrayList<ProblemDescriptor>(); PsiElement[] classes = PsiTreeUtil.collectElements(file, new AnnotatedPsiMethodFilter(DB_NAME)); for (PsiElement psiClass : classes) { checkClass((PsiClass) psiClass, manager, problemDescriptors); } return problemDescriptors.toArray(new ProblemDescriptor[problemDescriptors.size()]); } private void checkClass(PsiClass psiClass, InspectionManager inspectionManager, List<ProblemDescriptor> problemDescriptors) { PsiIdentifier nameIdentifier = psiClass.getNameIdentifier(); if (nameIdentifier == null) { return; } if (psiClass.isInterface() || psiClass.isEnum() || psiClass.isAnnotationType()) { problemDescriptors.add( inspectionManager.createProblemDescriptor( nameIdentifier, "Only classes could have methods with @DB annotation", new DeleteAnnotationFixAction(psiClass), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, true ) ); } else { checkModifiers(psiClass, inspectionManager, problemDescriptors); } } private void checkModifiers(PsiClass psiClass, InspectionManager inspectionManager, List<ProblemDescriptor> problemDescriptors) { PsiModifierList classModifierList = psiClass.getModifierList(); if (classModifierList != null && classModifierList.hasModifierProperty(FINAL_MODIFIER)) { PsiElement finalModifier = getModifier(classModifierList, FINAL_MODIFIER); problemDescriptors.add(inspectionManager.createProblemDescriptor( finalModifier, "Class with methods annotated with @DB should not be final", new DeleteModifierFixAction(finalModifier), ProblemHighlightType.GENERIC_ERROR, true)); } if (classModifierList != null && classModifierList.hasModifierProperty(PRIVATE_MODIFIER)) { PsiElement privateModifier = getModifier(classModifierList, PRIVATE_MODIFIER); problemDescriptors.add(inspectionManager.createProblemDescriptor( privateModifier, "Class with methods annotated with @DB should not be private", new DeleteModifierFixAction(privateModifier), ProblemHighlightType.GENERIC_ERROR, true)); } } private static class DeleteAnnotationFixAction extends IntentionAndQuickFixAction { private final PsiClass psiClass; DeleteAnnotationFixAction(PsiClass psiClass) { this.psiClass = psiClass; } @NotNull @Override public String getName() { return "Delete @DB annotation from methods"; } @NotNull @Override public String getFamilyName() { return "@DB fix actions"; } @Override public void applyFix(Project project, PsiFile psiFile, @Nullable Editor editor) { for (PsiMethod psiMethod : psiClass.getMethods()) { PsiAnnotation annotation = getAnnotation(psiMethod, DB_NAME); if (annotation != null) { annotation.delete(); } } } } private static class AnnotatedPsiMethodFilter implements PsiElementFilter { private String name; private AnnotatedPsiMethodFilter(String name) { this.name = name; } @Override public boolean isAccepted(PsiElement psiElement) { if (!(psiElement instanceof PsiClass)) { return false; } PsiClass psiClass = (PsiClass) psiElement; for (PsiMethod psiMethod : psiClass.getMethods()) { if (getAnnotation(psiMethod, name) != null) { return true; } } return false; } } }