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());
}
}
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;
}
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));
}
Aggregations