• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package annotator.scanner;
2 
3 import com.sun.source.tree.BlockTree;
4 import com.sun.source.tree.ClassTree;
5 import com.sun.source.tree.StatementTree;
6 import com.sun.source.tree.Tree;
7 import com.sun.source.util.TreePath;
8 import com.sun.source.util.TreePathScanner;
9 
10 /**
11  * LocalClassScanner determines the index of a tree for a local
12  * class. If the index is i, it is the ith local class with the class name in
13  * the file. Thus, if i = 2, it will have a name of the form
14  * OuterClass$2InnerClass.
15  */
16 public class LocalClassScanner extends TreePathScanner<Void, Integer> {
17 
18   /**
19    * Given a local class, computes and returns its 1-based index in the given
20    * tree representing a local class.
21    *
22    * @param path the source path ending in the local class
23    * @param localClass the local class to search for
24    * @return the index of the local class in the source code
25    */
indexOfClassTree(TreePath path, ClassTree localClass)26   public static int indexOfClassTree(TreePath path, ClassTree localClass) {
27     // Move up to the CLASS tree enclosing this CLASS tree and start the tree
28     // traversal from there. This prevents us from counting local classes that
29     // are in a different part of the tree and therefore aren't included in the
30     // index number.
31     int classesFound = 0;
32     boolean localClassFound = false;
33     while (path.getParentPath() != null && classesFound < 1) {
34       if (path.getLeaf() == localClass) {
35         localClassFound = true;
36       }
37       path = path.getParentPath();
38       if (localClassFound && path.getLeaf().getKind() == Tree.Kind.CLASS) {
39         classesFound++;
40       }
41     }
42     LocalClassScanner lcs = new LocalClassScanner(localClass);
43     lcs.scan(path, 0);
44     if (lcs.found) {
45       return lcs.index;
46     } else {
47       return -1;
48     }
49   }
50 
51   private int index;
52   private boolean found;
53   private ClassTree localClass;
54 
55   /**
56    * Creates a new LocalClassScanner that searches for the index of the given
57    * tree, representing a local class.
58    *
59    * @param localClass the local class to search for
60    */
LocalClassScanner(ClassTree localClass)61   private LocalClassScanner(ClassTree localClass) {
62     this.index = 1;
63     this.found = false;
64     this.localClass = localClass;
65   }
66 
67   // The level parameter keeps us from traversing too low in the tree and
68   // counting classes that aren't included in the index number.
69 
70   @Override
visitBlock(BlockTree node, Integer level)71   public Void visitBlock(BlockTree node, Integer level) {
72     if (level < 1) {
73       // Visit blocks since a local class can only be in a block. Then visit each
74       // statement of the block to see if any are the correct local class.
75       for (StatementTree statement : node.getStatements()) {
76         if (!found && statement.getKind() == Tree.Kind.CLASS) {
77           ClassTree c = (ClassTree) statement;
78           if (localClass == statement) {
79             found = true;
80           } else if (c.getSimpleName().equals(localClass.getSimpleName())) {
81             index++;
82           }
83         }
84       }
85       super.visitBlock(node, level + 1);
86     }
87     return null;
88   }
89 }
90