1 package com.puppycrawl.tools.checkstyle.checks.metrics; 20 21 import java.util.Stack ; 22 23 import com.puppycrawl.tools.checkstyle.api.Check; 24 import com.puppycrawl.tools.checkstyle.api.DetailAST; 25 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 26 27 39 public class JavaNCSSCheck extends Check 40 { 41 42 private static final int FILE_MAX_NCSS = 2000; 43 44 45 private static final int CLASS_MAX_NCSS = 1500; 46 47 48 private static final int METHOD_MAX_NCSS = 50; 49 50 51 private int mFileMax = FILE_MAX_NCSS; 52 53 54 private int mClassMax = CLASS_MAX_NCSS; 55 56 57 private int mMethodMax = METHOD_MAX_NCSS; 58 59 60 private Stack mCounters; 61 62 65 public int[] getDefaultTokens() 66 { 67 return new int[]{ 68 TokenTypes.CLASS_DEF, 69 TokenTypes.INTERFACE_DEF, 70 TokenTypes.METHOD_DEF, 71 TokenTypes.CTOR_DEF, 72 TokenTypes.INSTANCE_INIT, 73 TokenTypes.STATIC_INIT, 74 TokenTypes.PACKAGE_DEF, 75 TokenTypes.IMPORT, 76 TokenTypes.VARIABLE_DEF, 77 TokenTypes.CTOR_CALL, 78 TokenTypes.SUPER_CTOR_CALL, 79 TokenTypes.LITERAL_IF, 80 TokenTypes.LITERAL_ELSE, 81 TokenTypes.LITERAL_WHILE, 82 TokenTypes.LITERAL_DO, 83 TokenTypes.LITERAL_FOR, 84 TokenTypes.LITERAL_SWITCH, 85 TokenTypes.LITERAL_BREAK, 86 TokenTypes.LITERAL_CONTINUE, 87 TokenTypes.LITERAL_RETURN, 88 TokenTypes.LITERAL_THROW, 89 TokenTypes.LITERAL_SYNCHRONIZED, 90 TokenTypes.LITERAL_CATCH, 91 TokenTypes.LITERAL_FINALLY, 92 TokenTypes.EXPR, 93 TokenTypes.LABELED_STAT, 94 TokenTypes.LITERAL_CASE, 95 TokenTypes.LITERAL_DEFAULT, 96 }; 97 } 98 99 102 public int[] getRequiredTokens() 103 { 104 return new int[]{ 105 TokenTypes.CLASS_DEF, 106 TokenTypes.INTERFACE_DEF, 107 TokenTypes.METHOD_DEF, 108 TokenTypes.CTOR_DEF, 109 TokenTypes.INSTANCE_INIT, 110 TokenTypes.STATIC_INIT, 111 TokenTypes.PACKAGE_DEF, 112 TokenTypes.IMPORT, 113 TokenTypes.VARIABLE_DEF, 114 TokenTypes.CTOR_CALL, 115 TokenTypes.SUPER_CTOR_CALL, 116 TokenTypes.LITERAL_IF, 117 TokenTypes.LITERAL_ELSE, 118 TokenTypes.LITERAL_WHILE, 119 TokenTypes.LITERAL_DO, 120 TokenTypes.LITERAL_FOR, 121 TokenTypes.LITERAL_SWITCH, 122 TokenTypes.LITERAL_BREAK, 123 TokenTypes.LITERAL_CONTINUE, 124 TokenTypes.LITERAL_RETURN, 125 TokenTypes.LITERAL_THROW, 126 TokenTypes.LITERAL_SYNCHRONIZED, 127 TokenTypes.LITERAL_CATCH, 128 TokenTypes.LITERAL_FINALLY, 129 TokenTypes.EXPR, 130 TokenTypes.LABELED_STAT, 131 TokenTypes.LITERAL_CASE, 132 TokenTypes.LITERAL_DEFAULT, 133 }; 134 } 135 136 139 public void beginTree(DetailAST aRootAST) 140 { 141 mCounters = new Stack (); 142 143 mCounters.push(new Counter()); 145 } 146 147 150 public void visitToken(DetailAST aAST) 151 { 152 final int tokenType = aAST.getType(); 153 154 if ((TokenTypes.CLASS_DEF == tokenType) 155 || (TokenTypes.METHOD_DEF == tokenType) 156 || (TokenTypes.CTOR_DEF == tokenType) 157 || (TokenTypes.STATIC_INIT == tokenType) 158 || (TokenTypes.INSTANCE_INIT == tokenType)) 159 { 160 mCounters.push(new Counter()); 162 } 163 164 if (isCountable(aAST)) { 166 final int size = mCounters.size(); 168 for (int i = 0; i < size; i++) { 169 ((Counter) mCounters.get(i)).increment(); 170 } 171 } 172 } 173 174 177 public void leaveToken(DetailAST aAST) 178 { 179 final int tokenType = aAST.getType(); 180 if ((TokenTypes.METHOD_DEF == tokenType) 181 || (TokenTypes.CTOR_DEF == tokenType) 182 || (TokenTypes.STATIC_INIT == tokenType) 183 || (TokenTypes.INSTANCE_INIT == tokenType)) 184 { 185 final Counter counter = (Counter) mCounters.pop(); 187 188 final int count = counter.getCount(); 189 if (count > mMethodMax) { 190 log(aAST.getLineNo(), aAST.getColumnNo(), "ncss.method", 191 new Integer (count), new Integer (mMethodMax)); 192 } 193 } 194 else if (TokenTypes.CLASS_DEF == tokenType) { 195 final Counter counter = (Counter) mCounters.pop(); 197 198 final int count = counter.getCount(); 199 if (count > mClassMax) { 200 log(aAST.getLineNo(), aAST.getColumnNo(), "ncss.class", 201 new Integer (count), new Integer (mClassMax)); 202 } 203 } 204 } 205 206 209 public void finishTree(DetailAST aRootAST) 210 { 211 final Counter counter = (Counter) mCounters.pop(); 213 214 final int count = counter.getCount(); 215 if (count > mFileMax) { 216 log(aRootAST.getLineNo(), aRootAST.getColumnNo(), "ncss.file", 217 new Integer (count), new Integer (mMethodMax)); 218 } 219 } 220 221 227 public void setFileMaximum(int aFileMax) 228 { 229 mFileMax = aFileMax; 230 } 231 232 238 public void setClassMaximum(int aClassMax) 239 { 240 mClassMax = aClassMax; 241 } 242 243 249 public void setMethodMaximum(int aMethodMax) 250 { 251 mMethodMax = aMethodMax; 252 } 253 254 261 private boolean isCountable(DetailAST aAST) 262 { 263 boolean countable = true; 264 265 final int tokenType = aAST.getType(); 266 267 if (TokenTypes.EXPR == tokenType) { 269 countable = isExpressionCountable(aAST); 270 } 271 else if (TokenTypes.VARIABLE_DEF == tokenType) { 273 countable = isVariableDefCountable(aAST); 274 } 275 return countable; 276 } 277 278 284 private boolean isVariableDefCountable(DetailAST aAST) 285 { 286 boolean countable = false; 287 288 final int parentType = aAST.getParent().getType(); 291 292 if ((TokenTypes.SLIST == parentType) 293 || (TokenTypes.OBJBLOCK == parentType)) 294 { 295 final DetailAST prevSibling = aAST.getPreviousSibling(); 296 297 countable = (prevSibling == null) 302 || (TokenTypes.COMMA != prevSibling.getType()); 303 } 304 305 return countable; 306 } 307 308 314 private boolean isExpressionCountable(DetailAST aAST) 315 { 316 boolean countable = true; 317 318 final int parentType = aAST.getParent().getType(); 322 switch (parentType) { 323 case TokenTypes.SLIST : 324 case TokenTypes.LABELED_STAT : 325 case TokenTypes.LITERAL_FOR : 326 case TokenTypes.LITERAL_DO : 327 case TokenTypes.LITERAL_WHILE : 328 case TokenTypes.LITERAL_IF : 329 case TokenTypes.LITERAL_ELSE : 330 final DetailAST prevSibling = aAST.getPreviousSibling(); 332 countable = (prevSibling == null) 333 || (TokenTypes.LPAREN != prevSibling.getType()); 334 break; 335 default : 336 countable = false; 337 break; 338 } 339 return countable; 340 } 341 342 347 private class Counter 348 { 349 350 private int mIvCount; 351 352 355 public void increment() 356 { 357 mIvCount++; 358 } 359 360 365 public int getCount() 366 { 367 return mIvCount; 368 } 369 } 370 } 371 | Popular Tags |