• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package annotator.scanner;
2 
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 
8 import com.sun.source.tree.InstanceOfTree;
9 import com.sun.source.tree.Tree;
10 import com.sun.source.util.TreePath;
11 
12 /** InstanceOfScanner stores information about the names and offsets of
13  * instanceof checks inside a method, and can also be used to scan the source
14  * tree and determine the index of a given instanceof check, where the i^th
15  * index corresponds to the i^th instanceof check, using 0-based indexing.
16  */
17 public class InstanceOfScanner extends CommonScanner {
18 
19   /**
20    * Computes the index of the given instanceof tree amongst all instanceof
21    * tree inside its method, using 0-based indexing.
22    *
23    * @param origpath the path ending in the given instanceof tree
24    * @param tree the instanceof tree to search for
25    * @return the index of the given instanceof tree
26    */
indexOfInstanceOfTree(TreePath origpath, Tree tree)27   public static int indexOfInstanceOfTree(TreePath origpath, Tree tree) {
28     TreePath path = findCountingContext(origpath);
29     if (path == null) {
30       return -1;
31     }
32 
33     InstanceOfScanner ios = new InstanceOfScanner(tree);
34     ios.scan(path, null);
35     return ios.index;
36   }
37 
38   private int index = -1;
39   private boolean done = false;
40   private final Tree tree;
41 
42   /**
43    * Creates an InstanceOfScanner that will scan the source tree for the
44    *  given node representing the instanceof check to find.
45    * @param tree the given instanceof check to search for
46    */
InstanceOfScanner(Tree tree)47   private InstanceOfScanner(Tree tree) {
48     this.index = -1;
49     this.done = false;
50     this.tree = tree;
51   }
52 
53   @Override
visitInstanceOf(InstanceOfTree node, Void p)54   public Void visitInstanceOf(InstanceOfTree node, Void p) {
55     if (!done) {
56       index++;
57     }
58     if (tree == node) {
59       done = true;
60     }
61     return super.visitInstanceOf(node, p);
62   }
63 
64   // Map from name of a method to a list of bytecode offsets of all
65   // instanceof checks in that method.
66   private static Map<String, List<Integer>> methodNameToInstanceOfOffsets =
67     new HashMap<String, List<Integer>>();
68 
69   /**
70    * Adds an instanceof bytecode offset to the current list of offsets for
71    * methodName.  This method must be called with monotonically increasing
72    * offsets for any one method.
73    *
74    * @param methodName the name of the method
75    * @param offset the offset to add
76    */
addInstanceOfToMethod(String methodName, Integer offset)77   public static void addInstanceOfToMethod(String methodName, Integer offset) {
78     List<  Integer> offsetList = methodNameToInstanceOfOffsets.get(methodName);
79     if (offsetList == null) {
80       offsetList = new ArrayList<  Integer>();
81       methodNameToInstanceOfOffsets.put(methodName, offsetList);
82     }
83     offsetList.add(offset);
84   }
85 
86   /**
87    * Returns the index of the given offset within the list of offsets
88    * for the given method, using 0-based indexing,
89    * or returns a negative number if the offset is not one of the
90    * offsets in the method.
91    *
92    * @param methodName the name of the method
93    * @param offset the offset of the instanceof check
94    * @return the index of the given offset, or a negative number
95    *  if the offset does not exist inside the method
96    */
getMethodInstanceOfIndex(String methodName, Integer offset)97   public static Integer getMethodInstanceOfIndex(String methodName, Integer offset)  {
98     List<  Integer> offsetList = methodNameToInstanceOfOffsets.get(methodName);
99     if (offsetList == null) {
100       return -1;
101     }
102 
103     return offsetList.indexOf(offset);
104   }
105 }
106