mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-09 08:09:39 +07:00
[jvm] IDEA-296557 Convert "Test in production code" inspections to UAST and merge them together
GitOrigin-RevId: a084452c8af9d275285c2aa3591166552fec123b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
81c65b8d02
commit
f4bd22020b
@@ -773,6 +773,18 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
"</profile>");
|
||||
}
|
||||
|
||||
public void testTestInProductSourceInspections() throws Exception {
|
||||
checkMergedNoChanges("<profile version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
|
||||
" <inspection_tool class=\"TestCaseInProductCode\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
|
||||
" <inspection_tool class=\"TestMethodInProductCode\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
|
||||
"</profile>");
|
||||
checkMergedNoChanges("<profile version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
|
||||
" <inspection_tool class=\"TestInProductSource\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
|
||||
"</profile>");
|
||||
}
|
||||
|
||||
public void testMergedMethodDoesntCallSuperMethodInspections() throws Exception {
|
||||
checkMergedNoChanges("<profile version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"
|
||||
key="jvm.inspection.test.failed.line.display.name"
|
||||
implementationClass="com.intellij.codeInspection.test.TestFailedLineInspection"/>
|
||||
<localInspection language="UAST" enabledByDefault="false" level="WARNING" shortName="TestInProductSource"
|
||||
groupBundle="messages.JvmAnalysisBundle" bundle="messages.JvmAnalysisBundle"
|
||||
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"
|
||||
key="jvm.inspections.junit.test.case.in.product.source.display.name"
|
||||
implementationClass="com.intellij.codeInspection.test.TestInProductSourceInspection"/>
|
||||
<inspectionElementsMerger implementation="com.intellij.codeInspection.test.TestInProductSourceInspectionMerger"/>
|
||||
|
||||
<!--JUnit framework-->
|
||||
<localInspection language="UAST" enabledByDefault="false" level="WARNING" shortName="SuperTearDownInFinally"
|
||||
groupBundle="messages.JvmAnalysisBundle" bundle="messages.JvmAnalysisBundle"
|
||||
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.test.frameworks.group.name"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports methods annotated with the JUnit 4 or JUnit 5 <code>@Test</code> annotation that are located in production source trees.
|
||||
Reports test classes and test methods that are located in production source trees.
|
||||
This most likely a mistake and can result in test code being shipped into production.
|
||||
<!-- tooltip end -->
|
||||
</body>
|
||||
@@ -104,6 +104,10 @@ jvm.inspections.unconstructable.test.case.not.public.descriptor=Test class <code
|
||||
jvm.inspections.unconstructable.test.case.junit3.descriptor=Test class <code>#ref</code> is not constructable because it does not have a 'public' no-arg or single 'String' parameter constructor #loc
|
||||
jvm.inspections.unconstructable.test.case.junit4.descriptor=Test class <code>#ref</code> is not constructable because it should have exactly one 'public' no-arg constructor #loc
|
||||
|
||||
jvm.inspections.junit.test.case.in.product.source.display.name=Test in product source
|
||||
jvm.inspections.junit.test.case.in.product.source.problem.descriptor=Test case <code>#ref</code> should probably be placed in a test source tree #loc
|
||||
jvm.inspections.junit.test.method.in.product.source.problem.descriptor=Test method <code>#ref()</code> should probably be placed in a test source tree #loc
|
||||
|
||||
jvm.inspections.junit.malformed.declaration.name=JUnit malformed declaration
|
||||
jvm.inspections.junit.malformed.option.ignore.test.parameter.if.annotated.by=Ignore test parameter if it is annotated by:
|
||||
jvm.inspections.junit.malformed.method.no.arg.descriptor=Method <code>#ref</code> should be a {0}, {1} and have no parameters
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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
|
||||
|
||||
import com.intellij.analysis.JvmAnalysisBundle
|
||||
import com.intellij.codeInspection.AbstractBaseUastLocalInspectionTool
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.codeInspection.registerUProblem
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.uast.UastHintedVisitorAdapter
|
||||
import com.siyeh.ig.psiutils.TestUtils
|
||||
import org.jetbrains.uast.UClass
|
||||
import org.jetbrains.uast.UMethod
|
||||
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
|
||||
|
||||
class TestInProductSourceInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor =
|
||||
UastHintedVisitorAdapter.create(
|
||||
holder.file.language,
|
||||
TestInProductSourceVisitor(holder),
|
||||
arrayOf(UClass::class.java, UMethod::class.java),
|
||||
directOnly = true
|
||||
)
|
||||
}
|
||||
|
||||
private class TestInProductSourceVisitor(private val holder: ProblemsHolder) : AbstractUastNonRecursiveVisitor() {
|
||||
override fun visitClass(node: UClass): Boolean {
|
||||
val javaClass = node.javaPsi
|
||||
if (TestUtils.isInTestSourceContent(javaClass) || !TestUtils.isJUnitTestClass(javaClass)) return true
|
||||
val message = JvmAnalysisBundle.message("jvm.inspections.junit.test.case.in.product.source.problem.descriptor")
|
||||
holder.registerUProblem(node, message)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun visitMethod(node: UMethod): Boolean {
|
||||
val method = node.javaPsi
|
||||
val containingClass = method.containingClass ?: return true
|
||||
if (TestUtils.isInTestSourceContent(containingClass) || !TestUtils.isTestMethod(method)) return true
|
||||
val message = JvmAnalysisBundle.message("jvm.inspections.junit.test.method.in.product.source.problem.descriptor")
|
||||
holder.registerUProblem(node, message)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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
|
||||
|
||||
import com.intellij.codeInspection.ex.InspectionElementsMerger
|
||||
|
||||
class TestInProductSourceInspectionMerger : InspectionElementsMerger() {
|
||||
override fun getMergedToolName(): String = "TestInProductSource"
|
||||
|
||||
override fun getSourceToolNames(): Array<String> = arrayOf(
|
||||
"TestCaseInProductCode",
|
||||
"TestMethodInProductCode"
|
||||
)
|
||||
|
||||
override fun getSuppressIds(): Array<String> = arrayOf(
|
||||
"JUnitTestCaseInProductSource",
|
||||
"JUnitTestMethodInProductSource"
|
||||
)
|
||||
}
|
||||
@@ -613,8 +613,6 @@ long.literals.ending.with.lowercase.l.display.name='long' literal ending with 'l
|
||||
overly.complex.arithmetic.expression.display.name=Overly complex arithmetic expression
|
||||
junit.abstract.test.class.naming.convention.element.description=Abstract test class
|
||||
unnecessary.parentheses.display.name=Unnecessary parentheses
|
||||
test.case.in.product.code.display.name=JUnit 'TestCase' in product source
|
||||
test.method.in.product.code.display.name=JUnit test method in product source
|
||||
serializable.class.in.secure.context.display.name=Serializable class in secure context
|
||||
static.variable.naming.convention.element.description='static' field
|
||||
nested.method.call.display.name=Nested method call
|
||||
@@ -1067,8 +1065,6 @@ misordered.assert.equals.arguments.problem.descriptor=Arguments to <code>#ref()<
|
||||
simplifiable.junit.assertion.problem.descriptor=<code>#ref()</code> can be simplified to ''{0}'' #loc
|
||||
test.method.without.assertion.problem.descriptor=JUnit test method <code>#ref()</code> contains no assertions #loc
|
||||
test.case.with.no.test.methods.problem.descriptor=Test class <code>#ref</code> has no tests #loc
|
||||
test.case.in.product.code.problem.descriptor=Test case <code>#ref</code> should probably be placed in a test source tree #loc
|
||||
test.method.in.product.code.problem.descriptor=Test method <code>#ref()</code> should probably be placed in a test source tree #loc
|
||||
deserializable.class.in.secure.context.problem.descriptor=Class <code>#ref</code> may be deserialized, compromising security #loc
|
||||
serializable.class.in.secure.context.problem.descriptor=Class <code>#ref</code> may be serialized, compromising security #loc
|
||||
serializable.deserializable.class.in.secure.context.problem.descriptor=Class <code>#ref</code> may be serialized and deserialized, compromising security #loc
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2013 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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 com.siyeh.ig.junit;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.TestUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TestMethodInProductCodeInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getID() {
|
||||
return "JUnitTestMethodInProductSource";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"test.method.in.product.code.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new TestCaseInProductCodeVisitor();
|
||||
}
|
||||
|
||||
private static class TestCaseInProductCodeVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitMethod(@NotNull PsiMethod method) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (TestUtils.isInTestSourceContent(containingClass) ||
|
||||
!TestUtils.isAnnotatedTestMethod(method)) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.testIntegration.TestFramework;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.junit.JUnitCommonClassNames;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -38,6 +39,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.codeInsight.AnnotationUtil.CHECK_HIERARCHY;
|
||||
@@ -113,15 +115,22 @@ public final class TestUtils {
|
||||
return method != null && AnnotationUtil.isAnnotated(method, JUnitCommonClassNames.ORG_JUNIT_TEST, CHECK_HIERARCHY);
|
||||
}
|
||||
|
||||
public static boolean isAnnotatedTestMethod(@Nullable PsiMethod method) {
|
||||
public static boolean isTestMethod(@Nullable PsiMethod method) {
|
||||
if (method == null) return false;
|
||||
return TestFrameworks.getInstance().isTestMethod(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param frameworks to check matching with {@link TestFramework#getName}
|
||||
*/
|
||||
public static boolean isExecutableTestMethod(@Nullable PsiMethod method, List<String> frameworks) {
|
||||
if (method == null) return false;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) return false;
|
||||
final TestFramework testFramework = TestFrameworks.detectFramework(containingClass);
|
||||
if (testFramework == null) return false;
|
||||
if (testFramework.isTestMethod(method, false)) {
|
||||
@NonNls final String testFrameworkName = testFramework.getName();
|
||||
return testFrameworkName.equals("JUnit4") || testFrameworkName.equals("JUnit5");
|
||||
return ContainerUtil.exists(frameworks, testFramework.getName()::equals);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1388,18 +1388,10 @@
|
||||
groupKey="group.names.test.frameworks.issues" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.testFrameworks.SimplifiableAssertionInspection" cleanupTool="true"/>
|
||||
<inspectionElementsMerger implementation="com.siyeh.ig.testFrameworks.SimplifiableAssertionMerger"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="JUnitTestCaseInProductSource" shortName="TestCaseInProductCode" bundle="messages.InspectionGadgetsBundle"
|
||||
key="test.case.in.product.code.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.junit.TestCaseInProductCodeInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="JUnitTestCaseWithNoTests" shortName="TestCaseWithNoTestMethods" bundle="messages.InspectionGadgetsBundle"
|
||||
key="test.case.with.no.test.methods.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.junit.TestCaseWithNoTestMethodsInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="JUnitTestMethodInProductSource" shortName="TestMethodInProductCode"
|
||||
bundle="messages.InspectionGadgetsBundle" key="test.method.in.product.code.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.junit.TestMethodInProductCodeInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="JUnitTestMethodWithNoAssertions" shortName="TestMethodWithoutAssertion"
|
||||
bundle="messages.InspectionGadgetsBundle" key="test.method.without.assertion.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// 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.naming.NamingConvention;
|
||||
@@ -21,6 +7,8 @@ import com.intellij.psi.PsiMethod;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.psiutils.TestUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
@@ -32,7 +20,7 @@ public class JUnit4MethodNamingConvention extends NamingConvention<PsiMethod> {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(PsiMethod member) {
|
||||
return TestUtils.isAnnotatedTestMethod(member);
|
||||
return TestUtils.isExecutableTestMethod(member, List.of("JUnit4", "JUnit5"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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 WARRnS OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.junit;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.fixes.MoveClassFix;
|
||||
import com.siyeh.ig.psiutils.TestUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TestCaseInProductCodeInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return new MoveClassFix();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getID() {
|
||||
return "JUnitTestCaseInProductSource";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"test.case.in.product.code.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new TestCaseInProductCodeVisitor();
|
||||
}
|
||||
|
||||
private static class TestCaseInProductCodeVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitClass(@NotNull PsiClass aClass) {
|
||||
if (TestUtils.isInTestSourceContent(aClass) || !TestUtils.isJUnitTestClass(aClass)) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports JUnit 3 test classes in product source trees.
|
||||
This most likely indicates a programmer's error and can result in test code being shipped
|
||||
into production.
|
||||
<!-- tooltip end -->
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user