问题
In our project for chained if/else/if we would like to have following formatting:
if (flag1) {
// Do something 1
} else if (flag2) {
// Do something 2
} else if (flag3) {
// Do something 3
}
And forbid following one:
if (flag1) {
// Do something 1
} else {
if (flag2) {
// Do something 2
} else {
if (flag3) {
// Do something 3
}
}
}
Is there some predefined rule in either of listed above static code analysis tools to force this code style? If no - I know there is an ability to write custom rules in all of those tools, which one would you suggest to implement such a rule (not really familiar with writing custom rules in either of them)?
回答1:
It can be done with CheckStyle, but you'll have to code a custom check.
Using a custom check allows you to completely ignore comments. The line number that a token is on can be determined by calling getLineNo() on the DetailAST. Here's what the AST looks like, with line number information (red circles):
The custom check's code will likely be quite short. You basically register for LITERAL_ELSE
tokens and see if LITERAL_IF
is their only child. Also remember to handle SLIST
s. In those cases, LITERAL_IF
and RCURLY
should be the only children. Both cases are illustrated in the above picture.
Alternative using a RegExp check
For the record, I originally thought one could also configure a regex match using else[ \t{]*[\r\n]+[ \t{]*if\b
for the format
property (based on this post).
Here's the mentioned regex as a railroad diagram:
This turned out not to be feasible, because it produces false negatives when there are comments between between else
and if
. Worse, it also produces false positives when the nested if
is followed by unrelated code (like else { if() {...} <block of code>}
. Thanks @Anatoliy for pointing this out! Since comments and matching braces which are mixed with comments cannot be reliably grasped by regexes, these problems obsolete the RegExp approach.
回答2:
This post says you can't do it in Checkstyle.
In PMD you definitely can. The AST (abstract syntax tree) is different.
For the pattern you don't want
if (true) {
String a;
} else {
if (true) {
String b;
}
}
The tree looks like:
<IfStatement>
<Expression>...</Expression>
<Statement>...</Statement>
<Statement>
<Block>
<BlockStatement>
<IfStatement>...
For the pattern you do want
if (true) {
String a;
} else if (true) {
String b;
}
The tree looks like:
<IfStatement>
<Expression>...</Expression>
<Statement>...</Statement>
<Statement>
<IfStatement>...
In PMD 4 (which I used to make these trees), you write a rule by writing a XPath expression matching the pattern you don't want to occur.
来源:https://stackoverflow.com/questions/20792448/is-there-any-checkstyle-pmd-findbugs-rule-to-force-else-if-to-be-on-the-same-l