From 8115c7075d96ea0ba75b41c279314262db42afd3 Mon Sep 17 00:00:00 2001 From: Carsten Hammer Date: Sat, 23 Nov 2024 07:46:09 +0100 Subject: [PATCH] Supportmorecases (#119) * extract test classes and improve test coverage * enhance test coverage, fix duplication of some changes * refactor slightly to improve readability * detect classrule --- .../corext/fix/helper/AbstractTool.java | 97 ++++++++++++++++--- .../RuleExternalResourceJUnitPlugin.java | 3 + .../quickfix/Java8/JUnitCleanupCases.java | 7 +- 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/AbstractTool.java b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/AbstractTool.java index c12c77b0..2c621a19 100644 --- a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/AbstractTool.java +++ b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/AbstractTool.java @@ -39,6 +39,7 @@ import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.FieldDeclaration; +import org.eclipse.jdt.core.dom.IExtendedModifier; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MarkerAnnotation; import org.eclipse.jdt.core.dom.MethodDeclaration; @@ -71,6 +72,10 @@ */ public abstract class AbstractTool { + private static final String ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_ALL_CALLBACK= "org.junit.jupiter.api.extension.AfterAllCallback"; + private static final String ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_ALL_CALLBACK= "org.junit.jupiter.api.extension.BeforeAllCallback"; + private static final String AFTER_ALL_CALLBACK= "AfterAllCallback"; + private static final String BEFORE_ALL_CALLBACK= "BeforeAllCallback"; private static final String TEST_NAME= "testName"; private static final String METHOD_AFTER_EACH= "afterEach"; private static final String METHOD_BEFORE_EACH= "beforeEach"; @@ -332,15 +337,70 @@ private void adaptTypeDeclaration(TypeDeclaration typeDecl, ASTRewrite rewrite, importRewrite.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK); } + private boolean isUsedAsClassRule(TypeDeclaration node, String annotationclass) { + ITypeBinding typeBinding = node.resolveBinding(); + if (typeBinding == null) { + return false; + } + + CompilationUnit cu = (CompilationUnit) node.getRoot(); + if (cu == null) { + return false; + } + final boolean[] isClassRule = {false}; + + cu.accept(new ASTVisitor() { + @Override + public boolean visit(FieldDeclaration fieldDeclaration) { + // Prüfe, ob das Feld mit @ClassRule annotiert ist + boolean hasClassRuleAnnotation = fieldDeclaration.modifiers().stream() + .filter(modifier -> modifier instanceof Annotation) // Sicherstellen, dass es sich um eine Annotation handelt + .map(modifier -> (Annotation) modifier) // Cast zu Annotation + .anyMatch(annotation -> { + String annotationBinding = ((Annotation) annotation).getTypeName().getFullyQualifiedName(); + + return annotationBinding != null && annotationclass.equals(annotationBinding); + }); + + // Prüfe, ob das Feld vom Typ der aktuellen Klasse ist + if (hasClassRuleAnnotation) { + Type fieldType = fieldDeclaration.getType(); + if (fieldType.resolveBinding() != null && fieldType.resolveBinding().isEqualTo(typeBinding)) { + isClassRule[0] = true; + } + } + return super.visit(fieldDeclaration); + } + }); + + return isClassRule[0]; + } + private void refactorToImplementCallbacks(TypeDeclaration node, ASTRewrite rewriter, AST ast, TextEditGroup group, - ImportRewrite importRewriter) { - rewriter.remove(node.getSuperclassType(), group); - importRewriter.removeImport(ORG_JUNIT_RULES_EXTERNAL_RESOURCE); - ListRewrite listRewrite= rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); - addInterfaceCallback(listRewrite, ast, BEFORE_EACH_CALLBACK, group); - addInterfaceCallback(listRewrite, ast, AFTER_EACH_CALLBACK, group); - importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK); - importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK); + ImportRewrite importRewriter) { + // Entferne die Superklasse ExternalResource + rewriter.remove(node.getSuperclassType(), group); + importRewriter.removeImport(ORG_JUNIT_RULES_EXTERNAL_RESOURCE); + + // Prüfe, ob die Klasse statisch verwendet wird + boolean isStaticUsage = isUsedAsClassRule(node, "org.junit.ClassRule"); + + ListRewrite listRewrite = rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); + + // Füge die entsprechenden Callback-Interfaces hinzu + if (isStaticUsage) { + // Verwende BeforeAllCallback und AfterAllCallback für statische Ressourcen + addInterfaceCallback(listRewrite, ast, BEFORE_ALL_CALLBACK, group); + addInterfaceCallback(listRewrite, ast, AFTER_ALL_CALLBACK, group); + importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_ALL_CALLBACK); + importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_ALL_CALLBACK); + } else { + // Verwende BeforeEachCallback und AfterEachCallback für nicht-statische Ressourcen + addInterfaceCallback(listRewrite, ast, BEFORE_EACH_CALLBACK, group); + addInterfaceCallback(listRewrite, ast, AFTER_EACH_CALLBACK, group); + importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK); + importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK); + } } private void addBeforeAndAfterEachCallbacks(TypeDeclaration typeDecl, ASTRewrite rewrite, AST ast, @@ -538,12 +598,12 @@ protected boolean hasDefaultConstructorOrNoConstructor(TypeDeclaration classNode return !hasConstructor; } - private boolean isAnnotatedWithRule(BodyDeclaration declaration) { + private boolean isAnnotatedWithRule(BodyDeclaration declaration, String annotationclass) { for (Object modifier : declaration.modifiers()) { if (modifier instanceof Annotation) { Annotation annotation= (Annotation) modifier; ITypeBinding binding= annotation.resolveTypeBinding(); - if (binding != null && ORG_JUNIT_RULE.equals(binding.getQualifiedName())) { + if (binding != null && annotationclass.equals(binding.getQualifiedName())) { return true; } } @@ -605,8 +665,15 @@ public void migrateRuleToRegisterExtensionAndAdaptHierarchy(Optional in group); } for (FieldDeclaration field : testClass.getFields()) { - if (isAnnotatedWithRule(field) && isExternalResource(field)) { - removeRuleAnnotation(field, rewrite, group, importRewrite); + if (isAnnotatedWithRule(field, ORG_JUNIT_RULE) && isExternalResource(field)) { + removeRuleAnnotation(field, rewrite, group, importRewrite, ORG_JUNIT_RULE); + addRegisterExtensionAnnotation(field, rewrite, ast, importRewrite, group); + importRewrite.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_REGISTER_EXTENSION); + ITypeBinding fieldType= ((VariableDeclarationFragment) field.fragments().get(0)).resolveBinding() + .getType(); + adaptExternalResourceHierarchy(fieldType, rewrite, ast, importRewrite, group); + } else if (isAnnotatedWithRule(field, ORG_JUNIT_CLASS_RULE) && isExternalResource(field)) { + removeRuleAnnotation(field, rewrite, group, importRewrite, ORG_JUNIT_CLASS_RULE); addRegisterExtensionAnnotation(field, rewrite, ast, importRewrite, group); importRewrite.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_REGISTER_EXTENSION); ITypeBinding fieldType= ((VariableDeclarationFragment) field.fragments().get(0)).resolveBinding() @@ -644,15 +711,15 @@ public void process(Annotation node, IJavaProject jproject, ASTRewrite rewrite, } private void removeRuleAnnotation(BodyDeclaration declaration, ASTRewrite rewriter, TextEditGroup group, - ImportRewrite importRewriter) { + ImportRewrite importRewriter, String annotationclass) { List modifiers= declaration.modifiers(); for (Object modifier : modifiers) { if (modifier instanceof Annotation) { Annotation annotation= (Annotation) modifier; ITypeBinding binding= annotation.resolveTypeBinding(); - if (binding != null && binding.getQualifiedName().equals(ORG_JUNIT_RULE)) { + if (binding != null && binding.getQualifiedName().equals(annotationclass)) { rewriter.remove(annotation, group); - importRewriter.removeImport(ORG_JUNIT_RULE); + importRewriter.removeImport(annotationclass); break; } } diff --git a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleExternalResourceJUnitPlugin.java b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleExternalResourceJUnitPlugin.java index cfa0f86f..a5f05315 100644 --- a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleExternalResourceJUnitPlugin.java +++ b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleExternalResourceJUnitPlugin.java @@ -44,6 +44,9 @@ public void find(JUnitCleanUpFixCore fixcore, CompilationUnit compilationUnit, HelperVisitor.callFieldDeclarationVisitor(ORG_JUNIT_RULE, ORG_JUNIT_RULES_EXTERNAL_RESOURCE, compilationUnit, dataholder, nodesprocessed, (visited, aholder) -> processFoundNode(fixcore, operations, visited, aholder)); + HelperVisitor.callFieldDeclarationVisitor(ORG_JUNIT_CLASS_RULE, ORG_JUNIT_RULES_EXTERNAL_RESOURCE, compilationUnit, + dataholder, nodesprocessed, + (visited, aholder) -> processFoundNode(fixcore, operations, visited, aholder)); } private boolean processFoundNode(JUnitCleanUpFixCore fixcore, diff --git a/sandbox_junit_cleanup_test/src/org/eclipse/jdt/ui/tests/quickfix/Java8/JUnitCleanupCases.java b/sandbox_junit_cleanup_test/src/org/eclipse/jdt/ui/tests/quickfix/Java8/JUnitCleanupCases.java index 0391e3d1..c827a1a1 100644 --- a/sandbox_junit_cleanup_test/src/org/eclipse/jdt/ui/tests/quickfix/Java8/JUnitCleanupCases.java +++ b/sandbox_junit_cleanup_test/src/org/eclipse/jdt/ui/tests/quickfix/Java8/JUnitCleanupCases.java @@ -739,7 +739,7 @@ protected void after() { } @ClassRule - public static ExternalResource staticResource = new StaticExternalResource(); + public static ExternalResource staticResource = new StaticExternalResource(); // Klasse mit Konstruktor final class ConstructedExternalResource extends ExternalResource { @@ -792,7 +792,6 @@ public void testWithMultipleResources() { """ package test; -import org.junit.ClassRule; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; @@ -845,8 +844,8 @@ public void afterEach(ExtensionContext context) { } } - @ClassRule - public static ExternalResource staticResource = new StaticExternalResource(); + @RegisterExtension + public static ExternalResource staticResource = new StaticExternalResource(); // Klasse mit Konstruktor final class ConstructedExternalResource implements BeforeEachCallback, AfterEachCallback {