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 17 public class ParameterDocAnalyzer extends DocAnalyzer 18 { 19 23 public final static String MSG_PARAMETERS_DOCUMENTED_BUT_NO_CODE_PARAMETERS = "Parameters documented but no code parameters"; 24 25 28 public final static String MSG_PARAMETER_WITHOUT_NAME = "Parameter tag without name"; 29 30 33 public final static String MSG_PARAMETER_WITHOUT_DESCRIPTION = "Parameter without description"; 34 35 38 public final static String MSG_PARAMETER_NOT_IN_CODE_ORDER = "Parameter not in code order"; 39 40 44 public final static String MSG_PARAMETER_MISSPELLED = "Parameter misspelled"; 45 46 49 public final static String MSG_PARAMETER_TYPE_USED = "Parameter refers to type, not name"; 50 51 54 public final static String MSG_PARAMETER_NOT_DOCUMENTED = "Parameter not documented"; 55 56 59 public final static String MSG_PARAMETER_NOT_IN_CODE = "Parameter not in code"; 60 61 64 public final static String MSG_PARAMETER_REPEATED = "Parameter repeated"; 65 66 70 protected final static int CHKLVL_PARAM_DOC_EXISTS = 2; 71 72 75 private JavadocNode _javadoc; 76 77 80 private SimpleNode _function; 81 82 85 private ASTFormalParameters _parameterList; 86 87 90 private List _documentedParameters = new ArrayList(); 91 92 private int _nodeLevel; 93 94 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 114 public void run() 115 { 116 tr.Ace.log("function", _function); 117 118 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 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 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 )_documentedParameters.get(_documentedParameters.size() - 1)).intValue() > index) { 217 addViolation(MSG_PARAMETER_NOT_IN_CODE_ORDER, start, end); 218 } 219 220 Integer i = new Integer (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 (ni))) { 237 Token nameTk = ParameterUtil.getParameterName(param); 238 addViolation(MSG_PARAMETER_NOT_DOCUMENTED, nameTk); 239 } 240 } 241 } 242 243 246 protected int getMatchingParameter(String 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 266 protected int getClosestMatchingParameter(String 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 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
|