From 77435029e97f0750ccf8a95e429cb31360781199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Thu, 15 Jun 2023 16:13:02 +0200 Subject: [PATCH] IDEA-322654 Devkit: Inspection description checker inspection - support IntentionAction with skipBeforeAfter=true GitOrigin-RevId: 36ca4e229fa8a789969f300aa77921e2c6f1341a --- .../DescriptionNotFoundInspectionBase.java | 7 +++- ...ntentionDescriptionNotFoundInspection.java | 36 ++++++++++++++----- .../MyIntentionActionOptionalBeforeAfter.java | 14 ++++++++ .../description.html | 1 + .../resources/META-INF/plugin.xml | 4 +++ ...tionDescriptionNotFoundInspectionTest.java | 8 +++-- 6 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/MyIntentionActionOptionalBeforeAfter.java create mode 100644 plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/intentionDescriptions/MyIntentionActionOptionalBeforeAfter/description.html diff --git a/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java b/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java index 218c3f7a75f2..a56bba72bdc7 100644 --- a/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java +++ b/plugins/devkit/devkit-core/src/inspections/DescriptionNotFoundInspectionBase.java @@ -62,6 +62,10 @@ abstract class DescriptionNotFoundInspectionBase extends DevKitUastInspectionBas protected abstract boolean skipIfNotRegistered(PsiClass epClass); + protected boolean skipOptionalBeforeAfter(PsiClass epClass) { + return false; + } + protected boolean checkDynamicDescription(ProblemsHolder holder, Module module, PsiClass psiClass) { throw new IllegalStateException("must be implemented for " + getClass()); } @@ -81,7 +85,8 @@ abstract class DescriptionNotFoundInspectionBase extends DevKitUastInspectionBas final PsiFile descr = dir.findFile("description.html"); if (descr == null) continue; - if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) { + if (!hasBeforeAndAfterTemplate(dir.getVirtualFile()) && + !skipOptionalBeforeAfter(psiClass)) { ProblemHolderUtilKt.registerUProblem(holder, uClass, getHasNotBeforeAfterError()); } return true; diff --git a/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java b/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java index 761938752bd5..980607fcd6da 100644 --- a/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java +++ b/plugins/devkit/devkit-core/src/inspections/IntentionDescriptionNotFoundInspection.java @@ -1,19 +1,21 @@ -// Copyright 2000-2020 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. +// Copyright 2000-2023 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.openapi.module.Module; import com.intellij.psi.PsiClass; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.xml.DomElement; +import com.intellij.util.xml.DomManager; +import com.intellij.util.xml.GenericDomValue; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.dom.Extension; +import org.jetbrains.idea.devkit.util.DevKitDomUtil; import org.jetbrains.idea.devkit.util.ExtensionCandidate; import org.jetbrains.idea.devkit.util.ExtensionLocatorKt; -import java.util.List; - -/** - * @author Konstantin Bulenkov - */ -public class IntentionDescriptionNotFoundInspection extends DescriptionNotFoundInspectionBase { +public final class IntentionDescriptionNotFoundInspection extends DescriptionNotFoundInspectionBase { public IntentionDescriptionNotFoundInspection() { super(DescriptionType.INTENTION); @@ -21,8 +23,19 @@ public class IntentionDescriptionNotFoundInspection extends DescriptionNotFoundI @Override protected boolean skipIfNotRegistered(PsiClass epClass) { - final List registrations = ExtensionLocatorKt.locateExtensionsByPsiClass(epClass); - return registrations.isEmpty(); + return findCandidate(epClass) == null; + } + + @Override + protected boolean skipOptionalBeforeAfter(PsiClass epClass) { + ExtensionCandidate candidate = findCandidate(epClass); + assert candidate != null; + DomElement domElement = DomManager.getDomManager(epClass.getProject()).getDomElement(candidate.pointer.getElement()); + if (!(domElement instanceof Extension)) return false; + + @SuppressWarnings("unchecked") GenericDomValue skipBeforeAfterValue = + (GenericDomValue)DevKitDomUtil.getTag(domElement, "skipBeforeAfter"); + return skipBeforeAfterValue != null && Boolean.TRUE.equals(skipBeforeAfterValue.getValue()); } @Override @@ -36,4 +49,9 @@ public class IntentionDescriptionNotFoundInspection extends DescriptionNotFoundI protected String getHasNotBeforeAfterError() { return DevKitBundle.message("inspections.intention.description.no.before.after.template"); } + + @Nullable + private static ExtensionCandidate findCandidate(PsiClass epClass) { + return ContainerUtil.getOnlyItem(ExtensionLocatorKt.locateExtensionsByPsiClass(epClass)); + } } diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/MyIntentionActionOptionalBeforeAfter.java b/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/MyIntentionActionOptionalBeforeAfter.java new file mode 100644 index 000000000000..56f050b2e0c0 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/MyIntentionActionOptionalBeforeAfter.java @@ -0,0 +1,14 @@ +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Iconable; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; + +class MyIntentionActionOptionalBeforeAfter implements com.intellij.codeInsight.intention.IntentionAction { + + public String getText() { return"text"; } + public String getFamilyName() { return"familyName"; } + public boolean isAvailable(Project project,Editor editor,PsiFile file) {return true; } + public void invoke(Project project,Editor editor,PsiFile file) throws IncorrectOperationException {} + public boolean startInWriteAction() { return true; } +} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/intentionDescriptions/MyIntentionActionOptionalBeforeAfter/description.html b/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/intentionDescriptions/MyIntentionActionOptionalBeforeAfter/description.html new file mode 100644 index 000000000000..4e9882fe8c9c --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/intentionDescriptions/MyIntentionActionOptionalBeforeAfter/description.html @@ -0,0 +1 @@ +Correctly mapped. \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/resources/META-INF/plugin.xml b/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/resources/META-INF/plugin.xml index 62922d3fe0b2..2570d3032a81 100644 --- a/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/resources/META-INF/plugin.xml +++ b/plugins/devkit/devkit-java-tests/testData/inspections/intentionDescription/resources/META-INF/plugin.xml @@ -10,6 +10,10 @@ MyIntentionActionWithoutBeforeAfter + + MyIntentionActionOptionalBeforeAfter + true + MyQuickFixIntentionAction diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/IntentionDescriptionNotFoundInspectionTest.java b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/IntentionDescriptionNotFoundInspectionTest.java index b077b900899b..c7e5b218b5b3 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/IntentionDescriptionNotFoundInspectionTest.java +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/IntentionDescriptionNotFoundInspectionTest.java @@ -3,7 +3,6 @@ package org.jetbrains.idea.devkit.inspections; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.IntentionActionBean; -import com.intellij.codeInspection.LocalInspectionEP; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Iconable; @@ -15,8 +14,6 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.PathUtil; import org.jetbrains.idea.devkit.DevkitJavaTestsUtil; -import java.nio.file.Paths; - @TestDataPath("$CONTENT_ROOT/testData/inspections/intentionDescription") public class IntentionDescriptionNotFoundInspectionTest extends JavaCodeInsightFixtureTestCase { @@ -59,6 +56,11 @@ public class IntentionDescriptionNotFoundInspectionTest extends JavaCodeInsightF myFixture.testHighlighting("MyIntentionActionWithoutBeforeAfter.java"); } + public void testHighlightingOptionalBeforeAfter() { + myFixture.copyDirectoryToProject("intentionDescriptions", "intentionDescriptions"); + myFixture.testHighlighting("MyIntentionActionOptionalBeforeAfter.java"); + } + public void testQuickFix() { myFixture.configureByFile("MyQuickFixIntentionAction.java"); IntentionAction item = myFixture.findSingleIntention("Create description file description.html");