1 20 package com.puppycrawl.tools.checkstyle.checks.coding; 21 22 import java.util.HashMap ; 23 import java.util.HashSet ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 import java.util.Set ; 27 28 import antlr.collections.AST; 29 import com.puppycrawl.tools.checkstyle.api.Check; 30 import com.puppycrawl.tools.checkstyle.api.DetailAST; 31 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 32 33 51 public class EqualsHashCodeCheck 52 extends Check 53 { 54 57 58 private final Map mObjBlockEquals = new HashMap (); 59 60 61 private final Set mObjBlockWithHashCode = new HashSet (); 62 63 64 65 public int[] getDefaultTokens() 66 { 67 return new int[] {TokenTypes.METHOD_DEF}; 68 } 69 70 71 public void beginTree(DetailAST aRootAST) 72 { 73 mObjBlockEquals.clear(); 74 mObjBlockWithHashCode.clear(); 75 } 76 77 78 public void visitToken(DetailAST aAST) 79 { 80 final DetailAST modifiers = (DetailAST) aAST.getFirstChild(); 81 final AST type = aAST.findFirstToken(TokenTypes.TYPE); 82 final AST methodName = aAST.findFirstToken(TokenTypes.IDENT); 83 final DetailAST parameters = aAST.findFirstToken(TokenTypes.PARAMETERS); 84 85 if ((type.getFirstChild().getType() == TokenTypes.LITERAL_BOOLEAN) 86 && "equals".equals(methodName.getText()) 87 && modifiers.branchContains(TokenTypes.LITERAL_PUBLIC) 88 && (parameters.getChildCount() == 1) 89 && isObjectParam(parameters.getFirstChild()) 90 ) 91 { 92 mObjBlockEquals.put(aAST.getParent(), aAST); 93 } 94 else if ((type.getFirstChild().getType() == TokenTypes.LITERAL_INT) 95 && "hashCode".equals(methodName.getText()) 96 && modifiers.branchContains(TokenTypes.LITERAL_PUBLIC) 97 && (parameters.getFirstChild() == null)) { 99 mObjBlockWithHashCode.add(aAST.getParent()); 100 } 101 } 102 103 108 private boolean isObjectParam(AST aFirstChild) 109 { 110 final AST modifiers = aFirstChild.getFirstChild(); 111 final AST type = modifiers.getNextSibling(); 112 switch (type.getFirstChild().getType()) { 113 case TokenTypes.LITERAL_BOOLEAN: 114 case TokenTypes.LITERAL_BYTE: 115 case TokenTypes.LITERAL_CHAR: 116 case TokenTypes.LITERAL_DOUBLE: 117 case TokenTypes.LITERAL_FLOAT: 118 case TokenTypes.LITERAL_INT: 119 case TokenTypes.LITERAL_LONG: 120 case TokenTypes.LITERAL_SHORT: 121 return false; 122 default: 123 return true; 124 } 125 } 126 127 130 public void finishTree(DetailAST aRootAST) 131 { 132 final Set equalsDefs = mObjBlockEquals.keySet(); 133 for (final Iterator it = equalsDefs.iterator(); it.hasNext();) { 134 final Object objBlock = it.next(); 135 if (!mObjBlockWithHashCode.contains(objBlock)) { 136 final DetailAST equalsAST = 137 (DetailAST) mObjBlockEquals.get(objBlock); 138 log(equalsAST.getLineNo(), equalsAST.getColumnNo(), 139 "equals.noHashCode"); 140 } 141 } 142 143 mObjBlockEquals.clear(); 144 mObjBlockWithHashCode.clear(); 145 } 146 } 147 | Popular Tags |