Search in sources :

Example 1 with TypeValidationContext

use of org.gradle.internal.reflect.validation.TypeValidationContext in project gradle by gradle.

the class DefaultNodeValidator method hasValidationProblems.

@Override
public boolean hasValidationProblems(Node node) {
    if (node instanceof LocalTaskNode) {
        LocalTaskNode taskNode = (LocalTaskNode) node;
        WorkValidationContext validationContext = taskNode.getValidationContext();
        Class<?> taskType = GeneratedSubclasses.unpackType(taskNode.getTask());
        // We don't know whether the task is cacheable or not, so we ignore cacheability problems for scheduling
        TypeValidationContext taskValidationContext = validationContext.forType(taskType, false);
        taskNode.getTaskProperties().validateType(taskValidationContext);
        List<TypeValidationProblem> problems = validationContext.getProblems();
        problems.stream().filter(problem -> problem.getSeverity().isWarning()).forEach(problem -> {
            Optional<UserManualReference> userManualReference = problem.getUserManualReference();
            String docId = "more_about_tasks";
            String section = "sec:up_to_date_checks";
            if (userManualReference.isPresent()) {
                UserManualReference docref = userManualReference.get();
                docId = docref.getId();
                section = docref.getSection();
            }
            // Because our deprecation warning system doesn't support multiline strings (bummer!) both in rendering
            // **and** testing (no way to capture multiline deprecation warnings), we have to resort to removing details
            // and rendering
            String warning = convertToSingleLine(renderMinimalInformationAbout(problem, false, false));
            DeprecationLogger.deprecateBehaviour(warning).withContext("Execution optimizations are disabled to ensure correctness.").willBeRemovedInGradle8().withUserManual(docId, section).nagUser();
        });
        return !problems.isEmpty();
    } else {
        return false;
    }
}
Also used : TypeValidationProblem(org.gradle.internal.reflect.validation.TypeValidationProblem) GeneratedSubclasses(org.gradle.api.internal.GeneratedSubclasses) TypeValidationProblemRenderer.renderMinimalInformationAbout(org.gradle.internal.reflect.validation.TypeValidationProblemRenderer.renderMinimalInformationAbout) WorkValidationContext(org.gradle.internal.execution.WorkValidationContext) List(java.util.List) UserManualReference(org.gradle.internal.reflect.validation.UserManualReference) TypeValidationProblemRenderer.convertToSingleLine(org.gradle.internal.reflect.validation.TypeValidationProblemRenderer.convertToSingleLine) DeprecationLogger(org.gradle.internal.deprecation.DeprecationLogger) Optional(java.util.Optional) TypeValidationContext(org.gradle.internal.reflect.validation.TypeValidationContext) UserManualReference(org.gradle.internal.reflect.validation.UserManualReference) TypeValidationProblem(org.gradle.internal.reflect.validation.TypeValidationProblem) TypeValidationContext(org.gradle.internal.reflect.validation.TypeValidationContext) WorkValidationContext(org.gradle.internal.execution.WorkValidationContext)

Example 2 with TypeValidationContext

use of org.gradle.internal.reflect.validation.TypeValidationContext in project gradle by gradle.

the class TaskExecution method validate.

@Override
public void validate(WorkValidationContext validationContext) {
    Class<?> taskType = GeneratedSubclasses.unpackType(task);
    // TODO This should probably use the task class info store
    boolean cacheable = taskType.isAnnotationPresent(CacheableTask.class);
    TypeValidationContext typeValidationContext = validationContext.forType(taskType, cacheable);
    context.getTaskProperties().validateType(typeValidationContext);
    context.getTaskProperties().validate(new DefaultTaskValidationContext(fileOperations, reservedFileSystemLocationRegistry, typeValidationContext));
    context.getValidationAction().validate(context.getTaskExecutionMode().isTaskHistoryMaintained(), typeValidationContext);
}
Also used : DefaultTaskValidationContext(org.gradle.api.internal.tasks.DefaultTaskValidationContext) TypeValidationContext(org.gradle.internal.reflect.validation.TypeValidationContext)

Example 3 with TypeValidationContext

use of org.gradle.internal.reflect.validation.TypeValidationContext in project gradle by gradle.

the class DefaultTypeAnnotationMetadataStore method mergePropertiesAndFieldMetadata.

private ImmutableSortedSet<PropertyAnnotationMetadata> mergePropertiesAndFieldMetadata(Class<?> type, ImmutableList<PropertyAnnotationMetadataBuilder> propertyBuilders, ImmutableMap<String, ImmutableMap<Class<? extends Annotation>, Annotation>> fieldAnnotationsByPropertyName, TypeValidationContext validationContext) {
    ImmutableSortedSet.Builder<PropertyAnnotationMetadata> propertiesMetadataBuilder = ImmutableSortedSet.naturalOrder();
    ImmutableSet.Builder<String> fieldsSeenBuilder = ImmutableSet.builderWithExpectedSize(fieldAnnotationsByPropertyName.size());
    for (PropertyAnnotationMetadataBuilder metadataBuilder : propertyBuilders) {
        String propertyName = metadataBuilder.getPropertyName();
        ImmutableMap<Class<? extends Annotation>, Annotation> fieldAnnotations = fieldAnnotationsByPropertyName.get(propertyName);
        if (fieldAnnotations != null) {
            fieldsSeenBuilder.add(propertyName);
            for (Annotation annotation : fieldAnnotations.values()) {
                metadataBuilder.declareAnnotation(annotation);
            }
        }
        propertiesMetadataBuilder.add(metadataBuilder.build());
    }
    ImmutableSortedSet<PropertyAnnotationMetadata> propertiesMetadata = propertiesMetadataBuilder.build();
    // Report fields with annotations that have not been seen while processing properties
    ImmutableSet<String> fieldsSeen = fieldsSeenBuilder.build();
    if (fieldsSeen.size() != fieldAnnotationsByPropertyName.size()) {
        fieldAnnotationsByPropertyName.entrySet().stream().filter(entry -> {
            String fieldName = entry.getKey();
            ImmutableMap<Class<? extends Annotation>, Annotation> fieldAnnotations = entry.getValue();
            return !fieldAnnotations.isEmpty() && !fieldsSeen.contains(fieldName) && // @Inject is allowed on fields only
            !fieldAnnotations.containsKey(Inject.class);
        }).forEach(entry -> {
            String fieldName = entry.getKey();
            ImmutableMap<Class<? extends Annotation>, Annotation> fieldAnnotations = entry.getValue();
            validationContext.visitTypeProblem(problem -> problem.withId(ValidationProblemId.IGNORED_ANNOTATIONS_ON_FIELD).forType(type).reportAs(ERROR).withDescription(() -> String.format("field '%s' without corresponding getter has been annotated with %s", fieldName, simpleAnnotationNames(fieldAnnotations.keySet().stream()))).happensBecause("Annotations on fields are only used if there's a corresponding getter for the field").withLongDescription("If a field is annotated but there's no corresponding getter, then the annotations are ignored").addPossibleSolution(() -> "Add a getter for field '" + fieldName + "'").addPossibleSolution(() -> "Remove the annotations on '" + fieldName + "'").documentedAt("validation_problems", "ignored_annotations_on_field"));
        });
    }
    return propertiesMetadata;
}
Also used : Iterables(com.google.common.collect.Iterables) Arrays(java.util.Arrays) TypeAnnotationMetadata(org.gradle.internal.reflect.annotations.TypeAnnotationMetadata) ListMultimap(com.google.common.collect.ListMultimap) MultimapBuilder(com.google.common.collect.MultimapBuilder) HashMap(java.util.HashMap) PropertyAccessorType(org.gradle.internal.reflect.PropertyAccessorType) Inject(javax.inject.Inject) LinkedHashMap(java.util.LinkedHashMap) ImmutableList(com.google.common.collect.ImmutableList) Map(java.util.Map) TYPE(org.gradle.internal.reflect.AnnotationCategory.TYPE) Comparator.comparing(java.util.Comparator.comparing) Method(java.lang.reflect.Method) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) ImmutableSet(com.google.common.collect.ImmutableSet) Equivalence(com.google.common.base.Equivalence) Action(org.gradle.api.Action) Iterator(java.util.Iterator) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) 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) Field(java.lang.reflect.Field) Collectors(java.util.stream.Collectors) SetMultimap(com.google.common.collect.SetMultimap) Collectors.joining(java.util.stream.Collectors.joining) TypeAnnotationMetadataStore(org.gradle.internal.reflect.annotations.TypeAnnotationMetadataStore) List(java.util.List) SIGNATURE_EQUIVALENCE(org.gradle.internal.reflect.Methods.SIGNATURE_EQUIVALENCE) Stream(java.util.stream.Stream) Ordering(com.google.common.collect.Ordering) PropertyAnnotationMetadata(org.gradle.internal.reflect.annotations.PropertyAnnotationMetadata) ERROR(org.gradle.internal.reflect.validation.Severity.ERROR) PropertyProblemBuilder(org.gradle.internal.reflect.validation.PropertyProblemBuilder) Modifier(java.lang.reflect.Modifier) Annotation(java.lang.annotation.Annotation) CrossBuildInMemoryCacheFactory(org.gradle.cache.internal.CrossBuildInMemoryCacheFactory) ValidationProblemId(org.gradle.internal.reflect.problems.ValidationProblemId) AnnotatedElement(java.lang.reflect.AnnotatedElement) Inject(javax.inject.Inject) PropertyAnnotationMetadata(org.gradle.internal.reflect.annotations.PropertyAnnotationMetadata) Annotation(java.lang.annotation.Annotation) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet)

Example 4 with TypeValidationContext

use of org.gradle.internal.reflect.validation.TypeValidationContext in project gradle by gradle.

the class ValidateStep method validateImplementations.

private void validateImplementations(UnitOfWork work, BeforeExecutionState beforeExecutionState, WorkValidationContext validationContext) {
    MutableReference<Class<?>> workClass = MutableReference.empty();
    work.visitImplementations(new UnitOfWork.ImplementationVisitor() {

        @Override
        public void visitImplementation(Class<?> implementation) {
            workClass.set(GeneratedSubclasses.unpack(implementation));
        }

        @Override
        public void visitImplementation(ImplementationSnapshot implementation) {
        }
    });
    // It doesn't matter whether we use cacheable true or false, since none of the warnings depends on the cacheability of the task.
    Class<?> workType = workClass.get();
    TypeValidationContext workValidationContext = validationContext.forType(workType, true);
    validateImplementation(workValidationContext, beforeExecutionState.getImplementation(), "Implementation of ", work);
    beforeExecutionState.getAdditionalImplementations().forEach(additionalImplementation -> validateImplementation(workValidationContext, additionalImplementation, "Additional action of ", work));
    beforeExecutionState.getInputProperties().forEach((propertyName, valueSnapshot) -> {
        if (valueSnapshot instanceof ImplementationSnapshot) {
            ImplementationSnapshot implementationSnapshot = (ImplementationSnapshot) valueSnapshot;
            validateNestedInput(workValidationContext, propertyName, implementationSnapshot);
        }
    });
}
Also used : UnitOfWork(org.gradle.internal.execution.UnitOfWork) ImplementationSnapshot(org.gradle.internal.snapshot.impl.ImplementationSnapshot) TypeValidationContext(org.gradle.internal.reflect.validation.TypeValidationContext)

Example 5 with TypeValidationContext

use of org.gradle.internal.reflect.validation.TypeValidationContext in project gradle by gradle.

the class LocalTaskNodeExecutor method detectMissingDependencies.

private void detectMissingDependencies(LocalTaskNode node, boolean historyMaintained, ExecutionNodeAccessHierarchies.InputNodeAccessHierarchy inputHierarchy, TypeValidationContext validationContext) {
    for (String outputPath : node.getMutationInfo().outputPaths) {
        inputHierarchy.getNodesAccessing(outputPath).stream().filter(consumerNode -> hasNoSpecifiedOrder(node, consumerNode)).filter(LocalTaskNodeExecutor::isEnabled).forEach(consumerWithoutDependency -> collectValidationProblem(node, consumerWithoutDependency, validationContext, outputPath));
    }
    Set<String> taskInputs = new LinkedHashSet<>();
    Set<FilteredTree> filteredFileTreeTaskInputs = new LinkedHashSet<>();
    node.getTaskProperties().getInputFileProperties().forEach(spec -> {
        try {
            spec.getPropertyFiles().visitStructure(new FileCollectionStructureVisitor() {

                @Override
                public void visitCollection(FileCollectionInternal.Source source, Iterable<File> contents) {
                    contents.forEach(location -> taskInputs.add(location.getAbsolutePath()));
                }

                @Override
                public void visitGenericFileTree(FileTreeInternal fileTree, FileSystemMirroringFileTree sourceTree) {
                    fileTree.forEach(location -> taskInputs.add(location.getAbsolutePath()));
                }

                @Override
                public void visitFileTree(File root, PatternSet patterns, FileTreeInternal fileTree) {
                    if (patterns.isEmpty()) {
                        taskInputs.add(root.getAbsolutePath());
                    } else {
                        filteredFileTreeTaskInputs.add(new FilteredTree(root.getAbsolutePath(), patterns));
                    }
                }

                @Override
                public void visitFileTreeBackedByFile(File file, FileTreeInternal fileTree, FileSystemMirroringFileTree sourceTree) {
                    taskInputs.add(file.getAbsolutePath());
                }
            });
        } catch (Exception e) {
            if (historyMaintained) {
                // We would later try to snapshot the inputs anyway, no need to suppress the exception
                throw e;
            } else {
                validationContext.visitPropertyProblem(problem -> problem.withId(ValidationProblemId.UNRESOLVABLE_INPUT).forProperty(spec.getPropertyName()).reportAs(Severity.WARNING).withDescription(() -> String.format("cannot be resolved:%n%s%n", TextUtil.indent(e.getMessage(), "  "))).happensBecause("An input file collection couldn't be resolved, making it impossible to determine task inputs").addPossibleSolution("Consider using Task.dependsOn instead").documentedAt("validation_problems", "unresolvable_input"));
            }
        }
    });
    inputHierarchy.recordNodeAccessingLocations(node, taskInputs);
    for (String locationConsumedByThisTask : taskInputs) {
        collectValidationProblemsForConsumer(node, validationContext, locationConsumedByThisTask, outputHierarchy.getNodesAccessing(locationConsumedByThisTask));
    }
    for (FilteredTree filteredFileTreeInput : filteredFileTreeTaskInputs) {
        Spec<FileTreeElement> spec = filteredFileTreeInput.getPatterns().getAsSpec();
        inputHierarchy.recordNodeAccessingFileTree(node, filteredFileTreeInput.getRoot(), spec);
        collectValidationProblemsForConsumer(node, validationContext, filteredFileTreeInput.getRoot(), outputHierarchy.getNodesAccessing(filteredFileTreeInput.getRoot(), spec));
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Deque(java.util.Deque) Severity(org.gradle.internal.reflect.validation.Severity) DefaultTaskExecutionContext(org.gradle.api.internal.tasks.execution.DefaultTaskExecutionContext) HashSet(java.util.HashSet) TaskExecutionContext(org.gradle.api.internal.tasks.TaskExecutionContext) NodeExecutionContext(org.gradle.api.internal.tasks.NodeExecutionContext) TextUtil(org.gradle.util.internal.TextUtil) FileTreeElement(org.gradle.api.file.FileTreeElement) FileCollectionInternal(org.gradle.api.internal.file.FileCollectionInternal) LinkedHashSet(java.util.LinkedHashSet) TaskInternal(org.gradle.api.internal.TaskInternal) FileCollectionStructureVisitor(org.gradle.api.internal.file.FileCollectionStructureVisitor) FileSystemMirroringFileTree(org.gradle.api.internal.file.collections.FileSystemMirroringFileTree) PatternSet(org.gradle.api.tasks.util.PatternSet) Collection(java.util.Collection) Set(java.util.Set) TypeValidationContext(org.gradle.internal.reflect.validation.TypeValidationContext) TaskStateInternal(org.gradle.api.internal.tasks.TaskStateInternal) File(java.io.File) Objects(java.util.Objects) Spec(org.gradle.api.specs.Spec) TaskExecuter(org.gradle.api.internal.tasks.TaskExecuter) FileTreeInternal(org.gradle.api.internal.file.FileTreeInternal) Queue(java.util.Queue) ValidationProblemId(org.gradle.internal.reflect.problems.ValidationProblemId) ArrayDeque(java.util.ArrayDeque) FileTreeElement(org.gradle.api.file.FileTreeElement) FileTreeInternal(org.gradle.api.internal.file.FileTreeInternal) FileCollectionInternal(org.gradle.api.internal.file.FileCollectionInternal) FileCollectionStructureVisitor(org.gradle.api.internal.file.FileCollectionStructureVisitor) FileSystemMirroringFileTree(org.gradle.api.internal.file.collections.FileSystemMirroringFileTree) File(java.io.File) PatternSet(org.gradle.api.tasks.util.PatternSet)

Aggregations

TypeValidationContext (org.gradle.internal.reflect.validation.TypeValidationContext)5 Collection (java.util.Collection)2 List (java.util.List)2 Set (java.util.Set)2 Equivalence (com.google.common.base.Equivalence)1 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 ImmutableSortedSet (com.google.common.collect.ImmutableSortedSet)1 Iterables (com.google.common.collect.Iterables)1 ListMultimap (com.google.common.collect.ListMultimap)1 MultimapBuilder (com.google.common.collect.MultimapBuilder)1 Ordering (com.google.common.collect.Ordering)1 SetMultimap (com.google.common.collect.SetMultimap)1 File (java.io.File)1 Annotation (java.lang.annotation.Annotation)1 AnnotatedElement (java.lang.reflect.AnnotatedElement)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 Modifier (java.lang.reflect.Modifier)1