DevKit: cross-language ComponentNotRegisteredInspection + minor refactoring

This commit is contained in:
Yaroslav Pankratyev
2018-05-08 00:10:45 +07:00
parent 10084e7c98
commit f25fc66254
24 changed files with 378 additions and 219 deletions
@@ -71,7 +71,7 @@
<localInspection language="XML" shortName="PluginXmlValidity" displayName="Plugin.xml Validity" applyToDialects="false"
groupKey="inspections.group.name" enabledByDefault="true" level="ERROR"
implementationClass="org.jetbrains.idea.devkit.inspections.PluginXmlDomInspection"/>
<localInspection language="JAVA" shortName="ComponentNotRegistered"
<localInspection language="JVM" shortName="ComponentNotRegistered"
key="inspections.component.not.registered.name" groupKey="inspections.group.name" enabledByDefault="true"
level="WARNING" implementationClass="org.jetbrains.idea.devkit.inspections.ComponentNotRegisteredInspection"/>
<localInspection language="JAVA" shortName="InspectionDescriptionNotFoundInspection" displayName="Inspection Description Checker"
@@ -15,10 +15,10 @@
*/
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.jvm.DefaultJvmElementVisitor;
import com.intellij.lang.jvm.JvmClass;
import com.intellij.lang.jvm.JvmElementVisitor;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.components.BaseComponent;
import com.intellij.openapi.diagnostic.Logger;
@@ -48,10 +48,17 @@ import javax.swing.event.ChangeListener;
import java.util.Map;
import java.util.Set;
public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
public class ComponentNotRegisteredInspection extends DevKitJvmInspection {
public boolean CHECK_ACTIONS = true;
public boolean IGNORE_NON_PUBLIC = true;
private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.devkit.inspections.ComponentNotRegisteredInspection");
private static final Map<ComponentType, RegistrationCheckerUtil.RegistrationType> COMPONENT_TYPE_TO_REGISTRATION_TYPE =
ContainerUtil.<ComponentType, RegistrationCheckerUtil.RegistrationType>immutableMapBuilder()
.put(ComponentType.APPLICATION, RegistrationCheckerUtil.RegistrationType.APPLICATION_COMPONENT)
.put(ComponentType.PROJECT, RegistrationCheckerUtil.RegistrationType.PROJECT_COMPONENT)
.put(ComponentType.MODULE, RegistrationCheckerUtil.RegistrationType.MODULE_COMPONENT)
.build();
@Nullable
public JComponent createOptionsPanel() {
@@ -84,90 +91,87 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
}
@Nullable
public ProblemDescriptor[] checkClass(@NotNull PsiClass checkedClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
PsiIdentifier classIdentifier = checkedClass.getNameIdentifier();
if (classIdentifier != null &&
checkedClass.getQualifiedName() != null &&
checkedClass.getContainingFile().getVirtualFile() != null &&
!checkedClass.hasModifierProperty(PsiModifier.ABSTRACT) &&
!checkedClass.isEnum() &&
!PsiUtil.isInnerClass(checkedClass)) {
GlobalSearchScope scope = checkedClass.getResolveScope();
if (shouldCheckActionClass(checkedClass)) {
PsiClass actionClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(AnAction.class.getName(), scope);
if (actionClass == null) {
// stop if action class cannot be found (non-devkit module/project)
return null;
}
if (checkedClass.isInheritor(actionClass, true)) {
if (!isActionRegistered(checkedClass) && canFix(checkedClass)) {
LocalQuickFix fix = new RegisterActionFix(org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass));
ProblemDescriptor problem =
manager.createProblemDescriptor(classIdentifier,
DevKitBundle.message("inspections.component.not.registered.message",
DevKitBundle.message("new.menu.action.text")),
fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
return new ProblemDescriptor[]{problem};
}
// action IS registered, stop here
@Override
protected JvmElementVisitor<Boolean> buildVisitor(@NotNull Project project, @NotNull HighlightSink sink, boolean isOnTheFly) {
return new DefaultJvmElementVisitor<Boolean>() {
@Override
public Boolean visitClass(@NotNull JvmClass clazz) {
PsiElement sourceElement = clazz.getSourceElement();
if (!(sourceElement instanceof PsiClass)) {
return null;
}
checkClass(project, (PsiClass)sourceElement, sink);
return false;
}
PsiClass compClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(BaseComponent.class.getName(), scope);
if (compClass == null) {
// stop if component class cannot be found (non-devkit module/project)
return null;
}
if (!checkedClass.isInheritor(compClass, true)) {
return null;
}
for (ComponentType componentType : ComponentType.values()) {
if (!InheritanceUtil.isInheritor(checkedClass, componentType.myClassName)) {
continue;
}
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 final Map<ComponentType, RegistrationCheckerUtil.RegistrationType> COMPONENT_TYPE_TO_REGISTRATION_TYPE =
ContainerUtil.<ComponentType, RegistrationCheckerUtil.RegistrationType>immutableMapBuilder()
.put(ComponentType.APPLICATION, RegistrationCheckerUtil.RegistrationType.APPLICATION_COMPONENT)
.put(ComponentType.PROJECT, RegistrationCheckerUtil.RegistrationType.PROJECT_COMPONENT)
.put(ComponentType.MODULE, RegistrationCheckerUtil.RegistrationType.MODULE_COMPONENT)
.build();
private void checkClass(@NotNull Project project, @NotNull PsiClass checkedClass, @NotNull HighlightSink sink) {
if (checkedClass.getQualifiedName() == null ||
checkedClass.getContainingFile().getVirtualFile() == null ||
checkedClass.hasModifierProperty(PsiModifier.ABSTRACT) ||
checkedClass.isEnum() ||
PsiUtil.isInnerClass(checkedClass) ||
!shouldCheckActionClass(checkedClass)) {
return;
}
private static PsiClass findRegistrationType(@Nullable PsiClass checkedClass, RegistrationCheckerUtil.RegistrationType type) {
GlobalSearchScope scope = checkedClass.getResolveScope();
PsiClass actionClass = JavaPsiFacade.getInstance(project).findClass(AnAction.class.getName(), scope);
if (actionClass == null) {
// stop if action class cannot be found (non-devkit module/project)
return;
}
if (checkedClass.isInheritor(actionClass, true)) {
if (!isActionRegistered(checkedClass) && canFix(checkedClass)) {
LocalQuickFix fix = new RegisterActionFix(org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass));
sink.highlight(DevKitBundle.message("inspections.component.not.registered.message",
DevKitBundle.message("new.menu.action.text")), fix);
}
// action IS registered, stop here
return;
}
PsiClass compClass = JavaPsiFacade.getInstance(project).findClass(BaseComponent.class.getName(), scope);
if (compClass == null) {
// stop if component class cannot be found (non-devkit module/project)
return;
}
if (!checkedClass.isInheritor(compClass, true)) {
return;
}
for (ComponentType componentType : ComponentType.values()) {
if (!InheritanceUtil.isInheritor(checkedClass, componentType.myClassName)) {
continue;
}
if (findRegistrationType(checkedClass, COMPONENT_TYPE_TO_REGISTRATION_TYPE.get(componentType)) != null) {
return;
}
if (!canFix(checkedClass)) {
return;
}
LocalQuickFix fix = new RegisterComponentFix(componentType, org.jetbrains.idea.devkit.util.PsiUtil.createPointer(checkedClass));
sink.highlight(DevKitBundle.message("inspections.component.not.registered.message",
DevKitBundle.message(componentType.myPropertyKey)), fix);
}
}
private static PsiClass findRegistrationType(@NotNull PsiClass checkedClass, @NotNull RegistrationCheckerUtil.RegistrationType type) {
final Set<PsiClass> types = RegistrationCheckerUtil.getRegistrationTypes(checkedClass, type);
return ContainerUtil.getFirstItem(types);
}
private boolean shouldCheckActionClass(PsiClass psiClass) {
private boolean shouldCheckActionClass(@NotNull PsiClass psiClass) {
if (!CHECK_ACTIONS) return false;
if (IGNORE_NON_PUBLIC && !psiClass.hasModifierProperty(PsiModifier.PUBLIC)) return false;
return true;
}
private static boolean isActionRegistered(PsiClass actionClass) {
private static boolean isActionRegistered(@NotNull PsiClass actionClass) {
final PsiClass registrationType = findRegistrationType(actionClass, RegistrationCheckerUtil.RegistrationType.ACTION);
if (registrationType != null) {
return true;
@@ -197,7 +201,7 @@ public class ComponentNotRegisteredInspection extends DevKitInspectionBase {
return false;
}
private static boolean canFix(PsiClass psiClass) {
private static boolean canFix(@NotNull PsiClass psiClass) {
Project project = psiClass.getProject();
PsiFile psiFile = psiClass.getContainingFile();
LOG.assertTrue(psiFile != null);
@@ -15,159 +15,18 @@
*/
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.DevkitJavaTestsUtil;
import org.jetbrains.idea.devkit.dom.Anchor;
import org.jetbrains.idea.devkit.inspections.quickfix.RegisterActionFix;
import org.jetbrains.idea.devkit.util.ActionData;
import org.jetbrains.idea.devkit.util.PsiUtil;
@TestDataPath("$CONTENT_ROOT/testData/inspections/componentNotRegistered")
public class ComponentNotRegisteredInspectionTest extends PluginModuleTestCase {
public class ComponentNotRegisteredInspectionTest extends ComponentNotRegisteredInspectionTestBase {
@Override
protected String getBasePath() {
return DevkitJavaTestsUtil.TESTDATA_PATH + "inspections/componentNotRegistered";
}
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.addClass("package com.intellij.openapi.actionSystem; public class AnAction {}");
myFixture.addClass("package com.intellij.openapi.components; public interface BaseComponent {}");
myFixture.addClass("package com.intellij.openapi.components; public interface ApplicationComponent extends BaseComponent {}");
myFixture.enableInspections(new ComponentNotRegisteredInspection());
}
public void testRegisteredAction() {
setPluginXml("registeredAction-plugin.xml");
myFixture.testHighlighting("RegisteredAction.java");
}
public void testRegisteredActionInIDEAProject() {
PsiUtil.markAsIdeaProject(getProject(), true);
try {
myFixture.copyFileToProject("registeredAction-plugin.xml", "someOtherPluginXmlName.xml");
myFixture.testHighlighting("RegisteredAction.java");
}
finally {
PsiUtil.markAsIdeaProject(getProject(), false);
}
}
public void testRegisteredActionInOptionalPluginDescriptor() {
setPluginXml("registeredActionInOptionalPluginDescriptor-plugin.xml");
myFixture.copyFileToProject("registeredActionInOptionalPluginDescriptor-optional-plugin.xml",
"META-INF/optional-plugin.xml");
myFixture.testHighlighting("RegisteredAction.java");
}
public void testRegisteredInIncludedFileAction() {
setPluginXml("ActionXInclude.xml");
myFixture.copyFileToProject("ActionXInclude_included.xml", "META-INF/ActionXInclude_included.xml");
myFixture.testHighlighting("ActionXInclude.java");
}
public void testUnregisteredAction() {
setPluginXml("unregisteredAction-plugin.xml");
myFixture.testHighlighting("UnregisteredAction.java");
RegisterActionFix.ourTestActionData = new MyActionData("UnregisteredAction");
final IntentionAction registerAction = myFixture.findSingleIntention("Register Action");
myFixture.launchAction(registerAction);
myFixture.checkResultByFile("META-INF/plugin.xml", "unregisteredAction-plugin_after.xml", true);
}
public void testUnregisteredActionUsedViaConstructor() {
myFixture.testHighlighting("UnregisteredActionUsedViaConstructor.java");
}
public void testRegisteredApplicationComponent() {
setPluginXml("registeredApplicationComponent-plugin.xml");
myFixture.testHighlighting("RegisteredApplicationComponent.java");
}
public void testUnregisteredAbstractApplicationComponent() {
myFixture.testHighlighting("UnregisteredAbstractApplicationComponent.java");
}
public void testUnregisteredApplicationComponentWithoutPluginXml() {
myFixture.testHighlighting("UnregisteredApplicationComponent.java",
"UnregisteredApplicationComponentInterface.java");
}
public void testUnregisteredApplicationComponentWithRegisterFix() {
setPluginXml("unregisteredApplicationComponent-plugin.xml");
myFixture.testHighlighting("UnregisteredApplicationComponent.java",
"UnregisteredApplicationComponentInterface.java");
final IntentionAction registerAction = myFixture.findSingleIntention("Register Application Component");
myFixture.launchAction(registerAction);
myFixture.checkResultByFile("META-INF/plugin.xml", "unregisteredApplicationComponent-plugin_after.xml", true);
}
private static class MyActionData implements ActionData {
private final String myActionClassFqn;
public MyActionData(String actionClassFqn) {
myActionClassFqn = actionClassFqn;
}
@NotNull
@Override
public String getActionId() {
return StringUtil.getShortName(myActionClassFqn);
}
@NotNull
@Override
public String getActionText() {
return "Action Text " + myActionClassFqn;
}
@Override
public String getActionDescription() {
return "Description " + myActionClassFqn;
}
@Nullable
@Override
public String getSelectedGroupId() {
return getActionId() + "Group";
}
@Nullable
@Override
public String getSelectedActionId() {
return getActionId() + "SelectedAction";
}
@Override
public String getSelectedAnchor() {
return Anchor.before.name();
}
@Nullable
@Override
public String getFirstKeyStroke() {
return "1st Key " + getActionId();
}
@Nullable
@Override
public String getSecondKeyStroke() {
return "2nd Key " + getActionId();
}
protected String getSourceFileExtension() {
return "java";
}
}
@@ -0,0 +1 @@
class ActionXInclude : com.intellij.openapi.actionSystem.AnAction()
@@ -0,0 +1,3 @@
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="/META-INF/ActionXInclude_included.xml" xpointer="xpointer(/idea-plugin/*)"/>
</idea-plugin>
@@ -0,0 +1,5 @@
<idea-plugin>
<actions>
<action id="smth" class="ActionXInclude"/>
</actions>
</idea-plugin>
@@ -0,0 +1,7 @@
import com.intellij.openapi.actionSystem.AnAction
class RegisteredAction : AnAction() {
class InnerAction : AnAction()
}
@@ -0,0 +1,6 @@
import com.intellij.openapi.components.ApplicationComponent
class RegisteredApplicationComponent : ApplicationComponent {
class InnerStaticClassApplicationContext : ApplicationComponent
}
@@ -0,0 +1,3 @@
import com.intellij.openapi.components.ApplicationComponent
abstract class UnregisteredAbstractApplicationComponent : ApplicationComponent
@@ -0,0 +1,7 @@
import com.intellij.openapi.actionSystem.AnAction
class <warning descr="Action is not registered in plugin.xml">Unregistered<caret>Action</warning> : AnAction() {
class <warning descr="Action is not registered in plugin.xml">InnerAction</warning> : AnAction()
protected class NonPublicIsIgnored : AnAction()
}
@@ -0,0 +1,9 @@
@file:Suppress("UNUSED_VARIABLE")
import com.intellij.openapi.actionSystem.AnAction
class UnregisteredActionUsedViaConstructor : AnAction()
fun main(args: Array<String>) {
val mine = UnregisteredActionUsedViaConstructor()
}
@@ -0,0 +1,12 @@
import com.intellij.openapi.components.ApplicationComponent
class <warning descr="Application Component is not registered in plugin.xml">Unregistered<caret>ApplicationComponent</warning>
: ApplicationComponent, UnregisteredApplicationComponentInterface {
class <warning descr="Application Component is not registered in plugin.xml">InnerStaticClassApplicationContext</warning>
: ApplicationComponent
inner class InnerClassApplicationContextIsNotChecked : ApplicationComponent
fun getInstance() : UnregisteredApplicationComponentInterface? = null
}
@@ -0,0 +1 @@
interface UnregisteredApplicationComponentInterface
@@ -0,0 +1,10 @@
<idea-plugin>
<actions>
<action id="registeredAction" class="RegisteredAction"/>
<group id="group">
<group id="nestedGroup">
<action id="registeredInnerAction" class="RegisteredAction$InnerAction"/>
</group>
</group>
</actions>
</idea-plugin>
@@ -0,0 +1,6 @@
<idea-plugin>
<actions>
<action id="registeredAction" class="RegisteredAction"/>
<action id="registeredInnerAction" class="RegisteredAction.InnerAction"/>
</actions>
</idea-plugin>
@@ -0,0 +1,5 @@
<idea-plugin>
<!-- registeredActionInOptionalPluginDescriptor-optional-plugin.xml -->
<depends optional="true" config-file="optional-plugin.xml"/>
<depends optional="true" config-file="optional-plugin.xml"/>
</idea-plugin>
@@ -0,0 +1,11 @@
<idea-plugin>
<application-components>
<component>
<implementation-class>RegisteredApplicationComponent</implementation-class>
</component>
<component>
<implementation-class>RegisteredApplicationComponent$InnerStaticClassApplicationContext</implementation-class>
</component>
</application-components>
</idea-plugin>
@@ -0,0 +1,11 @@
<idea-plugin>
<actions>
<action id="UnregisteredAction" class="UnregisteredAction" text="Action Text UnregisteredAction"
description="Description UnregisteredAction">
<add-to-group group-id="UnregisteredActionGroup" anchor="before"
relative-to-action="UnregisteredActionSelectedAction"/>
<keyboard-shortcut keymap="$default" first-keystroke="1st Key UnregisteredAction"
second-keystroke="2nd Key UnregisteredAction"/>
</action>
</actions>
</idea-plugin>
@@ -0,0 +1,9 @@
<idea-plugin>
<application-components>
<component>
<implementation-class>UnregisteredApplicationComponent</implementation-class>
<interface-class>UnregisteredApplicationComponentInterface</interface-class>
</component>
</application-components>
</idea-plugin>
@@ -0,0 +1,27 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.devkit.kotlin.inspections;
import com.intellij.testFramework.TestDataPath;
import kotlin.KotlinVersion;
import org.jetbrains.idea.devkit.inspections.ComponentNotRegisteredInspectionTestBase;
import org.jetbrains.idea.devkit.kotlin.DevkitKtTestsUtil;
import org.junit.Assume;
@TestDataPath("$CONTENT_ROOT/testData/inspections/componentNotRegistered")
public class KtComponentNotRegisteredInspectionTest extends ComponentNotRegisteredInspectionTestBase {
@Override
protected void setUp() throws Exception {
super.setUp();
Assume.assumeTrue(KotlinVersion.CURRENT.isAtLeast(1, 2, 50));
}
@Override
protected String getSourceFileExtension() {
return "kt";
}
@Override
protected String getBasePath() {
return DevkitKtTestsUtil.TESTDATA_PATH + "inspections/componentNotRegistered";
}
}
@@ -0,0 +1,158 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.dom.Anchor;
import org.jetbrains.idea.devkit.inspections.quickfix.RegisterActionFix;
import org.jetbrains.idea.devkit.util.ActionData;
import org.jetbrains.idea.devkit.util.PsiUtil;
public abstract class ComponentNotRegisteredInspectionTestBase extends PluginModuleTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.addClass("package com.intellij.openapi.actionSystem; public class AnAction {}");
myFixture.addClass("package com.intellij.openapi.components; public interface BaseComponent {}");
myFixture.addClass("package com.intellij.openapi.components; public interface ApplicationComponent extends BaseComponent {}");
myFixture.enableInspections(new ComponentNotRegisteredInspection());
}
protected abstract String getSourceFileExtension();
public void testRegisteredAction() {
setPluginXml("registeredAction-plugin.xml");
myFixture.testHighlighting("RegisteredAction." + getSourceFileExtension());
}
public void testRegisteredActionInIDEAProject() {
PsiUtil.markAsIdeaProject(getProject(), true);
try {
myFixture.copyFileToProject("registeredAction-plugin.xml", "someOtherPluginXmlName.xml");
myFixture.testHighlighting("RegisteredAction." + getSourceFileExtension());
}
finally {
PsiUtil.markAsIdeaProject(getProject(), false);
}
}
public void testRegisteredActionInOptionalPluginDescriptor() {
setPluginXml("registeredActionInOptionalPluginDescriptor-plugin.xml");
myFixture.copyFileToProject("registeredActionInOptionalPluginDescriptor-optional-plugin.xml",
"META-INF/optional-plugin.xml");
myFixture.testHighlighting("RegisteredAction." + getSourceFileExtension());
}
public void testRegisteredInIncludedFileAction() {
setPluginXml("ActionXInclude.xml");
myFixture.copyFileToProject("ActionXInclude_included.xml", "META-INF/ActionXInclude_included.xml");
myFixture.testHighlighting("ActionXInclude." + getSourceFileExtension());
}
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
public void testUnregisteredAction() {
setPluginXml("unregisteredAction-plugin.xml");
myFixture.testHighlighting("UnregisteredAction." + getSourceFileExtension());
RegisterActionFix.ourTestActionData = new MyActionData("UnregisteredAction");
try {
final IntentionAction registerAction = myFixture.findSingleIntention("Register Action");
myFixture.launchAction(registerAction);
myFixture.checkResultByFile("META-INF/plugin.xml", "unregisteredAction-plugin_after.xml", true);
} finally {
RegisterActionFix.ourTestActionData = null;
}
}
public void testUnregisteredActionUsedViaConstructor() {
myFixture.testHighlighting("UnregisteredActionUsedViaConstructor." + getSourceFileExtension());
}
public void testRegisteredApplicationComponent() {
setPluginXml("registeredApplicationComponent-plugin.xml");
myFixture.testHighlighting("RegisteredApplicationComponent." + getSourceFileExtension());
}
public void testUnregisteredAbstractApplicationComponent() {
myFixture.testHighlighting("UnregisteredAbstractApplicationComponent." + getSourceFileExtension());
}
public void testUnregisteredApplicationComponentWithoutPluginXml() {
myFixture.testHighlighting("UnregisteredApplicationComponent." + getSourceFileExtension(),
"UnregisteredApplicationComponentInterface." + getSourceFileExtension());
}
public void testUnregisteredApplicationComponentWithRegisterFix() {
setPluginXml("unregisteredApplicationComponent-plugin.xml");
myFixture.testHighlighting("UnregisteredApplicationComponent." + getSourceFileExtension(),
"UnregisteredApplicationComponentInterface." + getSourceFileExtension());
final IntentionAction registerAction = myFixture.findSingleIntention("Register Application Component");
myFixture.launchAction(registerAction);
myFixture.checkResultByFile("META-INF/plugin.xml", "unregisteredApplicationComponent-plugin_after.xml", true);
}
public static class MyActionData implements ActionData {
private final String myActionClassFqn;
public MyActionData(String actionClassFqn) {
myActionClassFqn = actionClassFqn;
}
@NotNull
@Override
public String getActionId() {
return StringUtil.getShortName(myActionClassFqn);
}
@NotNull
@Override
public String getActionText() {
return "Action Text " + myActionClassFqn;
}
@Override
public String getActionDescription() {
return "Description " + myActionClassFqn;
}
@Nullable
@Override
public String getSelectedGroupId() {
return getActionId() + "Group";
}
@Nullable
@Override
public String getSelectedActionId() {
return getActionId() + "SelectedAction";
}
@Override
public String getSelectedAnchor() {
return Anchor.before.name();
}
@Nullable
@Override
public String getFirstKeyStroke() {
return "1st Key " + getActionId();
}
@Nullable
@Override
public String getSecondKeyStroke() {
return "2nd Key " + getActionId();
}
}
}