assertEquals between inconvertible types: junit & testng refactored; introduce junit 5 for assertEquals called on array

This commit is contained in:
Anna.Kozlova
2016-10-18 18:11:07 +02:00
parent c4a9c2f7c3
commit c28bda6b3f
7 changed files with 224 additions and 195 deletions
@@ -15,14 +15,10 @@
*/
package com.siyeh.ig.junit;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.PsiMethodCallExpression;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class AssertEqualsBetweenInconvertibleTypesInspection extends BaseInspection {
@@ -36,13 +32,7 @@ public class AssertEqualsBetweenInconvertibleTypesInspection extends BaseInspect
@Override
@NotNull
public String buildErrorString(Object... infos) {
final PsiType comparedType = (PsiType)infos[0];
final PsiType comparisonType = (PsiType)infos[1];
final String comparedTypeText = comparedType.getPresentableText();
final String comparisonTypeText = comparisonType.getPresentableText();
return InspectionGadgetsBundle.message("assertequals.between.inconvertible.types.problem.descriptor",
StringUtil.escapeXml(comparedTypeText),
StringUtil.escapeXml(comparisonTypeText));
return (String)infos[0];
}
@Override
@@ -60,63 +50,10 @@ public class AssertEqualsBetweenInconvertibleTypesInspection extends BaseInspect
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
@NonNls final String methodName = methodExpression.getReferenceName();
if (!"assertEquals".equals(methodName)) {
return;
final String compatibilityErrorMessage = AssertEqualsHint.areExpectedActualTypesCompatible(expression);
if (compatibilityErrorMessage != null) {
registerMethodCallError(expression, compatibilityErrorMessage);
}
final PsiMethod method = expression.resolveMethod();
if (method == null) {
return;
}
final PsiClass containingClass = method.getContainingClass();
final boolean junit5Assertions = InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS);
if (!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT) &&
!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_ASSERT) &&
!junit5Assertions) {
return;
}
final PsiParameterList parameterList = method.getParameterList();
final PsiParameter[] parameters = parameterList.getParameters();
if (parameters.length < 2) {
return;
}
final PsiType firstParameterType = parameters[0].getType();
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
final int argumentIndex;
if (!junit5Assertions && firstParameterType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
if (arguments.length < 3) {
return;
}
argumentIndex = 1;
}
else {
if (arguments.length < 2) {
return;
}
argumentIndex = 0;
}
final PsiExpression expression1 = arguments[argumentIndex];
final PsiExpression expression2 = arguments[argumentIndex + 1];
final PsiType type1 = expression1.getType();
if (type1 == null) {
return;
}
final PsiType type2 = expression2.getType();
if (type2 == null) {
return;
}
final PsiType parameterType1 = parameters[argumentIndex].getType();
final PsiType parameterType2 = parameters[argumentIndex + 1].getType();
final PsiClassType objectType = TypeUtils.getObjectType(expression);
if (!objectType.equals(parameterType1) || !objectType.equals(parameterType2)) {
return;
}
if (TypeUtils.areConvertible(type1, type2)) {
return;
}
registerMethodCallError(expression, type1, type2);
}
}
}
@@ -47,11 +47,17 @@ public class AssertEqualsCalledOnArrayInspection extends BaseInspection {
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
return new AssertEqualsCalledOnArrayFix();
return new AssertEqualsCalledOnArrayFix((String)infos[0]);
}
private static class AssertEqualsCalledOnArrayFix extends InspectionGadgetsFix {
private final String myAssertClassName;
public AssertEqualsCalledOnArrayFix(String assertClassName) {
myAssertClassName = assertClassName;
}
@Override
@NotNull
public String getFamilyName() {
@@ -67,11 +73,11 @@ public class AssertEqualsCalledOnArrayInspection extends BaseInspection {
}
final PsiReferenceExpression methodExpression = (PsiReferenceExpression)parent;
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null && ImportUtils.addStaticImport(JUnitCommonClassNames.ORG_JUNIT_ASSERT, "assertArrayEquals", methodExpression)) {
if (qualifier == null && ImportUtils.addStaticImport(myAssertClassName, "assertArrayEquals", methodExpression)) {
PsiReplacementUtil.replaceExpression(methodExpression, "assertArrayEquals");
}
else {
PsiReplacementUtil.replaceExpression(methodExpression, "org.junit.Assert.assertArrayEquals");
PsiReplacementUtil.replaceExpression(methodExpression, myAssertClassName + ".assertArrayEquals");
}
}
}
@@ -86,44 +92,19 @@ public class AssertEqualsCalledOnArrayInspection extends BaseInspection {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
@NonNls final String methodName = methodExpression.getReferenceName();
if (!"assertEquals".equals(methodName)) {
final AssertEqualsHint assertEqualsHint = AssertEqualsHint.create(expression);
if (assertEqualsHint == null) {
return;
}
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
final PsiType type1;
final PsiType type2;
if (arguments.length == 2) {
final PsiExpression argument0 = arguments[0];
type1 = argument0.getType();
final PsiExpression argument1 = arguments[1];
type2 = argument1.getType();
}
else if (arguments.length == 3) {
final PsiExpression argument0 = arguments[1];
type1 = argument0.getType();
final PsiExpression argument1 = arguments[2];
type2 = argument1.getType();
}
else {
return;
}
final int argIndex = assertEqualsHint.getArgIndex();
final PsiType type1 = arguments[argIndex].getType();
final PsiType type2 = arguments[argIndex + 1].getType();
if (!(type1 instanceof PsiArrayType) || !(type2 instanceof PsiArrayType)) {
return;
}
final PsiMethod method = expression.resolveMethod();
if (method == null) {
return;
}
final PsiClass containingClass = method.getContainingClass();
if (!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT) &&
!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_ASSERT) &&
!InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit")) {
return;
}
registerMethodCallError(expression);
registerMethodCallError(expression, assertEqualsHint.getAssertClassName());
}
}
}
@@ -0,0 +1,120 @@
/*
* Copyright 2000-2016 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 com.siyeh.ig.junit;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
public class AssertEqualsHint {
private final int myArgIndex;
private final PsiMethod myMethod;
private final String myClassName;
private AssertEqualsHint(int index, PsiMethod method, String className) {
myArgIndex = index;
myMethod = method;
myClassName = className;
}
public String getAssertClassName() {
return myClassName;
}
public int getArgIndex() {
return myArgIndex;
}
public PsiMethod getMethod() {
return myMethod;
}
public static AssertEqualsHint create(PsiMethodCallExpression expression) {
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
@NonNls final String methodName = methodExpression.getReferenceName();
if (!"assertEquals".equals(methodName)) {
return null;
}
final PsiMethod method = expression.resolveMethod();
if (method == null) {
return null;
}
final PsiClass containingClass = method.getContainingClass();
final boolean messageOnLastPosition = InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS) ||
InheritanceUtil.isInheritor(containingClass, "org.testng.Assert");
if (!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.JUNIT_FRAMEWORK_ASSERT) &&
!InheritanceUtil.isInheritor(containingClass, JUnitCommonClassNames.ORG_JUNIT_ASSERT) &&
!InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit") &&
!messageOnLastPosition) {
return null;
}
final PsiParameterList parameterList = method.getParameterList();
final PsiParameter[] parameters = parameterList.getParameters();
if (parameters.length < 2) {
return null;
}
final PsiType firstParameterType = parameters[0].getType();
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
final int argumentIndex;
if (!messageOnLastPosition && firstParameterType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
if (arguments.length < 3) {
return null;
}
argumentIndex = 1;
}
else {
if (arguments.length < 2) {
return null;
}
argumentIndex = 0;
}
return new AssertEqualsHint(argumentIndex, method, messageOnLastPosition ? JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS : JUnitCommonClassNames.ORG_JUNIT_ASSERT);
}
public static String areExpectedActualTypesCompatible(PsiMethodCallExpression expression) {
final AssertEqualsHint assertEqualsHint = create(expression);
if (assertEqualsHint == null) return null;
final PsiExpression[] arguments = expression.getArgumentList().getExpressions();
final int argIndex = assertEqualsHint.getArgIndex();
final PsiType type1 = arguments[argIndex].getType();
if (type1 == null) {
return null;
}
final PsiType type2 = arguments[argIndex + 1].getType();
if (type2 == null) {
return null;
}
final PsiParameter[] parameters = assertEqualsHint.getMethod().getParameterList().getParameters();
final PsiType parameterType1 = parameters[argIndex].getType();
final PsiType parameterType2 = parameters[argIndex + 1].getType();
final PsiClassType objectType = TypeUtils.getObjectType(expression);
if (!objectType.equals(parameterType1) || !objectType.equals(parameterType2)) {
return null;
}
if (TypeUtils.areConvertible(type1, type2)) {
return null;
}
final String comparedTypeText = type1.getPresentableText();
final String comparisonTypeText = type2.getPresentableText();
return InspectionGadgetsBundle.message("assertequals.between.inconvertible.types.problem.descriptor",
StringUtil.escapeXml(comparedTypeText),
StringUtil.escapeXml(comparisonTypeText));
}
}
@@ -0,0 +1,7 @@
class MyTest {
void myTest(){
Object[] a = {};
Object[] e = {""};
org.junit.jupiter.api.Assertions.assertArrayEquals(a, e, "message");
}
}
@@ -0,0 +1,7 @@
class MyTest {
void myTest(){
Object[] a = {};
Object[] e = {""};
org.junit.jupiter.api.Assertions.assert<caret>Equals(a, e, "message");
}
}
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2016 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 com.siyeh.ig.fixes.junit;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.IGQuickFixesTestCase;
import com.siyeh.ig.junit.AssertEqualsCalledOnArrayInspection;
import com.siyeh.ig.junit.UseOfObsoleteAssertInspection;
public class AssertEqualsCalledOnArrayInspectionTest extends IGQuickFixesTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
myFixture.addClass("package org.junit.jupiter.api;\n" +
"import java.util.function.Supplier;\n" +
"public final class Assertions {\n" +
" public static void assertArrayEquals(Object[] expected, Object[] actual) {}\n" +
" public static void assertArrayEquals(Object[] expected, Object[] actual, String message) {}\n" +
" public static void assertEquals(Object expected, Object actual) {}\n" +
" public static void assertEquals(Object expected, Object actual, String message) {}\n" +
"}");
myFixture.enableInspections(new AssertEqualsCalledOnArrayInspection());
}
public void testAssertEqualsForJunit5() {
doFixTest();
}
private void doFixTest() {
doTest(getTestName(true), InspectionGadgetsBundle.message("assertequals.called.on.arrays.quickfix"));
}
@Override
protected String getRelativePath() {
return "junit/assertEqualsOnArray";
}
}
@@ -17,12 +17,11 @@ package com.theoryinpractice.testng.inspection;
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiMethodCallExpression;
import com.siyeh.ig.junit.AssertEqualsHint;
import org.jetbrains.annotations.NotNull;
/**
@@ -32,95 +31,20 @@ public class AssertEqualsBetweenInconvertibleTypesTestNGInspection extends BaseJ
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new AssertEqualsBetweenInconvertibleTypesVisitor(holder);
}
return new JavaElementVisitor() {
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final String errorMessage = AssertEqualsHint.areExpectedActualTypesCompatible(expression);
if (errorMessage != null) {
final PsiElement referenceNameElement = expression.getMethodExpression().getReferenceNameElement();
if (referenceNameElement == null) {
return;
}
private static class AssertEqualsBetweenInconvertibleTypesVisitor extends JavaElementVisitor {
private final ProblemsHolder myProblemsHolder;
public AssertEqualsBetweenInconvertibleTypesVisitor(ProblemsHolder problemsHolder) {
myProblemsHolder = problemsHolder;
}
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
@NonNls final String methodName = methodExpression.getReferenceName();
if (!"assertEquals".equals(methodName)) {
return;
}
final PsiMethod method = expression.resolveMethod();
if (method == null) {
return;
}
final PsiClass containingClass = method.getContainingClass();
final boolean junit;
if (InheritanceUtil.isInheritor(containingClass, "org.testng.Assert")) {
junit = false;
}
else if (InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit")) {
junit = true;
}
else {
return;
}
final PsiParameterList parameterList = method.getParameterList();
final PsiParameter[] parameters = parameterList.getParameters();
if (parameters.length < 2) {
return;
}
final PsiType firstParameterType = parameters[0].getType();
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
final PsiExpression expression1;
final PsiExpression expression2;
final PsiType parameterType1;
final PsiType parameterType2;
if (junit && firstParameterType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
if (arguments.length < 3) {
return;
holder.registerProblem(referenceNameElement, errorMessage);
}
expression1 = arguments[1];
expression2 = arguments[2];
parameterType1 = parameters[1].getType();
parameterType2 = parameters[2].getType();
}
else {
if (arguments.length < 2) {
return;
}
expression1 = arguments[0];
expression2 = arguments[1];
parameterType1 = parameters[0].getType();
parameterType2 = parameters[1].getType();
}
final PsiType type1 = expression1.getType();
if (type1 == null) {
return;
}
final PsiType type2 = expression2.getType();
if (type2 == null) {
return;
}
final PsiManager manager = expression.getManager();
final GlobalSearchScope scope = expression.getResolveScope();
final PsiClassType objectType = PsiType.getJavaLangObject(manager, scope);
if (!objectType.equals(parameterType1) || !objectType.equals(parameterType2)) {
return;
}
if (TypeUtils.areConvertible(type1, type2)) {
return;
}
final PsiElement referenceNameElement = methodExpression.getReferenceNameElement();
if (referenceNameElement == null) {
return;
}
myProblemsHolder.registerProblem(referenceNameElement,
"<code>#ref()</code> between objects of inconvertible types '" +
StringUtil.escapeXml(type1.getPresentableText()) + "' and '" +
StringUtil.escapeXml(type2.getPresentableText()) + "' #loc");
}
};
}
}