View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.rule.comments;
5   
6   import java.util.ArrayList;
7   import java.util.List;
8   
9   import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
10  import net.sourceforge.pmd.lang.java.ast.Comment;
11  import net.sourceforge.pmd.lang.rule.properties.IntegerProperty;
12  import net.sourceforge.pmd.util.StringUtil;
13  
14  /**
15   * A rule to manage those who just can't shut up...
16   * 
17   * @author Brian Remedios
18   */
19  public class CommentSizeRule extends AbstractCommentRule {
20  
21  	 public static final IntegerProperty MAX_LINES = new IntegerProperty("maxLines", "Maximum lines", 2, 200, 6, 2.0f);
22  	 public static final IntegerProperty MAX_LINE_LENGTH = new IntegerProperty("maxLineLength", "Maximum line length", 1, 200, 80, 2.0f);
23  	  
24  	 private static final String CR = "\n";
25  	 
26  	public CommentSizeRule() {
27  		definePropertyDescriptor(MAX_LINES);
28  		definePropertyDescriptor(MAX_LINE_LENGTH);
29  	}	
30  	
31  	private static boolean hasRealText(String line) {
32  		
33  		if (StringUtil.isEmpty(line)) return false;
34  		
35  		return ! StringUtil.isAnyOf(line.trim(), "//", "/*", "/**", "*", "*/");
36  	}
37  	 
38  	private boolean hasTooManyLines(Comment comment) {
39  
40  		 String[] lines = comment.getImage().split(CR);
41  		 
42  		 int start = 0;	// start from top
43  		 for (; start<lines.length; start++ ) {
44  			 if (hasRealText(lines[start])) break;
45  		 }
46  		 
47  		  int end = lines.length - 1;	// go up from bottom
48  		 for (; end>0; end-- ) {
49  			 if (hasRealText(lines[end])) break;
50  		 }
51  		 
52  		 int lineCount = end - start + 1;
53  		 
54  		 return lineCount > getProperty(MAX_LINES);
55  	 }
56  	 
57  	private String withoutCommentMarkup(String text) {
58  				
59  		return StringUtil.withoutPrefixes(text.trim(), "//", "*", "/**");
60  	}
61  	
62  	private List<Integer> overLengthLineIndicesIn(Comment comment) {
63  
64  		int maxLength = getProperty(MAX_LINE_LENGTH);
65  				
66  		List<Integer> indicies = new ArrayList<Integer>();
67  		String[] lines = comment.getImage().split(CR);
68  		
69  		int offset = comment.getBeginLine();
70  		
71  		for (int i=0; i<lines.length; i++) {
72  			String cleaned = withoutCommentMarkup(lines[i]);
73  			if (cleaned.length() > maxLength) indicies.add(i+offset);
74  		}
75  		
76  		return indicies;
77  	}
78  	
79  	@Override
80      public Object visit(ASTCompilationUnit cUnit, Object data) {
81    
82  		for (Comment comment : cUnit.getComments()) {
83  			if (hasTooManyLines(comment)) {
84  				addViolationWithMessage(data, cUnit,
85  					this.getMessage() + ": Too many lines",
86  					comment.getBeginLine(), comment.getEndLine());
87  			}
88  			
89  			List<Integer> lineNumbers = overLengthLineIndicesIn(comment);
90  			if (lineNumbers.isEmpty()) continue;
91  				
92  			for (Integer lineNum : lineNumbers) {
93  				addViolationWithMessage(data, cUnit,
94  					this.getMessage() + ": Line too long",
95  					lineNum, lineNum);
96  			}
97  		}
98  
99          return super.visit(cUnit, data);
100     }
101 }