From b84657d1a959076cdb60912c6c57f064c24f57da Mon Sep 17 00:00:00 2001 From: Juergen Graf Date: Thu, 26 May 2011 16:43:36 +0200 Subject: [PATCH] add some new classes from wala --- .../client/JDTJavaSourceAnalysisEngine.java | 94 +++++++++++ .../translator/polyglot/ModuleSource.java | 60 +++++++ .../cast/js/test/TestForInLoopHackRhino.java | 14 ++ .../js/test/TestMozillaBugPagesRhino.java | 18 ++ ...tSimplePageCallGraphShapeRhinoJericho.java | 31 ++++ .../wala/cast/js/test/TestForInLoopHack.java | 137 ++++++++++++++++ .../cast/js/test/TestMozillaBugPages.java | 54 ++++++ .../com/ibm/wala/cast/test/Util.java | 40 +++++ .../ibm/wala/classLoader/CompoundModule.java | 154 ++++++++++++++++++ .../ibm/wala/util/functions/VoidFunction.java | 7 + 10 files changed, 609 insertions(+) create mode 100644 com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/client/JDTJavaSourceAnalysisEngine.java create mode 100644 com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/ModuleSource.java create mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHackRhino.java create mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPagesRhino.java create mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoJericho.java create mode 100644 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java create mode 100644 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java create mode 100644 com.ibm.wala.cast.test/harness-src/com/ibm/wala/cast/test/Util.java create mode 100644 com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java create mode 100644 com.ibm.wala.util/src/com/ibm/wala/util/functions/VoidFunction.java diff --git a/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/client/JDTJavaSourceAnalysisEngine.java b/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/client/JDTJavaSourceAnalysisEngine.java new file mode 100644 index 000000000..77bc4b5d0 --- /dev/null +++ b/com.ibm.wala.cast.java.jdt/source/com/ibm/wala/cast/java/client/JDTJavaSourceAnalysisEngine.java @@ -0,0 +1,94 @@ +/* + * 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. + * + * This file is a derivative of code released by the University of + * California under the terms listed below. + * + * WALA JDT Frontend is Copyright (c) 2008 The Regents of the + * University of California (Regents). Provided that this notice and + * the following two paragraphs are included in any distribution of + * Refinement Analysis Tools or its derivative work, Regents agrees + * not to assert any of Regents' copyright rights in Refinement + * Analysis Tools against recipient for recipient's reproduction, + * preparation of derivative works, public display, public + * performance, distribution or sublicensing of Refinement Analysis + * Tools and derivative works, in source code and object code form. + * This agreement not to assert does not confer, by implication, + * estoppel, or otherwise any license or rights in any intellectual + * property of Regents, including, but not limited to, any patents + * of Regents or Regents' employees. + * + * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, + * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, + * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE + * AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY + * WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING + * DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, + * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ +package com.ibm.wala.cast.java.client; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.IJavaProject; + +import com.ibm.wala.cast.java.translator.jdt.JDTClassLoaderFactory; +import com.ibm.wala.classLoader.ClassLoaderFactory; +import com.ibm.wala.ide.classloader.EclipseSourceFileModule; +import com.ibm.wala.ide.util.JdtUtil; +import com.ibm.wala.ipa.callgraph.impl.SetOfClasses; + +public class JDTJavaSourceAnalysisEngine extends JavaSourceAnalysisEngine { + protected final IJavaProject project; + + public JDTJavaSourceAnalysisEngine(IJavaProject project) { + super(); + this.project = project; + } + + public JDTJavaSourceAnalysisEngine(String projectName) { + this(JdtUtil.getNamedProject(projectName)); + } + + protected ClassLoaderFactory getClassLoaderFactory(SetOfClasses exclusions) { + return new JDTClassLoaderFactory(exclusions); + } + + public void addSourceModule(IResource file) { + IProject proj = project.getProject(); + IPath path = file.getProjectRelativePath(); + if (file.getType() == IResource.FILE) { + addSourceModule(EclipseSourceFileModule.createEclipseSourceFileModule(proj.getFile(path))); + } else { + assert file.getType() == IResource.FOLDER; + IFolder dir = proj.getFolder(path); + try { + for(IResource x : dir.members()) { + assert x.getType() == IResource.FILE || x.getType() == IResource.FOLDER; + addSourceModule(x); + } + } catch (CoreException e) { + throw new RuntimeException("trouble with " + file, e); + } + } + } + + public void addSourceModule(String fileName) { + IResource file = project.getProject().findMember(fileName); + assert file != null; + addSourceModule(file); + } + +} diff --git a/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/ModuleSource.java b/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/ModuleSource.java new file mode 100644 index 000000000..993d1f262 --- /dev/null +++ b/com.ibm.wala.cast.java.polyglot/source/com/ibm/wala/cast/java/translator/polyglot/ModuleSource.java @@ -0,0 +1,60 @@ +/****************************************************************************** + * Copyright (c) 2002 - 2006 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 + *****************************************************************************/ +/* + * Created on Oct 6, 2005 + */ +package com.ibm.wala.cast.java.translator.polyglot; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import com.ibm.wala.classLoader.SourceModule; + +import polyglot.frontend.FileSource; +import polyglot.frontend.Resource; + +/** + * A Polyglot Source whose input comes from an InputStream.
+ * Currently extends FileSource since that's all that the Polyglot Compiler class + * will accept. + * @author rfuhrer + */ +public class ModuleSource extends FileSource { + private final SourceModule module; + + SourceModule getModule() { + return module; + } + + public ModuleSource(final SourceModule module) throws IOException { + super(new Resource() { + public File file() { + return new File(module.getURL().getFile()); + } + + public InputStream getInputStream() throws IOException { + return module.getInputStream(); + } + + public String name() { + String fullPath = module.getURL().getFile(); + int idx= fullPath.lastIndexOf(File.separatorChar); + return (idx > 0) ? fullPath.substring(idx+1) : fullPath; + } + @Override + public String toString() { + return module.getName(); + } + }, true); + this.module = module; + } +} diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHackRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHackRhino.java new file mode 100644 index 000000000..b7c2de1c8 --- /dev/null +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHackRhino.java @@ -0,0 +1,14 @@ +package com.ibm.wala.cast.js.test; + +import org.junit.Before; + +import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; + +public class TestForInLoopHackRhino extends TestForInLoopHack { + + @Before + public void setUp() { + com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); + } + +} diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPagesRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPagesRhino.java new file mode 100644 index 000000000..1704ff458 --- /dev/null +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPagesRhino.java @@ -0,0 +1,18 @@ +package com.ibm.wala.cast.js.test; + +import org.junit.Before; + +import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; + +public class TestMozillaBugPagesRhino extends TestMozillaBugPages { + + public static void main(String[] args) { + justThisTest(TestMozillaBugPagesRhino.class); + } + + @Before + public void setUp() { + com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); + } + +} diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoJericho.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoJericho.java new file mode 100644 index 000000000..4e073940a --- /dev/null +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoJericho.java @@ -0,0 +1,31 @@ +package com.ibm.wala.cast.js.test; + +import java.io.IOException; +import java.net.URL; + +import org.junit.Test; + +import com.ibm.wala.cast.js.html.IHtmlParser; +import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.util.CancelException; + + +public class TestSimplePageCallGraphShapeRhinoJericho extends TestSimplePageCallGraphShapeRhino { + + @Test public void testCrawl() throws IOException, IllegalArgumentException, CancelException { + URL url = getClass().getClassLoader().getResource("pages/crawl.html"); + CallGraph CG = Util.makeHTMLCG(url); + verifyGraphAssertions(CG, null); + } + + public static void main(String[] args) { + justThisTest(TestSimplePageCallGraphShapeRhinoJericho.class); + } + + @Override + protected IHtmlParser getParser() { + return new JerichoHtmlParser(); + } + +} diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java new file mode 100644 index 000000000..20fe4c5a6 --- /dev/null +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java @@ -0,0 +1,137 @@ +package com.ibm.wala.cast.js.test; + +import java.io.IOException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Test; + +import com.ibm.wala.cast.js.html.JSSourceExtractor; +import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder; +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IMethod; +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.ContextItem; +import com.ibm.wala.ipa.callgraph.ContextKey; +import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.util.CancelException; +import com.ibm.wala.util.intset.IntSet; +import com.ibm.wala.util.intset.IntSetUtil; + +public class TestForInLoopHack extends TestJSCallGraphShape { + + @Before + public void config() { + JSSourceExtractor.USE_TEMP_NAME = false; + JSSourceExtractor.DELETE_UPON_EXIT = false; + } + + @Test public void testPage3WithoutHack() throws IOException, IllegalArgumentException, CancelException { + URL url = getClass().getClassLoader().getResource("pages/page3.html"); + JSCFABuilder builder = Util.makeHTMLCGBuilder(url); + CallGraph CG = builder.makeCallGraph(builder.getOptions()); + Util.dumpCG(builder.getPointerAnalysis(), CG); + } + + @Test public void testPage3WithHack() throws IOException, IllegalArgumentException, CancelException { + URL url = getClass().getClassLoader().getResource("pages/page3.html"); + JSCFABuilder builder = Util.makeHTMLCGBuilder(url); + addHackedForInLoopSensitivity(builder); + CallGraph CG = builder.makeCallGraph(builder.getOptions()); + Util.dumpCG(builder.getPointerAnalysis(), CG); + } + + private static final Object[][] assertionsForBadForin = new Object[][] { + new Object[] { ROOT, + new String[] { "tests/badforin.js" } }, + new Object[] { "tests/badforin.js", + new String[] { "tests/badforin.js/testForIn", "tests/badforin.js/_check_obj_foo", "tests/badforin.js/_check_obj_bar", "tests/badforin.js/_check_copy_foo", "tests/badforin.js/_check_copy_bar"} }, + new Object[] { "tests/badforin.js/testForIn", + new String[] { "tests/badforin.js/testForIn1", "tests/badforin.js/testForIn2" } }, + new Object[] { "tests/badforin.js/_check_obj_foo", + new String[] { "tests/badforin.js/testForIn1" } }, + new Object[] { "tests/badforin.js/_check_copy_foo", + new String[] { "tests/badforin.js/testForIn1" } }, + new Object[] { "tests/badforin.js/_check_obj_bar", + new String[] { "tests/badforin.js/testForIn2" } }, + new Object[] { "tests/badforin.js/_check_copy_bar", + new String[] { "tests/badforin.js/testForIn2" } } + }; + + @Test public void testBadForInWithoutHack() throws IOException, IllegalArgumentException, CancelException { + JSCFABuilder B = Util.makeScriptCGBuilder("tests", "badforin.js"); + CallGraph CG = B.makeCallGraph(B.getOptions()); + Util.dumpCG(B.getPointerAnalysis(), CG); + verifyGraphAssertions(CG, assertionsForBadForin); + } + + private static final Object[][] assertionsForBadForinHackPrecision = new Object[][] { + new Object[] { "tests/badforin.js/_check_obj_foo", + new String[] { "!tests/badforin.js/testForIn2" } }, + new Object[] { "tests/badforin.js/_check_copy_foo", + new String[] { "!tests/badforin.js/testForIn2" } }, + new Object[] { "tests/badforin.js/_check_obj_bar", + new String[] { "!tests/badforin.js/testForIn1" } }, + new Object[] { "tests/badforin.js/_check_copy_bar", + new String[] { "!tests/badforin.js/testForIn1" } } + }; + + @Test public void testBadForInWithHack() throws IOException, IllegalArgumentException, CancelException { + JSCFABuilder B = Util.makeScriptCGBuilder("tests", "badforin.js"); + addHackedForInLoopSensitivity(B); + CallGraph CG = B.makeCallGraph(B.getOptions()); + Util.dumpCG(B.getPointerAnalysis(), CG); + verifyGraphAssertions(CG, assertionsForBadForin); + verifyGraphAssertions(CG, assertionsForBadForinHackPrecision); + } + + private void addHackedForInLoopSensitivity(JSCFABuilder builder) { + final ContextSelector orig = builder.getContextSelector(); + builder.setContextSelector(new ContextSelector() { + public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { + final Context origContext = orig.getCalleeTarget(caller, site, callee, receiver); + if (callee.getDeclaringClass().getName().toString().contains("_forin_body")) { + class ForInContext implements Context { + private final InstanceKey obj = receiver[2]; + public ContextItem get(ContextKey name) { + if (name.equals(ContextKey.PARAMETERS[2])) { + return new FilteredPointerKey.SingleInstanceFilter(obj); + } else { + return origContext.get(name); + } + } + @Override + public int hashCode() { + return obj.hashCode(); + } + @Override + public boolean equals(Object other) { + return other != null && + getClass().equals(other.getClass()) && + obj.equals(((ForInContext)other).obj); + } + @Override + public String toString() { + return "for in hack filter for " + obj; + } + }; + return new ForInContext(); + } else { + return origContext; + } + } + public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { + if (caller.getIR().getCalls(site)[0].getNumberOfUses() > 2) { + return IntSetUtil.make(new int[]{2}).union(orig.getRelevantParameters(caller, site)); + } else { + return orig.getRelevantParameters(caller, site); + } + } + }); + } + +} diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java new file mode 100644 index 000000000..f0094a99b --- /dev/null +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java @@ -0,0 +1,54 @@ +package com.ibm.wala.cast.js.test; + +import java.io.IOException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Test; + +import com.ibm.wala.cast.js.html.JSSourceExtractor; +import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.util.CancelException; + +public class TestMozillaBugPages extends TestJSCallGraphShape { + + public static void main(String[] args) { + justThisTest(TestMozillaBugPages.class); + } + + @Before + public void config() { + JSSourceExtractor.USE_TEMP_NAME = false; + JSSourceExtractor.DELETE_UPON_EXIT = false; + } + + @Test public void testMozilla439164() throws IOException, IllegalArgumentException, CancelException { + URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug439164.html"); + JSCFABuilder builder = Util.makeHTMLCGBuilder(url); + CallGraph CG = builder.makeCallGraph(builder.getOptions()); + Util.dumpCG(builder.getPointerAnalysis(), CG); + } + + @Test public void testMozilla488233() throws IOException, IllegalArgumentException, CancelException { + URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug488233NoExtJS.html"); + JSCFABuilder builder = Util.makeHTMLCGBuilder(url); + CallGraph CG = builder.makeCallGraph(builder.getOptions()); + Util.dumpCG(builder.getPointerAnalysis(), CG); + } + + @Test public void testMozilla490152() throws IOException, IllegalArgumentException, CancelException { + URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug490152NoExtJS.html"); + JSCFABuilder builder = Util.makeHTMLCGBuilder(url); + CallGraph CG = builder.makeCallGraph(builder.getOptions()); + Util.dumpCG(builder.getPointerAnalysis(), CG); + } + + @Test public void testMozilla625562() throws IOException, IllegalArgumentException, CancelException { + URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug625562NoExtJS.html"); + JSCFABuilder builder = Util.makeHTMLCGBuilder(url); + CallGraph CG = builder.makeCallGraph(builder.getOptions()); + Util.dumpCG(builder.getPointerAnalysis(), CG); + } + +} diff --git a/com.ibm.wala.cast.test/harness-src/com/ibm/wala/cast/test/Util.java b/com.ibm.wala.cast.test/harness-src/com/ibm/wala/cast/test/Util.java new file mode 100644 index 000000000..7b3647e85 --- /dev/null +++ b/com.ibm.wala.cast.test/harness-src/com/ibm/wala/cast/test/Util.java @@ -0,0 +1,40 @@ +package com.ibm.wala.cast.test; + +import java.util.Iterator; + +import junit.framework.Assert; + +import com.ibm.wala.cast.loader.CAstAbstractLoader; +import com.ibm.wala.classLoader.IClassLoader; +import com.ibm.wala.classLoader.ModuleEntry; +import com.ibm.wala.ipa.cha.IClassHierarchy; +import com.ibm.wala.util.warnings.Warning; + +public class Util { + + public static void checkForFrontEndErrors(IClassHierarchy cha) { + StringBuffer message = null; + for(IClassLoader loader : cha.getLoaders()) { + if (loader instanceof CAstAbstractLoader) { + Iterator errors = ((CAstAbstractLoader)loader).getModulesWithParseErrors(); + if (errors.hasNext()) { + if (message == null) { + message = new StringBuffer("front end errors:\n"); + } + while (errors.hasNext()) { + ModuleEntry errorModule = errors.next(); + for(Warning w : (((CAstAbstractLoader)loader).getMessages(errorModule))) { + message.append("error in ").append(errorModule.getName()).append(":\n"); + message.append(w.toString()).append("\n"); + } + } + } + } + } + if (message != null) { + message.append("end of front end errors\n"); + } + Assert.assertTrue(String.valueOf(message), message == null); + } + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java new file mode 100644 index 000000000..42318f1ed --- /dev/null +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * 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.classLoader; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import com.ibm.wala.util.collections.NonNullSingletonIterator; +import com.ibm.wala.util.collections.Pair; + +public class CompoundModule implements ModuleEntry, Module, SourceModule { + private final SourceModule[] constituents; + private final URL name; + + public CompoundModule(URL name, SourceModule[] constituents) { + this.name = name; + this.constituents = constituents; + } + + public SourceModule[] getConstituents() { + SourceModule[] stuff = new SourceModule[ constituents.length ]; + System.arraycopy(constituents, 0, stuff, 0, constituents.length); + return stuff; + } + + public Iterator getEntries() { + return new NonNullSingletonIterator(this); + } + + public boolean isModuleFile() { + return false; + } + + public Module asModule() { + throw new UnsupportedOperationException(); + } + + public String getClassName() { + throw new UnsupportedOperationException(); + } + + public String getName() { + return name.toString(); + } + + public URL getURL() { + return name; + } + + public boolean isClassFile() { + return false; + } + + public boolean isSourceFile() { + return true; + } + + public InputStream getInputStream() { + return new InputStream() { + private int index = 0; + private InputStream currentStream; + + @Override + public int read() throws IOException { + if (currentStream == null) { + if (index < constituents.length) { + currentStream = constituents[index++].getInputStream(); + } else { + return -1; + } + } + int b = currentStream.read(); + if (b == -1) { + currentStream = null; + return read(); + } + return b; + } + }; + } + + public class Reader extends java.io.Reader { + private final List> locations = new ArrayList>(); + private int line = 0; + private int index = 0; + private LineNumberReader currentReader; + private URL currentName; + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + if (currentReader == null) { + if (index < constituents.length) { + currentName = constituents[index].getURL(); + currentReader = new LineNumberReader(new InputStreamReader(constituents[index++].getInputStream())); + } else { + return -1; + } + } + + int x; + if ((x = currentReader.read(cbuf, off, len)) == -1) { + line += currentReader.getLineNumber(); + locations.add(Pair.make(line, currentName)); + + currentReader.close(); + currentReader = null; + + return read(cbuf, off, len); + } + + return x; + } + + @Override + public void close() throws IOException { + if (currentReader!= null) { + currentReader.close(); + currentReader = null; + } + } + + public Pair getOriginalPosition(int lineNumber) { + int start = 0; + for(int i = 0; i < locations.size(); i++) { + if (locations.get(i).fst >= lineNumber) { + return Pair.make(lineNumber - start, locations.get(i).snd); + } else { + start = locations.get(i).fst; + } + } + throw new IllegalArgumentException("line number " + lineNumber + " too high"); + } + } + + public Reader getInputReader() { + return new Reader(); + } + +} diff --git a/com.ibm.wala.util/src/com/ibm/wala/util/functions/VoidFunction.java b/com.ibm.wala.util/src/com/ibm/wala/util/functions/VoidFunction.java new file mode 100644 index 000000000..f3ff46656 --- /dev/null +++ b/com.ibm.wala.util/src/com/ibm/wala/util/functions/VoidFunction.java @@ -0,0 +1,7 @@ +package com.ibm.wala.util.functions; + +public interface VoidFunction { + + void apply(T v); + +}