IDEA-301750 Devkit: merge InspectionMappingConsistencyInspection into PluginXmlExtensionRegistrationInspection

GitOrigin-RevId: 9bf4efdb32d5460ae020843a0d1e69dac04de40d
This commit is contained in:
Yann Cébron
2022-09-15 17:04:07 +02:00
committed by intellij-monorepo-bot
parent 68d244216b
commit d870048b17
12 changed files with 82 additions and 183 deletions

View File

@@ -1,8 +0,0 @@
<html>
<body>
Reports problems for inspection extension point registration in <code>plugin.xml</code>.
<p>
Inspection (group) name must be defined using respective attributes for proper presentation in IDE.
</p>
</body>
</html>

View File

@@ -8,6 +8,7 @@ Reports problems with extension registration in <code>plugin.xml</code>.
If the extension does not target a specific language, use quick fix to create an
explicit declaration for "any language".
</li>
<li>Inspections: missing attributes</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>

View File

@@ -131,12 +131,6 @@
groupKey="inspections.group.name"
enabledByDefault="true" level="ERROR"
implementationClass="org.jetbrains.idea.devkit.inspections.RegistrationProblemsInspection"/>
<localInspection language="XML" shortName="InspectionMappingConsistency" applyToDialects="false"
groupPathKey="inspections.group.path" groupKey="inspections.group.descriptor"
enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.InspectionMappingConsistencyInspection"
key="inspection.inspection.mapping.consistency.display.name"/>
<localInspection language="UAST" shortName="UndesirableClassUsage"
groupPathKey="inspections.group.path" groupKey="inspections.group.code"

View File

@@ -283,7 +283,6 @@ invalid.order.attribute.part=Invalid ''order'' attribute value part: ''{0}'', mu
inspections.inspection.description.optional.short.name=Inspection does not have a description{0}
inspections.inspection.mapping.consistency.specify.bundle=Bundle should be specified
inspections.inspection.mapping.consistency.fix.insert.attribute=Insert ''{0}'' attribute
inspections.inspection.mapping.consistency.specify.displayName.or.key=displayName or key should be specified
inspections.inspection.mapping.consistency.specify.groupName.or.groupKey=groupName or groupKey should be specified
@@ -589,7 +588,6 @@ inspection.inspection.description.not.found.inspection.display.name=Inspection d
inspection.inspection.using.gray.colors.display.name=Using new Color(a,a,a)
inspection.inspection.unique.toolbar.id.display.name=Specify toolbar id
inspection.intention.description.not.found.inspection.display.name=Intention description checker
inspection.inspection.mapping.consistency.display.name=<inspection> tag consistency
inspection.undesirable.class.usage.display.name=Undesirable class usage
inspection.file.equals.usage.display.name=File.equals() usage
inspection.unsafe.vfs.recursion.display.name=Unsafe VFS recursion

View File

@@ -1,93 +0,0 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInsight.daemon.impl.analysis.InsertRequiredAttributeFix;
import com.intellij.codeInspection.InspectionEP;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomUtil;
import com.intellij.util.xml.highlighting.AddDomElementQuickFix;
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
import com.intellij.util.xml.highlighting.DomHighlightingHelper;
import org.jetbrains.annotations.NonNls;
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.IdeaPlugin;
/**
* @author Dmitry Avdeev
*/
public class InspectionMappingConsistencyInspection extends DevKitPluginXmlInspectionBase {
@Override
protected void checkDomElement(DomElement element, DomElementAnnotationHolder holder, DomHighlightingHelper helper) {
if (!(element instanceof Extension)) {
return;
}
ExtensionPoint extensionPoint = ((Extension)element).getExtensionPoint();
if (extensionPoint == null ||
!InheritanceUtil.isInheritor(extensionPoint.getBeanClass().getValue(), InspectionEP.class.getName())) {
return;
}
if (!hasMissingAttribute(element, "key")) {
if (hasMissingAttribute(element, "bundle")) {
checkDefaultBundle(element, holder);
}
}
else if (hasMissingAttribute(element, "displayName")) {
//noinspection DialogTitleCapitalization
registerProblem(element, holder,
DevKitBundle.message("inspections.inspection.mapping.consistency.specify.displayName.or.key"),
"displayName", "key");
}
if (!hasMissingAttribute(element, "groupKey")) {
if (hasMissingAttribute(element, "bundle") &&
hasMissingAttribute(element, "groupBundle")) {
checkDefaultBundle(element, holder);
}
}
else if (hasMissingAttribute(element, "groupName")) {
//noinspection DialogTitleCapitalization
registerProblem(element, holder,
DevKitBundle.message("inspections.inspection.mapping.consistency.specify.groupName.or.groupKey"),
"groupName", "groupKey");
}
}
private static void checkDefaultBundle(DomElement element, DomElementAnnotationHolder holder) {
IdeaPlugin plugin = DomUtil.getParentOfType(element, IdeaPlugin.class, true);
if (plugin != null && !DomUtil.hasXml(plugin.getResourceBundle())) {
holder.createProblem(element, DevKitBundle.message("inspections.inspection.mapping.consistency.specify.bundle"),
new AddDomElementQuickFix<>(plugin.getResourceBundle()));
}
}
private static void registerProblem(DomElement element, DomElementAnnotationHolder holder,
@InspectionMessage String message,
@NonNls String... createAttrs) {
if (holder.isOnTheFly()) {
holder.createProblem(element, message, ContainerUtil.map(createAttrs, attributeName -> {
final XmlTag tag = element.getXmlTag();
assert tag != null;
return new InsertRequiredAttributeFix(tag, attributeName) {
@NotNull
@Override
public String getText() {
return DevKitBundle.message("inspections.inspection.mapping.consistency.fix.insert.attribute", attributeName);
}
};
}, new LocalQuickFix[createAttrs.length]));
}
else {
holder.createProblem(element, message);
}
}
}

View File

@@ -3,8 +3,10 @@ package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInsight.intention.IntentionActionBean;
import com.intellij.codeInsight.intention.preview.IntentionPreviewUtils;
import com.intellij.codeInspection.InspectionEP;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.ide.util.PsiNavigationSupport;
import com.intellij.lang.LanguageExtensionPoint;
import com.intellij.openapi.project.Project;
@@ -13,18 +15,22 @@ import com.intellij.psi.impl.source.resolve.reference.PsiReferenceContributorEP;
import com.intellij.psi.stubs.StubElementTypeHolderEP;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomUtil;
import com.intellij.util.xml.GenericDomValue;
import com.intellij.util.xml.highlighting.AddDomElementQuickFix;
import com.intellij.util.xml.highlighting.DefineAttributeQuickFix;
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
import com.intellij.util.xml.highlighting.DomHighlightingHelper;
import com.intellij.util.xml.reflect.DomAttributeChildDescription;
import com.intellij.util.xml.reflect.DomFixedChildDescription;
import org.jetbrains.annotations.NonNls;
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.IdeaPlugin;
import org.jetbrains.idea.devkit.dom.impl.LanguageResolvingUtil;
public class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlInspectionBase {
@@ -51,6 +57,33 @@ public class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlIns
return;
}
if (InheritanceUtil.isInheritor(extensionPoint.getBeanClass().getValue(), InspectionEP.class.getName())) {
if (!hasMissingAttribute(element, "key")) {
if (hasMissingAttribute(element, "bundle")) {
checkDefaultBundle(element, holder);
}
}
else if (hasMissingAttribute(element, "displayName")) {
//noinspection DialogTitleCapitalization
registerDefineAttributeProblem(element, holder,
DevKitBundle.message("inspections.inspection.mapping.consistency.specify.displayName.or.key"),
"displayName", "key");
}
if (!hasMissingAttribute(element, "groupKey")) {
if (hasMissingAttribute(element, "bundle") &&
hasMissingAttribute(element, "groupBundle")) {
checkDefaultBundle(element, holder);
}
}
else if (hasMissingAttribute(element, "groupName")) {
//noinspection DialogTitleCapitalization
registerDefineAttributeProblem(element, holder,
DevKitBundle.message("inspections.inspection.mapping.consistency.specify.groupName.or.groupKey"),
"groupName", "groupKey");
}
}
if (isExtensionPointWithLanguage(extensionPoint)) {
DomAttributeChildDescription<?> languageAttributeDescription = extension.getGenericInfo().getAttributeChildDescription("language");
if (languageAttributeDescription != null) {
@@ -77,6 +110,27 @@ public class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlIns
}
}
private static void checkDefaultBundle(DomElement element, DomElementAnnotationHolder holder) {
IdeaPlugin plugin = DomUtil.getParentOfType(element, IdeaPlugin.class, true);
if (plugin != null && !DomUtil.hasXml(plugin.getResourceBundle())) {
holder.createProblem(element, DevKitBundle.message("inspections.inspection.mapping.consistency.specify.bundle"),
new AddDomElementQuickFix<>(plugin.getResourceBundle()));
}
}
private static void registerDefineAttributeProblem(DomElement element, DomElementAnnotationHolder holder,
@InspectionMessage String message,
@NonNls String... attributeNames) {
if (holder.isOnTheFly()) {
holder.createProblem(element, message, ContainerUtil.map(attributeNames, attributeName -> {
return new DefineAttributeQuickFix(attributeName);
}, new LocalQuickFix[attributeNames.length]));
}
else {
holder.createProblem(element, message);
}
}
private static boolean isExtensionPointWithLanguage(ExtensionPoint extensionPoint) {
final String extensionBeanClass = extensionPoint.getBeanClass().getStringValue();
return PsiReferenceContributorEP.class.getName().equals(extensionBeanClass) ||

View File

@@ -8,14 +8,14 @@
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<<warning descr="Bundle should be specified"><warning descr="groupName or groupKey should be specified">localInspection</warning></warning> key="<error descr="Cannot resolve property key">foo</error>"/>
<<warning descr="Bundle should be specified"><warning descr="displayName or key should be specified">localInspection</warning></warning> groupKey="<error descr="Cannot resolve property key">foo</error>"/>
<<warning descr="Bundle should be specified"><warning descr="groupName or groupKey should be specified">localInspection</warning></warning> key="<error descr="Cannot resolve property key">foo</error>" groupBundle="bundle"/>
<<warning descr="Bundle should be specified"><warning descr="groupName or groupKey should be specified">localInspection</warning></warning> key="<error descr="Cannot resolve property key">foo</error>" language="XML"/>
<<warning descr="Bundle should be specified"><warning descr="displayName or key should be specified">localInspection</warning></warning> groupKey="<error descr="Cannot resolve property key">foo</error>" language="XML"/>
<<warning descr="Bundle should be specified"><warning descr="groupName or groupKey should be specified">localInspection</warning></warning> key="<error descr="Cannot resolve property key">foo</error>" groupBundle="bundle" language="XML"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo" bundle="bundle"/>
<<warning descr="displayName or key should be specified">localInspection</warning> groupKey="foo" bundle="bundle"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo" bundle="bundle" language="XML"/>
<<warning descr="displayName or key should be specified">localInspection</warning> groupKey="foo" bundle="bundle" language="XML"/>
<localInspection key="foo" bundle="bundle" groupName="groupName"/>
<localInspection groupKey="foo" bundle="bundle" displayName="displayName"/>
<localInspection key="foo" bundle="bundle" groupName="groupName" language="XML"/>
<localInspection groupKey="foo" bundle="bundle" displayName="displayName" language="XML"/>
</extensions>
</idea-plugin>

View File

@@ -10,16 +10,16 @@
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="<error descr="Cannot resolve property key">INVALID_VALUE</error>"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo"/>
<<warning descr="displayName or key should be specified">localInspection</warning> groupKey="foo"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo" groupBundle="bundle"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="<error descr="Cannot resolve property key">INVALID_VALUE</error>" language="XML"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo" language="XML"/>
<<warning descr="displayName or key should be specified">localInspection</warning> groupKey="foo" language="XML"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo" groupBundle="bundle" language="XML"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo" bundle="bundle"/>
<<warning descr="displayName or key should be specified">localInspection</warning> groupKey="foo" bundle="bundle"/>
<<warning descr="groupName or groupKey should be specified">localInspection</warning> key="foo" bundle="bundle" language="XML"/>
<<warning descr="displayName or key should be specified">localInspection</warning> groupKey="foo" bundle="bundle" language="XML"/>
<localInspection key="foo" bundle="bundle" groupName="groupName"/>
<localInspection groupKey="foo" bundle="bundle" displayName="displayName"/>
<localInspection key="foo" bundle="bundle" groupName="groupName" language="XML"/>
<localInspection groupKey="foo" bundle="bundle" displayName="displayName" language="XML"/>
</extensions>
</idea-plugin>

View File

@@ -1,7 +1,7 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<localInspection id="withLanguage" language="XML"/>
<localInspection id="withLanguage" language="XML" displayName="dummy" groupName="dummy"/>
<intentionAction>
<language>XML</language>
</intentionAction>
@@ -9,7 +9,7 @@
<psi.referenceProvider language="XML"/>
<<warning descr="Extension 'com.intellij.localInspection' should define 'language' attribute">localInspection</warning> id="withoutLanguage"/>
<<warning descr="Extension 'com.intellij.localInspection' should define 'language' attribute">localInspection</warning> id="withoutLanguage" displayName="dummy" groupName="dummy"/>
<<warning descr="Extension 'com.intellij.intentionAction' should define 'language' tag">intentionAction</warning>>
</intentionAction>

View File

@@ -1,55 +0,0 @@
/*
* Copyright 2000-2014 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.
*/
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInspection.LocalInspectionEP;
import com.intellij.testFramework.TestDataPath;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import com.intellij.util.PathUtil;
import org.jetbrains.idea.devkit.DevkitJavaTestsUtil;
/**
* @author Dmitry Avdeev
*/
@TestDataPath("$CONTENT_ROOT/testData/inspections/inspectionMappingConsistency")
public class InspectionMappingConsistencyInspectionTest extends JavaCodeInsightFixtureTestCase {
public void testInspectionMappings() {
myFixture.testHighlighting("inspectionMapping.xml", "bundle.properties");
}
public void testInspectionMappingsWithDefaultBundle() {
myFixture.testHighlighting("inspectionMappingWithDefaultBundle.xml", "bundle.properties");
}
@Override
protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) {
String pathForClass = PathUtil.getJarPathForClass(LocalInspectionEP.class);
moduleBuilder.addLibrary("lang-api", pathForClass);
}
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(new InspectionMappingConsistencyInspection());
}
@Override
protected String getBasePath() {
return DevkitJavaTestsUtil.TESTDATA_PATH + "inspections/inspectionMappingConsistency";
}
}

View File

@@ -30,6 +30,7 @@ public class PluginXmlExtensionRegistrationInspectionTest extends JavaCodeInsigh
moduleBuilder.addLibrary("core-api", PathUtil.getJarPathForClass(StubElementTypeHolderEP.class));
moduleBuilder.addLibrary("core-impl", PathUtil.getJarPathForClass(PsiReferenceContributorEP.class));
moduleBuilder.addLibrary("analysis-api", PathUtil.getJarPathForClass(IntentionActionBean.class));
moduleBuilder.addLibrary("lang-api", PathUtil.getJarPathForClass(LocalInspectionEP.class));
moduleBuilder.addLibrary("platform-rt", PathUtil.getJarPathForClass(IncorrectOperationException.class));
moduleBuilder.addLibrary("platform-resources", Paths.get(PathUtil.getJarPathForClass(LocalInspectionEP.class))
.resolveSibling("intellij.platform.resources").toString());
@@ -63,9 +64,16 @@ public class PluginXmlExtensionRegistrationInspectionTest extends JavaCodeInsigh
myFixture.checkResultByFile("addLanguageAttributeForCompletionContributorEPFix_after.xml");
}
public void testStubElementTypeHolder() {
myFixture.testHighlighting("stubElementTypeHolder.xml");
}
public void testInspectionMappings() {
myFixture.testHighlighting("inspectionMapping.xml", "bundle.properties");
}
public void testInspectionMappingsWithDefaultBundle() {
myFixture.testHighlighting("inspectionMappingWithDefaultBundle.xml", "bundle.properties");
}
}