下面列出了javax.lang.model.element.TypeParameterElement#getBounds ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Make a TypeVariableName for the given TypeMirror. This form is used internally to avoid
* infinite recursion in cases like {@code Enum<E extends Enum<E>>}. When we encounter such a
* thing, we will make a TypeVariableName without bounds and add that to the {@code typeVariables}
* map before looking up the bounds. Then if we encounter this TypeVariable again while
* constructing the bounds, we can just return it from the map. And, the code that put the entry
* in {@code variables} will make sure that the bounds are filled in before returning.
*/
static TypeVariableName get(
TypeVariable mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) {
TypeParameterElement element = (TypeParameterElement) mirror.asElement();
TypeVariableName typeVariableName = typeVariables.get(element);
if (typeVariableName == null) {
// Since the bounds field is public, we need to make it an unmodifiableList. But we control
// the List that that wraps, which means we can change it before returning.
List<TypeName> bounds = new ArrayList<>();
List<TypeName> visibleBounds = Collections.unmodifiableList(bounds);
typeVariableName = new TypeVariableName(element.getSimpleName().toString(), visibleBounds);
typeVariables.put(element, typeVariableName);
for (TypeMirror typeMirror : element.getBounds()) {
bounds.add(TypeName.get(typeMirror, typeVariables));
}
bounds.remove(OBJECT);
}
return typeVariableName;
}
private Map<TypeParameterElement, TypeMirror> getChildInstanceOfClassFromGeneric(final TypeElement typeElement, final Class<?> aClass) {
Map<TypeParameterElement, TypeMirror> result = new HashMap<>();
for (TypeParameterElement element : typeElement.getTypeParameters()) {
List<? extends TypeMirror> bounds = element.getBounds();
for (TypeMirror bound : bounds) {
if (bound instanceof DeclaredType && ((DeclaredType) bound).asElement() instanceof TypeElement) {
Collection<TypeMirror> viewsType = getViewsType((TypeElement) ((DeclaredType) bound).asElement());
boolean isViewType = false;
for (TypeMirror viewType : viewsType) {
if (((DeclaredType) viewType).asElement().toString().equals(aClass.getCanonicalName())) {
isViewType = true;
}
}
if (isViewType) {
result.put(element, bound);
break;
}
}
}
}
return result;
}
/**
* FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
*/
private void genFormalTypeParameter(TypeParameterElement typeParam, StringBuilder sb) {
sb.append(ElementUtil.getName(typeParam));
List<? extends TypeMirror> bounds = typeParam.getBounds();
if (bounds.isEmpty()) {
sb.append(':').append(JAVA_OBJECT_SIGNATURE);
} else {
if (TypeUtil.isInterface(bounds.get(0))) {
sb.append(':');
}
for (TypeMirror bound : bounds) {
sb.append(':');
genTypeSignature(bound, sb);
}
}
}
@Test
public void testMultipleTypeParameters() throws IOException {
compile("class Foo<T, U extends java.lang.CharSequence> { }");
TypeMirror objectType = elements.getTypeElement("java.lang.Object").asType();
TypeMirror charSequenceType = elements.getTypeElement("java.lang.CharSequence").asType();
TypeElement fooElement = elements.getTypeElement("Foo");
List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters();
assertSame(2, typeParameters.size());
TypeParameterElement tParam = typeParameters.get(0);
List<? extends TypeMirror> bounds = tParam.getBounds();
assertSame(1, bounds.size());
assertSameType(objectType, bounds.get(0));
TypeParameterElement uParam = typeParameters.get(1);
bounds = uParam.getBounds();
assertSame(1, bounds.size());
assertSameType(charSequenceType, bounds.get(0));
}
/**
* The type parameters to place on the builder, with the "extends ..." bounds.
*/
String alligatorWithBounds() {
List<TypeParameterElement> allParameters = allParameters();
if (allParameters.isEmpty()) {
return "";
}
StringBuilder alligator = new StringBuilder("<");
String separator = "";
for (TypeParameterElement param : allParameters) {
alligator.append(separator);
separator = ", ";
alligator.append(param.toString());
for (TypeMirror bound : param.getBounds()) {
alligator.append(" extends ").append(bound);
}
}
return alligator.append(">").toString();
}
/**
* Make a TypeVariableName for the given TypeMirror. This form is used internally to avoid
* infinite recursion in cases like {@code Enum<E extends Enum<E>>}. When we encounter such a
* thing, we will make a TypeVariableName without bounds and add that to the {@code typeVariables}
* map before looking up the bounds. Then if we encounter this TypeVariable again while
* constructing the bounds, we can just return it from the map. And, the code that put the entry
* in {@code variables} will make sure that the bounds are filled in before returning.
*/
static TypeVariableName get(
TypeVariable mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) {
TypeParameterElement element = (TypeParameterElement) mirror.asElement();
TypeVariableName typeVariableName = typeVariables.get(element);
if (typeVariableName == null) {
// Since the bounds field is public, we need to make it an unmodifiableList. But we control
// the List that that wraps, which means we can change it before returning.
List<TypeName> bounds = new ArrayList<>();
List<TypeName> visibleBounds = Collections.unmodifiableList(bounds);
typeVariableName = new TypeVariableName(element.getSimpleName().toString(), visibleBounds);
typeVariables.put(element, typeVariableName);
for (TypeMirror typeMirror : element.getBounds()) {
bounds.add(TypeName.get(typeMirror, typeVariables));
}
bounds.remove(OBJECT);
}
return typeVariableName;
}
private static void appendTypeParameterWithBounds(
TypeParameterElement typeParameter, StringBuilder sb) {
appendAnnotations(typeParameter.getAnnotationMirrors(), sb);
sb.append(typeParameter.getSimpleName());
String sep = " extends ";
for (TypeMirror bound : typeParameter.getBounds()) {
if (!isUnannotatedJavaLangObject(bound)) {
sb.append(sep);
sep = " & ";
sb.append(encodeWithAnnotations(bound));
}
}
}
private static String createHtmlHeader(boolean deprecated, TypeElement e) {
StringBuilder sb = new StringBuilder();
sb.append("<html>");
if (deprecated) sb.append("<s>");
sb.append(e.getSimpleName());
if (deprecated) sb.append("</s>");
List<? extends TypeParameterElement> typeParams = e.getTypeParameters();
if (typeParams != null && !typeParams.isEmpty()) {
sb.append("<"); // NOI18N
for(Iterator<? extends TypeParameterElement> it = typeParams.iterator(); it.hasNext();) {
TypeParameterElement tp = it.next();
sb.append(tp.getSimpleName());
try {
List<? extends TypeMirror> bounds = tp.getBounds();
if (!bounds.isEmpty()) {
sb.append(translateToHTML(printBounds(bounds)));
}
}
catch (NullPointerException npe) {
}
if (it.hasNext()) {
sb.append(", "); // NOI18N
}
}
sb.append(">"); // NOI18N
}
return sb.toString();
}
private void appendTypeParameterWithBounds(StringBuilder sb, TypeParameterElement typeParameter) {
sb.append(typeParameter.getSimpleName());
String sep = " extends ";
for (TypeMirror bound : typeParameter.getBounds()) {
if (!bound.toString().equals("java.lang.Object")) {
sb.append(sep);
sep = " & ";
bound.accept(TO_STRING_TYPE_VISITOR, sb);
}
}
}
public TypeParamDef apply(TypeParameterElement item) {
List<ClassRef> typeRefs = new ArrayList();
for (TypeMirror typeMirror : item.getBounds()) {
//TODO: Fix this
//typeRefs.add(toTypeRef.apply(typeMirror));
}
return new TypeParamDefBuilder()
.withName(item.getSimpleName().toString())
.withBounds(typeRefs)
.build();
}
public List<? extends TypeMirror> getBounds(TypeParameterElement tpe) {
List<? extends TypeMirror> bounds = tpe.getBounds();
if (!bounds.isEmpty()) {
TypeMirror upperBound = bounds.get(bounds.size() - 1);
if (ignoreBounds(upperBound)) {
return Collections.emptyList();
}
}
return bounds;
}
private void appendTypeParameterWithBounds(StringBuilder sb, TypeParameterElement typeParameter) {
sb.append(typeParameter.getSimpleName());
String sep = " extends ";
for (TypeMirror bound : typeParameter.getBounds()) {
if (!bound.toString().equals("java.lang.Object")) {
sb.append(sep);
sep = " & ";
bound.accept(TO_STRING_TYPE_VISITOR, sb);
}
}
}
/** Returns type variable equivalent to {@code element}. */
public static TypeVariableName get(TypeParameterElement element) {
String name = element.getSimpleName().toString();
List<? extends TypeMirror> boundsMirrors = element.getBounds();
List<TypeName> boundsTypeNames = new ArrayList<>();
for (TypeMirror typeMirror : boundsMirrors) {
boundsTypeNames.add(TypeName.get(typeMirror));
}
return TypeVariableName.of(name, boundsTypeNames);
}
@Override
public Integer visitTypeVariable(TypeVariable t, Set<Element> visiting) {
int result = hashKind(HASH_SEED, t);
result *= HASH_MULTIPLIER;
result += t.getLowerBound().accept(this, visiting);
TypeParameterElement element = (TypeParameterElement) t.asElement();
for (TypeMirror bound : element.getBounds()) {
result *= HASH_MULTIPLIER;
result += bound.accept(this, visiting);
}
return result;
}
void validateGenericEntityListener(
TypeElement classElement, EntityMeta entityMeta, TypeElement listenerElement) {
EntityAnnot entityAnnot = entityMeta.getEntityAnnot();
List<? extends TypeParameterElement> typeParams = listenerElement.getTypeParameters();
if (typeParams.size() == 0) {
throw new AptIllegalStateException("typeParams size should be more than 0");
}
if (typeParams.size() > 1) {
throw new AptException(
Message.DOMA4227,
classElement,
entityAnnot.getAnnotationMirror(),
entityAnnot.getListener(),
new Object[] {});
}
TypeParameterElement typeParam = typeParams.get(0);
for (TypeMirror bound : typeParam.getBounds()) {
if (!ctx.getMoreTypes().isAssignableWithErasure(classElement.asType(), bound)) {
throw new AptException(
Message.DOMA4229,
classElement,
entityAnnot.getAnnotationMirror(),
entityAnnot.getListener(),
new Object[] {typeParam.getSimpleName(), bound, classElement.getQualifiedName()});
}
}
if (findListenerTypeParam(listenerElement, 0) == null) {
throw new AptException(
Message.DOMA4228,
classElement,
entityAnnot.getAnnotationMirror(),
entityAnnot.getListener(),
new Object[] {typeParam.getSimpleName()});
}
}
private List<Type.Defined> getBounds(Type.Parameters parameters, TypeParameterElement p) {
List<Type.Defined> bounds = new ArrayList<>();
for (TypeMirror b : p.getBounds()) {
bounds.add((Type.Defined) b.accept(converter, parameters));
}
return bounds;
}
void validateInheritedEntityListener(
TypeElement classElement, EntityMeta entityMeta, TypeElement inheritedListenerElement) {
EntityAnnot entityAnnot = entityMeta.getEntityAnnot();
List<? extends TypeParameterElement> typeParams =
inheritedListenerElement.getTypeParameters();
if (typeParams.size() == 0) {
throw new AptException(
Message.DOMA4230,
classElement,
entityAnnot.getAnnotationMirror(),
new Object[] {
inheritedListenerElement.getQualifiedName(), classElement.getQualifiedName()
});
}
TypeParameterElement typeParam = typeParams.get(0);
for (TypeMirror bound : typeParam.getBounds()) {
if (!ctx.getMoreTypes().isAssignableWithErasure(classElement.asType(), bound)) {
throw new AptException(
Message.DOMA4231,
classElement,
entityAnnot.getAnnotationMirror(),
new Object[] {
inheritedListenerElement.getQualifiedName(),
typeParam.getSimpleName(),
bound,
classElement.getQualifiedName()
});
}
}
}
@Test
public void testUnboundedTypeParameter() throws IOException {
compile("class Foo<T> { }");
TypeElement fooElement = elements.getTypeElement("Foo");
TypeMirror objectType = elements.getTypeElement("java.lang.Object").asType();
List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters();
assertSame(1, typeParameters.size());
TypeParameterElement typeParam = typeParameters.get(0);
List<? extends TypeMirror> bounds = typeParam.getBounds();
assertSame(1, bounds.size());
assertSameType(objectType, bounds.get(0));
}
private String createHtmlHeader(CompilationInfo info, TypeElement e, boolean isDeprecated, boolean isInherited, boolean fqn) {
StringBuilder sb = new StringBuilder();
if ( isDeprecated ) {
sb.append("<s>"); // NOI18N
}
if( isInherited ) {
sb.append( "<font color=" + ui.getInheritedColor() + ">" ); // NOI18N
}
sb.append(Utils.escape(
fqn?
e.getQualifiedName().toString():
e.getSimpleName().toString()));
if ( isDeprecated ) {
sb.append("</s>"); // NOI18N
}
// sb.append(print(info, e.asType()));
List<? extends TypeParameterElement> typeParams = e.getTypeParameters();
//System.out.println("Element " + e + "type params" + typeParams.size() );
if ( typeParams != null && !typeParams.isEmpty() ) {
sb.append("<"); // NOI18N
for( Iterator<? extends TypeParameterElement> it = typeParams.iterator(); it.hasNext(); ) {
TypeParameterElement tp = it.next();
sb.append( Utils.escape(tp.getSimpleName().toString()) );
try { // XXX Verry ugly -> file a bug against Javac?
List<? extends TypeMirror> bounds = tp.getBounds();
//System.out.println( tp.getSimpleName() + " bounds size " + bounds.size() );
if ( !bounds.isEmpty() ) {
sb.append(printBounds(info, bounds, fqn));
}
}
catch ( NullPointerException npe ) {
System.err.println("El " + e );
npe.printStackTrace();
}
if ( it.hasNext() ) {
sb.append(", "); // NOI18N
}
}
sb.append(">"); // NOI18N
}
// Add superclass and implemented interfaces
TypeMirror sc = e.getSuperclass();
String scName = print(info, sc, fqn);
if ( sc == null ||
e.getKind() == ElementKind.ENUM ||
e.getKind() == ElementKind.ANNOTATION_TYPE ||
"Object".equals(scName) || // NOI18N
"<none>".equals(scName)) { // NOI18N
scName = null;
}
List<? extends TypeMirror> ifaces = e.getInterfaces();
if ( ( scName != null || !ifaces.isEmpty() ) &&
e.getKind() != ElementKind.ANNOTATION_TYPE ) {
sb.append( " :: " ); // NOI18N
if (scName != null) {
sb.append( "<font color=" + ui.getTypeColor() + ">" ); // NOI18N
sb.append( scName );
sb.append("</font>"); // NOI18N
}
if ( !ifaces.isEmpty() ) {
if ( scName != null ) {
sb.append( " : " ); // NOI18N
}
for (Iterator<? extends TypeMirror> it = ifaces.iterator(); it.hasNext();) {
TypeMirror typeMirror = it.next();
sb.append( "<font color=" + ui.getTypeColor() + ">" ); // NOI18N
sb.append( print(info, typeMirror, fqn) );
sb.append("</font>"); // NOI18N
if ( it.hasNext() ) {
sb.append(", "); // NOI18N
}
}
}
}
return sb.toString();
}
/**
* Returns a representation of the given {@code @RetroWeibo.Builder} class or interface. If the
* class or interface has abstract methods that could not be part of any builder, emits error
* messages and returns null.
*/
private Optional<Builder> builderFrom(
TypeElement builderTypeElement, Optional<ExecutableElement> validateMethod) {
// We require the builder to have the same type parameters as the @RetroWeibo class, meaning the
// same names and bounds. In principle the type parameters could have different names, but that
// would be confusing, and our code would reject it anyway because it wouldn't consider that
// the return type of Foo<U> build() was really the same as the declaration of Foo<T>. This
// check produces a better error message in that case and similar ones.
boolean ok = true;
int nTypeParameters = autoValueClass.getTypeParameters().size();
if (nTypeParameters != builderTypeElement.getTypeParameters().size()) {
ok = false;
} else {
for (int i = 0; i < nTypeParameters; i++) {
TypeParameterElement autoValueParam = autoValueClass.getTypeParameters().get(i);
TypeParameterElement builderParam = builderTypeElement.getTypeParameters().get(i);
if (!autoValueParam.getSimpleName().equals(builderParam.getSimpleName())) {
ok = false;
break;
}
Set<TypeMirror> autoValueBounds = new TypeMirrorSet(autoValueParam.getBounds());
Set<TypeMirror> builderBounds = new TypeMirrorSet(builderParam.getBounds());
if (!autoValueBounds.equals(builderBounds)) {
ok = false;
break;
}
}
}
if (!ok) {
errorReporter.reportError(
"Type parameters of " + builderTypeElement + " must have same names and bounds as "
+ "type parameters of " + autoValueClass, builderTypeElement);
return Optional.absent();
}
String typeParams = TypeSimplifier.actualTypeParametersString(autoValueClass);
List<ExecutableElement> buildMethods = new ArrayList<ExecutableElement>();
List<ExecutableElement> setterMethods = new ArrayList<ExecutableElement>();
// For each abstract method (in builderTypeElement or inherited), check that it is either
// a setter method or a build method. A setter method has one argument and returns
// builderTypeElement. A build method has no arguments and returns the @RetroWeibo class.
// Record each method in one of the two lists.
for (ExecutableElement method : abstractMethods(builderTypeElement)) {
boolean thisOk = false;
int nParameters = method.getParameters().size();
if (nParameters == 0
&& TYPE_EQUIVALENCE.equivalent(method.getReturnType(), autoValueClass.asType())) {
buildMethods.add(method);
thisOk = true;
} else if (nParameters == 1
&& TYPE_EQUIVALENCE.equivalent(method.getReturnType(), builderTypeElement.asType())) {
setterMethods.add(method);
thisOk = true;
}
if (!thisOk) {
errorReporter.reportError(
"Builder methods must either have no arguments and return "
+ autoValueClass + typeParams + " or have one argument and return "
+ builderTypeElement + typeParams,
method);
ok = false;
}
}
if (buildMethods.isEmpty()) {
errorReporter.reportError(
"Builder must have a single no-argument method returning "
+ autoValueClass + typeParams,
builderTypeElement);
ok = false;
} else if (buildMethods.size() > 1) {
// More than one eligible build method. Emit an error for each one, that is attached to
// that build method.
for (ExecutableElement buildMethod : buildMethods) {
errorReporter.reportError(
"Builder must have a single no-argument method returning "
+ autoValueClass + typeParams,
buildMethod);
}
ok = false;
}
if (ok) {
return Optional.of(new Builder(
builderTypeElement,
Iterables.getOnlyElement(buildMethods),
setterMethods,
validateMethod));
} else {
return Optional.absent();
}
}