Insertions.java revision d429e5d87eb48b6c7ad9041eba400e775a1796ef
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;
19d429e5d87eb48b6c7ad9041eba400e775a1796efDan 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;
37d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.ParameterizedTypeTree;
38d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.PrimitiveTypeTree;
39d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.Tree;
40d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.TreeVisitor;
41d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.TypeParameterTree;
42d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.source.tree.WildcardTree;
43d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.Kinds;
44d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.Symbol.ClassSymbol;
45d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.Symbol.MethodSymbol;
46d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry;
47d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
48d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.code.TypeTag;
49d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.tree.JCTree;
50d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownimport com.sun.tools.javac.util.Pair;
51290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
52290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown/**
53290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown * @author dbro
54290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown *
55d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown * The motivation for this class was to avoid wasting time going through
56d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown * an entire scene (which could involve many different classes) for
57d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown * every class, which is horribly wasteful when a JAIF covers every
58d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown * class in a large codebase, such as the Hadoop source.
59290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown */
60290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brownpublic class Insertions implements Iterable<Insertion> {
61d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private static final boolean ORGANIZE = true;
62d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
63d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private static final Comparator<Insertion> byASTRecord =
64d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      new Comparator<Insertion>() {
65d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        @Override
66d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        public int compare(Insertion o1, Insertion o2) {
67d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Criteria c1 = o1.getCriteria();
68d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Criteria c2 = o2.getCriteria();
69d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          ASTRecord r1 = new ASTRecord(c1.getClassName(),
70d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              c1.getMethodName(), c1.getFieldName(), c1.getASTPath());
71d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          ASTRecord r2 = new ASTRecord(c2.getClassName(),
72d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              c2.getMethodName(), c2.getFieldName(), c2.getASTPath());
73d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          return r1.compareTo(r2);
74d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
75d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      };
76d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
77d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  // store indexes insertions by (qualified) outer class name and inner
78d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  // class path (if any)
79d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private Map<String, Map<String, Set<Insertion>>> store;
80290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  private int size;
81290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
82d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private Pair<String, String> nameSplit(String name) {
83d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    int i = name.indexOf('$');  // FIXME: don't split on '$' in source
84d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return i < 0
85d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ? Pair.of(name, "")
86d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        : Pair.of(name.substring(0, i), name.substring(i));
87d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
88d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
89290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public Insertions() {
90d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    store = new HashMap<String, Map<String, Set<Insertion>>>();
91567ba7d414e53451066008d98bbeacdfed876aceDan Brown    size = 0;
92290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
93290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
94d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private void forClass(CompilationUnitTree cut,
95d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String qualifiedClassName, Set<Insertion> result) {
96d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Pair<String, String> pair = nameSplit(qualifiedClassName);
97d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<String, Set<Insertion>> map = store.get(pair.fst);
98d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (map != null) {
99d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Set<Insertion> set = map.get(pair.snd);
100d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (set != null) {
101d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        set = organizeTypedInsertions(cut, qualifiedClassName, set);
102d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        result.addAll(set);
103d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
104d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
105d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
106d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
107d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  public Set<Insertion> forClass(CompilationUnitTree cut,
108d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String qualifiedClassName) {
109d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Set<Insertion> set = new LinkedHashSet<Insertion>();
110d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    forClass(cut, qualifiedClassName, set);
111d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return set;
112d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
113d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
114d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  public Set<Insertion> forTopClass(CompilationUnitTree cut,
115d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String qualifiedOuterClassName) {
116d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<String, Set<Insertion>> map = store.get(qualifiedOuterClassName);
117d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (map == null || map.isEmpty()) {
118d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return Collections.<Insertion>emptySet();
119d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    } else {
120d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Set<Insertion> set = new LinkedHashSet<Insertion>();
121d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (String key : map.keySet()) {
122d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        String qualifiedClassName = qualifiedOuterClassName + key;
123d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        forClass(cut, qualifiedClassName, set);
124d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
125d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return set;
126d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
127290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
128290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
129290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public void add(Insertion ins) {
130290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    InClassCriterion icc = ins.getCriteria().getInClass();
131d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    String k1 = "";
132d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    String k2 = "";
133d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<String, Set<Insertion>> map;
134d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Set<Insertion> set;
135d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
136290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    if (icc != null) {
137d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Pair<String, String> triple = nameSplit(icc.className);
138d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      k1 = triple.fst;
139d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      k2 = triple.snd;
140290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    }
141d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    map = store.get(k1);
142d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (map == null) {
143d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      map = new HashMap<String, Set<Insertion>>();
144d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      store.put(k1, map);
145290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    }
146d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    set = map.get(k2);
147d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (set == null) {
148d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      set = new LinkedHashSet<Insertion>();
149d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      map.put(k2, set);
150d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
151d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
152d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    size -= set.size();
153d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    set.add(ins);
154d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    size += set.size();
155290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
156290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
157290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public void addAll(Collection<? extends Insertion> c) {
158290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    for (Insertion ins : c) {
159290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      add(ins);
160290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    }
161290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
162290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
163290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public int size() {
164290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    return size;
165290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
166290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
167290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  @Override
168290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  public Iterator<Insertion> iterator() {
169290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    return new Iterator<Insertion>() {
170d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private Iterator<Map<String, Set<Insertion>>> miter =
171d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          store.values().iterator();
172d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private Iterator<Set<Insertion>> siter =
173d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Collections.<Set<Insertion>>emptySet().iterator();
174d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private Iterator<Insertion> iiter =
175d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Collections.<Insertion>emptySet().iterator();
176290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
177290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      @Override
178290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      public boolean hasNext() {
179290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        if (iiter.hasNext()) { return true; }
180290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        while (siter.hasNext()) {
181290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown          iiter = siter.next().iterator();
182d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (iiter.hasNext()) { return true; }
183d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
184d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        while (miter.hasNext()) {
185d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          siter = miter.next().values().iterator();
186d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          while (siter.hasNext()) {
187d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            iiter = siter.next().iterator();
188d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (iiter.hasNext()) { return true; }
189290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown          }
190290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        }
191290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        return false;
192290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      }
193290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
194290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      @Override
195290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      public Insertion next() {
196290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        if (hasNext()) { return iiter.next(); }
197290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        throw new NoSuchElementException();
198290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      }
199290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown
200290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      @Override
201290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      public void remove() {
202290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown        throw new UnsupportedOperationException();
203290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown      }
204290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown    };
205290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown  }
206567ba7d414e53451066008d98bbeacdfed876aceDan Brown
207567ba7d414e53451066008d98bbeacdfed876aceDan Brown  public List<Insertion> toList() {
208567ba7d414e53451066008d98bbeacdfed876aceDan Brown    List<Insertion> list = new ArrayList<Insertion>(size);
209d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    for (Insertion ins : this) { list.add(ins); }
210567ba7d414e53451066008d98bbeacdfed876aceDan Brown    return null;
211567ba7d414e53451066008d98bbeacdfed876aceDan Brown  }
212d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
213d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  /*
214d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * This method detects inner type relationships among ASTPath-based
215d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * insertion specifications and organizes the insertions accordingly.
216d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * This step is necessary because 1) insertion proceeds from the end to
217d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * the beginning of the source and 2) the insertion location does not
218d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * always exist prior to the top-level type insertion.
219d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   */
220d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private Set<Insertion> organizeTypedInsertions(CompilationUnitTree cut,
221d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String className, Collection<Insertion> insertions) {
222d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    ASTRecordMap<TypedInsertion> map = new ASTRecordMap<TypedInsertion>();
223d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Set<Insertion> organized = new LinkedHashSet<Insertion>();
224d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Set<Insertion> unorganized = new TreeSet<Insertion>(byASTRecord);
225d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (!ORGANIZE) { organized.addAll(insertions); return organized; }
226d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    for (Insertion ins : insertions) {
227d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTPath p = ins.getCriteria().getASTPath();
228d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      GenericArrayLocationCriterion galc =
229d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          ins.getCriteria().getGenericArrayLocation();
230d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (p == null || p.isEmpty()
231d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          || galc != null && !galc.getLocation().isEmpty()
232d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          || ins instanceof CloseParenthesisInsertion) {
233d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        organized.add(ins);
234d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      } else {
235d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (!ins.getInserted() && ins instanceof TypedInsertion) {
236d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          Criteria criteria = ins.getCriteria();
237d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          ASTRecord rec = new ASTRecord(criteria.getClassName(),
238d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              criteria.getMethodName(), criteria.getFieldName(), p);
239d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          TypedInsertion tins = map.get(rec);
240d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (tins == null) {
241d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            map.put(rec, (TypedInsertion) ins);
242d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          } else {
243d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            mergeTypedInsertions(tins, (TypedInsertion) ins);
244d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
245d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } else {
246d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          unorganized.add(ins);
247d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
248d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
249d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
250d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (map.isEmpty()) {
251d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      organized.addAll(unorganized);
252d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return organized;
253d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
254d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
255d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    for (Insertion ins : unorganized) {
256d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Criteria criteria = ins.getCriteria();
257d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String methodName = criteria.getMethodName();
258d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      String fieldName = criteria.getFieldName();
259d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTPath ap1 = criteria.getASTPath();
260d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      List<TypePathEntry> tpes = new ArrayList<TypePathEntry>();
261d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (ap1 == null) {
262d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          // || methodName == null && fieldName == null)
263d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        organized.add(ins);
264d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        continue;
265d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
266d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
267d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // First find the relevant "top-level" insertion, if any.
268d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // ap0: path to top-level type; ap1: path to local type
269d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Tree.Kind kind;
270d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Deque<ASTPath> astack = new ArrayDeque<ASTPath>(ap1.size());
271d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTPath ap0 = ap1;
272d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      while (!ap0.isEmpty()) {
273d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        astack.push(ap0);
274d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ap0 = ap0.getParentPath();
275d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
276d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // ap0.isEmpty()
277d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
278d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // The sought node may or may not be found in the tree; if not, it
279d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // may need to be created later.  Use whatever part of the path
280d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // exists already to distinguish MEMBER_SELECT nodes that indicate
281d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // qualifiers from those that indicate local types.  Assume any
282d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // MEMBER_SELECTs in the AST path that don't correspond to
283d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // existing nodes are part of a type use.
284d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Tree node = null;
285d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = new ASTRecord(className, methodName, fieldName,
286d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          ASTPath.empty());
287d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      while (!astack.isEmpty()) {
288d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ap0 = astack.pop();
289d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        kind = ap0.get(-1).getTreeKind();
290d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        rec = rec.replacePath(ap0);
291d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (map.containsKey(rec)) {
292d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          ASTPath ap = ap0;
293d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          node = ASTIndex.getNode(cut, rec);
294d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          while (node == null && !ap.isEmpty()) {
295d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            ap = ap.getParentPath();
296d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            node = ASTIndex.getNode(cut, rec.replacePath(ap));
297d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
298d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
299d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
300d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
301d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
302d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      /*
303d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * Inner types require special consideration due to the
304d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * structural differences between an AST that represents a type
305d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * (subclass of com.sun.source.Tree) and the type's logical
306d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * representation (subclass of type.Type).  The differences are
307d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * most prominent in the case of a type with a parameterized
308d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * local type.  For example, the AST for A.B.C<D> looks like
309d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * this:
310d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
311d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                     ParameterizedType
312d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                    /                 \
313d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *               MemberSelect       Identifier
314d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *              /            \           |
315d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *        MemberSelect      (Name)       D
316d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *         /      \           |
317d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *  Identifier   (Name)       C
318d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *        |        |
319d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *        A        B
320d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
321d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * (Technically, the Names are not AST nodes but rather
322d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * attributes of their parent MemberSelect nodes.)  The logical
323d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * representation seems more intuitive:
324d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
325d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *       DeclaredType
326d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *      /     |      \
327d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *    Name  Params  Inner
328d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *     |      |       |
329d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *     A      -  DeclaredType
330d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *              /     |      \
331d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *            Name  Params  Inner
332d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *             |      |       |
333d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *             B      -  DeclaredType
334d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                      /     |      \
335d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                    Name  Params  Inner
336d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                     |      |       |
337d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *                     C      D       -
338d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
339d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * The opposing "chirality" of local type nesting means that the
340d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * usual recursive descent strategy doesn't work for finding a
341d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * logical type path in an AST; in effect, local types have to
342d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * be "turned inside-out".
343d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       *
344d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * Worse yet, the actual tree structure may not exist in the tree!
345d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * It is possible to recover the actual type from the symbol
346d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * table, but the methods to create AST nodes are not visible
347d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * here.  Hence, the conversion relies on custom implementations
348d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * of the interfaces in com.sun.source.tree.Tree, which are
349d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       * defined in the local class TypeTree.
350d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown       */
351d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
352d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      int i = ap0.size();
353d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      int n = ap1.size();
354d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      int depth;
355d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
356d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      // skip any declaration nodes
357d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      while (i < n) {
358d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ASTPath.ASTEntry entry = ap1.get(i);
359d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        kind = entry.getTreeKind();
360d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (kind != Tree.Kind.METHOD && kind != Tree.Kind.VARIABLE) {
361d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
362d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
363d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ++i;
364d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
365d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
366d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      TypedInsertion tins = map.get(rec);
367d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (tins == null) {
368d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        organized.add(ins);
369d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        continue;
370d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
371d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
372d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (node == null) {
373d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        // find actual type
374d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        switch (tins.getKind()) {
375d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case CONSTRUCTOR:
376d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          // TODO
377d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
378d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case NEW:
379d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          // TODO
380d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
381d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case RECEIVER:
382d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (node instanceof JCTree.JCMethodDecl) {
383d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            MethodSymbol msym = ((JCTree.JCMethodDecl) node).sym;
384d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            ClassSymbol csym = (ClassSymbol) msym.owner;
385d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (msym.name.toString().equals("<init>")) {  // ???
386d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              // TODO
387d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            } else {
388d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              node = TypeTree.fromType(csym.type);
389d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
390d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          } else {
391d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            // TODO
392d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
393d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
394d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        default:
395d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
396d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
397d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
398d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
399d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownloop:
400d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      while (i < n) {
401d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ASTPath.ASTEntry entry = ap1.get(i);
402d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        rec = rec.extend(entry);
403d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        depth = localDepth(node);
404d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        kind = entry.getTreeKind();
405d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
406d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        switch (kind) {
407d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case ARRAY_TYPE:
408d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (depth == 0 && node.getKind() == kind) {
409d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            node = ((ArrayTypeTree) node).getType();
410d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            tpes.add(TypePathEntry.ARRAY);
411d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            break;
412d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
413d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
414d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
415d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case MEMBER_SELECT:
416d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (depth > 0) {  // otherwise, shouldn't have MEMBER_SELECT
417d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            do {
418d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              node = ((MemberSelectTree) node).getExpression();
419d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              while (node.getKind() == Tree.Kind.ANNOTATED_TYPE) {
420d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                node = ((AnnotatedTypeTree) node).getUnderlyingType();
421d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              }
422d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (++i == n) {
423d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                do {
424d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                  tpes.add(TypePathEntry.INNER_TYPE);
425d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                } while (--depth > 0);
426d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                break loop;
427d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              }
428d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              entry = ap1.get(i);
429d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (--depth == 0) { continue loop; }  // avoid re-incrementing i
430d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            } while (entry.getTreeKind() == Tree.Kind.MEMBER_SELECT);
431d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            // normal exit means entry has wrong kind
432d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
433d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
434d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
435d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case PARAMETERIZED_TYPE:
436d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (depth == 0 && node.getKind() == kind) {
437d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            ParameterizedTypeTree ptt = (ParameterizedTypeTree) node;
438d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (entry.childSelectorIs(ASTPath.TYPE)) {
439d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              node = ptt.getType();
440d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              break;
441d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            } else if (entry.childSelectorIs(ASTPath.TYPE_PARAMETER)) {
442d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              List<? extends Tree> typeArgs = ptt.getTypeArguments();
443d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              int j = entry.getArgument();
444d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (j >= 0 && j < typeArgs.size()) {
445d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                // first make sure any inner types are accounted for
446d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                depth = localDepth(ptt.getType());
447d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                while (--depth >= 0) { tpes.add(TypePathEntry.INNER_TYPE); }
448d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                node = typeArgs.get(j);
449d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                tpes.add(
450d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                    new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, j));
451d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                break;
452d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              }
453d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
454d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
455d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
456d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
457d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case UNBOUNDED_WILDCARD:
458d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          switch (node.getKind()) {
459d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          case EXTENDS_WILDCARD:
460d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          case SUPER_WILDCARD:
461d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          case UNBOUNDED_WILDCARD:
462d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (depth == 0
463d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            && (i < 1
464d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                || ap1.get(i-1).getTreeKind() != Tree.Kind.INSTANCE_OF)
465d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                && (i < 2
466d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                    || ap1.get(i-2).getTreeKind() != Tree.Kind.ARRAY_TYPE)) {
467d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              break;
468d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }  // fall through
469d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          default:
470d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            throw new RuntimeException();
471d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
472d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
473d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        default:
474d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          node = ASTIndex.getNode(cut, rec);
475d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
476d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
477d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
478d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ++i;
479d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
480d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
481d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (tpes.isEmpty()) {
482d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        //assert ap1.equals(ap0) && !map.containsKey(ap0);
483d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        organized.add(ins);
484d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        //map.put(rec, (TypedInsertion) ins);
485d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      } else {
486d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        TypedInsertion top = tins;
487d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (top == null) {
488d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          organized.add(ins);
489d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } else {
490d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          criteria.add(new ASTPathCriterion(ap0));
491d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          criteria.add(new GenericArrayLocationCriterion(
492d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              new InnerTypeLocation(tpes)));
493d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          top.getInnerTypeInsertions().add(ins);
494d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
495d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
496d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
497d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    organized.addAll(map.values());
498d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return organized;
499d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
500d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
501d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private void mergeTypedInsertions(TypedInsertion ins0, TypedInsertion ins1) {
502d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    mergeTypes(ins0.getType(), ins1.getType());
503d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
504d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
505d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private void mergeTypes(Type t0, Type t1) {
506d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    if (t0 == t1) { return; }
507d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    switch (t0.getKind()) {
508d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    case ARRAY:
509d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      {
510d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ArrayType at0 = (ArrayType) t0;
511d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ArrayType at1 = (ArrayType) t1;
512d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        mergeTypes(at0.getComponentType(), at1.getComponentType());
513d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return;
514d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
515d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    case BOUNDED:
516d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      {
517d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        BoundedType bt0 = (BoundedType) t0;
518d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        BoundedType bt1 = (BoundedType) t1;
519d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (bt0.getBoundKind() != bt1.getBoundKind()) { break; }
520d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        mergeTypes(bt0.getBound(), bt1.getBound());
521d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        mergeTypes(bt0.getType(), bt1.getType());
522d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return;
523d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
524d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    case DECLARED:
525d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      {
526d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        DeclaredType dt0 = (DeclaredType) t0;
527d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        DeclaredType dt1 = (DeclaredType) t1;
528d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        List<Type> tps0 = dt0.getTypeParameters();
529d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        List<Type> tps1 = dt1.getTypeParameters();
530d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        int n = tps0.size();
531d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (tps1.size() != n) { break; }
532d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        mergeTypes(dt0.getInnerType(), dt1.getInnerType());
533d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        for (String anno : dt1.getAnnotations()) {
534d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (!dt0.getAnnotations().contains(anno)) {
535d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            dt0.addAnnotation(anno);
536d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
537d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
538d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        for (int i = 0; i < n; i++) {
539d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          mergeTypes(tps0.get(i), tps1.get(i));
540d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
541d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return;
542d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
543d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
544d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    throw new RuntimeException();
545d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
546d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
547d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  /**
548d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * @param node
549d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   * @return depth of innermost local type of {@code node}
550d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown   */
551d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private int localDepth(Tree node) {
552d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Tree t = node;
553d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    int n = 0;
554d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brownloop:
555d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    while (t != null) {
556d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (t.getKind()) {
557d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case ANNOTATED_TYPE:
558d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((AnnotatedTypeTree) t).getUnderlyingType();
559d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
560d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case MEMBER_SELECT:
561d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        JCTree.JCFieldAccess jfa = (JCTree.JCFieldAccess) t;
562d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (jfa.sym.kind != Kinds.PCK) {
563d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          t = jfa.getExpression();
564d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          ++n;
565d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
566d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } // else fall through
567d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
568d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break loop;
569d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
570d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
571d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    return n;
572d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
573d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
574d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  class ASTRecordMap<E> implements Map<ASTRecord, E> {
575d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    Map<ASTRecord, SortedMap<ASTPath, E>> back;
576d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
577d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    ASTRecordMap() {
578d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      back = new HashMap<ASTRecord, SortedMap<ASTPath, E>>();
579d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
580d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
581d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    private SortedMap<ASTPath, E> getMap(ASTRecord rec) {
582d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord key = rec.replacePath(ASTPath.empty());
583d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = back.get(key);
584d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      if (map == null) {
585d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        map = new TreeMap<ASTPath, E>();
586d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        back.put(key, map);
587d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
588d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map;
589d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
590d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
591d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
592d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public int size() {
593d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      int n = 0;
594d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (SortedMap<ASTPath, E> map : back.values()) {
595d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        n += map.size();
596d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
597d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return n;
598d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
599d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
600d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
601d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public boolean isEmpty() {
602d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return size() == 0;
603d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
604d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
605d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
606d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public boolean containsKey(Object key) {
607d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = (ASTRecord) key;
608d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> m = getMap(rec);
609d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return m != null && m.containsKey(rec.astPath);
610d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
611d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
612d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
613d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public boolean containsValue(Object value) {
614d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @SuppressWarnings("unchecked")
615d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      E e = (E) value;
616d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (SortedMap<ASTPath, E> map : back.values()) {
617d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (map.containsValue(e)) { return true; }
618d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
619d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return false;
620d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
621d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
622d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
623d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public E get(Object key) {
624d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = (ASTRecord) key;
625d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = getMap(rec);
626d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map == null ? null : map.get(rec.astPath);
627d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
628d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
629d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
630d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public E put(ASTRecord key, E value) {
631d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = (ASTRecord) key;
632d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = getMap(rec);
633d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map == null ? null : map.put(rec.astPath, value);
634d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
635d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
636d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
637d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public E remove(Object key) {
638d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ASTRecord rec = (ASTRecord) key;
639d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      SortedMap<ASTPath, E> map = getMap(rec);
640d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return map == null ? null : map.remove(rec.astPath);
641d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
642d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
643d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
644d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public void putAll(Map<? extends ASTRecord, ? extends E> m) {
645d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (Map.Entry<? extends ASTRecord, ? extends E> entry : m.entrySet()) {
646d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        put(entry.getKey(), entry.getValue());
647d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
648d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
649d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
650d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
651d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public void clear() {
652d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      back.clear();
653d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
654d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
655d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
656d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public Set<ASTRecord> keySet() {
657d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return back.keySet();
658d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
659d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
660d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
661d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public Collection<E> values() {
662d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Set<E> ret = new LinkedHashSet<E>();
663d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      for (SortedMap<ASTPath, E> m : back.values()) {
664d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ret.addAll(m.values());
665d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
666d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return ret;
667d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
668d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
669d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    @Override
670d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    public Set<Map.Entry<ASTRecord, E>> entrySet() {
671d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      final int size = size();
672d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return new AbstractSet<Map.Entry<ASTRecord, E>>() {
673d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        @Override
674d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        public Iterator<Map.Entry<ASTRecord, E>> iterator() {
675d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          return new Iterator<Map.Entry<ASTRecord, E>>() {
676d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            Iterator<Map.Entry<ASTRecord, SortedMap<ASTPath, E>>> iter0 =
677d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                back.entrySet().iterator();
678d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            Iterator<Map.Entry<ASTPath, E>> iter1 =
679d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                Collections.<Map.Entry<ASTPath, E>>emptyIterator();
680d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            ASTRecord rec = null;
681d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
682d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            @Override
683d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            public boolean hasNext() {
684d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (iter1.hasNext()) { return true; }
685d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              while (iter0.hasNext()) {
686d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                Map.Entry<ASTRecord, SortedMap<ASTPath, E>> entry =
687d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                    iter0.next();
688d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                rec = entry.getKey();
689d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                iter1 = entry.getValue().entrySet().iterator();
690d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                if (iter1.hasNext()) { return true; }
691d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              }
692d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              iter1 = Collections.<Map.Entry<ASTPath, E>>emptyIterator();
693d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              return false;
694d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
695d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
696d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            @Override
697d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            public Map.Entry<ASTRecord, E> next() {
698d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (!hasNext()) { throw new NoSuchElementException(); }
699d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              final Map.Entry<ASTPath, E> e0 = iter1.next();
700d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              return new Map.Entry<ASTRecord, E>() {
701d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                final ASTRecord key = rec.replacePath(e0.getKey());
702d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                final E val = e0.getValue();
703d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                @Override public ASTRecord getKey() { return key; }
704d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                @Override public E getValue() { return val; }
705d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                @Override public E setValue(E value) {
706d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                  throw new UnsupportedOperationException();
707d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown                }
708d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              };
709d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
710d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          };
711d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
712d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
713d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        @Override
714d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        public int size() { return size; }
715d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      };
716d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
717d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
718d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
719d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  private static abstract class TypeTree implements ExpressionTree {
720d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    private static Map<String, TypeTag> primTags = new HashMap<String, TypeTag>();
721d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    {
722d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("byte", TypeTag.BYTE);
723d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("char", TypeTag.CHAR);
724d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("short", TypeTag.SHORT);
725d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("long", TypeTag.LONG);
726d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("float", TypeTag.FLOAT);
727d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("int", TypeTag.INT);
728d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("double", TypeTag.DOUBLE);
729d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      primTags.put("boolean", TypeTag.BOOLEAN);
730d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
731d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
732d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static TypeTree fromType(final Type type) {
733d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (type.getKind()) {
734d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case ARRAY:
735d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final ArrayType atype = (ArrayType) type;
736d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final TypeTree componentType = fromType(atype.getComponentType());
737d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new ArrT(componentType);
738d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case BOUNDED:
739d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final BoundedType btype = (BoundedType) type;
740d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final BoundedType.BoundKind bk = btype.getBoundKind();
741d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final String bname = btype.getType().getName();
742d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final TypeTree bound = fromType(btype.getBound());
743d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new Param(bname, bk, bound);
744d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case DECLARED:
745d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        final DeclaredType dtype = (DeclaredType) type;
746d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (dtype.isWildcard()) {
747d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          return new WildT();
748d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } else {
749d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          final String dname = dtype.getName();
750d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          TypeTag typeTag = primTags.get(dname);
751d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (typeTag == null) {
752d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            final TypeTree base = new IdenT(dname);
753d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            TypeTree ret = base;
754d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            List<Type> params = dtype.getTypeParameters();
755d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            DeclaredType inner = dtype.getInnerType();
756d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            if (!params.isEmpty()) {
757d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              final List<Tree> typeArgs = new ArrayList<Tree>(params.size());
758d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              for (Type t : params) { typeArgs.add(fromType(t)); }
759d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              ret = new ParT(base, typeArgs);
760d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
761d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            return inner == null ? ret : meld(fromType(inner), ret);
762d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          } else {
763d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            final TypeKind typeKind = typeTag.getPrimitiveTypeKind();
764d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            return new PrimT(typeKind);
765d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
766d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
767d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
768d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        throw new RuntimeException("unknown type kind " + type.getKind());
769d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
770d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
771d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
772d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static TypeTree fromType(final com.sun.tools.javac.code.Type type) {
773d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return fromType(conv(type));
774d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
775d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
776d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    /**
777d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown     * @param jtype
778d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown     * @return
779d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown     */
780d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    private static Type conv(final com.sun.tools.javac.code.Type jtype) {
781d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Type type = null;
782d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      DeclaredType d;
783d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      com.sun.tools.javac.code.Type t;
784d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (jtype.getKind()) {
785d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case ARRAY:
786d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((com.sun.tools.javac.code.Type.ArrayType) jtype).elemtype;
787d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = new ArrayType(conv(t));
788d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
789d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case DECLARED:
790d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = jtype;
791d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        d = null;
792d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        do {
793d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          DeclaredType d0 = d;
794d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          com.sun.tools.javac.code.Type.ClassType ct =
795d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              (com.sun.tools.javac.code.Type.ClassType) t;
796d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          d = new DeclaredType(ct.tsym.name.toString());
797d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          d.setInnerType(d0);
798d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          d0 = d;
799d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          for (com.sun.tools.javac.code.Type a : ct.getTypeArguments()) {
800d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            d.addTypeParameter(conv(a));
801d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
802d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          t = ct.getEnclosingType();
803d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        } while (t.getKind() == TypeKind.DECLARED);
804d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = d;
805d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
806d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case WILDCARD:
807d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        BoundedType.BoundKind k;
808d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((com.sun.tools.javac.code.Type.WildcardType) jtype).bound;
809d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        switch (((com.sun.tools.javac.code.Type.WildcardType) jtype).kind) {
810d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case EXTENDS:
811d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          k = BoundedType.BoundKind.EXTENDS;
812d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
813d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case SUPER:
814d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          k = BoundedType.BoundKind.SUPER;
815d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
816d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case UNBOUND:
817d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          k = null;
818d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          break;
819d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        default:
820d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new RuntimeException();
821d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
822d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        d = new DeclaredType(jtype.tsym.name.toString());
823d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = k == null ? d : new BoundedType(d, k, (DeclaredType) conv(t));
824d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
825d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case TYPEVAR:
826d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = ((com.sun.tools.javac.code.Type.TypeVar) jtype).getUpperBound();
827d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = new BoundedType(new DeclaredType(jtype.tsym.name.toString()),
828d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            BoundedType.BoundKind.EXTENDS, (DeclaredType) conv(t));
829d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
830d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case INTERSECTION:
831d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        t = jtype.tsym.erasure_field;
832d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        type = new DeclaredType(t.tsym.name.toString());
833d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
834d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case UNION:
835d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        // TODO
836d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
837d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case BOOLEAN:
838d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case BYTE:
839d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case CHAR:
840d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case DOUBLE:
841d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case LONG:
842d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case SHORT:
843d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case FLOAT:
844d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case INT:
845d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        // TODO
846d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
847d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      //case ERROR:
848d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      //case EXECUTABLE:
849d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      //case NONE:
850d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      //case NULL:
851d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      //case OTHER:
852d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      //case PACKAGE:
853d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      //case VOID:
854d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
855d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        break;
856d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
857d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      return type;
858d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
859d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
860d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    private static TypeTree meld(final TypeTree t0, final TypeTree t1) {
861d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      switch (t0.getKind()) {
862d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case IDENTIFIER:
863d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        IdenT it = (IdenT) t0;
864d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new LocT(t1, it.getName());
865d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case MEMBER_SELECT:
866d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        LocT lt = (LocT) t0;
867d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new LocT(meld(lt.getExpression(), t1), lt.getIdentifier());
868d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      case PARAMETERIZED_TYPE:
869d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        ParT pt = (ParT) t0;
870d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return new ParT(meld(pt.getType(), t1), pt.getTypeArguments());
871d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      default:
872d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        throw new IllegalArgumentException("unexpected type " + t0);
873d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
874d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
875d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
876d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class ArrT extends TypeTree implements ArrayTypeTree {
877d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeTree componentType;
878d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
879d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ArrT(TypeTree componentType) {
880d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.componentType = componentType;
881d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
882d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
883d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
884d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.ARRAY_TYPE; }
885d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
886d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
887d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
888d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitArrayType(this, data);
889d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
890d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
891d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
892d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeTree getType() { return componentType; }
893d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
894d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
895d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return componentType + "[]"; }
896d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
897d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
898d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class LocT extends TypeTree implements MemberSelectTree {
899d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeTree expr;
900d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final Name name;
901d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
902d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      LocT(TypeTree expr, Name name) {
903d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.expr = expr;
904d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.name = name;
905d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
906d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
907d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
908d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.MEMBER_SELECT; }
909d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
910d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
911d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
912d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitMemberSelect(this, data);
913d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
914d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
915d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
916d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeTree getExpression() { return expr; }
917d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
918d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
919d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Name getIdentifier() { return name; }
920d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
921d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
922d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return expr + "." + name; }
923d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
924d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
925d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class ParT extends TypeTree implements ParameterizedTypeTree {
926d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeTree base;
927d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final List<? extends Tree> typeArgs;
928d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
929d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      ParT(TypeTree base, List<? extends Tree> typeArgs) {
930d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.base = base;
931d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.typeArgs = typeArgs;
932d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
933d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
934d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
935d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.PARAMETERIZED_TYPE; }
936d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
937d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
938d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
939d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitParameterizedType(this, data);
940d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
941d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
942d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
943d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeTree getType() { return base; }
944d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
945d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
946d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public List<? extends Tree> getTypeArguments() {
947d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return typeArgs;
948d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
949d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
950d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
951d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() {
952d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        StringBuilder sb = new StringBuilder(base.toString());
953d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        String s = "<";
954d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        for (Tree t : typeArgs) {
955d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          sb.append(s);
956d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          sb.append(t.toString());
957d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          s = ", ";
958d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
959d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        sb.append('>');
960d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return sb.toString();
961d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
962d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
963d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
964d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class PrimT extends TypeTree implements PrimitiveTypeTree {
965d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final TypeKind typeKind;
966d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
967d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      PrimT(TypeKind typeKind) {
968d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.typeKind = typeKind;
969d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
970d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
971d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
972d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.PRIMITIVE_TYPE; }
973d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
974d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
975d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
976d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitPrimitiveType(this, data);
977d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
978d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
979d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
980d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public TypeKind getPrimitiveTypeKind() { return typeKind; }
981d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
982d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
983d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() {
984d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        switch (typeKind) {
985d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case BOOLEAN: return "boolean";
986d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case BYTE: return "byte";
987d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case CHAR: return "char";
988d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case DOUBLE: return "double";
989d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case FLOAT: return "float";
990d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case INT: return "int";
991d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case LONG: return "long";
992d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        case SHORT: return "short";
993d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        //case VOID: return "void";
994d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        //case WILDCARD: return "?";
995d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        default:
996d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          throw new IllegalArgumentException("unexpected type kind "
997d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              + typeKind);
998d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
999d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1000d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1001d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1002d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class IdenT extends TypeTree implements IdentifierTree {
1003d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final String name;
1004d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1005d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      IdenT(String dname) {
1006d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.name = dname;
1007d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1008d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1009d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1010d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.IDENTIFIER; }
1011d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1012d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1013d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1014d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitIdentifier(this, data);
1015d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1016d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1017d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1018d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Name getName() { return new TypeName(name); }
1019d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1020d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1021d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return name; }
1022d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1023d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1024d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class WildT extends TypeTree implements WildcardTree {
1025d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1026d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.UNBOUNDED_WILDCARD; }
1027d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1028d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1029d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1030d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitWildcard(this, data);
1031d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1032d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1033d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1034d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Tree getBound() { return null; }
1035d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1036d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1037d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return "?"; }
1038d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1039d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1040d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class Param extends TypeTree implements TypeParameterTree {
1041d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final String bname;
1042d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final BoundedType.BoundKind bk;
1043d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final Tree bound;
1044d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1045d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      Param(String bname, BoundedType.BoundKind bk, TypeTree bound) {
1046d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.bname = bname;
1047d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.bk = bk;
1048d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.bound = bound;
1049d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1050d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1051d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1052d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Kind getKind() { return Kind.TYPE_PARAMETER; }
1053d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1054d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1055d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
1056d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return visitor.visitTypeParameter(this, data);
1057d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1058d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1059d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1060d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public Name getName() { return new TypeName(bname); }
1061d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1062d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1063d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public List<? extends Tree> getBounds() {
1064d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return Collections.singletonList(bound);
1065d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1066d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1067d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1068d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public List<? extends AnnotationTree> getAnnotations() {
1069d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return Collections.emptyList();
1070d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1071d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1072d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1073d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() {
1074d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return bname + " " + bk.toString() + " " + bound.toString();
1075d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1076d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1077d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1078d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    static final class TypeName implements Name {
1079d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      private final String str;
1080d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1081d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      TypeName(String str) {
1082d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        this.str = str;
1083d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1084d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1085d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1086d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public int length() { return str.length(); }
1087d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1088d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1089d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public char charAt(int index) { return str.charAt(index); }
1090d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1091d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1092d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public CharSequence subSequence(int start, int end) {
1093d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return str.subSequence(start, end);
1094d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1095d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1096d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1097d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public boolean contentEquals(CharSequence cs) {
1098d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        if (cs != null) {
1099d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          int n = length();
1100d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          if (cs.length() == n) {
1101d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            for (int i = 0; i < n; i++) {
1102d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown              if (charAt(i) != cs.charAt(i)) { return false; }
1103d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            }
1104d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown            return true;
1105d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown          }
1106d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        }
1107d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown        return false;
1108d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      }
1109d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown
1110d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      @Override
1111d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown      public String toString() { return str; }
1112d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown    }
1113d429e5d87eb48b6c7ad9041eba400e775a1796efDan Brown  }
1114290791bf3ace51eca8cb637b47e1e1d01d92111dDan Brown}
1115