最後,我確實實現了checkstyle的自定義檢查。這裏是源代碼,如果別人有興趣的話:
import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
public class IfBracesCheck extends Check {
@Override
public int[] getDefaultTokens() {
return new int[] {
TokenTypes.LITERAL_ELSE,
TokenTypes.LITERAL_IF,
};
}
@Override
public void visitToken(DetailAST aAST) {
final DetailAST slistAST = aAST.findFirstToken(TokenTypes.SLIST);
if(aAST.getType() == TokenTypes.LITERAL_ELSE) {
// If we have an else, it must have braces, except it is an "else if" (then the if must have braces).
DetailAST ifToken = aAST.findFirstToken(TokenTypes.LITERAL_IF);
if(ifToken == null) {
// This is an simple else, it must have brace.
if(slistAST == null) {
log(aAST.getLineNo(), "ifBracesElse", aAST.getText());
}
} else {
// This is an "else if", the if must have braces.
if(ifToken.findFirstToken(TokenTypes.SLIST) == null) {
log(aAST.getLineNo(), "ifBracesConditional", ifToken.getText(), aAST.getText() + " " + ifToken.getText());
}
}
} else if(aAST.getType() == TokenTypes.LITERAL_IF) {
// If the if uses braces, nothing as to be checked.
if (slistAST != null) {
return;
}
// We have an if, we need to check if it has no conditionnal structure as direct child.
final int[] conditionals = {
TokenTypes.LITERAL_DO,
TokenTypes.LITERAL_ELSE,
TokenTypes.LITERAL_FOR,
TokenTypes.LITERAL_IF,
TokenTypes.LITERAL_WHILE,
TokenTypes.LITERAL_SWITCH,
};
for(int conditional : conditionals) {
DetailAST conditionalAST = aAST.findFirstToken(conditional);
if (conditionalAST != null) {
log(aAST.getLineNo(), "ifBracesConditional", aAST.getText(), conditionalAST.getText());
// Let's trigger this only once.
return;
}
}
}
}
}
我嚴肅的建議是改變你的指導方針。你花時間尋找一個解決方案,使你的風格指南*劣勢*。內聯if語句(不使用塊)會導致錯誤。真的,真的很討厭的錯誤。 – 2011-05-26 17:06:38
@Mark我不知道如何使用內聯ifs來進行簡單的函數調用,但我認爲使用它們來檢查一些條件並在條件不滿足時拋出異常是合理的。 – 2011-05-26 17:15:28
這個問題不是關於指導是否合理。這個問題是關於如何修改checkstyle以支持這些準則。我認爲我們應該避免在這個問題上自己討論準則。 – 2011-05-26 17:25:59