1package annotator.find; 2 3import java.util.List; 4 5import annotations.el.BoundLocation; 6 7import com.sun.source.tree.ClassTree; 8import com.sun.source.tree.MethodTree; 9import com.sun.source.tree.Tree; 10import com.sun.source.tree.TypeParameterTree; 11import com.sun.source.util.TreePath; 12import com.sun.tools.javac.code.Type; 13import com.sun.tools.javac.tree.JCTree.JCExpression; 14 15public class BoundLocationCriterion implements Criterion { 16 17 private Criterion parentCriterion; 18 private final int boundIndex; 19 private final int paramIndex; 20 21 22 public BoundLocationCriterion(BoundLocation boundLoc) { 23 this(boundLoc.boundIndex, boundLoc.paramIndex); 24 } 25 26 private BoundLocationCriterion(int boundIndex, int paramIndex) { 27 this.boundIndex = boundIndex; 28 this.paramIndex = paramIndex; 29 30 if (boundIndex != -1) { 31 this.parentCriterion = new BoundLocationCriterion(-1, paramIndex); 32 } else if (paramIndex != -1) { 33 this.parentCriterion = null; 34 } 35 } 36 37 /** {@inheritDoc} */ 38 @Override 39 public boolean isSatisfiedBy(TreePath path, Tree leaf) { 40 assert path == null || path.getLeaf() == leaf; 41 return isSatisfiedBy(path); 42 } 43 44 /** {@inheritDoc} */ 45 @Override 46 public boolean isSatisfiedBy(TreePath path) { 47 if (path == null) { 48 return false; 49 } 50 51 Tree leaf = path.getLeaf(); 52 53 // System.out.printf("BoundLocationCriterion.isSatisfiedBy(%s):%n leaf=%s (%s)%n", path, leaf, leaf.getClass()); 54 55 TreePath parentPath = path.getParentPath(); 56 if (parentPath == null) { 57 return false; 58 } 59 60 Tree parent = parentPath.getLeaf(); 61 if (parent == null) { 62 return false; 63 } 64 65 boolean returnValue = false; 66 67 // System.out.printf("BoundLocationCriterion.isSatisfiedBy(%s):%n leaf=%s (%s)%n parent=%s (%s)%n", path, leaf, leaf.getClass(), parent, parent.getClass()); 68 69 // if boundIndex is not null, need to check that this is right bound 70 // in parent 71 if (boundIndex != -1) { 72 if (parent instanceof TypeParameterTree) { 73 List<? extends Tree> bounds = ((TypeParameterTree) parent).getBounds(); 74 int ix = boundIndex; 75 if (!bounds.isEmpty() && isInterface((JCExpression) bounds.get(0))) { 76 --ix; 77 } 78 if (ix < 0 || ix < bounds.size() && bounds.get(ix) == leaf) { 79 returnValue = parentCriterion.isSatisfiedBy(parentPath); 80 } 81 } else if (boundIndex == 0 && leaf instanceof TypeParameterTree) { 82 List<? extends Tree> bounds = ((TypeParameterTree) leaf).getBounds(); 83 if (bounds.isEmpty() || isInterface((JCExpression) bounds.get(0))) { 84 // If the bound is implicit (i.e., a missing "extends Object"), 85 // then permit the match here. 86 returnValue = parentCriterion.isSatisfiedBy(path); 87 } else { 88 Type type = ((JCExpression) bounds.get(0)).type; 89 if (type != null && type.tsym != null && type.tsym.isInterface()) { 90 returnValue = parentCriterion.isSatisfiedBy(parentPath); 91 } 92 } 93 } 94 } else if (paramIndex != -1) { 95 // if paramIndex is not null, need to ensure this present 96 // typeparameter tree represents the correct parameter 97 if (parent instanceof MethodTree || parent instanceof ClassTree) { 98 List<? extends TypeParameterTree> params = null; 99 100 if (parent instanceof MethodTree) { 101 params = ((MethodTree) parent).getTypeParameters(); 102 } else if (parent instanceof ClassTree) { 103 params = ((ClassTree) parent).getTypeParameters(); 104 } 105 106 if (paramIndex < params.size()) { 107 if (params.get(paramIndex) == leaf) { 108 returnValue = true; 109 } 110 } 111 } 112 } 113 114 if (!returnValue) { 115 return this.isSatisfiedBy(parentPath); 116 } else { 117 return true; 118 } 119 } 120 121 private boolean isInterface(JCExpression bound) { 122 Type type = bound.type; 123 return type != null && type.tsym != null && type.tsym.isInterface(); 124 } 125 126 /** {@inheritDoc} */ 127 @Override 128 public Kind getKind() { 129 return Kind.BOUND_LOCATION; 130 } 131 132 /** {@inheritDoc} */ 133 @Override 134 public String toString() { 135 return "BoundCriterion: at param index: " + paramIndex + 136 " at bound index: " + boundIndex; 137 } 138} 139