package gb.svnfilter.findbugs;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
/**
* Internal utility to select methods by their binary signature. For performance
* optimization matching is performed in two steps, where the first step should
* quickly identify methods in most situations: Identification by name and
* parameter count. Only if the first step does fails to identify a method
* unambiguously the parameter types are resolved in a second step.
*
* @author Marc R. Hoffmann
* @version $Revision: $
*/
@SuppressWarnings("unchecked")
public class MethodLocator {
/** Special value to identify ambiguous entries in {@link #indexParamCount} */
private static final Object AMBIGUOUS = new Object();
/** Index on methods by name and parameter count. */
private final Map indexParamCount = new HashMap();
/** Index on methods by name and parameter signature. */
private final Map indexParamSignature = new HashMap();
private final IType type;
/**
* Initializes a new locator for method search within the given type.
*
* @param type
* type to search methods in
* @throws JavaModelException
*/
public MethodLocator(final IType type) throws JavaModelException {
this.type = type;
final IMethod[] methods = type.getMethods();
for (int i = 0; i < methods.length; i++) {
addToIndex(methods[i]);
}
}
/**
* Searches for the method with the given binary name.
*
* @param name
* binary method name
* @param signature
* binary method signature
* @return method or <code>null</code>
*/
public IMethod findMethod(String name, String signature) {
if (name.equals("<init>")) { //$NON-NLS-1$
name = type.getElementName();
}
final Object value = indexParamCount.get(createParamCountKey(name,
signature));
if (value == AMBIGUOUS) {
return (IMethod) indexParamSignature.get(createParamSignatureKey(name,
signature));
}
return (IMethod) value;
}
private void addToIndex(final IMethod method) throws JavaModelException {
final String paramCountKey = createParamCountKey(method);
final Object existing = indexParamCount.get(paramCountKey);
if (existing == null) {
indexParamCount.put(paramCountKey, method);
return;
}
if (existing != AMBIGUOUS) {
indexParamCount.put(paramCountKey, AMBIGUOUS);
final IMethod m = (IMethod) existing;
indexParamSignature.put(createParamSignatureKey(m), m);
}
indexParamSignature.put(createParamSignatureKey(method), method);
}
private String createParamCountKey(final IMethod method) {
return method.getElementName() + "@" + method.getParameterTypes().length; //$NON-NLS-1$
}
private String createParamCountKey(final String name,
final String fullSignature) {
return name + "@" + Signature.getParameterCount(fullSignature); //$NON-NLS-1$
}
private String createParamSignatureKey(final IMethod method)
throws JavaModelException {
return method.getElementName() + "#" //$NON-NLS-1$
+ SignatureResolver.getParameters(method);
}
private String createParamSignatureKey(final String name,
final String fullSignature) {
return name + "#" + SignatureResolver.getParameters(fullSignature); //$NON-NLS-1$
}
}