Search in sources :

Example 1 with TypeAnnotationMetadata

use of org.gradle.internal.reflect.annotations.TypeAnnotationMetadata in project gradle by gradle.

the class DefaultTypeMetadataStore method createTypeMetadata.

private <T> TypeMetadata createTypeMetadata(Class<T> type) {
    Class<?> publicType = GeneratedSubclasses.unpack(type);
    ReplayingTypeValidationContext validationContext = new ReplayingTypeValidationContext();
    TypeAnnotationMetadata annotationMetadata = typeAnnotationMetadataStore.getTypeAnnotationMetadata(publicType);
    annotationMetadata.visitValidationFailures(validationContext);
    for (TypeAnnotationHandler annotationHandler : typeAnnotationHandlers) {
        if (annotationMetadata.isAnnotationPresent(annotationHandler.getAnnotationType())) {
            annotationHandler.validateTypeMetadata(publicType, validationContext);
        }
    }
    ImmutableSet.Builder<PropertyMetadata> effectiveProperties = ImmutableSet.builderWithExpectedSize(annotationMetadata.getPropertiesAnnotationMetadata().size());
    for (PropertyAnnotationMetadata propertyAnnotationMetadata : annotationMetadata.getPropertiesAnnotationMetadata()) {
        Map<AnnotationCategory, Annotation> propertyAnnotations = propertyAnnotationMetadata.getAnnotations();
        Annotation typeAnnotation = propertyAnnotations.get(TYPE);
        Annotation normalizationAnnotation = propertyAnnotations.get(NORMALIZATION);
        Class<? extends Annotation> propertyType = determinePropertyType(typeAnnotation, normalizationAnnotation);
        if (propertyType == null) {
            validationContext.visitPropertyProblem(problem -> problem.withId(ValidationProblemId.MISSING_ANNOTATION).forProperty(propertyAnnotationMetadata.getPropertyName()).reportAs(ERROR).withDescription(() -> "is missing " + displayName).happensBecause("A property without annotation isn't considered during up-to-date checking").addPossibleSolution(() -> "Add " + displayName).addPossibleSolution("Mark it as @Internal").documentedAt("validation_problems", "missing_annotation"));
            continue;
        }
        PropertyAnnotationHandler annotationHandler = propertyAnnotationHandlers.get(propertyType);
        if (annotationHandler == null) {
            validationContext.visitPropertyProblem(problem -> problem.withId(ValidationProblemId.ANNOTATION_INVALID_IN_CONTEXT).forProperty(propertyAnnotationMetadata.getPropertyName()).reportAs(ERROR).withDescription(() -> String.format("is annotated with invalid property type @%s", propertyType.getSimpleName())).happensBecause(() -> "The '@" + propertyType.getSimpleName() + "' annotation cannot be used in this context").addPossibleSolution("Remove the property").addPossibleSolution(() -> "Use a different annotation, e.g one of " + toListOfAnnotations(propertyAnnotationHandlers.keySet())).documentedAt("validation_problems", "annotation_invalid_in_context"));
            continue;
        }
        ImmutableSet<? extends AnnotationCategory> allowedModifiersForPropertyType = annotationHandler.getAllowedModifiers();
        for (Map.Entry<AnnotationCategory, Annotation> entry : propertyAnnotations.entrySet()) {
            AnnotationCategory annotationCategory = entry.getKey();
            if (annotationCategory == TYPE) {
                continue;
            }
            Class<? extends Annotation> annotationType = entry.getValue().annotationType();
            if (!allowedModifiersForPropertyType.contains(annotationCategory)) {
                validationContext.visitPropertyProblem(problem -> problem.withId(ValidationProblemId.INCOMPATIBLE_ANNOTATIONS).forProperty(propertyAnnotationMetadata.getPropertyName()).reportAs(ERROR).withDescription(() -> "is annotated with @" + annotationType.getSimpleName() + " but that is not allowed for '" + propertyType.getSimpleName() + "' properties").happensBecause(() -> "This modifier is used in conjunction with a property of type '" + propertyType.getSimpleName() + "' but this doesn't have semantics").withLongDescription(() -> "The list of allowed modifiers for '" + propertyType.getSimpleName() + "' is " + toListOfAnnotations(allowedPropertyModifiers)).addPossibleSolution(() -> "Remove the '@" + annotationType.getSimpleName() + "' annotation").documentedAt("validation_problems", "incompatible_annotations"));
            } else if (!allowedPropertyModifiers.contains(annotationType)) {
                validationContext.visitPropertyProblem(problem -> problem.withId(ValidationProblemId.ANNOTATION_INVALID_IN_CONTEXT).forProperty(propertyAnnotationMetadata.getPropertyName()).reportAs(ERROR).withDescription(() -> String.format("is annotated with invalid modifier @%s", annotationType.getSimpleName())).happensBecause(() -> "The '@" + annotationType.getSimpleName() + "' annotation cannot be used in this context").addPossibleSolution("Remove the annotation").addPossibleSolution(() -> "Use a different annotation, e.g one of " + toListOfAnnotations(allowedPropertyModifiers)).documentedAt("validation_problems", "annotation_invalid_in_context"));
            }
        }
        PropertyMetadata property = new DefaultPropertyMetadata(propertyType, propertyAnnotationMetadata);
        annotationHandler.validatePropertyMetadata(property, validationContext);
        if (annotationHandler.isPropertyRelevant()) {
            effectiveProperties.add(property);
        }
    }
    return new DefaultTypeMetadata(effectiveProperties.build(), validationContext, propertyAnnotationHandlers);
}
Also used : TypeAnnotationMetadata(org.gradle.internal.reflect.annotations.TypeAnnotationMetadata) AbstractOutputPropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.AbstractOutputPropertyAnnotationHandler) TypeAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler) InputFiles(org.gradle.api.tasks.InputFiles) Function(java.util.function.Function) NORMALIZATION(org.gradle.api.internal.tasks.properties.ModifierAnnotationCategory.NORMALIZATION) PropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler) Map(java.util.Map) TYPE(org.gradle.internal.reflect.AnnotationCategory.TYPE) Collector(java.util.stream.Collector) Method(java.lang.reflect.Method) Nullable(javax.annotation.Nullable) GeneratedSubclasses(org.gradle.api.internal.GeneratedSubclasses) Classpath(org.gradle.api.tasks.Classpath) ImmutableSet(com.google.common.collect.ImmutableSet) CompileClasspath(org.gradle.api.tasks.CompileClasspath) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) ReplayingTypeValidationContext(org.gradle.internal.reflect.validation.ReplayingTypeValidationContext) Set(java.util.Set) AnnotationCategory(org.gradle.internal.reflect.AnnotationCategory) TypeValidationContext(org.gradle.internal.reflect.validation.TypeValidationContext) CrossBuildInMemoryCache(org.gradle.cache.internal.CrossBuildInMemoryCache) Maps(com.google.common.collect.Maps) Collectors(java.util.stream.Collectors) TypeAnnotationMetadataStore(org.gradle.internal.reflect.annotations.TypeAnnotationMetadataStore) PropertyMetadata(org.gradle.internal.reflect.PropertyMetadata) PropertyAnnotationMetadata(org.gradle.internal.reflect.annotations.PropertyAnnotationMetadata) ERROR(org.gradle.internal.reflect.validation.Severity.ERROR) Annotation(java.lang.annotation.Annotation) CrossBuildInMemoryCacheFactory(org.gradle.cache.internal.CrossBuildInMemoryCacheFactory) ValidationProblemId(org.gradle.internal.reflect.problems.ValidationProblemId) AbstractOutputPropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.AbstractOutputPropertyAnnotationHandler) PropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler) TypeAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler) PropertyAnnotationMetadata(org.gradle.internal.reflect.annotations.PropertyAnnotationMetadata) ReplayingTypeValidationContext(org.gradle.internal.reflect.validation.ReplayingTypeValidationContext) AnnotationCategory(org.gradle.internal.reflect.AnnotationCategory) Annotation(java.lang.annotation.Annotation) ImmutableSet(com.google.common.collect.ImmutableSet) PropertyMetadata(org.gradle.internal.reflect.PropertyMetadata) TypeAnnotationMetadata(org.gradle.internal.reflect.annotations.TypeAnnotationMetadata) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap)

Aggregations

ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Maps (com.google.common.collect.Maps)1 Annotation (java.lang.annotation.Annotation)1 Method (java.lang.reflect.Method)1 Collection (java.util.Collection)1 Map (java.util.Map)1 Set (java.util.Set)1 Function (java.util.function.Function)1 Collector (java.util.stream.Collector)1 Collectors (java.util.stream.Collectors)1 Nullable (javax.annotation.Nullable)1 GeneratedSubclasses (org.gradle.api.internal.GeneratedSubclasses)1 NORMALIZATION (org.gradle.api.internal.tasks.properties.ModifierAnnotationCategory.NORMALIZATION)1 AbstractOutputPropertyAnnotationHandler (org.gradle.api.internal.tasks.properties.annotations.AbstractOutputPropertyAnnotationHandler)1 PropertyAnnotationHandler (org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler)1 TypeAnnotationHandler (org.gradle.api.internal.tasks.properties.annotations.TypeAnnotationHandler)1 Classpath (org.gradle.api.tasks.Classpath)1 CompileClasspath (org.gradle.api.tasks.CompileClasspath)1 InputFiles (org.gradle.api.tasks.InputFiles)1