diff --git a/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java b/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java index 8538484bf42b..78513d3b4553 100644 --- a/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java +++ b/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java @@ -25,7 +25,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.NullableLazyValue; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.MethodReferencesSearch; @@ -41,12 +40,12 @@ import org.jetbrains.idea.devkit.DevKitBundle; import org.jetbrains.idea.devkit.inspections.quickfix.RegisterActionFix; import org.jetbrains.idea.devkit.inspections.quickfix.RegisterComponentFix; import org.jetbrains.idea.devkit.module.PluginModuleType; -import org.jetbrains.idea.devkit.util.ActionType; import org.jetbrains.idea.devkit.util.ComponentType; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import java.util.Map; import java.util.Set; public class ComponentNotRegisteredInspection extends DevKitInspectionBase { @@ -101,15 +100,6 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase { GlobalSearchScope scope = checkedClass.getResolveScope(); - final NullableLazyValue registrationType = new NullableLazyValue() { - @Nullable - @Override - protected PsiClass compute() { - final Set types = RegistrationCheckerUtil.getRegistrationTypes(checkedClass, CHECK_ACTIONS); - return ContainerUtil.getFirstItem(types); - } - }; - if (CHECK_ACTIONS) { PsiClass actionClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(AnAction.class.getName(), scope); if (actionClass == null) { @@ -120,7 +110,7 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase { if (IGNORE_NON_PUBLIC && !checkedClass.hasModifierProperty(PsiModifier.PUBLIC)) { return null; } - if (!isActionRegistered(checkedClass, registrationType.getValue()) && canFix(checkedClass)) { + if (!isActionRegistered(checkedClass) && canFix(checkedClass)) { LocalQuickFix fix = new RegisterActionFix(org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass)); ProblemDescriptor problem = manager.createProblemDescriptor(classIdentifier, @@ -139,45 +129,50 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase { // stop if component class cannot be found (non-devkit module/project) return null; } - if (checkedClass.isInheritor(compClass, true)) { - boolean registeredAsComponent = false; + if (!checkedClass.isInheritor(compClass, true)) { + return null; + } - final PsiClass registrationClass = registrationType.getValue(); - if (registrationClass != null) { - final String qualifiedName = registrationClass.getQualifiedName(); - registeredAsComponent = !ActionType.ACTION.myClassName.equals(qualifiedName) && - !ActionType.GROUP.myClassName.equals(qualifiedName); + for (ComponentType componentType : ComponentType.values()) { + if (!InheritanceUtil.isInheritor(checkedClass, componentType.myClassName)) { + continue; } - if (!registeredAsComponent && canFix(checkedClass)) { - ComponentType type = null; - for (ComponentType componentType : ComponentType.values()) { - if (InheritanceUtil.isInheritor(checkedClass, componentType.myClassName)) { - type = componentType; - break; - } - } - if (type == null) { - return null; - } - - LocalQuickFix fix = new RegisterComponentFix(type, org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass)); - ProblemDescriptor problem = - manager.createProblemDescriptor(classIdentifier, - DevKitBundle.message("inspections.component.not.registered.message", - DevKitBundle.message(type.myPropertyKey)), - fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly); - return new ProblemDescriptor[]{problem}; + if (findRegistrationType(checkedClass, COMPONENT_TYPE_TO_REGISTRATION_TYPE.get(componentType)) != null) { + return null; } + + if (!canFix(checkedClass)) { + return null; + } + LocalQuickFix fix = new RegisterComponentFix(componentType, org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass)); + ProblemDescriptor problem = + manager.createProblemDescriptor(classIdentifier, + DevKitBundle.message("inspections.component.not.registered.message", + DevKitBundle.message(componentType.myPropertyKey)), + fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly); + return new ProblemDescriptor[]{problem}; } } return null; } - private static boolean isActionRegistered(PsiClass actionClass, PsiClass registrationType) { + private static final Map COMPONENT_TYPE_TO_REGISTRATION_TYPE = + ContainerUtil.immutableMapBuilder() + .put(ComponentType.APPLICATION, RegistrationCheckerUtil.RegistrationType.APPLICATION_COMPONENT) + .put(ComponentType.PROJECT, RegistrationCheckerUtil.RegistrationType.PROJECT_COMPONENT) + .put(ComponentType.MODULE, RegistrationCheckerUtil.RegistrationType.MODULE_COMPONENT) + .build(); + + private static PsiClass findRegistrationType(@Nullable PsiClass checkedClass, RegistrationCheckerUtil.RegistrationType type) { + final Set types = RegistrationCheckerUtil.getRegistrationTypes(checkedClass, type); + return ContainerUtil.getFirstItem(types); + } + + private static boolean isActionRegistered(PsiClass actionClass) { + final PsiClass registrationType = findRegistrationType(actionClass, RegistrationCheckerUtil.RegistrationType.ACTION); if (registrationType != null) { - if (ActionType.ACTION.myClassName.equals(registrationType.getQualifiedName())) return true; - if (ActionType.GROUP.myClassName.equals(registrationType.getQualifiedName())) return true; + return true; } // search code usages: 1) own CTOR calls 2) usage via "new ActionClass()" diff --git a/plugins/devkit/src/inspections/RegistrationCheckerUtil.java b/plugins/devkit/src/inspections/RegistrationCheckerUtil.java index 9edc40a45ec2..17d8701ae527 100644 --- a/plugins/devkit/src/inspections/RegistrationCheckerUtil.java +++ b/plugins/devkit/src/inspections/RegistrationCheckerUtil.java @@ -42,8 +42,17 @@ import java.util.Set; class RegistrationCheckerUtil { + enum RegistrationType { + ALL, + ALL_COMPONENTS, + APPLICATION_COMPONENT, + PROJECT_COMPONENT, + MODULE_COMPONENT, + ACTION + } + @Nullable - static Set getRegistrationTypes(PsiClass psiClass, boolean includeActions) { + static Set getRegistrationTypes(PsiClass psiClass, RegistrationType registrationType) { final Project project = psiClass.getProject(); final PsiFile psiFile = psiClass.getContainingFile(); @@ -56,7 +65,7 @@ class RegistrationCheckerUtil { final boolean isIdeaProject = PsiUtil.isIdeaProject(project); - final Set pluginModuleResults = checkModule(module, isIdeaProject, psiClass, includeActions); + final Set pluginModuleResults = checkModule(module, isIdeaProject, psiClass, registrationType); if (pluginModuleResults != null) { return pluginModuleResults; } @@ -64,7 +73,7 @@ class RegistrationCheckerUtil { final List candidateModules = PluginModuleType.getCandidateModules(module); candidateModules.remove(module); // already checked for (Module m : candidateModules) { - Set types = checkModule(m, isIdeaProject, psiClass, includeActions); + Set types = checkModule(m, isIdeaProject, psiClass, registrationType); if (types != null) return types; } @@ -75,7 +84,7 @@ class RegistrationCheckerUtil { private static Set checkModule(Module module, boolean isIdeaProject, PsiClass psiClass, - boolean includeActions) { + RegistrationType registrationType) { List> pluginXmlCandidates = findPluginXmlFilesForModule(module, isIdeaProject); if (pluginXmlCandidates.isEmpty()) return null; @@ -88,7 +97,7 @@ class RegistrationCheckerUtil { for (DomFileElement pluginXml : pluginXmlCandidates) { // "main" plugin.xml - if (!processPluginXml(pluginXml, finder, includeActions)) return finder.getTypes(); + if (!processPluginXml(pluginXml, finder, registrationType)) return finder.getTypes(); if (isIdeaProject) continue; // pluginXmlCandidates == all candidates in module @@ -105,7 +114,7 @@ class RegistrationCheckerUtil { final DomFileElement dependentIdeaPlugin = DescriptorUtil.getIdeaPlugin(depPluginXml); if (dependentIdeaPlugin != null) { - if (!processPluginXml(dependentIdeaPlugin, finder, includeActions)) return finder.getTypes(); + if (!processPluginXml(dependentIdeaPlugin, finder, registrationType)) return finder.getTypes(); } } } @@ -131,23 +140,34 @@ class RegistrationCheckerUtil { private static boolean processPluginXml(DomFileElement pluginXml, RegistrationTypeFinder finder, - boolean includeActions) { + RegistrationType registrationType) { final IdeaPlugin rootElement = pluginXml.getRootElement(); - if (!ContainerUtil.process(rootElement.getApplicationComponents(), components -> - finder.processComponents(ComponentType.APPLICATION, components.getComponents()))) { - return false; - } - if (!ContainerUtil.process(rootElement.getProjectComponents(), components -> - finder.processComponents(ComponentType.PROJECT, components.getComponents()))) { - return false; - } - if (!ContainerUtil.process(rootElement.getModuleComponents(), components -> - finder.processComponents(ComponentType.MODULE, components.getComponents()))) { - return false; + final boolean findAll = registrationType == RegistrationType.ALL; + final boolean allComponents = findAll || registrationType == RegistrationType.ALL_COMPONENTS; + + if (allComponents || registrationType == RegistrationType.APPLICATION_COMPONENT) { + if (!ContainerUtil.process(rootElement.getApplicationComponents(), components -> + finder.processComponents(ComponentType.APPLICATION, components.getComponents()))) { + return false; + } } - if (includeActions) { + if (allComponents || registrationType == RegistrationType.PROJECT_COMPONENT) { + if (!ContainerUtil.process(rootElement.getProjectComponents(), components -> + finder.processComponents(ComponentType.PROJECT, components.getComponents()))) { + return false; + } + } + + if (allComponents || registrationType == RegistrationType.MODULE_COMPONENT) { + if (!ContainerUtil.process(rootElement.getModuleComponents(), components -> + finder.processComponents(ComponentType.MODULE, components.getComponents()))) { + return false; + } + } + + if (findAll || registrationType == RegistrationType.ACTION) { if (!ContainerUtil.process(rootElement.getActions(), actions -> finder.processActions(actions))) { return false; diff --git a/plugins/devkit/src/inspections/RegistrationProblemsInspection.java b/plugins/devkit/src/inspections/RegistrationProblemsInspection.java index b288812eb227..aba52942d4dc 100644 --- a/plugins/devkit/src/inspections/RegistrationProblemsInspection.java +++ b/plugins/devkit/src/inspections/RegistrationProblemsInspection.java @@ -115,7 +115,9 @@ public class RegistrationProblemsInspection extends DevKitInspectionBase { nameIdentifier != null && checkedClass.getQualifiedName() != null && checkedClass.getContainingFile().getVirtualFile() != null) { - final Set componentClasses = RegistrationCheckerUtil.getRegistrationTypes(checkedClass, CHECK_ACTIONS); + final RegistrationCheckerUtil.RegistrationType registrationType = + CHECK_ACTIONS ? RegistrationCheckerUtil.RegistrationType.ALL : RegistrationCheckerUtil.RegistrationType.ALL_COMPONENTS; + final Set componentClasses = RegistrationCheckerUtil.getRegistrationTypes(checkedClass, registrationType); if (componentClasses != null && !componentClasses.isEmpty()) { List problems = new SmartList<>();