1 20 package com.puppycrawl.tools.checkstyle.checks.coding; 21 22 import antlr.collections.AST; 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 54 public class UnnecessaryParenthesesCheck extends Check 55 { 56 57 private static final int MIN_CHILDREN_FOR_MATCH = 3; 58 59 private static final int MAX_QUOTED_LENGTH = 25; 60 61 62 private static final int [] LITERALS = { 63 TokenTypes.NUM_DOUBLE, 64 TokenTypes.NUM_FLOAT, 65 TokenTypes.NUM_INT, 66 TokenTypes.NUM_LONG, 67 TokenTypes.STRING_LITERAL, 68 TokenTypes.LITERAL_NULL, 69 TokenTypes.LITERAL_FALSE, 70 TokenTypes.LITERAL_TRUE, 71 }; 72 73 74 private static final int [] ASSIGNMENTS = { 75 TokenTypes.ASSIGN, 76 TokenTypes.BAND_ASSIGN, 77 TokenTypes.BOR_ASSIGN, 78 TokenTypes.BSR_ASSIGN, 79 TokenTypes.BXOR_ASSIGN, 80 TokenTypes.DIV_ASSIGN, 81 TokenTypes.MINUS_ASSIGN, 82 TokenTypes.MOD_ASSIGN, 83 TokenTypes.PLUS_ASSIGN, 84 TokenTypes.SL_ASSIGN, 85 TokenTypes.SR_ASSIGN, 86 TokenTypes.STAR_ASSIGN, 87 }; 88 89 93 private DetailAST mParentToSkip; 94 95 private int mAssignDepth; 96 97 98 public int[] getDefaultTokens() 99 { 100 return new int [] { 101 TokenTypes.EXPR, 102 TokenTypes.IDENT, 103 TokenTypes.NUM_DOUBLE, 104 TokenTypes.NUM_FLOAT, 105 TokenTypes.NUM_INT, 106 TokenTypes.NUM_LONG, 107 TokenTypes.STRING_LITERAL, 108 TokenTypes.LITERAL_NULL, 109 TokenTypes.LITERAL_FALSE, 110 TokenTypes.LITERAL_TRUE, 111 TokenTypes.ASSIGN, 112 TokenTypes.BAND_ASSIGN, 113 TokenTypes.BOR_ASSIGN, 114 TokenTypes.BSR_ASSIGN, 115 TokenTypes.BXOR_ASSIGN, 116 TokenTypes.DIV_ASSIGN, 117 TokenTypes.MINUS_ASSIGN, 118 TokenTypes.MOD_ASSIGN, 119 TokenTypes.PLUS_ASSIGN, 120 TokenTypes.SL_ASSIGN, 121 TokenTypes.SR_ASSIGN, 122 TokenTypes.STAR_ASSIGN, 123 }; 124 } 125 126 127 public void visitToken(DetailAST aAST) 128 { 129 final int type = aAST.getType(); 130 final boolean surrounded = isSurrounded(aAST); 131 final DetailAST parent = aAST.getParent(); 132 133 if ((type == TokenTypes.ASSIGN) 134 && (parent.getType() == TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR)) 135 { 136 return; 138 } 139 140 if (surrounded && (type == TokenTypes.IDENT)) { 142 mParentToSkip = aAST.getParent(); 143 log(aAST, "unnecessary.paren.ident", aAST.getText()); 144 return; 145 } 146 147 if (surrounded && inTokenList(type, LITERALS)) { 149 mParentToSkip = aAST.getParent(); 150 if (type == TokenTypes.STRING_LITERAL) { 151 log(aAST, "unnecessary.paren.string", 152 chopString(aAST.getText())); 153 } 154 else { 155 log(aAST, "unnecessary.paren.literal", aAST.getText()); 156 } 157 return; 158 } 159 160 if (inTokenList(type, ASSIGNMENTS)) { 162 mAssignDepth++; 163 final DetailAST last = aAST.getLastChild(); 164 if (last.getType() == TokenTypes.RPAREN) { 165 log(aAST, "unnecessary.paren.assign"); 166 } 167 } 168 } 169 170 171 public void leaveToken(DetailAST aAST) 172 { 173 final int type = aAST.getType(); 174 final DetailAST parent = aAST.getParent(); 175 176 if ((type == TokenTypes.ASSIGN) 177 && (parent.getType() == TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR)) 178 { 179 return; 181 } 182 183 if (type == TokenTypes.EXPR) { 185 186 190 if ((mParentToSkip != aAST) && exprSurrounded(aAST)) { 191 if (mAssignDepth >= 1) { 192 log(aAST, "unnecessary.paren.assign"); 193 } 194 else if (aAST.getParent().getType() 195 == TokenTypes.LITERAL_RETURN) 196 { 197 log(aAST, "unnecessary.paren.return"); 198 } 199 else { 200 log(aAST, "unnecessary.paren.expr"); 201 } 202 } 203 204 mParentToSkip = null; 205 } 206 else if (inTokenList(type, ASSIGNMENTS)) { 207 mAssignDepth--; 208 } 209 210 super.leaveToken(aAST); 211 } 212 213 223 private boolean isSurrounded(DetailAST aAST) 224 { 225 final DetailAST prev = aAST.getPreviousSibling(); 226 final DetailAST next = (DetailAST) aAST.getNextSibling(); 227 228 return (prev != null) && (prev.getType() == TokenTypes.LPAREN) 229 && (next != null) && (next.getType() == TokenTypes.RPAREN); 230 } 231 232 241 private boolean exprSurrounded(DetailAST aAST) 242 { 243 if (aAST.getType() != TokenTypes.EXPR) { 244 throw new IllegalArgumentException ("Not an expression node."); 245 } 246 boolean surrounded = false; 247 if (aAST.getChildCount() >= MIN_CHILDREN_FOR_MATCH) { 248 final AST n1 = aAST.getFirstChild(); 249 final AST nn = aAST.getLastChild(); 250 251 surrounded = (n1.getType() == TokenTypes.LPAREN) 252 && (nn.getType() == TokenTypes.RPAREN); 253 } 254 return surrounded; 255 } 256 257 264 private boolean inTokenList(int aType, int [] aTokens) 265 { 266 270 boolean found = false; 271 for (int i = 0; (i < aTokens.length) && !found; i++) { 272 found = aTokens[i] == aType; 273 } 274 return found; 275 } 276 277 285 private String chopString(String aString) 286 { 287 if (aString.length() > MAX_QUOTED_LENGTH) { 288 return aString.substring(0, MAX_QUOTED_LENGTH) + "...\""; 289 } 290 return aString; 291 } 292 } 293 | Popular Tags |