work on CHA

This commit is contained in:
Julian Dolby 2013-04-03 12:12:43 -04:00
parent c9e1b2e587
commit 321e925660
19 changed files with 497 additions and 50 deletions

View File

@ -49,11 +49,11 @@
<target name="getSources" depends="fetchJLex" />
<target name="testdatadir" depends="init,testdata.exists" unless="testdatadir.present">
<mkdir dir="${basedir}/../com.ibm.wala.cast.java.test/testdata"/>
<mkdir dir="${basedir}/../com.ibm.wala.ide.jdt.test/testdata"/>
</target>
<target name="testdata.exists" depends="init">
<available file="${basedir}/../com.ibm.wala.cast.java.test/testdata"
<available file="${basedir}/../com.ibm.wala.ide.jdt.test/testdata"
type="dir"
property="testdatadir.present"/>
</target>
@ -65,7 +65,7 @@
</target>
<target name="jar" depends="compile,testdatadir">
<jar destfile="${basedir}/../com.ibm.wala.cast.java.test/testdata/test_project.zip" basedir="${basedir}"/>
<jar destfile="${basedir}/../com.ibm.wala.ide.jdt.test/testdata/test_project.zip" basedir="${basedir}"/>
</target>
<target name="init" depends="properties">

View File

@ -0,0 +1,9 @@
package javaonepointfive;
public class TypeInferencePrimAndStringOp {
public static void main(String[] args) {
int a = 2;
String result = "a" + a;
}
}

View File

@ -33,7 +33,7 @@ import com.ibm.wala.util.debug.Assertions;
public class AstJavaTypeInference extends AstTypeInference {
protected final IClass stringClass;
protected IClass stringClass;
protected class AstJavaTypeOperatorFactory extends AstTypeOperatorFactory implements AstJavaInstructionVisitor {
public void visitBinaryOp(SSABinaryOpInstruction instruction) {
@ -96,7 +96,13 @@ public class AstJavaTypeInference extends AstTypeInference {
public AstJavaTypeInference(IR ir, IClassHierarchy cha, boolean doPrimitives) {
super(ir, cha, JavaPrimitiveType.BOOLEAN, doPrimitives);
this.stringClass = cha.lookupClass(TypeReference.JavaLangString);
}
IClass getStringClass() {
if (stringClass == null) {
this.stringClass = cha.lookupClass(TypeReference.JavaLangString);
}
return stringClass;
}
protected void initialize() {
@ -125,12 +131,12 @@ public class AstJavaTypeInference extends AstTypeInference {
TypeVariable r = (TypeVariable) rhs[i];
TypeAbstraction ta = r.getType();
if (ta instanceof PointType) {
if (ta.getType().equals(stringClass)) {
if (ta.getType().equals(getStringClass())) {
meet = new PointType(ta.getType());
break;
}
} else if (ta instanceof ConeType) {
if (ta.getType().equals(stringClass)) {
if (ta.getType().equals(getStringClass())) {
meet = new PointType(ta.getType());
break;
}

View File

@ -135,7 +135,7 @@ public class CrossLanguageClassHierarchy implements IClassHierarchy {
return getHierarchy(c).getNumber(c);
}
public Collection<IMethod> getPossibleTargets(MethodReference ref) {
public Set<IMethod> getPossibleTargets(MethodReference ref) {
return getHierarchy(ref).getPossibleTargets(ref);
}

View File

@ -0,0 +1,41 @@
package com.ibm.wala.core.tests.callGraph;
import java.io.IOException;
import org.junit.Test;
import com.ibm.wala.core.tests.util.TestConstants;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.cha.CHACallGraph;
import com.ibm.wala.ipa.callgraph.impl.AllApplicationEntrypoints;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.CancelException;
public class CHACallGraphTest {
@Test public void testJava_cup() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
testCHA(TestConstants.JAVA_CUP, TestConstants.JAVA_CUP_MAIN);
}
public static CallGraph testCHA(String scopeFile, String mainClass) throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(scopeFile, CallGraphTestUtil.REGRESSION_EXCLUSIONS);
ClassHierarchy cha = ClassHierarchy.make(scope);
Iterable<Entrypoint> entrypoints;
if (mainClass == null) {
entrypoints = new AllApplicationEntrypoints(scope, cha);
} else {
entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, mainClass);
}
CHACallGraph CG = new CHACallGraph(cha);
CG.init(entrypoints);
return CG;
}
public static void main(String[] args) throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
testCHA(args[0], args.length>1? args[1]: null);
}
}

View File

@ -28,6 +28,7 @@ Export-Package: .,
com.ibm.wala.demandpa.util,
com.ibm.wala.escape,
com.ibm.wala.ipa.callgraph,
com.ibm.wala.ipa.callgraph.cha,
com.ibm.wala.ipa.callgraph.impl,
com.ibm.wala.ipa.callgraph.propagation,
com.ibm.wala.ipa.callgraph.propagation.cfa,

View File

@ -0,0 +1,345 @@
/*******************************************************************************
* Copyright (c) 2007 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.cha;
import java.lang.ref.SoftReference;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.BasicCallGraph;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
import com.ibm.wala.ipa.callgraph.impl.FakeWorldClinitMethod;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.DefUse;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.ComposedIterator;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.FilterIterator;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.collections.IteratorUtil;
import com.ibm.wala.util.collections.MapIterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.functions.Function;
import com.ibm.wala.util.graph.NumberedEdgeManager;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
public class CHACallGraph extends BasicCallGraph<CHAContextInterpreter> {
private final IClassHierarchy cha;
private final AnalysisOptions options;
private final AnalysisCache cache;
private boolean isInitialized = false;
private class CHANode extends NodeImpl {
protected CHANode(IMethod method, Context C) {
super(method, C);
}
public IR getIR() {
assert false;
return null;
}
public DefUse getDU() {
assert false;
return null;
}
public Iterator<NewSiteReference> iterateNewSites() {
assert false;
return null;
}
public Iterator<CallSiteReference> iterateCallSites() {
return getInterpreter(this).iterateCallSites(this);
}
@Override
public boolean equals(Object obj) {
return obj.getClass()==getClass() && getMethod().equals(((CHANode)obj).getMethod());
}
@Override
public int hashCode() {
return getMethod().hashCode();
}
@Override
public boolean addTarget(CallSiteReference reference, CGNode target) {
return false;
}
}
public CHACallGraph(IClassHierarchy cha) {
this.cha = cha;
this.options = new AnalysisOptions();
this.cache = new AnalysisCache();
setInterpreter(new ContextInsensitiveCHAContextInterpreter());
}
public void init(Iterable<Entrypoint> entrypoints) throws CancelException {
super.init();
CGNode root = getFakeRootNode();
int programCounter = 0;
for(Entrypoint e : entrypoints) {
root.addTarget(e.makeSite(programCounter++), null);
}
closure(root, true);
isInitialized = true;
}
public IClassHierarchy getClassHierarchy() {
return cha;
}
private Iterator<IMethod> getPossibleTargets(CallSiteReference site) {
if (site.isDispatch()) {
return cha.getPossibleTargets(site.getDeclaredTarget()).iterator();
} else {
IMethod m = cha.resolveMethod(site.getDeclaredTarget());
if (m != null) {
return new NonNullSingletonIterator<IMethod>(m);
} else {
return EmptyIterator.instance();
}
}
}
public Set<CGNode> getPossibleTargets(CGNode node, CallSiteReference site) {
return Iterator2Collection.toSet(
new MapIterator<IMethod,CGNode>(
new FilterIterator<IMethod>(
getPossibleTargets(site),
new Filter<IMethod>() {
public boolean accepts(IMethod o) {
return !o.isAbstract();
}
}
),
new Function<IMethod,CGNode>() {
public CGNode apply(IMethod object) {
try {
return findOrCreateNode(object, Everywhere.EVERYWHERE);
} catch (CancelException e) {
assert false : e.toString();
return null;
}
}
}));
}
public int getNumberOfTargets(CGNode node, CallSiteReference site) {
return IteratorUtil.count(getPossibleTargets(site));
}
public Iterator<CallSiteReference> getPossibleSites(final CGNode src, final CGNode target) {
return
new FilterIterator<CallSiteReference>(getInterpreter(src).iterateCallSites(src),
new Filter<CallSiteReference>() {
public boolean accepts(CallSiteReference o) {
return getPossibleTargets(src, o).contains(target);
}
});
}
private class CHARootNode extends CHANode {
private final Set<CallSiteReference> calls = HashSetFactory.make();
protected CHARootNode(IMethod method, Context C) {
super(method, C);
}
@Override
public Iterator<CallSiteReference> iterateCallSites() {
return calls.iterator();
}
@Override
public boolean addTarget(CallSiteReference reference, CGNode target) {
return calls.add(reference);
}
}
@Override
protected CGNode makeFakeRootNode() throws CancelException {
return new CHARootNode(new FakeRootMethod(cha, options, cache), Everywhere.EVERYWHERE);
}
@Override
protected CGNode makeFakeWorldClinitNode() throws CancelException {
return new CHARootNode(new FakeWorldClinitMethod(cha, options, cache), Everywhere.EVERYWHERE);
}
private void closure(CGNode n, boolean fromRoot) throws CancelException {
for(Iterator<CallSiteReference> sites = n.iterateCallSites(); sites.hasNext(); ) {
Iterator<IMethod> methods = getPossibleTargets(sites.next());
while (methods.hasNext()) {
IMethod target = methods.next();
if (!target.isAbstract()) {
CGNode callee = getNode(target, Everywhere.EVERYWHERE);
if (callee == null) {
callee = findOrCreateNode(target, Everywhere.EVERYWHERE);
if (fromRoot) {
registerEntrypoint(callee);
}
}
}
}
}
}
private int clinitPC = 0;
@Override
public CGNode findOrCreateNode(IMethod method, Context C) throws CancelException {
assert C.equals(Everywhere.EVERYWHERE);
assert !method.isAbstract();
CGNode n = getNode(method, C);
if (n == null) {
assert !isInitialized;
n = makeNewNode(method, C);
IMethod clinit = method.getDeclaringClass().getClassInitializer();
if (clinit != null && getNode(clinit, Everywhere.EVERYWHERE) == null) {
CGNode cln = makeNewNode(clinit, Everywhere.EVERYWHERE);
CGNode clinits = getFakeWorldClinitNode();
clinits.addTarget(CallSiteReference.make(clinitPC++, clinit.getReference(), IInvokeInstruction.Dispatch.STATIC), cln);
}
}
return n;
}
private CGNode makeNewNode(IMethod method, Context C) throws CancelException {
CGNode n;
Key k = new Key(method, C);
n = new CHANode(method, C);
registerNode(k, n);
closure(n, false);
return n;
}
@Override
protected NumberedEdgeManager<CGNode> getEdgeManager() {
return new NumberedEdgeManager<CGNode>() {
private final Map<CGNode, SoftReference<Set<CGNode>>> predecessors = HashMapFactory.make();
private Set<CGNode> getPreds(CGNode n) {
if (predecessors.containsKey(n) && predecessors.get(n).get() != null) {
return predecessors.get(n).get();
} else {
Set<CGNode> preds = HashSetFactory.make();
for(CGNode node : CHACallGraph.this) {
if (getPossibleSites(node, n).hasNext()) {
preds.add(node);
}
}
predecessors.put(n, new SoftReference<Set<CGNode>>(preds));
return preds;
}
}
public Iterator<CGNode> getPredNodes(CGNode n) {
return getPreds(n).iterator();
}
public int getPredNodeCount(CGNode n) {
return getPreds(n).size();
}
public Iterator<CGNode> getSuccNodes(final CGNode n) {
return new FilterIterator<CGNode>(new ComposedIterator<CallSiteReference, CGNode>(n.iterateCallSites()) {
@Override
public Iterator<? extends CGNode> makeInner(CallSiteReference outer) {
return getPossibleTargets(n, outer).iterator();
}
},
new Filter<CGNode>() {
private final MutableIntSet nodes = IntSetUtil.make();
public boolean accepts(CGNode o) {
if (nodes.contains(o.getGraphNodeId())) {
return false;
} else {
nodes.add(o.getGraphNodeId());
return true;
}
}
});
}
public int getSuccNodeCount(CGNode N) {
return IteratorUtil.count(getSuccNodes(N));
}
public void addEdge(CGNode src, CGNode dst) {
assert false;
}
public void removeEdge(CGNode src, CGNode dst) throws UnsupportedOperationException {
assert false;
}
public void removeAllIncidentEdges(CGNode node) throws UnsupportedOperationException {
assert false;
}
public void removeIncomingEdges(CGNode node) throws UnsupportedOperationException {
assert false;
}
public void removeOutgoingEdges(CGNode node) throws UnsupportedOperationException {
assert false;
}
public boolean hasEdge(CGNode src, CGNode dst) {
return getPossibleSites(src, dst).hasNext();
}
public IntSet getSuccNodeNumbers(CGNode node) {
MutableIntSet result = IntSetUtil.make();
for(Iterator<CGNode> ss = getSuccNodes(node); ss.hasNext(); ) {
result.add(ss.next().getGraphNodeId());
}
return result;
}
public IntSet getPredNodeNumbers(CGNode node) {
MutableIntSet result = IntSetUtil.make();
for(Iterator<CGNode> ss = getPredNodes(node); ss.hasNext(); ) {
result.add(ss.next().getGraphNodeId());
}
return result;
}
};
}
}

View File

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2007 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.cha;
import java.util.Iterator;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.ipa.callgraph.CGNode;
public interface CHAContextInterpreter {
/**
* Does this object understand the given method? The caller had better check this before inquiring on other properties.
*/
public boolean understands(CGNode node);
/**
* @return an Iterator of the call statements that may execute in a given method for a given context
*/
public abstract Iterator<CallSiteReference> iterateCallSites(CGNode node);
}

View File

@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 2007 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.cha;
import java.util.Iterator;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.CodeScanner;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
import com.ibm.wala.util.debug.Assertions;
public class ContextInsensitiveCHAContextInterpreter implements CHAContextInterpreter {
public boolean understands(CGNode node) {
return true;
}
public Iterator<CallSiteReference> iterateCallSites(CGNode node) {
if (node == null) {
throw new IllegalArgumentException("node is null");
}
try {
return CodeScanner.getCallSites(node.getMethod()).iterator();
} catch (InvalidClassFileException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
return null;
}
}
}

View File

@ -23,7 +23,6 @@ import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.propagation.ReceiverInstanceContext;
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.types.MethodReference;
@ -42,7 +41,7 @@ import com.ibm.wala.util.graph.traverse.DFS;
/**
* Basic data structure support for a call graph.
*/
public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> implements CallGraph {
public abstract class BasicCallGraph<T> extends AbstractNumberedGraph<CGNode> implements CallGraph {
private static final boolean DEBUG = false;
@ -61,7 +60,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
/**
* An object that handles context interpreter functions
*/
private SSAContextInterpreter interpreter;
private T interpreter;
/**
* Set of nodes that are entrypoints for this analysis
@ -81,7 +80,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
*
* TODO: this is a bit redundant with the nodes Map. Restructure these data structures for space efficiency.
*/
final private Map<MethodReference, Set<CGNode>> mr2Nodes = HashMapFactory.make();
protected final Map<MethodReference, Set<CGNode>> mr2Nodes = HashMapFactory.make();
public BasicCallGraph() {
super();
@ -303,7 +302,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
* @param node a call graph node we want information about
* @return an object that knows how to interpret information about the node
*/
protected SSAContextInterpreter getInterpreter(CGNode node) {
protected T getInterpreter(CGNode node) {
if (interpreter == null) {
throw new IllegalStateException("must register an interpreter for this call graph");
}
@ -344,7 +343,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
return getNode(N.getMethod(), N.getContext()) != null;
}
public void setInterpreter(SSAContextInterpreter interpreter) {
public void setInterpreter(T interpreter) {
this.interpreter = interpreter;
}

View File

@ -23,6 +23,7 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.BytecodeConstants;
import com.ibm.wala.ssa.DefUse;
@ -50,7 +51,7 @@ import com.ibm.wala.util.intset.SparseIntSet;
/**
* A call graph which explicitly holds the target for each call site in each node.
*/
public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstants {
public class ExplicitCallGraph extends BasicCallGraph<SSAContextInterpreter> implements BytecodeConstants {
protected final IClassHierarchy cha;

View File

@ -19,6 +19,7 @@ import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.cha.ContextInsensitiveCHAContextInterpreter;
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
import com.ibm.wala.types.FieldReference;
@ -27,7 +28,7 @@ import com.ibm.wala.util.debug.Assertions;
/**
* Default implementation of MethodContextInterpreter for context-insensitive analysis
*/
public abstract class ContextInsensitiveRTAInterpreter implements RTAContextInterpreter, SSAContextInterpreter {
public abstract class ContextInsensitiveRTAInterpreter extends ContextInsensitiveCHAContextInterpreter implements RTAContextInterpreter, SSAContextInterpreter {
private final AnalysisCache analysisCache;
@ -52,19 +53,6 @@ public abstract class ContextInsensitiveRTAInterpreter implements RTAContextInte
}
}
public Iterator<CallSiteReference> iterateCallSites(CGNode node) {
if (node == null) {
throw new IllegalArgumentException("node is null");
}
try {
return CodeScanner.getCallSites(node.getMethod()).iterator();
} catch (InvalidClassFileException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
return null;
}
}
public Iterator<FieldReference> iterateFieldsRead(CGNode node) {
if (node == null) {
throw new IllegalArgumentException("node is null");
@ -91,10 +79,6 @@ public abstract class ContextInsensitiveRTAInterpreter implements RTAContextInte
}
}
public boolean understands(CGNode node) {
return true;
}
public boolean recordFactoryType(CGNode node, IClass klass) {
// not a factory type
return false;

View File

@ -12,31 +12,22 @@ package com.ibm.wala.ipa.callgraph.propagation.rta;
import java.util.Iterator;
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.cha.CHAContextInterpreter;
import com.ibm.wala.types.FieldReference;
/**
* This object will analyze a method in a context and return information needed for RTA.
*/
public interface RTAContextInterpreter {
/**
* Does this object understand the given method? The caller had better check this before inquiring on other properties.
*/
public boolean understands(CGNode node);
public interface RTAContextInterpreter extends CHAContextInterpreter {
/**
* @return an Iterator of the types that may be allocated by a given method in a given context.
*/
public abstract Iterator<NewSiteReference> iterateNewSites(CGNode node);
/**
* @return an Iterator of the call statements that may execute in a given method for a given context
*/
public abstract Iterator<CallSiteReference> iterateCallSites(CGNode node);
/**
* @return iterator of FieldReference
*/

View File

@ -389,7 +389,7 @@ public class ClassHierarchy implements IClassHierarchy {
* @return the set of IMethods that this call can resolve to.
* @throws IllegalArgumentException if ref is null
*/
public Collection<IMethod> getPossibleTargets(MethodReference ref) {
public Set<IMethod> getPossibleTargets(MethodReference ref) {
if (ref == null) {
throw new IllegalArgumentException("ref is null");
}

View File

@ -52,7 +52,7 @@ public interface IClassHierarchy extends Iterable<IClass> {
* @return the set of IMethods that this call can resolve to.
* @throws IllegalArgumentException if ref is null
*/
public Collection<IMethod> getPossibleTargets(MethodReference ref);
public Set<IMethod> getPossibleTargets(MethodReference ref);
/**
* Find the possible targets of a call to a method reference where the receiver is of a certain type

View File

@ -9,7 +9,7 @@ Require-Bundle: com.ibm.wala.core;bundle-version="1.1.3",
com.ibm.wala.cast.js;bundle-version="1.0.0",
com.ibm.wala.cast.js.rhino;bundle-version="1.0.0",
com.ibm.wala.ide.jsdt;bundle-version="1.0.0",
org.eclipse.wst.jsdt.core;bundle-version="1.1.202",
org.eclipse.wst.jsdt.core,
org.eclipse.equinox.common;bundle-version="3.6.100",
com.ibm.wala.ide.tests;bundle-version="1.1.3",
org.eclipse.core.runtime;bundle-version="3.8.0"

View File

@ -26,7 +26,7 @@
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/Oracle Java 1.7"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JDK 1.6"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.ibm.wala.ide.jsdt.tests.JSProjectScopeTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.ide.jsdt.tests"/>

View File

@ -114,7 +114,7 @@ public class EclipseTestUtil {
IPath path = new Path("testdata").append(filename);
URL url = FileLocator.find(bundle, path, null);
assert url != null;
assert url != null : bundle.toString() + " path " + path.toString();
try {
URL fileURL = FileLocator.toFileURL(url);
File file = new File(fileURL.getPath());

View File

@ -31,7 +31,7 @@ public abstract class ComposedIterator<O,I> implements Iterator<I> {
break;
}
}
if (!inner.hasNext()) {
if (inner != null && !inner.hasNext()) {
inner = null;
}
}