110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipackage annotator.find;
210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport java.util.List;
410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport annotations.el.BoundLocation;
610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport com.sun.source.tree.ClassTree;
810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport com.sun.source.tree.MethodTree;
910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport com.sun.source.tree.Tree;
1010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport com.sun.source.tree.TypeParameterTree;
1110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport com.sun.source.util.TreePath;
12dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brownimport com.sun.tools.javac.code.Type;
13dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brownimport com.sun.tools.javac.tree.JCTree.JCExpression;
1410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
1510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipublic class BoundLocationCriterion implements Criterion {
1610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
1710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  private Criterion parentCriterion;
18315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak  private final int boundIndex;
19315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak  private final int paramIndex;
2010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
2110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
2210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  public BoundLocationCriterion(BoundLocation boundLoc) {
2310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    this(boundLoc.boundIndex, boundLoc.paramIndex);
2410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  }
2510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
26315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak  private BoundLocationCriterion(int boundIndex, int paramIndex) {
2710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    this.boundIndex = boundIndex;
2810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    this.paramIndex = paramIndex;
2910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
30315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak    if (boundIndex != -1) {
31315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak      this.parentCriterion = new BoundLocationCriterion(-1, paramIndex);
32315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak    } else if (paramIndex != -1) {
3310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      this.parentCriterion = null;
3410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
3510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  }
3610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
374735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  /** {@inheritDoc} */
384735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  @Override
394735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  public boolean isSatisfiedBy(TreePath path, Tree leaf) {
404735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst    assert path == null || path.getLeaf() == leaf;
414735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst    return isSatisfiedBy(path);
424735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  }
434735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst
444735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  /** {@inheritDoc} */
454735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  @Override
4610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  public boolean isSatisfiedBy(TreePath path) {
474735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst    if (path == null) {
4810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      return false;
4910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
5010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
5110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    Tree leaf = path.getLeaf();
5210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
530f7ed8e9f456276945e3cc04203c31dbce61a0b5Michael Ernst    // System.out.printf("BoundLocationCriterion.isSatisfiedBy(%s):%n  leaf=%s (%s)%n", path, leaf, leaf.getClass());
540f7ed8e9f456276945e3cc04203c31dbce61a0b5Michael Ernst
5510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    TreePath parentPath = path.getParentPath();
5610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    if (parentPath == null) {
5710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      return false;
5810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
5910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
6010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    Tree parent = parentPath.getLeaf();
6110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    if (parent == null) {
6210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      return false;
6310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
6410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
6510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    boolean returnValue = false;
6610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
670f7ed8e9f456276945e3cc04203c31dbce61a0b5Michael Ernst    // System.out.printf("BoundLocationCriterion.isSatisfiedBy(%s):%n  leaf=%s (%s)%n  parent=%s (%s)%n", path, leaf, leaf.getClass(), parent, parent.getClass());
680f7ed8e9f456276945e3cc04203c31dbce61a0b5Michael Ernst
6910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    // if boundIndex is not null, need to check that this is right bound
7010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    // in parent
71315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak    if (boundIndex != -1) {
7210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      if (parent instanceof TypeParameterTree) {
73dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        List<? extends Tree> bounds = ((TypeParameterTree) parent).getBounds();
74dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        int ix = boundIndex;
75dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        if (!bounds.isEmpty() && isInterface((JCExpression) bounds.get(0))) {
76dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown          --ix;
7710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
78dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        if (ix < 0 || ix < bounds.size() && bounds.get(ix) == leaf) {
79dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown          returnValue = parentCriterion.isSatisfiedBy(parentPath);
80dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        }
81dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown      } else if (boundIndex == 0 && leaf instanceof TypeParameterTree) {
82dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        List<? extends Tree> bounds = ((TypeParameterTree) leaf).getBounds();
83dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        if (bounds.isEmpty() || isInterface((JCExpression) bounds.get(0))) {
840f7ed8e9f456276945e3cc04203c31dbce61a0b5Michael Ernst          // If the bound is implicit (i.e., a missing "extends Object"),
850f7ed8e9f456276945e3cc04203c31dbce61a0b5Michael Ernst          // then permit the match here.
860f7ed8e9f456276945e3cc04203c31dbce61a0b5Michael Ernst          returnValue = parentCriterion.isSatisfiedBy(path);
87dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        } else {
88dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown          Type type = ((JCExpression) bounds.get(0)).type;
89dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown          if (type != null && type.tsym != null && type.tsym.isInterface()) {
90dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown            returnValue = parentCriterion.isSatisfiedBy(parentPath);
91dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown          }
92dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown        }
9310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      }
94315403cf0cb532b4bce3c6da753046b993eac572Eric Spishak    } else if (paramIndex != -1) {
9510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      // if paramIndex is not null, need to ensure this present
9610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      // typeparameter tree represents the correct parameter
9710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      if (parent instanceof MethodTree || parent instanceof ClassTree) {
9810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        List<? extends TypeParameterTree> params = null;
9910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
10010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        if (parent instanceof MethodTree) {
10110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali          params = ((MethodTree) parent).getTypeParameters();
10210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        } else if (parent instanceof ClassTree) {
10310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali          params = ((ClassTree) parent).getTypeParameters();
10410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
10510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
10610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        if (paramIndex < params.size()) {
10710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali          if (params.get(paramIndex) == leaf) {
10810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            returnValue = true;
10910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali          }
11010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
11110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      }
11210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
11310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
11410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    if (!returnValue) {
11510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      return this.isSatisfiedBy(parentPath);
11610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    } else {
11710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      return true;
11810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
11910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  }
12010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
121dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown  private boolean isInterface(JCExpression bound) {
122dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown    Type type = bound.type;
123dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown    return type != null && type.tsym != null && type.tsym.isInterface();
124dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown  }
125dd5ddd43212d92e5d5051c2f070fb299a1e1e43bDan Brown
1264735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  /** {@inheritDoc} */
1270c0bd9d1e50a213629b2031d1c906cdf688af580Werner Dietl  @Override
12810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  public Kind getKind() {
12910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    return Kind.BOUND_LOCATION;
13010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  }
13110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
1324735bdd95fe3025e721476ae821d0aca6127f80aMichael Ernst  /** {@inheritDoc} */
1330c0bd9d1e50a213629b2031d1c906cdf688af580Werner Dietl  @Override
13410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  public String toString() {
13510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    return "BoundCriterion: at param index: " + paramIndex +
13610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali      " at bound index: " + boundIndex;
13710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali  }
13810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali}
139