dagger.internal.codegen.processingstep.ComponentProcessingStep 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.
/*
* Copyright (C) 2014 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.processingstep;
import static com.google.common.collect.Sets.union;
import static dagger.internal.codegen.base.ComponentAnnotation.allComponentAnnotations;
import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotations;
import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotations;
import static dagger.internal.codegen.base.ComponentCreatorAnnotation.allCreatorAnnotations;
import static java.util.Collections.disjoint;
import androidx.room.compiler.processing.XMessager;
import androidx.room.compiler.processing.XTypeElement;
import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.ClassName;
import dagger.internal.codegen.base.SourceFileGenerator;
import dagger.internal.codegen.binding.BindingGraph;
import dagger.internal.codegen.binding.BindingGraphFactory;
import dagger.internal.codegen.binding.ComponentDescriptor;
import dagger.internal.codegen.validation.BindingGraphValidator;
import dagger.internal.codegen.validation.ComponentCreatorValidator;
import dagger.internal.codegen.validation.ComponentDescriptorValidator;
import dagger.internal.codegen.validation.ComponentValidator;
import dagger.internal.codegen.validation.ValidationReport;
import java.util.Set;
import javax.inject.Inject;
/**
* A {@link ProcessingStep} that is responsible for dealing with a component or production component
* as part of the {@link ComponentProcessor}.
*/
final class ComponentProcessingStep extends TypeCheckingProcessingStep {
private final XMessager messager;
private final ComponentValidator componentValidator;
private final ComponentCreatorValidator creatorValidator;
private final ComponentDescriptorValidator componentDescriptorValidator;
private final ComponentDescriptor.Factory componentDescriptorFactory;
private final BindingGraphFactory bindingGraphFactory;
private final SourceFileGenerator componentGenerator;
private final BindingGraphValidator bindingGraphValidator;
@Inject
ComponentProcessingStep(
XMessager messager,
ComponentValidator componentValidator,
ComponentCreatorValidator creatorValidator,
ComponentDescriptorValidator componentDescriptorValidator,
ComponentDescriptor.Factory componentDescriptorFactory,
BindingGraphFactory bindingGraphFactory,
SourceFileGenerator componentGenerator,
BindingGraphValidator bindingGraphValidator) {
this.messager = messager;
this.componentValidator = componentValidator;
this.creatorValidator = creatorValidator;
this.componentDescriptorValidator = componentDescriptorValidator;
this.componentDescriptorFactory = componentDescriptorFactory;
this.bindingGraphFactory = bindingGraphFactory;
this.componentGenerator = componentGenerator;
this.bindingGraphValidator = bindingGraphValidator;
}
@Override
public Set annotationClassNames() {
return union(allComponentAnnotations(), allCreatorAnnotations());
}
@Override
protected void process(XTypeElement element, ImmutableSet annotations) {
if (!disjoint(annotations, rootComponentAnnotations())) {
processRootComponent(element);
}
if (!disjoint(annotations, subcomponentAnnotations())) {
processSubcomponent(element);
}
if (!disjoint(annotations, allCreatorAnnotations())) {
processCreator(element);
}
}
private void processRootComponent(XTypeElement component) {
if (!isComponentValid(component)) {
return;
}
ComponentDescriptor componentDescriptor =
componentDescriptorFactory.rootComponentDescriptor(component);
if (!isValid(componentDescriptor)) {
return;
}
Supplier fullBindingGraphSupplier =
Suppliers.memoize(
() -> bindingGraphFactory.create(componentDescriptor, true).topLevelBindingGraph());
if (bindingGraphValidator.shouldDoFullBindingGraphValidation(component)) {
if (!bindingGraphValidator.isValid(fullBindingGraphSupplier.get())) {
return;
}
}
BindingGraph bindingGraph = bindingGraphFactory.create(componentDescriptor, false);
if (bindingGraphValidator.isValid(
bindingGraph.topLevelBindingGraph(), fullBindingGraphSupplier)) {
generateComponent(bindingGraph);
}
}
private void processSubcomponent(XTypeElement subcomponent) {
if (!isComponentValid(subcomponent)) {
return;
}
// TODO(dpb): ComponentDescriptorValidator for subcomponents, as we do for root components.
ComponentDescriptor subcomponentDescriptor =
componentDescriptorFactory.subcomponentDescriptor(subcomponent);
if (!bindingGraphValidator.shouldDoFullBindingGraphValidation(subcomponent)) {
return;
}
BindingGraph fullBindingGraph = bindingGraphFactory.create(subcomponentDescriptor, true);
// In this case, we don't actually care about the return value. The important part here is that
// BindingGraphValidator#isValid() runs all of the SPI plugins and reports any errors.
// TODO(bcorso): Add a separate API with no return value for this particular case.
boolean unusedIsValid = bindingGraphValidator.isValid(fullBindingGraph.topLevelBindingGraph());
}
private void generateComponent(BindingGraph bindingGraph) {
componentGenerator.generate(bindingGraph, messager);
}
private void processCreator(XTypeElement creator) {
creatorValidator.validate(creator).printMessagesTo(messager);
}
private boolean isComponentValid(XTypeElement component) {
ValidationReport report = componentValidator.validate(component);
report.printMessagesTo(messager);
return report.isClean();
}
private boolean isValid(ComponentDescriptor componentDescriptor) {
ValidationReport componentDescriptorReport =
componentDescriptorValidator.validate(componentDescriptor);
componentDescriptorReport.printMessagesTo(messager);
return componentDescriptorReport.isClean();
}
}