Skip to content

Commit

Permalink
Add module-level validation. When -Adagger.moduleBindingValidation=ER…
Browse files Browse the repository at this point in the history
…ROR or =WARNING is set, then each module is processed as a kind of component (without generating any code) in order to validate the bindings installed by it and all included modules. Any binding graph errors, such as duplicate bindngs (but not including missing bindings), will be reported as errors or warnings depending on the option. SPI plugins will also run on those module-level binding graphs.

Relnotes:
    Add module-level validation. When `-Adagger.moduleBindingValidation=ERROR` or
    `=WARNING` is set, then each module is processed as a kind of component (without
    generating any code) in order to validate the bindings installed by it and all included
    modules. Any binding graph errors, such as duplicate bindngs (but not including
    missing bindings), will be reported as errors or warnings depending on the option.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=223803671
  • Loading branch information
netdpb authored and ronshapiro committed Dec 5, 2018
1 parent c940d6d commit 325b516
Show file tree
Hide file tree
Showing 32 changed files with 1,026 additions and 288 deletions.
18 changes: 9 additions & 9 deletions java/dagger/internal/codegen/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,11 @@ java_library(
"AnnotationExpression.java",
"Binding.java",
"BindingDeclaration.java",
"BindingDeclarationFormatter.java",
"BindingFactory.java",
"BindingGraph.java",
"BindingGraphConverter.java",
"BindingGraphFactory.java",
"BindingNode.java",
"BindingRequest.java",
"BindingType.java",
Expand All @@ -142,6 +145,7 @@ java_library(
"DelegateDeclaration.java",
"DependencyEdgeImpl.java",
"DependencyRequestFactory.java",
"DependencyRequestFormatter.java",
"DependencyVariableNamer.java", # Used by SourceFiles
"ErrorMessages.java", # Consider splitting this up as it pulls in too much
"FrameworkDependency.java",
Expand All @@ -154,6 +158,7 @@ java_library(
"MapKeys.java",
"MembersInjectionBinding.java",
"MethodSignature.java",
"MethodSignatureFormatter.java",
"ModuleDescriptor.java",
"MultibindingDeclaration.java",
"OptionalBindingDeclaration.java",
Expand All @@ -174,7 +179,7 @@ java_library(
name = "validation",
srcs = [
"AnyBindingMethodValidator.java",
"BindingDeclarationFormatter.java",
"BindingGraphPlugins.java",
"BindingMethodProcessingStep.java",
"BindingMethodValidator.java",
"BindsInstanceProcessingStep.java",
Expand All @@ -184,12 +189,12 @@ java_library(
"ComponentDescriptorValidator.java",
"ComponentHierarchyValidator.java",
"ComponentValidator.java",
"DependencyRequestFormatter.java",
"DependencyRequestValidator.java",
"DiagnosticReporterFactory.java",
"InjectValidator.java",
"MapKeyValidator.java",
"MembersInjectionValidator.java",
"MethodSignatureFormatter.java",
"ModuleValidation.java",
"ModuleValidator.java",
"MultibindingAnnotationsProcessingStep.java",
"MultibindsMethodValidator.java",
Expand All @@ -208,10 +213,8 @@ java_library(
java_library(
name = "binding_graph_validation",
srcs = [
"BindingGraphPlugins.java",
"DependencyCycleValidator.java",
"DependsOnProductionExecutorValidator.java",
"DiagnosticReporterFactory.java",
"DuplicateBindingsValidator.java",
"IncompatiblyScopedBindingsValidator.java",
"InjectBindingValidator.java",
Expand All @@ -220,7 +223,6 @@ java_library(
"NullableBindingValidator.java",
"ProvisionDependencyOnProducerBindingValidator.java",
"SubcomponentFactoryMethodValidator.java",
"Validation.java",
],
plugins = CODEGEN_PLUGINS,
tags = ["maven:merged"],
Expand Down Expand Up @@ -324,8 +326,6 @@ simple_jar(
java_library(
name = "processor",
srcs = [
"BindingGraphConverter.java",
"BindingGraphFactory.java",
"BindingGraphValidationModule.java",
"BindingMethodValidatorsModule.java",
"ComponentGenerator.java",
Expand All @@ -342,6 +342,7 @@ java_library(
"SourceFileGeneratorsModule.java",
"SpiModule.java",
"SystemComponentsModule.java",
"Validation.java",
],
plugins = CODEGEN_PLUGINS,
resource_jars = [":processor_manifest_files.jar"],
Expand Down Expand Up @@ -376,7 +377,6 @@ java_library(
deps = [
":base",
":binding",
":binding_graph_validation",
":kythe_plugin",
":processor",
":validation",
Expand Down
3 changes: 2 additions & 1 deletion java/dagger/internal/codegen/BindingGraphConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ dagger.model.BindingGraph convert(BindingGraph rootGraph) {
unreachableNodes(traverser.network.asGraph(), rootComponentNode(traverser.network))
.forEach(traverser.network::removeNode);

return BindingGraphProxies.bindingGraph(traverser.network);
return BindingGraphProxies.bindingGraph(
traverser.network, rootGraph.componentDescriptor().kind().isForModuleValidation());
}

// TODO(dpb): Example of BindingGraph logic applied to derived networks.
Expand Down
7 changes: 5 additions & 2 deletions java/dagger/internal/codegen/BindingGraphFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,11 @@ private BindingGraph create(
ImmutableSet.Builder<DelegateDeclaration> delegatesBuilder = ImmutableSet.builder();
ImmutableSet.Builder<OptionalBindingDeclaration> optionalsBuilder = ImmutableSet.builder();

// binding for the component itself
explicitBindingsBuilder.add(bindingFactory.componentBinding(componentDescriptor.typeElement()));
if (!componentDescriptor.kind().isForModuleValidation()) {
// binding for the component itself
explicitBindingsBuilder.add(
bindingFactory.componentBinding(componentDescriptor.typeElement()));
}

// Collect Component dependencies.
for (ComponentRequirement dependency : componentDescriptor.dependencies()) {
Expand Down
22 changes: 22 additions & 0 deletions java/dagger/internal/codegen/BindingGraphValidationModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,26 @@ static BindingGraphPlugins validationPlugins(
return new BindingGraphPlugins(
validationPlugins, filer, types, elements, processingOptions, diagnosticReporterFactory);
}

@Provides
@Singleton
@ModuleValidation
static BindingGraphPlugins moduleValidationPlugins(
@Validation Set<BindingGraphPlugin> validationPlugins,
Filer filer,
Types types,
Elements elements,
@ProcessingOptions Map<String, String> processingOptions,
DiagnosticReporterFactory diagnosticReporterFactory,
CompilerOptions compilerOptions) {
return new BindingGraphPlugins(
validationPlugins,
filer,
types,
elements,
processingOptions,
diagnosticReporterFactory
.treatingErrorsAs(compilerOptions.moduleBindingValidationType())
.withoutPrintingEntryPoints());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ final class BindsInstanceProcessingStep extends TypeCheckingProcessingStep<Execu

private static final ImmutableSet<Class<? extends Annotation>> COMPONENT_ANNOTATIONS =
Stream.of(ComponentDescriptor.Kind.values())
.filter(kind -> !kind.isForModuleValidation())
.map(ComponentDescriptor.Kind::annotationType)
.collect(toImmutableSet());
private static final ImmutableSet<Class<? extends Annotation>> MODULE_ANNOTATIONS =
Expand Down
2 changes: 1 addition & 1 deletion java/dagger/internal/codegen/BuilderValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public ValidationReport<TypeElement> validate(TypeElement subject) {
Element componentElement = subject.getEnclosingElement();
ErrorMessages.ComponentBuilderMessages msgs = ErrorMessages.builderMsgsFor(componentKind);
Class<? extends Annotation> componentAnnotation = componentKind.annotationType();
Class<? extends Annotation> builderAnnotation = componentKind.builderAnnotationType();
Class<? extends Annotation> builderAnnotation = componentKind.builderAnnotationType().get();
checkArgument(subject.getAnnotation(builderAnnotation) != null);

if (!isAnnotationPresent(componentElement, componentAnnotation)) {
Expand Down
30 changes: 25 additions & 5 deletions java/dagger/internal/codegen/CompilerOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import static dagger.internal.codegen.FeatureStatus.DISABLED;
import static dagger.internal.codegen.FeatureStatus.ENABLED;
import static dagger.internal.codegen.ValidationType.ERROR;
import static dagger.internal.codegen.ValidationType.NONE;
import static dagger.internal.codegen.ValidationType.WARNING;
import static java.util.EnumSet.allOf;

Expand Down Expand Up @@ -104,6 +105,10 @@ boolean doCheckForNulls() {

abstract boolean useGradleIncrementalProcessing();

abstract ValidationType moduleBindingValidationType();

abstract Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind();

static Builder builder() {
return new AutoValue_CompilerOptions.Builder()
.headerCompilation(false)
Expand Down Expand Up @@ -158,6 +163,10 @@ Builder warnIfInjectionFactoryNotGeneratedUpstream(

Builder useGradleIncrementalProcessing(boolean enabled);

Builder moduleBindingValidationType(ValidationType validationType);

Builder moduleHasDifferentScopesDiagnosticKind(Diagnostic.Kind kind);

@CheckReturnValue
CompilerOptions build();
}
Expand Down Expand Up @@ -296,6 +305,16 @@ private enum Validation implements Option {
PRIVATE_MEMBER_VALIDATION(kindSetter(Builder::privateMemberValidationKind), ERROR, WARNING),

STATIC_MEMBER_VALIDATION(kindSetter(Builder::staticMemberValidationKind), ERROR, WARNING),

/** Whether to validate partial binding graphs associated with modules. */
MODULE_BINDING_VALIDATION(Builder::moduleBindingValidationType, NONE, ERROR, WARNING),

/**
* How to report conflicting scoped bindings when validating partial binding graphs associated
* with modules.
*/
MODULE_HAS_DIFFERENT_SCOPES_VALIDATION(
kindSetter(Builder::moduleHasDifferentScopesDiagnosticKind), ERROR, WARNING),
;

static BiConsumer<Builder, ValidationType> kindSetter(
Expand All @@ -304,20 +323,21 @@ static BiConsumer<Builder, ValidationType> kindSetter(
setter.accept(builder, validationType.diagnosticKind().get());
}

final ValidationType defaultType;
final ImmutableSet<ValidationType> validTypes;
final BiConsumer<Builder, ValidationType> setter;

Validation(BiConsumer<Builder, ValidationType> setter) {
this.setter = setter;
this.validTypes = immutableEnumSet(allOf(ValidationType.class));
this(setter, ERROR, WARNING, NONE);
}

Validation(
BiConsumer<Builder, ValidationType> setter,
ValidationType validType,
ValidationType defaultType,
ValidationType... moreValidTypes) {
this.setter = setter;
this.validTypes = immutableEnumSet(validType, moreValidTypes);
this.defaultType = defaultType;
this.validTypes = immutableEnumSet(defaultType, moreValidTypes);
}

@Override
Expand All @@ -326,7 +346,7 @@ public void set(Builder builder, ProcessingEnvironment processingEnvironment) {
}

ValidationType validationType(ProcessingEnvironment processingEnvironment) {
return CompilerOptions.valueOf(processingEnvironment, toString(), ERROR, validTypes);
return CompilerOptions.valueOf(processingEnvironment, toString(), defaultType, validTypes);
}

@Override
Expand Down
Loading

0 comments on commit 325b516

Please sign in to comment.