diff --git a/compiler/src/it/functional-tests/src/main/java/test/multipackage/MultibindsComponent.java b/compiler/src/it/functional-tests/src/main/java/test/multipackage/MultibindsComponent.java new file mode 100644 index 00000000000..b4ef7475b7c --- /dev/null +++ b/compiler/src/it/functional-tests/src/main/java/test/multipackage/MultibindsComponent.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 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 test.multipackage; + +import dagger.Component; +import test.multipackage.a.AMultibindsModule; +import test.multipackage.a.UsesInaccessible; + +/** + * A component that tests the interaction between multiple packages and {@code @Multibinding}s. + * Specifically, we want: + * + * + */ +@Component(modules = {AMultibindsModule.class}) +interface MultibindsComponent { + UsesInaccessible usesInaccessible(); +} diff --git a/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AModule.java b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AModule.java index d3a46dddcb0..7095d98dfe6 100644 --- a/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AModule.java +++ b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AModule.java @@ -25,7 +25,6 @@ import dagger.multibindings.StringKey; import java.util.HashSet; import java.util.Set; -import javax.inject.Inject; @Module public abstract class AModule { @@ -49,9 +48,4 @@ static Set provideSetOfInaccessibles() { @IntoMap @StringKey("inaccessible") abstract Inaccessible provideInaccessibleToMap(Inaccessible inaccessible); - - static class Inaccessible { - @Inject Inaccessible() {} - } - } diff --git a/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AMultibindsModule.java b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AMultibindsModule.java new file mode 100644 index 00000000000..2ddd0d8e371 --- /dev/null +++ b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AMultibindsModule.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 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 test.multipackage.a; + +import dagger.Module; +import dagger.multibindings.Multibinds; +import java.util.Map; +import java.util.Set; + +/** A module that {@code @Multibinds} a set and a map of {@link Inaccessible}. */ +@Module +public abstract class AMultibindsModule { + @Multibinds + abstract Set inaccessibleSet(); + + @Multibinds + abstract Map inaccessibleMap(); +} diff --git a/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/Inaccessible.java b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/Inaccessible.java new file mode 100644 index 00000000000..e20d74f0e09 --- /dev/null +++ b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/Inaccessible.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 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 test.multipackage.a; + +import javax.inject.Inject; + +final class Inaccessible { + @Inject Inaccessible() {} +} \ No newline at end of file diff --git a/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/UsesInaccessible.java b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/UsesInaccessible.java index 19ca465103c..76249291335 100644 --- a/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/UsesInaccessible.java +++ b/compiler/src/it/functional-tests/src/main/java/test/multipackage/a/UsesInaccessible.java @@ -19,7 +19,6 @@ import java.util.Map; import java.util.Set; import javax.inject.Inject; -import test.multipackage.a.AModule.Inaccessible; @SuppressWarnings("unused") public class UsesInaccessible { diff --git a/compiler/src/main/java/dagger/internal/codegen/AbstractComponentWriter.java b/compiler/src/main/java/dagger/internal/codegen/AbstractComponentWriter.java index 4af116af33a..d9923a91f18 100644 --- a/compiler/src/main/java/dagger/internal/codegen/AbstractComponentWriter.java +++ b/compiler/src/main/java/dagger/internal/codegen/AbstractComponentWriter.java @@ -23,6 +23,7 @@ import static com.google.common.collect.Iterables.getOnlyElement; import static com.squareup.javapoet.MethodSpec.constructorBuilder; import static com.squareup.javapoet.MethodSpec.methodBuilder; +import static com.squareup.javapoet.TypeSpec.classBuilder; import static dagger.internal.codegen.AbstractComponentWriter.InitializationState.DELEGATED; import static dagger.internal.codegen.AbstractComponentWriter.InitializationState.INITIALIZED; import static dagger.internal.codegen.AbstractComponentWriter.InitializationState.UNINITIALIZED; @@ -140,13 +141,15 @@ abstract class AbstractComponentWriter { protected final BindingGraph graph; protected final ImmutableMap subcomponentNames; private final Map initializationStates = new HashMap<>(); - protected TypeSpec.Builder component; + protected final TypeSpec.Builder component; private final UniqueNameSet componentFieldNames = new UniqueNameSet(); private final Map memberSelects = new HashMap<>(); private final Map producerFromProviderMemberSelects = new HashMap<>(); private final Map requestFulfillments = Maps.newLinkedHashMap(); protected final MethodSpec.Builder constructor = constructorBuilder().addModifiers(PRIVATE); protected Optional builderName = Optional.absent(); + private final OptionalFactories optionalFactories; + private boolean done; /** * For each component requirement, the builder field. This map is empty for subcomponents that do @@ -162,13 +165,6 @@ abstract class AbstractComponentWriter { */ protected final Map componentContributionFields = Maps.newHashMap(); - /** - * The factory classes that implement {@code Provider>} within the component. If the - * key is {@link Optional#absent()}, the class provides absent values. - */ - private final Map, TypeSpec> optionalFactoryClasses = - new HashMap<>(); - AbstractComponentWriter( Types types, Elements elements, @@ -176,14 +172,30 @@ abstract class AbstractComponentWriter { CompilerOptions compilerOptions, ClassName name, BindingGraph graph, - ImmutableMap subcomponentNames) { + ImmutableMap subcomponentNames, + OptionalFactories optionalFactories) { this.types = types; this.elements = elements; this.keyFactory = keyFactory; this.compilerOptions = compilerOptions; + this.component = classBuilder(name); this.name = name; this.graph = graph; this.subcomponentNames = subcomponentNames; + this.optionalFactories = optionalFactories; + } + + protected AbstractComponentWriter( + AbstractComponentWriter parent, ClassName name, BindingGraph graph) { + this( + parent.types, + parent.elements, + parent.keyFactory, + parent.compilerOptions, + name, + graph, + parent.subcomponentNames, + parent.optionalFactories); } protected final TypeElement componentDefinitionType() { @@ -267,8 +279,8 @@ private void setInitializationState(BindingKey bindingKey, InitializationState s * component must be regenerated, use a new instance. */ final TypeSpec.Builder write() { - checkState(component == null, "ComponentWriter has already been generated."); - component = createComponentClass(); + checkState(!done, "ComponentWriter has already been generated."); + decorateComponent(); addBuilder(); addFactoryMethods(); addFrameworkFields(); @@ -276,13 +288,18 @@ final TypeSpec.Builder write() { implementInterfaceMethods(); addSubcomponents(); component.addMethod(constructor.build()); + if (graph.componentDescriptor().kind().isTopLevel()) { + optionalFactories.addMembers(component); + } + done = true; return component; } /** - * Creates the component implementation class. + * Adds Javadoc, modifiers, supertypes, and annotations to the component implementation class + * declaration. */ - protected abstract TypeSpec.Builder createComponentClass(); + protected abstract void decorateComponent(); /** * Adds a builder type. @@ -737,7 +754,7 @@ private void implementInterfaceMethods() { } } - public MethodSpec.Builder methodSpecForComponentMethod( + private MethodSpec.Builder methodSpecForComponentMethod( ExecutableElement method, ExecutableType methodType) { String methodName = method.getSimpleName().toString(); MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(methodName); @@ -1279,41 +1296,16 @@ private CodeBlock initializeFactoryForSyntheticOptionalBinding(ContributionBindi } if (binding.dependencies().isEmpty()) { - return CodeBlock.of( - "$N.instance()", optionalFactoryClass(Optional.absent())); + return optionalFactories.absentOptionalProvider(); } else { TypeMirror valueType = OptionalType.from(binding.key()).valueType(); - DependencyRequest.Kind optionalValueKind = - DependencyRequest.extractKindAndType(valueType).kind(); + DependencyRequest.Kind valueKind = DependencyRequest.extractKindAndType(valueType).kind(); FrameworkDependency frameworkDependency = getOnlyElement(frameworkDependenciesForBinding(binding)); CodeBlock dependencyArgument = getDependencyArgument(frameworkDependency).getExpressionFor(name); - return CodeBlock.of( - "$N.of($L)", optionalFactoryClass(Optional.of(optionalValueKind)), dependencyArgument); - } - } - - /** - * Returns the nested class that implements {@code Provider>} for optional bindings. - * Adds it to the root component if it hasn't already been added. - * - *

If {@code optionalValueKind} is absent, returns a {@link Provider} class that returns {@link - * Optional#absent()}. - * - *

If {@code optionalValueKind} is present, returns a {@link Provider} class where {@code T} - * represents dependency requests of that kind. - */ - protected TypeSpec optionalFactoryClass(Optional optionalValueKind) { - if (!optionalFactoryClasses.containsKey(optionalValueKind)) { - TypeSpec factory = - optionalValueKind.isPresent() - ? OptionalFactoryClasses.presentFactoryClass(optionalValueKind.get()) - : OptionalFactoryClasses.ABSENT_FACTORY_CLASS; - component.addType(factory); - optionalFactoryClasses.put(optionalValueKind, factory); + return optionalFactories.presentOptionalProvider(valueKind, dependencyArgument); } - return optionalFactoryClasses.get(optionalValueKind); } private static String simpleVariableName(TypeElement typeElement) { diff --git a/compiler/src/main/java/dagger/internal/codegen/ComponentWriter.java b/compiler/src/main/java/dagger/internal/codegen/ComponentWriter.java index 1237643facf..f14e3ffbce5 100644 --- a/compiler/src/main/java/dagger/internal/codegen/ComponentWriter.java +++ b/compiler/src/main/java/dagger/internal/codegen/ComponentWriter.java @@ -64,7 +64,8 @@ final class ComponentWriter extends AbstractComponentWriter { compilerOptions, name, graph, - new UniqueSubcomponentNamesGenerator(graph).generate()); + new UniqueSubcomponentNamesGenerator(graph).generate(), + new OptionalFactories()); } /** @@ -142,10 +143,9 @@ private static ImmutableListMultimap qualifiedNames } @Override - protected TypeSpec.Builder createComponentClass() { - TypeSpec.Builder component = classBuilder(name).addModifiers(PUBLIC, FINAL); + protected void decorateComponent() { + component.addModifiers(PUBLIC, FINAL); addSupertype(component, componentDefinitionType()); - return component; } @Override diff --git a/compiler/src/main/java/dagger/internal/codegen/MemberSelect.java b/compiler/src/main/java/dagger/internal/codegen/MemberSelect.java index 99f5ead6fa9..015ad36bf6b 100644 --- a/compiler/src/main/java/dagger/internal/codegen/MemberSelect.java +++ b/compiler/src/main/java/dagger/internal/codegen/MemberSelect.java @@ -26,7 +26,6 @@ import static dagger.internal.codegen.TypeNames.MAP_PROVIDER_FACTORY; import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTOR; import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTORS; -import static dagger.internal.codegen.TypeNames.SET; import com.google.common.collect.ImmutableList; import com.squareup.javapoet.ClassName; @@ -144,10 +143,7 @@ static MemberSelect emptyFrameworkMapFactory( */ static MemberSelect emptySetProvider(ClassName setFactoryType, SetType setType) { return new ParameterizedStaticMethod( - setFactoryType, - ImmutableList.of(setType.elementType()), - CodeBlock.of("empty()"), - SET); + setFactoryType, ImmutableList.of(setType.elementType()), CodeBlock.of("empty()"), FACTORY); } private static final class ParameterizedStaticMethod extends MemberSelect { diff --git a/compiler/src/main/java/dagger/internal/codegen/OptionalFactoryClasses.java b/compiler/src/main/java/dagger/internal/codegen/OptionalFactories.java similarity index 54% rename from compiler/src/main/java/dagger/internal/codegen/OptionalFactoryClasses.java rename to compiler/src/main/java/dagger/internal/codegen/OptionalFactories.java index c40a725607c..d9a03cbc2cc 100644 --- a/compiler/src/main/java/dagger/internal/codegen/OptionalFactoryClasses.java +++ b/compiler/src/main/java/dagger/internal/codegen/OptionalFactories.java @@ -23,6 +23,7 @@ import static com.squareup.javapoet.TypeSpec.classBuilder; import static dagger.internal.codegen.AnnotationSpecs.SUPPRESS_WARNINGS_RAWTYPES; import static dagger.internal.codegen.AnnotationSpecs.SUPPRESS_WARNINGS_UNCHECKED; +import static dagger.internal.codegen.TypeNames.PROVIDER; import static dagger.internal.codegen.TypeNames.lazyOf; import static dagger.internal.codegen.TypeNames.optionalOf; import static dagger.internal.codegen.TypeNames.providerOf; @@ -34,59 +35,87 @@ import com.google.common.base.Optional; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeVariableName; +import dagger.internal.InstanceFactory; import dagger.internal.Preconditions; +import java.util.EnumMap; +import java.util.Map; import javax.inject.Provider; -/** Factory class specifications for optional bindings. */ +/** + * The nested class and static methods required by the component to implement optional bindings. + */ // TODO(dpb): Name classes correctly if a component uses both Guava and JDK Optional. -final class OptionalFactoryClasses { +final class OptionalFactories { /** - * The class specification for a {@link Provider>} that always returns {@code + * A field specification for a {@link Provider>} that always returns {@code * Optional.absent()}. */ - static final TypeSpec ABSENT_FACTORY_CLASS = absentFactoryClass(); + private static final FieldSpec ABSENT_OPTIONAL_PROVIDER_FIELD = + FieldSpec.builder(PROVIDER, "ABSENT_OPTIONAL_PROVIDER", PRIVATE, STATIC, FINAL) + .addAnnotation(SUPPRESS_WARNINGS_RAWTYPES) + .initializer("$T.create($T.absent())", InstanceFactory.class, Optional.class) + .addJavadoc( + "A {@link $T} that returns {@code $T.absent()}.", Provider.class, Optional.class) + .build(); - private static TypeSpec absentFactoryClass() { - String className = "AbsentOptionalFactory"; - TypeVariableName typeVariable = TypeVariableName.get("T"); - - return classBuilder(className) - .addTypeVariable(typeVariable) - .addModifiers(PRIVATE, STATIC, FINAL) - .addSuperinterface(providerOf(optionalOf(typeVariable))) - .addJavadoc("A {@link $T} that returns {$T.absent()}.", Provider.class, Optional.class) - .addField(FieldSpec.builder(Provider.class, "INSTANCE", PRIVATE, STATIC, FINAL) - .addAnnotation(SUPPRESS_WARNINGS_RAWTYPES) - .initializer("new $L()", className) - .build()) - .addMethod( - methodBuilder("instance") - .addModifiers(PRIVATE, STATIC) - .addTypeVariable(typeVariable) - .returns(providerOf(optionalOf(typeVariable))) - .addCode("$L // safe covariant cast\n", SUPPRESS_WARNINGS_UNCHECKED) - .addCode("$1T provider = ($1T) INSTANCE;", providerOf(optionalOf(typeVariable))) - .addCode("return provider;") - .build()) - .addMethod( - methodBuilder("get") - .addAnnotation(Override.class) - .addModifiers(PUBLIC) - .returns(optionalOf(typeVariable)) - .addCode("return $T.absent();", Optional.class) - .build()) - .build(); + /** + * A method specification for a {@link Provider>} that always returns {@code + * Optional.absent()}. + */ + private static final MethodSpec ABSENT_OPTIONAL_PROVIDER_METHOD = + methodBuilder("absentOptionalProvider") + .addModifiers(PRIVATE, STATIC) + .addTypeVariable(TypeVariableName.get("T")) + .returns(providerOf(optionalOf(TypeVariableName.get("T")))) + .addJavadoc( + "Returns a {@link $T} that returns {@code $T.absent()}.", + Provider.class, + Optional.class) + .addCode("$L // safe covariant cast\n", SUPPRESS_WARNINGS_UNCHECKED) + .addCode( + "$1T provider = ($1T) $2N;", + providerOf(optionalOf(TypeVariableName.get("T"))), + ABSENT_OPTIONAL_PROVIDER_FIELD) + .addCode("return provider;") + .build(); + + /** + * The factory classes that implement present optional bindings for a given kind of dependency + * request within the component. + */ + private final Map presentFactoryClasses = + new EnumMap<>(DependencyRequest.Kind.class); + + /** + * If the component contains any absent optional bindings, this will be the member select for a + * static method that returns a Provider> that always returns {@link + * Optional#absent()}. + */ + private Optional absentOptionalProviderMethod = Optional.absent(); + + /** + * Returns an expression that calls a static method that returns a {@code Provider>} + * for absent optional bindings. + */ + CodeBlock absentOptionalProvider() { + if (!absentOptionalProviderMethod.isPresent()) { + absentOptionalProviderMethod = + Optional.of(CodeBlock.of("$N()", ABSENT_OPTIONAL_PROVIDER_METHOD)); + } + return absentOptionalProviderMethod.get(); } /** - * Returns the class specification for a {@link Provider} that returns a present value. The class - * is generic in {@code T}. + * Returns an expression for an instance of a nested class that implements {@code + * Provider>} for a present optional binding, where {@code T} represents dependency + * requests of that kind. * *

    *
  • If {@code optionalRequestKind} is {@link DependencyRequest.Kind#INSTANCE}, the class @@ -100,23 +129,44 @@ private static TypeSpec absentFactoryClass() { *
* *

Production requests are not yet supported. + * + * @param delegateProvider an expression for a {@link Provider} of the underlying type + */ + CodeBlock presentOptionalProvider(DependencyRequest.Kind valueKind, CodeBlock delegateProvider) { + if (!presentFactoryClasses.containsKey(valueKind)) { + presentFactoryClasses.put(valueKind, createPresentFactoryClass(valueKind)); + } + return CodeBlock.of("$N.of($L)", presentFactoryClasses.get(valueKind), delegateProvider); + } + + /** + * Adds classes and methods required by previous calls to {@link #absentOptionalProvider()} and + * {@link #presentOptionalProvider(DependencyRequest.Kind, CodeBlock)} to the top-level {@code + * component}. */ - static TypeSpec presentFactoryClass(DependencyRequest.Kind optionalValueKind) { + void addMembers(TypeSpec.Builder component) { + if (absentOptionalProviderMethod.isPresent()) { + component.addField(ABSENT_OPTIONAL_PROVIDER_FIELD).addMethod(ABSENT_OPTIONAL_PROVIDER_METHOD); + } + for (TypeSpec presentFactoryClass : presentFactoryClasses.values()) { + component.addType(presentFactoryClass); + } + } + + private TypeSpec createPresentFactoryClass(DependencyRequest.Kind valueKind) { String factoryClassName = String.format( - "PresentOptional%sFactory", - UPPER_UNDERSCORE.to(UPPER_CAMEL, optionalValueKind.toString())); - + "PresentOptional%sFactory", UPPER_UNDERSCORE.to(UPPER_CAMEL, valueKind.toString())); + TypeVariableName typeVariable = TypeVariableName.get("T"); - + FieldSpec providerField = FieldSpec.builder(providerOf(typeVariable), "provider", PRIVATE, FINAL).build(); - + ParameterSpec providerParameter = ParameterSpec.builder(providerOf(typeVariable), "provider").build(); - - ParameterizedTypeName optionalType = optionalType(optionalValueKind, typeVariable); - + + ParameterizedTypeName optionalType = optionalType(valueKind, typeVariable); return classBuilder(factoryClassName) .addTypeVariable(typeVariable) .addModifiers(PRIVATE, STATIC, FINAL) @@ -144,7 +194,7 @@ static TypeSpec presentFactoryClass(DependencyRequest.Kind optionalValueKind) { .addCode( "return $T.of($L);", Optional.class, - FrameworkType.PROVIDER.to(optionalValueKind, CodeBlock.of("$N", providerField))) + FrameworkType.PROVIDER.to(valueKind, CodeBlock.of("$N", providerField))) .build()) .addMethod( methodBuilder("of") @@ -157,7 +207,7 @@ static TypeSpec presentFactoryClass(DependencyRequest.Kind optionalValueKind) { .build(); } - private static ParameterizedTypeName optionalType( + private ParameterizedTypeName optionalType( DependencyRequest.Kind optionalValueKind, TypeName valueType) { switch (optionalValueKind) { case INSTANCE: diff --git a/compiler/src/main/java/dagger/internal/codegen/SubcomponentWriter.java b/compiler/src/main/java/dagger/internal/codegen/SubcomponentWriter.java index 5c87ab4d562..7a4b7155f51 100644 --- a/compiler/src/main/java/dagger/internal/codegen/SubcomponentWriter.java +++ b/compiler/src/main/java/dagger/internal/codegen/SubcomponentWriter.java @@ -42,7 +42,6 @@ import com.squareup.javapoet.TypeSpec; import dagger.internal.Preconditions; import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor; -import dagger.internal.codegen.DependencyRequest.Kind; import java.util.List; import java.util.Set; import javax.lang.model.element.TypeElement; @@ -67,14 +66,7 @@ final class SubcomponentWriter extends AbstractComponentWriter { AbstractComponentWriter parent, Optional subcomponentFactoryMethod, BindingGraph subgraph) { - super( - parent.types, - parent.elements, - parent.keyFactory, - parent.compilerOptions, - subcomponentName(parent, subgraph), - subgraph, - parent.subcomponentNames); + super(parent, subcomponentName(parent, subgraph), subgraph); this.parent = parent; this.subcomponentFactoryMethod = subcomponentFactoryMethod; } @@ -118,16 +110,14 @@ private ExecutableType resolvedSubcomponentFactoryMethod() { } @Override - protected TypeSpec.Builder createComponentClass() { - TypeSpec.Builder subcomponent = classBuilder(name).addModifiers(PRIVATE, FINAL); - + protected void decorateComponent() { + component.addModifiers(PRIVATE, FINAL); addSupertype( - subcomponent, + component, MoreTypes.asTypeElement( graph.componentDescriptor().builderSpec().isPresent() ? graph.componentDescriptor().builderSpec().get().componentType() : resolvedSubcomponentFactoryMethod().getReturnType())); - return subcomponent; } @Override @@ -173,11 +163,6 @@ protected void addFactoryMethods() { parent.component.addMethod(componentMethod.build()); } - @Override - protected TypeSpec optionalFactoryClass(Optional optionalValueKind) { - return parent.optionalFactoryClass(optionalValueKind); - } - private void writeSubcomponentWithoutBuilder( MethodSpec.Builder componentMethod, ExecutableType resolvedMethod) { ImmutableList.Builder subcomponentConstructorParameters = ImmutableList.builder(); diff --git a/compiler/src/main/java/dagger/internal/codegen/TypeSpecs.java b/compiler/src/main/java/dagger/internal/codegen/TypeSpecs.java index 3adcde1ad6d..92f1a3aedc5 100644 --- a/compiler/src/main/java/dagger/internal/codegen/TypeSpecs.java +++ b/compiler/src/main/java/dagger/internal/codegen/TypeSpecs.java @@ -16,6 +16,7 @@ package dagger.internal.codegen; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeSpec; import javax.lang.model.element.TypeElement; @@ -28,15 +29,16 @@ final class TypeSpecs { /** * If {@code supertype} is a class, adds it as a superclass for {@code typeBuilder}; if it is an * interface, adds it as a superinterface. + * + * @return {@code typeBuilder} */ - static void addSupertype(TypeSpec.Builder typeBuilder, TypeElement supertype) { + @CanIgnoreReturnValue + static TypeSpec.Builder addSupertype(TypeSpec.Builder typeBuilder, TypeElement supertype) { switch (supertype.getKind()) { case CLASS: - typeBuilder.superclass(ClassName.get(supertype)); - break; + return typeBuilder.superclass(ClassName.get(supertype)); case INTERFACE: - typeBuilder.addSuperinterface(ClassName.get(supertype)); - break; + return typeBuilder.addSuperinterface(ClassName.get(supertype)); default: throw new AssertionError(supertype + " is neither a class nor an interface."); }