blob: 5fc2381914760a9a627cf8a5d4f7fc088ce0b63b [file] [log] [blame]
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javadoc;
import com.sun.javadoc.*;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ArrayType;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.code.Type.TypeVar;
import com.sun.tools.javac.util.List;
import static com.sun.tools.javac.code.TypeTag.ARRAY;
/**
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class TypeMaker {
public static com.sun.javadoc.Type getType(DocEnv env, Type t) {
return getType(env, t, true);
}
/**
* @param errToClassDoc if true, ERROR type results in a ClassDoc;
* false preserves legacy behavior
*/
public static com.sun.javadoc.Type getType(DocEnv env, Type t,
boolean errorToClassDoc) {
return getType(env, t, errorToClassDoc, true);
}
public static com.sun.javadoc.Type getType(DocEnv env, Type t,
boolean errToClassDoc, boolean considerAnnotations) {
try {
return getTypeImpl(env, t, errToClassDoc, considerAnnotations);
} catch (CompletionFailure cf) {
/* Quietly ignore completion failures and try again - the type
* for which the CompletionFailure was thrown shouldn't be completed
* again by the completer that threw the CompletionFailure.
*/
return getType(env, t, errToClassDoc, considerAnnotations);
}
}
@SuppressWarnings("fallthrough")
private static com.sun.javadoc.Type getTypeImpl(DocEnv env, Type t,
boolean errToClassDoc, boolean considerAnnotations) {
if (env.legacyDoclet) {
t = env.types.erasure(t);
}
if (considerAnnotations && t.isAnnotated()) {
return new AnnotatedTypeImpl(env, t);
}
switch (t.getTag()) {
case CLASS:
if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) {
return env.getParameterizedType((ClassType)t);
} else {
return env.getClassDoc((ClassSymbol)t.tsym);
}
case WILDCARD:
Type.WildcardType a = (Type.WildcardType)t;
return new WildcardTypeImpl(env, a);
case TYPEVAR: return new TypeVariableImpl(env, (TypeVar)t);
case ARRAY: return new ArrayTypeImpl(env, t);
case BYTE: return PrimitiveType.byteType;
case CHAR: return PrimitiveType.charType;
case SHORT: return PrimitiveType.shortType;
case INT: return PrimitiveType.intType;
case LONG: return PrimitiveType.longType;
case FLOAT: return PrimitiveType.floatType;
case DOUBLE: return PrimitiveType.doubleType;
case BOOLEAN: return PrimitiveType.booleanType;
case VOID: return PrimitiveType.voidType;
case ERROR:
if (errToClassDoc)
return env.getClassDoc((ClassSymbol)t.tsym);
// FALLTHRU
default:
return new PrimitiveType(t.tsym.getQualifiedName().toString());
}
}
/**
* Convert a list of javac types into an array of javadoc types.
*/
public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts) {
return getTypes(env, ts, new com.sun.javadoc.Type[ts.length()]);
}
/**
* Like the above version, but use and return the array given.
*/
public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts,
com.sun.javadoc.Type res[]) {
int i = 0;
for (Type t : ts) {
res[i++] = getType(env, t);
}
return res;
}
public static String getTypeName(Type t, boolean full) {
switch (t.getTag()) {
case ARRAY:
StringBuilder s = new StringBuilder();
while (t.hasTag(ARRAY)) {
s.append("[]");
t = ((ArrayType)t).elemtype;
}
s.insert(0, getTypeName(t, full));
return s.toString();
case CLASS:
return ClassDocImpl.getClassName((ClassSymbol)t.tsym, full);
default:
return t.tsym.getQualifiedName().toString();
}
}
/**
* Return the string representation of a type use. Bounds of type
* variables are not included; bounds of wildcard types are.
* Class names are qualified if "full" is true.
*/
static String getTypeString(DocEnv env, Type t, boolean full) {
// TODO: should annotations be included here?
if (t.isAnnotated()) {
t = t.unannotatedType();
}
switch (t.getTag()) {
case ARRAY:
StringBuilder s = new StringBuilder();
while (t.hasTag(ARRAY)) {
s.append("[]");
t = env.types.elemtype(t);
}
s.insert(0, getTypeString(env, t, full));
return s.toString();
case CLASS:
return ParameterizedTypeImpl.
parameterizedTypeToString(env, (ClassType)t, full);
case WILDCARD:
Type.WildcardType a = (Type.WildcardType)t;
return WildcardTypeImpl.wildcardTypeToString(env, a, full);
default:
return t.tsym.getQualifiedName().toString();
}
}
/**
* Return the formal type parameters of a class or method as an
* angle-bracketed string. Each parameter is a type variable with
* optional bounds. Class names are qualified if "full" is true.
* Return "" if there are no type parameters or we're hiding generics.
*/
static String typeParametersString(DocEnv env, Symbol sym, boolean full) {
if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) {
return "";
}
StringBuilder s = new StringBuilder();
for (Type t : sym.type.getTypeArguments()) {
s.append(s.length() == 0 ? "<" : ", ");
s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full));
}
s.append(">");
return s.toString();
}
/**
* Return the actual type arguments of a parameterized type as an
* angle-bracketed string. Class name are qualified if "full" is true.
* Return "" if there are no type arguments or we're hiding generics.
*/
static String typeArgumentsString(DocEnv env, ClassType cl, boolean full) {
if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) {
return "";
}
StringBuilder s = new StringBuilder();
for (Type t : cl.getTypeArguments()) {
s.append(s.length() == 0 ? "<" : ", ");
s.append(getTypeString(env, t, full));
}
s.append(">");
return s.toString();
}
private static class ArrayTypeImpl implements com.sun.javadoc.Type {
Type arrayType;
DocEnv env;
ArrayTypeImpl(DocEnv env, Type arrayType) {
this.env = env;
this.arrayType = arrayType;
}
private com.sun.javadoc.Type skipArraysCache = null;
public com.sun.javadoc.Type getElementType() {
return TypeMaker.getType(env, env.types.elemtype(arrayType));
}
private com.sun.javadoc.Type skipArrays() {
if (skipArraysCache == null) {
Type t;
for (t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) { }
skipArraysCache = TypeMaker.getType(env, t);
}
return skipArraysCache;
}
/**
* Return the type's dimension information, as a string.
* <p>
* For example, a two dimensional array of String returns '[][]'.
*/
public String dimension() {
StringBuilder dimension = new StringBuilder();
for (Type t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) {
dimension.append("[]");
}
return dimension.toString();
}
/**
* Return unqualified name of type excluding any dimension information.
* <p>
* For example, a two dimensional array of String returns 'String'.
*/
public String typeName() {
return skipArrays().typeName();
}
/**
* Return qualified name of type excluding any dimension information.
*<p>
* For example, a two dimensional array of String
* returns 'java.lang.String'.
*/
public String qualifiedTypeName() {
return skipArrays().qualifiedTypeName();
}
/**
* Return the simple name of this type excluding any dimension information.
*/
public String simpleTypeName() {
return skipArrays().simpleTypeName();
}
/**
* Return this type as a class. Array dimensions are ignored.
*
* @return a ClassDocImpl if the type is a Class.
* Return null if it is a primitive type..
*/
public ClassDoc asClassDoc() {
return skipArrays().asClassDoc();
}
/**
* Return this type as a <code>ParameterizedType</code> if it
* represents a parameterized type. Array dimensions are ignored.
*/
public ParameterizedType asParameterizedType() {
return skipArrays().asParameterizedType();
}
/**
* Return this type as a <code>TypeVariable</code> if it represents
* a type variable. Array dimensions are ignored.
*/
public TypeVariable asTypeVariable() {
return skipArrays().asTypeVariable();
}
/**
* Return null, as there are no arrays of wildcard types.
*/
public WildcardType asWildcardType() {
return null;
}
/**
* Return null, as there are no annotations of the type
*/
public AnnotatedType asAnnotatedType() {
return null;
}
/**
* Return this type as an <code>AnnotationTypeDoc</code> if it
* represents an annotation type. Array dimensions are ignored.
*/
public AnnotationTypeDoc asAnnotationTypeDoc() {
return skipArrays().asAnnotationTypeDoc();
}
/**
* Return true if this is an array of a primitive type.
*/
public boolean isPrimitive() {
return skipArrays().isPrimitive();
}
/**
* Return a string representation of the type.
*
* Return name of type including any dimension information.
* <p>
* For example, a two dimensional array of String returns
* <code>String[][]</code>.
*
* @return name of type including any dimension information.
*/
@Override
public String toString() {
return qualifiedTypeName() + dimension();
}
}
}