From 10dfaf51b37436b84b9a646350fac210b2e092b8 Mon Sep 17 00:00:00 2001 From: rmfuhrer Date: Thu, 6 Dec 2007 14:53:29 +0000 Subject: [PATCH] Now maintains a set of "compatible" Languages that contribute types to the given ClassHierarchy, which has a unique root type. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2114 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/ipa/cha/ClassHierarchy.java | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java index 0d971a45a..8398a4756 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java @@ -64,12 +64,19 @@ public class ClassHierarchy implements IClassHierarchy { private static final boolean DEBUG = false; /** - * Language of classes represented in this hierarchy + * Languages that contribute classes to the set represented in this hierarchy. + * The languages may for example be related by inheritance (e.g. X10 derives + * from Java, and shares a common type hierarchy rooted at java.lang.Object). */ - private final Language language; + private final Set languages = new HashSet(); final private HashMap map = HashMapFactory.make(); + /** + * TypeReference for the root type + */ + private TypeReference rootTypeRef; + /** * root node of the class hierarchy */ @@ -140,13 +147,23 @@ public class ClassHierarchy implements IClassHierarchy { return result; } - protected ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, IProgressMonitor monitor) - throws ClassHierarchyException { - this(scope, factory, Language.JAVA, monitor); - } +// protected ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, IProgressMonitor monitor) +// throws ClassHierarchyException { +// this(scope, factory, Language.JAVA, monitor); +// } private ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, Language language, IProgressMonitor progressMonitor) throws ClassHierarchyException, IllegalArgumentException { + this(scope, factory, Collections.singleton(language), progressMonitor); + } + + private ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, IProgressMonitor progressMonitor) + throws ClassHierarchyException, IllegalArgumentException { + this(scope, factory, scope.getLanguages(), progressMonitor); + } + + private ClassHierarchy(AnalysisScope scope, ClassLoaderFactory factory, Set languages, IProgressMonitor progressMonitor) + throws ClassHierarchyException, IllegalArgumentException { // now is a good time to clear the warnings globally. // TODO: think of a better way to guard against warning leaks. Warnings.clear(); @@ -154,16 +171,30 @@ public class ClassHierarchy implements IClassHierarchy { if (factory == null) { throw new IllegalArgumentException(); } - if (language == null) { - throw new IllegalArgumentException(); + if (scope.getLanguages().size() == 0) { + throw new IllegalArgumentException("AnalysisScope must contain at least 1 language"); } this.scope = scope; this.factory = factory; - this.language = language; + Set langNames= new HashSet(); + for(Language lang: languages) { + this.languages.add(lang); + this.languages.addAll(lang.getDerivedLanguages()); + langNames.add(lang.getName()); + } + for(Language lang: this.languages) { + if (lang.getRootType() != null) { + if (this.rootTypeRef != null) { + throw new IllegalArgumentException("AnalysisScope must have only 1 root type"); + } else { + this.rootTypeRef= lang.getRootType(); + } + } + } try { int numLoaders = 0; for (ClassLoaderReference ref : scope.getLoaders()) { - if (ref.getLanguage().equals(language.getName())) { + if (langNames.contains(ref.getLanguage())) { numLoaders++; } } @@ -181,7 +212,7 @@ public class ClassHierarchy implements IClassHierarchy { } } - if (ref.getLanguage().equals(language.getName())) { + if (langNames.contains(ref.getLanguage())) { IClassLoader icl = factory.getLoader(ref, this, scope); loaders[idx++] = icl; addAllClasses(icl, progressMonitor); @@ -200,7 +231,7 @@ public class ClassHierarchy implements IClassHierarchy { } if (root == null) { - throw new ClassHierarchyException("failed to load root " + language.getRootType() + " of class hierarchy"); + throw new ClassHierarchyException("failed to load root " + rootTypeRef + " of class hierarchy"); } // perform numbering for subclass tests. @@ -262,7 +293,7 @@ public class ClassHierarchy implements IClassHierarchy { } Node node = findOrCreateNode(klass); - if (klass.getReference().equals(language.getRootType())) { + if (klass.getReference().equals(this.rootTypeRef)) { // there is only one root Assertions._assert(root == null); root = node; @@ -284,7 +315,7 @@ public class ClassHierarchy implements IClassHierarchy { Trace.println("addChild " + node.getJavaClass() + " to " + supernode.getJavaClass()); } supernode.addChild(node); - if (supernode.getJavaClass().getReference().equals(language.getRootType())) { + if (supernode.getJavaClass().getReference().equals(rootTypeRef)) { node = null; } else { node = supernode; @@ -1123,6 +1154,11 @@ public class ClassHierarchy implements IClassHierarchy { return new ClassHierarchy(scope, factory, monitor); } + public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, Set languages) + throws ClassHierarchyException { + return new ClassHierarchy(scope, factory, languages, new NullProgressMonitor()); + } + public static ClassHierarchy make(AnalysisScope scope, ClassLoaderFactory factory, Language language) throws ClassHierarchyException { return new ClassHierarchy(scope, factory, language, new NullProgressMonitor());