Search in sources :

Example 1 with AttributeDescriber

use of org.gradle.api.internal.attributes.AttributeDescriber in project gradle by gradle.

the class AttributeConfigurationSelector method selectConfigurationUsingAttributeMatching.

private static ConfigurationMetadata selectConfigurationUsingAttributeMatching(ImmutableAttributes consumerAttributes, Collection<? extends Capability> explicitRequestedCapabilities, ComponentResolveMetadata targetComponent, AttributesSchemaInternal consumerSchema, List<IvyArtifactName> requestedArtifacts, AttributeMatchingExplanationBuilder explanationBuilder) {
    Optional<ImmutableList<? extends ConfigurationMetadata>> variantsForGraphTraversal = targetComponent.getVariantsForGraphTraversal();
    ImmutableList<? extends ConfigurationMetadata> consumableConfigurations = variantsForGraphTraversal.or(ImmutableList.of());
    AttributesSchemaInternal producerAttributeSchema = targetComponent.getAttributesSchema();
    AttributeMatcher attributeMatcher = consumerSchema.withProducer(producerAttributeSchema);
    ConfigurationMetadata fallbackConfiguration = targetComponent.getConfiguration(Dependency.DEFAULT_CONFIGURATION);
    if (fallbackConfiguration != null && !fallbackConfiguration.isCanBeConsumed()) {
        fallbackConfiguration = null;
    }
    ModuleVersionIdentifier versionId = targetComponent.getModuleVersionId();
    if (!consumableConfigurations.isEmpty()) {
        ImmutableList<ConfigurationMetadata> variantsProvidingRequestedCapabilities = filterVariantsByRequestedCapabilities(targetComponent, explicitRequestedCapabilities, consumableConfigurations, versionId.getGroup(), versionId.getName(), true, explanationBuilder);
        if (variantsProvidingRequestedCapabilities.isEmpty()) {
            throw new NoMatchingCapabilitiesException(targetComponent, explicitRequestedCapabilities, consumableConfigurations);
        }
        consumableConfigurations = variantsProvidingRequestedCapabilities;
    }
    List<ConfigurationMetadata> matches = attributeMatcher.matches(consumableConfigurations, consumerAttributes, fallbackConfiguration, explanationBuilder);
    if (matches.size() > 1) {
        // there's an ambiguity, but we may have several variants matching the requested capabilities.
        // Here we're going to check if in the candidates, there's a single one _strictly_ matching the requested capabilities.
        List<ConfigurationMetadata> strictlyMatchingCapabilities = filterVariantsByRequestedCapabilities(targetComponent, explicitRequestedCapabilities, matches, versionId.getGroup(), versionId.getName(), false, explanationBuilder);
        if (strictlyMatchingCapabilities.size() == 1) {
            return singleVariant(variantsForGraphTraversal, strictlyMatchingCapabilities);
        } else if (strictlyMatchingCapabilities.size() > 1) {
            // there are still more than one candidate, but this time we know only a subset strictly matches the required attributes
            // so we perform another round of selection on the remaining candidates
            strictlyMatchingCapabilities = attributeMatcher.matches(strictlyMatchingCapabilities, consumerAttributes, fallbackConfiguration, explanationBuilder);
            if (strictlyMatchingCapabilities.size() == 1) {
                return singleVariant(variantsForGraphTraversal, strictlyMatchingCapabilities);
            }
        }
        if (requestedArtifacts.size() == 1) {
            // Here, we know that the user requested a specific classifier. There may be multiple
            // candidate variants left, but maybe only one of them provides the classified artifact
            // we're looking for.
            String classifier = requestedArtifacts.get(0).getClassifier();
            if (classifier != null) {
                List<ConfigurationMetadata> sameClassifier = findVariantsProvidingExactlySameClassifier(matches, classifier);
                if (sameClassifier != null && sameClassifier.size() == 1) {
                    return singleVariant(variantsForGraphTraversal, sameClassifier);
                }
            }
        }
    }
    if (matches.size() == 1) {
        return singleVariant(variantsForGraphTraversal, matches);
    } else if (!matches.isEmpty()) {
        AttributeDescriber describer = DescriberSelector.selectDescriber(consumerAttributes, consumerSchema);
        if (explanationBuilder instanceof TraceDiscardedConfigurations) {
            Set<ConfigurationMetadata> discarded = Cast.uncheckedCast(((TraceDiscardedConfigurations) explanationBuilder).discarded);
            throw new AmbiguousConfigurationSelectionException(describer, consumerAttributes, attributeMatcher, matches, targetComponent, variantsForGraphTraversal.isPresent(), discarded);
        } else {
            // Perform a second resolution with tracing
            return selectConfigurationUsingAttributeMatching(consumerAttributes, explicitRequestedCapabilities, targetComponent, consumerSchema, requestedArtifacts, new TraceDiscardedConfigurations());
        }
    } else {
        AttributeDescriber describer = DescriberSelector.selectDescriber(consumerAttributes, consumerSchema);
        throw new NoMatchingConfigurationSelectionException(describer, consumerAttributes, attributeMatcher, targetComponent, variantsForGraphTraversal.isPresent());
    }
}
Also used : Set(java.util.Set) AmbiguousConfigurationSelectionException(org.gradle.internal.component.AmbiguousConfigurationSelectionException) ImmutableList(com.google.common.collect.ImmutableList) NoMatchingCapabilitiesException(org.gradle.internal.component.NoMatchingCapabilitiesException) AttributesSchemaInternal(org.gradle.api.internal.attributes.AttributesSchemaInternal) NoMatchingConfigurationSelectionException(org.gradle.internal.component.NoMatchingConfigurationSelectionException) ModuleVersionIdentifier(org.gradle.api.artifacts.ModuleVersionIdentifier) AttributeDescriber(org.gradle.api.internal.attributes.AttributeDescriber)

Example 2 with AttributeDescriber

use of org.gradle.api.internal.attributes.AttributeDescriber in project gradle by gradle.

the class DescriberSelector method selectDescriber.

public static AttributeDescriber selectDescriber(AttributeContainerInternal consumerAttributes, AttributesSchemaInternal consumerSchema) {
    List<AttributeDescriber> consumerDescribers = consumerSchema.getConsumerDescribers();
    Set<Attribute<?>> consumerAttributeSet = consumerAttributes.keySet();
    AttributeDescriber current = null;
    int maxSize = 0;
    for (AttributeDescriber consumerDescriber : consumerDescribers) {
        int size = Sets.intersection(consumerDescriber.getAttributes(), consumerAttributeSet).size();
        if (size > maxSize) {
            // Select the describer which handles the maximum number of attributes
            current = consumerDescriber;
            maxSize = size;
        }
    }
    if (current != null) {
        return new FallbackDescriber(current);
    }
    return DefaultDescriber.INSTANCE;
}
Also used : Attribute(org.gradle.api.attributes.Attribute) AttributeDescriber(org.gradle.api.internal.attributes.AttributeDescriber)

Example 3 with AttributeDescriber

use of org.gradle.api.internal.attributes.AttributeDescriber in project gradle by gradle.

the class AttributeMatchingVariantSelector method doSelect.

private ResolvedArtifactSet doSelect(ResolvedVariantSet producer, Factory factory, AttributeMatchingExplanationBuilder explanationBuilder) {
    AttributeMatcher matcher = schema.withProducer(producer.getSchema());
    ImmutableAttributes componentRequested = attributesFactory.concat(requested, producer.getOverriddenAttributes());
    List<? extends ResolvedVariant> matches = matcher.matches(producer.getVariants(), componentRequested, explanationBuilder);
    if (matches.size() == 1) {
        return matches.get(0).getArtifacts();
    }
    if (matches.size() > 1) {
        if (explanationBuilder instanceof TraceDiscardedVariants) {
            Set<ResolvedVariant> discarded = Cast.uncheckedCast(((TraceDiscardedVariants) explanationBuilder).discarded);
            AttributeDescriber describer = DescriberSelector.selectDescriber(componentRequested, schema);
            throw new AmbiguousVariantSelectionException(describer, producer.asDescribable().getDisplayName(), componentRequested, matches, matcher, discarded);
        } else {
            // because we're going to fail, we can afford a second run with details
            return doSelect(producer, factory, new TraceDiscardedVariants());
        }
    }
    List<Pair<ResolvedVariant, MutableConsumerVariantMatchResult.ConsumerVariant>> candidates = new ArrayList<>();
    for (ResolvedVariant variant : producer.getVariants()) {
        AttributeContainerInternal variantAttributes = variant.getAttributes().asImmutable();
        ConsumerVariantMatchResult matchResult = consumerProvidedVariantFinder.collectConsumerVariants(variantAttributes, componentRequested);
        for (MutableConsumerVariantMatchResult.ConsumerVariant consumerVariant : matchResult.getMatches()) {
            candidates.add(Pair.of(variant, consumerVariant));
        }
    }
    if (candidates.size() > 1) {
        candidates = tryDisambiguate(matcher, candidates, componentRequested, explanationBuilder);
    }
    if (candidates.size() == 1) {
        Pair<ResolvedVariant, MutableConsumerVariantMatchResult.ConsumerVariant> result = candidates.get(0);
        ResolvedVariant variant = result.getLeft();
        VariantDefinition definition = result.getRight();
        return factory.asTransformed(variant, definition, dependenciesResolver, transformedVariantFactory);
    }
    if (!candidates.isEmpty()) {
        throw new AmbiguousTransformException(producer.asDescribable().getDisplayName(), componentRequested, candidates);
    }
    if (ignoreWhenNoMatches) {
        return ResolvedArtifactSet.EMPTY;
    }
    throw new NoMatchingVariantSelectionException(producer.asDescribable().getDisplayName(), componentRequested, producer.getVariants(), matcher, DescriberSelector.selectDescriber(componentRequested, schema));
}
Also used : AttributeMatcher(org.gradle.internal.component.model.AttributeMatcher) ImmutableAttributes(org.gradle.api.internal.attributes.ImmutableAttributes) NoMatchingVariantSelectionException(org.gradle.internal.component.NoMatchingVariantSelectionException) ResolvedVariant(org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedVariant) ArrayList(java.util.ArrayList) AttributeContainerInternal(org.gradle.api.internal.attributes.AttributeContainerInternal) AmbiguousVariantSelectionException(org.gradle.internal.component.AmbiguousVariantSelectionException) AttributeDescriber(org.gradle.api.internal.attributes.AttributeDescriber) Pair(org.gradle.internal.Pair)

Aggregations

AttributeDescriber (org.gradle.api.internal.attributes.AttributeDescriber)3 ImmutableList (com.google.common.collect.ImmutableList)1 ArrayList (java.util.ArrayList)1 Set (java.util.Set)1 ModuleVersionIdentifier (org.gradle.api.artifacts.ModuleVersionIdentifier)1 Attribute (org.gradle.api.attributes.Attribute)1 ResolvedVariant (org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvedVariant)1 AttributeContainerInternal (org.gradle.api.internal.attributes.AttributeContainerInternal)1 AttributesSchemaInternal (org.gradle.api.internal.attributes.AttributesSchemaInternal)1 ImmutableAttributes (org.gradle.api.internal.attributes.ImmutableAttributes)1 Pair (org.gradle.internal.Pair)1 AmbiguousConfigurationSelectionException (org.gradle.internal.component.AmbiguousConfigurationSelectionException)1 AmbiguousVariantSelectionException (org.gradle.internal.component.AmbiguousVariantSelectionException)1 NoMatchingCapabilitiesException (org.gradle.internal.component.NoMatchingCapabilitiesException)1 NoMatchingConfigurationSelectionException (org.gradle.internal.component.NoMatchingConfigurationSelectionException)1 NoMatchingVariantSelectionException (org.gradle.internal.component.NoMatchingVariantSelectionException)1 AttributeMatcher (org.gradle.internal.component.model.AttributeMatcher)1