mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
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
This commit is contained in:
committed by
intellij-monorepo-bot
parent
181c26a8b8
commit
241ea1120e
+9
-6
@@ -3,12 +3,15 @@
|
||||
Reports problems with extension registration in <code>plugin.xml</code>.
|
||||
<p>
|
||||
The following problems are reported:
|
||||
<ul>
|
||||
<li>Missing <code>language</code> declaration.
|
||||
If the extension does not target a specific language, specify
|
||||
<code>language=""</code> or <code><language></language></code> explicitly for "any language".</li>
|
||||
<li><code>com.intellij.stubElementTypeHolder</code> without <code>externalIdPrefix</code>, see <a href='https://plugins.jetbrains.com/docs/intellij/stub-indexes.html?from=?from=DevkitPluginXmlInspectionDescription'>Stub Indexes</a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Missing <code>language</code> declaration.
|
||||
If the extension does not target a specific language, use quick fix to create an
|
||||
explicit declaration for "any language".
|
||||
</li>
|
||||
<li><code>com.intellij.stubElementTypeHolder</code> without <code>externalIdPrefix</code>, see <a
|
||||
href='https://plugins.jetbrains.com/docs/intellij/stub-indexes.html?from=?from=DevkitPluginXmlInspectionDescription'>Stub Indexes</a>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><small>New in 2022.3</small>
|
||||
</body>
|
||||
|
||||
@@ -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<LanguageDefinition> 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<PsiClass> epBeanClass = extensionPoint.getBeanClass();
|
||||
if (EP_WITH_ANY_LANGUAGE_ID.contains(epBeanClass.getStringValue())) {
|
||||
return "any";
|
||||
|
||||
+32
-22
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<idea-plugin>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<completion.<caret>contributor />
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<idea-plugin>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<completion.contributor language="<caret>any"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+11
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user