Search in sources :

Example 1 with RecordComponentStub

use of org.checkerframework.framework.stub.AnnotationFileParser.RecordComponentStub in project checker-framework by typetools.

the class AnnotationFileElementTypes method injectRecordComponentType.

/**
 * Adds annotations from stub files for the corresponding record components (if the given
 * constructor/method is the canonical constructor or a record accessor). Such transfer is
 * automatically done by javac usually, but not from stubs.
 *
 * @param types a Types instance used for checking type equivalence
 * @param elt a member. This method does nothing if it's not a method or constructor.
 * @param memberType the type corresponding to the element elt; side-effected by this method
 */
public void injectRecordComponentType(Types types, Element elt, AnnotatedExecutableType memberType) {
    if (parsing) {
        throw new BugInCF("parsing while calling injectRecordComponentType");
    }
    if (elt.getKind() == ElementKind.METHOD) {
        if (((ExecutableElement) elt).getParameters().isEmpty()) {
            String recordName = ElementUtils.getQualifiedName(elt.getEnclosingElement());
            AnnotationFileParser.RecordStub recordComponentType = annotationFileAnnos.records.get(recordName);
            if (recordComponentType != null) {
                // If the record component has an annotation in the stub, the component annotation
                // replaces any from the same hierarchy on the accessor method, unless there is an
                // accessor in the stubs file (which may or may not have an annotation in the same
                // hierarchy;
                // the user may want to specify the annotation or deliberately not annotate the accessor).
                // We thus only replace the method annotation with the component annotation
                // if there is no accessor in the stubs file:
                RecordComponentStub recordComponentStub = recordComponentType.componentsByName.get(elt.getSimpleName().toString());
                if (recordComponentStub != null && !recordComponentStub.hasAccessorInStubs()) {
                    replaceAnnotations(memberType.getReturnType(), recordComponentStub.type);
                }
            }
        }
    } else if (elt.getKind() == ElementKind.CONSTRUCTOR) {
        if (AnnotationFileUtil.isCanonicalConstructor((ExecutableElement) elt, types)) {
            TypeElement enclosing = (TypeElement) elt.getEnclosingElement();
            AnnotationFileParser.RecordStub recordComponentType = annotationFileAnnos.records.get(enclosing.getQualifiedName().toString());
            if (recordComponentType != null) {
                List<AnnotatedTypeMirror> componentsInCanonicalConstructor = recordComponentType.getComponentsInCanonicalConstructor();
                if (componentsInCanonicalConstructor != null) {
                    for (int i = 0; i < componentsInCanonicalConstructor.size(); i++) {
                        replaceAnnotations(memberType.getParameterTypes().get(i), componentsInCanonicalConstructor.get(i));
                    }
                }
            }
        }
    }
}
Also used : RecordComponentStub(org.checkerframework.framework.stub.AnnotationFileParser.RecordComponentStub) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) List(java.util.List) ArrayList(java.util.ArrayList) BugInCF(org.checkerframework.javacutil.BugInCF)

Example 2 with RecordComponentStub

use of org.checkerframework.framework.stub.AnnotationFileParser.RecordComponentStub in project checker-framework by typetools.

the class AnnotationFileElementTypes method getDeclAnnotations.

/**
 * Returns the set of declaration annotations for {@code e} containing only annotations explicitly
 * written in an annotation file or the empty set if {@code e} does not appear in an annotation
 * file.
 *
 * @param elt element for which annotations are returned
 * @return an AnnotatedTypeMirror for {@code e} containing only annotations explicitly written in
 *     the annotation file and in the element. {@code null} is returned if {@code element} does
 *     not appear in an annotation file.
 */
public Set<AnnotationMirror> getDeclAnnotations(Element elt) {
    if (parsing) {
        return Collections.emptySet();
    }
    parseEnclosingClass(elt);
    String eltName = ElementUtils.getQualifiedName(elt);
    if (annotationFileAnnos.declAnnos.containsKey(eltName)) {
        return annotationFileAnnos.declAnnos.get(eltName);
    } else {
        // Handle annotations on record declarations.
        boolean canTransferAnnotationsToSameName;
        // Do nothing unless this element is a record.
        Element enclosingType;
        switch(elt.getKind()) {
            case METHOD:
                // Annotations transfer to zero-arg accessor methods of same name:
                canTransferAnnotationsToSameName = ((ExecutableElement) elt).getParameters().isEmpty();
                enclosingType = elt.getEnclosingElement();
                break;
            case FIELD:
                // Annotations transfer to fields of same name:
                canTransferAnnotationsToSameName = true;
                enclosingType = elt.getEnclosingElement();
                break;
            case PARAMETER:
                // Annotations transfer to compact canonical constructor parameter of same name:
                canTransferAnnotationsToSameName = ElementUtils.isCompactCanonicalRecordConstructor(elt.getEnclosingElement()) && elt.getEnclosingElement().getKind() == ElementKind.CONSTRUCTOR;
                enclosingType = elt.getEnclosingElement().getEnclosingElement();
                break;
            default:
                canTransferAnnotationsToSameName = false;
                enclosingType = null;
                break;
        }
        if (canTransferAnnotationsToSameName && enclosingType.getKind().toString().equals("RECORD")) {
            AnnotationFileParser.RecordStub recordStub = annotationFileAnnos.records.get(enclosingType.getSimpleName().toString());
            if (recordStub != null && recordStub.componentsByName.containsKey(elt.getSimpleName().toString())) {
                RecordComponentStub recordComponentStub = recordStub.componentsByName.get(elt.getSimpleName().toString());
                return recordComponentStub.getAnnotationsForTarget(elt.getKind());
            }
        }
    }
    return Collections.emptySet();
}
Also used : RecordComponentStub(org.checkerframework.framework.stub.AnnotationFileParser.RecordComponentStub) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement)

Aggregations

ExecutableElement (javax.lang.model.element.ExecutableElement)2 TypeElement (javax.lang.model.element.TypeElement)2 RecordComponentStub (org.checkerframework.framework.stub.AnnotationFileParser.RecordComponentStub)2 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Element (javax.lang.model.element.Element)1 BugInCF (org.checkerframework.javacutil.BugInCF)1