提交 d9792ef4 编写于 作者: S SeanCai 提交者: GitHub

Merge pull request #138 from kerie/master

1.author标签不区分大小写,2.在有注解的情况下正确关联注释与节点
......@@ -21,7 +21,7 @@ import java.util.SortedMap;
import java.util.TreeMap;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.util.CommentUtils;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeSortUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
......@@ -75,19 +75,19 @@ public class AvoidCommentBehindStatementRule extends AbstractAliCommentRule {
// expression nodes
List<ASTExpression> expressionNodes = cUnit.findDescendantsOfType(ASTExpression.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, expressionNodes);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, expressionNodes);
// filed declaration nodes
List<ASTFieldDeclaration> fieldNodes =
cUnit.findDescendantsOfType(ASTFieldDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, fieldNodes);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, fieldNodes);
// enum constant nodes
List<ASTEnumConstant> enumConstantNodes =
cUnit.findDescendantsOfType(ASTEnumConstant.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, enumConstantNodes);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, enumConstantNodes);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
return itemsByLineNumber;
}
......
......@@ -34,7 +34,8 @@ import net.sourceforge.pmd.lang.java.ast.Comment;
*/
public class ClassMustHaveAuthorRule extends AbstractAliCommentRule {
private static final Pattern AUTHOR_PATTERN = Pattern.compile(".*@author.*", Pattern.DOTALL);
private static final Pattern AUTHOR_PATTERN = Pattern.compile(".*@author.*",
Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
private static final String MESSAGE_KEY_PREFIX = "java.comment.ClassMustHaveAuthorRule.violation.msg";
......
......@@ -16,15 +16,17 @@
package com.alibaba.p3c.pmd.lang.java.rule.comment;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.util.CommentUtils;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeSortUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
......@@ -43,7 +45,7 @@ import org.apache.commons.lang3.StringUtils;
/**
* [Mandatory] Javadoc should be used for classes, class variables and methods.
* The format should be '\/** comment **\/', rather than '// xxx'.
* The format should be '\/** comment *\/', rather than '// xxx'.
*
* @author keriezhang
* @date 2016/12/14
......@@ -155,8 +157,13 @@ public class CommentsMustBeJavadocFormatRule extends AbstractAliCommentRule {
if (value instanceof AbstractJavaNode) {
AbstractJavaNode node = (AbstractJavaNode)value;
// skip annotation node, we will deal with it later.
if (node instanceof ASTAnnotation) {
continue;
}
// Check if comment is one line above class, field, method.
if (lastComment != null && isCommentOneLineBefore(lastComment, lastNode, node)) {
if (lastComment != null && isCommentOneLineBefore(itemsByLineNumber, lastComment, lastNode, node)) {
node.comment(lastComment);
lastComment = null;
}
......@@ -172,28 +179,31 @@ public class CommentsMustBeJavadocFormatRule extends AbstractAliCommentRule {
SortedMap<Integer, Node> itemsByLineNumber = new TreeMap<>();
CommentUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
List<ASTAnnotation> annotations = cUnit.findDescendantsOfType(ASTAnnotation.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, annotations);
List<ASTClassOrInterfaceDeclaration> classDecl =
cUnit.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, classDecl);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, classDecl);
List<ASTFieldDeclaration> fields = cUnit.findDescendantsOfType(ASTFieldDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, fields);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, fields);
List<ASTMethodDeclaration> methods = cUnit.findDescendantsOfType(ASTMethodDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, methods);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, methods);
List<ASTConstructorDeclaration> constructors = cUnit.findDescendantsOfType(ASTConstructorDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, constructors);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, constructors);
List<ASTEnumDeclaration> enumDecl = cUnit.findDescendantsOfType(ASTEnumDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, enumDecl);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, enumDecl);
return itemsByLineNumber;
}
private boolean isCommentOneLineBefore(Comment lastComment, Node lastNode, Node node) {
private boolean isCommentOneLineBefore(SortedMap<Integer, Node> items, Comment lastComment, Node lastNode, Node node) {
ASTClassOrInterfaceBodyDeclaration parentClass =
node.getFirstParentOfType(ASTClassOrInterfaceBodyDeclaration.class);
......@@ -207,7 +217,31 @@ public class CommentsMustBeJavadocFormatRule extends AbstractAliCommentRule {
return false;
}
return lastComment.getEndLine() + 1 == node.getBeginLine();
// check if there is nothing in the middle except annotations.
SortedMap<Integer, Node> subMap = items.subMap(NodeSortUtils.generateIndex(lastComment),
NodeSortUtils.generateIndex(node));
Iterator<Entry<Integer, Node>> iter = subMap.entrySet().iterator();
// skip the first comment node.
iter.next();
int lastEndLine = lastComment.getEndLine();
while (iter.hasNext()) {
Entry<Integer, Node> entry = iter.next();
Node value = entry.getValue();
// only annotation node is allowed between comment and node.
if (!(value instanceof ASTAnnotation)) {
return false;
}
// allow annotation node after comment.
if (lastEndLine + 1 == value.getBeginLine()) {
lastEndLine = value.getEndLine();
}
}
return lastEndLine + 1 == node.getBeginLine();
}
/**
......
......@@ -21,7 +21,7 @@ import java.util.SortedMap;
import java.util.TreeMap;
import com.alibaba.p3c.pmd.I18nResources;
import com.alibaba.p3c.pmd.lang.java.rule.util.CommentUtils;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeSortUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
......@@ -65,12 +65,12 @@ public class EnumConstantsMustHaveCommentRule extends AbstractAliCommentRule {
SortedMap<Integer, Node> itemsByLineNumber = new TreeMap<>();
List<ASTEnumDeclaration> enumDecl = cUnit.findDescendantsOfType(ASTEnumDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, enumDecl);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, enumDecl);
List<ASTEnumConstant> contantDecl = cUnit.findDescendantsOfType(ASTEnumConstant.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, contantDecl);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, contantDecl);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
return itemsByLineNumber;
}
......
......@@ -21,7 +21,7 @@ import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Pattern;
import com.alibaba.p3c.pmd.lang.java.rule.util.CommentUtils;
import com.alibaba.p3c.pmd.lang.java.rule.util.NodeSortUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
......@@ -144,25 +144,25 @@ public class RemoveCommentedCodeRule extends AbstractAliCommentRule {
List<ASTImportDeclaration> importDecl = cUnit
.findDescendantsOfType(ASTImportDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, importDecl);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, importDecl);
List<ASTClassOrInterfaceDeclaration> classDecl = cUnit
.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, classDecl);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, classDecl);
List<ASTFieldDeclaration> fields = cUnit.findDescendantsOfType(ASTFieldDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, fields);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, fields);
List<ASTMethodDeclaration> methods = cUnit.findDescendantsOfType(ASTMethodDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, methods);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, methods);
List<ASTConstructorDeclaration> constructors = cUnit.findDescendantsOfType(ASTConstructorDeclaration.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, constructors);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, constructors);
List<ASTBlockStatement> blockStatements = cUnit.findDescendantsOfType(ASTBlockStatement.class);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, blockStatements);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, blockStatements);
CommentUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
return itemsByLineNumber;
}
......
......@@ -26,7 +26,7 @@ import net.sourceforge.pmd.lang.ast.Node;
* @date 2016/11/21
*
*/
public class CommentUtils {
public class NodeSortUtils {
/**
* add node to SortedMap with sequence to determine comment location
......@@ -36,8 +36,16 @@ public class CommentUtils {
*/
public static void addNodesToSortedMap(SortedMap<Integer, Node> map, List<? extends Node> nodes) {
for (Node node : nodes) {
// sorted by line and column
map.put((node.getBeginLine() << 16) + node.getBeginColumn(), node);
map.put(generateIndex(node), node);
}
}
/**
* set order according to node begin line and begin column
* @param node node to sort
* @return generated index
*/
public static int generateIndex(Node node) {
return (node.getBeginLine() << 16) + node.getBeginColumn();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<code-fragment id="class-without-author"><![CDATA[
<code-fragment id="class-without-author"><![CDATA[
public class ClassMustHaveAuthorRule {}
]]>
</code-fragment>
</code-fragment>
<test-code>
<description>Class without author.</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="class-without-author" />
</test-code>
<test-code>
<description>Class without author.</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="class-without-author" />
</test-code>
<code-fragment id="class-with-author"><![CDATA[
<code-fragment id="class-with-author"><![CDATA[
/**
* @author keriezhang
* @date 2017/07/18
*/
public class ClassMustHaveAuthorRule {}
]]>
</code-fragment>
<test-code>
<description>Class with author.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-author" />
</test-code>
<code-fragment id="class-with-date"><![CDATA[
</code-fragment>
<test-code>
<description>Class with author.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-author" />
</test-code>
<code-fragment id="class-with-date"><![CDATA[
/**
* @date 2016/12/14
*/
public class ClassMustHaveAuthorRule {}
]]>
</code-fragment>
<test-code>
<description>Class with date.</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code-ref id="class-with-date" />
</test-code>
<code-fragment id="class-with-author-and-date"><![CDATA[
</code-fragment>
<test-code>
<description>Class with date.</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code-ref id="class-with-date" />
</test-code>
<code-fragment id="class-with-author-and-date"><![CDATA[
/**
* @author keriezhang
* @date 2016/12/14
*/
public class ClassMustHaveAuthorRule {}
]]>
</code-fragment>
<test-code>
<description>Class with author and date.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-author-and-date" />
</test-code>
</code-fragment>
<test-code>
<description>Class with author and date.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-author-and-date" />
</test-code>
<code-fragment id="class-with-inner-class"><![CDATA[
<code-fragment id="class-with-inner-class"><![CDATA[
/**
* @author keriezhang
* @date 2016/12/14
......@@ -66,28 +66,28 @@ public class Outer_Demo {
}
}
]]>
</code-fragment>
<test-code>
<description>Class with inner class.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-inner-class" />
</test-code>
</code-fragment>
<test-code>
<description>Class with inner class.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-inner-class" />
</test-code>
<code-fragment id="enum-without-author"><![CDATA[
<code-fragment id="enum-without-author"><![CDATA[
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
]]>
</code-fragment>
<test-code>
<description>Enum without author</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="enum-without-author" />
</test-code>
</code-fragment>
<test-code>
<description>Enum without author</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>1</expected-linenumbers>
<code-ref id="enum-without-author" />
</test-code>
<code-fragment id="enum-with-author"><![CDATA[
<code-fragment id="enum-with-author"><![CDATA[
/**
* @author keriezhang
* @date 2016/12/14
......@@ -97,14 +97,14 @@ public enum Day {
THURSDAY, FRIDAY, SATURDAY
}
]]>
</code-fragment>
<test-code>
<description>Enum with author</description>
<expected-problems>0</expected-problems>
<code-ref id="enum-with-author" />
</test-code>
</code-fragment>
<test-code>
<description>Enum with author</description>
<expected-problems>0</expected-problems>
<code-ref id="enum-with-author" />
</test-code>
<code-fragment id="enum-in-class"><![CDATA[
<code-fragment id="enum-in-class"><![CDATA[
/**
* @author keriezhang
* @date 2016/12/14
......@@ -117,14 +117,14 @@ public class Vehicle {
}
}
]]>
</code-fragment>
<test-code>
<description>Enum in class</description>
<expected-problems>0</expected-problems>
<code-ref id="enum-in-class" />
</test-code>
</code-fragment>
<test-code>
<description>Enum in class</description>
<expected-problems>0</expected-problems>
<code-ref id="enum-in-class" />
</test-code>
<code-fragment id="enum-in-interface"><![CDATA[
<code-fragment id="enum-in-interface"><![CDATA[
/**
* @author keriezhang
* @date 2016/12/14
......@@ -137,11 +137,31 @@ public interface Vehicle {
}
}
]]>
</code-fragment>
<test-code>
<description>Enum in interface</description>
<expected-problems>0</expected-problems>
<code-ref id="enum-in-interface" />
</test-code>
</code-fragment>
<test-code>
<description>Enum in interface</description>
<expected-problems>0</expected-problems>
<code-ref id="enum-in-interface" />
</test-code>
<code-fragment id="upper-case-author-annotation"><![CDATA[
/**
* @Author keriezhang
* @date 2016/12/14
*/
public interface Vehicle {
public Number getNumber();
public void method2();
public enum color {
RED, GREEN, ANY;
}
}
]]>
</code-fragment>
<test-code>
<description>Uppercase author annotation</description>
<expected-problems>0</expected-problems>
<code-ref id="upper-case-author-annotation" />
</test-code>
</test-data>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<code-fragment id="class-without-comments"><![CDATA[
<code-fragment id="class-without-comments"><![CDATA[
public class CommentsMustBeJavadocFormat {
private String name;
public void getName() {}
}
]]>
</code-fragment>
</code-fragment>
<test-code>
<description>Class have no comment.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-without-comments" />
</test-code>
<test-code>
<description>Class have no comment.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-without-comments" />
</test-code>
<code-fragment id="class-with-non-javadoc-comments"><![CDATA[
<code-fragment id="class-with-non-javadoc-comments"><![CDATA[
// a comment
// a comment
public class CommentsMustBeJavadocFormat {
......@@ -26,17 +26,17 @@ public class CommentsMustBeJavadocFormat {
public void getName() {}
}
]]>
</code-fragment>
</code-fragment>
<test-code>
<description>Class have non-javadoc comments.</description>
<expected-problems>3</expected-problems>
<expected-linenumbers>2,4,6</expected-linenumbers>
<code-ref id="class-with-non-javadoc-comments" />
</test-code>
<test-code>
<description>Class have non-javadoc comments.</description>
<expected-problems>3</expected-problems>
<expected-linenumbers>2,4,6</expected-linenumbers>
<code-ref id="class-with-non-javadoc-comments" />
</test-code>
<code-fragment id="class-with-javadoc-comments"><![CDATA[
<code-fragment id="class-with-javadoc-comments"><![CDATA[
/**
* test
*/
......@@ -52,15 +52,15 @@ public class CommentsMustBeJavadocFormat {
public void getName() {}
}
]]>
</code-fragment>
<test-code>
<description>Class have javadoc comments.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-javadoc-comments" />
</test-code>
</code-fragment>
<test-code>
<description>Class have javadoc comments.</description>
<expected-problems>0</expected-problems>
<code-ref id="class-with-javadoc-comments" />
</test-code>
<code-fragment id="anonymous-class-with-non-javadoc-comments"><![CDATA[
<code-fragment id="anonymous-class-with-non-javadoc-comments"><![CDATA[
// comment of outer class
public class Outer_class {
// comment of method of outer class
......@@ -76,17 +76,17 @@ public class Outer_class {
}
}
]]>
</code-fragment>
<test-code>
<description>Anonymous Inner Class have non javadoc comments.
</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>1,3</expected-linenumbers>
<code-ref id="anonymous-class-with-non-javadoc-comments" />
</test-code>
</code-fragment>
<test-code>
<description>Anonymous Inner Class have non javadoc comments.
</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>1,3</expected-linenumbers>
<code-ref id="anonymous-class-with-non-javadoc-comments" />
</test-code>
<code-fragment id="non-javadoc-comments-before-package-and-import"><![CDATA[
<code-fragment id="non-javadoc-comments-before-package-and-import"><![CDATA[
/*
* Created on 18 nov. 2004
*/
......@@ -104,15 +104,15 @@ public class PMDProjectPropertyPage extends PropertyPage {
}
]]>
</code-fragment>
<test-code>
<description>Non-javadoc comments before package and import
</description>
<expected-problems>0</expected-problems>
<code-ref id="non-javadoc-comments-before-package-and-import" />
</test-code>
<code-fragment id="ignore-comments-behind-statements"><![CDATA[
</code-fragment>
<test-code>
<description>Non-javadoc comments before package and import
</description>
<expected-problems>0</expected-problems>
<code-ref id="non-javadoc-comments-before-package-and-import" />
</test-code>
<code-fragment id="ignore-comments-behind-statements"><![CDATA[
public class CommentsMustBeJavadocFormat {
private String name; //avoid two two violations in one line.
private Integer age;
......@@ -120,12 +120,71 @@ public class CommentsMustBeJavadocFormat {
}
}
]]>
</code-fragment>
<test-code>
<description>Ignore comments behind statements.
</description>
<expected-problems>0</expected-problems>
<code-ref id="ignore-comments-behind-statements" />
</test-code>
</code-fragment>
<test-code>
<description>Ignore comments behind statements.
</description>
<expected-problems>0</expected-problems>
<code-ref id="ignore-comments-behind-statements" />
</test-code>
<code-fragment id="when-node-has-annotation-wrong-format"><![CDATA[
// test when class has annotation
@Controller
@Rest
public class CommentsMustBeJavadocFormat {
// test when node has annotation
@Test
private String name;
// test when node has annotation2
@Hello(asdf="asdf")
@world
private Integer age;
// test when method has annotation
@Test
@Autowired
public void getName() {
}
}
]]>
</code-fragment>
<test-code>
<description>When node has annotation and wrong comment format
</description>
<expected-problems>4</expected-problems>
<expected-linenumbers>1,5,9,14</expected-linenumbers>
<code-ref id="when-node-has-annotation-wrong-format" />
</test-code>
<code-fragment id="when-node-has-annotation-right-format"><![CDATA[
/** test when class has annotation */
@Controller
@Rest
public class CommentsMustBeJavadocFormat {
/** test when node has annotation */
@Test
private String name;
/** test when node has annotation2 */
@Hello(asdf="asdf")
@world
private Integer age;
/** test when method has annotation */
@Test
@Autowired
public void getName() {
}
}
]]>
</code-fragment>
<test-code>
<description>When node has annotation and right comment format
</description>
<expected-problems>0</expected-problems>
<code-ref id="when-node-has-annotation-right-format" />
</test-code>
</test-data>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册