View Javadoc

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