private String entryPointErrorMessage(DependencyEdge entryPoint) { return String.format( "%s is a provision entry-point, which cannot depend on a production.", entryPoint.dependencyRequest().key()); }
@Override public String visitExecutableAsMethod(ExecutableElement method, DependencyRequest request) { return INDENT + request.key() + " is " + componentMethodRequestVerb(request) + " at\n" + DOUBLE_INDENT + elementToString(method); }
private static TypeName asyncDependencyType(DependencyRequest dependency) { TypeName keyName = TypeName.get(dependency.key().type()); switch (dependency.kind()) { case INSTANCE: return keyName; case PRODUCED: return producedOf(keyName); default: throw new AssertionError(); } }
@Override ImmutableList<CodeBlock> parameterCodeBlocks() { ImmutableList.Builder<CodeBlock> parameterCodeBlocks = ImmutableList.builder(); for (DependencyRequest dependency : binding.explicitDependencies()) { parameterCodeBlocks.add( frameworkTypeUsageStatement( CodeBlock.of("$N", fields.get(dependency.key())), dependency.kind())); } return parameterCodeBlocks.build(); } }
@Override public String toString() { String string = dependencyRequest .requestElement() .map(DaggerElements::elementToString) .orElseGet( () -> "synthetic request for " + dependencyRequest.kind().format(dependencyRequest.key())); return entryPoint ? string + " (entry point)" : string; } }
protected final ImmutableSet<FrameworkDependency> frameworkDependenciesToImplement() { ImmutableSet<Key> alreadyImplementedKeys = componentImplementation.superclassContributionsMade(bindingRequest()).stream() .map(dependency -> dependency.key()) .collect(toImmutableSet()); return binding.frameworkDependencies().stream() .filter(frameworkDependency -> !alreadyImplementedKeys.contains(frameworkDependency.key())) .collect(toImmutableSet()); }
private TypeMirror fieldType(ComponentMethodDescriptor componentMethod) { return types.wrapType(componentMethod.dependencyRequest().get().key().type(), Producer.class); } }
@Override public String visitVariable(VariableElement variable, DependencyRequest request) { TypeMirror requestedType = requestType(request.kind(), request.key().type(), types); return INDENT + formatQualifier(request.key().qualifier()) + requestedType + " is injected at\n" + DOUBLE_INDENT + elementToString(variable); }
private boolean isSingleValue(DependencyRequest dependency) { return graph .contributionBindings() .get(dependency.key()) .contributionBinding() .contributionType() .equals(ContributionType.SET); }
/** * Returns a mapping of {@link DependencyRequest}s to {@link CodeBlock}s that {@linkplain * #frameworkTypeUsageStatement(CodeBlock, RequestKind) use them}. */ static ImmutableMap<DependencyRequest, CodeBlock> frameworkFieldUsages( ImmutableSet<DependencyRequest> dependencies, ImmutableMap<Key, FieldSpec> fields) { return Maps.toMap( dependencies, dep -> frameworkTypeUsageStatement(CodeBlock.of("$N", fields.get(dep.key())), dep.kind())); }
/** * Returns the parameter type for {@code dependency}. If the raw type is not accessible, returns * {@link Object}. */ private static TypeName accessibleType(DependencyRequest dependency) { TypeName typeName = requestTypeName(dependency.kind(), accessibleType(dependency.key().type())); return dependency .requestElement() .map(element -> element.asType().getKind().isPrimitive()) .orElse(false) ? typeName.unbox() : typeName; }
/** * Returns the return type of {@link #methodElement()} as resolved in the {@link * ComponentDescriptor#typeElement() component type}. If there are no type variables in the * return type, this is the equivalent of {@code methodElement().getReturnType()}. */ TypeMirror resolvedReturnType(DaggerTypes types) { checkState(dependencyRequest().isPresent()); TypeMirror returnType = methodElement().getReturnType(); if (returnType.getKind().isPrimitive() || returnType.getKind().equals(VOID)) { return returnType; } return BindingRequest.bindingRequest(dependencyRequest().get()) .requestedType(dependencyRequest().get().key().type(), types); } }
/** * {@link #resolve(Key) Resolves} each of the dependencies of the bindings owned by this * component. */ private void resolveDependencies(ResolvedBindings resolvedBindings) { for (Binding binding : resolvedBindings.bindingsOwnedBy(componentDescriptor)) { for (DependencyRequest dependency : binding.dependencies()) { resolve(dependency.key()); } } }
/** * Creates a {@link BindingRequest} for a normal dependency request for the given {@link Key} and * {@link RequestKind}. */ static BindingRequest bindingRequest(Key key, RequestKind requestKind) { // When there's a request that has a 1:1 mapping to a FrameworkType, the request should be // associated with that FrameworkType as well, because we want to ensure that if a request // comes in for that as a dependency first and as a framework instance later, they resolve to // the same binding expression. // TODO(cgdecker): Instead of doing this, make ComponentBindingExpressions create a // BindingExpression for the RequestKind that simply delegates to the BindingExpression for the // FrameworkType. Then there are separate BindingExpressions, but we don't end up doing weird // things like creating two fields when there should only be one. return new AutoValue_BindingRequest( key, Optional.of(requestKind), FrameworkType.forRequestKind(requestKind)); }
private boolean dependsOnLocalBindingsUncached(Binding binding) { if ((!binding.scope().isPresent() || binding.scope().get().isReusable()) // TODO(beder): Figure out what happens with production subcomponents. && !binding.bindingType().equals(BindingType.PRODUCTION)) { for (DependencyRequest dependency : binding.dependencies()) { if (dependsOnLocalBindings(dependency.key())) { return true; } } } return false; }
/** * Returns {@code true} if the {@code @Binds} binding's scope is stronger than the scope of the * binding it depends on. */ static boolean isBindsScopeStrongerThanDependencyScope( ResolvedBindings resolvedBindings, BindingGraph graph) { ContributionBinding bindsBinding = resolvedBindings.contributionBinding(); checkArgument(bindsBinding.kind().equals(DELEGATE)); Binding dependencyBinding = graph .contributionBindings() .get(getOnlyElement(bindsBinding.dependencies()).key()) .binding(); ScopeKind bindsScope = ScopeKind.get(bindsBinding, graph); ScopeKind dependencyScope = ScopeKind.get(dependencyBinding, graph); return bindsScope.isStrongerScopeThan(dependencyScope); }
private static ComponentRequirement requirement( ExecutableElement method, VariableElement parameter, TypeMirror type, DependencyRequestFactory dependencyRequestFactory) { if (isAnnotationPresent(method, BindsInstance.class)) { DependencyRequest request = dependencyRequestFactory.forRequiredResolvedVariable(parameter, type); return ComponentRequirement.forBoundInstance( request.key(), request.isNullable(), method.getSimpleName().toString()); } return ConfigurationAnnotations.getModuleAnnotation(asTypeElement(type)).isPresent() ? ComponentRequirement.forModule(type) : ComponentRequirement.forDependency(type); } }
private boolean breaksCycle(DependencyEdge edge, BindingGraph graph) { if (edge.dependencyRequest().key().multibindingContributionIdentifier().isPresent()) { return false; } if (breaksCycle(edge.dependencyRequest().key().type(), edge.dependencyRequest().kind())) { return true; } Node target = graph.network().incidentNodes(edge).target(); if (target instanceof dagger.model.Binding && ((dagger.model.Binding) target).kind().equals(BindingKind.OPTIONAL)) { /* For @BindsOptionalOf bindings, unwrap the type inside the Optional. If the unwrapped type * breaks the cycle, so does the optional binding. */ TypeMirror optionalValueType = OptionalType.from(edge.dependencyRequest().key()).valueType(); RequestKind requestKind = getRequestKind(optionalValueType); return breaksCycle(extractKeyType(requestKind, optionalValueType), requestKind); } return false; }
@Override Expression getDependencyExpression(ClassName requestingClass) { Expression delegateExpression = componentBindingExpressions.getDependencyExpression( bindingRequest(getOnlyElement(binding.dependencies()).key(), requestKind), requestingClass); TypeMirror contributedType = binding.contributedType(); switch (requestKind) { case INSTANCE: return instanceRequiresCast(delegateExpression, requestingClass) ? delegateExpression.castTo(contributedType) : delegateExpression; default: return castToRawTypeIfNecessary( delegateExpression, requestType(requestKind, contributedType, types)); } }
private static CodeBlock injectionMethodArgument( DependencyRequest dependency, CodeBlock argument, ClassName generatedTypeName) { TypeMirror keyType = dependency.key().type(); CodeBlock.Builder codeBlock = CodeBlock.builder(); if (!isRawTypeAccessible(keyType, generatedTypeName.packageName()) && isTypeAccessibleFrom(keyType, generatedTypeName.packageName())) { if (!dependency.kind().equals(RequestKind.INSTANCE)) { TypeName usageTypeName = accessibleType(dependency); codeBlock.add("($T) ($T)", usageTypeName, rawTypeName(usageTypeName)); } else if (dependency.requestElement().get().asType().getKind().equals(TypeKind.TYPEVAR)) { codeBlock.add("($T)", keyType); } } return codeBlock.add(argument).build(); }