JUnitCleanUpFixCore.java
/*******************************************************************************
* 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;
import static org.sandbox.jdt.internal.corext.fix.helper.lib.JUnitConstants.ORG_JUNIT_JUPITER_SUITE;
import static org.sandbox.jdt.internal.corext.fix.helper.lib.JUnitConstants.ORG_JUNIT_RUNWITH;
import static org.sandbox.jdt.internal.corext.fix.helper.lib.JUnitConstants.ORG_JUNIT_SUITE;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
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.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.text.edits.TextEditGroup;
import org.sandbox.jdt.internal.common.ReferenceHolder;
import org.sandbox.jdt.internal.corext.fix.helper.AfterClassJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.AfterJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.AssertJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.AssertOptimizationJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.AssumeJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.AssumeOptimizationJUnitPlugin;
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.CategoryJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.ExternalResourceJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.FixMethodOrderJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.IgnoreJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.LostTestFinderJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.RuleErrorCollectorJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.RuleExpectedExceptionJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.RuleExternalResourceJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.RuleTemporayFolderJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.RuleTestnameJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.RuleTimeoutJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.RunWithJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.SuiteMethodJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.TestExpectedAndTimeoutJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.TestExpectedJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.TestJUnit3Plugin;
import org.sandbox.jdt.internal.corext.fix.helper.TestJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.TestTimeoutJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.ThrowingRunnableJUnitPlugin;
import org.sandbox.jdt.internal.corext.fix.helper.lib.AbstractTool;
import org.sandbox.jdt.internal.corext.fix.helper.lib.JunitHolder;
import org.sandbox.jdt.internal.ui.fix.MultiFixMessages;
public enum JUnitCleanUpFixCore {
BEFORE(new BeforeJUnitPlugin()),
AFTER(new AfterJUnitPlugin()),
TEST(new TestJUnitPlugin()),
TEST3(new TestJUnit3Plugin()),
TEST_EXPECTED_TIMEOUT(new TestExpectedAndTimeoutJUnitPlugin()),
TEST_TIMEOUT(new TestTimeoutJUnitPlugin()),
TEST_EXPECTED(new TestExpectedJUnitPlugin()),
BEFORECLASS(new BeforeClassJUnitPlugin()),
AFTERCLASS(new AfterClassJUnitPlugin()),
IGNORE(new IgnoreJUnitPlugin()),
CATEGORY(new CategoryJUnitPlugin()),
FIX_METHOD_ORDER(new FixMethodOrderJUnitPlugin()),
RUNWITH(new RunWithJUnitPlugin()),
SUITEMETHOD(new SuiteMethodJUnitPlugin()),
ASSERT(new AssertJUnitPlugin()),
ASSERT_OPTIMIZATION(new AssertOptimizationJUnitPlugin()),
ASSUME(new AssumeJUnitPlugin()),
ASSUME_OPTIMIZATION(new AssumeOptimizationJUnitPlugin()),
// Dedicated rule migrations must claim their types before the generic
// ExternalResource rule fallback sees the same field.
RULETESTNAME(new RuleTestnameJUnitPlugin()),
RULETEMPORARYFOLDER(new RuleTemporayFolderJUnitPlugin()),
RULETIMEOUT(new RuleTimeoutJUnitPlugin()),
RULEEXPECTEDEXCEPTION(new RuleExpectedExceptionJUnitPlugin()),
RULEERRORCOLLECTOR(new RuleErrorCollectorJUnitPlugin()),
RULEEXTERNALRESOURCE(new RuleExternalResourceJUnitPlugin()),
EXTERNALRESOURCE(new ExternalResourceJUnitPlugin()),
LOSTTESTS(new LostTestFinderJUnitPlugin()),
PARAMETERIZED(new ClosedParameterizedTestJUnitPlugin()),
THROWINGRUNNABLE(new ThrowingRunnableJUnitPlugin());
AbstractTool<ReferenceHolder<Integer, JunitHolder>> junitfound;
@SuppressWarnings("unchecked")
JUnitCleanUpFixCore(AbstractTool<? extends ReferenceHolder<Integer, JunitHolder>> junitprocess) {
this.junitfound= (AbstractTool<ReferenceHolder<Integer, JunitHolder>>) junitprocess;
}
public String getPreview(boolean i) {
long countother= junitfound.getPreview(!i).lines().count();
StringBuilder preview= new StringBuilder(junitfound.getPreview(i));
long countnow= preview.toString().lines().count();
if(countnow<countother) {
for (long ii=0;ii<countother-countnow;ii++) {
preview.append(System.lineSeparator());
}
}
return preview.toString();
}
public void findOperations(final CompilationUnit compilationUnit,
final Set<CompilationUnitRewriteOperationWithSourceRange> operations, final Set<ASTNode> nodesprocessed) {
junitfound.find(this, compilationUnit, operations, nodesprocessed);
}
public CompilationUnitRewriteOperationWithSourceRange rewrite(final ReferenceHolder<Integer, JunitHolder> hit) {
JunitHolder rangeAnchor= hit.get(0);
JunitHolder snapshot= hit.get(hit.size() - 1);
ReferenceHolder<Integer, JunitHolder> operationData= ReferenceHolder.createIndexed();
operationData.put(Integer.valueOf(0), snapshot);
boolean suiteRunnerPresent= this == RUNWITH && hasSuiteRunner(snapshot.getMinv());
return new CompilationUnitRewriteOperationWithSourceRange() {
@Override
public void rewriteASTInternal(final CompilationUnitRewrite cuRewrite,
final LinkedProposalModelCore linkedModel) throws CoreException {
TextEditGroup group= createTextEditGroup(Messages.format(MultiFixMessages.JUnitCleanUp_description,
new Object[] { JUnitCleanUpFixCore.this.toString() }), cuRewrite);
TightSourceRangeComputer rangeComputer;
ASTRewrite rewrite= cuRewrite.getASTRewrite();
if (rewrite.getExtendedSourceRangeComputer() instanceof TightSourceRangeComputer) {
rangeComputer= (TightSourceRangeComputer) rewrite.getExtendedSourceRangeComputer();
} else {
rangeComputer= new TightSourceRangeComputer();
}
// Preserve historical operation ordering while keeping rewrite data isolated.
rangeComputer.addTightSourceNode(rangeAnchor.getMinv());
rewrite.setTargetSourceRangeComputer(rangeComputer);
junitfound.rewrite(JUnitCleanUpFixCore.this, operationData, cuRewrite, group);
if (suiteRunnerPresent) {
// A later SuiteClasses rewrite removes the old Suite simple name. Re-add
// the JUnit Platform import after every related independent operation.
cuRewrite.getImportRewrite().addImport(ORG_JUNIT_JUPITER_SUITE);
}
}
};
}
private static boolean hasSuiteRunner(ASTNode node) {
if (!(node.getRoot() instanceof CompilationUnit root)) {
return false;
}
boolean[] result= new boolean[1];
root.accept(new ASTVisitor() {
@Override
public boolean visit(SingleMemberAnnotation annotation) {
ITypeBinding annotationType= annotation.resolveTypeBinding();
String annotationName= annotationType == null
? annotation.getTypeName().getFullyQualifiedName()
: annotationType.getQualifiedName();
if (!ORG_JUNIT_RUNWITH.equals(annotationName) && !"RunWith".equals(annotationName)) { //$NON-NLS-1$
return true;
}
if (annotation.getValue() instanceof TypeLiteral typeLiteral) {
ITypeBinding runnerBinding= typeLiteral.getType().resolveBinding();
String runnerName= runnerBinding == null ? typeLiteral.getType().toString()
: runnerBinding.getQualifiedName();
if (ORG_JUNIT_SUITE.equals(runnerName) || "Suite".equals(runnerName)) { //$NON-NLS-1$
result[0]= true;
return false;
}
}
return true;
}
});
return result[0];
}
@Override
public String toString() {
return junitfound.toString();
}
}