more flexible eclipse project paths and engines for javascript to

support adding different model JS files as prologues.
This commit is contained in:
Julian Dolby 2013-08-07 15:19:27 -04:00
parent 1dd180cf93
commit 24aeda3ef8
7 changed files with 97 additions and 64 deletions

View File

@ -47,13 +47,15 @@ public class JavaEclipseProjectPath extends EclipseProjectPath<IClasspathEntry,
}
}
protected JavaEclipseProjectPath(IProject project, com.ibm.wala.ide.util.EclipseProjectPath.AnalysisScopeType scopeType)
protected JavaEclipseProjectPath(com.ibm.wala.ide.util.EclipseProjectPath.AnalysisScopeType scopeType)
throws IOException, CoreException {
super(project, scopeType);
super(scopeType);
}
public static JavaEclipseProjectPath make(IJavaProject p, AnalysisScopeType scopeType) throws IOException, CoreException {
return new JavaEclipseProjectPath(p.getProject(), scopeType);
JavaEclipseProjectPath path = new JavaEclipseProjectPath(scopeType);
path.create(p.getProject());
return path;
}
@Override
@ -78,7 +80,8 @@ public class JavaEclipseProjectPath extends EclipseProjectPath<IClasspathEntry,
entry = JavaCore.getResolvedClasspathEntry(entry);
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_SOURCE: {
resolveSourcePathEntry(includeSource? JavaSourceLoader.SOURCE: Loader.APPLICATION, includeSource, cpeFromMainProject, entry.getPath(), entry.getOutputLocation(), "java");
resolveSourcePathEntry(includeSource? JavaSourceLoader.SOURCE: Loader.APPLICATION, includeSource, cpeFromMainProject, entry.getPath(), entry.getOutputLocation(), entry.getExclusionPatterns()
, "java");
break;
}
case IClasspathEntry.CPE_LIBRARY: {

View File

@ -20,11 +20,13 @@ import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import com.ibm.wala.cast.ipa.callgraph.CAstAnalysisScope;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.callgraph.fieldbased.FieldBasedCallGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.OptimisticCallgraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.PessimisticCallGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FilteredFlowGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraph;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraphBuilder;
import com.ibm.wala.cast.js.client.impl.ZeroCFABuilderFactory;
import com.ibm.wala.cast.js.html.IncludedPosition;
import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
@ -32,6 +34,7 @@ import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ide.client.EclipseProjectSourceAnalysisEngine;
@ -85,7 +88,7 @@ public class EclipseJavaScriptAnalysisEngine extends EclipseProjectSourceAnalysi
@Override
protected JavaScriptEclipseProjectPath createProjectPath(IJavaScriptProject project) throws IOException, CoreException {
return JavaScriptEclipseProjectPath.make(project);
return JavaScriptEclipseProjectPath.make(project, Collections.EMPTY_SET);
}
@Override
@ -116,7 +119,14 @@ public class EclipseJavaScriptAnalysisEngine extends EclipseProjectSourceAnalysi
}
private String getScriptName(AstMethod m) {
String fileName = m.getSourcePosition().getURL().getFile();
// we want the original including file, since that will be the "script"
Position p = m.getSourcePosition();
while (p instanceof IncludedPosition) {
p = ((IncludedPosition)p).getIncludePosition();
}
String fileName = p.getURL().getFile();
return fileName.substring(fileName.lastIndexOf('/') + 1);
}
@ -127,14 +137,14 @@ public class EclipseJavaScriptAnalysisEngine extends EclipseProjectSourceAnalysi
scripts.add(scriptName);
}
FieldBasedCallGraphBuilder builder = new PessimisticCallGraphBuilder(getClassHierarchy(), getDefaultOptions(roots), makeDefaultCache()) {
FieldBasedCallGraphBuilder builder = new OptimisticCallgraphBuilder(getClassHierarchy(), getDefaultOptions(roots), makeDefaultCache()) {
@Override
protected FlowGraph flowGraphFactory() {
FlowGraphBuilder b = new FilteredFlowGraphBuilder(cha, cache, new Function<IMethod, Boolean>() {
@Override
public Boolean apply(IMethod object) {
if (object instanceof AstMethod) {
return scripts.contains(getScriptName((AstMethod)object));
return scripts.contains(getScriptName((AstMethod)object));
} else {
return true;
}

View File

@ -1,13 +1,16 @@
package com.ibm.wala.cast.js.client;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import com.ibm.wala.cast.ipa.callgraph.CAstAnalysisScope;
import com.ibm.wala.cast.js.JavaScriptPlugin;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
@ -21,11 +24,17 @@ import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
public class EclipseWebAnalysisEngine extends EclipseJavaScriptAnalysisEngine {
public EclipseWebAnalysisEngine(IJavaScriptProject project) throws IOException, CoreException {
private final Set<Pair<String, Plugin>> models = HashSetFactory.make();
public EclipseWebAnalysisEngine(IJavaScriptProject project, Collection<Pair<String, Plugin>> models) throws IOException, CoreException {
super(project);
// core DOM model
this.models.add(Pair.make("preamble.js", (Plugin)JavaScriptPlugin.getDefault()));
this.models.addAll(models);
}
@Override
@ -40,15 +49,19 @@ public class EclipseWebAnalysisEngine extends EclipseJavaScriptAnalysisEngine {
@Override
protected JavaScriptEclipseProjectPath createProjectPath(IJavaScriptProject project) throws IOException, CoreException {
return new EclipseWebProjectPath(project);
return EclipseWebProjectPath.make(project, models);
}
@Override
public CallGraph getFieldBasedCallGraph(String scriptName) throws CancelException {
Set<Entrypoint> eps= HashSetFactory.make();
eps.add(JSCallGraphUtil.makeScriptRoots(getClassHierarchy()).make(scriptName));
eps.add(JSCallGraphUtil.makeScriptRoots(getClassHierarchy()).make("Lpreamble.js"));
eps.add(JSCallGraphUtil.makeScriptRoots(getClassHierarchy()).make("Lprologue.js"));
for(Pair<String,Plugin> model : models) {
eps.add(JSCallGraphUtil.makeScriptRoots(getClassHierarchy()).make("L" + model.fst));
}
return getFieldBasedCallGraph(eps);
}

View File

@ -1,6 +1,5 @@
package com.ibm.wala.ide.util;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
@ -10,32 +9,34 @@ import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
import com.ibm.wala.cast.js.JavaScriptPlugin;
import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.classLoader.FileModule;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.ide.classloader.EclipseSourceDirectoryTreeModule;
import com.ibm.wala.util.collections.MapUtil;
import com.ibm.wala.util.io.FileProvider;
import com.ibm.wala.util.collections.Pair;
public class EclipseWebProjectPath extends JavaScriptEclipseProjectPath {
private boolean addedPreamble;
public EclipseWebProjectPath(IJavaScriptProject p) throws IOException, CoreException {
super(p);
public EclipseWebProjectPath(Set<Pair<String, Plugin>> models) throws IOException, CoreException {
super(models);
}
public static EclipseWebProjectPath make(IJavaScriptProject p, Set<Pair<String, Plugin>> models) throws IOException, CoreException {
EclipseWebProjectPath path = new EclipseWebProjectPath(models);
path.create(p.getProject());
return path;
}
@Override
protected void resolveSourcePathEntry(com.ibm.wala.ide.util.EclipseProjectPath.ILoader loader, boolean includeSource, boolean cpeFromMainProject, IPath p, IPath o, String fileExtension) {
protected void resolveSourcePathEntry(com.ibm.wala.ide.util.EclipseProjectPath.ILoader loader, boolean includeSource, boolean cpeFromMainProject, IPath p, IPath o, IPath[] excludePaths, String fileExtension) {
List<Module> s = MapUtil.findOrCreateList(modules, loader);
Iterator<FileModule> htmlPages = new EclipseSourceDirectoryTreeModule(p, "html").getEntries();
Iterator<FileModule> htmlPages = new EclipseSourceDirectoryTreeModule(p, excludePaths, "html").getEntries();
while (htmlPages.hasNext()) {
FileModule htmlPage = htmlPages.next();
Set<MappedSourceModule> scripts;
@ -43,11 +44,6 @@ public class EclipseWebProjectPath extends JavaScriptEclipseProjectPath {
try {
scripts = WebUtil.extractScriptFromHTML(new URL(urlString)).fst;
s.addAll(scripts);
if (! addedPreamble) {
File preamble = getProlgueFile("preamble.js");
s.add(new SourceFileModule(preamble, "preamble.js", null));
addedPreamble = true;
}
} catch (MalformedURLException e1) {
assert false : "internal error constructing URL " + urlString;
} catch (Error e1) {

View File

@ -13,37 +13,27 @@ package com.ibm.wala.ide.util;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Collection;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.wst.jsdt.core.IIncludePathEntry;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import com.ibm.wala.cast.js.JavaScriptPlugin;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.collections.MapUtil;
import com.ibm.wala.util.io.FileProvider;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
public class JavaScriptEclipseProjectPath extends EclipseProjectPath<IIncludePathEntry, IJavaScriptProject> {
protected File getProlgueFile(String file) {
try {
FileProvider fileProvider = new EclipseFileProvider(JavaScriptPlugin.getDefault());
JavaScriptLoader.addBootstrapFile(file);
return fileProvider.getFile("dat/" + file, getClass().getClassLoader());
} catch (IOException e) {
assert false : "cannot find " + file;
return null;
}
}
public enum JSLoader implements ILoader {
JAVASCRIPT(JavaScriptTypes.jsLoader);
@ -59,20 +49,36 @@ public class JavaScriptEclipseProjectPath extends EclipseProjectPath<IIncludePat
}
}
protected JavaScriptEclipseProjectPath(IJavaScriptProject p) throws IOException,
private final Set<Pair<String, Plugin>> models = HashSetFactory.make();
protected JavaScriptEclipseProjectPath(Set<Pair<String, Plugin>> models) throws IOException,
CoreException {
super(p.getProject(), AnalysisScopeType.SOURCE_FOR_PROJ_AND_LINKED_PROJS);
List<Module> s = MapUtil.findOrCreateList(modules, JSLoader.JAVASCRIPT);
File preamble = getProlgueFile("prologue.js");
s.add(new SourceFileModule(preamble, "prologue.js", null));
super(AnalysisScopeType.SOURCE_FOR_PROJ_AND_LINKED_PROJS);
this.models.addAll(models);
this.models.add(Pair.make("prologue.js", (Plugin)JavaScriptPlugin.getDefault()));
}
public static JavaScriptEclipseProjectPath make(IJavaScriptProject p) throws IOException, CoreException {
return new JavaScriptEclipseProjectPath(p);
public static JavaScriptEclipseProjectPath make(IJavaScriptProject p, Set<Pair<String, Plugin>> models) throws IOException, CoreException {
JavaScriptEclipseProjectPath path = new JavaScriptEclipseProjectPath(models);
path.create(p.getProject());
return path;
}
@Override
public EclipseProjectPath create(IProject project) throws CoreException, IOException {
EclipseProjectPath path = super.create(project);
Collection<Module> s = modules.get(JSLoader.JAVASCRIPT);
for(Pair<String,Plugin> model : models) {
File modelFile = JsdtUtil.getProlgueFile(model.fst, model.snd);
s.add(new SourceFileModule(modelFile, model.fst, null));
}
return path;
}
@Override
protected IJavaScriptProject makeProject(IProject p) {
try {
if (p.hasNature(JavaScriptCore.NATURE_ID)) {
@ -98,7 +104,7 @@ public class JavaScriptEclipseProjectPath extends EclipseProjectPath<IIncludePat
IIncludePathEntry e = JavaScriptCore.getResolvedIncludepathEntry(entry);
switch (e.getEntryKind()) {
case IIncludePathEntry.CPE_SOURCE:
resolveSourcePathEntry(JSLoader.JAVASCRIPT, true, cpeFromMainProject, e.getPath(), null, "js");
resolveSourcePathEntry(JSLoader.JAVASCRIPT, true, cpeFromMainProject, e.getPath(), null, e.getExclusionPatterns(), "js");
}
}

View File

@ -32,7 +32,7 @@ abstract public class EclipseProjectAnalysisEngine<P> extends AbstractAnalysisEn
protected final IPath workspaceRootPath;
protected final EclipseProjectPath<?,P> ePath;
protected EclipseProjectPath<?,P> ePath;
public EclipseProjectAnalysisEngine(P project) throws IOException, CoreException {
super();
@ -40,7 +40,6 @@ abstract public class EclipseProjectAnalysisEngine<P> extends AbstractAnalysisEn
this.workspaceRootPath = ResourcesPlugin.getWorkspace().getRoot().getLocation();
assert project != null;
assert workspaceRootPath != null;
this.ePath = createProjectPath(project);
}
abstract protected EclipseProjectPath<?,P> createProjectPath(P project) throws IOException, CoreException;
@ -52,9 +51,14 @@ abstract public class EclipseProjectAnalysisEngine<P> extends AbstractAnalysisEn
@Override
public void buildAnalysisScope() throws IOException {
super.scope = ePath.toAnalysisScope(makeAnalysisScope());
if (getExclusionsFile() != null) {
scope.setExclusions(FileOfClasses.createFileOfClasses(new File(getExclusionsFile())));
try {
ePath = createProjectPath(project);
super.scope = ePath.toAnalysisScope(makeAnalysisScope());
if (getExclusionsFile() != null) {
scope.setExclusions(FileOfClasses.createFileOfClasses(new File(getExclusionsFile())));
}
} catch (CoreException e) {
assert false : e.getMessage();
}
}

View File

@ -123,20 +123,21 @@ public abstract class EclipseProjectPath<E, P> {
MapUtil.findOrCreateList(modules, loader);
}
}
protected EclipseProjectPath(IProject project, AnalysisScopeType scopeType) throws IOException, CoreException {
this(scopeType);
public EclipseProjectPath create(IProject project) throws CoreException, IOException {
assert project != null;
if (project == null) {
throw new IllegalArgumentException("null project");
}
boolean includeSource = (scopeType != AnalysisScopeType.NO_SOURCE);
resolveProjectClasspathEntries(makeProject(project), includeSource);
if (isPluginProject(project)) {
resolvePluginClassPath(project, includeSource);
}
return this;
}
@ -158,10 +159,10 @@ public abstract class EclipseProjectPath<E, P> {
}
}
protected void resolveSourcePathEntry(ILoader loader, boolean includeSource, boolean cpeFromMainProject, IPath p, IPath o, String fileExtension) {
protected void resolveSourcePathEntry(ILoader loader, boolean includeSource, boolean cpeFromMainProject, IPath p, IPath o, IPath[] excludePaths, String fileExtension) {
if (includeSource) {
List<Module> s = MapUtil.findOrCreateList(modules, loader);
s.add(new EclipseSourceDirectoryTreeModule(p, fileExtension));
s.add(new EclipseSourceDirectoryTreeModule(p, excludePaths, fileExtension));
} else if (o != null) {
File output = makeAbsolute(o).toFile();
List<Module> s = MapUtil.findOrCreateList(modules, cpeFromMainProject ? Loader.APPLICATION : loader);
@ -332,7 +333,7 @@ public abstract class EclipseProjectPath<E, P> {
return toAnalysisScope(getClass().getClassLoader(), null);
}
public Collection<Module> getModules(Loader loader, boolean binary) {
public Collection<Module> getModules(ILoader loader, boolean binary) {
return Collections.unmodifiableCollection(modules.get(loader));
}