From 0195834dd26aa8878b83edcda2b12207b52e9c4a Mon Sep 17 00:00:00 2001 From: Carsten Hammer Date: Mon, 21 Oct 2024 21:23:54 +0200 Subject: [PATCH] add ExtensionContext --- .../jdt/internal/common/HelperVisitor.java | 28 +++ .../jdt/internal/common/LambdaASTVisitor.java | 17 +- .../corext/fix/JUnitCleanUpFixCore.java | 4 +- .../helper/ExternalResourceJUnitPlugin.java | 210 ++++++++++++++++++ .../corext/fix/helper/JunitHolder.java | 5 + .../RuleExternalResourceJUnitPlugin.java | 92 +++++--- .../fix/helper/RuleTestnameJUnitPlugin.java | 5 +- .../ui/tests/quickfix/Java8CleanUpTest.java | 9 +- 8 files changed, 325 insertions(+), 45 deletions(-) create mode 100644 sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/ExternalResourceJUnitPlugin.java diff --git a/sandbox_common/src/org/sandbox/jdt/internal/common/HelperVisitor.java b/sandbox_common/src/org/sandbox/jdt/internal/common/HelperVisitor.java index 59da41a0..aa3e2e26 100644 --- a/sandbox_common/src/org/sandbox/jdt/internal/common/HelperVisitor.java +++ b/sandbox_common/src/org/sandbox/jdt/internal/common/HelperVisitor.java @@ -1190,6 +1190,17 @@ public BiPredicate addTypeDeclaration(BiPredicate addTypeDeclaration(String derivedfrom, BiPredicate bs) { + predicatedata.put(VisitorEnum.TypeDeclaration, Map.ofEntries( + new AbstractMap.SimpleEntry<>(SUPERCLASSNAME, derivedfrom) + )); + return predicatemap.put(VisitorEnum.TypeDeclaration, bs); + } /** * * @param bs @@ -5215,6 +5226,23 @@ public static void callTypeDeclarationVisitor(ASTNode node, ReferenceHold hv.build(node); } + /** + * @param + * @param + * @param derivedfrom + * @param node + * @param dataholder + * @param nodesprocessed + * @param bs + */ + public static void callTypeDeclarationVisitor(String derivedfrom, ASTNode node, ReferenceHolder dataholder, Set nodesprocessed, + BiPredicate> bs) { + + HelperVisitor,V,T> hv= new HelperVisitor<>(nodesprocessed, dataholder); + hv.addTypeDeclaration(derivedfrom, bs); + hv.build(node); + } + /** * * @param diff --git a/sandbox_common/src/org/sandbox/jdt/internal/common/LambdaASTVisitor.java b/sandbox_common/src/org/sandbox/jdt/internal/common/LambdaASTVisitor.java index 3e850357..ef6343ca 100644 --- a/sandbox_common/src/org/sandbox/jdt/internal/common/LambdaASTVisitor.java +++ b/sandbox_common/src/org/sandbox/jdt/internal/common/LambdaASTVisitor.java @@ -996,8 +996,21 @@ public boolean visit(TryStatement node) { @Override public boolean visit(TypeDeclaration node) { if (this.helperVisitor.predicatemap.containsKey(VisitorEnum.TypeDeclaration)) { - return ((BiPredicate) (this.helperVisitor.predicatemap.get(VisitorEnum.TypeDeclaration))) - .test(node, this.helperVisitor.dataholder); + Map map=(Map) this.helperVisitor.getSupplierData().get(VisitorEnum.TypeDeclaration); + if(map != null) { + String superclassname=(String) map.get(HelperVisitor.SUPERCLASSNAME); + if(superclassname != null) { + boolean bothmatch=false; + ITypeBinding binding = node.resolveBinding(); + if (isExternalResource(binding,superclassname)) { + bothmatch=true; + } + if(!bothmatch) { + return true; + } + } + } + return ((BiPredicate) (this.helperVisitor.predicatemap.get(VisitorEnum.TypeDeclaration))).test(node, this.helperVisitor.dataholder); } return true; } diff --git a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/JUnitCleanUpFixCore.java b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/JUnitCleanUpFixCore.java index 2ee17c50..39bcd82d 100644 --- a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/JUnitCleanUpFixCore.java +++ b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/JUnitCleanUpFixCore.java @@ -32,6 +32,7 @@ import org.sandbox.jdt.internal.corext.fix.helper.AssertJUnitPlugin; import org.sandbox.jdt.internal.corext.fix.helper.BeforeClassJUnitPlugin; import org.sandbox.jdt.internal.corext.fix.helper.BeforeJUnitPlugin; +import org.sandbox.jdt.internal.corext.fix.helper.ExternalResourceJUnitPlugin; import org.sandbox.jdt.internal.corext.fix.helper.IgnoreJUnitPlugin; import org.sandbox.jdt.internal.corext.fix.helper.JunitHolder; import org.sandbox.jdt.internal.corext.fix.helper.RuleExternalResourceJUnitPlugin; @@ -53,7 +54,8 @@ public enum JUnitCleanUpFixCore { ASSERT(new AssertJUnitPlugin()), RULEEXTERNALRESOURCE(new RuleExternalResourceJUnitPlugin()), RULETESTNAME(new RuleTestnameJUnitPlugin()), - RULETEMPORARYFOLDER(new RuleTemporayFolderJUnitPlugin()); + RULETEMPORARYFOLDER(new RuleTemporayFolderJUnitPlugin()), + EXTERNALRESOURCE(new ExternalResourceJUnitPlugin()); AbstractTool> junitfound; diff --git a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/ExternalResourceJUnitPlugin.java b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/ExternalResourceJUnitPlugin.java new file mode 100644 index 00000000..35727da6 --- /dev/null +++ b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/ExternalResourceJUnitPlugin.java @@ -0,0 +1,210 @@ +/******************************************************************************* + * Copyright (c) 2021 Carsten Hammer. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Carsten Hammer + *******************************************************************************/ +package org.sandbox.jdt.internal.corext.fix.helper; + +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; +import org.eclipse.jdt.core.dom.rewrite.ListRewrite; +import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFixCore.CompilationUnitRewriteOperationWithSourceRange; +import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; +import org.eclipse.text.edits.TextEditGroup; +import org.sandbox.jdt.internal.common.HelperVisitor; +import org.sandbox.jdt.internal.common.ReferenceHolder; +import org.sandbox.jdt.internal.corext.fix.JUnitCleanUpFixCore; + +/** + * + * + */ +public class ExternalResourceJUnitPlugin extends AbstractTool> { + + private static final String ORG_JUNIT_JUPITER_API_EXTENSION_EXTENSION_CONTEXT = "org.junit.jupiter.api.extension.ExtensionContext"; + private static final String ORG_JUNIT_RULE = "org.junit.Rule"; + private static final String ORG_JUNIT_RULES_EXTERNAL_RESOURCE = "org.junit.rules.ExternalResource"; + private static final String ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK = "org.junit.jupiter.api.extension.BeforeEachCallback"; + private static final String ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK = "org.junit.jupiter.api.extension.AfterEachCallback"; + private static final String ORG_JUNIT_JUPITER_API_EXTENSION_EXTEND_WITH = "org.junit.jupiter.api.extension.ExtendWith"; + + + @Override + public void find(JUnitCleanUpFixCore fixcore, CompilationUnit compilationUnit, + Set operations, Set nodesprocessed) { + ReferenceHolder dataholder = new ReferenceHolder<>(); + HelperVisitor.callTypeDeclarationVisitor(ORG_JUNIT_RULES_EXTERNAL_RESOURCE,compilationUnit, dataholder, nodesprocessed, + (visited, aholder) -> processFoundNode(fixcore, operations, visited, aholder)); + } + + private boolean processFoundNode(JUnitCleanUpFixCore fixcore, + Set operations, TypeDeclaration node, + ReferenceHolder dataholder) { + JunitHolder mh = new JunitHolder(); + mh.minv = node; + dataholder.put(dataholder.size(), mh); + operations.add(fixcore.rewrite(dataholder)); + return false; + } + + @Override + public void rewrite(JUnitCleanUpFixCore upp, final ReferenceHolder hit, + final CompilationUnitRewrite cuRewrite, TextEditGroup group) { + ASTRewrite rewriter = cuRewrite.getASTRewrite(); + AST ast = cuRewrite.getRoot().getAST(); + ImportRewrite importrewriter = cuRewrite.getImportRewrite(); + for (Entry entry : hit.entrySet()) { + JunitHolder mh = entry.getValue(); + TypeDeclaration node = mh.getTypeDeclaration(); + modifyExternalResourceClass(node,rewriter,ast,group); + importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_EXTEND_WITH); + importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK); + importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK); + importrewriter.removeImport(ORG_JUNIT_RULES_EXTERNAL_RESOURCE); + importrewriter.removeImport(ORG_JUNIT_RULE); + importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_EXTENSION_CONTEXT); + } + } + + private void modifyExternalResourceClass(TypeDeclaration node, ASTRewrite rewriter,AST ast, TextEditGroup group) { + ITypeBinding binding = node.resolveBinding(); + if (isExternalResource(binding)&& hasDefaultConstructorOrNoConstructor(node)) { + if(isDirect(binding)) { + rewriter.remove(node.getSuperclassType(), group); + } + ListRewrite listRewrite = rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); + listRewrite.insertLast(ast.newSimpleType(ast.newName("BeforeEachCallback")), group); + listRewrite.insertLast(ast.newSimpleType(ast.newName("AfterEachCallback")), group); + for (MethodDeclaration method : node.getMethods()) { + if (method.getName().getIdentifier().equals("before")) { + rewriter.replace(method.getName(), ast.newSimpleName("beforeEach"), group); + extracted(rewriter, ast, method, group); + } + if (method.getName().getIdentifier().equals("after")) { + rewriter.replace(method.getName(), ast.newSimpleName("afterEach"), group); + extracted(rewriter, ast, method, group); + } + } + } + } + + private boolean isDirect(ITypeBinding fieldTypeBinding) { + ITypeBinding binding =fieldTypeBinding; + ITypeBinding superClass = binding.getSuperclass(); + + boolean isDirectlyExtendingExternalResource = false; + boolean isIndirectlyExtendingExternalResource = false; + + // Prüfen, ob die Klasse direkt oder indirekt von ExternalResource erbt + while (superClass != null) { + if (superClass.getQualifiedName().equals("org.junit.rules.ExternalResource")) { + if (binding.getSuperclass().getQualifiedName().equals("org.junit.rules.ExternalResource")) { + isDirectlyExtendingExternalResource = true; + } else { + isIndirectlyExtendingExternalResource = true; + } + break; + } + superClass = superClass.getSuperclass(); + } + return isDirectlyExtendingExternalResource; + } + + private void extracted(ASTRewrite rewriter, AST ast, MethodDeclaration method, TextEditGroup group) { + ListRewrite listRewrite; + boolean hasExtensionContext = false; + for (Object param : method.parameters()) { + if (param instanceof SingleVariableDeclaration) { + SingleVariableDeclaration variable = (SingleVariableDeclaration) param; + if (variable.getType().toString().equals("ExtensionContext")) { + hasExtensionContext = true; + break; + } + } + } + + if (!hasExtensionContext) { + // Adding the ExtensionContext parameter to the method + + SingleVariableDeclaration newParam = ast.newSingleVariableDeclaration(); + newParam.setType(ast.newSimpleType(ast.newName("ExtensionContext"))); + newParam.setName(ast.newSimpleName("context")); + + listRewrite = rewriter.getListRewrite(method, MethodDeclaration.PARAMETERS_PROPERTY); + listRewrite.insertLast(newParam, group); + } + } + + private boolean hasDefaultConstructorOrNoConstructor(TypeDeclaration classNode) { + boolean hasConstructor = false; + for (Object bodyDecl : classNode.bodyDeclarations()) { + if (bodyDecl instanceof MethodDeclaration) { + MethodDeclaration method = (MethodDeclaration) bodyDecl; + if (method.isConstructor()) { + hasConstructor = true; + if (method.parameters().isEmpty() && method.getBody() != null && method.getBody().statements().isEmpty()) { + return true; + } + } + } + } + return !hasConstructor; + } + + private boolean isExternalResource(ITypeBinding typeBinding) { + while (typeBinding != null) { + if (typeBinding.getQualifiedName().equals(ORG_JUNIT_RULES_EXTERNAL_RESOURCE)) { + return true; + } + typeBinding = typeBinding.getSuperclass(); + } + return false; + } + + @Override + public String getPreview(boolean afterRefactoring) { + if (afterRefactoring) { + return +""" + private String testName; + + @BeforeEach + void init(TestInfo testInfo) { + this.testName = testInfo.getDisplayName(); + } + @Test + public void test(){ + System.out.println("Test name: " + testName); + } +"""; //$NON-NLS-1$ + } + return +""" + @Rule + public TestName tn = new TestName(); + + @Test + public void test(){ + System.out.println("Test name: " + tn.getMethodName()); + } +"""; //$NON-NLS-1$ + } +} diff --git a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/JunitHolder.java b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/JunitHolder.java index 9d1138aa..95a66f18 100644 --- a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/JunitHolder.java +++ b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/JunitHolder.java @@ -7,6 +7,7 @@ import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.TypeDeclaration; public class JunitHolder { public ASTNode minv; @@ -31,4 +32,8 @@ public ImportDeclaration getImportDeclaration() { public FieldDeclaration getFieldDeclaration() { return (FieldDeclaration)minv; } + + public TypeDeclaration getTypeDeclaration() { + return (TypeDeclaration)minv; + } } \ No newline at end of file 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 e5db9e61..5671fa19 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 @@ -105,35 +105,42 @@ public void process(Annotation node,IJavaProject jproject,ASTRewrite rewrite,AST FieldDeclaration field = (FieldDeclaration) parent; ITypeBinding fieldTypeBinding = ((VariableDeclarationFragment) field.fragments().get(0)).resolveBinding().getType(); if (isExternalResource(fieldTypeBinding)) { - if(!fieldTypeBinding.isAnonymous()) { +// if(!fieldTypeBinding.isAnonymous()) { + if (isDirect(fieldTypeBinding)) { rewrite.remove(field, group); - ASTNode parentNode = field.getParent(); - while (parentNode != null && !(parentNode instanceof TypeDeclaration)) { - parentNode = parentNode.getParent(); - } - TypeDeclaration typedecl=(TypeDeclaration) parentNode; - if (typedecl != null) { - TypeDeclaration parentClass = typedecl; - SingleMemberAnnotation newAnnotation = ast.newSingleMemberAnnotation(); - newAnnotation.setTypeName(ast.newName("ExtendWith")); - final TypeLiteral newTypeLiteral = ast.newTypeLiteral(); - newTypeLiteral.setType(ast.newSimpleType(ast.newSimpleName(fieldTypeBinding.getName()))); - newAnnotation.setValue(newTypeLiteral); - ListRewrite modifierListRewrite = rewrite.getListRewrite(parentClass, TypeDeclaration.MODIFIERS2_PROPERTY); - modifierListRewrite.insertFirst(newAnnotation, group); - } - modifyExternalResourceClass(field, rewrite,ast, group); - importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_EXTEND_WITH); - importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK); - importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK); - importrewriter.removeImport(ORG_JUNIT_RULES_EXTERNAL_RESOURCE); importrewriter.removeImport(ORG_JUNIT_RULE); } + ASTNode parentNode = field.getParent(); + while (parentNode != null && !(parentNode instanceof TypeDeclaration)) { + parentNode = parentNode.getParent(); + } + TypeDeclaration typedecl=(TypeDeclaration) parentNode; + if (typedecl != null) { + TypeDeclaration parentClass = typedecl; + SingleMemberAnnotation newAnnotation = ast.newSingleMemberAnnotation(); + newAnnotation.setTypeName(ast.newName("ExtendWith")); + final TypeLiteral newTypeLiteral = ast.newTypeLiteral(); + newTypeLiteral.setType(ast.newSimpleType(ast.newSimpleName(fieldTypeBinding.getName()))); + newAnnotation.setValue(newTypeLiteral); + ListRewrite modifierListRewrite = rewrite.getListRewrite(parentClass, TypeDeclaration.MODIFIERS2_PROPERTY); + modifierListRewrite.insertFirst(newAnnotation, group); + } + // modifyExternalResourceClass(field, rewrite,ast, group); + importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_EXTEND_WITH); + importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK); + importrewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK); + importrewriter.removeImport(ORG_JUNIT_RULES_EXTERNAL_RESOURCE); +// } } } } } + private boolean isDirect(ITypeBinding fieldTypeBinding) { + + return fieldTypeBinding.getQualifiedName().equals("org.junit.rules.ExternalResource"); + } + private boolean isExternalResource(ITypeBinding typeBinding) { while (typeBinding != null) { if (typeBinding.getQualifiedName().equals(ORG_JUNIT_RULES_EXTERNAL_RESOURCE)) { @@ -148,21 +155,18 @@ private void modifyExternalResourceClass(FieldDeclaration field, ASTRewrite rewr field.getParent().accept(new ASTVisitor() { @Override public boolean visit(TypeDeclaration node) { - if (node.getSuperclassType() != null) { - ITypeBinding binding = node.getSuperclassType().resolveBinding(); - if (binding != null && binding.getQualifiedName().equals(ORG_JUNIT_RULES_EXTERNAL_RESOURCE)) { - rewriter.remove(node.getSuperclassType(), group); - AST ast = node.getAST(); - ListRewrite listRewrite = rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); - listRewrite.insertLast(ast.newSimpleType(ast.newName("BeforeEachCallback")), group); - listRewrite.insertLast(ast.newSimpleType(ast.newName("AfterEachCallback")), group); - for (MethodDeclaration method : node.getMethods()) { - if (method.getName().getIdentifier().equals("before")) { - rewriter.replace(method.getName(), ast.newSimpleName("beforeEach"), group); - } - if (method.getName().getIdentifier().equals("after")) { - rewriter.replace(method.getName(), ast.newSimpleName("afterEach"), group); - } + ITypeBinding binding = node.resolveBinding(); + if (isExternalResource(binding)&& hasDefaultConstructorOrNoConstructor(node)) { + rewriter.remove(node.getSuperclassType(), group); + ListRewrite listRewrite = rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); + listRewrite.insertLast(ast.newSimpleType(ast.newName("BeforeEachCallback")), group); + listRewrite.insertLast(ast.newSimpleType(ast.newName("AfterEachCallback")), group); + for (MethodDeclaration method : node.getMethods()) { + if (method.getName().getIdentifier().equals("before")) { + rewriter.replace(method.getName(), ast.newSimpleName("beforeEach"), group); + } + if (method.getName().getIdentifier().equals("after")) { + rewriter.replace(method.getName(), ast.newSimpleName("afterEach"), group); } } } @@ -171,6 +175,22 @@ public boolean visit(TypeDeclaration node) { }); } + private boolean hasDefaultConstructorOrNoConstructor(TypeDeclaration classNode) { + boolean hasConstructor = false; + for (Object bodyDecl : classNode.bodyDeclarations()) { + if (bodyDecl instanceof MethodDeclaration) { + MethodDeclaration method = (MethodDeclaration) bodyDecl; + if (method.isConstructor()) { + hasConstructor = true; + if (method.parameters().isEmpty() && method.getBody() != null && method.getBody().statements().isEmpty()) { + return true; + } + } + } + } + return !hasConstructor; + } + @Override public String getPreview(boolean afterRefactoring) { if (afterRefactoring) { diff --git a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleTestnameJUnitPlugin.java b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleTestnameJUnitPlugin.java index 1e4be5fd..04fdbfc8 100644 --- a/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleTestnameJUnitPlugin.java +++ b/sandbox_junit_cleanup/src/org/sandbox/jdt/internal/corext/fix/helper/RuleTestnameJUnitPlugin.java @@ -97,7 +97,6 @@ public void rewrite(JUnitCleanUpFixCore upp, final ReferenceHolder