io.codemodder.codemods.MigrateFilesCommonsIOToNIOCodemod Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-codemods Show documentation
Show all versions of core-codemods Show documentation
Codemods for fixing common errors across many Java projects
package io.codemodder.codemods;
import static io.codemodder.ast.ASTTransforms.removeImportIfUnused;
import static io.codemodder.javaparser.JavaParserTransformer.replace;
import com.contrastsecurity.sarif.Result;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MethodCallExpr;
import io.codemodder.*;
import io.codemodder.javaparser.ChangesResult;
import io.codemodder.providers.sarif.semgrep.SemgrepScan;
import java.util.Objects;
import javax.inject.Inject;
/**
* Migrates {@link org.apache.commons.io.FileUtils} APIs to {@link java.nio.file.Files} where
* possible. Some of the contracts between FileUtils and Files are similar, but not exactly the
* same, so they're not good candidates for simple migration of APIs.
*/
@Codemod(
id = "pixee:java/migrate-files-commons-io-to-nio",
importance = Importance.MEDIUM,
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW)
public final class MigrateFilesCommonsIOToNIOCodemod extends CompositeJavaParserChanger {
@Inject
public MigrateFilesCommonsIOToNIOCodemod(
final ReadLinesCodemod readLinesCodemod,
final ReadStringCodemod readStringCodemod,
final ReadBytesCodemod readBytesCodemod) {
super(readLinesCodemod, readStringCodemod, readBytesCodemod);
}
private static class ReadLinesCodemod extends CommonsToNIOToPathChanger {
private static final String RULE =
"""
rules:
- id: migrate-files-commons-io-to-nio-read-file-to-lines
pattern-either:
- pattern: (org.apache.commons.io.FileUtils).readLines($X)
- pattern: (org.apache.commons.io.FileUtils).readLines($X, (Charset $Y))
""";
@Inject
private ReadLinesCodemod(@SemgrepScan(yaml = RULE) final RuleSarif sarif) {
super(sarif, "readAllLines");
}
}
private static class ReadStringCodemod extends CommonsToNIOToPathChanger {
private static final String RULE =
"""
rules:
- id: migrate-files-commons-io-to-nio-read-file-to-string
pattern-either:
- pattern: (org.apache.commons.io.FileUtils).readFileToString($X)
- pattern: (org.apache.commons.io.FileUtils).readFileToString($X, (Charset $Y))
""";
@Inject
private ReadStringCodemod(@SemgrepScan(yaml = RULE) final RuleSarif sarif) {
super(sarif, "readString");
}
}
private static class ReadBytesCodemod extends CommonsToNIOToPathChanger {
private static final String RULE =
"""
rules:
- id: migrate-files-commons-io-to-nio-read-file-to-bytes
pattern: (org.apache.commons.io.FileUtils).readFileToByteArray($X)
""";
@Inject
private ReadBytesCodemod(@SemgrepScan(yaml = RULE) final RuleSarif sarif) {
super(sarif, "readAllBytes");
}
}
private abstract static class CommonsToNIOToPathChanger
extends SarifPluginJavaParserChanger {
private final String methodName;
private CommonsToNIOToPathChanger(final RuleSarif ruleSarif, final String methodName) {
super(ruleSarif, MethodCallExpr.class, CodemodReporterStrategy.empty());
this.methodName = Objects.requireNonNull(methodName);
}
@Override
public ChangesResult onResultFound(
final CodemodInvocationContext context,
final CompilationUnit cu,
final MethodCallExpr readFileToStringCall,
final Result result) {
switchFirstArgumentToPath(readFileToStringCall.getArguments());
boolean success =
replace(readFileToStringCall)
.withStaticMethod("java.nio.file.Files", methodName)
.withSameArguments();
if (success) {
removeImportIfUnused(cu, "org.apache.commons.io.FileUtils");
}
return success ? ChangesResult.changesApplied : ChangesResult.noChanges;
}
/**
* Changes the first argument of the given {@link NodeList} to a {@link java.nio.file.Path}.
* Assumes the first argument is a {@link java.io.File}.
*/
private static void switchFirstArgumentToPath(final NodeList arguments) {
MethodCallExpr toPath = new MethodCallExpr(arguments.get(0), "toPath");
arguments.set(0, toPath);
}
}
}