RuleImportCleanupSupport.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer and others.
*
* 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
*******************************************************************************/
package org.sandbox.jdt.internal.corext.fix.helper;
import static org.sandbox.jdt.internal.corext.fix.helper.lib.JUnitConstants.ORG_JUNIT_RULE;
import static org.sandbox.jdt.internal.corext.fix.helper.lib.JUnitConstants.ORG_JUNIT_RULES_TEMPORARY_FOLDER;
import static org.sandbox.jdt.internal.corext.fix.helper.lib.JUnitConstants.ORG_JUNIT_RULES_TEST_NAME;
import java.util.EnumSet;
import java.util.Set;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFixCore.CompilationUnitRewriteOperationWithSourceRange;
import org.eclipse.jdt.internal.corext.fix.LinkedProposalModelCore;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.sandbox.jdt.internal.corext.fix.JUnitCleanUpFixCore;
import org.sandbox.jdt.internal.corext.fix.helper.lib.TestNameRefactorer;
/** Coordinates removal of the shared {@code org.junit.Rule} import. */
public final class RuleImportCleanupSupport {
private RuleImportCleanupSupport() {
throw new UnsupportedOperationException("Utility class"); //$NON-NLS-1$
}
/**
* Adds one final import edit when every {@code @Rule} field in this compilation
* unit is selected and eligibility-proven for a dedicated or generic rule
* rewrite. Other rule kinds remain fail-closed and retain their import.
*/
public static void addIfSafe(CompilationUnit root, EnumSet<JUnitCleanUpFixCore> fixes,
Set<CompilationUnitRewriteOperationWithSourceRange> operations) {
if (root == null || fixes == null || operations == null || operations.isEmpty()) {
return;
}
boolean[] sawRule= { false };
boolean[] allSelectedAndEligible= { true };
root.accept(new ASTVisitor() {
@Override
public boolean visit(FieldDeclaration field) {
if (!hasRuleAnnotation(field)) {
return true;
}
sawRule[0]= true;
allSelectedAndEligible[0]&= isSelectedAndEligible(field, fixes);
return allSelectedAndEligible[0];
}
});
if (sawRule[0] && allSelectedAndEligible[0]) {
operations.add(new RemoveRuleImportOperation());
}
}
private static boolean isSelectedAndEligible(FieldDeclaration field,
EnumSet<JUnitCleanUpFixCore> fixes) {
ITypeBinding binding= field.getType().resolveBinding();
String qualifiedType= binding == null ? null : binding.getErasure().getQualifiedName();
if (ORG_JUNIT_RULES_TEMPORARY_FOLDER.equals(qualifiedType)) {
return fixes.contains(JUnitCleanUpFixCore.RULETEMPORARYFOLDER)
&& RuleTemporayFolderJUnitPlugin.assess(field).eligible();
}
if (ORG_JUNIT_RULES_TEST_NAME.equals(qualifiedType)) {
return fixes.contains(JUnitCleanUpFixCore.RULETESTNAME)
&& TestNameRefactorer.assess(field).eligible();
}
return fixes.contains(JUnitCleanUpFixCore.RULEEXTERNALRESOURCE)
&& RuleExternalResourceJUnitPlugin.isEligibleExternalResourceType(binding);
}
private static boolean hasRuleAnnotation(FieldDeclaration field) {
for (Object modifier : field.modifiers()) {
if (modifier instanceof Annotation annotation) {
ITypeBinding binding= annotation.resolveTypeBinding();
if (binding != null && ORG_JUNIT_RULE.equals(binding.getQualifiedName())) {
return true;
}
}
}
return false;
}
private static final class RemoveRuleImportOperation
extends CompilationUnitRewriteOperationWithSourceRange {
@Override
public void rewriteASTInternal(CompilationUnitRewrite cuRewrite,
LinkedProposalModelCore linkedModel) {
ImportRewrite imports= cuRewrite.getImportRewrite();
imports.removeImport(ORG_JUNIT_RULE);
}
}
}