com.xenoamess.p3c.pmd.lang.java.rule.comment.RemoveCommentedCodeRule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of p3c-pmd Show documentation
Show all versions of p3c-pmd Show documentation
Alibaba Java Coding Guidelines PMD implementations(XenoAmess
TPM)
/*
* Copyright 1999-2017 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.xenoamess.p3c.pmd.lang.java.rule.comment;
import com.xenoamess.p3c.pmd.lang.java.rule.util.NodeSortUtils;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.Comment;
import net.sourceforge.pmd.lang.java.ast.JavaNode;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Pattern;
/**
* [Recommended] Codes or configuration that is noticed to be obsoleted should be resolutely removed from projects.
*
* @author keriezhang
* @date 2017/04/14
*/
public class RemoveCommentedCodeRule extends AbstractAliCommentRule {
private static final Pattern SUPPRESS_PATTERN = Pattern.compile("\\s*///.*", Pattern.DOTALL);
private static final Pattern PRE_TAG_PATTERN = Pattern.compile(".*.*", Pattern.DOTALL);
private static final Pattern IMPORT_PATTERN = Pattern.compile(".*import\\s(static\\s)?(\\w*\\.)*\\w*;.*",
Pattern.DOTALL);
private static final Pattern FIELD_PATTERN = Pattern.compile(".*private\\s+(\\w*)\\s+(\\w*);.*", Pattern.DOTALL);
private static final Pattern METHOD_PATTERN = Pattern.compile(
".*(public|protected|private)\\s+\\w+\\s+\\w+\\(.*\\)\\s+\\{.*", Pattern.DOTALL);
/**
* If string matches format ".xxx(.*);\n", then mark it as code.
*/
private static final Pattern STATEMENT_PATTERN = Pattern.compile(".*\\.\\w+\\(.*\\);\n.*", Pattern.DOTALL);
@Override
public Object visit(ASTCompilationUnit cUnit, Object data) {
checkCommentsBetweenDeclarations(cUnit, data);
return super.visit(cUnit, data);
}
protected void checkCommentsBetweenDeclarations(ASTCompilationUnit cUnit, Object data) {
SortedMap itemsByLineNumber = orderedCommentsAndDeclarations(cUnit);
Comment lastComment = null;
boolean suppressWarning = false;
CommentPatternEnum commentPattern = CommentPatternEnum.NONE;
for (Entry entry : itemsByLineNumber.entrySet()) {
Node value = entry.getValue();
if (value instanceof JavaNode) {
JavaNode node = (JavaNode) value;
// add violation on the node after comment.
if (lastComment != null && isCommentBefore(lastComment, node)) {
// find code comment, but need filter some case.
if (!CommentPatternEnum.NONE.equals(commentPattern)) {
// check statement pattern only in method
boolean statementOutsideMethod = CommentPatternEnum.STATEMENT.equals(commentPattern)
&& !(node instanceof ASTBlockStatement);
if (!statementOutsideMethod) {
addViolationWithMessage(data, node, getMessage(),
lastComment.getBeginLine(),
lastComment.getEndLine());
}
}
lastComment = null;
}
// reset data after each node.
suppressWarning = false;
commentPattern = CommentPatternEnum.NONE;
} else if (value instanceof Comment) {
lastComment = (Comment) value;
String content = lastComment.getImage();
if (!suppressWarning) {
suppressWarning = SUPPRESS_PATTERN.matcher(content).matches();
}
if (!suppressWarning && CommentPatternEnum.NONE.equals(commentPattern)) {
commentPattern = this.scanCommentedCode(content);
}
}
}
}
/**
* Common Situations, check in following order:
* 1. commented import
* 2. commented field
* 3. commented method
* 4. commented statement
*
* @param content comment content
* @return check result
*/
protected CommentPatternEnum scanCommentedCode(String content) {
CommentPatternEnum pattern = CommentPatternEnum.NONE;
// Skip comment which contains pre tag.
if (PRE_TAG_PATTERN.matcher(content).matches()) {
return pattern;
}
if (IMPORT_PATTERN.matcher(content).matches()) {
pattern = CommentPatternEnum.IMPORT;
} else if (FIELD_PATTERN.matcher(content).matches()) {
pattern = CommentPatternEnum.FIELD;
} else if (METHOD_PATTERN.matcher(content).matches()) {
pattern = CommentPatternEnum.METHOD;
} else if (STATEMENT_PATTERN.matcher(content).matches()) {
pattern = CommentPatternEnum.STATEMENT;
}
return pattern;
}
@Override
protected SortedMap orderedCommentsAndDeclarations(ASTCompilationUnit cUnit) {
SortedMap itemsByLineNumber = new TreeMap<>();
List importDecl = cUnit
.findDescendantsOfType(ASTImportDeclaration.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, importDecl);
List classDecl = cUnit
.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, classDecl);
List fields = cUnit.findDescendantsOfType(ASTFieldDeclaration.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, fields);
List methods = cUnit.findDescendantsOfType(ASTMethodDeclaration.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, methods);
List constructors = cUnit.findDescendantsOfType(ASTConstructorDeclaration.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, constructors);
List blockStatements = cUnit.findDescendantsOfType(ASTBlockStatement.class);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, blockStatements);
NodeSortUtils.addNodesToSortedMap(itemsByLineNumber, cUnit.getComments());
return itemsByLineNumber;
}
private boolean isCommentBefore(Comment n1, Node n2) {
return n1.getEndLine() < n2.getBeginLine() || n1.getEndLine() == n2.getBeginLine()
&& n1.getEndColumn() < n2.getBeginColumn();
}
enum CommentPatternEnum {
/**
* comment has code pattern
*/
IMPORT,
FIELD,
METHOD,
STATEMENT,
NONE
}
}