TypeInfo.java revision 9ccd9e3a9df835dc134e7edd2e4236220aed401e
1/* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.doclava; 18 19import com.google.clearsilver.jsilver.data.Data; 20 21import java.util.*; 22 23public class TypeInfo { 24 public static final Set<String> PRIMITIVE_TYPES = Collections.unmodifiableSet( 25 new HashSet<String>(Arrays.asList("boolean", "byte", "char", "double", "float", "int", 26 "long", "short", "void"))); 27 28 public TypeInfo(boolean isPrimitive, String dimension, String simpleTypeName, 29 String qualifiedTypeName, ClassInfo cl) { 30 mIsPrimitive = isPrimitive; 31 mDimension = dimension; 32 mSimpleTypeName = simpleTypeName; 33 mQualifiedTypeName = qualifiedTypeName; 34 mClass = cl; 35 } 36 37 public TypeInfo(String typeString) { 38 // VarArgs 39 if (typeString.endsWith("...")) { 40 typeString = typeString.substring(0, typeString.length() - 3); 41 } 42 43 // Generic parameters 44 int paramStartPos = typeString.indexOf('<'); 45 if (paramStartPos > -1) { 46 ArrayList<TypeInfo> generics = new ArrayList<TypeInfo>(); 47 int paramEndPos = typeString.lastIndexOf('>'); 48 49 int entryStartPos = paramStartPos + 1; 50 int bracketNesting = 0; 51 for (int i = entryStartPos; i < paramEndPos; i++) { 52 char c = typeString.charAt(i); 53 if (c == ',' && bracketNesting == 0) { 54 String entry = typeString.substring(entryStartPos, i).trim(); 55 TypeInfo info = new TypeInfo(entry); 56 generics.add(info); 57 entryStartPos = i + 1; 58 } else if (c == '<') { 59 bracketNesting++; 60 } else if (c == '>') { 61 bracketNesting--; 62 } 63 } 64 65 TypeInfo info = new TypeInfo(typeString.substring(entryStartPos, paramEndPos).trim()); 66 generics.add(info); 67 68 mTypeArguments = new TypeInfo[generics.size()]; 69 generics.toArray(mTypeArguments); 70 71 if (paramEndPos < typeString.length() - 1) { 72 typeString = typeString.substring(0,paramStartPos) + typeString.substring(paramEndPos + 1); 73 } else { 74 typeString = typeString.substring(0,paramStartPos); 75 } 76 } 77 78 // Dimensions 79 int pos = typeString.indexOf('['); 80 if (pos > -1) { 81 mDimension = typeString.substring(pos); 82 typeString = typeString.substring(0, pos); 83 } else { 84 mDimension = ""; 85 } 86 87 if (PRIMITIVE_TYPES.contains(typeString)) { 88 mIsPrimitive = true; 89 mSimpleTypeName = typeString; 90 mQualifiedTypeName = typeString; 91 } else { 92 mQualifiedTypeName = typeString; 93 pos = typeString.lastIndexOf('.'); 94 if (pos > -1) { 95 mSimpleTypeName = typeString.substring(pos + 1); 96 } else { 97 mSimpleTypeName = typeString; 98 } 99 } 100 } 101 102 public ClassInfo asClassInfo() { 103 return mClass; 104 } 105 106 public boolean isPrimitive() { 107 return mIsPrimitive; 108 } 109 110 public String dimension() { 111 return mDimension; 112 } 113 114 public String simpleTypeName() { 115 return mSimpleTypeName; 116 } 117 118 public String qualifiedTypeName() { 119 return mQualifiedTypeName; 120 } 121 122 public String fullName() { 123 if (mFullName != null) { 124 return mFullName; 125 } else { 126 return fullName(new HashSet<String>()); 127 } 128 } 129 130 public static String typeArgumentsName(TypeInfo[] args, HashSet<String> typeVars) { 131 String result = "<"; 132 for (int i = 0; i < args.length; i++) { 133 result += args[i].fullName(typeVars); 134 if (i != args.length - 1) { 135 result += ", "; 136 } 137 } 138 result += ">"; 139 return result; 140 } 141 142 public String fullName(HashSet<String> typeVars) { 143 mFullName = fullNameNoDimension(typeVars) + mDimension; 144 return mFullName; 145 } 146 147 public String fullNameNoDimension(HashSet<String> typeVars) { 148 String fullName = null; 149 if (mIsTypeVariable) { 150 if (typeVars.contains(mQualifiedTypeName)) { 151 // don't recurse forever with the parameters. This handles 152 // Enum<K extends Enum<K>> 153 return mQualifiedTypeName; 154 } 155 typeVars.add(mQualifiedTypeName); 156 } 157 /* 158 * if (fullName != null) { return fullName; } 159 */ 160 fullName = mQualifiedTypeName; 161 if (mTypeArguments != null && mTypeArguments.length > 0) { 162 fullName += typeArgumentsName(mTypeArguments, typeVars); 163 } else if (mSuperBounds != null && mSuperBounds.length > 0) { 164 fullName += " super " + mSuperBounds[0].fullName(typeVars); 165 for (int i = 1; i < mSuperBounds.length; i++) { 166 fullName += " & " + mSuperBounds[i].fullName(typeVars); 167 } 168 } else if (mExtendsBounds != null && mExtendsBounds.length > 0) { 169 fullName += " extends " + mExtendsBounds[0].fullName(typeVars); 170 for (int i = 1; i < mExtendsBounds.length; i++) { 171 fullName += " & " + mExtendsBounds[i].fullName(typeVars); 172 } 173 } 174 return fullName; 175 } 176 177 public TypeInfo[] typeArguments() { 178 return mTypeArguments; 179 } 180 181 public void makeHDF(Data data, String base) { 182 makeHDFRecursive(data, base, false, false, new HashSet<String>()); 183 } 184 185 public void makeQualifiedHDF(Data data, String base) { 186 makeHDFRecursive(data, base, true, false, new HashSet<String>()); 187 } 188 189 public void makeHDF(Data data, String base, boolean isLastVararg, HashSet<String> typeVariables) { 190 makeHDFRecursive(data, base, false, isLastVararg, typeVariables); 191 } 192 193 public void makeQualifiedHDF(Data data, String base, HashSet<String> typeVariables) { 194 makeHDFRecursive(data, base, true, false, typeVariables); 195 } 196 197 private void makeHDFRecursive(Data data, String base, boolean qualified, boolean isLastVararg, 198 HashSet<String> typeVars) { 199 String label = qualified ? qualifiedTypeName() : simpleTypeName(); 200 label += (isLastVararg) ? "..." : dimension(); 201 data.setValue(base + ".label", label); 202 if (mIsTypeVariable || mIsWildcard) { 203 // could link to an @param tag on the class to describe this 204 // but for now, just don't make it a link 205 } else if (!isPrimitive() && mClass != null) { 206 if (mClass.isIncluded()) { 207 data.setValue(base + ".link", mClass.htmlPage()); 208 data.setValue(base + ".since", mClass.getSince()); 209 } else { 210 Doclava.federationTagger.tagAll(new ClassInfo[] {mClass}); 211 if (!mClass.getFederatedReferences().isEmpty()) { 212 FederatedSite site = mClass.getFederatedReferences().iterator().next(); 213 data.setValue(base + ".link", site.linkFor(mClass.htmlPage())); 214 data.setValue(base + ".federated", site.name()); 215 } 216 } 217 } 218 219 if (mIsTypeVariable) { 220 if (typeVars.contains(qualifiedTypeName())) { 221 // don't recurse forever with the parameters. This handles 222 // Enum<K extends Enum<K>> 223 return; 224 } 225 typeVars.add(qualifiedTypeName()); 226 } 227 if (mTypeArguments != null) { 228 TypeInfo.makeHDF(data, base + ".typeArguments", mTypeArguments, qualified, typeVars); 229 } 230 if (mSuperBounds != null) { 231 TypeInfo.makeHDF(data, base + ".superBounds", mSuperBounds, qualified, typeVars); 232 } 233 if (mExtendsBounds != null) { 234 TypeInfo.makeHDF(data, base + ".extendsBounds", mExtendsBounds, qualified, typeVars); 235 } 236 } 237 238 public static void makeHDF(Data data, String base, TypeInfo[] types, boolean qualified, 239 HashSet<String> typeVariables) { 240 final int N = types.length; 241 for (int i = 0; i < N; i++) { 242 types[i].makeHDFRecursive(data, base + "." + i, qualified, false, typeVariables); 243 } 244 } 245 246 public static void makeHDF(Data data, String base, TypeInfo[] types, boolean qualified) { 247 makeHDF(data, base, types, qualified, new HashSet<String>()); 248 } 249 250 void setTypeArguments(TypeInfo[] args) { 251 mTypeArguments = args; 252 } 253 254 void setBounds(TypeInfo[] superBounds, TypeInfo[] extendsBounds) { 255 mSuperBounds = superBounds; 256 mExtendsBounds = extendsBounds; 257 } 258 259 void setIsTypeVariable(boolean b) { 260 mIsTypeVariable = b; 261 } 262 263 void setIsWildcard(boolean b) { 264 mIsWildcard = b; 265 } 266 267 static HashSet<String> typeVariables(TypeInfo[] params) { 268 return typeVariables(params, new HashSet<String>()); 269 } 270 271 static HashSet<String> typeVariables(TypeInfo[] params, HashSet<String> result) { 272 for (TypeInfo t : params) { 273 if (t.mIsTypeVariable) { 274 result.add(t.mQualifiedTypeName); 275 } 276 } 277 return result; 278 } 279 280 281 public boolean isTypeVariable() { 282 return mIsTypeVariable; 283 } 284 285 public String defaultValue() { 286 if (mIsPrimitive) { 287 if ("boolean".equals(mSimpleTypeName)) { 288 return "false"; 289 } else { 290 return "0"; 291 } 292 } else { 293 return "null"; 294 } 295 } 296 297 @Override 298 public String toString() { 299 String returnString = ""; 300 returnString += 301 "Primitive?: " + mIsPrimitive + " TypeVariable?: " + mIsTypeVariable + " Wildcard?: " 302 + mIsWildcard + " Dimension: " + mDimension + " QualifedTypeName: " 303 + mQualifiedTypeName; 304 305 if (mTypeArguments != null) { 306 returnString += "\nTypeArguments: "; 307 for (TypeInfo tA : mTypeArguments) { 308 returnString += tA.qualifiedTypeName() + "(" + tA + ") "; 309 } 310 } 311 if (mSuperBounds != null) { 312 returnString += "\nSuperBounds: "; 313 for (TypeInfo tA : mSuperBounds) { 314 returnString += tA.qualifiedTypeName() + "(" + tA + ") "; 315 } 316 } 317 if (mExtendsBounds != null) { 318 returnString += "\nExtendsBounds: "; 319 for (TypeInfo tA : mExtendsBounds) { 320 returnString += tA.qualifiedTypeName() + "(" + tA + ") "; 321 } 322 } 323 return returnString; 324 } 325 326 private boolean mIsPrimitive; 327 private boolean mIsTypeVariable; 328 private boolean mIsWildcard; 329 private String mDimension; 330 private String mSimpleTypeName; 331 private String mQualifiedTypeName; 332 private ClassInfo mClass; 333 private TypeInfo[] mTypeArguments; 334 private TypeInfo[] mSuperBounds; 335 private TypeInfo[] mExtendsBounds; 336 private String mFullName; 337} 338