/******************************************************************************
* Copyright (c) 2002 - 2012 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.cast.js.callgraph.fieldbased.flowgraph.vertices;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.cast.js.ipa.summaries.JavaScriptConstructorFunctions.JavaScriptConstructor;
import com.ibm.wala.cast.js.types.JavaScriptMethods;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.collections.Pair;
/**
* A function vertex represents a function object (or, more precisely, all function objects
* arising from a single function expression or declaration).
*
* @author mschaefer
*/
public class FuncVertex extends Vertex implements ObjectVertex {
// the IClass representing this function in the class hierarchy
protected final IClass klass;
FuncVertex(IClass method) {
this.klass = method;
}
public String getFullName() {
return klass.getName().toString();
}
@Override
public <T> T accept(VertexVisitor<T> visitor) {
return visitor.visitFuncVertex(this);
}
@Override
public String toString() {
String methodName = klass.getName().toString();
return "Func(" + methodName.substring(methodName.lastIndexOf('/')+1) + ")";
}
@Override
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
MethodReference ctorRef = JavaScriptMethods.makeCtorReference(JavaScriptTypes.Function);
Set<CGNode> f = CG.getNodes(ctorRef);
CGNode ctor = null;
for(CGNode n : f) {
JavaScriptConstructor c = (JavaScriptConstructor) n.getMethod();
if (c.constructedType().equals(klass)) {
ctor = n;
break;
}
}
// built in objects
if (ctor == null) {
return EmptyIterator.instance();
}
Iterator<CGNode> callers = CG.getPredNodes(ctor);
CGNode caller = callers.next();
assert !callers.hasNext();
Iterator<CallSiteReference> sites = CG.getPossibleSites(caller, ctor);
CallSiteReference site = sites.next();
assert !sites.hasNext() : caller + " --> " + ctor + " @ " + site + " and " + sites.next() + "\n" + caller.getIR();
return NonNullSingletonIterator.make(Pair.make(caller, NewSiteReference.make(site.getProgramCounter(), klass.getReference())));
}
@Override
public IClass getConcreteType() {
return klass;
}
}