io.codemodder.examples.MakeJUnit5TestsFinalCodemod Maven / Gradle / Ivy
package io.codemodder.examples;
import com.contrastsecurity.sarif.Result;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import io.codemodder.*;
import io.codemodder.codetf.CodeTFReference;
import io.codemodder.javaparser.ChangesResult;
import io.codemodder.providers.sarif.semgrep.SemgrepScan;
import java.nio.file.Path;
import java.util.List;
import javax.inject.Inject;
/** A codemod that adds final modifiers to JUnit 5 tests. */
@Codemod(
id = "codemodder:java/make-junit5-tests-final",
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
importance = Importance.LOW)
public final class MakeJUnit5TestsFinalCodemod
extends SarifPluginJavaParserChanger {
private static final String DETECTION_RULE =
"""
rules:
- id: find-nonfinal-junit-class-modifiers
patterns:
- pattern: class $CLASS { ... }
- pattern-not: final class $CLASS { ... }
- pattern-not: abstract class $CLASS { ... }
- metavariable-regex:
metavariable: $CLASS
regex: .*Test
- pattern-inside: |
...
import org.junit.jupiter.api.Test;
...
""";
@Inject
public MakeJUnit5TestsFinalCodemod(@SemgrepScan(yaml = DETECTION_RULE) final RuleSarif sarif) {
super(sarif, ClassOrInterfaceDeclaration.class, CodemodReporterStrategy.empty());
}
@Override
public ChangesResult onResultFound(
final CodemodInvocationContext context,
final CompilationUnit cu,
final ClassOrInterfaceDeclaration typeDefinition,
final Result result) {
typeDefinition.getModifiers().add(Modifier.finalModifier());
return ChangesResult.changesApplied;
}
@Override
public String getSummary() {
return "Tests made final!";
}
@Override
public String getDescription() {
return "JUnit 5 tests should be final!";
}
@Override
public List getReferences() {
return List.of(
new CodeTFReference(
"https://github.com/HugoMatilla/Effective-JAVA-Summary#17-design-and-document-for-inheritance-or-else-prohibit-it",
"Effective Java (Chapter 17: Design and document for inheritance or else prohibit it)"));
}
@Override
public String getIndividualChangeDescription(final Path filePath, final CodemodChange change) {
return "Made class final";
}
}