blob: 8572f59c86c0ecbc178d36c1a499ef9a528565d1 [file] [log] [blame]
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.doclava;
import com.google.clearsilver.jsilver.data.Data;
import java.util.*;
public class TypeInfo {
public static final Set<String> PRIMITIVE_TYPES = Collections.unmodifiableSet(
new HashSet<String>(Arrays.asList("boolean", "byte", "char", "double", "float", "int",
"long", "short", "void")));
public TypeInfo(boolean isPrimitive, String dimension, String simpleTypeName,
String qualifiedTypeName, ClassInfo cl) {
mIsPrimitive = isPrimitive;
mDimension = dimension;
mSimpleTypeName = simpleTypeName;
mQualifiedTypeName = qualifiedTypeName;
mClass = cl;
}
public TypeInfo(String typeString) {
// VarArgs
if (typeString.endsWith("...")) {
typeString = typeString.substring(0, typeString.length() - 3);
}
// Generic parameters
int paramStartPos = typeString.indexOf('<');
if (paramStartPos > -1) {
ArrayList<TypeInfo> generics = new ArrayList<TypeInfo>();
int paramEndPos = typeString.lastIndexOf('>');
int entryStartPos = paramStartPos + 1;
int bracketNesting = 0;
for (int i = entryStartPos; i < paramEndPos; i++) {
char c = typeString.charAt(i);
if (c == ',' && bracketNesting == 0) {
String entry = typeString.substring(entryStartPos, i).trim();
TypeInfo info = new TypeInfo(entry);
generics.add(info);
entryStartPos = i + 1;
} else if (c == '<') {
bracketNesting++;
} else if (c == '>') {
bracketNesting--;
}
}
TypeInfo info = new TypeInfo(typeString.substring(entryStartPos, paramEndPos).trim());
generics.add(info);
mTypeArguments = new TypeInfo[generics.size()];
generics.toArray(mTypeArguments);
if (paramEndPos < typeString.length() - 1) {
typeString = typeString.substring(0,paramStartPos) + typeString.substring(paramEndPos + 1);
} else {
typeString = typeString.substring(0,paramStartPos);
}
}
// Dimensions
int pos = typeString.indexOf('[');
if (pos > -1) {
mDimension = typeString.substring(pos);
typeString = typeString.substring(0, pos);
} else {
mDimension = "";
}
if (PRIMITIVE_TYPES.contains(typeString)) {
mIsPrimitive = true;
mSimpleTypeName = typeString;
mQualifiedTypeName = typeString;
} else {
mQualifiedTypeName = typeString;
pos = typeString.lastIndexOf('.');
if (pos > -1) {
mSimpleTypeName = typeString.substring(pos + 1);
} else {
mSimpleTypeName = typeString;
}
}
}
public ClassInfo asClassInfo() {
return mClass;
}
public boolean isPrimitive() {
return mIsPrimitive;
}
public String dimension() {
return mDimension;
}
public String simpleTypeName() {
return mSimpleTypeName;
}
public String qualifiedTypeName() {
return mQualifiedTypeName;
}
public String fullName() {
if (mFullName != null) {
return mFullName;
} else {
return fullName(new HashSet<String>());
}
}
public static String typeArgumentsName(TypeInfo[] args, HashSet<String> typeVars) {
String result = "<";
for (int i = 0; i < args.length; i++) {
result += args[i].fullName(typeVars);
if (i != args.length - 1) {
result += ", ";
}
}
result += ">";
return result;
}
public String fullName(HashSet<String> typeVars) {
mFullName = fullNameNoDimension(typeVars) + mDimension;
return mFullName;
}
public String fullNameNoDimension(HashSet<String> typeVars) {
String fullName = null;
if (mIsTypeVariable) {
if (typeVars.contains(mQualifiedTypeName)) {
// don't recurse forever with the parameters. This handles
// Enum<K extends Enum<K>>
return mQualifiedTypeName;
}
typeVars.add(mQualifiedTypeName);
}
/*
* if (fullName != null) { return fullName; }
*/
fullName = mQualifiedTypeName;
if (mTypeArguments != null && mTypeArguments.length > 0) {
fullName += typeArgumentsName(mTypeArguments, typeVars);
} else if (mSuperBounds != null && mSuperBounds.length > 0) {
fullName += " super " + mSuperBounds[0].fullName(typeVars);
for (int i = 1; i < mSuperBounds.length; i++) {
fullName += " & " + mSuperBounds[i].fullName(typeVars);
}
} else if (mExtendsBounds != null && mExtendsBounds.length > 0) {
fullName += " extends " + mExtendsBounds[0].fullName(typeVars);
for (int i = 1; i < mExtendsBounds.length; i++) {
fullName += " & " + mExtendsBounds[i].fullName(typeVars);
}
}
return fullName;
}
public TypeInfo[] typeArguments() {
return mTypeArguments;
}
public void makeHDF(Data data, String base) {
makeHDFRecursive(data, base, false, false, new HashSet<String>());
}
public void makeQualifiedHDF(Data data, String base) {
makeHDFRecursive(data, base, true, false, new HashSet<String>());
}
public void makeHDF(Data data, String base, boolean isLastVararg, HashSet<String> typeVariables) {
makeHDFRecursive(data, base, false, isLastVararg, typeVariables);
}
public void makeQualifiedHDF(Data data, String base, HashSet<String> typeVariables) {
makeHDFRecursive(data, base, true, false, typeVariables);
}
private void makeHDFRecursive(Data data, String base, boolean qualified, boolean isLastVararg,
HashSet<String> typeVars) {
String label = qualified ? qualifiedTypeName() : simpleTypeName();
label += (isLastVararg) ? "..." : dimension();
data.setValue(base + ".label", label);
if (mIsTypeVariable || mIsWildcard) {
// could link to an @param tag on the class to describe this
// but for now, just don't make it a link
} else if (!isPrimitive() && mClass != null) {
if (mClass.isIncluded()) {
data.setValue(base + ".link", mClass.htmlPage());
data.setValue(base + ".since", mClass.getSince());
} else {
Doclava.federationTagger.tagAll(new ClassInfo[] {mClass});
if (!mClass.getFederatedReferences().isEmpty()) {
FederatedSite site = mClass.getFederatedReferences().iterator().next();
data.setValue(base + ".link", site.linkFor(mClass.htmlPage()));
data.setValue(base + ".federated", site.name());
}
}
}
if (mIsTypeVariable) {
if (typeVars.contains(qualifiedTypeName())) {
// don't recurse forever with the parameters. This handles
// Enum<K extends Enum<K>>
return;
}
typeVars.add(qualifiedTypeName());
}
if (mTypeArguments != null) {
TypeInfo.makeHDF(data, base + ".typeArguments", mTypeArguments, qualified, typeVars);
}
if (mSuperBounds != null) {
TypeInfo.makeHDF(data, base + ".superBounds", mSuperBounds, qualified, typeVars);
}
if (mExtendsBounds != null) {
TypeInfo.makeHDF(data, base + ".extendsBounds", mExtendsBounds, qualified, typeVars);
}
}
public static void makeHDF(Data data, String base, TypeInfo[] types, boolean qualified,
HashSet<String> typeVariables) {
final int N = types.length;
for (int i = 0; i < N; i++) {
types[i].makeHDFRecursive(data, base + "." + i, qualified, false, typeVariables);
}
}
public static void makeHDF(Data data, String base, TypeInfo[] types, boolean qualified) {
makeHDF(data, base, types, qualified, new HashSet<String>());
}
void setTypeArguments(TypeInfo[] args) {
mTypeArguments = args;
}
void setBounds(TypeInfo[] superBounds, TypeInfo[] extendsBounds) {
mSuperBounds = superBounds;
mExtendsBounds = extendsBounds;
}
void setIsTypeVariable(boolean b) {
mIsTypeVariable = b;
}
void setIsWildcard(boolean b) {
mIsWildcard = b;
}
static HashSet<String> typeVariables(TypeInfo[] params) {
return typeVariables(params, new HashSet());
}
static HashSet<String> typeVariables(TypeInfo[] params, HashSet<String> result) {
for (TypeInfo t : params) {
if (t.mIsTypeVariable) {
result.add(t.mQualifiedTypeName);
}
}
return result;
}
public boolean isTypeVariable() {
return mIsTypeVariable;
}
public String defaultValue() {
if (mIsPrimitive) {
if ("boolean".equals(mSimpleTypeName)) {
return "false";
} else {
return "0";
}
} else {
return "null";
}
}
@Override
public String toString() {
String returnString = "";
returnString +=
"Primitive?: " + mIsPrimitive + " TypeVariable?: " + mIsTypeVariable + " Wildcard?: "
+ mIsWildcard + " Dimension: " + mDimension + " QualifedTypeName: "
+ mQualifiedTypeName;
if (mTypeArguments != null) {
returnString += "\nTypeArguments: ";
for (TypeInfo tA : mTypeArguments) {
returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
}
}
if (mSuperBounds != null) {
returnString += "\nSuperBounds: ";
for (TypeInfo tA : mSuperBounds) {
returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
}
}
if (mExtendsBounds != null) {
returnString += "\nExtendsBounds: ";
for (TypeInfo tA : mExtendsBounds) {
returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
}
}
return returnString;
}
private boolean mIsPrimitive;
private boolean mIsTypeVariable;
private boolean mIsWildcard;
private String mDimension;
private String mSimpleTypeName;
private String mQualifiedTypeName;
private ClassInfo mClass;
private TypeInfo[] mTypeArguments;
private TypeInfo[] mSuperBounds;
private TypeInfo[] mExtendsBounds;
private String mFullName;
}