blob: c7bffeb411f9346bae432c6f048cfe933c76fc49 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.reflect.generics.visitor;
27
28
29import java.lang.reflect.Type;
30import java.util.List;
31import java.util.Iterator;
32import sun.reflect.generics.tree.*;
33import sun.reflect.generics.factory.*;
34
35
36
37/**
38 * Visitor that converts AST to reified types.
39 */
40public class Reifier implements TypeTreeVisitor<Type> {
41 private Type resultType;
42 private GenericsFactory factory;
43
44 private Reifier(GenericsFactory f){
45 factory = f;
46 }
47
48 private GenericsFactory getFactory(){ return factory;}
49
50 /**
51 * Factory method. The resulting visitor will convert an AST
52 * representing generic signatures into corresponding reflective
53 * objects, using the provided factory, <tt>f</tt>.
54 * @param f - a factory that can be used to manufacture reflective
55 * objects returned by this visitor
56 * @return A visitor that can be used to reify ASTs representing
57 * generic type information into reflective objects
58 */
59 public static Reifier make(GenericsFactory f){
60 return new Reifier(f);
61 }
62
63 // Helper method. Visits an array of TypeArgument and produces
64 // reified Type array.
65 private Type[] reifyTypeArguments(TypeArgument[] tas) {
66 Type[] ts = new Type[tas.length];
67 for (int i = 0; i < tas.length; i++) {
68 tas[i].accept(this);
69 ts[i] = resultType;
70 }
71 return ts;
72 }
73
74
75 /**
76 * Accessor for the result of the last visit by this visitor,
77 * @return The type computed by this visitor based on its last
78 * visit
79 */
80 public Type getResult() { assert resultType != null;return resultType;}
81
82 public void visitFormalTypeParameter(FormalTypeParameter ftp){
83 resultType = getFactory().makeTypeVariable(ftp.getName(),
84 ftp.getBounds());
85 }
86
87
88 public void visitClassTypeSignature(ClassTypeSignature ct){
89 // This method examines the pathname stored in ct, which has the form
90 // n1.n2...nk<targs>....
91 // where n1 ... nk-1 might not exist OR
92 // nk might not exist (but not both). It may be that k equals 1.
93 // The idea is that nk is the simple class type name that has
94 // any type parameters associated with it.
95 // We process this path in two phases.
96 // First, we scan until we reach nk (if it exists).
97 // If nk does not exist, this identifies a raw class n1 ... nk-1
98 // which we can return.
99 // if nk does exist, we begin the 2nd phase.
100 // Here nk defines a parameterized type. Every further step nj (j > k)
101 // down the path must also be represented as a parameterized type,
102 // whose owner is the representation of the previous step in the path,
103 // n{j-1}.
104
105 // extract iterator on list of simple class type sigs
106 List<SimpleClassTypeSignature> scts = ct.getPath();
107 assert(!scts.isEmpty());
108 Iterator<SimpleClassTypeSignature> iter = scts.iterator();
109 SimpleClassTypeSignature sc = iter.next();
110 StringBuilder n = new StringBuilder(sc.getName());
111 boolean dollar = sc.getDollar();
112
113 // phase 1: iterate over simple class types until
114 // we are either done or we hit one with non-empty type parameters
115 while (iter.hasNext() && sc.getTypeArguments().length == 0) {
116 sc = iter.next();
117 dollar = sc.getDollar();
118 n.append(dollar?"$":".").append(sc.getName());
119 }
120
121 // Now, either sc is the last element of the list, or
122 // it has type arguments (or both)
123 assert(!(iter.hasNext()) || (sc.getTypeArguments().length > 0));
124 // Create the raw type
125 Type c = getFactory().makeNamedType(n.toString());
126 // if there are no type arguments
127 if (sc.getTypeArguments().length == 0) {
128 //we have surely reached the end of the path
129 assert(!iter.hasNext());
130 resultType = c; // the result is the raw type
131 } else {
132 assert(sc.getTypeArguments().length > 0);
133 // otherwise, we have type arguments, so we create a parameterized
134 // type, whose declaration is the raw type c, and whose owner is
135 // the declaring class of c (if any). This latter fact is indicated
136 // by passing null as the owner.
137 // First, we reify the type arguments
138 Type[] pts = reifyTypeArguments(sc.getTypeArguments());
139
140 Type owner = getFactory().makeParameterizedType(c, pts, null);
141 // phase 2: iterate over remaining simple class types
142 dollar =false;
143 while (iter.hasNext()) {
144 sc = iter.next();
145 dollar = sc.getDollar();
146 n.append(dollar?"$":".").append(sc.getName()); // build up raw class name
147 c = getFactory().makeNamedType(n.toString()); // obtain raw class
148 pts = reifyTypeArguments(sc.getTypeArguments());// reify params
149 // Create a parameterized type, based on type args, raw type
150 // and previous owner
151 owner = getFactory().makeParameterizedType(c, pts, owner);
152 }
153 resultType = owner;
154 }
155 }
156
157 public void visitArrayTypeSignature(ArrayTypeSignature a){
158 // extract and reify component type
159 a.getComponentType().accept(this);
160 Type ct = resultType;
161 resultType = getFactory().makeArrayType(ct);
162 }
163
164 public void visitTypeVariableSignature(TypeVariableSignature tv){
165 resultType = getFactory().findTypeVariable(tv.getIdentifier());
166 }
167
168 public void visitWildcard(Wildcard w){
169 resultType = getFactory().makeWildcard(w.getUpperBounds(),
170 w.getLowerBounds());
171 }
172
173 public void visitSimpleClassTypeSignature(SimpleClassTypeSignature sct){
174 resultType = getFactory().makeNamedType(sct.getName());
175 }
176
177 public void visitBottomSignature(BottomSignature b){
178
179 }
180
181 public void visitByteSignature(ByteSignature b){
182 resultType = getFactory().makeByte();
183 }
184
185 public void visitBooleanSignature(BooleanSignature b){
186 resultType = getFactory().makeBool();
187 }
188
189 public void visitShortSignature(ShortSignature s){
190 resultType = getFactory().makeShort();
191 }
192
193 public void visitCharSignature(CharSignature c){
194 resultType = getFactory().makeChar();
195 }
196
197 public void visitIntSignature(IntSignature i){
198 resultType = getFactory().makeInt();
199 }
200
201 public void visitLongSignature(LongSignature l){
202 resultType = getFactory().makeLong();
203 }
204
205 public void visitFloatSignature(FloatSignature f){
206 resultType = getFactory().makeFloat();
207 }
208
209 public void visitDoubleSignature(DoubleSignature d){
210 resultType = getFactory().makeDouble();
211 }
212
213 public void visitVoidDescriptor(VoidDescriptor v){
214 resultType = getFactory().makeVoid();
215 }
216
217
218}