/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.symboltable; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType; import net.sourceforge.pmd.lang.symboltable.AbstractNameDeclaration; public class MethodNameDeclaration extends AbstractNameDeclaration { public MethodNameDeclaration(ASTMethodDeclarator node) { super(node); } public int getParameterCount() { return ((ASTMethodDeclarator) node).getParameterCount(); } public boolean isVarargs() { ASTFormalParameters params = (ASTFormalParameters) node.jjtGetChild(0); if (params.getParameterCount() == 0) { return false; } // If it's a varargs, it HAS to be the last parameter ASTFormalParameter p = (ASTFormalParameter) params.jjtGetChild(params.getParameterCount() - 1); return p.isVarargs(); } public ASTMethodDeclarator getMethodNameDeclaratorNode() { return (ASTMethodDeclarator) node; } public String getParameterDisplaySignature() { StringBuilder sb = new StringBuilder("("); ASTFormalParameters params = (ASTFormalParameters) node.jjtGetChild(0); // TODO - this can be optimized - add [0] then ,[n] in a loop. // no need to trim at the end for (int i = 0; i < ((ASTMethodDeclarator) node).getParameterCount(); i++) { ASTFormalParameter p = (ASTFormalParameter) params.jjtGetChild(i); sb.append(p.getTypeNode().getTypeImage()); if (p.isVarargs()) { sb.append("..."); } sb.append(','); } if (sb.charAt(sb.length() - 1) == ',') { sb.deleteCharAt(sb.length() - 1); } sb.append(')'); return sb.toString(); } @Override public boolean equals(Object o) { if (!(o instanceof MethodNameDeclaration)) { return false; } MethodNameDeclaration other = (MethodNameDeclaration) o; // compare name if (!other.node.getImage().equals(node.getImage())) { return false; } // compare parameter count - this catches the case where there are no // params, too if (((ASTMethodDeclarator) other.node).getParameterCount() != ((ASTMethodDeclarator) node) .getParameterCount()) { return false; } // compare parameter types ASTFormalParameters myParams = (ASTFormalParameters) node.jjtGetChild(0); ASTFormalParameters otherParams = (ASTFormalParameters) other.node.jjtGetChild(0); for (int i = 0; i < ((ASTMethodDeclarator) node).getParameterCount(); i++) { ASTFormalParameter myParam = (ASTFormalParameter) myParams.jjtGetChild(i); ASTFormalParameter otherParam = (ASTFormalParameter) otherParams.jjtGetChild(i); // Compare vararg if (myParam.isVarargs() != otherParam.isVarargs()) { return false; } Node myTypeNode = myParam.getTypeNode().jjtGetChild(0); Node otherTypeNode = otherParam.getTypeNode().jjtGetChild(0); // compare primitive vs reference type if (myTypeNode.getClass() != otherTypeNode.getClass()) { return false; } // simple comparison of type images // this can be fooled by one method using "String" // and the other method using "java.lang.String" // once we get real types in here that should get fixed String myTypeImg; String otherTypeImg; if (myTypeNode instanceof ASTPrimitiveType) { myTypeImg = myTypeNode.getImage(); otherTypeImg = otherTypeNode.getImage(); } else { myTypeImg = myTypeNode.jjtGetChild(0).getImage(); otherTypeImg = otherTypeNode.jjtGetChild(0).getImage(); } if (!myTypeImg.equals(otherTypeImg)) { return false; } // if type is ASTPrimitiveType and is an array, make sure the other // one is also } return true; } @Override public int hashCode() { int hash = node.getImage().hashCode() * 31 + ((ASTMethodDeclarator) node).getParameterCount(); ASTFormalParameters myParams = (ASTFormalParameters) node.jjtGetChild(0); for (int i = 0; i < ((ASTMethodDeclarator) node).getParameterCount(); i++) { ASTFormalParameter myParam = (ASTFormalParameter) myParams.jjtGetChild(i); Node myTypeNode = myParam.getTypeNode().jjtGetChild(0); String myTypeImg; if (myTypeNode instanceof ASTPrimitiveType) { myTypeImg = myTypeNode.getImage(); } else { myTypeImg = myTypeNode.jjtGetChild(0).getImage(); } hash = hash * 31 + myTypeImg.hashCode(); } return hash; } @Override public String toString() { return "Method " + node.getImage() + ", line " + node.getBeginLine() + ", params = " + ((ASTMethodDeclarator) node).getParameterCount(); } }