dagger.internal.codegen.binding.ComponentDeclarations Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dagger-compiler Show documentation
Show all versions of dagger-compiler Show documentation
A fast dependency injector for Android and Java.
The newest version!
/*
* Copyright (C) 2024 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dagger.internal.codegen.binding;
import static dagger.internal.codegen.binding.SourceFiles.generatedMonitoringModuleName;
import androidx.room.compiler.processing.XProcessingEnv;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimaps;
import dagger.internal.codegen.base.DaggerSuperficialValidation;
import dagger.internal.codegen.javapoet.TypeNames;
import dagger.internal.codegen.model.Key;
import java.util.Optional;
import javax.inject.Inject;
/** Stores the bindings and declarations of a component by key. */
final class ComponentDeclarations {
private final ImmutableSetMultimap bindings;
private final ImmutableSetMultimap delegates;
private final ImmutableSetMultimap multibindings;
private final ImmutableSetMultimap optionalBindings;
private final ImmutableSetMultimap subcomponents;
private final ImmutableSetMultimap multibindingContributions;
private final ImmutableSetMultimap delegateMultibindingContributions;
private ComponentDeclarations(
ImmutableSetMultimap bindings,
ImmutableSetMultimap delegates,
ImmutableSetMultimap multibindings,
ImmutableSetMultimap optionalBindings,
ImmutableSetMultimap subcomponents) {
this.bindings = bindings;
this.delegates = delegates;
this.multibindings = multibindings;
this.optionalBindings = optionalBindings;
this.subcomponents = subcomponents;
this.multibindingContributions = multibindingContributionsByMultibindingKey(bindings.values());
this.delegateMultibindingContributions =
multibindingContributionsByMultibindingKey(delegates.values());
}
ImmutableSet bindings(Key key) {
return bindings.get(key);
}
ImmutableSet delegates(Key key) {
return delegates.get(key);
}
ImmutableSet delegateMultibindingContributions(Key key) {
return delegateMultibindingContributions.get(key);
}
ImmutableSet multibindings(Key key) {
return multibindings.get(key);
}
ImmutableSet multibindingContributions(Key key) {
return multibindingContributions.get(key);
}
ImmutableSet optionalBindings(Key key) {
return optionalBindings.get(key);
}
ImmutableSet subcomponents(Key key) {
return subcomponents.get(key);
}
ImmutableSet allDeclarations() {
return ImmutableSet.builder()
.addAll(bindings.values())
.addAll(delegates.values())
.addAll(multibindings.values())
.addAll(optionalBindings.values())
.addAll(subcomponents.values())
.build();
}
/**
* A multimap of those {@code declarations} that are multibinding contribution declarations,
* indexed by the key of the set or map to which they contribute.
*/
private static
ImmutableSetMultimap multibindingContributionsByMultibindingKey(
Iterable declarations) {
ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder();
for (T declaration : declarations) {
if (declaration.key().multibindingContributionIdentifier().isPresent()) {
builder.put(declaration.key().withoutMultibindingContributionIdentifier(), declaration);
}
}
return builder.build();
}
static final class Factory {
private final XProcessingEnv processingEnv;
private final ModuleDescriptor.Factory moduleDescriptorFactory;
@Inject
Factory(
XProcessingEnv processingEnv,
ModuleDescriptor.Factory moduleDescriptorFactory) {
this.processingEnv = processingEnv;
this.moduleDescriptorFactory = moduleDescriptorFactory;
}
ComponentDeclarations create(
Optional parentDescriptor, ComponentDescriptor descriptor) {
ImmutableSet.Builder bindings = ImmutableSet.builder();
ImmutableSet.Builder delegates = ImmutableSet.builder();
ImmutableSet.Builder multibindings = ImmutableSet.builder();
ImmutableSet.Builder optionalBindings =ImmutableSet.builder();
ImmutableSet.Builder subcomponents = ImmutableSet.builder();
bindings.addAll(descriptor.bindings());
delegates.addAll(descriptor.delegateDeclarations());
multibindings.addAll(descriptor.multibindingDeclarations());
optionalBindings.addAll(descriptor.optionalBindingDeclarations());
subcomponents.addAll(descriptor.subcomponentDeclarations());
// Note: The implicit production modules are not included directly in the component descriptor
// because we don't know whether to install them or not without knowing the parent component.
for (ModuleDescriptor module : implicitProductionModules(descriptor, parentDescriptor)) {
bindings.addAll(module.bindings());
delegates.addAll(module.delegateDeclarations());
multibindings.addAll(module.multibindingDeclarations());
optionalBindings.addAll(module.optionalDeclarations());
subcomponents.addAll(module.subcomponentDeclarations());
}
return new ComponentDeclarations(
indexDeclarationsByKey(bindings.build()),
indexDeclarationsByKey(delegates.build()),
indexDeclarationsByKey(multibindings.build()),
indexDeclarationsByKey(optionalBindings.build()),
indexDeclarationsByKey(subcomponents.build()));
}
/**
* Returns all the modules that should be installed in the component. For production components
* and production subcomponents that have a parent that is not a production component or
* subcomponent, also includes the production monitoring module for the component and the
* production executor module.
*/
private ImmutableSet implicitProductionModules(
ComponentDescriptor descriptor, Optional parentDescriptor) {
return shouldIncludeImplicitProductionModules(descriptor, parentDescriptor)
? ImmutableSet.of(
moduleDescriptorFactory.create(
DaggerSuperficialValidation.requireTypeElement(
processingEnv, generatedMonitoringModuleName(descriptor.typeElement()))),
moduleDescriptorFactory.create(
processingEnv.requireTypeElement(TypeNames.PRODUCTION_EXECTUTOR_MODULE)))
: ImmutableSet.of();
}
private static boolean shouldIncludeImplicitProductionModules(
ComponentDescriptor descriptor, Optional parentDescriptor) {
return descriptor.isProduction()
&& descriptor.isRealComponent()
&& (parentDescriptor.isEmpty() || !parentDescriptor.get().isProduction());
}
/** Indexes {@code bindingDeclarations} by {@link BindingDeclaration#key()}. */
private static
ImmutableSetMultimap indexDeclarationsByKey(Iterable declarations) {
return ImmutableSetMultimap.copyOf(Multimaps.index(declarations, BindingDeclaration::key));
}
}
}