provide more options for choosing classfiles vs source files. Thanks to Dan Marino.

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3852 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
dolby-oss 2010-07-19 14:05:19 +00:00
parent 3fcb6de3ba
commit 086c22dc13
5 changed files with 88 additions and 77 deletions

View File

@ -1677,15 +1677,30 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
*/ */
private ITypeBinding findClosestEnclosingClassSubclassOf(ITypeBinding typeOfThis, ITypeBinding owningType, boolean isPrivate) { private ITypeBinding findClosestEnclosingClassSubclassOf(ITypeBinding typeOfThis, ITypeBinding owningType, boolean isPrivate) {
// GENERICS // GENERICS
if (owningType.isParameterizedType()) // if (owningType.isParameterizedType())
owningType = owningType.getTypeDeclaration(); // owningType = owningType.getTypeDeclaration();
if (typeOfThis.isParameterizedType()) // if (typeOfThis.isParameterizedType())
typeOfThis = typeOfThis.getTypeDeclaration(); // typeOfThis = typeOfThis.getTypeDeclaration();
// typeOfThis.getTypeDeclaration() // // typeOfThis.getTypeDeclaration()
owningType = owningType.getErasure();
ITypeBinding current = typeOfThis; ITypeBinding current = typeOfThis;
while (current != null) { while (current != null) {
boolean isInSubtype = current.isSubTypeCompatible(owningType); current = current.getErasure();
// Walk the hierarchy rather than using isSubTypeCompatible to handle
// generics -- we need to perform erasure of super types
boolean isInSubtype = false;//current.isSubTypeCompatible(owningType);
ITypeBinding supertp = current;
while (supertp != null){
supertp = supertp.getErasure();
// Use isSubTypeCompatible even though we are manually walking type hierarchy --
// that way interfaces are handled without us having to do it manually.
if (supertp.isSubTypeCompatible(owningType)){
isInSubtype = true;
break;
}
supertp = supertp.getSuperclass();
}
// how could it be in the subtype and private? this only happens the supertype is also an // how could it be in the subtype and private? this only happens the supertype is also an
// enclosing type. in that case the variable refers to the field in the enclosing instance. // enclosing type. in that case the variable refers to the field in the enclosing instance.

View File

@ -132,11 +132,11 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
} }
final ASTParser parser = ASTParser.newParser(AST.JLS3); final ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setResolveBindings(true);
for (IProject proj : projectsFiles.keySet()) { for (IProject proj : projectsFiles.keySet()) {
parser.setProject(JavaCore.create(proj)); parser.setProject(JavaCore.create(proj));
ArrayList<ICompilationUnit> files = projectsFiles.get(proj); parser.setResolveBindings(true);
ArrayList<ICompilationUnit> files = projectsFiles.get(proj);
parser.createASTs(files.toArray(new ICompilationUnit[files.size()]), new String[0], new ASTRequestor() { parser.createASTs(files.toArray(new ICompilationUnit[files.size()]), new String[0], new ASTRequestor() {
public void acceptAST(ICompilationUnit source, CompilationUnit ast) { public void acceptAST(ICompilationUnit source, CompilationUnit ast) {

View File

@ -103,21 +103,29 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
} }
public IClass getSuperclass() { public IClass getSuperclass() {
boolean excludedSupertype=false;
for (Iterator iter = superTypeNames.iterator(); iter.hasNext();) { for (Iterator iter = superTypeNames.iterator(); iter.hasNext();) {
TypeName name = (TypeName) iter.next(); TypeName name = (TypeName) iter.next();
IClass domoType = lookupClass(name); IClass domoType = lookupClass(name);
if (domoType != null && !domoType.isInterface()) { if (domoType != null && !domoType.isInterface()) {
return domoType; return domoType;
} }
if (domoType == null && getClassHierarchy().getScope().getExclusions().contains(name.toString().substring(1))){
excludedSupertype = true;
}
} }
// The following test allows the root class to reside in source; without // The following test allows the root class to reside in source; without
// it, the assertion requires all classes represented by a JavaClass to // it, the assertion requires all classes represented by a JavaClass to
// have a superclass. // have a superclass.
if (!getName().equals(JavaSourceLoaderImpl.this.getLanguage().getRootType().getName())) { if (!getName().equals(JavaSourceLoaderImpl.this.getLanguage().getRootType().getName()) && !excludedSupertype) {
Assertions.UNREACHABLE("Cannot find super class for " + this + " in " + superTypeNames); Assertions.UNREACHABLE("Cannot find super class for " + this + " in " + superTypeNames);
} }
if (excludedSupertype){
System.err.println("Not tracking calls through excluded superclass of " + getName() + " extends " + superTypeNames);
}
return null; return null;
} }
@ -127,15 +135,11 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
TypeName name = (TypeName) iter.next(); TypeName name = (TypeName) iter.next();
IClass domoType = lookupClass(name); IClass domoType = lookupClass(name);
if (domoType != null && domoType.isInterface()) { if (domoType != null && domoType.isInterface()) {
result.add(domoType); result.add(domoType);
}
if (domoType == null && !getClassHierarchy().getScope().getExclusions().contains(name.toString().substring(1))){
assert false : "Failed to find all non-excluded interfaces.";
} }
}
// The following computation allows the root class to reside in source
int numSuperClasses = (getName().equals(JavaSourceLoaderImpl.this.getLanguage().getRootType().getName())) ? 0 : 1; // 0 if the root class
if (result.size() != (superTypeNames.size() - numSuperClasses)) {
assert result.size() == superTypeNames.size() - numSuperClasses : "found " + result + " interfaces for " + superTypeNames
+ " for " + this;
} }
return result; return result;

View File

@ -65,17 +65,17 @@ public abstract class AbstractJavaAnalysisAction implements IObjectActionDelegat
* Compute an analysis scope for the current selection * Compute an analysis scope for the current selection
*/ */
public static AnalysisScope computeScope(IStructuredSelection selection) throws IOException { public static AnalysisScope computeScope(IStructuredSelection selection) throws IOException {
return computeScope(selection, false, true); return computeScope(selection, EclipseProjectPath.AnalysisScopeType.NO_SOURCE);
} }
/** /**
* Compute an analysis scope for the current selection * Compute an analysis scope for the current selection
* *
* @param includeSource should files from the source folders in Eclipse projects be included * @param scopeType should analysis use the source files in the Eclipse projects rather than the class files.
* @param includeClassFiles should class files built by Eclipse, in the project output folders, be include?
*/ */
public static AnalysisScope computeScope(final IStructuredSelection selection, final boolean includeSource, public static AnalysisScope computeScope(final IStructuredSelection selection,
final boolean includeClassFiles) throws IOException { final EclipseProjectPath.AnalysisScopeType scopeType) throws IOException
{
if (selection == null) { if (selection == null) {
throw new IllegalArgumentException("null selection"); throw new IllegalArgumentException("null selection");
} }
@ -91,7 +91,7 @@ public abstract class AbstractJavaAnalysisAction implements IObjectActionDelegat
IJavaElement e = (IJavaElement) object; IJavaElement e = (IJavaElement) object;
IJavaProject jp = e.getJavaProject(); IJavaProject jp = e.getJavaProject();
try { try {
projectPaths.add(EclipseProjectPath.make(jp, includeSource, includeClassFiles)); projectPaths.add(EclipseProjectPath.make(jp, scopeType));
} catch (CoreException e1) { } catch (CoreException e1) {
e1.printStackTrace(); e1.printStackTrace();
// skip and continue // skip and continue

View File

@ -59,9 +59,10 @@ import com.ibm.wala.util.debug.Assertions;
* We set up classloaders as follows: * We set up classloaders as follows:
* <ul> * <ul>
* <li>The project being analyzed is in the Application Loader * <li>The project being analyzed is in the Application Loader
* <li>Projects on which the main project depends are in the Extension loader * <li>Frameworks, application libraries, and linked projects on which the main project depends are in the Extension loader
* <li>System libraries are in the primordial loader. * <li>System libraries are in the primordial loader.
* <li>Source modules go in a special Source loader. * <li>All source modules go in a special Source loader. This includes source from linked projects if
* SOURCE_FOR_PROJ_AND_LINKED_PROJS is specified.
* </ul> * </ul>
*/ */
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
@ -80,6 +81,10 @@ public class EclipseProjectPath {
this.ref = ref; this.ref = ref;
} }
}; };
public enum AnalysisScopeType {
NO_SOURCE, SOURCE_FOR_PROJ, SOURCE_FOR_PROJ_AND_LINKED_PROJS
}
/** /**
* The project whose path this object represents * The project whose path this object represents
@ -101,27 +106,23 @@ public class EclipseProjectPath {
private final Collection<IClasspathEntry> alreadyResolved = HashSetFactory.make(); private final Collection<IClasspathEntry> alreadyResolved = HashSetFactory.make();
/** /**
* Should the analysis scope include source files * Which source files, if any, should be included in the analysis scope.
*/ */
private final boolean includeSource; private final AnalysisScopeType scopeType;
/** protected EclipseProjectPath(IJavaProject project, AnalysisScopeType scopeType) throws IOException,
* Should the analysis scope include class files generated by the Eclipse build process?
*/
private final boolean includeClassFiles;
protected EclipseProjectPath(IJavaProject project, boolean includeSource, boolean includeClassFiles) throws IOException,
CoreException { CoreException {
if (project == null) { if (project == null) {
throw new IllegalArgumentException("null project"); throw new IllegalArgumentException("null project");
} }
this.includeSource = includeSource; this.scopeType = scopeType;
this.includeClassFiles = includeClassFiles;
this.project = project; this.project = project;
assert project != null; assert project != null;
for (Loader loader : Loader.values()) { for (Loader loader : Loader.values()) {
MapUtil.findOrCreateList(modules, loader); MapUtil.findOrCreateList(modules, loader);
} }
boolean includeSource = (scopeType != AnalysisScopeType.NO_SOURCE);
resolveProjectClasspathEntries(includeSource); resolveProjectClasspathEntries(includeSource);
if (isPluginProject(project)) { if (isPluginProject(project)) {
resolvePluginClassPath(project.getProject(), includeSource); resolvePluginClassPath(project.getProject(), includeSource);
@ -129,19 +130,20 @@ public class EclipseProjectPath {
} }
public static EclipseProjectPath make(IJavaProject project) throws IOException, CoreException { public static EclipseProjectPath make(IJavaProject project) throws IOException, CoreException {
return make(project, false, true); return make(project, AnalysisScopeType.NO_SOURCE);
} }
public static EclipseProjectPath make(IJavaProject project, boolean includeSource, boolean includeClassFiles) throws IOException, public static EclipseProjectPath make(IJavaProject project, AnalysisScopeType scopeType) throws IOException,
CoreException { CoreException {
return new EclipseProjectPath(project, includeSource, includeClassFiles); return new EclipseProjectPath(project, scopeType);
} }
/** /**
* Figure out what a classpath entry means and add it to the appropriate set of modules * Figure out what a classpath entry means and add it to the appropriate set of modules
*/ */
private void resolveClasspathEntry(IClasspathEntry entry, Loader loader, boolean includeSource) throws JavaModelException, private void resolveClasspathEntry(IClasspathEntry entry, Loader loader, boolean includeSource, boolean cpeFromMainProject)
IOException { throws JavaModelException, IOException
{
IClasspathEntry e = JavaCore.getResolvedClasspathEntry(entry); IClasspathEntry e = JavaCore.getResolvedClasspathEntry(entry);
if (alreadyResolved.contains(e)) { if (alreadyResolved.contains(e)) {
return; return;
@ -153,7 +155,7 @@ public class EclipseProjectPath {
IClasspathContainer cont = JavaCore.getClasspathContainer(entry.getPath(), project); IClasspathContainer cont = JavaCore.getClasspathContainer(entry.getPath(), project);
IClasspathEntry[] entries = cont.getClasspathEntries(); IClasspathEntry[] entries = cont.getClasspathEntries();
resolveClasspathEntries(entries, cont.getKind() == IClasspathContainer.K_APPLICATION ? loader : Loader.PRIMORDIAL, resolveClasspathEntries(entries, cont.getKind() == IClasspathContainer.K_APPLICATION ? loader : Loader.PRIMORDIAL,
includeSource); includeSource, false);
} else if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { } else if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
File file = makeAbsolute(e.getPath()).toFile(); File file = makeAbsolute(e.getPath()).toFile();
JarFile j; JarFile j;
@ -171,14 +173,12 @@ public class EclipseProjectPath {
s.add(file.isDirectory() ? (Module) new BinaryDirectoryTreeModule(file) : (Module) new JarFileModule(j)); s.add(file.isDirectory() ? (Module) new BinaryDirectoryTreeModule(file) : (Module) new JarFileModule(j));
} }
} else if (e.getEntryKind() == IClasspathEntry.CPE_SOURCE) { } else if (e.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
List<Module> s = MapUtil.findOrCreateList(modules, loader);
if (includeSource) { if (includeSource) {
List<Module> s = MapUtil.findOrCreateList(modules, Loader.APPLICATION);
s.add(new EclipseSourceDirectoryTreeModule(e.getPath())); s.add(new EclipseSourceDirectoryTreeModule(e.getPath()));
} }else if (e.getOutputLocation() != null) {
if (e.getOutputLocation() != null) {
File output = makeAbsolute(e.getOutputLocation()).toFile(); File output = makeAbsolute(e.getOutputLocation()).toFile();
s = MapUtil.findOrCreateList(modules, loader); List<Module> s = MapUtil.findOrCreateList(modules, cpeFromMainProject ? Loader.APPLICATION : loader);
s.add(new BinaryDirectoryTreeModule(output)); s.add(new BinaryDirectoryTreeModule(output));
} }
} else if (e.getEntryKind() == IClasspathEntry.CPE_PROJECT) { } else if (e.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
@ -192,10 +192,13 @@ public class EclipseProjectPath {
if (isPluginProject(javaProject)) { if (isPluginProject(javaProject)) {
resolvePluginClassPath(javaProject.getProject(), includeSource); resolvePluginClassPath(javaProject.getProject(), includeSource);
} }
resolveClasspathEntries(javaProject.getRawClasspath(), loader, includeSource); resolveClasspathEntries(javaProject.getRawClasspath(), loader,
scopeType==AnalysisScopeType.SOURCE_FOR_PROJ_AND_LINKED_PROJS ? includeSource : false, false);
File output = makeAbsolute(javaProject.getOutputLocation()).toFile(); File output = makeAbsolute(javaProject.getOutputLocation()).toFile();
List<Module> s = MapUtil.findOrCreateList(modules, loader); List<Module> s = MapUtil.findOrCreateList(modules, loader);
s.add(new BinaryDirectoryTreeModule(output)); if (!includeSource){
s.add(new BinaryDirectoryTreeModule(output));
}
} }
} catch (CoreException e1) { } catch (CoreException e1) {
e1.printStackTrace(); e1.printStackTrace();
@ -262,7 +265,7 @@ public class EclipseProjectPath {
IClasspathEntry e = (IClasspathEntry) o; IClasspathEntry e = (IClasspathEntry) o;
entries[i++] = e; entries[i++] = e;
} }
resolveClasspathEntries(entries, loader, includeSource); resolveClasspathEntries(entries, loader, includeSource, false);
// recurse to handle dependencies. put these in the Extension loader // recurse to handle dependencies. put these in the Extension loader
for (BundleDescription b : PDEStateHelper.getImportedBundles(bd)) { for (BundleDescription b : PDEStateHelper.getImportedBundles(bd)) {
@ -305,10 +308,10 @@ public class EclipseProjectPath {
return true; return true;
} }
protected void resolveClasspathEntries(IClasspathEntry[] entries, Loader loader, boolean includeSource) protected void resolveClasspathEntries(IClasspathEntry[] entries, Loader loader, boolean includeSource, boolean entriesFromTopLevelProject)
throws JavaModelException, IOException { throws JavaModelException, IOException {
for (int i = 0; i < entries.length; i++) { for (int i = 0; i < entries.length; i++) {
resolveClasspathEntry(entries[i], loader, includeSource); resolveClasspathEntry(entries[i], loader, includeSource, entriesFromTopLevelProject);
} }
} }
@ -326,7 +329,18 @@ public class EclipseProjectPath {
} }
private void resolveProjectClasspathEntries(boolean includeSource) throws JavaModelException, IOException { private void resolveProjectClasspathEntries(boolean includeSource) throws JavaModelException, IOException {
resolveClasspathEntries(project.getRawClasspath(), Loader.EXTENSION, includeSource);
resolveClasspathEntries(project.getRawClasspath(), Loader.EXTENSION, includeSource, true);
if (!includeSource){
File dir = makeAbsolute(project.getOutputLocation()).toFile();
if (!dir.isDirectory()) {
System.err.println("PANIC: project output location is not a directory: " + dir);
} else {
MapUtil.findOrCreateList(modules, Loader.APPLICATION).add(new BinaryDirectoryTreeModule(dir));
}
}
} }
/** /**
@ -341,24 +355,6 @@ public class EclipseProjectPath {
} }
public AnalysisScope toAnalysisScope(AnalysisScope scope) { public AnalysisScope toAnalysisScope(AnalysisScope scope) {
try {
List<Module> l = MapUtil.findOrCreateList(modules, Loader.APPLICATION);
if (includeClassFiles) {
File dir = makeAbsolute(project.getOutputLocation()).toFile();
if (!dir.isDirectory()) {
System.err.println("PANIC: project output location is not a directory: " + dir);
} else {
l.add(new BinaryDirectoryTreeModule(dir));
}
}
if (includeSource) {
for (IClasspathEntry e : project.getRawClasspath()) {
if (e.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
l.add(new EclipseSourceDirectoryTreeModule(e.getPath()));
}
}
}
for (Loader loader : Loader.values()) { for (Loader loader : Loader.values()) {
for (Module m : modules.get(loader)) { for (Module m : modules.get(loader)) {
@ -366,11 +362,7 @@ public class EclipseProjectPath {
} }
} }
return scope; return scope;
} catch (JavaModelException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
return null;
}
} }
public AnalysisScope toAnalysisScope(final File exclusionsFile) throws IOException { public AnalysisScope toAnalysisScope(final File exclusionsFile) throws IOException {