use of javax.lang.model.type.TypeVariable in project react4j by react4j.
the class React4jProcessor method createInputDescriptor.
@Nonnull
private InputDescriptor createInputDescriptor(@Nonnull final ViewDescriptor descriptor, @Nonnull final ExecutableElement method) {
final String name = deriveInputName(method);
final ExecutableType methodType = resolveMethodType(descriptor, method);
verifyNoDuplicateAnnotations(method);
MemberChecks.mustBeAbstract(Constants.INPUT_CLASSNAME, method);
MemberChecks.mustNotHaveAnyParameters(Constants.INPUT_CLASSNAME, method);
MemberChecks.mustReturnAValue(Constants.INPUT_CLASSNAME, method);
MemberChecks.mustNotThrowAnyExceptions(Constants.INPUT_CLASSNAME, method);
MemberChecks.mustNotBePackageAccessInDifferentPackage(descriptor.getElement(), Constants.VIEW_CLASSNAME, Constants.INPUT_CLASSNAME, method);
final TypeMirror returnType = method.getReturnType();
if ("build".equals(name)) {
throw new ProcessorException("@Input named 'build' is invalid as it conflicts with the method named " + "build() that is used in the generated Builder classes", method);
} else if ("child".equals(name) && (returnType.getKind() != TypeKind.DECLARED && !"react4j.ReactNode".equals(returnType.toString()))) {
throw new ProcessorException("@Input named 'child' should be of type react4j.ReactNode", method);
} else if ("children".equals(name) && (returnType.getKind() != TypeKind.DECLARED && !"react4j.ReactNode[]".equals(returnType.toString()))) {
throw new ProcessorException("@Input named 'children' should be of type react4j.ReactNode[]", method);
}
if (returnType instanceof TypeVariable) {
final TypeVariable typeVariable = (TypeVariable) returnType;
final String typeVariableName = typeVariable.asElement().getSimpleName().toString();
List<? extends TypeParameterElement> typeParameters = method.getTypeParameters();
if (typeParameters.stream().anyMatch(p -> p.getSimpleName().toString().equals(typeVariableName))) {
throw new ProcessorException("@Input named '" + name + "' is has a type variable as a return type " + "that is declared on the method.", method);
}
}
final String qualifier = (String) AnnotationsUtil.getAnnotationValue(method, Constants.INPUT_CLASSNAME, "qualifier").getValue();
final boolean contextInput = isContextInput(method);
final Element inputType = processingEnv.getTypeUtils().asElement(returnType);
final boolean immutable = isInputImmutable(method);
final boolean observable = isInputObservable(descriptor, method, immutable);
final boolean disposable = null != inputType && isInputDisposable(method, inputType);
final TypeName typeName = TypeName.get(returnType);
if (typeName.isBoxedPrimitive() && AnnotationsUtil.hasNonnullAnnotation(method)) {
throw new ProcessorException("@Input named '" + name + "' is a boxed primitive annotated with a " + "@Nonnull annotation. The return type should be the primitive type.", method);
}
final ImmutableInputKeyStrategy strategy = immutable ? getImmutableInputKeyStrategy(typeName, inputType) : null;
if (!"".equals(qualifier) && !contextInput) {
throw new ProcessorException(MemberChecks.mustNot(Constants.INPUT_CLASSNAME, "specify qualifier parameter unless source=CONTEXT is also specified"), method);
}
final String requiredValue = ((VariableElement) AnnotationsUtil.getAnnotationValue(method, Constants.INPUT_CLASSNAME, "require").getValue()).getSimpleName().toString();
final boolean dependency = isInputDependency(method, immutable, disposable);
final InputDescriptor inputDescriptor = new InputDescriptor(descriptor, name, qualifier, method, methodType, inputType, contextInput, !immutable, observable, disposable, dependency, strategy, requiredValue);
if (inputDescriptor.mayNeedMutableInputAccessedInPostConstructInvariant()) {
if (ElementsUtil.isWarningSuppressed(method, Constants.WARNING_MUTABLE_INPUT_ACCESSED_IN_POST_CONSTRUCT, Constants.SUPPRESS_REACT4J_WARNINGS_CLASSNAME)) {
inputDescriptor.suppressMutableInputAccessedInPostConstruct();
}
}
return inputDescriptor;
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class AnnotatedTypes method findTypeArguments.
/**
* Given a method or constructor invocation, return a mapping of the type variables to their type
* arguments, if any exist.
*
* <p>It uses the method or constructor invocation type arguments if they were specified and
* otherwise it infers them based on the passed arguments or the return type context, according to
* JLS 15.12.2.
*
* @param atypeFactory the annotated type factory
* @param expr the method or constructor invocation tree; the passed argument has to be a subtype
* of MethodInvocationTree or NewClassTree
* @param elt the element corresponding to the tree
* @param preType the (partially annotated) type corresponding to the tree - the result of
* AnnotatedTypes.asMemberOf with the receiver and elt
* @return the mapping of the type variables to type arguments for this method or constructor
* invocation
*/
public static Map<TypeVariable, AnnotatedTypeMirror> findTypeArguments(final ProcessingEnvironment processingEnv, final AnnotatedTypeFactory atypeFactory, final ExpressionTree expr, final ExecutableElement elt, final AnnotatedExecutableType preType) {
// Is the method a generic method?
if (elt.getTypeParameters().isEmpty()) {
return Collections.emptyMap();
}
List<? extends Tree> targs;
if (expr instanceof MethodInvocationTree) {
targs = ((MethodInvocationTree) expr).getTypeArguments();
} else if (expr instanceof NewClassTree) {
targs = ((NewClassTree) expr).getTypeArguments();
} else if (expr instanceof MemberReferenceTree) {
targs = ((MemberReferenceTree) expr).getTypeArguments();
if (targs == null) {
// TODO: Add type argument inference as part of fix for #979
return new HashMap<>();
}
} else {
// This case should never happen.
throw new BugInCF("AnnotatedTypes.findTypeArguments: unexpected tree: " + expr);
}
// Has the user supplied type arguments?
if (!targs.isEmpty()) {
List<? extends AnnotatedTypeVariable> tvars = preType.getTypeVariables();
Map<TypeVariable, AnnotatedTypeMirror> typeArguments = new HashMap<>();
for (int i = 0; i < elt.getTypeParameters().size(); ++i) {
AnnotatedTypeVariable typeVar = tvars.get(i);
AnnotatedTypeMirror typeArg = atypeFactory.getAnnotatedTypeFromTypeTree(targs.get(i));
// TODO: the call to getTypeParameterDeclaration shouldn't be necessary - typeVar
// already should be a declaration.
typeArguments.put(typeVar.getUnderlyingType(), typeArg);
}
return typeArguments;
} else {
return atypeFactory.getTypeArgumentInference().inferTypeArgs(atypeFactory, expr, elt, preType);
}
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class AnnotatedTypes method substituteUninferredTypeArgs.
/**
* Substitutes uninferred type arguments for type variables in {@code memberType}.
*
* @param atypeFactory the type factory
* @param member the element with type {@code memberType}; used to obtain the enclosing type
* @param memberType the type to side-effect
* @return memberType, with type arguments substituted for type variables
*/
private static AnnotatedTypeMirror substituteUninferredTypeArgs(AnnotatedTypeFactory atypeFactory, Element member, AnnotatedTypeMirror memberType) {
TypeElement enclosingClassOfMember = ElementUtils.enclosingTypeElement(member);
final Map<TypeVariable, AnnotatedTypeMirror> mappings = new HashMap<>();
while (enclosingClassOfMember != null) {
if (!enclosingClassOfMember.getTypeParameters().isEmpty()) {
AnnotatedDeclaredType enclosingType = atypeFactory.getAnnotatedType(enclosingClassOfMember);
for (final AnnotatedTypeMirror type : enclosingType.getTypeArguments()) {
AnnotatedTypeVariable typeParameter = (AnnotatedTypeVariable) type;
mappings.put(typeParameter.getUnderlyingType(), atypeFactory.getUninferredWildcardType(typeParameter));
}
}
enclosingClassOfMember = ElementUtils.enclosingTypeElement(enclosingClassOfMember.getEnclosingElement());
}
if (!mappings.isEmpty()) {
return atypeFactory.getTypeVarSubstitutor().substitute(mappings, memberType);
}
return memberType;
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class CFTreeBuilder method createAnnotatedType.
/**
* Builds an AST Tree representing a type, including AnnotationTrees for its annotations. This
* internal method differs from the public {@link #buildAnnotatedType(TypeMirror)} only in that it
* does not reset the list of visited wildcards.
*
* @param type the type for which to create a tree
* @return a Tree representing the type
*/
private Tree createAnnotatedType(TypeMirror type) {
// Implementation based on com.sun.tools.javac.tree.TreeMaker.Type
// Convert the annotations from a set of AnnotationMirrors
// to a list of AnnotationTrees.
java.util.List<? extends AnnotationMirror> annotations = type.getAnnotationMirrors();
List<JCAnnotation> annotationTrees = convertAnnotationMirrorsToAnnotationTrees(annotations);
// Convert the underlying type from a TypeMirror to an ExpressionTree and combine with the
// AnnotationTrees to form a ClassTree of kind ANNOTATION_TYPE.
JCExpression typeTree;
switch(type.getKind()) {
case BYTE:
typeTree = maker.TypeIdent(TypeTag.BYTE);
break;
case CHAR:
typeTree = maker.TypeIdent(TypeTag.CHAR);
break;
case SHORT:
typeTree = maker.TypeIdent(TypeTag.SHORT);
break;
case INT:
typeTree = maker.TypeIdent(TypeTag.INT);
break;
case LONG:
typeTree = maker.TypeIdent(TypeTag.LONG);
break;
case FLOAT:
typeTree = maker.TypeIdent(TypeTag.FLOAT);
break;
case DOUBLE:
typeTree = maker.TypeIdent(TypeTag.DOUBLE);
break;
case BOOLEAN:
typeTree = maker.TypeIdent(TypeTag.BOOLEAN);
break;
case VOID:
typeTree = maker.TypeIdent(TypeTag.VOID);
break;
case TYPEVAR:
// No recursive annotations.
TypeVariable underlyingTypeVar = (TypeVariable) type;
typeTree = maker.Ident((TypeSymbol) underlyingTypeVar.asElement());
break;
case WILDCARD:
WildcardType wildcardType = (WildcardType) type;
boolean visitedBefore = !visitedWildcards.add(wildcardType);
if (!visitedBefore && wildcardType.getExtendsBound() != null) {
Tree annotatedExtendsBound = createAnnotatedType(wildcardType.getExtendsBound());
typeTree = maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), (JCTree) annotatedExtendsBound);
} else if (!visitedBefore && wildcardType.getSuperBound() != null) {
Tree annotatedSuperBound = createAnnotatedType(wildcardType.getSuperBound());
typeTree = maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), (JCTree) annotatedSuperBound);
} else {
typeTree = maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
}
break;
case INTERSECTION:
IntersectionType intersectionType = (IntersectionType) type;
List<JCExpression> components = List.nil();
for (TypeMirror bound : intersectionType.getBounds()) {
components = components.append((JCExpression) createAnnotatedType(bound));
}
typeTree = maker.TypeIntersection(components);
break;
// TODO: case UNION similar to INTERSECTION, but write test first.
case DECLARED:
typeTree = maker.Type((Type) type);
if (typeTree instanceof JCTypeApply) {
// Replace the type parameters with annotated versions.
DeclaredType annotatedDeclaredType = (DeclaredType) type;
List<JCExpression> typeArgTrees = List.nil();
for (TypeMirror arg : annotatedDeclaredType.getTypeArguments()) {
typeArgTrees = typeArgTrees.append((JCExpression) createAnnotatedType(arg));
}
JCExpression clazz = (JCExpression) ((JCTypeApply) typeTree).getType();
typeTree = maker.TypeApply(clazz, typeArgTrees);
}
break;
case ARRAY:
ArrayType arrayType = (ArrayType) type;
Tree componentTree = createAnnotatedType(arrayType.getComponentType());
typeTree = maker.TypeArray((JCExpression) componentTree);
break;
case ERROR:
typeTree = maker.TypeIdent(TypeTag.ERROR);
break;
default:
assert false : "unexpected type: " + type;
typeTree = null;
break;
}
typeTree.setType((Type) type);
if (annotationTrees.isEmpty()) {
return typeTree;
}
JCAnnotatedType annotatedTypeTree = maker.AnnotatedType(annotationTrees, typeTree);
annotatedTypeTree.setType((Type) type);
return annotatedTypeTree;
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class DefaultTypeArgumentInference method handleUninferredTypeVariables.
/**
* For any types we have not inferred, use a wildcard with the bounds from the original type
* parameter.
*/
private void handleUninferredTypeVariables(AnnotatedTypeFactory typeFactory, AnnotatedExecutableType methodType, Set<TypeVariable> targets, Map<TypeVariable, AnnotatedTypeMirror> inferredArgs) {
for (AnnotatedTypeVariable atv : methodType.getTypeVariables()) {
final TypeVariable typeVar = atv.getUnderlyingType();
if (targets.contains((TypeVariable) TypeAnnotationUtils.unannotatedType(typeVar))) {
final AnnotatedTypeMirror inferredType = inferredArgs.get(typeVar);
if (inferredType == null) {
AnnotatedTypeMirror dummy = typeFactory.getUninferredWildcardType(atv);
inferredArgs.put(atv.getUnderlyingType(), dummy);
} else {
typeFactory.addDefaultAnnotations(inferredType);
}
}
}
}
Aggregations