From 13739a831dc236c0649478db660209cefa50c8d8 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Wed, 9 May 2018 18:15:03 +0200 Subject: [PATCH] junit 5: support migration of assertions in method references (IDEA-187308) --- .../siyeh/ig/testFrameworks/AssertHint.java | 32 ++++++++ .../JUnit5AssertionsConverterInspection.java | 78 ++++++++++++++----- .../FullConversion.after.java | 10 +++ .../junit5_converter/FullConversion.java | 10 +++ 4 files changed, 110 insertions(+), 20 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/testFrameworks/AssertHint.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/testFrameworks/AssertHint.java index b29eb80e0dd0..195f3517f7af 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/testFrameworks/AssertHint.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/testFrameworks/AssertHint.java @@ -121,6 +121,38 @@ public class AssertHint { return new AssertHint(argumentIndex, messageOnFirstPosition, message, method); } + public static AssertHint create(PsiMethodReferenceExpression methodExpression, + Function methodNameToParamCount, + boolean checkTestNG) { + @NonNls final String methodName = methodExpression.getReferenceName(); + Integer minimumParamCount = methodNameToParamCount.apply(methodName); + if (minimumParamCount == null) { + return null; + } + JavaResolveResult resolveResult = methodExpression.advancedResolve(false); + PsiElement element = resolveResult.getElement(); + if (!(element instanceof PsiMethod)) { + return null; + } + + final PsiMethod method = (PsiMethod)element; + if (method.hasModifierProperty(PsiModifier.PRIVATE) || !resolveResult.isValidResult()) { + return null; + } + final boolean messageOnLastPosition = isMessageOnLastPosition(method, checkTestNG); + final boolean messageOnFirstPosition = isMessageOnFirstPosition(method, checkTestNG); + if (!messageOnFirstPosition && !messageOnLastPosition) { + return null; + } + final PsiParameterList parameterList = method.getParameterList(); + final PsiParameter[] parameters = parameterList.getParameters(); + if (parameters.length != minimumParamCount) { + return null; + } + + return new AssertHint(0, messageOnFirstPosition, null, method); + } + public static boolean isMessageOnFirstPosition(PsiMethod method, boolean checkTestNG) { PsiClass containingClass = method.getContainingClass(); final String qualifiedName = containingClass.getQualifiedName(); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit5AssertionsConverterInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit5AssertionsConverterInspection.java index 9044dae511fb..712e4403e9e6 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit5AssertionsConverterInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit5AssertionsConverterInspection.java @@ -20,11 +20,13 @@ import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testIntegration.TestFramework; +import com.intellij.util.Consumer; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -72,19 +74,51 @@ public class JUnit5AssertionsConverterInspection extends BaseInspection { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { + doCheck(expression, + () -> AssertHint.create(expression, methodName -> AssertHint.JUnitCommonAssertNames.ASSERT_METHOD_2_PARAMETER_COUNT.get(methodName), false), + psiMethod -> { + final PsiClass containingClass = psiMethod.getContainingClass(); + if (containingClass == null) { + return; + } + + String methodName = psiMethod.getName(); + registerMethodCallError(expression, containingClass.getName(), + getNewAssertClassName(methodName), + absentInJUnit5(psiMethod, methodName)); + }); + } + + @Override + public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { + doCheck(expression, + () -> AssertHint.create(expression, methodName -> AssertHint.JUnitCommonAssertNames.ASSERT_METHOD_2_PARAMETER_COUNT.get(methodName), false), + psiMethod -> { + final PsiClass containingClass = psiMethod.getContainingClass(); + if (containingClass == null) { + return; + } + + String methodName = psiMethod.getName(); + registerError(expression, containingClass.getQualifiedName(), getNewAssertClassName(methodName), absentInJUnit5(psiMethod, methodName)); + }); + } + + private void doCheck(PsiElement expression, + Computable computable, + Consumer registerError) { final Project project = expression.getProject(); final Module module = ModuleUtilCore.findModuleForPsiElement(expression); if (module == null) { return; } - final PsiClass newAssertClass = JavaPsiFacade.getInstance(project) - .findClass(JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)); + final PsiClass newAssertClass = JavaPsiFacade.getInstance(project).findClass(JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_ASSERTIONS, + GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)); if (newAssertClass == null) { return; } - AssertHint hint = AssertHint.create(expression, methodName -> - AssertHint.JUnitCommonAssertNames.ASSERT_METHOD_2_PARAMETER_COUNT.get(methodName), false); + AssertHint hint = computable.compute(); if (hint == null) { return; } @@ -94,27 +128,18 @@ public class JUnit5AssertionsConverterInspection extends BaseInspection { return; } - final PsiClass containingClass = psiMethod.getContainingClass(); - if (containingClass == null) { - return; - } - final String name = containingClass.getQualifiedName(); if (hint.isMessageOnFirstPosition()) { PsiFile file = expression.getContainingFile(); if (file instanceof PsiClassOwner) { for (PsiClass psiClass : ((PsiClassOwner)file).getClasses()) { TestFramework testFramework = TestFrameworks.detectFramework(psiClass); if (testFramework != null && myFrameworkName.equals(testFramework.getName())) { - String methodName = psiMethod.getName(); - registerMethodCallError(expression, name, - getNewAssertClassName(methodName), - absentInJUnit5(psiMethod, methodName)); + registerError.consume(psiMethod); break; } } } - } } @@ -153,8 +178,17 @@ public class JUnit5AssertionsConverterInspection extends BaseInspection { @Override protected void doFix(Project project, ProblemDescriptor descriptor) { - final PsiMethodCallExpression methodCallExpression = - PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethodCallExpression.class); + PsiElement element = descriptor.getPsiElement(); + if (element instanceof PsiMethodReferenceExpression) { + AssertHint assertHint = + AssertHint.create((PsiMethodReferenceExpression)element, methodName -> AssertHint.JUnitCommonAssertNames.ASSERT_METHOD_2_PARAMETER_COUNT.get(methodName), false); + if (assertHint != null) { + replaceQualifier(project, assertHint.getMethod().getName(), (PsiReferenceExpression)element); + } + return; + } + + final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); if (methodCallExpression == null) { return; } @@ -167,9 +201,6 @@ public class JUnit5AssertionsConverterInspection extends BaseInspection { } String methodName = assertHint.getMethod().getName(); - PsiClass newAssertClass = JavaPsiFacade.getInstance(project).findClass(getNewAssertClassName(methodName), - methodCallExpression.getResolveScope()); - if (!"assertThat".equals(methodName)) { PsiExpression message = assertHint.getMessage(); if (message != null) { @@ -177,6 +208,14 @@ public class JUnit5AssertionsConverterInspection extends BaseInspection { message.delete(); } } + replaceQualifier(project, methodName, methodCallExpression.getMethodExpression()); + } + + private static void replaceQualifier(Project project, + String methodName, + final PsiReferenceExpression methodExpression) { + PsiClass newAssertClass = JavaPsiFacade.getInstance(project).findClass(getNewAssertClassName(methodName), + methodExpression.getResolveScope()); if (newAssertClass == null) { return; @@ -186,7 +225,6 @@ public class JUnit5AssertionsConverterInspection extends BaseInspection { return; } - PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); methodExpression.setQualifierExpression(JavaPsiFacade.getElementFactory(project).createReferenceExpression(newAssertClass)); JavaCodeStyleManager.getInstance(project).shortenClassReferences(methodExpression); } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.after.java index e19e44b2649a..23cf9027e046 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.after.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.after.java @@ -1,5 +1,7 @@ import org.junit.jupiter.api.Test; +import java.util.*; + import static org.junit.jupiter.api.Assertions.*; public class FullConversion { @@ -8,4 +10,12 @@ public class FullConversion { fail("fail"); assertTrue(true, "always"); } + + @Test + public void testMethodRefs() { + List booleanList = new ArrayList<>(); + booleanList.add(true); + + booleanList.forEach(Assertions::assertTrue); + } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.java index 6b1fa755f4e9..a4cb519404ee 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/junit/junit5_converter/FullConversion.java @@ -1,6 +1,8 @@ import static org.junit.Assert.*; import org.junit.Test; +import org.junit.Assert; +import java.util.*; public class FullConversion { @Test @@ -8,4 +10,12 @@ public class FullConversion { fail("fail"); assertTrue("always", true); } + + @Test + public void testMethodRefs() { + List booleanList = new ArrayList<>(); + booleanList.add(true); + + booleanList.forEach(Assert::assertTrue); + } }