154 lines
6.2 KiB
Java
154 lines
6.2 KiB
Java
package com.google.checkstyle.test.base;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
|
|
|
|
public class IndentationConfigurationBuilder extends ConfigurationBuilder
|
|
{
|
|
private static final int TAB_WIDTH = 4;
|
|
|
|
public IndentationConfigurationBuilder(File aROOT) {
|
|
super(aROOT);
|
|
}
|
|
|
|
@Override
|
|
public Integer[] getLinesWithWarn(String aFileName) throws IOException {
|
|
return getLinesWithWarnAndCheckComments(aFileName, TAB_WIDTH);
|
|
}
|
|
|
|
private static final Pattern NONEMPTY_LINE_REGEX =
|
|
Pattern.compile(".*?\\S+.*?");
|
|
|
|
private static final Pattern LINE_WITH_COMMENT_REGEX =
|
|
Pattern.compile(".*?\\S+.*?(//indent:(\\d+) exp:((>=\\d+)|(\\d+(,\\d+)*?))( warn)?)");
|
|
|
|
private static final Pattern GET_INDENT_FROM_COMMENT_REGEX =
|
|
Pattern.compile("//indent:(\\d+).*?");
|
|
|
|
private static final Pattern MULTILEVEL_COMMENT_REGEX =
|
|
Pattern.compile("//indent:\\d+ exp:(\\d+(,\\d+)+?)( warn)?");
|
|
|
|
private static final Pattern SINGLE_LEVEL_COMMENT_REGEX =
|
|
Pattern.compile("//indent:\\d+ exp:(\\d+)( warn)?");
|
|
|
|
private static final Pattern NON_STRICT_LEVEL_COMMENT_REGEX =
|
|
Pattern.compile("//indent:\\d+ exp:>=(\\d+)( warn)?");
|
|
|
|
private static Integer[] getLinesWithWarnAndCheckComments(String aFileName,
|
|
final int tabWidth)
|
|
throws IOException
|
|
{
|
|
List<Integer> result = new ArrayList<>();
|
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(
|
|
new FileInputStream(aFileName), StandardCharsets.UTF_8))) {
|
|
int lineNumber = 1;
|
|
for (String line = br.readLine(); line != null; line = br.readLine()) {
|
|
Matcher match = LINE_WITH_COMMENT_REGEX.matcher(line);
|
|
if (match.matches()) {
|
|
final String comment = match.group(1);
|
|
final int indentInComment = getIndentFromComment(comment);
|
|
final int actualIndent = getLineStart(line, tabWidth);
|
|
|
|
if (actualIndent != indentInComment) {
|
|
throw new IllegalStateException(String.format(
|
|
"File \"%1$s\" has incorrect indentation in comment."
|
|
+ "Line %2$d: comment:%3$d, actual:%4$d.",
|
|
aFileName,
|
|
lineNumber,
|
|
indentInComment,
|
|
actualIndent));
|
|
}
|
|
|
|
if (isWarnComment(comment)) {
|
|
result.add(lineNumber);
|
|
}
|
|
|
|
if (!isCommentConsistent(comment)) {
|
|
throw new IllegalStateException(String.format(
|
|
"File \"%1$s\" has inconsistent comment on line %2$d",
|
|
aFileName,
|
|
lineNumber));
|
|
}
|
|
}
|
|
else if (NONEMPTY_LINE_REGEX.matcher(line).matches()) {
|
|
throw new IllegalStateException(String.format(
|
|
"File \"%1$s\" has no indentation comment or its format "
|
|
+ "malformed. Error on line: %2$d(%3$s)",
|
|
aFileName,
|
|
lineNumber,
|
|
line));
|
|
}
|
|
lineNumber++;
|
|
}
|
|
}
|
|
return result.toArray(new Integer[result.size()]);
|
|
}
|
|
|
|
private static int getIndentFromComment(String comment)
|
|
{
|
|
final Matcher match = GET_INDENT_FROM_COMMENT_REGEX.matcher(comment);
|
|
match.matches();
|
|
return Integer.parseInt(match.group(1));
|
|
}
|
|
|
|
private static boolean isWarnComment(String comment)
|
|
{
|
|
return comment.endsWith(" warn");
|
|
}
|
|
|
|
private static boolean isCommentConsistent(String comment)
|
|
{
|
|
final int indentInComment = getIndentFromComment(comment);
|
|
final boolean isWarnComment = isWarnComment(comment);
|
|
|
|
Matcher multilevelMatch = MULTILEVEL_COMMENT_REGEX.matcher(comment);
|
|
if (multilevelMatch.matches()) {
|
|
final String[] levels = multilevelMatch.group(1).split(",");
|
|
final String indentInCommentStr = String.valueOf(indentInComment);
|
|
final boolean containsActualLevel =
|
|
Arrays.asList(levels).contains(indentInCommentStr);
|
|
|
|
return containsActualLevel && !isWarnComment
|
|
|| !containsActualLevel && isWarnComment;
|
|
}
|
|
|
|
Matcher singleLevelMatch = SINGLE_LEVEL_COMMENT_REGEX.matcher(comment);
|
|
if (singleLevelMatch.matches()) {
|
|
final int expectedLevel = Integer.parseInt(singleLevelMatch.group(1));
|
|
|
|
return expectedLevel == indentInComment && !isWarnComment
|
|
|| expectedLevel != indentInComment && isWarnComment;
|
|
}
|
|
|
|
Matcher nonStrictLevelMatch = NON_STRICT_LEVEL_COMMENT_REGEX.matcher(comment);
|
|
if (nonStrictLevelMatch.matches()) {
|
|
final int expectedMinimalIndent = Integer.parseInt(nonStrictLevelMatch.group(1));
|
|
|
|
return indentInComment >= expectedMinimalIndent && !isWarnComment
|
|
|| indentInComment < expectedMinimalIndent && isWarnComment;
|
|
}
|
|
|
|
throw new IllegalArgumentException("Cannot determine if commit is consistent");
|
|
}
|
|
|
|
private static int getLineStart(String line, final int tabWidth)
|
|
{
|
|
for (int index = 0; index < line.length(); ++index) {
|
|
if (!Character.isWhitespace(line.charAt(index))) {
|
|
return CommonUtils.lengthExpandedTabs(line, index, tabWidth);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
} |