KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > incava > doctorj > ItemDocAnalyzer


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 /**
15  * Analyzes Javadoc and code.
16  */

17 public abstract class ItemDocAnalyzer extends DocAnalyzer
18 {
19     public final static String JavaDoc MSG_NO_SUMMARY_SENTENCE = "No summary sentence";
20
21     public final static String JavaDoc MSG_SUMMARY_SENTENCE_DOES_NOT_END_WITH_PERIOD = "Summary sentence does not end with period";
22
23     public final static String JavaDoc MSG_SUMMARY_SENTENCE_TOO_SHORT = "Summary sentence too short";
24
25     public final static String JavaDoc MSG_SEE_WITHOUT_REFERENCE = "@see without reference";
26
27     public final static String JavaDoc MSG_SINCE_WITHOUT_TEXT = "@since without text";
28
29     public final static String JavaDoc MSG_DEPRECATED_WITHOUT_TEXT = "@deprecated without text";
30     
31     public final static String JavaDoc 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 JavaDoc dictName)
51     {
52         spellChecker.addDictionary(dictName);
53     }
54
55     /**
56      * Returns the Javadoc for the given node. By default, this is parses from
57      * the whitespace immediately preceding this node. Other nodes might be
58      * nested under the node with the preceding Javadoc.
59      */

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     /**
76      * Returns the node that contains the access and modifier tokens.
77      */

78     protected abstract SimpleNode getEnclosingNode();
79
80     /**
81      * Runs the analysis. Should be invoked by either the constructors of
82      * concrete, final subclasses, or by the client.
83      */

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 JavaDoc desc = new StringBuffer JavaDoc("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     /**
121      * Adds a violation for this type of item, with the violation pointing to
122      * the name for this item.
123      */

124     protected abstract void addUndocumentedViolation(String JavaDoc desc);
125
126     protected void checkJavadoc(JavadocNode javadoc)
127     {
128         // check for short summary sentence and spell check the description.
129

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 JavaDoc descStr = desc.text;
139                 // tr.Ace.log("desc: '" + descStr + "'");
140
int dotPos = descStr.indexOf('.');
141                 int len = descStr.length();
142                 
143                 // tr.Ace.log("dotPos: " + dotPos);
144

145                 // skip sequences like '127.0.0.1', i.e., whitespace must follow the dot:
146
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 JavaDoc 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         // check for proper tags for this type of item
197
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         // check each tag for this item
213
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 JavaDoc 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     /**
249      * Returns the type of item this analyzer is operating on.
250      */

251     protected abstract String JavaDoc getItemType();
252
253     /**
254      * Returns the valid tags, as strings, for this type of item.
255      */

256     protected abstract List getValidTags();
257
258 }
259
Popular Tags