1290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownpackage annotator.find;
2290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
3d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport java.util.AbstractSet;
4d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport java.util.ArrayDeque;
5567ba7d414e53451066008d98bbeacdfed876aceDan Brownimport java.util.ArrayList;
6290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport java.util.Collection;
7290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport java.util.Collections;
8d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport java.util.Comparator;
9d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport java.util.Deque;
10290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport java.util.HashMap;
11290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport java.util.Iterator;
12d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport java.util.LinkedHashSet;
13567ba7d414e53451066008d98bbeacdfed876aceDan Brownimport java.util.List;
14290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport java.util.Map;
15290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport java.util.NoSuchElementException;
16290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownimport java.util.Set;
17d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport java.util.SortedMap;
18d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport java.util.TreeMap;
19eaf2af4be89d5a1729112ebf477079bee1014929Dan Brownimport java.util.TreeSet;
20d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
21d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport javax.lang.model.element.Name;
22d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport javax.lang.model.type.TypeKind;
23d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
24d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport annotations.el.InnerTypeLocation;
25d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport annotations.io.ASTIndex;
26d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport annotations.io.ASTPath;
27d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport annotations.io.ASTRecord;
28d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport type.*;
29d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
30d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.AnnotatedTypeTree;
31d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.AnnotationTree;
32d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.ArrayTypeTree;
33d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.CompilationUnitTree;
34d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.ExpressionTree;
35d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.IdentifierTree;
36d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.MemberSelectTree;
378af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brownimport com.sun.source.tree.NewArrayTree;
38d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.ParameterizedTypeTree;
39d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.PrimitiveTypeTree;
40d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.Tree;
41d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.TreeVisitor;
42d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.TypeParameterTree;
43d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.WildcardTree;
448af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brownimport com.sun.source.util.TreePath;
45d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.Kinds;
46d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.Symbol.ClassSymbol;
47d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.Symbol.MethodSymbol;
48d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry;
49d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
50d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.TypeTag;
51d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.tree.JCTree;
52dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brownimport com.sun.tools.javac.tree.JCTree.JCExpression;
53d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.util.Pair;
54290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
55290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown/**
56290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown * @author dbro
57290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown *
5863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * An indexed collection (though not {@link java.util.Collection}, only
59a53f379c5f7e30c61896b73ab56974dc15bbce7dDan Brown * {@link java.lang.Iterable}) of {@link Insertion}s with methods to
6063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * select those specified for a given class or for an outer class along
6163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * with its local classes.  This class is especially useful when a
6263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * single JAIF stores annotations for many source files, as it reduces
6363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * the number of insertions to be considered for any AST node.
6463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown *
6563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * The class now serves a second purpose, which should probably be
6663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * separated out (according to OO dogma, at least): It attaches
6763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * {@link annotations.io.ASTPath}-based inner type {@link Insertion}s to
6863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * a {@link TypedInsertion} on the outer type if one exists (see
6963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * {@link #organizeTypedInsertions(CompilationUnitTree, String, Collection)}.
7063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * Since getting these insertions right depends on this organization,
7163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * this class is now essential for correctness, not merely for
7263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown * performance.
73290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown */
74290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownpublic class Insertions implements Iterable<Insertion> {
75eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown  private static int kindLevel(Insertion i) {
76eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    // ordered so insertion that depends on another gets inserted after other
77eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    switch (i.getKind()) {
78eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    case CONSTRUCTOR:
79eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown      return 3;
80eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    case NEW:
81eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    case RECEIVER:
82eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown      return 2;
83eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    case CAST:
84eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown        return 1;
8552e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst    // case ANNOTATION:
8652e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst    // case CLOSE_PARENTHESIS:
87eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    default:
88eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown      return 0;
89eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown    }
90eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown  }
91eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown
92d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private static final Comparator<Insertion> byASTRecord =
93d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      new Comparator<Insertion>() {
94d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        @Override
95d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        public int compare(Insertion o1, Insertion o2) {
96d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Criteria c1 = o1.getCriteria();
97d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Criteria c2 = o2.getCriteria();
98eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          ASTPath p1 = c1.getASTPath();
99eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          ASTPath p2 = c2.getASTPath();
100eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          ASTRecord r1 = new ASTRecord(null,
101eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown              c1.getClassName(), c1.getMethodName(), c1.getFieldName(),
102eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown              p1 == null ? ASTPath.empty() : p1);
103eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          ASTRecord r2 = new ASTRecord(null,
104eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown              c2.getClassName(), c2.getMethodName(), c2.getFieldName(),
105eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown              p2 == null ? ASTPath.empty() : p2);
106eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          int c = r1.compareTo(r2);
107eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          if (c == 0) {
10852e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst            // c = o1.getKind().compareTo(o2.getKind());
109eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown            c = Integer.compare(kindLevel(o2), kindLevel(o1));  // descending
110eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown            if (c == 0) { c = o1.toString().compareTo(o2.toString()); }
111eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          }
112eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          return c;
113d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
114d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      };
115d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
116d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  // store indexes insertions by (qualified) outer class name and inner
117d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  // class path (if any)
118d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private Map<String, Map<String, Set<Insertion>>> store;
119290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  private int size;
120290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
121d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private Pair<String, String> nameSplit(String name) {
122d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    int i = name.indexOf('$');  // FIXME: don't split on '$' in source
123d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return i < 0
124d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ? Pair.of(name, "")
125d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        : Pair.of(name.substring(0, i), name.substring(i));
126d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
127d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
128290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public Insertions() {
129d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    store = new HashMap<String, Map<String, Set<Insertion>>>();
130567ba7d414e53451066008d98bbeacdfed876aceDan Brown    size = 0;
131290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
132290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
13363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  // auxiliary for following two methods
134d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private void forClass(CompilationUnitTree cut,
135d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String qualifiedClassName, Set<Insertion> result) {
136d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Pair<String, String> pair = nameSplit(qualifiedClassName);
137d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<String, Set<Insertion>> map = store.get(pair.fst);
138d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (map != null) {
139eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown      Set<Insertion> set = new TreeSet<Insertion>(byASTRecord);
140eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown      set.addAll(map.get(pair.snd));
141d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (set != null) {
142d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        set = organizeTypedInsertions(cut, qualifiedClassName, set);
143d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        result.addAll(set);
144d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
145d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
146d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
147d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
14863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  /**
14963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * Selects {@link Insertion}s relevant to a given class.
15063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   *
15163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * @param cut the current compilation unit
15263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * @param qualifiedClassName the fully qualified class name
15363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * @return {@link java.util.Set} of {@link Insertion}s with an
15463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   *          {@link InClassCriterion} for the given class
15563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   */
156d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  public Set<Insertion> forClass(CompilationUnitTree cut,
157d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String qualifiedClassName) {
158d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Set<Insertion> set = new LinkedHashSet<Insertion>();
159d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    forClass(cut, qualifiedClassName, set);
160d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return set;
161d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
162d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
16363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  /**
16463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * Selects {@link Insertion}s relevant to a given outer class and its
16563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * local classes.
16663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   *
16763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * @param cut the current compilation unit
168a53f379c5f7e30c61896b73ab56974dc15bbce7dDan Brown   * @param qualifiedOuterClassName the fully qualified outer class name
16963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * @return {@link java.util.Set} of {@link Insertion}s with an
17063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   *          {@link InClassCriterion} for the given outer class or one
17163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   *          of its local classes
17263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   */
17363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  public Set<Insertion> forOuterClass(CompilationUnitTree cut,
174d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String qualifiedOuterClassName) {
175d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<String, Set<Insertion>> map = store.get(qualifiedOuterClassName);
176d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (map == null || map.isEmpty()) {
177d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return Collections.<Insertion>emptySet();
178d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    } else {
179d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Set<Insertion> set = new LinkedHashSet<Insertion>();
180d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (String key : map.keySet()) {
181d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        String qualifiedClassName = qualifiedOuterClassName + key;
182d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        forClass(cut, qualifiedClassName, set);
183d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
184d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return set;
185d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
186290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
187290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
18863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  /**
18963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * Add an {@link Insertion} to this collection.
19063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   */
191290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public void add(Insertion ins) {
192290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    InClassCriterion icc = ins.getCriteria().getInClass();
193d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    String k1 = "";
194d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    String k2 = "";
195d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<String, Set<Insertion>> map;
196d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Set<Insertion> set;
197d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
198290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    if (icc != null) {
199d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Pair<String, String> triple = nameSplit(icc.className);
200d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      k1 = triple.fst;
201d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      k2 = triple.snd;
202290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    }
203d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    map = store.get(k1);
204d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (map == null) {
205d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      map = new HashMap<String, Set<Insertion>>();
206d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      store.put(k1, map);
207290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    }
208d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    set = map.get(k2);
209d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (set == null) {
210d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      set = new LinkedHashSet<Insertion>();
211d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      map.put(k2, set);
212d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
213d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
214d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    size -= set.size();
215d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    set.add(ins);
216d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    size += set.size();
217290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
218290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
21963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  /**
22063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * Add all {@link Insertion}s in the given
22163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * {@link java.util.Collection} to this collection.
22263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   */
223290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public void addAll(Collection<? extends Insertion> c) {
224290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    for (Insertion ins : c) {
225290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      add(ins);
226290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    }
227290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
228290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
22963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  /**
23063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * Returns the number of {@link Insertion}s in this collection.
23163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   */
232290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public int size() {
233290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    return size;
234290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
235290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
236290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  @Override
237290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public Iterator<Insertion> iterator() {
238290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    return new Iterator<Insertion>() {
239d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private Iterator<Map<String, Set<Insertion>>> miter =
240d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          store.values().iterator();
241d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private Iterator<Set<Insertion>> siter =
242d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Collections.<Set<Insertion>>emptySet().iterator();
243d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private Iterator<Insertion> iiter =
244d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Collections.<Insertion>emptySet().iterator();
245290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
246290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      @Override
247290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      public boolean hasNext() {
248290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        if (iiter.hasNext()) { return true; }
249290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        while (siter.hasNext()) {
250290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown          iiter = siter.next().iterator();
251d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (iiter.hasNext()) { return true; }
252d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
253d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        while (miter.hasNext()) {
254d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          siter = miter.next().values().iterator();
255d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          while (siter.hasNext()) {
256d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            iiter = siter.next().iterator();
257d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (iiter.hasNext()) { return true; }
258290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown          }
259290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        }
260290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        return false;
261290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      }
262290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
263290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      @Override
264290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      public Insertion next() {
265290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        if (hasNext()) { return iiter.next(); }
266290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        throw new NoSuchElementException();
267290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      }
268290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
269290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      @Override
270290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      public void remove() {
271290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        throw new UnsupportedOperationException();
272290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      }
273290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    };
274290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
275567ba7d414e53451066008d98bbeacdfed876aceDan Brown
27663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  /**
27763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * Returns a {@link java.util.List} containing all {@link Insertion}s
27863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   * in this collection.
27963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown   */
280567ba7d414e53451066008d98bbeacdfed876aceDan Brown  public List<Insertion> toList() {
281567ba7d414e53451066008d98bbeacdfed876aceDan Brown    List<Insertion> list = new ArrayList<Insertion>(size);
282d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    for (Insertion ins : this) { list.add(ins); }
283567ba7d414e53451066008d98bbeacdfed876aceDan Brown    return null;
284567ba7d414e53451066008d98bbeacdfed876aceDan Brown  }
285d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
286d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  /*
287d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * This method detects inner type relationships among ASTPath-based
288d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * insertion specifications and organizes the insertions accordingly.
289d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * This step is necessary because 1) insertion proceeds from the end to
290d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * the beginning of the source and 2) the insertion location does not
291d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * always exist prior to the top-level type insertion.
292d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   */
293d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private Set<Insertion> organizeTypedInsertions(CompilationUnitTree cut,
294d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String className, Collection<Insertion> insertions) {
295d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    ASTRecordMap<TypedInsertion> map = new ASTRecordMap<TypedInsertion>();
296d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Set<Insertion> organized = new LinkedHashSet<Insertion>();
29763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    Set<Insertion> unorganized = new LinkedHashSet<Insertion>();
29863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    List<Insertion> list = new ArrayList<Insertion>();
29963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown
30063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    // First divide the insertions into three buckets: TypedInsertions
30163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    // on outer types (map), ASTPath-based insertions on local types
30263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    // (unorganized -- built as list and then sorted, since building as
303bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown    // a set spuriously removes "duplicates" according to the
30463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    // comparator), and everything else (organized -- where all
30563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    // eventually land).
306d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    for (Insertion ins : insertions) {
3078af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      if (ins.getInserted()) { continue; }
3088af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      Criteria criteria = ins.getCriteria();
309d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      GenericArrayLocationCriterion galc =
3108af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          criteria.getGenericArrayLocation();
3118af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      ASTPath p = criteria.getASTPath();
312d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (p == null || p.isEmpty()
313d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          || galc != null && !galc.getLocation().isEmpty()
3148af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          || ins instanceof CastInsertion
315d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          || ins instanceof CloseParenthesisInsertion) {
316d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        organized.add(ins);
317d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      } else {
318125d482f12943f55c03587db440b9519c102cf9fDan Brown        ASTRecord rec = new ASTRecord(cut, criteria.getClassName(),
3198af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            criteria.getMethodName(), criteria.getFieldName(), p);
3208af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        ASTPath.ASTEntry entry = rec.astPath.get(-1);
321bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown        Tree node;
322bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown
323bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown        if (entry.getTreeKind() == Tree.Kind.NEW_ARRAY
324bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown            && entry.childSelectorIs(ASTPath.TYPE)
325bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown            && entry.getArgument() == 0) {
326bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          ASTPath temp = rec.astPath.getParentPath();
327bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          node = ASTIndex.getNode(cut, rec.replacePath(temp));
328bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          node = node instanceof JCTree.JCNewArray
329bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              ? TypeTree.fromType(((JCTree.JCNewArray) node).type)
330bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              : null;
331bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown        } else {
332bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          node = ASTIndex.getNode(cut, rec);
333bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown        }
334bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown
3358af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        if (ins instanceof TypedInsertion) {
336d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          TypedInsertion tins = map.get(rec);
3378af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          if (ins instanceof NewInsertion) {
3388af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            NewInsertion nins = (NewInsertion) ins;
3398af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (entry.getTreeKind() == Tree.Kind.NEW_ARRAY
340bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                && entry.childSelectorIs(ASTPath.TYPE)) {
341bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              int a = entry.getArgument();
342bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              List<TypePathEntry> loc0 = new ArrayList<TypePathEntry>(a);
343bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              ASTRecord rec0 = null;
344bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              if (a == 0) {
345bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                rec0 = rec.replacePath(p.getParentPath());
346bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                Tree t = ASTIndex.getNode(cut, rec0);
347bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                if (t == null || t.toString().startsWith("{")) {
348bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  rec0 = null;
349bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                } else {
350bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  rec = rec0;
351bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  rec0 = rec.extend(Tree.Kind.NEW_ARRAY,
352bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                      ASTPath.TYPE, 0);
353bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                }
354bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              } else if (node != null
355bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  && !nins.getInnerTypeInsertions().isEmpty()) {
356bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                if (node.getKind() == Tree.Kind.IDENTIFIER) {
357bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  node = ASTIndex.getNode(cut,
358bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                      rec.replacePath(p.getParentPath()));
359bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                }
360bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                if ((node.getKind() == Tree.Kind.NEW_ARRAY
361bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                    || node.getKind() == Tree.Kind.ARRAY_TYPE)
362bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                    && !node.toString().startsWith("{")) {
363bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  rec = rec.replacePath(p.getParentPath());
364bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown
365bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  Collections.fill(loc0, TypePathEntry.ARRAY);
36652e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst                  // irec = rec;
36752e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst                  // if (node.getKind() == Tree.Kind.NEW_ARRAY) {
368bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  rec0 = rec.extend(Tree.Kind.NEW_ARRAY,
369bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                      ASTPath.TYPE, 0);
37052e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst                  // }
371bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                }
3728af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              }
3738af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
374bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              if (rec0 != null) {
3758af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                for (Insertion inner : nins.getInnerTypeInsertions()) {
3768af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  Criteria icriteria = inner.getCriteria();
3778af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  GenericArrayLocationCriterion igalc =
3788af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                      icriteria.getGenericArrayLocation();
3798af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  if (igalc != null) {
380bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                    ASTRecord rec1;
381bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                    int b = igalc.getLocation().size();
3828af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    List<TypePathEntry> loc =
383bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                        new ArrayList<TypePathEntry>(a + b);
3848af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    loc.addAll(loc0);
3858af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    loc.addAll(igalc.getLocation());
386bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                    rec1 = extendToInnerType(rec0, loc, node);
3878af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    icriteria.add(new GenericArrayLocationCriterion());
388bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                    icriteria.add(new ASTPathCriterion(rec1.astPath));
3898af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    inner.setInserted(false);
3908af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    organized.add(inner);
3918af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  }
3928af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                }
3938af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                nins.getInnerTypeInsertions().clear();
3948af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              }
3958af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
3968af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          }
397d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (tins == null) {
398d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            map.put(rec, (TypedInsertion) ins);
399eaf2af4be89d5a1729112ebf477079bee1014929Dan Brown          } else if (tins.getType().equals(((TypedInsertion) ins).getType())) {
400d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            mergeTypedInsertions(tins, (TypedInsertion) ins);
401d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
402d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } else {
4038af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          int d = newArrayInnerTypeDepth(p);
4048af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          if (d > 0) {
4058af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            ASTPath temp = p;
4068af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            while (!temp.isEmpty()
4078af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                && (node == null || node.getKind() != Tree.Kind.NEW_ARRAY)) {
4088af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              // TODO: avoid repeating work of newArrayInnerTypeDepth()
4098af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              temp = temp.getParentPath();
4108af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              node = ASTIndex.getNode(cut, rec.replacePath(temp));
4118af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
4128af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (node == null) {
4138af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              // TODO: ???
4148af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
4158af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            temp = temp.extend(
4168af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                new ASTPath.ASTEntry(Tree.Kind.NEW_ARRAY, ASTPath.TYPE, 0));
4178af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (node.toString().startsWith("{")) {
4188af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              TypedInsertion tins = map.get(rec.replacePath(temp));
4198af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              if (tins == null) {
4208af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                // TODO
4218af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              } else {
4228af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                tins.getInnerTypeInsertions().add(ins);
4238af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                ins.setInserted(true);
4248af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              }
4258af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            } else {
4268af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              List<? extends ExpressionTree> dims =
4278af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  ((NewArrayTree) node).getDimensions();
4288af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              ASTRecord irec = rec.replacePath(p.getParentPath())
4298af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  .extend(Tree.Kind.NEW_ARRAY, ASTPath.TYPE, 0);
4308af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              GenericArrayLocationCriterion igalc =
4318af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  criteria.getGenericArrayLocation();
4328af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              for (int i = 0 ; i < d; i++) {
4338af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                irec = irec.extend(Tree.Kind.ARRAY_TYPE, ASTPath.TYPE);
4348af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              }
4358af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              if (igalc != null) {
4368af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                List<TypePathEntry> loc = igalc.getLocation();
4378af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                if (!loc.isEmpty()) {
4388af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  try {
4398af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    Tree dim = dims.get(d-1);
4408af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    irec = extendToInnerType(irec, loc, dim);
4418af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    criteria.add(new ASTPathCriterion(irec.astPath));
4428af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                    criteria.add(new GenericArrayLocationCriterion());
4438af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  } catch (RuntimeException e) {}
4448af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                }
4458af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              }
4468af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
4478af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          }
44863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          list.add(ins);
449d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
450d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
451d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
45252e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst    // if (map.isEmpty()) {
45363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    //  organized.addAll(unorganized);
45463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    //  return organized;
45552e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst    // }
45663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    Collections.sort(list, byASTRecord);
45763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    unorganized.addAll(list);
45863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown
45963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    // Each Insertion in unorganized gets attached to a TypedInsertion
46063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    // in map if possible; otherwise, it gets dumped into organized.
461d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    for (Insertion ins : unorganized) {
462d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Criteria criteria = ins.getCriteria();
463d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String methodName = criteria.getMethodName();
464d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String fieldName = criteria.getFieldName();
465d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTPath ap1 = criteria.getASTPath();
466d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      List<TypePathEntry> tpes = new ArrayList<TypePathEntry>();
467d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (ap1 == null) {
468d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          // || methodName == null && fieldName == null)
469d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        organized.add(ins);
470d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        continue;
471d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
472d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
473d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // First find the relevant "top-level" insertion, if any.
474d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // ap0: path to top-level type; ap1: path to local type
47563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      ASTRecord rec;
476d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Tree.Kind kind;
477d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Deque<ASTPath> astack = new ArrayDeque<ASTPath>(ap1.size());
478d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTPath ap0 = ap1;
47963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      do {
480d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        astack.push(ap0);
481d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ap0 = ap0.getParentPath();
48263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      } while (!ap0.isEmpty());
48363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      do {
48463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        ap0 = astack.pop();
48563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        kind = ap0.get(-1).getTreeKind();
486125d482f12943f55c03587db440b9519c102cf9fDan Brown        rec = new ASTRecord(cut, className, methodName, fieldName, ap0);
48763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      } while (!(astack.isEmpty() || map.containsKey(rec)));
48863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown
48963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      TypedInsertion tins = map.get(rec);
4908af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      TreePath path = ASTIndex.getTreePath(cut, rec);
4918af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      Tree node = path == null ? null : path.getLeaf();
4928af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      if (node == null && ap0.isEmpty()) {
49363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        organized.add(ins);
49463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        continue;
495d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
496d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
4978af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      // Try to create a top-level insertion if none exists (e.g., if
4988af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      // there is an insertion for NewArray.type 1 but not for 0).
4998af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      if (tins == null) {
5008af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        GenericArrayLocationCriterion galc =
5018af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            criteria.getGenericArrayLocation();
5028af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        if (node == null) {
5038af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          // TODO: figure out from rec?
5048af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          organized.add(ins);
5058af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          continue;
5068af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        } else {
507dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          Tree t = path.getLeaf();
508dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          switch (t.getKind()) {
509dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          case NEW_ARRAY:
510dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            int d = 0;
511dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            ASTPath.ASTEntry e = ap1.get(-1);
512dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            List<TypePathEntry> loc = null;
513dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            List<Insertion> inners = new ArrayList<Insertion>();
514dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            Type type = TypeTree.conv(((JCTree.JCNewArray) t).type);
515dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            if (e.getTreeKind() == Tree.Kind.NEW_ARRAY) {
516dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              d += e.getArgument();
517dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            }
518dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            if (galc != null) {
519dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              loc = galc.getLocation();
520dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              int n = loc.size();
521dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              while (--n >= 0 && loc.get(n).tag == TypePathEntryKind.ARRAY) {
522dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                ++d;
5238af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              }
524dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              loc = n < 0 ? null : loc.subList(0, ++n);
5258af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
526dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            criteria.add(new ASTPathCriterion(
527dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                rec.astPath.getParentPath().extendNewArray(d)));
528dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            criteria.add(loc == null || loc.isEmpty()
529dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                ? new GenericArrayLocationCriterion()
530dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                : new GenericArrayLocationCriterion(
531dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                    new InnerTypeLocation(loc)));
532dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            inners.add(ins);
533dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            tins = new NewInsertion(type, criteria, inners);
534dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            tins.setInserted(true);
535dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            map.put(rec, tins);
53673f64a6a4e25b34d0b40cedf1a28b7e04b2d6f02Paulo Barros            break;
537dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          default:
538dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            break;
539dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          }
540dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          path = path.getParentPath();
5418af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
5428af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      }
5438af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
544d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // The sought node may or may not be found in the tree; if not, it
545d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // may need to be created later.  Use whatever part of the path
546d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // exists already to distinguish MEMBER_SELECT nodes that indicate
547d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // qualifiers from those that indicate local types.  Assume any
548d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // MEMBER_SELECTs in the AST path that don't correspond to
549d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // existing nodes are part of a type use.
55063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      if (node == null) {
551659c92f44b77fb68121f6af34565c59388369955Dan Brown        ASTPath ap = ap0;
552659c92f44b77fb68121f6af34565c59388369955Dan Brown        if (!ap.isEmpty()) {
553659c92f44b77fb68121f6af34565c59388369955Dan Brown          do {
554659c92f44b77fb68121f6af34565c59388369955Dan Brown            ap = ap.getParentPath();
555659c92f44b77fb68121f6af34565c59388369955Dan Brown            node = ASTIndex.getNode(cut, rec.replacePath(ap));
556659c92f44b77fb68121f6af34565c59388369955Dan Brown          } while (node == null && !ap.isEmpty());
557659c92f44b77fb68121f6af34565c59388369955Dan Brown        }
55863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        if (node == null) {
55963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          organized.add(ins);
56063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          continue;
56163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        }
56263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown
56363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        // find actual type
56463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        ClassSymbol csym = null;
56563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        switch (tins.getKind()) {
56663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        case CONSTRUCTOR:
56763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (node instanceof JCTree.JCMethodDecl) {
56863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            MethodSymbol msym = ((JCTree.JCMethodDecl) node).sym;
56963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            csym = (ClassSymbol) msym.owner;
57063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            node = TypeTree.fromType(csym.type);
57163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            break;
57263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          } else if (node instanceof JCTree.JCClassDecl) {
57363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            csym = ((JCTree.JCClassDecl) node).sym;
57463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            if (csym.owner instanceof ClassSymbol) {
57563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              csym = (ClassSymbol) csym.owner;
57663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              node = TypeTree.fromType(csym.type);
57763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              break;
57863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            }
579d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
58063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          throw new RuntimeException();
58163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        case NEW:
58263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (node instanceof JCTree.JCNewArray) {
58363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            if (node.toString().startsWith("{")) {
58463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              node = TypeTree.fromType(((JCTree.JCNewArray) node).type);
58563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              break;
58663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            } else {
58763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              organized.add(ins);
58863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              continue;
58963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            }
59063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          }
59163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          throw new RuntimeException();
59263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        case RECEIVER:
59363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (node instanceof JCTree.JCMethodDecl) {
59463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            JCTree.JCMethodDecl jmd = (JCTree.JCMethodDecl) node;
59563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            csym = (ClassSymbol) jmd.sym.owner;
59663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            if ("<init>".equals(jmd.name.toString())) {
59763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              csym = (ClassSymbol) csym.owner;
59863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            }
59963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          } else if (node instanceof JCTree.JCClassDecl) {
60063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            csym = ((JCTree.JCClassDecl) node).sym;
60163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          }
60263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (csym != null) {
60363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            node = TypeTree.fromType(csym.type);
60463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            break;
60563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          }
60673f64a6a4e25b34d0b40cedf1a28b7e04b2d6f02Paulo Barros          throw new RuntimeException();
60763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        default:
60863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          throw new RuntimeException();
609d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
610d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
611d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
612d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      /*
613d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * Inner types require special consideration due to the
614d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * structural differences between an AST that represents a type
615d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * (subclass of com.sun.source.Tree) and the type's logical
616d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * representation (subclass of type.Type).  The differences are
617d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * most prominent in the case of a type with a parameterized
618d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * local type.  For example, the AST for A.B.C<D> looks like
619d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * this:
620d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
621d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                     ParameterizedType
622d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                    /                 \
623d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *               MemberSelect       Identifier
624d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *              /            \           |
625d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *        MemberSelect      (Name)       D
626d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *         /      \           |
627d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *  Identifier   (Name)       C
628d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *        |        |
629d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *        A        B
630d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
631d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * (Technically, the Names are not AST nodes but rather
632d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * attributes of their parent MemberSelect nodes.)  The logical
633d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * representation seems more intuitive:
634d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
635d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *       DeclaredType
636d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *      /     |      \
637d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *    Name  Params  Inner
638d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *     |      |       |
639d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *     A      -  DeclaredType
640d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *              /     |      \
641d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *            Name  Params  Inner
642d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *             |      |       |
643d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *             B      -  DeclaredType
644d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                      /     |      \
645d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                    Name  Params  Inner
646d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                     |      |       |
647d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                     C      D       -
648d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
649d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * The opposing "chirality" of local type nesting means that the
650d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * usual recursive descent strategy doesn't work for finding a
651d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * logical type path in an AST; in effect, local types have to
652d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * be "turned inside-out".
653d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
654d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * Worse yet, the actual tree structure may not exist in the tree!
655d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * It is possible to recover the actual type from the symbol
656d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * table, but the methods to create AST nodes are not visible
657d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * here.  Hence, the conversion relies on custom implementations
658d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * of the interfaces in com.sun.source.tree.Tree, which are
659d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * defined in the local class TypeTree.
660d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       */
661d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      int i = ap0.size();
662d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      int n = ap1.size();
66363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      int actualDepth = 0;  // inner type levels seen
66463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      int expectedDepth = 0;  // inner type levels anticipated
665d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
666d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // skip any declaration nodes
667d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      while (i < n) {
668d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ASTPath.ASTEntry entry = ap1.get(i);
669d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        kind = entry.getTreeKind();
670d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (kind != Tree.Kind.METHOD && kind != Tree.Kind.VARIABLE) {
671d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
672d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
673d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ++i;
674d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
675d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
67663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      // now build up the type path in JVM's format
677d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      while (i < n) {
678d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ASTPath.ASTEntry entry = ap1.get(i);
679d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        rec = rec.extend(entry);
680d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        kind = entry.getTreeKind();
681d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
68263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        while (node.getKind() == Tree.Kind.ANNOTATED_TYPE) {  // skip
68363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          node = ((AnnotatedTypeTree) node).getUnderlyingType();
68463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        }
68563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        if (expectedDepth == 0) {
68663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          expectedDepth = localDepth(node);
68763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        }
68863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown
689d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        switch (kind) {
690d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case ARRAY_TYPE:
69163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (expectedDepth == 0 && node.getKind() == kind) {
692d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            node = ((ArrayTypeTree) node).getType();
69363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            while (--actualDepth >= 0) {
69463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              tpes.add(TypePathEntry.INNER_TYPE);
69563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            }
696d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            tpes.add(TypePathEntry.ARRAY);
697d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            break;
698d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
699d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
700d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
701d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case MEMBER_SELECT:
70263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (--expectedDepth >= 0) {  // otherwise, shouldn't have MEMBER_SELECT
70363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            node = ((MemberSelectTree) node).getExpression();
70463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            ++actualDepth;
70563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            break;
70663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          }
70763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          throw new RuntimeException();
70863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown
70963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        case NEW_ARRAY:
710dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          assert tpes.isEmpty();
711dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          ap0 = ap0.add(new ASTPath.ASTEntry(Tree.Kind.NEW_ARRAY,
712dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              ASTPath.TYPE, 0));
71363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (expectedDepth == 0 && node.getKind() == kind) {
71463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            if (node instanceof JCTree.JCNewArray) {
715dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              int arg = entry.getArgument();
716dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              if (arg > 0) {
717dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                node = ((JCTree.JCNewArray) node).elemtype;
718dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                tpes.add(TypePathEntry.ARRAY);
719dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                while (--arg > 0 && node instanceof JCTree.JCArrayTypeTree) {
720dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                  node = ((JCTree.JCArrayTypeTree) node).elemtype;
721dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                  tpes.add(TypePathEntry.ARRAY);
722dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                }
723dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                if (arg > 0) { throw new RuntimeException(); }
724dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              } else {
725dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                node = TypeTree.fromType(((JCTree.JCNewArray) node).type);
726dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              }
72763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            } else {
7288af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              throw new RuntimeException("NYI");  // TODO
72963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            }
73063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            break;
731d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
732d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
733d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
734d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case PARAMETERIZED_TYPE:
73563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (node.getKind() == kind) {
736d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            ParameterizedTypeTree ptt = (ParameterizedTypeTree) node;
737d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (entry.childSelectorIs(ASTPath.TYPE)) {
738d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              node = ptt.getType();
73963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              break;  // ParameterizedType.type is "transparent" wrt type path
74063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            } else if (expectedDepth == 0
74163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                && entry.childSelectorIs(ASTPath.TYPE_ARGUMENT)) {
742d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              List<? extends Tree> typeArgs = ptt.getTypeArguments();
743d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              int j = entry.getArgument();
744d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (j >= 0 && j < typeArgs.size()) {
74563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                // make sure any inner types are accounted for
74663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                actualDepth = 0;
74763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                expectedDepth = localDepth(ptt.getType());
74863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                while (--expectedDepth >= 0) {
74963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                  tpes.add(TypePathEntry.INNER_TYPE);
75063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                }
751d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                node = typeArgs.get(j);
752d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                tpes.add(
753d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                    new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, j));
754d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                break;
755d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              }
756d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
757d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
758d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
759d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
760d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case UNBOUNDED_WILDCARD:
76163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (ASTPath.isWildcard(node.getKind())) {
76263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            if (expectedDepth == 0
76363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                && (i < 1
76463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                    || ap1.get(i-1).getTreeKind() != Tree.Kind.INSTANCE_OF)
765d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                && (i < 2
766d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                    || ap1.get(i-2).getTreeKind() != Tree.Kind.ARRAY_TYPE)) {
76763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              while (--actualDepth >= 0) {
76863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown                tpes.add(TypePathEntry.INNER_TYPE);
76963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              }
77063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown              tpes.add(TypePathEntry.WILDCARD);
771d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              break;
77263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            }
773d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
77463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          throw new RuntimeException();
775d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
776d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        default:
777d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          node = ASTIndex.getNode(cut, rec);
778d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
779d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
780d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
781d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ++i;
782d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
783d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
78463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      while (--actualDepth >= 0) {
78563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        tpes.add(TypePathEntry.INNER_TYPE);
78663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown      }
78763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown
788dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      organized.add(ins);
789d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (tpes.isEmpty()) {
79052e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst        // assert ap1.equals(ap0) && !map.containsKey(ap0);
791dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown//        organized.add(ins);
79252e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst        // map.put(rec, (TypedInsertion) ins);
793d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      } else {
79463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        criteria.add(new ASTPathCriterion(ap0));
79563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        criteria.add(new GenericArrayLocationCriterion(
79663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            new InnerTypeLocation(tpes)));
79763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        tins.getInnerTypeInsertions().add(ins);
798d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
799d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
800d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    organized.addAll(map.values());
801d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return organized;
802d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
803d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
8048af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  private int newArrayInnerTypeDepth(ASTPath path) {
8058af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    int d = 0;
8068af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    if (path != null) {
8078af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      while (!path.isEmpty()) {
8088af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        ASTPath.ASTEntry entry = path.get(-1);
8098af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        switch (entry.getTreeKind()) {
8108af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        case ANNOTATED_TYPE:
8118af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        case MEMBER_SELECT:
8128af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        case PARAMETERIZED_TYPE:
8138af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        case UNBOUNDED_WILDCARD:
8148af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          d = 0;
8158af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          break;
8168af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        case ARRAY_TYPE:
8178af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          ++d;
8188af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          break;
8198af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        case NEW_ARRAY:
8208af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          if (entry.childSelectorIs(ASTPath.TYPE) && entry.hasArgument()) {
8218af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            d += entry.getArgument();
8228af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          }
8238af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          return d;
8248af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        default:
8258af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          return 0;
8268af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
8278af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        path = path.getParentPath();
8288af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      }
8298af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    }
8308af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    return 0;
8318af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  }
8328af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
8338af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  /**
8348af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * Find an {@link ASTRecord} for the tree corresponding to a nested
8358af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * type of the type (use) to which the given record corresponds.
8368af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   *
8378af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * @param rec record of (outer) type AST to be annotated
8388af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * @param loc inner type path
8398af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * @return record that locates the (nested) type in the source
8408af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   */
8418af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  private ASTRecord extendToInnerType(ASTRecord rec, List<TypePathEntry> loc) {
8428af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    ASTRecord r = rec;
8438af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    Iterator<TypePathEntry> iter = loc.iterator();
8448af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    int depth = 0;
8458af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
8468af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    while (iter.hasNext()) {
8478af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      TypePathEntry tpe = iter.next();
8488af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      switch (tpe.tag) {
8498af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case ARRAY:
8508af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        while (depth-- > 0) {
8518af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          r = r.extend(Tree.Kind.MEMBER_SELECT, ASTPath.EXPRESSION);
8528af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
8538af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        r = r.extend(Tree.Kind.ARRAY_TYPE, ASTPath.TYPE);
8548af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        break;
8558af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case INNER_TYPE:
8568af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        ++depth;
8578af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        break;
8588af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case TYPE_ARGUMENT:
8598af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        depth = 0;
8608af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        r = r.extend(Tree.Kind.PARAMETERIZED_TYPE, ASTPath.TYPE_ARGUMENT,
8618af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            tpe.arg);
8628af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        break;
8638af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case WILDCARD:
8648af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        while (depth-- > 0) {
8658af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          r = r.extend(Tree.Kind.MEMBER_SELECT, ASTPath.EXPRESSION);
8668af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
8678af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        r = r.extend(Tree.Kind.UNBOUNDED_WILDCARD, ASTPath.BOUND);
8688af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        break;
8698af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      default:
8708af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        throw new RuntimeException();
8718af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      }
8728af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    }
8738af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    while (depth-- > 0) {
8748af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      r = r.extend(Tree.Kind.MEMBER_SELECT, ASTPath.EXPRESSION);
8758af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    }
8768af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    return r;
8778af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  }
8788af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
8798af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  /**
8808af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * Find an {@link ASTRecord} for the tree corresponding to a nested
8818af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * type of the type (use) to which the given tree and record
8828af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * correspond.
8838af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   *
8848af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * @param rec record that locates {@code node} in the source
8858af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * @param loc inner type path
8868af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * @param node starting point for inner type path
8878af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   * @return record that locates the nested type in the source
8888af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown   */
8898af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  private ASTRecord extendToInnerType(ASTRecord rec,
8908af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      List<TypePathEntry> loc, Tree node) {
8918af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    ASTRecord r = rec;
8928af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    Tree t = node;
8938af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    Iterator<TypePathEntry> iter = loc.iterator();
8948af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    TypePathEntry tpe = iter.next();
8958af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
8968af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brownouter:
8978af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    while (true) {
8988af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      int d = localDepth(node);
8998af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
9008af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      switch (t.getKind()) {
9018af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case ANNOTATED_TYPE:
9028af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        r = r.extend(Tree.Kind.ANNOTATED_TYPE, ASTPath.TYPE);
9038af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        t = ((JCTree.JCAnnotatedType) t).getUnderlyingType();
9048af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        break;
9058af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
9068af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case ARRAY_TYPE:
9078af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        if (d == 0 && tpe.tag == TypePathEntryKind.ARRAY) {
908bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          int a = 0;
909bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          if (!r.astPath.isEmpty()) {
910bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown            ASTPath.ASTEntry e = r.astPath.get(-1);
911bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown            if (e.getTreeKind() == Tree.Kind.NEW_ARRAY
912bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                && e.childSelectorIs(ASTPath.TYPE)) {
913bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              a = 1 + e.getArgument();
914bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown            }
915bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          }
916bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          r = a > 0
917bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              ? r.replacePath(r.astPath.getParentPath())
918bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown                  .extend(Tree.Kind.NEW_ARRAY, ASTPath.TYPE, a)
919bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown              : r.extend(Tree.Kind.ARRAY_TYPE, ASTPath.TYPE);
920bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          t = ((ArrayTypeTree) t).getType();
9218af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          break;
9228af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
9238af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        throw new RuntimeException();
9248af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
9258af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case MEMBER_SELECT:
9268af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        if (d > 0 && tpe.tag == TypePathEntryKind.INNER_TYPE) {
9278af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          Tree temp = t;
9288af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          do {
9298af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            temp = ((JCTree.JCFieldAccess) temp).getExpression();
9308af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (!iter.hasNext()) {
9318af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              do {
9328af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                r = r.extend(Tree.Kind.MEMBER_SELECT, ASTPath.EXPRESSION);
9338af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              } while (--d > 0);
9348af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              return r;
9358af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
9368af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            tpe = iter.next();
9378af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (--d == 0) {
9388af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              continue outer;  // avoid next() at end of loop
9398af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
9408af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          } while (tpe.tag == TypePathEntryKind.INNER_TYPE);
9418af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
9428af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        throw new RuntimeException();
9438af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
9448af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case NEW_ARRAY:
9458af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        if (d == 0) {
9468af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          if (!r.astPath.isEmpty()) {
9478af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            ASTPath.ASTEntry e = r.astPath.get(-1);
9488af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (e.getTreeKind() == Tree.Kind.NEW_ARRAY) {
9498af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              int a = 0;
9508af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              while (tpe.tag == TypePathEntryKind.ARRAY) {
9518af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                ++a;
9528af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                if (!iter.hasNext()) { break; }
9538af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                tpe = iter.next();
9548af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              }
9558af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              r = r.replacePath(r.astPath.getParentPath())
9568af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                  .extend(Tree.Kind.NEW_ARRAY, ASTPath.TYPE, a);
9578af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              break;
9588af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
9598af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          }
9608af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          r = r.extend(Tree.Kind.ARRAY_TYPE, ASTPath.TYPE);
9618af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          t = ((JCTree.JCArrayTypeTree) t).getType();
9628af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          break;
9638af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
9648af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        throw new RuntimeException();
9658af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
9668af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case PARAMETERIZED_TYPE:
9678af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        if (d == 0 && tpe.tag == TypePathEntryKind.TYPE_ARGUMENT) {
9688af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          r = r.extend(Tree.Kind.PARAMETERIZED_TYPE,
9698af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              ASTPath.TYPE_ARGUMENT, tpe.arg);
9708af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          t = ((JCTree.JCTypeApply) t).getTypeArguments().get(tpe.arg);
9718af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          break;
9728af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        } else if (d > 0 && tpe.tag == TypePathEntryKind.INNER_TYPE) {
9738af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          Tree temp = ((JCTree.JCTypeApply) t).getType();
9748af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          r = r.extend(Tree.Kind.PARAMETERIZED_TYPE, ASTPath.TYPE);
9758af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          t = temp;
9768af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          do {
9778af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            temp = ((JCTree.JCFieldAccess) temp).getExpression();
9788af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (!iter.hasNext()) {
9798af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              do {
9808af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown                r = r.extend(Tree.Kind.MEMBER_SELECT, ASTPath.EXPRESSION);
9818af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              } while (--d > 0);
9824ae81f26445bc9397bd3e1edb062e0388ed82a6fMichael Ernst              return r;
9838af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
9848af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            tpe = iter.next();
9858af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            if (--d == 0) {
9868af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown              continue outer;  // avoid next() at end of loop
9878af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown            }
9888af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          } while (tpe.tag == TypePathEntryKind.INNER_TYPE);
9898af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
9908af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        throw new RuntimeException();
9918af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
9928af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case EXTENDS_WILDCARD:
9938af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case SUPER_WILDCARD:
9948af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      case UNBOUNDED_WILDCARD:
9958af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        if (tpe.tag == TypePathEntryKind.WILDCARD) {
9968af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          t = ((JCTree.JCWildcard) t).getBound();
9978af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown          break;
9988af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        }
9998af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        throw new RuntimeException();
10008af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
10018af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      default:
1002bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown        if (iter.hasNext()) {
1003bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown          throw new RuntimeException();
1004bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown        }
10058af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      }
10068af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
10078af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      if (!iter.hasNext()) { return r; }
10088af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown      tpe = iter.next();
10098af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown    }
10108af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown  }
10118af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown
101263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  // merge annotations, assuming types are structurally identical
1013d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private void mergeTypedInsertions(TypedInsertion ins0, TypedInsertion ins1) {
1014d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    mergeTypes(ins0.getType(), ins1.getType());
1015d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
1016d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1017d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private void mergeTypes(Type t0, Type t1) {
1018d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (t0 == t1) { return; }
1019d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    switch (t0.getKind()) {
1020d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    case ARRAY:
1021d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      {
1022d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ArrayType at0 = (ArrayType) t0;
1023d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ArrayType at1 = (ArrayType) t1;
1024d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        mergeTypes(at0.getComponentType(), at1.getComponentType());
1025d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return;
1026d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1027d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    case BOUNDED:
1028d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      {
1029d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        BoundedType bt0 = (BoundedType) t0;
1030d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        BoundedType bt1 = (BoundedType) t1;
1031d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (bt0.getBoundKind() != bt1.getBoundKind()) { break; }
1032d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        mergeTypes(bt0.getBound(), bt1.getBound());
10334f36ca57e86fb378d83d121bdc424e8477196bd6Michael Ernst        mergeTypes(bt0.getName(), bt1.getName());
1034d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return;
1035d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1036d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    case DECLARED:
1037d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      {
1038d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        DeclaredType dt0 = (DeclaredType) t0;
1039d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        DeclaredType dt1 = (DeclaredType) t1;
1040d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        List<Type> tps0 = dt0.getTypeParameters();
1041d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        List<Type> tps1 = dt1.getTypeParameters();
1042d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        int n = tps0.size();
1043d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (tps1.size() != n) { break; }
1044d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        mergeTypes(dt0.getInnerType(), dt1.getInnerType());
1045d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        for (String anno : dt1.getAnnotations()) {
1046d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (!dt0.getAnnotations().contains(anno)) {
1047d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            dt0.addAnnotation(anno);
1048d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
1049d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1050d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        for (int i = 0; i < n; i++) {
1051d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          mergeTypes(tps0.get(i), tps1.get(i));
1052d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1053d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return;
1054d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1055d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1056d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    throw new RuntimeException();
1057d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
1058d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
105963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  // Returns the depth of the innermost local type of a type AST.
1060d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private int localDepth(Tree node) {
1061d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Tree t = node;
1062d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    int n = 0;
1063d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownloop:
1064d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    while (t != null) {
1065d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (t.getKind()) {
1066d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case ANNOTATED_TYPE:
1067d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((AnnotatedTypeTree) t).getUnderlyingType();
1068d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1069d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case MEMBER_SELECT:
107063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        if (t instanceof JCTree.JCFieldAccess) {
107163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          JCTree.JCFieldAccess jfa = (JCTree.JCFieldAccess) t;
107263edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          if (jfa.sym.kind == Kinds.PCK) {
107363edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            t = jfa.getExpression();
107463edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown            continue;
107563edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown          }
107663edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        }
107763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        t = ((MemberSelectTree) t).getExpression();
107863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        ++n;
107963edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        break;
1080d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
1081d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break loop;
1082d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1083d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1084d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return n;
1085d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
1086d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
108763edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  // Provides an additional level of indexing.
1088d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  class ASTRecordMap<E> implements Map<ASTRecord, E> {
1089d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<ASTRecord, SortedMap<ASTPath, E>> back;
1090d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1091d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    ASTRecordMap() {
1092d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      back = new HashMap<ASTRecord, SortedMap<ASTPath, E>>();
1093d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1094d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1095d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    private SortedMap<ASTPath, E> getMap(ASTRecord rec) {
1096d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord key = rec.replacePath(ASTPath.empty());
1097d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = back.get(key);
1098d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (map == null) {
1099d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        map = new TreeMap<ASTPath, E>();
1100d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        back.put(key, map);
1101d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1102d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map;
1103d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1104d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1105d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1106d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public int size() {
1107d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      int n = 0;
1108d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (SortedMap<ASTPath, E> map : back.values()) {
1109d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        n += map.size();
1110d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1111d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return n;
1112d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1113d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1114d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1115d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public boolean isEmpty() {
1116d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return size() == 0;
1117d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1118d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1119d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1120d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public boolean containsKey(Object key) {
1121d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = (ASTRecord) key;
1122d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> m = getMap(rec);
1123d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return m != null && m.containsKey(rec.astPath);
1124d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1125d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1126d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1127d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public boolean containsValue(Object value) {
1128d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @SuppressWarnings("unchecked")
1129d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      E e = (E) value;
1130d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (SortedMap<ASTPath, E> map : back.values()) {
1131d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (map.containsValue(e)) { return true; }
1132d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1133d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return false;
1134d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1135d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1136d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1137d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public E get(Object key) {
1138d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = (ASTRecord) key;
1139d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = getMap(rec);
1140d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map == null ? null : map.get(rec.astPath);
1141d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1142d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1143d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1144d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public E put(ASTRecord key, E value) {
114573f64a6a4e25b34d0b40cedf1a28b7e04b2d6f02Paulo Barros      ASTRecord rec = key;
1146d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = getMap(rec);
1147d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map == null ? null : map.put(rec.astPath, value);
1148d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1149d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1150d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1151d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public E remove(Object key) {
1152d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = (ASTRecord) key;
1153d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = getMap(rec);
1154d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map == null ? null : map.remove(rec.astPath);
1155d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1156d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1157d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1158d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public void putAll(Map<? extends ASTRecord, ? extends E> m) {
1159d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (Map.Entry<? extends ASTRecord, ? extends E> entry : m.entrySet()) {
1160d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        put(entry.getKey(), entry.getValue());
1161d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1162d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1163d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1164d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1165d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public void clear() {
1166d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      back.clear();
1167d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1168d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1169d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1170d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public Set<ASTRecord> keySet() {
1171d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return back.keySet();
1172d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1173d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1174d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1175d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public Collection<E> values() {
1176d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Set<E> ret = new LinkedHashSet<E>();
1177d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (SortedMap<ASTPath, E> m : back.values()) {
1178d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ret.addAll(m.values());
1179d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1180d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return ret;
1181d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1182d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1183d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
1184d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public Set<Map.Entry<ASTRecord, E>> entrySet() {
1185d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      final int size = size();
1186d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return new AbstractSet<Map.Entry<ASTRecord, E>>() {
1187d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        @Override
1188d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        public Iterator<Map.Entry<ASTRecord, E>> iterator() {
1189d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          return new Iterator<Map.Entry<ASTRecord, E>>() {
1190d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            Iterator<Map.Entry<ASTRecord, SortedMap<ASTPath, E>>> iter0 =
1191d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                back.entrySet().iterator();
1192d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            Iterator<Map.Entry<ASTPath, E>> iter1 =
1193d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                Collections.<Map.Entry<ASTPath, E>>emptyIterator();
1194d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            ASTRecord rec = null;
1195d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1196d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            @Override
1197d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            public boolean hasNext() {
1198d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (iter1.hasNext()) { return true; }
1199d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              while (iter0.hasNext()) {
1200d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                Map.Entry<ASTRecord, SortedMap<ASTPath, E>> entry =
1201d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                    iter0.next();
1202d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                rec = entry.getKey();
1203d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                iter1 = entry.getValue().entrySet().iterator();
1204d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                if (iter1.hasNext()) { return true; }
1205d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              }
1206d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              iter1 = Collections.<Map.Entry<ASTPath, E>>emptyIterator();
1207d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              return false;
1208d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
1209d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1210d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            @Override
1211d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            public Map.Entry<ASTRecord, E> next() {
1212d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (!hasNext()) { throw new NoSuchElementException(); }
1213d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              final Map.Entry<ASTPath, E> e0 = iter1.next();
1214d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              return new Map.Entry<ASTRecord, E>() {
1215d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                final ASTRecord key = rec.replacePath(e0.getKey());
1216d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                final E val = e0.getValue();
1217d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                @Override public ASTRecord getKey() { return key; }
1218d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                @Override public E getValue() { return val; }
1219d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                @Override public E setValue(E value) {
1220d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                  throw new UnsupportedOperationException();
1221d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                }
1222d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              };
1223d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
1224a53f379c5f7e30c61896b73ab56974dc15bbce7dDan Brown
1225a53f379c5f7e30c61896b73ab56974dc15bbce7dDan Brown            @Override
1226a53f379c5f7e30c61896b73ab56974dc15bbce7dDan Brown            public void remove() {
1227a53f379c5f7e30c61896b73ab56974dc15bbce7dDan Brown              throw new UnsupportedOperationException();
1228a53f379c5f7e30c61896b73ab56974dc15bbce7dDan Brown            }
1229d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          };
1230d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1231d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1232d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        @Override
1233d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        public int size() { return size; }
1234d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      };
1235d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1236d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
1237d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
123863edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown  // Simple AST implementation used only in determining type paths.
1239bb22bd2c7b16d78b88334ddfb534c74de11a6fcbDan Brown  static abstract class TypeTree implements ExpressionTree {
124063edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown    private static Map<String, TypeTag> primTags =
124163edc7df4f710c01cef3691b4468e564a9d1d912Dan Brown        new HashMap<String, TypeTag>();
1242d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    {
1243d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("byte", TypeTag.BYTE);
1244d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("char", TypeTag.CHAR);
1245d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("short", TypeTag.SHORT);
1246d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("long", TypeTag.LONG);
1247d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("float", TypeTag.FLOAT);
1248d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("int", TypeTag.INT);
1249d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("double", TypeTag.DOUBLE);
1250d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("boolean", TypeTag.BOOLEAN);
1251d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1252d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1253dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown    static TypeTree fromJCTree(JCTree jt) {
1254dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      if (jt != null) {
1255dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        Kind kind = jt.getKind();
1256dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        switch (kind) {
1257dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case ANNOTATED_TYPE:
1258dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          return fromJCTree(
1259dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              ((JCTree.JCAnnotatedType) jt).getUnderlyingType());
1260dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case IDENTIFIER:
1261dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          return new IdenT(
1262dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              ((JCTree.JCIdent) jt).sym.getSimpleName().toString());
1263dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case ARRAY_TYPE:
1264dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          return new ArrT(
1265dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              fromJCTree(((JCTree.JCArrayTypeTree) jt).getType()));
1266dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case MEMBER_SELECT:
1267dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          return new LocT(
1268dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              fromJCTree(((JCTree.JCFieldAccess) jt).getExpression()),
1269dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              ((JCTree.JCFieldAccess) jt).getIdentifier());
1270dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case EXTENDS_WILDCARD:
1271dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case SUPER_WILDCARD:
1272dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          return new WildT(kind,
1273dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              fromJCTree(((JCTree.JCWildcard) jt).getBound()));
1274dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case UNBOUNDED_WILDCARD:
1275dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          return new WildT();
1276dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        case PARAMETERIZED_TYPE:
1277dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          com.sun.tools.javac.util.List<JCExpression> typeArgs =
1278dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            ((JCTree.JCTypeApply) jt).getTypeArguments();
1279dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          List<Tree> args = new ArrayList<Tree>(typeArgs.size());
1280dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          for (JCTree.JCExpression typeArg : typeArgs) {
1281dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            args.add(fromJCTree(typeArg));
1282dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          }
1283dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          return new ParT(
1284dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              fromJCTree(((JCTree.JCTypeApply) jt).getType()),
1285dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown              args);
1286dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        default:
1287dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          break;
1288dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        }
1289dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      }
1290dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      return null;
1291dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown    }
1292dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown
1293d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static TypeTree fromType(final Type type) {
1294d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (type.getKind()) {
1295d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case ARRAY:
1296d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final ArrayType atype = (ArrayType) type;
1297d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final TypeTree componentType = fromType(atype.getComponentType());
1298d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new ArrT(componentType);
1299d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case BOUNDED:
1300d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final BoundedType btype = (BoundedType) type;
1301d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final BoundedType.BoundKind bk = btype.getBoundKind();
13024f36ca57e86fb378d83d121bdc424e8477196bd6Michael Ernst        final String bname = btype.getName().getName();
1303d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final TypeTree bound = fromType(btype.getBound());
1304d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new Param(bname, bk, bound);
1305d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case DECLARED:
1306d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final DeclaredType dtype = (DeclaredType) type;
1307d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (dtype.isWildcard()) {
1308d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          return new WildT();
1309d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } else {
1310d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          final String dname = dtype.getName();
1311d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          TypeTag typeTag = primTags.get(dname);
1312d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (typeTag == null) {
1313d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            final TypeTree base = new IdenT(dname);
1314d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            TypeTree ret = base;
1315d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            List<Type> params = dtype.getTypeParameters();
1316d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            DeclaredType inner = dtype.getInnerType();
1317d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (!params.isEmpty()) {
1318d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              final List<Tree> typeArgs = new ArrayList<Tree>(params.size());
1319d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              for (Type t : params) { typeArgs.add(fromType(t)); }
1320d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              ret = new ParT(base, typeArgs);
1321d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
1322d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            return inner == null ? ret : meld(fromType(inner), ret);
1323d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          } else {
1324d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            final TypeKind typeKind = typeTag.getPrimitiveTypeKind();
1325d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            return new PrimT(typeKind);
1326d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
1327d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1328d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
1329d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        throw new RuntimeException("unknown type kind " + type.getKind());
1330d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1331d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1332d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1333d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static TypeTree fromType(final com.sun.tools.javac.code.Type type) {
1334d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return fromType(conv(type));
1335d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1336d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1337d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    /**
1338d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown     * @param jtype
1339d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown     * @return
1340d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown     */
1341920f9e69de5097b03adc702e5ffc60c3b8ca6628Dan Brown    static Type conv(final com.sun.tools.javac.code.Type jtype) {
1342d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Type type = null;
1343d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      DeclaredType d;
1344d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      com.sun.tools.javac.code.Type t;
1345d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (jtype.getKind()) {
1346d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case ARRAY:
1347d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((com.sun.tools.javac.code.Type.ArrayType) jtype).elemtype;
1348d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = new ArrayType(conv(t));
1349d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1350d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case DECLARED:
1351d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = jtype;
1352d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        d = null;
1353d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        do {
1354d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          DeclaredType d0 = d;
1355d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          com.sun.tools.javac.code.Type.ClassType ct =
1356d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              (com.sun.tools.javac.code.Type.ClassType) t;
1357d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          d = new DeclaredType(ct.tsym.name.toString());
1358d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          d.setInnerType(d0);
1359d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          d0 = d;
1360d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          for (com.sun.tools.javac.code.Type a : ct.getTypeArguments()) {
1361d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            d.addTypeParameter(conv(a));
1362d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
1363d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          t = ct.getEnclosingType();
1364d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } while (t.getKind() == TypeKind.DECLARED);
1365d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = d;
1366d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1367d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case WILDCARD:
1368d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        BoundedType.BoundKind k;
1369d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((com.sun.tools.javac.code.Type.WildcardType) jtype).bound;
1370d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        switch (((com.sun.tools.javac.code.Type.WildcardType) jtype).kind) {
1371d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case EXTENDS:
1372d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          k = BoundedType.BoundKind.EXTENDS;
1373d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
1374d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case SUPER:
1375d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          k = BoundedType.BoundKind.SUPER;
1376d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
1377d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case UNBOUND:
1378d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          k = null;
1379dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          type = new DeclaredType("?");
1380d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
1381d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        default:
1382d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
1383d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1384dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        if (k != null) {
1385dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          d = new DeclaredType(jtype.tsym.name.toString());
1386dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown          type = new BoundedType(d, k, (DeclaredType) conv(t));
1387dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        }
1388d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1389d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case TYPEVAR:
1390d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((com.sun.tools.javac.code.Type.TypeVar) jtype).getUpperBound();
139133bacff74b22abfe0605a20e90b6486b37a8080eDan Brown        type = conv(t);
139233bacff74b22abfe0605a20e90b6486b37a8080eDan Brown        if (type.getKind() == Type.Kind.DECLARED) {
139333bacff74b22abfe0605a20e90b6486b37a8080eDan Brown          type = new BoundedType(new DeclaredType(jtype.tsym.name.toString()),
139433bacff74b22abfe0605a20e90b6486b37a8080eDan Brown              BoundedType.BoundKind.EXTENDS, (DeclaredType) type);
139533bacff74b22abfe0605a20e90b6486b37a8080eDan Brown        }  // otherwise previous conv should have been here already
1396d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1397d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case INTERSECTION:
13988af822a8f4c2b07c3e7c14c30f2814cd8000542fDan Brown        t = jtype.tsym.erasure_field;  // ???
1399d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = new DeclaredType(t.tsym.name.toString());
1400d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1401d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case UNION:
1402d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        // TODO
1403d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1404d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case BOOLEAN:
1405d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case BYTE:
1406d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case CHAR:
1407d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case DOUBLE:
1408d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case LONG:
1409d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case SHORT:
1410d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case FLOAT:
1411d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case INT:
14124ae81f26445bc9397bd3e1edb062e0388ed82a6fMichael Ernst        type = new DeclaredType(jtype.tsym.name.toString());
1413d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
141452e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst      // case ERROR:
141552e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst      // case EXECUTABLE:
141652e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst      // case NONE:
141752e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst      // case NULL:
141852e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst      // case OTHER:
141952e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst      // case PACKAGE:
142052e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst      // case VOID:
1421d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
1422d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
1423d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1424d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return type;
1425d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1426d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1427d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    private static TypeTree meld(final TypeTree t0, final TypeTree t1) {
1428d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (t0.getKind()) {
1429d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case IDENTIFIER:
1430d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        IdenT it = (IdenT) t0;
1431d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new LocT(t1, it.getName());
1432d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case MEMBER_SELECT:
1433d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        LocT lt = (LocT) t0;
1434d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new LocT(meld(lt.getExpression(), t1), lt.getIdentifier());
1435d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case PARAMETERIZED_TYPE:
1436d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ParT pt = (ParT) t0;
1437d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new ParT(meld(pt.getType(), t1), pt.getTypeArguments());
1438d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
1439d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        throw new IllegalArgumentException("unexpected type " + t0);
1440d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1441d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1442d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1443d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class ArrT extends TypeTree implements ArrayTypeTree {
1444d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeTree componentType;
1445d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1446d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ArrT(TypeTree componentType) {
1447d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.componentType = componentType;
1448d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1449d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1450d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1451d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.ARRAY_TYPE; }
1452d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1453d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1454d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1455d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitArrayType(this, data);
1456d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1457d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1458d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1459d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeTree getType() { return componentType; }
1460d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1461d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1462d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return componentType + "[]"; }
1463d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1464d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1465d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class LocT extends TypeTree implements MemberSelectTree {
1466d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeTree expr;
1467d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final Name name;
1468d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1469d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      LocT(TypeTree expr, Name name) {
1470d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.expr = expr;
1471d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.name = name;
1472d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1473d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1474d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1475d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.MEMBER_SELECT; }
1476d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1477d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1478d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1479d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitMemberSelect(this, data);
1480d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1481d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1482d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1483d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeTree getExpression() { return expr; }
1484d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1485d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1486d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Name getIdentifier() { return name; }
1487d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1488d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1489d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return expr + "." + name; }
1490d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1491d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1492d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class ParT extends TypeTree implements ParameterizedTypeTree {
1493d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeTree base;
1494d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final List<? extends Tree> typeArgs;
1495d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1496d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ParT(TypeTree base, List<? extends Tree> typeArgs) {
1497d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.base = base;
1498d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.typeArgs = typeArgs;
1499d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1500d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1501d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1502d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.PARAMETERIZED_TYPE; }
1503d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1504d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1505d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1506d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitParameterizedType(this, data);
1507d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1508d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1509d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1510d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeTree getType() { return base; }
1511d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1512d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1513d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public List<? extends Tree> getTypeArguments() {
1514d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return typeArgs;
1515d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1516d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1517d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1518d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() {
1519d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        StringBuilder sb = new StringBuilder(base.toString());
1520d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        String s = "<";
1521d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        for (Tree t : typeArgs) {
1522d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          sb.append(s);
1523d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          sb.append(t.toString());
1524d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          s = ", ";
1525d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1526d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        sb.append('>');
1527d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return sb.toString();
1528d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1529d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1530d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1531d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class PrimT extends TypeTree implements PrimitiveTypeTree {
1532d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeKind typeKind;
1533d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1534d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      PrimT(TypeKind typeKind) {
1535d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.typeKind = typeKind;
1536d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1537d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1538d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1539d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.PRIMITIVE_TYPE; }
1540d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1541d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1542d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1543d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitPrimitiveType(this, data);
1544d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1545d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1546d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1547d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeKind getPrimitiveTypeKind() { return typeKind; }
1548d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1549d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1550d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() {
1551d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        switch (typeKind) {
1552d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case BOOLEAN: return "boolean";
1553d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case BYTE: return "byte";
1554d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case CHAR: return "char";
1555d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case DOUBLE: return "double";
1556d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case FLOAT: return "float";
1557d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case INT: return "int";
1558d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case LONG: return "long";
1559d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case SHORT: return "short";
156052e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst        // case VOID: return "void";
156152e8495fa4d3730f1ae8e4d97c01dbc24a7ea4a2Michael Ernst        // case WILDCARD: return "?";
1562d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        default:
1563d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new IllegalArgumentException("unexpected type kind "
1564d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              + typeKind);
1565d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1566d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1567d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1568d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1569d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class IdenT extends TypeTree implements IdentifierTree {
1570d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final String name;
1571d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1572d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      IdenT(String dname) {
1573d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.name = dname;
1574d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1575d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1576d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1577d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.IDENTIFIER; }
1578d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1579d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1580d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1581d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitIdentifier(this, data);
1582d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1583d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1584d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1585d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Name getName() { return new TypeName(name); }
1586d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1587d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1588d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return name; }
1589d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1590d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1591d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class WildT extends TypeTree implements WildcardTree {
1592dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      private final TypeTree bound;
1593dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      private final Kind kind;
1594dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown
1595dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      WildT() {
1596dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        this(Kind.UNBOUNDED_WILDCARD, null);
1597dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      }
1598dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown
1599dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      WildT(TypeTree bound, BoundedType.BoundKind bk) {
1600dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        this(bk == BoundedType.BoundKind.SUPER
1601dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                ? Kind.SUPER_WILDCARD
1602dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown                : Kind.EXTENDS_WILDCARD,
1603dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown            bound);
1604dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      }
1605dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown
1606dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      WildT(Kind kind, TypeTree bound) {
1607dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        this.kind = kind;
1608dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown        this.bound = bound;
1609dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      }
1610dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown
1611d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1612dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      public Kind getKind() { return kind; }
1613d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1614d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1615d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1616d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitWildcard(this, data);
1617d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1618d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1619d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1620dc2fa55e1f5a1e05ec9e21d6593f76e4449b9a6bDan Brown      public Tree getBound() { return bound; }
1621d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1622d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1623d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return "?"; }
1624d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1625d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1626d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class Param extends TypeTree implements TypeParameterTree {
1627d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final String bname;
1628d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final BoundedType.BoundKind bk;
1629d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final Tree bound;
1630d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1631d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Param(String bname, BoundedType.BoundKind bk, TypeTree bound) {
1632d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.bname = bname;
1633d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.bk = bk;
1634d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.bound = bound;
1635d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1636d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1637d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1638d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.TYPE_PARAMETER; }
1639d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1640d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1641d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1642d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitTypeParameter(this, data);
1643d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1644d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1645d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1646d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Name getName() { return new TypeName(bname); }
1647d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1648d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1649d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public List<? extends Tree> getBounds() {
1650d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return Collections.singletonList(bound);
1651d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1652d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1653d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1654d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public List<? extends AnnotationTree> getAnnotations() {
1655d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return Collections.emptyList();
1656d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1657d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1658d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1659d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() {
1660d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return bname + " " + bk.toString() + " " + bound.toString();
1661d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1662d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1663d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1664d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class TypeName implements Name {
1665d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final String str;
1666d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1667d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      TypeName(String str) {
1668d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.str = str;
1669d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1670d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1671d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1672d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public int length() { return str.length(); }
1673d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1674d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1675d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public char charAt(int index) { return str.charAt(index); }
1676d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1677d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1678d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public CharSequence subSequence(int start, int end) {
1679d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return str.subSequence(start, end);
1680d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1681d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1682d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1683d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public boolean contentEquals(CharSequence cs) {
1684d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (cs != null) {
1685d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          int n = length();
1686d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (cs.length() == n) {
1687d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            for (int i = 0; i < n; i++) {
1688d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (charAt(i) != cs.charAt(i)) { return false; }
1689d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
1690d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            return true;
1691d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
1692d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1693d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return false;
1694d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1695d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1696d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1697d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return str; }
1698d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1699d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
1700290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown}
1701