Skip to content

Commit

Permalink
add ExtensionContext
Browse files Browse the repository at this point in the history
  • Loading branch information
carstenartur committed Oct 21, 2024
1 parent 87fbab1 commit 0195834
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,17 @@ public BiPredicate<? extends ASTNode, E> addTypeDeclaration(BiPredicate<TypeDecl
return predicatemap.put(VisitorEnum.TypeDeclaration, bs);
}

/**
* @param derivedfrom
* @param bs
* @return
*/
public BiPredicate<? extends ASTNode, E> addTypeDeclaration(String derivedfrom, BiPredicate<TypeDeclaration, E> bs) {
predicatedata.put(VisitorEnum.TypeDeclaration, Map.ofEntries(
new AbstractMap.SimpleEntry<>(SUPERCLASSNAME, derivedfrom)
));
return predicatemap.put(VisitorEnum.TypeDeclaration, bs);
}
/**
*
* @param bs
Expand Down Expand Up @@ -5215,6 +5226,23 @@ public static <V, T> void callTypeDeclarationVisitor(ASTNode node, ReferenceHold
hv.build(node);
}

/**
* @param <V>
* @param <T>
* @param derivedfrom
* @param node
* @param dataholder
* @param nodesprocessed
* @param bs
*/
public static <V, T> void callTypeDeclarationVisitor(String derivedfrom, ASTNode node, ReferenceHolder<V, T> dataholder, Set<ASTNode> nodesprocessed,
BiPredicate<TypeDeclaration, ReferenceHolder<V, T>> bs) {

HelperVisitor<ReferenceHolder<V, T>,V,T> hv= new HelperVisitor<>(nodesprocessed, dataholder);
hv.addTypeDeclaration(derivedfrom, bs);
hv.build(node);
}

/**
*
* @param <V>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -996,8 +996,21 @@ public boolean visit(TryStatement node) {
@Override
public boolean visit(TypeDeclaration node) {
if (this.helperVisitor.predicatemap.containsKey(VisitorEnum.TypeDeclaration)) {
return ((BiPredicate<TypeDeclaration, E>) (this.helperVisitor.predicatemap.get(VisitorEnum.TypeDeclaration)))
.test(node, this.helperVisitor.dataholder);
Map<String, Object> map=(Map<String, Object>) 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<TypeDeclaration, E>) (this.helperVisitor.predicatemap.get(VisitorEnum.TypeDeclaration))).test(node, this.helperVisitor.dataholder);
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<ReferenceHolder<Integer, JunitHolder>> junitfound;

Expand Down
Original file line number Diff line number Diff line change
@@ -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<ReferenceHolder<Integer, JunitHolder>> {

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<CompilationUnitRewriteOperationWithSourceRange> operations, Set<ASTNode> nodesprocessed) {
ReferenceHolder<Integer, JunitHolder> 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<CompilationUnitRewriteOperationWithSourceRange> operations, TypeDeclaration node,
ReferenceHolder<Integer, JunitHolder> 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<Integer, JunitHolder> hit,
final CompilationUnitRewrite cuRewrite, TextEditGroup group) {
ASTRewrite rewriter = cuRewrite.getASTRewrite();
AST ast = cuRewrite.getRoot().getAST();
ImportRewrite importrewriter = cuRewrite.getImportRewrite();
for (Entry<Integer, JunitHolder> 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")) {

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
rewriter.replace(method.getName(), ast.newSimpleName("beforeEach"), group);
extracted(rewriter, ast, method, group);
}
if (method.getName().getIdentifier().equals("after")) {

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
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;

Check warning

Code scanning / PMD

Avoid unused local variables such as 'element'. Warning

Avoid unused local variables such as 'isIndirectlyExtendingExternalResource'.

Check notice

Code scanning / Pmd (reported by Codacy)

Avoid unused local variables such as 'isIndirectlyExtendingExternalResource'. Note

Avoid unused local variables such as 'isIndirectlyExtendingExternalResource'.

// Prüfen, ob die Klasse direkt oder indirekt von ExternalResource erbt
while (superClass != null) {
if (superClass.getQualifiedName().equals("org.junit.rules.ExternalResource")) {

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
if (binding.getSuperclass().getQualifiedName().equals("org.junit.rules.ExternalResource")) {

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
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")) {

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
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)) {

Check warning

Code scanning / PMD

Position literals first in String comparisons Warning

Position literals first in String comparisons
return true;
}
typeBinding = typeBinding.getSuperclass();

Check notice

Code scanning / Pmd (reported by Codacy)

Avoid reassigning parameters such as 'typeBinding' Note

Avoid reassigning parameters such as 'typeBinding'
}
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$
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,4 +32,8 @@ public ImportDeclaration getImportDeclaration() {
public FieldDeclaration getFieldDeclaration() {
return (FieldDeclaration)minv;
}

public TypeDeclaration getTypeDeclaration() {
return (TypeDeclaration)minv;
}
}
Loading

0 comments on commit 0195834

Please sign in to comment.