1 package org.incava.doctorj; 2 3 import java.util.*; 4 import net.sourceforge.pmd.ast.JavaParserConstants; 5 import net.sourceforge.pmd.ast.SimpleNode; 6 import net.sourceforge.pmd.ast.Token; 7 import org.incava.analysis.Report; 8 import org.incava.java.SimpleNodeUtil; 9 import org.incava.javadoc.*; 10 import org.incava.text.LineMapping; 11 import org.incava.text.Location; 12 13 14 17 public abstract class ItemDocAnalyzer extends DocAnalyzer 18 { 19 public final static String MSG_NO_SUMMARY_SENTENCE = "No summary sentence"; 20 21 public final static String MSG_SUMMARY_SENTENCE_DOES_NOT_END_WITH_PERIOD = "Summary sentence does not end with period"; 22 23 public final static String MSG_SUMMARY_SENTENCE_TOO_SHORT = "Summary sentence too short"; 24 25 public final static String MSG_SEE_WITHOUT_REFERENCE = "@see without reference"; 26 27 public final static String MSG_SINCE_WITHOUT_TEXT = "@since without text"; 28 29 public final static String MSG_DEPRECATED_WITHOUT_TEXT = "@deprecated without text"; 30 31 public final static String MSG_TAG_IMPROPER_ORDER = "Tag in improper order"; 32 33 protected final static int CHKLVL_SUMMARY_SENTENCE = 1; 34 35 protected final static int CHKLVL_MISORDERED_TAGS = 0; 36 37 protected final static int CHKLVL_VALID_TAGS = 0; 38 39 public static ItemCommentSpellCheck spellChecker = new ItemCommentSpellCheck(); 40 41 private SimpleNode _node; 42 43 public ItemDocAnalyzer(Report r, SimpleNode node) 44 { 45 super(r); 46 47 _node = node; 48 } 49 50 public static void addDictionary(String dictName) 51 { 52 spellChecker.addDictionary(dictName); 53 } 54 55 60 protected JavadocNode getJavadoc() 61 { 62 SimpleNode sn = getEnclosingNode(); 63 JavadocNode javadoc = null; 64 Token first = sn.getFirstToken(); 65 Token st = first.specialToken; 66 67 while (javadoc == null && st != null) { 68 javadoc = JavadocNode.parse(st.image, st.beginLine, st.beginColumn); 69 st = st.specialToken; 70 } 71 72 return javadoc; 73 } 74 75 78 protected abstract SimpleNode getEnclosingNode(); 79 80 84 public void run() 85 { 86 SimpleNode encNode = getEnclosingNode(); 87 JavadocNode javadoc = getJavadoc(); 88 89 if (javadoc == null) { 90 if (isCheckable(encNode, CHKLVL_DOC_EXISTS)) { 91 tr.Ace.log("no Javadoc"); 92 StringBuffer desc = new StringBuffer ("Undocumented "); 93 if (SimpleNodeUtil.hasLeadingToken(encNode, JavaParserConstants.PUBLIC)) { 94 desc.append("public "); 95 } 96 else if (SimpleNodeUtil.hasLeadingToken(encNode, JavaParserConstants.PROTECTED)) { 97 desc.append("protected "); 98 } 99 else if (SimpleNodeUtil.hasLeadingToken(encNode, JavaParserConstants.PRIVATE)) { 100 desc.append("private "); 101 } 102 103 if (SimpleNodeUtil.hasLeadingToken(encNode, JavaParserConstants.ABSTRACT)) { 104 desc.append("abstract "); 105 } 106 107 desc.append(getItemType()); 108 109 addUndocumentedViolation(desc.toString()); 110 } 111 else { 112 tr.Ace.log("not checkable"); 113 } 114 } 115 else { 116 checkJavadoc(javadoc); 117 } 118 } 119 120 124 protected abstract void addUndocumentedViolation(String desc); 125 126 protected void checkJavadoc(JavadocNode javadoc) 127 { 128 130 SimpleNode encNode = getEnclosingNode(); 131 132 if (isCheckable(encNode, CHKLVL_SUMMARY_SENTENCE)) { 133 JavadocElement desc = javadoc.getDescription(); 134 if (desc == null) { 135 addViolation(MSG_NO_SUMMARY_SENTENCE, javadoc.getStartLine(), javadoc.getStartColumn(), javadoc.getEndLine(), javadoc.getEndColumn()); 136 } 137 else { 138 String descStr = desc.text; 139 int dotPos = descStr.indexOf('.'); 141 int len = descStr.length(); 142 143 145 while (dotPos != -1 && dotPos + 1 < len && !Character.isWhitespace(descStr.charAt(dotPos + 1))) { 147 dotPos = descStr.indexOf('.', dotPos + 1); 148 } 149 150 if (dotPos == -1) { 151 LineMapping lines = new LineMapping(descStr, desc.start.line, desc.start.column); 152 Location end = lines.getLocation(descStr.length() - 1); 153 addViolation(MSG_SUMMARY_SENTENCE_DOES_NOT_END_WITH_PERIOD, desc.start, end); 154 } 155 else { 156 String summarySentence = descStr.substring(0, dotPos + 1); 157 tr.Ace.log("summary: '" + summarySentence + "'"); 158 int nSpaces = 0; 159 int spacePos = -1; 160 while ((spacePos = summarySentence.indexOf(' ', spacePos + 1)) != -1) { 161 ++nSpaces; 162 } 163 if (nSpaces < 3) { 164 LineMapping lines = new LineMapping(descStr, desc.start.line, desc.start.column); 165 Location end = lines.getLocation(dotPos); 166 addViolation(MSG_SUMMARY_SENTENCE_TOO_SHORT, desc.start, end); 167 } 168 } 169 170 spellChecker.check(this, desc); 171 } 172 } 173 else { 174 tr.Ace.log("NOT checking summary sentence"); 175 } 176 177 if (isCheckable(encNode, CHKLVL_MISORDERED_TAGS)) { 178 tr.Ace.log("checking for misordered tags"); 179 int previousOrderIndex = -1; 180 JavadocTaggedNode[] taggedComments = javadoc.getTaggedComments(); 181 for (int ti = 0; ti < taggedComments.length; ++ti) { 182 JavadocTag tag = taggedComments[ti].getTag(); 183 int index = JavadocTags.getIndex(tag.text); 184 tr.Ace.log("index of '" + tag.text + "': " + index); 185 if (index < previousOrderIndex) { 186 addViolation(MSG_TAG_IMPROPER_ORDER, tag.start, tag.end); 187 break; 188 } 189 previousOrderIndex = index; 190 } 191 } 192 else { 193 tr.Ace.log("skipping check for misordered tags"); 194 } 195 196 if (isCheckable(encNode, CHKLVL_VALID_TAGS)) { 198 tr.Ace.log("checking for valid tags"); 199 List validTags = getValidTags(); 200 JavadocTaggedNode[] taggedComments = javadoc.getTaggedComments(); 201 for (int ti = 0; ti < taggedComments.length; ++ti) { 202 JavadocTag tag = taggedComments[ti].getTag(); 203 if (!validTags.contains(tag.text)) { 204 addViolation("Tag not valid for " + getItemType(), tag.start, tag.end); 205 } 206 } 207 } 208 else { 209 tr.Ace.log("skipping check for valid tags"); 210 } 211 212 if (isCheckable(encNode, CHKLVL_TAG_CONTENT)) { 214 JavadocTaggedNode[] taggedComments = javadoc.getTaggedComments(); 215 for (int ti = 0; ti < taggedComments.length; ++ti) { 216 JavadocTag tag = taggedComments[ti].getTag(); 217 tr.Ace.log("checking tag: " + tag); 218 if (tag.text.equals(JavadocTags.SEE)) { 219 checkForTagDescription(taggedComments[ti], MSG_SEE_WITHOUT_REFERENCE); 220 } 221 else if (tag.text.equals(JavadocTags.SINCE)) { 222 checkForTagDescription(taggedComments[ti], MSG_SINCE_WITHOUT_TEXT); 223 } 224 else if (tag.text.equals(JavadocTags.DEPRECATED)) { 225 checkForTagDescription(taggedComments[ti], MSG_DEPRECATED_WITHOUT_TEXT); 226 } 227 } 228 } 229 else { 230 tr.Ace.log("skipping check for tag content"); 231 } 232 } 233 234 protected void checkForTagDescription(JavadocTaggedNode taggedNode, String msg) 235 { 236 JavadocElement desc = taggedNode.getDescription(); 237 if (desc == null) { 238 JavadocTag tag = taggedNode.getTag(); 239 addViolation(msg, tag.start, tag.end); 240 } 241 } 242 243 protected SimpleNode getNode() 244 { 245 return _node; 246 } 247 248 251 protected abstract String getItemType(); 252 253 256 protected abstract List getValidTags(); 257 258 } 259
| Popular Tags
|