目的
ソースレビューの数が多く大変なため、単純なパターンは自動的にチェックするためのツールを作成したい。
※仕掛中
copied!
package check;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class JavaCodingConventionChecker {
// private static final String INDENTATION = " ";
private static final Pattern PATTERN_CLASS_NAME = Pattern.compile("^[A-Z][a-zA-Z0-9]*$");
private static final Pattern PATTERN_METHOD_NAME = Pattern.compile("^[a-z][a-zA-Z0-9]*$");
private static final Pattern PATTERN_VARIABLE_NAME = Pattern.compile("^[a-z][a-zA-Z0-9]*$");
private static final Pattern PATTERN_CONSTANT_NAME = Pattern.compile("^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$");
private static final Pattern PATTERN_COMMENT = Pattern.compile("^\\s*(//|/\\*|\\*)?\\s*(.*)$");
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: JavaCodingConventionChecker ");
System.exit(1);
}
File directory = new File(args[0]);
if (!directory.isDirectory()) {
System.err.println("Not a directory: " + directory.getAbsolutePath());
System.exit(1);
}
checkDirectory(directory);
System.out.println("Java coding convention check passed!");
}
private static void checkDirectory(File directory) throws IOException {
for (File file : directory.listFiles()) {
if (file.isDirectory()) {
checkDirectory(file);
} else if (file.getName().endsWith(".java")) {
checkFile(file);
}
}
}
private static void checkFile(File file) throws IOException {
int lineNumber = 0;
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
lineNumber++;
checkLine(line, lineNumber);
}
}
}
private static void checkLine(String line, int lineNumber) {
//クラス名が大文字始まりかどうか、キャメルケースであるかどうかをチェックする
checkClassName(line, lineNumber);
//メソッド名が小文字始まりかどうか、キャメルケースであるかどうかをチェックする
checkMethodName(line, lineNumber);
//変数名が小文字始まりかどうか、キャメルケースであるかどうかをチェックする
checkVariableName(line, lineNumber);
//定数名が大文字であり、単語の区切りにはアンダースコアを使用しているかどうかをチェックする
checkConstantName(line, lineNumber);
//インデントがタブまたは4つのスペースで行われているかどうかをチェックする
checkIndentation(line, lineNumber);
//コメントのインデントが正しいかどうか、コメントがピリオドで終わっているかどうかをチェックする
checkComment(line, lineNumber);
}
private static void checkClassName(String line, int lineNumber) {
if (line.contains("class ")) {
String className = line.split("class ")[1].split(" ")[0];
if (!PATTERN_CLASS_NAME.matcher(className).matches()) {
System.err.println("Invalid class name on line " + lineNumber + ": " + className);
}
}
}
private static void checkMethodName(String line, int lineNumber) {
if (line.contains("void ")) {
String methodName = line.split("void ")[1].split("\\(")[0];
if (!PATTERN_METHOD_NAME.matcher(methodName).matches()) {
System.err.println("Invalid method name on line " + lineNumber + ": " + methodName);
}
}
}
private static void checkVariableName(String line, int lineNumber) {
if (line.contains("=") && !line.contains("==") && !line.contains("!=")) {
String variableName = line.split("=")[0].trim().split(" ")[1];
if (!PATTERN_VARIABLE_NAME.matcher(variableName).matches()) {
System.err.println("Invalid variable name on line " + lineNumber + ": " + variableName);
}
}
}
private static void checkConstantName(String line, int lineNumber) {
if (line.contains("final ")) {
String[] parts = line.split("final ");
for (int i = 1; i < parts.length; i++) {
String constantName = parts[i].split(" ")[0];
if (!PATTERN_CONSTANT_NAME.matcher(constantName).matches()) {
System.err.println("Invalid constant name on line " + lineNumber + ": " + constantName);
}
}
}
}
private static void checkIndentation(String line, int lineNumber) {
// コメントアウト行の場合はチェックをスキップする
if (line.trim().startsWith("//") || line.trim().startsWith("/*") || line.trim().startsWith("*")) {
return;
}
int indentationLevel = 0;
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ') {
indentationLevel++;
} else if (line.charAt(i) == '\t') {
indentationLevel += 4;
} else {
break;
}
}
if (indentationLevel % 4 != 0) {
System.err.println("Invalid indentation on line " + lineNumber + ": " + line);
}
}
private static void checkComment(String line, int lineNumber) {
Matcher matcher = PATTERN_COMMENT.matcher(line);
if (matcher.matches()) {
String comment = "";
if (matcher.find()) {
comment = matcher.group(2);
}
if (comment.startsWith(" ")) {
System.err.println("Invalid comment indentation on line " + lineNumber + ": " + line);
}
if (comment.length() > 0 && !comment.endsWith(".")) {
System.err.println("Missing period at end of comment on line " + lineNumber + ": " + line);
}
}
}
}