KickJava   Java API By Example, From Geeks To Geeks.

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


1 package org.incava.doctorj;
2
3 import java.io.*;
4 import java.util.*;
5 import net.sourceforge.pmd.ast.*;
6 import org.incava.analysis.*;
7 import org.incava.java.ParameterUtil;
8 import org.incava.java.SimpleNodeUtil;
9 import org.incava.javadoc.*;
10 import org.incava.text.Location;
11 import org.incava.text.SpellChecker;
12
13
14 /**
15  * Checks the validity of Javadoc for a list of parameters.
16  */

17 public class ParameterDocAnalyzer extends DocAnalyzer
18 {
19     /**
20      * The message for documented parameters for a function without any in the
21      * code.
22      */

23     public final static String JavaDoc MSG_PARAMETERS_DOCUMENTED_BUT_NO_CODE_PARAMETERS = "Parameters documented but no code parameters";
24     
25     /**
26      * The message for a parameter field without a name.
27      */

28     public final static String JavaDoc MSG_PARAMETER_WITHOUT_NAME = "Parameter tag without name";
29
30     /**
31      * The message for a parameter field without a description.
32      */

33     public final static String JavaDoc MSG_PARAMETER_WITHOUT_DESCRIPTION = "Parameter without description";
34
35     /**
36      * The message for parameters being misordered with regard to the code.
37      */

38     public final static String JavaDoc MSG_PARAMETER_NOT_IN_CODE_ORDER = "Parameter not in code order";
39
40     /**
41      * The message for a parameter being apparently misspelled from that in the
42      * code.
43      */

44     public final static String JavaDoc MSG_PARAMETER_MISSPELLED = "Parameter misspelled";
45
46     /**
47      * The message for a parameter referring to argument type, not name.
48      */

49     public final static String JavaDoc MSG_PARAMETER_TYPE_USED = "Parameter refers to type, not name";
50
51     /**
52      * The message for an undocumented code parameter.
53      */

54     public final static String JavaDoc MSG_PARAMETER_NOT_DOCUMENTED = "Parameter not documented";
55
56     /**
57      * The message for a documented parameter not found in the code.
58      */

59     public final static String JavaDoc MSG_PARAMETER_NOT_IN_CODE = "Parameter not in code";
60
61     /**
62      * The message for a repeated documented parameter.
63      */

64     public final static String JavaDoc MSG_PARAMETER_REPEATED = "Parameter repeated";
65
66     /**
67      * The warning level for checking for the existence of Javadoc for
68      * parameters.
69      */

70     protected final static int CHKLVL_PARAM_DOC_EXISTS = 2;
71
72     /**
73      * The Javadoc block applicable to this parameter list.
74      */

75     private JavadocNode _javadoc;
76
77     /**
78      * The function containing the list of parameters.
79      */

80     private SimpleNode _function;
81
82     /**
83      * The list of parameters in the code.
84      */

85     private ASTFormalParameters _parameterList;
86
87     /**
88      * The list of parameters from the code, that were documented.
89      */

90     private List _documentedParameters = new ArrayList();
91
92     private int _nodeLevel;
93
94     /**
95      * Creates and runs the parameter documentation analyzer.
96      *
97      * @param report The report to which to send violations.
98      * @param javadoc The javadoc for the function. Should not be null.
99      * @param function The constructor or method.
100      */

101     public ParameterDocAnalyzer(Report report, JavadocNode javadoc, SimpleNode function, ASTFormalParameters parameterList, int nodeLevel)
102     {
103         super(report);
104
105         _javadoc = javadoc;
106         _function = function;
107         _parameterList = parameterList;
108         _nodeLevel = nodeLevel;
109     }
110
111     /**
112      * Analyzes the Javadoc for the parameter list.
113      */

114     public void run()
115     {
116         tr.Ace.log("function", _function);
117
118         // foreach @throws / @parameter tag:
119
// - check for target
120
// - check for description
121
// - in order as in code
122

123         boolean misorderedReported = false;
124         int parameterIndex = 0;
125             
126         JavadocTaggedNode[] taggedComments = _javadoc.getTaggedComments();
127         for (int ti = 0; ti < taggedComments.length; ++ti) {
128             JavadocTaggedNode jtn = taggedComments[ti];
129             tr.Ace.bold("jtn", jtn);
130             JavadocTag tag = jtn.getTag();
131             
132             tr.Ace.yellow("tag", tag);
133             if (tag.text.equals(JavadocTags.PARAM)) {
134                 tr.Ace.magenta("parameter");
135                 
136                 JavadocElement tgt = jtn.getTarget();
137                 tr.Ace.magenta("tgt", tgt);
138
139                 tr.Ace.yellow("parameter index: " + parameterIndex);
140
141                 if (!SimpleNodeUtil.hasChildren(_parameterList)) {
142                     addViolation(MSG_PARAMETERS_DOCUMENTED_BUT_NO_CODE_PARAMETERS, tag.start, tag.end);
143                     break;
144                 }
145                 else if (tgt == null) {
146                     if (Options.warningLevel >= CHKLVL_TAG_CONTENT + _nodeLevel) {
147                         addViolation(MSG_PARAMETER_WITHOUT_NAME, tag.start, tag.end);
148                     }
149                     else {
150                         tr.Ace.log("function", _function);
151                     }
152                 }
153                 else {
154                     JavadocElement desc = jtn.getDescriptionNonTarget();
155                     if (jtn.getDescriptionNonTarget() == null) {
156                         if (Options.warningLevel >= CHKLVL_TAG_CONTENT + _nodeLevel) {
157                             addViolation(MSG_PARAMETER_WITHOUT_DESCRIPTION, tgt.start, tgt.end);
158                         }
159                         else {
160                             tr.Ace.log("function", _function);
161                         }
162                     }
163
164                     String JavaDoc tgtStr = tgt.text;
165                     int index = getMatchingParameter(tgtStr);
166                     
167                     tr.Ace.log("matching parameter: " + index);
168
169                     if (index == -1) {
170                         index = getClosestMatchingParameter(tgtStr);
171                         tr.Ace.log("closest matching parameter: " + index);
172                         tr.Ace.log("parameter index: " + parameterIndex);
173
174                         SimpleNodeUtil.dump(_parameterList, "pppp");
175
176                         if (index == -1) {
177                             String JavaDoc paramType = ParameterUtil.getParameterType(_parameterList, parameterIndex);
178                             tr.Ace.log("paramType: " + paramType + "; tgtStr: " + tgtStr);
179
180                             if (tgtStr.equals(paramType)) {
181                                 addViolation(MSG_PARAMETER_TYPE_USED, tgt.start, tgt.end);
182                                 addDocumentedParameter(parameterIndex, tgt.start, tgt.end);
183                             }
184                             else {
185                                 addViolation(MSG_PARAMETER_NOT_IN_CODE, tgt.start, tgt.end);
186                             }
187                         }
188                         else {
189                             addViolation(MSG_PARAMETER_MISSPELLED, tgt.start, tgt.end);
190                             addDocumentedParameter(index, tgt.start, tgt.end);
191                         }
192                     }
193                     else {
194                         addDocumentedParameter(index, tgt.start, tgt.end);
195                     }
196                 }
197                 ++parameterIndex;
198             }
199         }
200
201         tr.Ace.log("documentedParameters", _documentedParameters);
202
203         if (_parameterList == null) {
204             tr.Ace.log("no parameters");
205         }
206         else if (isCheckable(_function, CHKLVL_PARAM_DOC_EXISTS)) {
207             reportUndocumentedParameters();
208         }
209         else {
210             tr.Ace.log("function", _function);
211         }
212     }
213
214     protected void addDocumentedParameter(int index, Location start, Location end)
215     {
216         if (_documentedParameters.size() > 0 && ((Integer JavaDoc)_documentedParameters.get(_documentedParameters.size() - 1)).intValue() > index) {
217             addViolation(MSG_PARAMETER_NOT_IN_CODE_ORDER, start, end);
218         }
219         
220         Integer JavaDoc i = new Integer JavaDoc(index);
221         if (_documentedParameters.contains(i)) {
222             addViolation(MSG_PARAMETER_REPEATED, start, end);
223         }
224         else {
225             _documentedParameters.add(i);
226         }
227     }
228     
229     protected void reportUndocumentedParameters()
230     {
231         ASTFormalParameter[] params = ParameterUtil.getParameters(_parameterList);
232         
233         for (int ni = 0; ni < params.length; ++ni) {
234             tr.Ace.log("parameter", params[ni]);
235             ASTFormalParameter param = params[ni];
236             if (!_documentedParameters.contains(new Integer JavaDoc(ni))) {
237                 Token nameTk = ParameterUtil.getParameterName(param);
238                 addViolation(MSG_PARAMETER_NOT_DOCUMENTED, nameTk);
239             }
240         }
241     }
242
243     /**
244      * Returns the first param in the list whose name matches the given string.
245      */

246     protected int getMatchingParameter(String JavaDoc str)
247     {
248         ASTFormalParameter[] params = ParameterUtil.getParameters(_parameterList);
249         
250         for (int ni = 0; ni < params.length; ++ni) {
251             tr.Ace.log("parameter", params[ni]);
252             ASTFormalParameter param = params[ni];
253             Token nameTk = ParameterUtil.getParameterName(param);
254             if (nameTk.image.equals(str)) {
255                 return ni;
256             }
257         }
258
259         return -1;
260     }
261
262     /**
263      * Returns the first param in the list whose name most closely matches the
264      * given string.
265      */

266     protected int getClosestMatchingParameter(String JavaDoc str)
267     {
268         if (_parameterList == null) {
269             return -1;
270         }
271         else {
272             SpellChecker spellChecker = new SpellChecker();
273             int bestDistance = -1;
274             int bestIndex = -1;
275             ASTFormalParameter[] params = ParameterUtil.getParameters(_parameterList);
276         
277             for (int ni = 0; ni < params.length; ++ni) {
278                 tr.Ace.log("parameter", params[ni]);
279                 ASTFormalParameter param = params[ni];
280                 Token nameTk = ParameterUtil.getParameterName(param);
281                 int dist = spellChecker.editDistance(nameTk.image, str);
282
283                 // tr.Ace.log("edit distance(param: '" + paramTkn.image + "', str: '" + str + "'): " + dist);
284

285                 if (dist >= 0 && dist <= SpellChecker.DEFAULT_MAX_DISTANCE && (bestDistance == -1 || dist < bestDistance)) {
286                     bestDistance = dist;
287                     bestIndex = ni;
288                 }
289             }
290
291             return bestIndex;
292         }
293     }
294
295 }
296
Popular Tags