Search in sources :

Example 16 with TypeVariable

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;
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) TypeName(com.squareup.javapoet.TypeName) ProcessorException(org.realityforge.proton.ProcessorException) TypeMirror(javax.lang.model.type.TypeMirror) TypeVariable(javax.lang.model.type.TypeVariable) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) TypeParameterElement(javax.lang.model.element.TypeParameterElement) Nonnull(javax.annotation.Nonnull)

Example 17 with TypeVariable

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);
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) NewClassTree(com.sun.source.tree.NewClassTree) BugInCF(org.checkerframework.javacutil.BugInCF) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 18 with TypeVariable

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;
}
Also used : TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TypeElement(javax.lang.model.element.TypeElement) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 19 with TypeVariable

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;
}
Also used : JCAnnotatedType(com.sun.tools.javac.tree.JCTree.JCAnnotatedType) JCTree(com.sun.tools.javac.tree.JCTree) JCTypeApply(com.sun.tools.javac.tree.JCTree.JCTypeApply) ArrayType(javax.lang.model.type.ArrayType) WildcardType(javax.lang.model.type.WildcardType) JCAnnotatedType(com.sun.tools.javac.tree.JCTree.JCAnnotatedType) DeclaredType(javax.lang.model.type.DeclaredType) WildcardType(javax.lang.model.type.WildcardType) ArrayType(javax.lang.model.type.ArrayType) IntersectionType(javax.lang.model.type.IntersectionType) Type(com.sun.tools.javac.code.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) IntersectionType(javax.lang.model.type.IntersectionType) TypeVariable(javax.lang.model.type.TypeVariable) TypeMirror(javax.lang.model.type.TypeMirror) Tree(com.sun.source.tree.Tree) JCTree(com.sun.tools.javac.tree.JCTree) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) DeclaredType(javax.lang.model.type.DeclaredType)

Example 20 with TypeVariable

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);
            }
        }
    }
}
Also used : TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Aggregations

TypeVariable (javax.lang.model.type.TypeVariable)80 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)38 TypeMirror (javax.lang.model.type.TypeMirror)30 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)22 TypeElement (javax.lang.model.element.TypeElement)21 ArrayList (java.util.ArrayList)16 DeclaredType (javax.lang.model.type.DeclaredType)15 HashMap (java.util.HashMap)14 LinkedHashMap (java.util.LinkedHashMap)13 Map (java.util.Map)13 ExecutableElement (javax.lang.model.element.ExecutableElement)12 TypeParameterElement (javax.lang.model.element.TypeParameterElement)12 Test (org.junit.Test)10 ArrayType (javax.lang.model.type.ArrayType)9 WildcardType (javax.lang.model.type.WildcardType)9 AnnotationMirror (javax.lang.model.element.AnnotationMirror)8 Element (javax.lang.model.element.Element)8 AnnotationMirrorMap (org.checkerframework.framework.util.AnnotationMirrorMap)8 AnnotationMirrorSet (org.checkerframework.framework.util.AnnotationMirrorSet)8 VariableElement (javax.lang.model.element.VariableElement)7