Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'addCommentDefaultModifierRule' of https://github.com/Mo…
…nits/pmd into Monits-addCommentDefaultModifierRule
- Loading branch information
Showing
4 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
...in/java/net/sourceforge/pmd/lang/java/rule/comments/CommentDefaultAccessModifierRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/** | ||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html | ||
*/ | ||
package net.sourceforge.pmd.lang.java.rule.comments; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; | ||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; | ||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; | ||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; | ||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator; | ||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; | ||
import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode; | ||
import net.sourceforge.pmd.lang.java.ast.Comment; | ||
import net.sourceforge.pmd.lang.rule.properties.StringProperty; | ||
|
||
/** | ||
* Check for Methods, Fields and Nested Classes that have a default access modifier | ||
* | ||
* @author Damián Techeira | ||
*/ | ||
public class CommentDefaultAccessModifierRule extends AbstractCommentRule { | ||
|
||
private static final StringProperty REGEX_DESCRIPTOR = new StringProperty("regex", "Regular expression", "", 1.0f); | ||
private static final String MESSAGE = "To avoid mistakes add a comment " + | ||
"at the beginning of the %s %s if you want a default access modifier"; | ||
private final Set<Integer> interestingLineNumberComments = new HashSet<Integer>(); | ||
|
||
public CommentDefaultAccessModifierRule() { | ||
definePropertyDescriptor(REGEX_DESCRIPTOR); | ||
} | ||
|
||
public CommentDefaultAccessModifierRule(final String regex) { | ||
this(); | ||
setRegex(regex); | ||
} | ||
|
||
public void setRegex(final String regex) { | ||
setProperty(CommentDefaultAccessModifierRule.REGEX_DESCRIPTOR, regex); | ||
} | ||
|
||
@Override | ||
public Object visit(final ASTCompilationUnit node, final Object data) { | ||
interestingLineNumberComments.clear(); | ||
final List<Comment> comments = node.getComments(); | ||
for (final Comment comment : comments) { | ||
if (comment.getImage().matches(getProperty(REGEX_DESCRIPTOR).trim())) { | ||
interestingLineNumberComments.add(comment.getBeginLine()); | ||
} | ||
} | ||
return super.visit(node, data); | ||
} | ||
|
||
@Override | ||
public Object visit(final ASTMethodDeclaration decl, final Object data) { | ||
if (shouldReport(decl)) { | ||
addViolationWithMessage(data, decl, String.format(MESSAGE, | ||
decl.getFirstChildOfType(ASTMethodDeclarator.class).getImage(), "method")); | ||
} | ||
return super.visit(decl, data); | ||
} | ||
|
||
@Override | ||
public Object visit(final ASTFieldDeclaration decl, final Object data) { | ||
if (shouldReport(decl)) { | ||
addViolationWithMessage(data, decl, String.format(MESSAGE, | ||
decl.getFirstDescendantOfType(ASTVariableDeclaratorId.class).getImage(), "field")); | ||
} | ||
return super.visit(decl, data); | ||
} | ||
|
||
@Override | ||
public Object visit(final ASTClassOrInterfaceDeclaration decl, final Object data) { | ||
// check for nested classes | ||
if (decl.isNested() && shouldReport(decl)) { | ||
addViolationWithMessage(data, decl, String.format(MESSAGE, decl.getImage(), "nested class")); | ||
} | ||
return super.visit(decl, data); | ||
} | ||
|
||
private boolean shouldReport(final AbstractJavaAccessNode decl) { | ||
// ignore if is a Interface | ||
return !decl.getParentsOfType(ASTClassOrInterfaceDeclaration.class).get(0).isInterface() | ||
// check if the field/method/nested class has a default access modifier | ||
&& decl.isPackagePrivate() | ||
// if is a default access modifier check if there is a comment in this line | ||
&& !interestingLineNumberComments.contains(decl.getBeginLine()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
...esources/net/sourceforge/pmd/lang/java/rule/comments/xml/CommentDefaultAccessModifier.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<test-data> | ||
<code-fragment id="some-methods-fields-with-default-access-modifier"><![CDATA[ | ||
public class Foo { | ||
public final String stringValue = "stringValue"; // should not be reported | ||
final String otherStringValue = "otherStringValue"; // should be reported | ||
/* default */ final String otherValue = "otherValue"; // should not be reported | ||
/* default */ final String anotherValue = "anotherValue"; // should not be reported | ||
public void test() { // should not be reported | ||
} | ||
void test2() { // should be reported | ||
} | ||
/* default */ void test3() { // should not be reported | ||
} | ||
/* default */ void test4() { // should not be reported | ||
} | ||
} | ||
]]> | ||
</code-fragment> | ||
<test-code> | ||
<description>Some methods and Fields with default access modifier in a class</description> | ||
<expected-problems>2</expected-problems> | ||
<code-ref id="some-methods-fields-with-default-access-modifier"/> | ||
</test-code> | ||
|
||
<code-fragment id="all-methods-fields-with-default-access-modifier"><![CDATA[ | ||
public class Foo { | ||
final String stringValue = "stringValue"; | ||
final String otherStringValue = "otherStringValue"; | ||
final String otherValue = "otherValue"; | ||
void test() { | ||
} | ||
void test2() { | ||
} | ||
void test3() { | ||
} | ||
} | ||
]]> | ||
</code-fragment> | ||
<test-code> | ||
<description>All methods and Field with default access modifier in a class</description> | ||
<expected-problems>6</expected-problems> | ||
<code-ref id="all-methods-fields-with-default-access-modifier"/> | ||
</test-code> | ||
|
||
<code-fragment id="all-methods-fields-without-default-access-modifier"><![CDATA[ | ||
public class Foo { | ||
private final String stringValue = "stringValue"; | ||
private final String otherStringValue = "otherStringValue"; | ||
private final String otherValue = "otherValue"; | ||
public void test() { | ||
} | ||
public void test2() { | ||
} | ||
public void test3() { | ||
} | ||
} | ||
]]> | ||
</code-fragment> | ||
<test-code> | ||
<description>All methods and Field without default access modifier in a class</description> | ||
<expected-problems>0</expected-problems> | ||
<code-ref id="all-methods-fields-without-default-access-modifier"/> | ||
</test-code> | ||
|
||
<code-fragment id="interface-with-methods-with-default-access-modifier"><![CDATA[ | ||
public interface Foo { | ||
void test(); | ||
public void test2(); | ||
void test3(); | ||
} | ||
]]></code-fragment> | ||
<test-code> | ||
<description>Methods with default access modifier in an Interface</description> | ||
<expected-problems>0</expected-problems> | ||
<code-ref id="interface-with-methods-with-default-access-modifier"/> | ||
</test-code> | ||
|
||
<code-fragment id="nested-class-with-default-access-modifier"><![CDATA[ | ||
public class Foo { | ||
private final String stringValue = "stringValue"; | ||
public void test() { | ||
} | ||
class NestedClass { | ||
} | ||
static class OtherNestedClass { | ||
} | ||
public class AnotherNestedClass { | ||
} | ||
} | ||
]]></code-fragment> | ||
<test-code> | ||
<description>Nested classes with default access modifier</description> | ||
<expected-problems>2</expected-problems> | ||
<code-ref id="nested-class-with-default-access-modifier"/> | ||
</test-code> | ||
|
||
<code-fragment id="own-regex-to-default-access-modifier-rule"><![CDATA[ | ||
public class Foo { | ||
/* default */ final String stringValue = "stringValue"; | ||
void test() { | ||
} | ||
/* package-private */ class NestedClass { | ||
} | ||
/* package-private */ class OtherNestedClass { | ||
} | ||
static class AnotherNestedClass { | ||
} | ||
} | ||
]]></code-fragment> | ||
<test-code> | ||
<description>Test own regex to default access modifier rule</description> | ||
<rule-property name="regex">\/\*\s+package-private\s+\*\/</rule-property> | ||
<expected-problems>3</expected-problems> | ||
<code-ref id="own-regex-to-default-access-modifier-rule"/> | ||
</test-code> | ||
</test-data> |