いいチャレンジのような音ですが、これを行うための自動ツールも見つけられませんでした。すでに説明したように、コードの書式を変更するには多くのオプションがあります。その他の小さな問題では、おそらくCheckstyleをコマンドラインから実行し、修正可能な警告をフィルタリングすることができます。 Javaソースコードを解析して変更するためのライブラリは、例えばJavaParserのように実際に変更を加えるのに役立ちます。おそらく、JavaParserのようなJavaソースコード操作ツールを使用して、比較的短時間でカスタムツールを書くことができます。
(使用することができANTLRのような他のツールがありますが、スタックオーバーフロー上のより多くのアイデアのためにこの質問を参照してください。Java: parse java source code, extract methodsRoasterとJavaPoetのようないくつかのライブラリは、このような状況では、それらはあまり適してメソッドの本体を解析しません。 。
// Example.java:
package q45326752;
public class Example {
public static void main(String[] arguments) {
System.out.println("Hello Checkstyle...");
int perfectNumber = 1 + 2 + 3;
System.out.println("Perfect number: " + perfectNumber);
}
}
Checkstyle warnings:
java -jar checkstyle-8.0-all.jar -c checkstyle-checks.xml Example.java
[ERROR] Example.java:4:29: Parameter arguments should be final. [FinalParameters]
[ERROR] Example.java:7:13: Variable 'perfectNumber' should be declared final. [FinalLocalVariable]
:)非常に簡単な例として
は、我々はのCheckstyleのみ)FinalParameters
チェックしFinalLocalVariable
最小限checkstyle-checks.xml
Checkstyle構成ファイルを使用して(2つのメッセージを生成するために小さなJavaクラスを持っていると仮定します
JavaParserを使用すると、このような2つの警告が自動的に修正される可能性があります(コードはそのアイデアを実証しようとします。いくつかの部分)は、今では無視されています:
// AutomaticCheckstyleFix.java:
package q45326752;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.*;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.expr.*;
import com.github.javaparser.ast.stmt.*;
import java.io.File;
import java.io.FileNotFoundException;
public class AutomaticCheckstyleFix {
private MethodDeclaration bestMatchMethod;
private int bestMatchMethodLineNumber;
private Statement statementByLineNumber;
public static void main(final String[] arguments) {
final String filePath = "q45326752\\input\\Example.java";
try {
new AutomaticCheckstyleFix().fixSimpleCheckstyleIssues(new File(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private void fixSimpleCheckstyleIssues(File file) throws FileNotFoundException {
CompilationUnit javaClass = JavaParser.parse(file);
System.out.println("Original Java class:\n\n" + javaClass);
System.out.println();
System.out.println();
// Example.java:4:29: Parameter arguments should be final. [FinalParameters]
MethodDeclaration methodIssue1 = getMethodByLineNumber(javaClass, 4);
if (methodIssue1 != null) {
methodIssue1.getParameterByName("arguments")
.ifPresent(parameter -> parameter.setModifier(Modifier.FINAL, true));
}
// Example.java:7:13: Variable 'perfectNumber' should be declared final.
// [FinalLocalVariable]
Statement statementIssue2 = getStatementByLineNumber(javaClass, 7);
if (statementIssue2 instanceof ExpressionStmt) {
Expression expression = ((ExpressionStmt) statementIssue2).getExpression();
if (expression instanceof VariableDeclarationExpr) {
((VariableDeclarationExpr) expression).addModifier(Modifier.FINAL);
}
}
System.out.println("Modified Java class:\n\n" + javaClass);
}
private MethodDeclaration getMethodByLineNumber(CompilationUnit javaClass,
int issueLineNumber) {
bestMatchMethod = null;
javaClass.getTypes().forEach(type -> type.getMembers().stream()
.filter(declaration -> declaration instanceof MethodDeclaration)
.forEach(method -> {
if (method.getTokenRange().isPresent()) {
int methodLineNumber = method.getTokenRange().get()
.getBegin().getRange().begin.line;
if (bestMatchMethod == null
|| (methodLineNumber < issueLineNumber
&& methodLineNumber > bestMatchMethodLineNumber)) {
bestMatchMethod = (MethodDeclaration) method;
bestMatchMethodLineNumber = methodLineNumber;
}
}
})
);
return bestMatchMethod;
}
private Statement getStatementByLineNumber(CompilationUnit javaClass,
int issueLineNumber) {
statementByLineNumber = null;
MethodDeclaration method = getMethodByLineNumber(javaClass, issueLineNumber);
if (method != null) {
method.getBody().ifPresent(blockStmt
-> blockStmt.getStatements().forEach(statement
-> statement.getTokenRange().ifPresent(tokenRange -> {
if (tokenRange.getBegin().getRange().begin.line == issueLineNumber) {
statementByLineNumber = statement;
}
})));
}
return statementByLineNumber;
}
}
別のアプローチは、あなたがのために自動修正を作成しようとしているものに基づいて新しいのCheckstyleプラグインを作成することができます。警告を出すだけでなく、これらの問題が修正された修正バージョンを生成するのに十分な情報があるかもしれません。
個人的に私は、コミット時に自動的に問題が解決されることを躊躇します。多くの簡単な修正がある場合、自動化は歓迎ですが、これらの変更をコミットする前に確認したいと思います。このようなツールを実行して変更を確認すると、非常に簡単な方法で多くの簡単な問題を解決できます。
Iが自動的に修正することができると思ういくつかのチェック:最終
ModifierOrder追加:
EclipseでもCheckstyleの問題を解決できるようです。https://stackoverflow.com/a/8417213/1694043 Eclipseがプロジェクト全体に対してこれを行うようにしたり、この機能を分離してスタンドアロンのツールから実行することは可能かもしれません。 –