Search in sources :

Example 1 with PropertyAnnotationHandler

use of org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler in project gradle by gradle.

the class AbstractNestedRuntimeBeanNode method visitProperties.

protected void visitProperties(PropertyVisitor visitor, final Queue<RuntimeBeanNode<?>> queue, final RuntimeBeanNodeFactory nodeFactory, TypeValidationContext validationContext) {
    TypeMetadata typeMetadata = getTypeMetadata();
    typeMetadata.visitValidationFailures(getPropertyName(), validationContext);
    for (PropertyMetadata propertyMetadata : typeMetadata.getPropertiesMetadata()) {
        PropertyAnnotationHandler annotationHandler = typeMetadata.getAnnotationHandlerFor(propertyMetadata);
        if (annotationHandler.shouldVisit(visitor)) {
            String propertyName = getQualifiedPropertyName(propertyMetadata.getPropertyName());
            PropertyValue value = new BeanPropertyValue(getBean(), propertyMetadata.getGetterMethod());
            annotationHandler.visitPropertyValue(propertyName, value, propertyMetadata, visitor, new BeanPropertyContext() {

                @Override
                public void addNested(String propertyName, Object bean) {
                    queue.add(nodeFactory.create(AbstractNestedRuntimeBeanNode.this, propertyName, bean));
                }
            });
        }
    }
}
Also used : TypeMetadata(org.gradle.api.internal.tasks.properties.TypeMetadata) PropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler) BeanPropertyContext(org.gradle.api.internal.tasks.properties.BeanPropertyContext) PropertyMetadata(org.gradle.internal.reflect.PropertyMetadata) PropertyValue(org.gradle.api.internal.tasks.properties.PropertyValue)

Example 2 with PropertyAnnotationHandler

use of org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler in project gradle by gradle.

the class InspectionSchemeFactory method inspectionScheme.

/**
 * Creates a new {@link InspectionScheme} with the given annotations enabled and using the given instantiation scheme.
 */
public InspectionScheme inspectionScheme(Collection<Class<? extends Annotation>> annotations, Collection<Class<? extends Annotation>> propertyModifiers, InstantiationScheme instantiationScheme) {
    ImmutableList.Builder<PropertyAnnotationHandler> propertyHandlers = ImmutableList.builderWithExpectedSize(annotations.size());
    for (Class<? extends Annotation> annotation : annotations) {
        PropertyAnnotationHandler propertyHandler = allKnownPropertyHandlers.get(annotation);
        if (propertyHandler == null) {
            throw new IllegalArgumentException(String.format("@%s is not a registered property type annotation.", annotation.getSimpleName()));
        }
        propertyHandlers.add(propertyHandler);
    }
    for (Class<? extends Annotation> annotation : instantiationScheme.getInjectionAnnotations()) {
        if (!annotations.contains(annotation)) {
            propertyHandlers.add(new NoOpPropertyAnnotationHandler(annotation));
        }
    }
    return new InspectionSchemeImpl(allKnownTypeHandlers, propertyHandlers.build(), propertyModifiers, typeAnnotationMetadataStore, cacheFactory);
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) PropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler) NoOpPropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.NoOpPropertyAnnotationHandler) NoOpPropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.NoOpPropertyAnnotationHandler)

Example 3 with PropertyAnnotationHandler

use of org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler 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)

Example 4 with PropertyAnnotationHandler

use of org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler in project gradle by gradle.

the class ValidationServicesFixture method getServices.

public static ServiceRegistry getServices() {
    DefaultServiceRegistry registry = new DefaultServiceRegistry();
    registry.addProvider(new Object() {

        ExecutionGlobalServices.AnnotationHandlerRegistration createAnnotationRegistration() {
            return () -> ImmutableList.of(ValidationProblem.class);
        }

        PropertyAnnotationHandler createValidationProblemAnnotationHandler() {
            return new ValidationProblemPropertyAnnotationHandler();
        }
    });
    return registry;
}
Also used : DefaultServiceRegistry(org.gradle.internal.service.DefaultServiceRegistry) PropertyAnnotationHandler(org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler)

Aggregations

PropertyAnnotationHandler (org.gradle.api.internal.tasks.properties.annotations.PropertyAnnotationHandler)4 PropertyMetadata (org.gradle.internal.reflect.PropertyMetadata)2 ImmutableList (com.google.common.collect.ImmutableList)1 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 BeanPropertyContext (org.gradle.api.internal.tasks.properties.BeanPropertyContext)1 NORMALIZATION (org.gradle.api.internal.tasks.properties.ModifierAnnotationCategory.NORMALIZATION)1 PropertyValue (org.gradle.api.internal.tasks.properties.PropertyValue)1 TypeMetadata (org.gradle.api.internal.tasks.properties.TypeMetadata)1