blob: 89ad944a0f788c3c8f49a17cf6040bcc50058da4 [file] [log] [blame]
/*
* Copyright 2008-2012 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.codeInsight.AnnotationUtil;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.RenameFix;
import com.siyeh.ig.psiutils.TestUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class JUnit4AnnotatedMethodInJUnit3TestCaseInspection extends JUnit4AnnotatedMethodInJUnit3TestCaseInspectionBase {
@NotNull
@Override
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
final List<InspectionGadgetsFix> fixes = new ArrayList(3);
final PsiMethod method = (PsiMethod)infos[1];
if (AnnotationUtil.isAnnotated(method, IGNORE, false)) {
fixes.add(new RemoveIgnoreAndRename(method));
}
if (TestUtils.isJUnit4TestMethod(method)) {
String methodName = method.getName();
String newMethodName;
if (methodName.startsWith("test")) {
newMethodName = null;
}
else {
boolean lowCaseStyle = methodName.contains("_");
newMethodName = "test" + (lowCaseStyle ? "_" + methodName : StringUtil.capitalize(methodName));
}
fixes.add(new RemoveTestAnnotationFix(newMethodName));
}
final PsiClass aClass = (PsiClass)infos[0];
final String className = aClass.getName();
fixes.add(new ConvertToJUnit4Fix(className));
return fixes.toArray(new InspectionGadgetsFix[fixes.size()]);
}
private static void deleteAnnotation(ProblemDescriptor descriptor, final String qualifiedName) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiModifierListOwner)) {
return;
}
final PsiModifierListOwner method = (PsiModifierListOwner)parent;
final PsiModifierList modifierList = method.getModifierList();
if (modifierList == null) {
return;
}
final PsiAnnotation annotation = modifierList.findAnnotation(qualifiedName);
if (annotation == null) {
return;
}
annotation.delete();
}
private static class RemoveIgnoreAndRename extends RenameFix {
public RemoveIgnoreAndRename(@NonNls PsiMethod method) {
super("_" + method.getName());
}
@NotNull
@Override
public String getName() {
return InspectionGadgetsBundle.message("ignore.test.method.in.class.extending.junit3.testcase.quickfix", getTargetName());
}
@Override
public void doFix(Project project, ProblemDescriptor descriptor) {
deleteAnnotation(descriptor, IGNORE);
super.doFix(project, descriptor);
}
}
private static class ConvertToJUnit4Fix extends InspectionGadgetsFix {
private final String className;
ConvertToJUnit4Fix(String className) {
this.className = className;
}
@Override
@NotNull
public String getName() {
return InspectionGadgetsBundle.message("convert.junit3.test.class.quickfix", className);
}
@NotNull
@Override
public String getFamilyName() {
return "Convert JUnit 3 class to JUnit 4";
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiMember)) {
return;
}
final PsiMember member = (PsiMember)parent;
final PsiClass containingClass = member.getContainingClass();
if (containingClass == null) {
return;
}
final PsiReferenceList extendsList = containingClass.getExtendsList();
if (extendsList == null) {
return;
}
final PsiMethod[] methods = containingClass.getMethods();
for (PsiMethod method : methods) {
@NonNls final String name = method.getName();
if (method.hasModifierProperty(PsiModifier.STATIC)) {
continue;
}
final PsiType returnType = method.getReturnType();
if (!PsiType.VOID.equals(returnType)) {
continue;
}
final PsiModifierList modifierList = method.getModifierList();
if (name.startsWith("test")) {
addAnnotationIfNotPresent(modifierList, "org.junit.Test");
}
else if (name.equals("setUp")) {
transformSetUpOrTearDownMethod(method);
addAnnotationIfNotPresent(modifierList, "org.junit.Before");
}
else if (name.equals("tearDown")) {
transformSetUpOrTearDownMethod(method);
addAnnotationIfNotPresent(modifierList, "org.junit.After");
}
method.accept(new MethodCallModifier());
}
final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
referenceElement.delete();
}
}
private static void addAnnotationIfNotPresent(PsiModifierList modifierList, String qualifiedAnnotationName) {
if (modifierList.findAnnotation(qualifiedAnnotationName) != null) {
return;
}
final PsiAnnotation annotation = modifierList.addAnnotation(qualifiedAnnotationName);
final Project project = modifierList.getProject();
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
codeStyleManager.shortenClassReferences(annotation);
}
private static void transformSetUpOrTearDownMethod(PsiMethod method) {
final PsiModifierList modifierList = method.getModifierList();
if (modifierList.hasModifierProperty(PsiModifier.PROTECTED)) {
modifierList.setModifierProperty(PsiModifier.PROTECTED, false);
}
if (!modifierList.hasModifierProperty(PsiModifier.PUBLIC)) {
modifierList.setModifierProperty(PsiModifier.PUBLIC, true);
}
final PsiAnnotation overrideAnnotation = modifierList.findAnnotation("java.lang.Override");
if (overrideAnnotation != null) {
overrideAnnotation.delete();
}
method.accept(new SuperLifeCycleCallRemover(method.getName()));
}
private static class SuperLifeCycleCallRemover extends JavaRecursiveElementVisitor {
@NotNull private final String myLifeCycleMethodName;
private SuperLifeCycleCallRemover(@NotNull String lifeCycleMethodName) {
myLifeCycleMethodName = lifeCycleMethodName;
}
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
final String methodName = methodExpression.getReferenceName();
if (!myLifeCycleMethodName.equals(methodName)) {
return;
}
final PsiExpression target = methodExpression.getQualifierExpression();
if (!(target instanceof PsiSuperExpression)) {
return;
}
expression.delete();
}
}
private static class MethodCallModifier extends JavaRecursiveElementVisitor {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
if (methodExpression.getQualifierExpression() != null) {
return;
}
final PsiMethod method = expression.resolveMethod();
if (method == null) {
return;
}
final PsiClass aClass = method.getContainingClass();
if (aClass == null) {
return;
}
final String name = aClass.getQualifiedName();
if (!"junit.framework.Assert".equals(name)) {
return;
}
@NonNls final String newExpressionText = "org.junit.Assert." + expression.getText();
final Project project = expression.getProject();
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiExpression newExpression = factory.createExpressionFromText(newExpressionText, expression);
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
final PsiElement replacedExpression = expression.replace(newExpression);
codeStyleManager.shortenClassReferences(replacedExpression);
}
}
}
private static class RemoveTestAnnotationFix extends RenameFix {
private final String myNewName;
public RemoveTestAnnotationFix(String newName) {
super(newName);
myNewName = newName;
}
@Override
@NotNull
public String getFamilyName() {
return InspectionGadgetsBundle.message("remove.junit4.test.annotation.quickfix");
}
@Override
@NotNull
public String getName() {
return myNewName == null ? getFamilyName()
: InspectionGadgetsBundle.message("remove.junit4.test.annotation.and.rename.quickfix", myNewName);
}
@Override
public void doFix(Project project, ProblemDescriptor descriptor) {
deleteAnnotation(descriptor, "org.junit.Test");
if (myNewName != null) {
super.doFix(project, descriptor);
}
}
}
}