blob: e939f5bf311ed9c67b2caf9bfe0cee1cd1268952 [file] [log] [blame]
Ben Dodson920dbbb2010-08-04 15:21:06 -07001/*
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) {
Ben Dodson9ccd9e32010-08-06 17:18:52 -0700268 return typeVariables(params, new HashSet<String>());
Ben Dodson920dbbb2010-08-04 15:21:06 -0700269 }
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}