1 /* 2 * Copyright (c) 2003, 2005, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.reflect.generics.visitor; 27 28 29 import java.lang.reflect.Type; 30 import java.util.List; 31 import java.util.Iterator; 32 import sun.reflect.generics.tree.*; 33 import sun.reflect.generics.factory.*; 34 35 36 37 /** 38 * Visitor that converts AST to reified types. 39 */ 40 public class Reifier implements TypeTreeVisitor<Type> { 41 private Type resultType; 42 private final 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, {@code f}. 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 }