WALA/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/ClassHierarchyMethodTargetS...

80 lines
2.5 KiB
Java

/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.ipa.callgraph.impl;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.MethodTargetSelector;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.TypeReference;
/**
* A {@link MethodTargetSelector} that simply looks up the declared type, name and descriptor of a {@link CallSiteReference} in the
* appropriate class hierarchy.
*/
public class ClassHierarchyMethodTargetSelector implements MethodTargetSelector {
/**
* Governing class hierarchy
*/
private final IClassHierarchy classHierarchy;
/**
* Initialization. The class hierarchy is needed for lookups and the warnings are used when the lookups fails (which should never
* happen).
*
* @param cha The class hierarchy to use.
*/
public ClassHierarchyMethodTargetSelector(IClassHierarchy cha) {
classHierarchy = cha;
}
/**
* This target selector searches the class hierarchy for the method matching the signature of the call that is appropriate for the
* receiver type.
*
* @throws IllegalArgumentException if call is null
*/
@Override
public IMethod getCalleeTarget(CGNode caller, CallSiteReference call, IClass receiver) {
if (call == null) {
throw new IllegalArgumentException("call is null");
}
IClass klass;
TypeReference targetType = call.getDeclaredTarget().getDeclaringClass();
// java virtual calls
if (call.isDispatch()) {
assert receiver != null : "null receiver for " + call;
klass = receiver;
// java static calls
} else if (call.isFixed()) {
klass = classHierarchy.lookupClass(targetType);
if (klass == null) {
return null;
}
// anything else
} else {
return null;
}
return classHierarchy.resolveMethod(klass, call.getDeclaredTarget().getSelector());
}
public boolean mightReturnSyntheticMethod() {
return false;
}
}