[jvm] IDEA-297699 Convert IgnoredJUnitTestInspection to UAST

GitOrigin-RevId: cb170f7fd68445f72606e6a864fb941d820ff26b
This commit is contained in:
Bart van Helvert
2022-07-10 18:10:26 +02:00
committed by intellij-monorepo-bot
parent 019e97fe33
commit 819f4e36e3
14 changed files with 174 additions and 175 deletions

View File

@@ -57,6 +57,11 @@
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"
key="jvm.inspections.unconstructable.test.case.display.name"
implementationClass="com.intellij.codeInspection.test.junit.JUnitUnconstructableTestCaseInspection"/>
<localInspection language="UAST" enabledByDefault="false" level="WARNING" shortName="IgnoredJUnitTest"
groupBundle="messages.JvmAnalysisBundle" bundle="messages.JvmAnalysisBundle"
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"
key="jvm.inspections.junit.ignored.test.display.name"
implementationClass="com.intellij.codeInspection.test.junit.JUnitIgnoredTestInspection"/>
<localInspection language="UAST" enabledByDefault="false" cleanupTool="true" level="WARNING" shortName="AssertEqualsCalledOnArray"
groupBundle="messages.JvmAnalysisBundle" bundle="messages.JvmAnalysisBundle"
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"

View File

@@ -168,6 +168,11 @@ jvm.inspections.junit.assertequals.on.array.problem.descriptor=<code>#ref()</cod
jvm.inspections.junit.assertequals.may.be.assertsame.display.name='assertEquals()' may be 'assertSame()'
jvm.inspections.junit.assertequals.may.be.assertsame.problem.descriptor=<code>#ref()</code> may be 'assertSame()' #loc
jvm.inspections.junit.ignored.test.display.name=JUnit test annotated with '@Ignore'/'@Disabled'
jvm.inspections.junit.ignored.test.ignore.reason.option=Only report annotations without reason
jvm.inspections.junit.ignored.test.class.problem.descriptor=Test class ''{0}'' is ignored/disabled {1, choice, 1#|2#without reason} #loc
jvm.inspections.junit.ignored.test.method.problem.descriptor=Test method ''{0}()'' is ignored/disabled {1, choice, 1#|2#without reason} #loc
jvm.inspections.migrate.assertion.name=JUnit assertion can be 'assertThat()' call
jvm.inspections.migrate.assert.to.matcher.option=Statically import matcher's methods
jvm.inspections.migrate.assert.to.matcher.description=Assert expression <code>#ref</code> can be replaced with ''{0}'' call #loc

View File

@@ -0,0 +1,53 @@
// 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.codeInspection.test.junit
import com.intellij.analysis.JvmAnalysisBundle
import com.intellij.codeInspection.*
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel
import com.intellij.codeInspection.util.InspectionMessage
import com.intellij.psi.PsiElementVisitor
import com.intellij.uast.UastHintedVisitorAdapter
import com.siyeh.ig.junit.JUnitCommonClassNames.*
import org.jetbrains.uast.*
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
import javax.swing.JComponent
class JUnitIgnoredTestInspection : AbstractBaseUastLocalInspectionTool() {
@JvmField
var onlyReportWithoutReason = true
override fun createOptionsPanel(): JComponent = SingleCheckboxOptionsPanel(
JvmAnalysisBundle.message("jvm.inspections.junit.ignored.test.ignore.reason.option"), this, "onlyReportWithoutReason"
)
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor =
UastHintedVisitorAdapter.create(
holder.file.language,
JUnitIgnoredTestVisitor(holder, onlyReportWithoutReason),
arrayOf(UClass::class.java, UMethod::class.java),
directOnly = true
)
}
private class JUnitIgnoredTestVisitor(
private val holder: ProblemsHolder,
private val onlyReportWithoutReason: Boolean
) : AbstractUastNonRecursiveVisitor() {
val withoutReasonChoice = if (onlyReportWithoutReason) 2 else 1
override fun visitClass(node: UClass): Boolean = checkIgnoreOrDisabled(
node, JvmAnalysisBundle.message("jvm.inspections.junit.ignored.test.class.problem.descriptor", node.javaPsi.name, withoutReasonChoice)
)
override fun visitMethod(node: UMethod): Boolean = checkIgnoreOrDisabled(
node, JvmAnalysisBundle.message("jvm.inspections.junit.ignored.test.method.problem.descriptor", node.name, withoutReasonChoice)
)
private fun checkIgnoreOrDisabled(node: UDeclaration, message: @InspectionMessage String): Boolean {
val annotations = node.findAnnotations(ORG_JUNIT_IGNORE, ORG_JUNIT_JUPITER_API_DISABLED)
if (annotations.isEmpty()) return true
if (onlyReportWithoutReason && annotations.any { it.findDeclaredAttributeValue("value") != null }) return true
holder.registerUProblem(node, message)
return true
}
}

View File

@@ -0,0 +1,43 @@
package com.intellij.codeInspection.tests.java.test.junit
import com.intellij.codeInspection.tests.ULanguage
import com.intellij.codeInspection.tests.test.junit.JUnitIgnoredTestInspectionTestBase
class JavaJUnitIgnoredTestInspectionTest : JUnitIgnoredTestInspectionTestBase() {
fun `test JUnit 4 @Ignore`() {
myFixture.testHighlighting(ULanguage.JAVA, """
import org.junit.*;
@Ignore("for good reason")
class IgnoredJUnitTest {
@Ignore
@Test
public void <warning descr="Test method 'foo1()' is ignored/disabled without reason">foo1</warning>() { }
@Ignore("valid description")
@Test
public void foo2() { }
}
""".trimIndent())
}
fun `test JUnit 5 @Disabled`() {
myFixture.testHighlighting(ULanguage.JAVA, """
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.Ignore;
@Disabled
class <warning descr="Test class 'DisabledJUnit5Test' is ignored/disabled without reason">DisabledJUnit5Test</warning> {
@Disabled
@Test
void <warning descr="Test method 'foo1()' is ignored/disabled without reason">foo1</warning>() { }
@Disabled
@Ignore("valid reason")
@Test
void foo2() { }
}
""".trimIndent())
}
}

View File

@@ -0,0 +1,43 @@
package com.intellij.codeInspection.tests.kotlin.test.junit
import com.intellij.codeInspection.tests.ULanguage
import com.intellij.codeInspection.tests.test.junit.JUnitIgnoredTestInspectionTestBase
class KotlinJUnitIgnoredTestInspectionTest : JUnitIgnoredTestInspectionTestBase() {
fun `test JUnit 4 @Ignore`() {
myFixture.testHighlighting(ULanguage.KOTLIN, """
import org.junit.*
@Ignore("for good reason")
class IgnoredJUnitTest {
@Ignore
@Test
public fun <warning descr="Test method 'foo1()' is ignored/disabled without reason">foo1</warning>() { }
@Ignore("valid description")
@Test
public fun foo2() { }
}
""".trimIndent())
}
fun `test JUnit 5 @Disabled`() {
myFixture.testHighlighting(ULanguage.KOTLIN, """
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.junit.Ignore
@Disabled
class <warning descr="Test class 'DisabledJUnit5Test' is ignored/disabled without reason">DisabledJUnit5Test</warning> {
@Disabled
@Test
fun <warning descr="Test method 'foo1()' is ignored/disabled without reason">foo1</warning>() { }
@Disabled
@Ignore("valid reason")
@Test
fun foo2() { }
}
""".trimIndent())
}
}

View File

@@ -0,0 +1,24 @@
package com.intellij.codeInspection.tests.test.junit
import com.intellij.codeInspection.InspectionProfileEntry
import com.intellij.codeInspection.test.junit.JUnitIgnoredTestInspection
import com.intellij.codeInspection.tests.UastInspectionTestBase
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ContentEntry
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.pom.java.LanguageLevel
import com.intellij.testFramework.LightProjectDescriptor
abstract class JUnitIgnoredTestInspectionTestBase : UastInspectionTestBase() {
override val inspection: InspectionProfileEntry = JUnitIgnoredTestInspection()
protected open class JUnitProjectDescriptor(languageLevel: LanguageLevel) : ProjectDescriptor(languageLevel) {
override fun configureModule(module: Module, model: ModifiableRootModel, contentEntry: ContentEntry) {
super.configureModule(module, model, contentEntry)
model.addJUnit4Library()
model.addJUnit5Library()
}
}
override fun getProjectDescriptor(): LightProjectDescriptor = JUnitProjectDescriptor(sdkLevel)
}

View File

@@ -1873,10 +1873,6 @@ unnecessary.return.option=Ignore in then branch of 'if' statement with 'else' br
usage.of.obsolete.assert.display.name=Usage of obsolete 'junit.framework.Assert' method
use.of.obsolete.assert.problem.descriptor=Call to <code>#ref()</code> from ''{0}'' should be replaced with call to method from ''org.junit.Assert'' #loc
use.of.obsolete.assert.quickfix=Replace with 'org.junit.Assert' method call
ignored.junit.test.display.name=JUnit test annotated with '@Ignore'/'@Disabled'
ignored.junit.test.classproblem.descriptor=Test class ''{0}'' annotated with <code>#ref</code> #loc
ignored.junit.test.method.problem.descriptor=Test method ''{0}()'' annotated with <code>#ref</code> #loc
ignored.junit.test.ignore.reason.option=Only report annotations without reason
unclear.binary.expression.display.name=Multiple operators with different precedence
unclear.binary.expression.problem.descriptor=Expression could use clarifying parentheses #loc
unclear.binary.expression.quickfix=Add clarifying parentheses

View File

@@ -1,78 +0,0 @@
// Copyright 2000-2021 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 com.siyeh.ig.junit;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class IgnoredJUnitTestInspection extends BaseInspection {
public boolean onlyReportWithoutReason = true;
@Override
public @Nullable JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("ignored.junit.test.ignore.reason.option"),
this, "onlyReportWithoutReason");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
final PsiNamedElement info = (PsiNamedElement)infos[0];
if (info instanceof PsiClass) {
return InspectionGadgetsBundle.message("ignored.junit.test.classproblem.descriptor", info.getName());
}
else {
return InspectionGadgetsBundle.message("ignored.junit.test.method.problem.descriptor", info.getName());
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new IgnoredJUnitTestVisitor();
}
private class IgnoredJUnitTestVisitor extends BaseInspectionVisitor {
@Override
public void visitAnnotation(@NotNull PsiAnnotation annotation) {
super.visitAnnotation(annotation);
final PsiModifierListOwner modifierListOwner = PsiTreeUtil.getParentOfType(annotation, PsiModifierListOwner.class);
if (!(modifierListOwner instanceof PsiClass || modifierListOwner instanceof PsiMethod)) {
return;
}
final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement();
if (nameReferenceElement == null) {
return;
}
final PsiElement target = nameReferenceElement.resolve();
if (!(target instanceof PsiClass)) {
return;
}
final PsiClass aClass = (PsiClass)target;
@NonNls final String qualifiedName = aClass.getQualifiedName();
if (!"org.junit.Ignore".equals(qualifiedName) && !"org.junit.jupiter.api.Disabled".equals(qualifiedName)) {
return;
}
final PsiNameValuePair attribute = AnnotationUtil.findDeclaredAttribute(annotation, null);
if (attribute != null) {
final PsiAnnotationMemberValue value = attribute.getValue();
if (onlyReportWithoutReason && value instanceof PsiExpression &&
ExpressionUtils.computeConstantExpression((PsiExpression)value) instanceof String) {
return;
}
}
registerError(nameReferenceElement, modifierListOwner);
}
}
}

View File

@@ -50,6 +50,7 @@ public final class JUnitCommonClassNames {
ORG_JUNIT_JUPITER_PARAMS_PROVIDER_NULL_AND_EMPTY_SOURCE);
public static final String ORG_JUNIT_JUPITER_PARAMS_PROVIDER_ARGUMENTS = "org.junit.jupiter.params.provider.Arguments";
public static final String ORG_JUNIT_JUPITER_PARAMS_CONVERTER_CONVERT_WITH = "org.junit.jupiter.params.converter.ConvertWith";
public static final String ORG_JUNIT_JUPITER_API_DISABLED = "org.junit.jupiter.api.Disabled";
public static final String ORG_JUNIT_JUPITER_API_TEST = "org.junit.jupiter.api.Test";
public static final String ORG_JUNIT_JUPITER_API_TEST_FACTORY = "org.junit.jupiter.api.TestFactory";
public static final String ORG_JUNIT_JUPITER_API_NESTED = "org.junit.jupiter.api.Nested";

View File

@@ -1355,9 +1355,6 @@
groupKey="group.names.test.frameworks.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.testFrameworks.ConstantAssertArgumentInspection"/>
<inspectionElementsMerger implementation="com.siyeh.ig.testFrameworks.ConstantAssertArgumentMerger"/>
<localInspection groupPath="Java" language="JAVA" shortName="IgnoredJUnitTest" bundle="messages.InspectionGadgetsBundle" key="ignored.junit.test.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.junit.IgnoredJUnitTestInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="JUnit3StyleTestMethodInJUnit4Class" bundle="messages.InspectionGadgetsBundle"
key="junit3.style.test.method.in.junit4.class.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.junit.issues" enabledByDefault="true" level="WARNING"

View File

@@ -1,11 +0,0 @@
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@Disabled("valid reason")
class DisabledJUnit5Test {
@<warning descr="Test method 'addition()' annotated with 'Disabled'">Disabled</warning>
@Test
void addition() {
}
}

View File

@@ -1,9 +0,0 @@
import org.junit.*;
@Ignore("for good reason")
public class IgnoredJUnitTest {
@<warning descr="Test method 'testThis()' annotated with 'Ignore'">Ignore</warning>
@Test
public void testThis() {}
}

View File

@@ -1,70 +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 com.siyeh.ig.junit;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightJavaInspectionTestCase;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class IgnoredJUnitTestInspectionTest extends LightJavaInspectionTestCase {
public void testIgnoredJUnitTest() {
addEnvironmentClass("package org.junit;\n" +
"\n" +
"import java.lang.annotation.ElementType;\n" +
"import java.lang.annotation.Retention;\n" +
"import java.lang.annotation.RetentionPolicy;\n" +
"import java.lang.annotation.Target;\n" +
"\n" +
"@Retention(RetentionPolicy.RUNTIME)\n" +
"@Target({ElementType.METHOD, ElementType.TYPE})\n" +
"public @interface Ignore {\n" +
" String value() default \"\";\n" +
"}");
addEnvironmentClass("package org.junit;\n" +
"\n" +
"import java.lang.annotation.ElementType;\n" +
"import java.lang.annotation.Retention;\n" +
"import java.lang.annotation.RetentionPolicy;\n" +
"import java.lang.annotation.Target;\n" +
"\n" +
"@Retention(RetentionPolicy.RUNTIME)\n" +
"@Target(ElementType.METHOD)\n" +
"public @interface Test {}");
doTest();
}
public void testDisabledJUnit5Test() {
addEnvironmentClass("package org.junit.jupiter.api;\n" +
"\n" +
"import java.lang.annotation.ElementType;\n" +
"import java.lang.annotation.Retention;\n" +
"import java.lang.annotation.RetentionPolicy;\n" +
"import java.lang.annotation.Target;\n" +
"\n" +
"@Target({ElementType.TYPE, ElementType.METHOD})\n" +
"@Retention(RetentionPolicy.RUNTIME)\n" +
"public @interface Disabled {\n" +
" String value() default \"\";\n" +
"}");
addEnvironmentClass("package org.junit.jupiter.api;\n" +
"\n" +
"import java.lang.annotation.Documented;\n" +
"import java.lang.annotation.ElementType;\n" +
"import java.lang.annotation.Retention;\n" +
"import java.lang.annotation.RetentionPolicy;\n" +
"import java.lang.annotation.Target;\n" +
"\n" +
"@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})\n" +
"@Retention(RetentionPolicy.RUNTIME)\n" +
"public @interface Test {}");
doTest();
}
@Override
protected @Nullable InspectionProfileEntry getInspection() {
return new IgnoredJUnitTestInspection();
}
}