From 241ea1120e6b560e2a1f54f1de0a230cc17aff56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Wed, 14 Sep 2022 11:32:45 +0200 Subject: [PATCH] IDEA-297798 DevKit: new inspection to highlight missing "language" declaration in extension point registration, use exceptions for "any language" value for select EPs GitOrigin-RevId: 88cf39c413f79b9c5df5779ab7793f0504b3af36 --- .../PluginXmlExtensionRegistration.html | 15 +++--- .../src/dom/impl/LanguageResolvingUtil.java | 10 +++- ...ginXmlExtensionRegistrationInspection.java | 54 +++++++++++-------- ...AttributeForCompletionContributorEPFix.xml | 6 +++ ...uteForCompletionContributorEPFix_after.xml | 6 +++ ...mlExtensionRegistrationInspectionTest.java | 11 ++++ .../highlighting/DefineAttributeQuickFix.java | 26 ++++----- 7 files changed, 82 insertions(+), 46 deletions(-) create mode 100644 plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix.xml create mode 100644 plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix_after.xml diff --git a/plugins/devkit/devkit-core/resources/inspectionDescriptions/PluginXmlExtensionRegistration.html b/plugins/devkit/devkit-core/resources/inspectionDescriptions/PluginXmlExtensionRegistration.html index 818caa09a529..28dacf9eaa1b 100644 --- a/plugins/devkit/devkit-core/resources/inspectionDescriptions/PluginXmlExtensionRegistration.html +++ b/plugins/devkit/devkit-core/resources/inspectionDescriptions/PluginXmlExtensionRegistration.html @@ -3,12 +3,15 @@ Reports problems with extension registration in plugin.xml.

The following problems are reported: -

+

New in 2022.3 diff --git a/plugins/devkit/devkit-core/src/dom/impl/LanguageResolvingUtil.java b/plugins/devkit/devkit-core/src/dom/impl/LanguageResolvingUtil.java index 8844e7971071..84d0cc292fb5 100644 --- a/plugins/devkit/devkit-core/src/dom/impl/LanguageResolvingUtil.java +++ b/plugins/devkit/devkit-core/src/dom/impl/LanguageResolvingUtil.java @@ -43,7 +43,7 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.StreamSupport; -final class LanguageResolvingUtil { +public final class LanguageResolvingUtil { private static final String ANY_LANGUAGE_DEFAULT_ID = Language.ANY.getID(); static Collection getAllLanguageDefinitions(ConvertContext context) { @@ -333,6 +333,14 @@ final class LanguageResolvingUtil { return ANY_LANGUAGE_DEFAULT_ID; } + return getAnyLanguageValue(extensionPoint); + } + + /** + * @return value for "any language" for given EP {@code language} declaration, with few exceptions it's always {@link Language#ANY} ID. + */ + @NotNull + public static String getAnyLanguageValue(ExtensionPoint extensionPoint) { final GenericAttributeValue epBeanClass = extensionPoint.getBeanClass(); if (EP_WITH_ANY_LANGUAGE_ID.contains(epBeanClass.getStringValue())) { return "any"; diff --git a/plugins/devkit/devkit-core/src/inspections/PluginXmlExtensionRegistrationInspection.java b/plugins/devkit/devkit-core/src/inspections/PluginXmlExtensionRegistrationInspection.java index 30bc2b222fdb..ae71b8e69dbd 100644 --- a/plugins/devkit/devkit-core/src/inspections/PluginXmlExtensionRegistrationInspection.java +++ b/plugins/devkit/devkit-core/src/inspections/PluginXmlExtensionRegistrationInspection.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.devkit.DevKitBundle; import org.jetbrains.idea.devkit.dom.Extension; import org.jetbrains.idea.devkit.dom.ExtensionPoint; +import org.jetbrains.idea.devkit.dom.impl.LanguageResolvingUtil; public class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlInspectionBase { @@ -59,7 +60,7 @@ public class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlIns holder.createProblem(extension, DevKitBundle.message("inspection.plugin.xml.extension.registration.should.define.language.attribute", extensionPoint.getEffectiveQualifiedName()), - new DefineAttributeQuickFix("language")); + new DefineAttributeQuickFix("language", "", LanguageResolvingUtil.getAnyLanguageValue(extensionPoint))); } return; } @@ -72,27 +73,7 @@ public class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlIns holder.createProblem(extension, DevKitBundle.message("inspection.plugin.xml.extension.registration.should.define.language.tag", extensionPoint.getEffectiveQualifiedName()), - new LocalQuickFix() { - @Override - public @NotNull String getFamilyName() { - return DevKitBundle.message("inspection.plugin.xml.extension.registration.should.define.language.tag.family.name"); - } - - @Override - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - Extension fixExtension = DomUtil.findDomElement(descriptor.getPsiElement(), Extension.class, false); - if (fixExtension == null) return; - - XmlTag xmlTag = fixExtension.getXmlTag(); - XmlTag languageTag = xmlTag.createChildTag("language", null, "", false); - XmlTag addedLanguageTag = xmlTag.addSubTag(languageTag, true); - if (!IntentionPreviewUtils.isPreviewElement(addedLanguageTag)) { - PsiNavigationSupport.getInstance() - .createNavigatable(project, addedLanguageTag.getContainingFile().getVirtualFile(), - addedLanguageTag.getValue().getTextRange().getEndOffset()).navigate(true); - } - } - }); + new AddLanguageTagQuickFix(LanguageResolvingUtil.getAnyLanguageValue(extensionPoint))); } } } @@ -105,4 +86,33 @@ public class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlIns IntentionActionBean.class.getName().equals(extensionBeanClass) || InheritanceUtil.isInheritor(extensionPoint.getBeanClass().getValue(), LanguageExtensionPoint.class.getName()); } + + private static class AddLanguageTagQuickFix implements LocalQuickFix { + + private final String myAnyLanguageID; + + private AddLanguageTagQuickFix(String anyLanguageId) { + myAnyLanguageID = anyLanguageId; + } + + @Override + public @NotNull String getFamilyName() { + return DevKitBundle.message("inspection.plugin.xml.extension.registration.should.define.language.tag.family.name"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + Extension fixExtension = DomUtil.findDomElement(descriptor.getPsiElement(), Extension.class, false); + if (fixExtension == null) return; + + XmlTag xmlTag = fixExtension.getXmlTag(); + XmlTag languageTag = xmlTag.createChildTag("language", null, myAnyLanguageID, false); + XmlTag addedLanguageTag = xmlTag.addSubTag(languageTag, true); + if (!IntentionPreviewUtils.isPreviewElement(addedLanguageTag)) { + PsiNavigationSupport.getInstance() + .createNavigatable(project, addedLanguageTag.getContainingFile().getVirtualFile(), + addedLanguageTag.getValue().getTextRange().getEndOffset()).navigate(true); + } + } + } } diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix.xml b/plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix.xml new file mode 100644 index 000000000000..1b4d0dfe2aeb --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix.xml @@ -0,0 +1,6 @@ + + + + contributor /> + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix_after.xml b/plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix_after.xml new file mode 100644 index 000000000000..7622c53afdd9 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/pluginXmlExtensionRegistration/addLanguageAttributeForCompletionContributorEPFix_after.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/PluginXmlExtensionRegistrationInspectionTest.java b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/PluginXmlExtensionRegistrationInspectionTest.java index 319bd87cc660..ee970d1aad5d 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/PluginXmlExtensionRegistrationInspectionTest.java +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/PluginXmlExtensionRegistrationInspectionTest.java @@ -54,6 +54,17 @@ public class PluginXmlExtensionRegistrationInspectionTest extends JavaCodeInsigh myFixture.checkResultByFile("languageAddLanguageTagFix_after.xml"); } + public void testLanguageAddLanguageAttributeForCompletionContributorEPFix() { + IntentionAction action = + myFixture.getAvailableIntention("Define language attribute", + "addLanguageAttributeForCompletionContributorEPFix.xml"); + assertNotNull(action); + myFixture.checkPreviewAndLaunchAction(action); + myFixture.checkResultByFile("addLanguageAttributeForCompletionContributorEPFix_after.xml"); + } + + + public void testStubElementTypeHolder() { myFixture.testHighlighting("stubElementTypeHolder.xml"); } diff --git a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DefineAttributeQuickFix.java b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DefineAttributeQuickFix.java index 74b3c9c568db..d7a68ae73483 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DefineAttributeQuickFix.java +++ b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DefineAttributeQuickFix.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.util.xml.highlighting; import com.intellij.codeInspection.LocalQuickFix; @@ -30,15 +16,21 @@ import org.jetbrains.annotations.NotNull; */ public class DefineAttributeQuickFix implements LocalQuickFix { private final String myAttrName; + private final String myAttrValue; private final String myNamespace; public DefineAttributeQuickFix(String attrName) { - this(attrName, ""); + this(attrName, "", ""); } public DefineAttributeQuickFix(@NotNull final String attrName, @NotNull String namespace) { + this(attrName, namespace, ""); + } + + public DefineAttributeQuickFix(@NotNull final String attrName, @NotNull String namespace, @NotNull String attrValue) { myAttrName = attrName; myNamespace = namespace; + myAttrValue = attrValue; } @Override @@ -56,7 +48,7 @@ public class DefineAttributeQuickFix implements LocalQuickFix { @Override public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { XmlTag tag = (XmlTag)descriptor.getPsiElement(); - XmlAttribute attribute = tag.setAttribute(myAttrName, myNamespace.equals(tag.getNamespace())? "": myNamespace, ""); + XmlAttribute attribute = tag.setAttribute(myAttrName, myNamespace.equals(tag.getNamespace()) ? "" : myNamespace, myAttrValue); VirtualFile virtualFile = tag.getContainingFile().getVirtualFile(); if (virtualFile != null) { PsiNavigationSupport.getInstance().createNavigatable(project, virtualFile,