/** * Copyright (C) 2005 - 2011 Eric Van Dewoestine * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.eclim.plugin.jdt.util; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.Signature; /** * Utility methods for working with IMethod elements. * * @author Eric Van Dewoestine */ public class MethodUtils { private static final String VARARGS = "..."; /** * Determines if the supplied types contains the specified method. * * @param typeInfo The type info. * @param method The method. * @return true if the type contains the method, false otherwise. */ public static boolean containsMethod(TypeInfo typeInfo, IMethod method) throws Exception { /*IMethod[] methods = type.getMethods(); for(int ii = 0; ii < methods.length; ii++){ if(methods[ii].isSimilar(method)){ return true; } } return false;*/ IType type = typeInfo.getType(); String signature = getMinimalMethodSignature(method, typeInfo); if(method.isConstructor()){ signature = signature.replaceFirst( method.getDeclaringType().getElementName(), type.getElementName()); } IMethod[] methods = type.getMethods(); for (int ii = 0; ii < methods.length; ii++){ String methodSig = getMinimalMethodSignature(methods[ii], typeInfo); if(methodSig.equals(signature)){ return true; } } return false; } /** * Gets the method from the supplied type that matches the signature of the * specified method. * * @param typeInfo The type info. * @param method The method. * @return The method or null if none found. */ public static IMethod getMethod(TypeInfo typeInfo, IMethod method) throws Exception { IType type = typeInfo.getType(); String signature = getMinimalMethodSignature(method, typeInfo); if(method.isConstructor()){ signature = signature.replaceFirst( method.getDeclaringType().getElementName(), type.getElementName()); } IMethod[] methods = type.getMethods(); for (int ii = 0; ii < methods.length; ii++){ String methodSig = getMinimalMethodSignature(methods[ii], typeInfo); if(methodSig.equals(signature)){ return methods[ii]; } } return null; } /** * Retrieves the method which follows the supplied method in the specified * type. * * @param type The type. * @param method The method. * @return The method declared after the supplied method. */ public static IMethod getMethodAfter(IType type, IMethod method) throws Exception { if(type == null || method == null){ return null; } // get the method after the sibling. IMethod[] all = type.getMethods(); for (int ii = 0; ii < all.length; ii++){ if(all[ii].equals(method) && ii < all.length - 1){ return all[ii + 1]; } } return null; } /** * Gets a String representation of the supplied method's signature. * * @param method The method. * @param typeInfo The type info. * @return The signature. */ public static String getMethodSignature(IMethod method, TypeInfo typeInfo) throws Exception { int flags = method.getFlags(); StringBuffer buffer = new StringBuffer(); if(method.getDeclaringType().isInterface()){ buffer.append("public "); }else{ buffer.append( Flags.isPublic(method.getFlags()) ? "public " : "protected "); } buffer.append(Flags.isAbstract(flags) ? "abstract " : ""); if(!method.isConstructor()){ String name = Signature.getSignatureSimpleName(method.getReturnType()); buffer.append(TypeUtils.replaceTypeParams(name, typeInfo)).append(' '); } buffer.append(method.getElementName()) .append("(") .append(getMethodParameters(method, typeInfo, true)) .append(')'); String[] exceptions = method.getExceptionTypes(); if(exceptions.length > 0){ buffer.append("\n\tthrows ").append(getMethodThrows(method)); } return buffer.toString(); } /** * Gets just enough of a method's signature that it can be distiguished from * the other methods. * * @param method The method. * @return The signature. */ public static String getMinimalMethodSignature( IMethod method, TypeInfo typeInfo) throws Exception { StringBuffer buffer = new StringBuffer(); buffer.append(method.getElementName()) .append('(') .append(getMethodParameters(method, typeInfo, false)) .append(')'); return buffer.toString(); } /** * Gets the supplied method's parameter types and optoinally names, in a comma * separated string. * * @param method The method. * @param typeInfo The type info. * @param includeNames true to include the paramter names in the string. * @return The parameters as a string. */ public static String getMethodParameters( IMethod method, TypeInfo typeInfo, boolean includeNames) throws Exception { StringBuffer buffer = new StringBuffer(); String[] paramTypes = method.getParameterTypes(); String[] paramNames = null; if(includeNames){ paramNames = method.getParameterNames(); } boolean varargs = false; for(int ii = 0; ii < paramTypes.length; ii++){ if(ii != 0){ buffer.append(includeNames ? ", " : ","); } String type = paramTypes[ii]; // check for varargs if (ii == paramTypes.length - 1 && Signature.getTypeSignatureKind(type) == Signature.ARRAY_TYPE_SIGNATURE && Flags.isVarargs(method.getFlags())) { type = Signature.getElementType(paramTypes[ii]); varargs = true; } type = Signature.getSignatureSimpleName(type); type = type.replaceAll("\\?\\s+extends\\s+", ""); type = TypeUtils.replaceTypeParams(type, typeInfo); buffer.append(type); if(varargs){ buffer.append(VARARGS); } if(includeNames){ buffer.append(' ').append(paramNames[ii]); } } return buffer.toString(); } /** * Gets the list of thrown exceptions as a comma separated string. * * @param method The method. * @return The thrown exceptions or null if none. */ public static String getMethodThrows(IMethod method) throws Exception { String[] exceptions = method.getExceptionTypes(); if(exceptions.length > 0){ StringBuffer buffer = new StringBuffer(); for(int ii = 0; ii < exceptions.length; ii++){ if(ii != 0){ buffer.append(", "); } buffer.append(Signature.getSignatureSimpleName(exceptions[ii])); } return buffer.toString(); } return null; } }