use of javax.lang.model.type.TypeVariable in project immutables by immutables.
the class TypeStringProvider method caseType.
void caseType(TypeMirror type) {
if (ended) {
// to prevent additional recursive effects when using workaround
return;
}
switch(type.getKind()) {
case ERROR:
unresolvedTypeHasOccured = true;
// $FALL-THROUGH$
case DECLARED:
DeclaredType declaredType = (DeclaredType) type;
appendResolved(declaredType);
appendTypeArguments(type, declaredType);
break;
case ARRAY:
TypeMirror componentType = ((ArrayType) type).getComponentType();
int mark = buffer.length();
caseType(componentType);
cutTypeArgument(type, mark);
buffer.append('[').append(']');
break;
case WILDCARD:
WildcardType wildcard = (WildcardType) type;
@Nullable TypeMirror extendsBound = wildcard.getExtendsBound();
@Nullable TypeMirror superBound = wildcard.getSuperBound();
if (extendsBound != null) {
buffer.append("? extends ");
caseType(extendsBound);
} else if (superBound != null) {
buffer.append("? super ");
caseType(superBound);
} else {
buffer.append('?');
}
break;
case TYPEVAR:
if (allowedTypevars.length != 0) {
TypeVariable typeVariable = (TypeVariable) type;
String var = typeVariable.toString();
int indexOfVar = Arrays.asList(allowedTypevars).indexOf(var);
if (indexOfVar >= 0) {
if (typevarArguments != null) {
buffer.append(typevarArguments[indexOfVar]);
} else {
hasTypeVariables = true;
buffer.append(var);
}
break;
}
// If we don't have such parameter we consider this is the quirk
// that was witnessed in Eclipse, we let the code below deal with it.
}
// ended flag
if (tryToUseSourceAsAWorkaround()) {
ended = true;
break;
}
reporter.withElement(element).error("It is a compiler/annotation processing bug to receive type variable '%s' here." + " To avoid it — do not use not yet generated types in %s attribute", type, element.getSimpleName());
// just append as toString whatever we have
buffer.append(type);
break;
case BOOLEAN:
case CHAR:
case INT:
case DOUBLE:
case FLOAT:
case SHORT:
case LONG:
case BYTE:
String typeName = Ascii.toLowerCase(type.getKind().name());
buffer.append(typeName);
/* Just skip type annotations with primitives (for now?) too many problems/breakages
List<? extends AnnotationMirror> annotations = null;
if (processNestedTypeUseAnnotations
&& startType != type
&& !(annotations = AnnotationMirrors.from(type)).isEmpty()) {
buffer.append(typeAnnotationsToBuffer(annotations, true)).append(typeName);
} else {
buffer.append(typeName);
}*/
break;
default:
buffer.append(type);
}
// workaround for Javac problem
if (unresolvedTypeHasOccured && buffer.toString().contains("<any>")) {
if (tryToUseSourceAsAWorkaround()) {
ended = true;
}
}
}
use of javax.lang.model.type.TypeVariable in project auto by google.
the class BuilderMethodClassifierForAutoBuilder method rewriteParameterTypes.
// Rewrites the parameter types of the executable so they use the type variables of the builder
// where appropriate.
//
// Suppose we have something like this:
//
// static <E> Set<E> singletonSet(E elem) {...}
//
// @AutoBuilder(callMethod = "singletonSet")
// interface SingletonSetBuilder<E> {
// SingletonSetBuilder<E> setElem(E elem);
// Set<E> build();
// }
//
// We want to check that the type of the setter `setElem` matches the type of the
// parameter it is setting. But in fact it doesn't: the type of the setter is
// E-of-SingletonSetBuilder while the type of the parameter is E-of-singletonSet. So we
// need to rewrite any type variables mentioned in parameters so that they use the corresponding
// types from the builder. We want to return a map where "elem" is mapped to
// E-of-SingletonSetBuilder, even though the `elem` that we get from the parameters of
// singletonSet is going to be E-of-singletonSet. And we also want that to work if the parameter
// is something more complicated, like List<? extends E>.
//
// For the corresponding situation with AutoValue, we have a way of dodging the problem somewhat.
// For an @AutoValue class Foo<E> with a builder Builder<E>, we can craft a DeclaredType
// Foo<E> where the E comes from Builder<E>, and we can use Types.asMemberOf to determine the
// return types of methods (which are what we want to rewrite in that case). But that doesn't
// work here because singletonSet is static and Types.asMemberOf would have no effect on it.
//
// So instead we take the type of each parameter and feed it through a TypeVisitor that rewrites
// type variables, rewriting from E-of-singletonSet to E-of-SingletonSetBuilder. Then we can use
// Types.isSameType or Types.isAssignable and it will work as we expect.
//
// In principle a similar situation arises with the return type Set<E> of singletonSet versus
// the return type Set<E> of SingletonSetBuilder.build(). But in fact we only use
// MoreTypes.equivalence to compare those, and that returns true for distinct type variables if
// they have the same name and bounds.
private static ImmutableMap<String, TypeMirror> rewriteParameterTypes(ExecutableElement executable, TypeElement builderType, ErrorReporter errorReporter, Types typeUtils) {
ImmutableList<TypeParameterElement> executableTypeParams = executableTypeParams(executable);
List<? extends TypeParameterElement> builderTypeParams = builderType.getTypeParameters();
if (!BuilderSpec.sameTypeParameters(executableTypeParams, builderTypeParams)) {
errorReporter.abortWithError(builderType, "[AutoBuilderTypeParams] Builder type parameters %s must match type parameters %s of %s", TypeEncoder.typeParametersString(builderTypeParams), TypeEncoder.typeParametersString(executableTypeParams), AutoBuilderProcessor.executableString(executable));
}
if (executableTypeParams.isEmpty()) {
// variables to substitute.
return executable.getParameters().stream().collect(toImmutableMap(v -> v.getSimpleName().toString(), Element::asType));
}
Map<Equivalence.Wrapper<TypeVariable>, TypeMirror> typeVariables = new LinkedHashMap<>();
for (int i = 0; i < executableTypeParams.size(); i++) {
TypeVariable from = MoreTypes.asTypeVariable(executableTypeParams.get(i).asType());
TypeVariable to = MoreTypes.asTypeVariable(builderTypeParams.get(i).asType());
typeVariables.put(MoreTypes.equivalence().wrap(from), to);
}
Function<TypeVariable, TypeMirror> substitute = v -> typeVariables.get(MoreTypes.equivalence().wrap(v));
return executable.getParameters().stream().collect(toImmutableMap(v -> v.getSimpleName().toString(), v -> TypeVariables.substituteTypeVariables(v.asType(), substitute, typeUtils)));
}
use of javax.lang.model.type.TypeVariable in project auto by google.
the class TypeVariables method canAssignStaticMethodResult.
/**
* Tests whether a given parameter can be given to a static method like {@code
* ImmutableMap.copyOf} to produce a value that can be assigned to the given target type.
*
* <p>For example, suppose we have this method in {@code ImmutableMap}:<br>
* {@code static <K, V> ImmutableMap<K, V> copyOf(Map<? extends K, ? extends V>)}<br>
* and we want to know if we can do this:
*
* <pre>
* {@code ImmutableMap<String, Integer> actualParameter = ...;}
* {@code ImmutableMap<String, Number> target = ImmutableMap.copyOf(actualParameter);}
* </pre>
*
* We will infer {@code K=String}, {@code V=Number} based on the target type, and then rewrite the
* formal parameter type from<br>
* {@code Map<? extends K, ? extends V>} to<br>
* {@code Map<? extends String, ? extends Number>}. Then we can check whether {@code
* actualParameter} is assignable to that.
*
* <p>The logic makes some simplifying assumptions, which are met for the {@code copyOf} and
* {@code of} methods that we use this for. The method must be static, it must have exactly one
* parameter, and it must have type parameters without bounds that are the same as the type
* parameters of its return type. We can see that these assumptions are met for the {@code
* ImmutableMap.copyOf} example above.
*/
static boolean canAssignStaticMethodResult(ExecutableElement method, TypeMirror actualParameterType, TypeMirror targetType, Types typeUtils) {
if (!targetType.getKind().equals(TypeKind.DECLARED) || !method.getModifiers().contains(Modifier.STATIC) || method.getParameters().size() != 1) {
return false;
}
List<? extends TypeParameterElement> typeParameters = method.getTypeParameters();
List<? extends TypeMirror> targetTypeArguments = MoreTypes.asDeclared(targetType).getTypeArguments();
if (typeParameters.size() != targetTypeArguments.size()) {
return false;
}
Map<Equivalence.Wrapper<TypeVariable>, TypeMirror> typeVariables = new LinkedHashMap<>();
for (int i = 0; i < typeParameters.size(); i++) {
TypeVariable v = MoreTypes.asTypeVariable(typeParameters.get(i).asType());
typeVariables.put(MoreTypes.equivalence().wrap(v), targetTypeArguments.get(i));
}
Function<TypeVariable, TypeMirror> substitute = v -> typeVariables.get(MoreTypes.equivalence().wrap(v));
TypeMirror formalParameterType = method.getParameters().get(0).asType();
SubstitutionVisitor substitutionVisitor = new SubstitutionVisitor(substitute, typeUtils);
TypeMirror substitutedParameterType = substitutionVisitor.visit(formalParameterType, null);
if (substitutedParameterType.getKind().equals(TypeKind.WILDCARD)) {
// If the target type is Optional<? extends Foo> then <T> T Optional.of(T) will give us
// ? extends Foo here, and typeUtils.isAssignable will return false. But we can in fact
// give a Foo as an argument, so we just replace ? extends Foo with Foo.
WildcardType wildcard = MoreTypes.asWildcard(substitutedParameterType);
if (wildcard.getExtendsBound() != null) {
substitutedParameterType = wildcard.getExtendsBound();
}
}
return typeUtils.isAssignable(actualParameterType, substitutedParameterType);
}
use of javax.lang.model.type.TypeVariable in project vertx-docgen by vert-x3.
the class Helper method toString.
/**
* Compute the string representation of a type mirror.
*
* @param mirror the type mirror
* @param buffer the buffer appended with the string representation
*/
static void toString(TypeMirror mirror, StringBuilder buffer) {
if (mirror instanceof DeclaredType) {
DeclaredType dt = (DeclaredType) mirror;
TypeElement elt = (TypeElement) dt.asElement();
buffer.append(elt.getQualifiedName().toString());
List<? extends TypeMirror> args = dt.getTypeArguments();
if (args.size() > 0) {
buffer.append("<");
for (int i = 0; i < args.size(); i++) {
if (i > 0) {
buffer.append(",");
}
toString(args.get(i), buffer);
}
buffer.append(">");
}
} else if (mirror instanceof PrimitiveType) {
PrimitiveType pm = (PrimitiveType) mirror;
buffer.append(pm.getKind().name().toLowerCase());
} else if (mirror instanceof javax.lang.model.type.WildcardType) {
javax.lang.model.type.WildcardType wt = (javax.lang.model.type.WildcardType) mirror;
buffer.append("?");
if (wt.getSuperBound() != null) {
buffer.append(" super ");
toString(wt.getSuperBound(), buffer);
} else if (wt.getExtendsBound() != null) {
buffer.append(" extends ");
toString(wt.getExtendsBound(), buffer);
}
} else if (mirror instanceof javax.lang.model.type.TypeVariable) {
javax.lang.model.type.TypeVariable tv = (TypeVariable) mirror;
TypeParameterElement elt = (TypeParameterElement) tv.asElement();
buffer.append(elt.getSimpleName().toString());
if (tv.getUpperBound() != null && !tv.getUpperBound().toString().equals("java.lang.Object")) {
buffer.append(" extends ");
toString(tv.getUpperBound(), buffer);
} else if (tv.getLowerBound() != null && tv.getLowerBound().getKind() != TypeKind.NULL) {
buffer.append(" super ");
toString(tv.getUpperBound(), buffer);
}
} else if (mirror instanceof javax.lang.model.type.ArrayType) {
javax.lang.model.type.ArrayType at = (ArrayType) mirror;
toString(at.getComponentType(), buffer);
buffer.append("[]");
} else {
throw new UnsupportedOperationException("todo " + mirror + " " + mirror.getKind());
}
}
use of javax.lang.model.type.TypeVariable in project LoganSquare by bluelinelabs.
the class ObjectMapperInjector method getTypeSpec.
private TypeSpec getTypeSpec() {
TypeSpec.Builder builder = TypeSpec.classBuilder(mJsonObjectHolder.injectedClassName).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
builder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unsafe,unchecked\"").build());
builder.superclass(ParameterizedTypeName.get(ClassName.get(JsonMapper.class), mJsonObjectHolder.objectTypeName));
for (TypeParameterElement typeParameterElement : mJsonObjectHolder.typeParameters) {
builder.addTypeVariable(TypeVariableName.get((TypeVariable) typeParameterElement.asType()));
}
if (mJsonObjectHolder.hasParentClass()) {
FieldSpec.Builder parentMapperBuilder;
if (mJsonObjectHolder.parentTypeParameters.size() == 0) {
parentMapperBuilder = FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(JsonMapper.class), mJsonObjectHolder.parentTypeName), PARENT_OBJECT_MAPPER_VARIABLE_NAME).addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL).initializer("$T.mapperFor($T.class)", LoganSquare.class, mJsonObjectHolder.parentTypeName);
} else {
parentMapperBuilder = FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(JsonMapper.class), mJsonObjectHolder.getParameterizedParentTypeName()), PARENT_OBJECT_MAPPER_VARIABLE_NAME).addModifiers(Modifier.PRIVATE);
if (mJsonObjectHolder.typeParameters.size() == 0) {
parentMapperBuilder.initializer("$T.mapperFor(new $T<$T>() { })", LoganSquare.class, ParameterizedType.class, mJsonObjectHolder.getParameterizedParentTypeName());
}
}
builder.addField(parentMapperBuilder.build());
}
// TypeConverters could be expensive to create, so just use one per class
Set<ClassName> typeConvertersUsed = new HashSet<>();
for (JsonFieldHolder fieldHolder : mJsonObjectHolder.fieldMap.values()) {
if (fieldHolder.type instanceof TypeConverterFieldType) {
typeConvertersUsed.add(((TypeConverterFieldType) fieldHolder.type).getTypeConverterClassName());
}
}
for (ClassName typeConverter : typeConvertersUsed) {
builder.addField(FieldSpec.builder(typeConverter, getStaticFinalTypeConverterVariableName(typeConverter)).addModifiers(Modifier.PROTECTED, Modifier.STATIC, Modifier.FINAL).initializer("new $T()", typeConverter).build());
}
MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
List<String> createdJsonMappers = new ArrayList<>();
if (mJsonObjectHolder.typeParameters.size() > 0) {
constructorBuilder.addParameter(ClassName.get(ParameterizedType.class), "type");
constructorBuilder.addStatement("partialMappers.put(type, this)");
for (TypeParameterElement typeParameterElement : mJsonObjectHolder.typeParameters) {
final String typeName = typeParameterElement.getSimpleName().toString();
final String typeArgumentName = typeName + "Type";
final String jsonMapperVariableName = getJsonMapperVariableNameForTypeParameter(typeName);
if (!createdJsonMappers.contains(jsonMapperVariableName)) {
createdJsonMappers.add(jsonMapperVariableName);
// Add a JsonMapper reference
builder.addField(FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(JsonMapper.class), TypeVariableName.get(typeName)), jsonMapperVariableName).addModifiers(Modifier.PRIVATE, Modifier.FINAL).build());
constructorBuilder.addParameter(ClassName.get(ParameterizedType.class), typeArgumentName);
constructorBuilder.addStatement("$L = $T.mapperFor($L, partialMappers)", jsonMapperVariableName, LoganSquare.class, typeArgumentName);
}
}
constructorBuilder.addParameter(ParameterizedTypeName.get(ClassName.get(SimpleArrayMap.class), ClassName.get(ParameterizedType.class), ClassName.get(JsonMapper.class)), "partialMappers");
}
for (JsonFieldHolder jsonFieldHolder : mJsonObjectHolder.fieldMap.values()) {
if (jsonFieldHolder.type instanceof ParameterizedTypeField) {
final String jsonMapperVariableName = getJsonMapperVariableNameForTypeParameter(((ParameterizedTypeField) jsonFieldHolder.type).getParameterName());
if (!createdJsonMappers.contains(jsonMapperVariableName)) {
ParameterizedTypeName parameterizedType = ParameterizedTypeName.get(ClassName.get(JsonMapper.class), jsonFieldHolder.type.getTypeName());
createdJsonMappers.add(jsonMapperVariableName);
builder.addField(FieldSpec.builder(parameterizedType, jsonMapperVariableName).addModifiers(Modifier.PRIVATE, Modifier.FINAL).build());
String typeName = jsonMapperVariableName + "Type";
constructorBuilder.addStatement("$T $L = new $T<$T>() { }", ParameterizedType.class, typeName, ParameterizedType.class, jsonFieldHolder.type.getTypeName());
if (mJsonObjectHolder.typeParameters.size() > 0) {
constructorBuilder.beginControlFlow("if ($L.equals(type))", typeName);
constructorBuilder.addStatement("$L = ($T)this", jsonMapperVariableName, JsonMapper.class);
constructorBuilder.nextControlFlow("else");
constructorBuilder.addStatement("$L = $T.mapperFor($L, partialMappers)", jsonMapperVariableName, LoganSquare.class, typeName);
constructorBuilder.endControlFlow();
} else {
constructorBuilder.addStatement("$L = $T.mapperFor($L)", jsonMapperVariableName, LoganSquare.class, typeName);
}
}
}
}
if (createdJsonMappers.size() > 0) {
if (mJsonObjectHolder.hasParentClass()) {
constructorBuilder.addStatement("$L = $T.mapperFor(new $T<$T>() { })", PARENT_OBJECT_MAPPER_VARIABLE_NAME, LoganSquare.class, ParameterizedType.class, mJsonObjectHolder.getParameterizedParentTypeName());
}
builder.addMethod(constructorBuilder.build());
}
builder.addMethod(getParseMethod());
builder.addMethod(getParseFieldMethod());
builder.addMethod(getSerializeMethod());
addUsedJsonMapperVariables(builder);
addUsedTypeConverterMethods(builder);
return builder.build();
}
Aggregations