/**
* Validates that among the dependencies are at most one scoped dependency,
* that there are no cycles within the scoping chain, and that singleton
* components have no scoped dependencies.
*/
private void validateDependencyScopes(BindingGraph subject,
Builder<BindingGraph> reportBuilder) {
ComponentDescriptor descriptor = subject.componentDescriptor();
Optional<AnnotationMirror> scope = subject.componentDescriptor().scope();
ImmutableSet<TypeElement> scopedDependencies = scopedTypesIn(descriptor.dependencies());
if (scope.isPresent()) {
// Dagger 1.x scope compatibility requires this be suppress-able.
if (scopeCycleValidationType.diagnosticKind().isPresent()
&& isTypeOf(Singleton.class, scope.get().getAnnotationType())) {
// Singleton is a special-case representing the longest lifetime, and therefore
// @Singleton components may not depend on scoped components
if (!scopedDependencies.isEmpty()) {
StringBuilder message = new StringBuilder(
"This @Singleton component cannot depend on scoped components:\n");
appendIndentedComponentsList(message, scopedDependencies);
reportBuilder.addItem(message.toString(),
scopeCycleValidationType.diagnosticKind().get(),
descriptor.componentDefinitionType(),
descriptor.componentAnnotation());
}
} else if (scopedDependencies.size() > 1) {
// Scoped components may depend on at most one scoped component.
StringBuilder message = new StringBuilder(ErrorMessages.format(scope.get()))
.append(' ')
.append(descriptor.componentDefinitionType().getQualifiedName())
.append(" depends on more than one scoped component:\n");
appendIndentedComponentsList(message, scopedDependencies);
reportBuilder.addItem(message.toString(),
descriptor.componentDefinitionType(),
descriptor.componentAnnotation());
} else {
// Dagger 1.x scope compatibility requires this be suppress-able.
if (!scopeCycleValidationType.equals(ValidationType.NONE)) {
validateScopeHierarchy(descriptor.componentDefinitionType(),
descriptor.componentDefinitionType(),
reportBuilder,
new ArrayDeque<Equivalence.Wrapper<AnnotationMirror>>(),
new ArrayDeque<TypeElement>());
}
}
} else {
// Scopeless components may not depend on scoped components.
if (!scopedDependencies.isEmpty()) {
StringBuilder message =
new StringBuilder(descriptor.componentDefinitionType().getQualifiedName())
.append(" (unscoped) cannot depend on scoped components:\n");
appendIndentedComponentsList(message, scopedDependencies);
reportBuilder.addItem(message.toString(),
descriptor.componentDefinitionType(),
descriptor.componentAnnotation());
}
}
}
Last active
August 29, 2015 14:22
-
-
Save twocity/fbe5a60f78ca6219d004 to your computer and use it in GitHub Desktop.
validateDependencyScopes
// For every @Provides method, confirm it overrides nothing *and* nothing overrides it.
// Consider the following hierarchy:
// class Parent {
// @Provides Foo a() {}
// @Provides Foo b() {}
// Foo c() {}
// }
// class Child extends Parent {
// @Provides Foo a() {}
// Foo b() {}
// @Provides Foo c() {}
// }
// In each of those cases, we want to fail. "a" is clear, "b" because Child is overriding
// a method marked @Provides in Parent, and "c" because Child is defining an @Provides
// method that overrides Parent.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment