fix some warnings
[eclipsethinslicer.git] / Svelte / src / edu / berkeley / cs / bodik / svelte / CallGraphUtils.java
blob3419c89795f711934eaa92e8e73818f6f916cd7c
1 /*******************************************************************************
2 * This program and the accompanying materials
3 * are made available under the terms of the Eclipse Public License v1.0
4 * which accompanies this distribution, and is available at
5 * http://www.eclipse.org/legal/epl-v10.html.
6 *
7 * This file is a derivative of code released by the University of
8 * California under the terms listed below.
10 * Refinement Analysis Tools is Copyright ©2007 The Regents of the
11 * University of California (Regents). Provided that this notice and
12 * the following two paragraphs are included in any distribution of
13 * Refinement Analysis Tools or its derivative work, Regents agrees
14 * not to assert any of Regents' copyright rights in Refinement
15 * Analysis Tools against recipient for recipient’s reproduction,
16 * preparation of derivative works, public display, public
17 * performance, distribution or sublicensing of Refinement Analysis
18 * Tools and derivative works, in source code and object code form.
19 * This agreement not to assert does not confer, by implication,
20 * estoppel, or otherwise any license or rights in any intellectual
21 * property of Regents, including, but not limited to, any patents
22 * of Regents or Regents’ employees.
24 * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
25 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
26 * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
27 * AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 * FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
33 * WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
34 * DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
35 * IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
36 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
38 package edu.berkeley.cs.bodik.svelte;
40 import java.io.IOException;
41 import java.io.PrintStream;
42 import java.net.MalformedURLException;
43 import java.net.URL;
44 import java.util.Iterator;
45 import java.util.Set;
47 import junit.framework.Assert;
49 import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
50 import com.ibm.wala.classLoader.IClass;
51 import com.ibm.wala.classLoader.IClassLoader;
52 import com.ibm.wala.classLoader.IMethod;
53 import com.ibm.wala.eclipse.util.EclipseProjectPath;
54 import com.ibm.wala.ipa.callgraph.CGNode;
55 import com.ibm.wala.ipa.callgraph.CallGraph;
56 import com.ibm.wala.ipa.cha.IClassHierarchy;
57 import com.ibm.wala.types.Descriptor;
58 import com.ibm.wala.util.collections.HashSetFactory;
59 import com.ibm.wala.util.debug.Assertions;
60 import com.ibm.wala.util.strings.Atom;
62 /**
63 * Utilities for dealing with call graphs and call graph
65 * @author Evan Battaglia
68 public class CallGraphUtils {
70 /**
71 * Find a method whose signature matches <code>([Ljava/lang/String;)V</code>, that is,
72 * <code>void main(String args[])</code>
74 * @param cg
75 * The callgraph to search thru. WARNING: May not look thru all nodes (see code
76 * details)
78 * @return The CGNode representing the method, or null if it could not be found.
80 public static CGNode findMainMethod(CallGraph cg) {
81 Descriptor d = Descriptor.findOrCreateUTF8("([Ljava/lang/String;)V");
82 Atom name = Atom.findOrCreateUnicodeAtom("main");
83 for (Iterator<? extends CGNode> it = cg.getSuccNodes(cg.getFakeRootNode()); it.hasNext();) {
84 CGNode n = it.next();
85 if (n.getMethod().getName().equals(name) && n.getMethod().getDescriptor().equals(d)) {
86 return n;
89 Assertions.UNREACHABLE("failed to find main() method");
90 return null;
93 /**
94 * Find any method in a callgraph. Usually not general enough to find all methods. Don't use
95 * this, use the code from the slicer plugin (added here later hopefully) Parameters same as
96 * findMainMethod.
98 * @param cg
99 * @param name
100 * @return
102 public static CGNode findMethod(CallGraph cg, String name) {
103 Atom a = Atom.findOrCreateUnicodeAtom(name);
104 for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
105 CGNode n = it.next();
106 if (n.getMethod().getName().equals(a)) {
107 return n;
110 Assertions.UNREACHABLE("failed to find method " + name);
111 return null;
115 * Print (to System.out) the IR of a Call Graph.
117 * @param cg
118 * @param assertReachable
119 * @throws IOException
121 protected static void dumpIR(CallGraph cg, boolean assertReachable) throws IOException {
122 Set<IMethod> unreachable = HashSetFactory.make();
123 IClassHierarchy cha = cg.getClassHierarchy();
124 IClassLoader sourceLoader = cha.getLoader(EclipseProjectPath.SOURCE_REF);
125 for (Iterator<IClass> iter = sourceLoader.iterateAllClasses(); iter.hasNext();) {
126 IClass clazz = iter.next();
127 PrintStream Trace = System.out; // CHANGED by evan
128 Trace.println(clazz);
129 if (clazz.isInterface())
130 continue;
132 for (IMethod m : clazz.getDeclaredMethods()) {
133 if (m.isAbstract()) {
134 Trace.println(m);
135 } else {
136 Iterator<CGNode> nodeIter = cg.getNodes(m.getReference()).iterator();
137 if (!nodeIter.hasNext()) {
138 Trace.println("Method " + m.getReference() + " not reachable?");
139 unreachable.add(m);
140 continue;
142 CGNode node = nodeIter.next();
143 Trace.println(node.getIR());
148 if (assertReachable) {
149 Assert.assertTrue(unreachable.toString(), unreachable.isEmpty());
154 * Find shortest method whose range of line numbers includes linenum, in the class classname.
155 * This is useful if you are trying to find the statement on a particular line number. You can
156 * first find the method with this, then look through and find the statement matching the line
157 * number.
159 * @param cg
160 * A call graph.
161 * @param linenum
162 * A line number in the file, STARTING FROM 1. If this is between a method's start
163 * and end line numbers, the method will be returned.
164 * @param classname
165 * A fully qualified class name (i.e. com.example.mypackage.MyClass). For the case of inner
166 * classes, the outer/enclosing class is acceptable (i.e. Foo for Foo$Bar or Foo$1)
168 * @return The CGNode of the method found.
170 public static CGNode findMethodIncludingLineNumInClass(CallGraph cg, int linenum,
171 String classname) {
172 String codedclassname = "L" + classname.replace('.', '/');
173 String classnameplusdollarsign = codedclassname + "$"; // the code we want may actually be in Foo$Bar or Foo$1
174 // we check if starts with Foo$ (same file -- line numbers are unique within this file)
175 CGNode shortest_node = null;
176 int len_shortest_node = Integer.MAX_VALUE;
177 for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
178 CGNode n = it.next();
179 IMethod m = n.getMethod();
181 if (m.getDeclaringClass().getName().toString().equals(codedclassname)
182 || m.getDeclaringClass().getName().toString().startsWith(classnameplusdollarsign)) {
183 Position pos = CGNodeUtils.getSourcePosition(n);
184 System.out.printf("***METHOD %s line %d to %d\n", m.toString(), pos.getFirstLine(),
185 pos.getLastLine());
186 if (linenum >= pos.getFirstLine() && linenum <= pos.getLastLine()) {
187 if ((pos.getLastLine() - pos.getFirstLine()) < len_shortest_node) {
188 len_shortest_node = pos.getLastLine() - pos.getFirstLine();
189 shortest_node = n;
194 return shortest_node;
198 * Find a method whose range of line numbers includes linenum, in the file filename (absolute
199 * [?]) This is useful if you are trying to find the statement on a particular line number. You
200 * can first find the method with this, then look through and find the statement matching the
201 * line number.
203 * @param cg
204 * @param linenum
205 * @param filename
206 * @return
208 public static CGNode findMethodIncludingLineNum(CallGraph cg, int linenum,
209 String filename) {
210 String windowsFixedFilename = null;
211 try {
212 windowsFixedFilename = new URL("file:" + filename).getFile();
213 } catch (MalformedURLException e) {
214 Assertions.UNREACHABLE("Invalid filename in findMethodIncludingLineNum?!");
216 CGNode shortest_node = null;
217 int len_shortest_node = Integer.MAX_VALUE;
218 for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
219 CGNode n = it.next();
220 IMethod m = n.getMethod();
222 if (m.getDeclaringClass().getSourceFileName() != null && m.getDeclaringClass().getSourceFileName().toString().equals(windowsFixedFilename)) {
223 Position pos = CGNodeUtils.getSourcePosition(n);
224 if ( pos != null ) {
225 System.out.printf("***METHOD %s line %d to %d\n", m.toString(), pos.getFirstLine(),
226 pos.getLastLine());
227 if (linenum >= pos.getFirstLine() && linenum <= pos.getLastLine()) {
228 if ((pos.getLastLine() - pos.getFirstLine()) < len_shortest_node) {
229 len_shortest_node = pos.getLastLine() - pos.getFirstLine();
230 shortest_node = n;
236 return shortest_node;