more work for reuse
make synthetic code better support non-Java languages
This commit is contained in:
parent
81a6e67b4b
commit
6c1d0d9cb6
|
@ -94,7 +94,6 @@ public class CAstAnalysisScope extends AnalysisScope {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ClassLoaderReference getSyntheticLoader() {
|
public ClassLoaderReference getSyntheticLoader() {
|
||||||
Assertions.UNREACHABLE();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
return getField(name);
|
return getField(name);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Collection<IMethod> getDeclaredMethods() {
|
public Collection<? extends IMethod> getDeclaredMethods() {
|
||||||
return declaredMethods.values();
|
return declaredMethods.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<IMethod> getAllMethods() {
|
public Collection<? extends IMethod> getAllMethods() {
|
||||||
Collection<IMethod> result = HashSetFactory.make();
|
Collection<IMethod> result = HashSetFactory.make();
|
||||||
for (IMethod iMethod : getDeclaredMethods()) {
|
for (IMethod iMethod : getDeclaredMethods()) {
|
||||||
result.add(iMethod);
|
result.add(iMethod);
|
||||||
|
|
|
@ -88,4 +88,45 @@ public class AstDynamicField implements IField {
|
||||||
public Collection<Annotation> getAnnotations() {
|
public Collection<Annotation> getAnnotations() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((cls == null) ? 0 : cls.hashCode());
|
||||||
|
result = prime * result + ((descriptor == null) ? 0 : descriptor.hashCode());
|
||||||
|
result = prime * result + (isStatic ? 1231 : 1237);
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
AstDynamicField other = (AstDynamicField) obj;
|
||||||
|
if (cls == null) {
|
||||||
|
if (other.cls != null)
|
||||||
|
return false;
|
||||||
|
} else if (!cls.equals(other.cls))
|
||||||
|
return false;
|
||||||
|
if (descriptor == null) {
|
||||||
|
if (other.descriptor != null)
|
||||||
|
return false;
|
||||||
|
} else if (!descriptor.equals(other.descriptor))
|
||||||
|
return false;
|
||||||
|
if (isStatic != other.isStatic)
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import com.ibm.wala.classLoader.ClassLoaderFactory;
|
||||||
import com.ibm.wala.classLoader.IClassLoader;
|
import com.ibm.wala.classLoader.IClassLoader;
|
||||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
|
import com.ibm.wala.ipa.summaries.BypassSyntheticClassLoader;
|
||||||
import com.ibm.wala.types.ClassLoaderReference;
|
import com.ibm.wala.types.ClassLoaderReference;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
|
||||||
|
@ -28,8 +29,13 @@ public abstract class SingleClassLoaderFactory implements ClassLoaderFactory {
|
||||||
*/
|
*/
|
||||||
private IClassLoader THE_LOADER = null;
|
private IClassLoader THE_LOADER = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support synthetic classes
|
||||||
|
*/
|
||||||
|
private IClassLoader syntheticLoader;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IClassLoader getLoader(ClassLoaderReference classLoaderReference, IClassHierarchy cha, AnalysisScope scope) {
|
public IClassLoader getLoader(ClassLoaderReference classLoaderReference, IClassHierarchy cha, AnalysisScope scope) {
|
||||||
if (THE_LOADER == null) {
|
if (THE_LOADER == null) {
|
||||||
THE_LOADER = makeTheLoader(cha);
|
THE_LOADER = makeTheLoader(cha);
|
||||||
try {
|
try {
|
||||||
|
@ -39,9 +45,14 @@ public abstract class SingleClassLoaderFactory implements ClassLoaderFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert classLoaderReference.equals(getTheReference());
|
if (classLoaderReference.equals(scope.getSyntheticLoader())) {
|
||||||
|
syntheticLoader = new BypassSyntheticClassLoader(scope.getSyntheticLoader(), THE_LOADER, scope.getExclusions(), cha);
|
||||||
return THE_LOADER;
|
return syntheticLoader;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
assert classLoaderReference.equals(getTheReference());
|
||||||
|
return THE_LOADER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IClassLoader getTheLoader() {
|
public IClassLoader getTheLoader() {
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class DefaultMethodsTest extends WalaTestCase {
|
||||||
TypeReference test1Type = TypeReference.findOrCreate(ClassLoaderReference.Application, "LdefaultMethods/DefaultMethods$Test1");
|
TypeReference test1Type = TypeReference.findOrCreate(ClassLoaderReference.Application, "LdefaultMethods/DefaultMethods$Test1");
|
||||||
IClass test1Class = cha.lookupClass(test1Type);
|
IClass test1Class = cha.lookupClass(test1Type);
|
||||||
|
|
||||||
Collection<IMethod> allMethods = test1Class.getAllMethods();
|
Collection<? extends IMethod> allMethods = test1Class.getAllMethods();
|
||||||
IMethod defaultMethod = test1Class.getMethod(t1m.getSelector());
|
IMethod defaultMethod = test1Class.getMethod(t1m.getSelector());
|
||||||
Assert.assertTrue("Expecting default methods to show up in IClass.allMethods()", allMethods.contains(defaultMethod));
|
Assert.assertTrue("Expecting default methods to show up in IClass.allMethods()", allMethods.contains(defaultMethod));
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class GetMethodContextInterpreter implements SSAContextInterpreter {
|
||||||
*/
|
*/
|
||||||
private static Collection<IMethod> getAllNormalPublicMethods(IClass cls,Atom name) {
|
private static Collection<IMethod> getAllNormalPublicMethods(IClass cls,Atom name) {
|
||||||
Collection<IMethod> result = HashSetFactory.make();
|
Collection<IMethod> result = HashSetFactory.make();
|
||||||
Collection<IMethod> allMethods = null;
|
Collection<? extends IMethod> allMethods = null;
|
||||||
allMethods = cls.getAllMethods();
|
allMethods = cls.getAllMethods();
|
||||||
for (IMethod m : allMethods) {
|
for (IMethod m : allMethods) {
|
||||||
if (!m.isInit() && !m.isClinit() && m.isPublic() && m.getSelector().getName().equals(name)) {
|
if (!m.isInit() && !m.isClinit() && m.isPublic() && m.getSelector().getName().equals(name)) {
|
||||||
|
|
|
@ -239,7 +239,7 @@ public class JavaLangClassContextInterpreter implements SSAContextInterpreter {
|
||||||
*/
|
*/
|
||||||
private static Collection<IMethod> getAllNormalPublicMethods(IClass cls) {
|
private static Collection<IMethod> getAllNormalPublicMethods(IClass cls) {
|
||||||
Collection<IMethod> result = HashSetFactory.make();
|
Collection<IMethod> result = HashSetFactory.make();
|
||||||
Collection<IMethod> allMethods = null;
|
Collection<? extends IMethod> allMethods = null;
|
||||||
allMethods = cls.getAllMethods();
|
allMethods = cls.getAllMethods();
|
||||||
for (IMethod m : allMethods) {
|
for (IMethod m : allMethods) {
|
||||||
if (!m.isInit() && !m.isClinit() && m.isPublic()) {
|
if (!m.isInit() && !m.isClinit() && m.isPublic()) {
|
||||||
|
|
|
@ -343,7 +343,7 @@ public class ArrayClass implements IClass, Constants {
|
||||||
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Collection<IMethod> getAllMethods() {
|
public Collection<? extends IMethod> getAllMethods() {
|
||||||
return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()).getAllMethods();
|
return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()).getAllMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -405,7 +405,7 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
|
||||||
}
|
}
|
||||||
IClass s = getSuperclass();
|
IClass s = getSuperclass();
|
||||||
while (s != null) {
|
while (s != null) {
|
||||||
Iterator<IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator();
|
Iterator<? extends IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator();
|
||||||
while (superDeclaredMethods.hasNext()) {
|
while (superDeclaredMethods.hasNext()) {
|
||||||
result.add(superDeclaredMethods.next());
|
result.add(superDeclaredMethods.next());
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ public interface IClass extends IClassHierarchyDweller {
|
||||||
/**
|
/**
|
||||||
* @return an Iterator of the IMethods declared by this class.
|
* @return an Iterator of the IMethods declared by this class.
|
||||||
*/
|
*/
|
||||||
Collection<IMethod> getDeclaredMethods();
|
Collection<? extends IMethod> getDeclaredMethods();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the instance fields declared by this class or any of its superclasses.
|
* Compute the instance fields declared by this class or any of its superclasses.
|
||||||
|
@ -155,7 +155,7 @@ public interface IClass extends IClassHierarchyDweller {
|
||||||
/**
|
/**
|
||||||
* Compute the methods declared by this class or any of its superclasses.
|
* Compute the methods declared by this class or any of its superclasses.
|
||||||
*/
|
*/
|
||||||
Collection<IMethod> getAllMethods();
|
Collection<? extends IMethod> getAllMethods();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the instance fields declared by this class.
|
* Compute the instance fields declared by this class.
|
||||||
|
|
|
@ -16,7 +16,6 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
import com.ibm.wala.types.ClassLoaderReference;
|
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.types.annotations.Annotation;
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
|
@ -77,7 +76,7 @@ public abstract class SyntheticClass implements IClass {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IClassLoader getClassLoader() {
|
public IClassLoader getClassLoader() {
|
||||||
return cha.getLoader(ClassLoaderReference.Primordial);
|
return cha.getLoader(T.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -112,7 +112,14 @@ public class BypassMethodTargetSelector implements MethodTargetSelector {
|
||||||
IMethod target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget,
|
IMethod target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget,
|
||||||
site.isStatic());
|
site.isStatic());
|
||||||
|
|
||||||
|
// try synthetic method that matches receiver type
|
||||||
|
if (dispatchType != null) {
|
||||||
|
ref = MethodReference.findOrCreate(dispatchType.getReference(), ref.getSelector());
|
||||||
|
chaTarget = chaMethodTargetSelector.getCalleeTarget(caller, site, dispatchType);
|
||||||
|
target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget,
|
||||||
|
site.isStatic());
|
||||||
|
}
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.err.println("target is initially " + target);
|
System.err.println("target is initially " + target);
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ public class BypassSyntheticClass extends SyntheticClass {
|
||||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
|
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Collection<IMethod> getDeclaredMethods() {
|
public Collection<? extends IMethod> getDeclaredMethods() {
|
||||||
return realType.getDeclaredMethods();
|
return realType.getDeclaredMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ public class BypassSyntheticClass extends SyntheticClass {
|
||||||
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Collection<IMethod> getAllMethods() {
|
public Collection<? extends IMethod> getAllMethods() {
|
||||||
return realType.getAllMethods();
|
return realType.getAllMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ import com.ibm.wala.util.strings.Atom;
|
||||||
*
|
*
|
||||||
* Code that wants to introduce synthetic classes uses the registerClass method,
|
* Code that wants to introduce synthetic classes uses the registerClass method,
|
||||||
* giving it an Atom which is the class name, and an IClass which is the class
|
* giving it an Atom which is the class name, and an IClass which is the class
|
||||||
* to load. Since the synthetic loader musat be a child of the others, it would
|
* to load. Since the synthetic loader must be a child of the others, it would
|
||||||
* be very bad to use an existing name for a new synthetic class.
|
* be very bad to use an existing name for a new synthetic class.
|
||||||
*
|
*
|
||||||
* Class lookup works just as for any other classloader.
|
* Class lookup works just as for any other classloader.
|
||||||
|
@ -148,7 +148,7 @@ public class BypassSyntheticClassLoader implements IClassLoader {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Language getLanguage() {
|
public Language getLanguage() {
|
||||||
return Language.JAVA;
|
return parent.getLanguage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -54,8 +54,8 @@ public class JUnitEntryPoints {
|
||||||
System.out.println("application class: " + klass);
|
System.out.println("application class: " + klass);
|
||||||
|
|
||||||
// return all the tests methods
|
// return all the tests methods
|
||||||
Collection<IMethod> methods = klass.getAllMethods();
|
Collection<? extends IMethod> methods = klass.getAllMethods();
|
||||||
Iterator<IMethod> methodsIt = methods.iterator();
|
Iterator<? extends IMethod> methodsIt = methods.iterator();
|
||||||
|
|
||||||
while (methodsIt.hasNext()) {
|
while (methodsIt.hasNext()) {
|
||||||
IMethod m = methodsIt.next();
|
IMethod m = methodsIt.next();
|
||||||
|
|
|
@ -248,7 +248,7 @@ nextMethod:
|
||||||
// Don't consider internal overrides
|
// Don't consider internal overrides
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final Collection<IMethod> methods = candid.getDeclaredMethods();
|
final Collection<? extends IMethod> methods = candid.getDeclaredMethods();
|
||||||
for (final IMethod method : methods) {
|
for (final IMethod method : methods) {
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ nextMethod:
|
||||||
{ // Overridden methods
|
{ // Overridden methods
|
||||||
if (isAPIComponent(appClass)) continue;
|
if (isAPIComponent(appClass)) continue;
|
||||||
if (isExcluded(appClass)) continue;
|
if (isExcluded(appClass)) continue;
|
||||||
final Collection<IMethod> methods = appClass.getDeclaredMethods();
|
final Collection<? extends IMethod> methods = appClass.getDeclaredMethods();
|
||||||
for (final IMethod method : methods) {
|
for (final IMethod method : methods) {
|
||||||
if ((method.isInit() || method.isClinit()) && (! this.flags.contains(LocatorFlags.WITH_CTOR))) {
|
if ((method.isInit() || method.isClinit()) && (! this.flags.contains(LocatorFlags.WITH_CTOR))) {
|
||||||
logger.debug("Skipping constructor of {}", method);
|
logger.debug("Skipping constructor of {}", method);
|
||||||
|
@ -359,7 +359,7 @@ nextMethod:
|
||||||
}
|
}
|
||||||
if (isExcluded(iFace)) continue;
|
if (isExcluded(iFace)) continue;
|
||||||
logger.debug("Searching Interface {}", iFace);
|
logger.debug("Searching Interface {}", iFace);
|
||||||
final Collection<IMethod> ifMethods = iFace.getDeclaredMethods();
|
final Collection<? extends IMethod> ifMethods = iFace.getDeclaredMethods();
|
||||||
for (final IMethod ifMethod : ifMethods) {
|
for (final IMethod ifMethod : ifMethods) {
|
||||||
final IMethod method = appClass.getMethod(ifMethod.getSelector());
|
final IMethod method = appClass.getMethod(ifMethod.getSelector());
|
||||||
if (method != null && method.getDeclaringClass().getClassLoader().getReference().equals(ClassLoaderReference.Application)) {
|
if (method != null && method.getDeclaringClass().getClassLoader().getReference().equals(ClassLoaderReference.Application)) {
|
||||||
|
|
|
@ -85,7 +85,7 @@ public class MethodNamePattern {
|
||||||
Collection<IMethod> matching = new LinkedList<>();
|
Collection<IMethod> matching = new LinkedList<>();
|
||||||
Atom atom = Atom.findOrCreateUnicodeAtom(memberName);
|
Atom atom = Atom.findOrCreateUnicodeAtom(memberName);
|
||||||
Descriptor desc = descriptor == null ? null : Descriptor.findOrCreateUTF8(descriptor);
|
Descriptor desc = descriptor == null ? null : Descriptor.findOrCreateUTF8(descriptor);
|
||||||
Collection<IMethod> allMethods = c.getAllMethods();
|
Collection<? extends IMethod> allMethods = c.getAllMethods();
|
||||||
for(IMethod m: allMethods) {
|
for(IMethod m: allMethods) {
|
||||||
if(m.getName().equals(atom) && (desc == null || m.getDescriptor().equals(desc))) {
|
if(m.getName().equals(atom) && (desc == null || m.getDescriptor().equals(desc))) {
|
||||||
matching.add(m);
|
matching.add(m);
|
||||||
|
|
Loading…
Reference in New Issue