Create an experimental mode that merges fast init mode and default mode.
RELNOTES=n/a
PiperOrigin-RevId: 423948272
diff --git a/java/dagger/internal/codegen/writing/ComponentImplementation.java b/java/dagger/internal/codegen/writing/ComponentImplementation.java
index 3351a93..e18c6c2 100644
--- a/java/dagger/internal/codegen/writing/ComponentImplementation.java
+++ b/java/dagger/internal/codegen/writing/ComponentImplementation.java
@@ -47,6 +47,7 @@
import androidx.room.compiler.processing.XMessager;
import androidx.room.compiler.processing.XType;
+import androidx.room.compiler.processing.XTypeElement;
import androidx.room.compiler.processing.compat.XConverters;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
@@ -116,14 +117,18 @@
}
/** Compiler Modes. */
- // TODO(wanyingd): add experimental merged mode.
public enum CompilerMode {
DEFAULT,
- FAST_INIT;
+ FAST_INIT,
+ EXPERIMENTAL_MERGED_MODE;
public boolean isFastInit() {
return this == CompilerMode.FAST_INIT;
}
+
+ public boolean isExperimentalMergedMode() {
+ return this == CompilerMode.EXPERIMENTAL_MERGED_MODE;
+ }
}
/** A type of field that this component can contain. */
@@ -310,10 +315,13 @@
this.componentFieldsByImplementation =
createComponentFieldsByImplementation(this, compilerOptions);
this.messager = messager;
+ XTypeElement typeElement = rootComponentImplementation().componentDescriptor().typeElement();
this.compilerMode =
- compilerOptions.fastInit(rootComponentImplementation().componentDescriptor().typeElement())
+ compilerOptions.fastInit(typeElement)
? CompilerMode.FAST_INIT
- : CompilerMode.DEFAULT;
+ : (compilerOptions.experimentalMergedMode(typeElement)
+ ? CompilerMode.EXPERIMENTAL_MERGED_MODE
+ : CompilerMode.DEFAULT);
}
/**
diff --git a/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java b/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java
index 93eab6a..31eecb2 100644
--- a/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java
@@ -36,31 +36,43 @@
private final BindingGraph bindingGraph;
private final ComponentRequirementExpressions componentRequirementExpressions;
private final CompilerOptions compilerOptions;
+ private final boolean isExperimentalMergedMode;
@AssistedInject
ComponentProvisionRequestRepresentation(
@Assisted ProvisionBinding binding,
BindingGraph bindingGraph,
+ ComponentImplementation componentImplementation,
ComponentRequirementExpressions componentRequirementExpressions,
CompilerOptions compilerOptions) {
this.binding = binding;
this.bindingGraph = bindingGraph;
this.componentRequirementExpressions = componentRequirementExpressions;
this.compilerOptions = compilerOptions;
+ this.isExperimentalMergedMode =
+ componentImplementation.compilerMode().isExperimentalMergedMode();
}
@Override
Expression getDependencyExpression(ClassName requestingClass) {
+ CodeBlock componentDependency =
+ isExperimentalMergedMode
+ ? CodeBlock.of("(($T) dependencies[0])", componentRequirement().type().getTypeName())
+ : getComponentRequirementExpression(requestingClass);
CodeBlock invocation =
CodeBlock.of(
"$L.$L()",
- componentRequirementExpressions.getExpression(componentRequirement(), requestingClass),
+ componentDependency,
toJavac(binding.bindingElement().get()).getSimpleName());
return Expression.create(
binding.contributedPrimitiveType().orElse(binding.key().type().xprocessing()),
maybeCheckForNull(binding, compilerOptions, invocation));
}
+ CodeBlock getComponentRequirementExpression(ClassName requestingClass) {
+ return componentRequirementExpressions.getExpression(componentRequirement(), requestingClass);
+ }
+
private ComponentRequirement componentRequirement() {
return bindingGraph
.componentDescriptor()
diff --git a/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java b/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java
index 5ba0515..324cef6 100644
--- a/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java
+++ b/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java
@@ -18,6 +18,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
@@ -65,8 +66,12 @@
membersInjectionBindingRepresentationFactory;
private final ProvisionBindingRepresentation.Factory provisionBindingRepresentationFactory;
private final ProductionBindingRepresentation.Factory productionBindingRepresentationFactory;
+ private final ExperimentalSwitchingProviderDependencyRepresentation.Factory
+ experimentalSwitchingProviderDependencyRepresentationFactory;
private final DaggerTypes types;
private final Map<Binding, BindingRepresentation> representations = new HashMap<>();
+ private final Map<Binding, ExperimentalSwitchingProviderDependencyRepresentation>
+ experimentalSwitchingProviderDependencyRepresentations = new HashMap<>();
@Inject
ComponentRequestRepresentations(
@@ -77,6 +82,8 @@
MembersInjectionBindingRepresentation.Factory membersInjectionBindingRepresentationFactory,
ProvisionBindingRepresentation.Factory provisionBindingRepresentationFactory,
ProductionBindingRepresentation.Factory productionBindingRepresentationFactory,
+ ExperimentalSwitchingProviderDependencyRepresentation.Factory
+ experimentalSwitchingProviderDependencyRepresentationFactory,
DaggerTypes types) {
this.parent = parent;
this.graph = graph;
@@ -85,6 +92,8 @@
membersInjectionBindingRepresentationFactory;
this.provisionBindingRepresentationFactory = provisionBindingRepresentationFactory;
this.productionBindingRepresentationFactory = productionBindingRepresentationFactory;
+ this.experimentalSwitchingProviderDependencyRepresentationFactory =
+ experimentalSwitchingProviderDependencyRepresentationFactory;
this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
this.types = types;
}
@@ -222,4 +231,29 @@
}
throw new AssertionError();
}
+
+ /**
+ * Returns an {@link ExperimentalSwitchingProviderDependencyRepresentation} for the requested
+ * binding to satisfy dependency requests on it from experimental switching providers. Cannot be
+ * used for Members Injection requests.
+ */
+ ExperimentalSwitchingProviderDependencyRepresentation
+ getExperimentalSwitchingProviderDependencyRepresentation(BindingRequest request) {
+ checkState(
+ componentImplementation.compilerMode().isExperimentalMergedMode(),
+ "Compiler mode should be experimentalMergedMode!");
+ Optional<Binding> localBinding = graph.localContributionBinding(request.key());
+
+ if (localBinding.isPresent()) {
+ return reentrantComputeIfAbsent(
+ experimentalSwitchingProviderDependencyRepresentations,
+ localBinding.get(),
+ binding ->
+ experimentalSwitchingProviderDependencyRepresentationFactory.create(
+ (ProvisionBinding) binding));
+ }
+
+ checkArgument(parent.isPresent(), "no expression found for %s", request);
+ return parent.get().getExperimentalSwitchingProviderDependencyRepresentation(request);
+ }
}
diff --git a/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviderDependencyRepresentation.java b/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviderDependencyRepresentation.java
new file mode 100644
index 0000000..817f76b
--- /dev/null
+++ b/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviderDependencyRepresentation.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 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.writing;
+
+import static androidx.room.compiler.processing.compat.XConverters.toJavac;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.assisted.Assisted;
+import dagger.assisted.AssistedFactory;
+import dagger.assisted.AssistedInject;
+import dagger.internal.codegen.base.ContributionType;
+import dagger.internal.codegen.binding.BindsTypeChecker;
+import dagger.internal.codegen.binding.FrameworkType;
+import dagger.internal.codegen.binding.ProvisionBinding;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
+import dagger.spi.model.BindingKind;
+import dagger.spi.model.DependencyRequest;
+import dagger.spi.model.RequestKind;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Returns type casted expressions to satisfy dependency requests from experimental switching
+ * providers.
+ */
+final class ExperimentalSwitchingProviderDependencyRepresentation {
+ private final ProvisionBinding binding;
+ private final ShardImplementation shardImplementation;
+ private final BindsTypeChecker bindsTypeChecker;
+ private final DaggerTypes types;
+ private final DaggerElements elements;
+ private final TypeMirror type;
+
+ @AssistedInject
+ ExperimentalSwitchingProviderDependencyRepresentation(
+ @Assisted ProvisionBinding binding,
+ ComponentImplementation componentImplementation,
+ DaggerTypes types,
+ DaggerElements elements) {
+ this.binding = binding;
+ this.shardImplementation = componentImplementation.shardImplementation(binding);
+ this.types = types;
+ this.elements = elements;
+ this.bindsTypeChecker = new BindsTypeChecker(types, elements);
+ this.type =
+ isDelegateSetValuesBinding()
+ ? types.erasure(elements.getTypeElement(TypeNames.COLLECTION).asType())
+ : toJavac(binding.contributedType());
+ }
+
+ Expression getDependencyExpression(RequestKind requestKind, ProvisionBinding requestingBinding) {
+ int index = findIndexOfDependency(requestingBinding);
+ TypeMirror frameworkType =
+ types.getDeclaredType(elements.getTypeElement(FrameworkType.PROVIDER.frameworkClassName()));
+ Expression expression =
+ FrameworkType.PROVIDER.to(
+ requestKind,
+ Expression.create(
+ frameworkType, CodeBlock.of("(($T) dependencies[$L])", frameworkType, index)),
+ types);
+ if (usesExplicitTypeCast(expression, requestKind)) {
+ return expression.castTo(type);
+ }
+ if (usesErasedTypeCast(requestKind)) {
+ return expression.castTo(types.erasure(type));
+ }
+ return expression;
+ }
+
+ private int findIndexOfDependency(ProvisionBinding requestingBinding) {
+ return requestingBinding.dependencies().stream()
+ .map(DependencyRequest::key)
+ .collect(toImmutableList())
+ .indexOf(binding.key())
+ + (requestingBinding.requiresModuleInstance()
+ && requestingBinding.contributingModule().isPresent()
+ ? 1
+ : 0);
+ }
+
+ private boolean isDelegateSetValuesBinding() {
+ return binding.kind().equals(BindingKind.DELEGATE)
+ && binding.contributionType().equals(ContributionType.SET_VALUES);
+ }
+
+ private boolean usesExplicitTypeCast(Expression expression, RequestKind requestKind) {
+ // If the type is accessible, we can directly cast the expression use the type.
+ return requestKind.equals(RequestKind.INSTANCE)
+ && !bindsTypeChecker.isAssignable(expression.type(), type, binding.contributionType())
+ && isTypeAccessibleFrom(type, shardImplementation.name().packageName());
+ }
+
+ private boolean usesErasedTypeCast(RequestKind requestKind) {
+ // If a type has inaccessible type arguments, then cast to raw type.
+ return requestKind.equals(RequestKind.INSTANCE)
+ && !isTypeAccessibleFrom(type, shardImplementation.name().packageName())
+ && isRawTypeAccessible(type, shardImplementation.name().packageName());
+ }
+
+ @AssistedFactory
+ static interface Factory {
+ ExperimentalSwitchingProviderDependencyRepresentation create(ProvisionBinding binding);
+ }
+}
diff --git a/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviders.java b/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviders.java
new file mode 100644
index 0000000..679be6b
--- /dev/null
+++ b/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviders.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2022 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.writing;
+
+import static androidx.room.compiler.processing.compat.XConverters.toJavac;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getLast;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.codegen.base.UniqueNameSet;
+import dagger.internal.codegen.binding.ProvisionBinding;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
+import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.spi.model.Key;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import javax.inject.Inject;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Keeps track of all provider expression requests for a component.
+ *
+ * <p>The provider expression request will be satisfied by a single generated {@code Provider} class
+ * that can provide instances for all types by switching on an id.
+ */
+@PerComponentImplementation
+final class ExperimentalSwitchingProviders {
+ /**
+ * Each switch size is fixed at 100 cases each and put in its own method. This is to limit the
+ * size of the methods so that we don't reach the "huge" method size limit for Android that will
+ * prevent it from being AOT compiled in some versions of Android (b/77652521). This generally
+ * starts to happen around 1500 cases, but we are choosing 100 to be safe.
+ */
+ // TODO(bcorso): Include a proguard_spec in the Dagger library to prevent inlining these methods?
+ // TODO(ronshapiro): Consider making this configurable via a flag.
+ private static final int MAX_CASES_PER_SWITCH = 100;
+
+ private static final long MAX_CASES_PER_CLASS = MAX_CASES_PER_SWITCH * MAX_CASES_PER_SWITCH;
+ private static final TypeVariableName T = TypeVariableName.get("T");
+
+ /**
+ * Maps a {@link Key} to an instance of a {@link SwitchingProviderBuilder}. Each group of {@code
+ * MAX_CASES_PER_CLASS} keys will share the same instance.
+ */
+ private final Map<Key, SwitchingProviderBuilder> switchingProviderBuilders =
+ new LinkedHashMap<>();
+
+ private final ShardImplementation componentShard;
+ private final DaggerTypes types;
+ private final UniqueNameSet switchingProviderNames = new UniqueNameSet();
+ private final ComponentRequestRepresentations componentRequestRepresentations;
+ private final ComponentImplementation componentImplementation;
+
+ @Inject
+ ExperimentalSwitchingProviders(
+ ComponentImplementation componentImplementation,
+ ComponentRequestRepresentations componentRequestRepresentations,
+ DaggerTypes types) {
+ this.componentShard = checkNotNull(componentImplementation).getComponentShard();
+ this.componentRequestRepresentations = componentRequestRepresentations;
+ this.componentImplementation = componentImplementation;
+ this.types = checkNotNull(types);
+ }
+
+ /** Returns the framework instance creation expression for an inner switching provider class. */
+ FrameworkInstanceCreationExpression newFrameworkInstanceCreationExpression(
+ ProvisionBinding binding, RequestRepresentation unscopedInstanceRequestRepresentation) {
+ return new FrameworkInstanceCreationExpression() {
+ @Override
+ public CodeBlock creationExpression() {
+ return switchingProviderBuilders
+ .computeIfAbsent(binding.key(), key -> getSwitchingProviderBuilder())
+ .getNewInstanceCodeBlock(binding, unscopedInstanceRequestRepresentation);
+ }
+ };
+ }
+
+ private SwitchingProviderBuilder getSwitchingProviderBuilder() {
+ if (switchingProviderBuilders.size() % MAX_CASES_PER_CLASS == 0) {
+ String name = switchingProviderNames.getUniqueName("SwitchingProvider");
+ // TODO(wanyingd): move Switching Providers and injection methods to Shard classes to avoid
+ // exceeding component class constant pool limit.
+ SwitchingProviderBuilder switchingProviderBuilder =
+ new SwitchingProviderBuilder(componentShard.name().nestedClass(name));
+ componentShard.addTypeSupplier(switchingProviderBuilder::build);
+ return switchingProviderBuilder;
+ }
+ return getLast(switchingProviderBuilders.values());
+ }
+
+ // TODO(bcorso): Consider just merging this class with ExperimentalSwitchingProviders.
+ private final class SwitchingProviderBuilder {
+ // Keep the switch cases ordered by switch id. The switch Ids are assigned in pre-order
+ // traversal, but the switch cases are assigned in post-order traversal of the binding graph.
+ private final Map<Integer, CodeBlock> switchCases = new TreeMap<>();
+ private final Map<Key, Integer> switchIds = new HashMap<>();
+ private final ClassName switchingProviderType;
+
+ SwitchingProviderBuilder(ClassName switchingProviderType) {
+ this.switchingProviderType = checkNotNull(switchingProviderType);
+ }
+
+ private CodeBlock getNewInstanceCodeBlock(
+ ProvisionBinding binding, RequestRepresentation unscopedInstanceRequestRepresentation) {
+ Key key = binding.key();
+ if (!switchIds.containsKey(key)) {
+ int switchId = switchIds.size();
+ switchIds.put(key, switchId);
+ switchCases.put(
+ switchId, createSwitchCaseCodeBlock(key, unscopedInstanceRequestRepresentation));
+ }
+
+ ShardImplementation shardImplementation =
+ componentImplementation.shardImplementation(binding);
+ CodeBlock switchingProviderDependencies;
+ switch (binding.kind()) {
+ // TODO(wanyingd): there might be a better way to get component requirement information
+ // without using unscopedInstanceRequestRepresentation.
+ case COMPONENT_PROVISION:
+ switchingProviderDependencies =
+ ((ComponentProvisionRequestRepresentation) unscopedInstanceRequestRepresentation)
+ .getComponentRequirementExpression(shardImplementation.name());
+ break;
+ case SUBCOMPONENT_CREATOR:
+ switchingProviderDependencies =
+ ((SubcomponentCreatorRequestRepresentation) unscopedInstanceRequestRepresentation)
+ .getDependencyExpressionArguments();
+ break;
+ case MULTIBOUND_SET:
+ case MULTIBOUND_MAP:
+ case OPTIONAL:
+ case INJECTION:
+ case PROVISION:
+ case ASSISTED_FACTORY:
+ // Arguments built in the order of module reference, provision dependencies and members
+ // injection dependencies
+ switchingProviderDependencies =
+ componentRequestRepresentations.getCreateMethodArgumentsCodeBlock(
+ binding, shardImplementation.name());
+ break;
+ default:
+ throw new IllegalArgumentException("Unexpected binding kind: " + binding.kind());
+ }
+
+ TypeMirror castedType =
+ shardImplementation.accessibleType(toJavac(binding.contributedType()));
+ return CodeBlock.of(
+ "new $T<$L>($L)",
+ switchingProviderType,
+ // Add the type parameter explicitly when the binding is scoped because Java can't resolve
+ // the type when wrapped. For example, the following will error:
+ // fooProvider = DoubleCheck.provider(new SwitchingProvider<>(1));
+ CodeBlock.of("$T", castedType),
+ switchingProviderDependencies.isEmpty()
+ ? CodeBlock.of("$L", switchIds.get(key))
+ : CodeBlock.of("$L, $L", switchIds.get(key), switchingProviderDependencies));
+ }
+
+ private CodeBlock createSwitchCaseCodeBlock(
+ Key key, RequestRepresentation unscopedInstanceRequestRepresentation) {
+ // TODO(bcorso): Try to delay calling getDependencyExpression() until we are writing out the
+ // SwitchingProvider because calling it here makes FrameworkFieldInitializer think there's a
+ // cycle when initializing ExperimentalSwitchingProviders which adds an unnecessary
+ // DelegateFactory.
+ CodeBlock instanceCodeBlock =
+ unscopedInstanceRequestRepresentation
+ .getDependencyExpression(switchingProviderType)
+ .box(types)
+ .codeBlock();
+
+ return CodeBlock.builder()
+ // TODO(bcorso): Is there something else more useful than the key?
+ .add("case $L: // $L \n", switchIds.get(key), key)
+ .addStatement("return ($T) $L", T, instanceCodeBlock)
+ .build();
+ }
+
+ private TypeSpec build() {
+ TypeSpec.Builder builder =
+ classBuilder(switchingProviderType)
+ .addModifiers(PRIVATE, FINAL, STATIC)
+ .addTypeVariable(T)
+ .addSuperinterface(providerOf(T))
+ .addMethods(getMethods());
+
+ // The SwitchingProvider constructor lists switch id first and then the dependency array.
+ MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
+ builder.addField(TypeName.INT, "id", PRIVATE, FINAL);
+ constructor.addParameter(TypeName.INT, "id").addStatement("this.id = id");
+ // Pass in provision dependencies and members injection dependencies.
+ builder.addField(Object[].class, "dependencies", FINAL, PRIVATE);
+ constructor
+ .addParameter(Object[].class, "dependencies")
+ .addStatement("this.dependencies = dependencies")
+ .varargs(true);
+
+ return builder.addMethod(constructor.build()).build();
+ }
+
+ private ImmutableList<MethodSpec> getMethods() {
+ ImmutableList<CodeBlock> switchCodeBlockPartitions = switchCodeBlockPartitions();
+ if (switchCodeBlockPartitions.size() == 1) {
+ // There are less than MAX_CASES_PER_SWITCH cases, so no need for extra get methods.
+ return ImmutableList.of(
+ methodBuilder("get")
+ .addModifiers(PUBLIC)
+ .addAnnotation(suppressWarnings(UNCHECKED))
+ .addAnnotation(Override.class)
+ .returns(T)
+ .addCode(getOnlyElement(switchCodeBlockPartitions))
+ .build());
+ }
+
+ // This is the main public "get" method that will route to private getter methods.
+ MethodSpec.Builder routerMethod =
+ methodBuilder("get")
+ .addModifiers(PUBLIC)
+ .addAnnotation(Override.class)
+ .returns(T)
+ .beginControlFlow("switch (id / $L)", MAX_CASES_PER_SWITCH);
+
+ ImmutableList.Builder<MethodSpec> getMethods = ImmutableList.builder();
+ for (int i = 0; i < switchCodeBlockPartitions.size(); i++) {
+ MethodSpec method =
+ methodBuilder("get" + i)
+ .addModifiers(PRIVATE)
+ .addAnnotation(suppressWarnings(UNCHECKED))
+ .returns(T)
+ .addCode(switchCodeBlockPartitions.get(i))
+ .build();
+ getMethods.add(method);
+ routerMethod.addStatement("case $L: return $N()", i, method);
+ }
+
+ routerMethod.addStatement("default: throw new $T(id)", AssertionError.class).endControlFlow();
+
+ return getMethods.add(routerMethod.build()).build();
+ }
+
+ private ImmutableList<CodeBlock> switchCodeBlockPartitions() {
+ return Lists.partition(ImmutableList.copyOf(switchCases.values()), MAX_CASES_PER_SWITCH)
+ .stream()
+ .map(
+ partitionCases ->
+ CodeBlock.builder()
+ .beginControlFlow("switch (id)")
+ .add(CodeBlocks.concat(partitionCases))
+ .addStatement("default: throw new $T(id)", AssertionError.class)
+ .endControlFlow()
+ .build())
+ .collect(toImmutableList());
+ }
+ }
+}
diff --git a/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java b/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java
index 94e9df0..8bceddc 100644
--- a/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java
+++ b/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java
@@ -16,18 +16,29 @@
package dagger.internal.codegen.writing;
+import static dagger.spi.model.BindingKind.DELEGATE;
+
import dagger.internal.codegen.binding.ContributionBinding;
import dagger.internal.codegen.writing.ComponentImplementation.CompilerMode;
+import dagger.spi.model.BindingKind;
/** Generation mode for satisfying framework request to Provision Binding. */
enum FrameworkInstanceKind {
SWITCHING_PROVIDER,
+ EXPERIMENTAL_SWITCHING_PROVIDER,
STATIC_FACTORY,
PROVIDER_FIELD;
public static FrameworkInstanceKind from(ContributionBinding binding, CompilerMode compilerMode) {
if (usesSwitchingProvider(binding, compilerMode)) {
- return SWITCHING_PROVIDER;
+ if (compilerMode.isExperimentalMergedMode()) {
+ return EXPERIMENTAL_SWITCHING_PROVIDER;
+ } else if (compilerMode.isFastInit()) {
+ return SWITCHING_PROVIDER;
+ } else {
+ throw new IllegalStateException(
+ "Compiler mode " + compilerMode + " cannot use Switching Provider.");
+ }
} else if (usesStaticFactoryCreation(binding, compilerMode)) {
return STATIC_FACTORY;
} else {
@@ -37,7 +48,12 @@
private static boolean usesSwitchingProvider(
ContributionBinding binding, CompilerMode compilerMode) {
- if (!compilerMode.isFastInit()) {
+ if (!compilerMode.isFastInit() && !compilerMode.isExperimentalMergedMode()) {
+ return false;
+ }
+ // TODO(wanyingd): remove this check once we allow inaccessible types in merged mode.
+ if (compilerMode.isExperimentalMergedMode()
+ && binding.kind().equals(BindingKind.ASSISTED_FACTORY)) {
return false;
}
switch (binding.kind()) {
@@ -83,9 +99,11 @@
case MULTIBOUND_SET:
return true;
case PROVISION:
- return !compilerMode.isFastInit() && !binding.requiresModuleInstance();
+ return !compilerMode.isFastInit()
+ && !compilerMode.isExperimentalMergedMode()
+ && !binding.requiresModuleInstance();
case INJECTION:
- return !compilerMode.isFastInit();
+ return !compilerMode.isFastInit() && !compilerMode.isExperimentalMergedMode();
default:
return false;
}
diff --git a/java/dagger/internal/codegen/writing/MapRequestRepresentation.java b/java/dagger/internal/codegen/writing/MapRequestRepresentation.java
index 295fdd8..92ad920 100644
--- a/java/dagger/internal/codegen/writing/MapRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/MapRequestRepresentation.java
@@ -58,11 +58,13 @@
private final ComponentRequestRepresentations componentRequestRepresentations;
private final DaggerTypes types;
private final DaggerElements elements;
+ private final boolean isExperimentalMergedMode;
@AssistedInject
MapRequestRepresentation(
@Assisted ProvisionBinding binding,
BindingGraph graph,
+ ComponentImplementation componentImplementation,
ComponentRequestRepresentations componentRequestRepresentations,
DaggerTypes types,
DaggerElements elements) {
@@ -74,6 +76,8 @@
this.elements = elements;
this.dependencies =
Maps.toMap(binding.dependencies(), dep -> graph.contributionBinding(dep.key()));
+ this.isExperimentalMergedMode =
+ componentImplementation.compilerMode().isExperimentalMergedMode();
}
@Override
@@ -138,9 +142,15 @@
return CodeBlock.of(
"$L, $L",
getMapKeyExpression(dependencies.get(dependency), requestingClass, elements),
- componentRequestRepresentations
- .getDependencyExpression(bindingRequest(dependency), requestingClass)
- .codeBlock());
+ isExperimentalMergedMode
+ ? componentRequestRepresentations
+ .getExperimentalSwitchingProviderDependencyRepresentation(
+ bindingRequest(dependency))
+ .getDependencyExpression(dependency.kind(), binding)
+ .codeBlock()
+ : componentRequestRepresentations
+ .getDependencyExpression(bindingRequest(dependency), requestingClass)
+ .codeBlock());
}
private Expression collectionsStaticFactoryInvocation(
diff --git a/java/dagger/internal/codegen/writing/MembersInjectionMethods.java b/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
index a3d42e9..ce332f5 100644
--- a/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
+++ b/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
@@ -17,12 +17,15 @@
package dagger.internal.codegen.writing;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.MEMBERS_INJECTION_METHOD;
import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.ClassName;
@@ -52,6 +55,7 @@
@PerComponentImplementation
final class MembersInjectionMethods {
private final Map<Key, Expression> injectMethodExpressions = new LinkedHashMap<>();
+ private final Map<Key, Expression> experimentalInjectMethodExpressions = new LinkedHashMap<>();
private final ComponentImplementation componentImplementation;
private final ComponentRequestRepresentations bindingExpressions;
private final BindingGraph graph;
@@ -86,7 +90,7 @@
: graph.localContributionBinding(key).get();
Expression expression =
reentrantComputeIfAbsent(
- injectMethodExpressions, key, k -> injectMethodExpression(binding));
+ injectMethodExpressions, key, k -> injectMethodExpression(binding, false));
ShardImplementation shardImplementation = componentImplementation.shardImplementation(binding);
return Expression.create(
expression.type(),
@@ -99,8 +103,32 @@
instance));
}
- private Expression injectMethodExpression(Binding binding) {
- ShardImplementation shardImplementation = componentImplementation.shardImplementation(binding);
+ /**
+ * Returns the members injection {@link Expression} for the given {@link Key}, creating it if
+ * necessary.
+ */
+ Expression getInjectExpressionExperimental(
+ ProvisionBinding provisionBinding, CodeBlock instance, ClassName requestingClass) {
+ checkState(
+ componentImplementation.compilerMode().isExperimentalMergedMode(),
+ "Compiler mode should be experimentalMergedMode!");
+ Expression expression =
+ reentrantComputeIfAbsent(
+ experimentalInjectMethodExpressions,
+ provisionBinding.key(),
+ k -> injectMethodExpression(provisionBinding, true));
+ return Expression.create(
+ expression.type(), CodeBlock.of("$L($L, dependencies)", expression.codeBlock(), instance));
+ }
+
+ private Expression injectMethodExpression(Binding binding, boolean useStaticInjectionMethod) {
+ // TODO(wanyingd): move Switching Providers and injection methods to Shard classes to avoid
+ // exceeding component class constant pool limit.
+ // Add to Component Shard so that is can be accessible from Switching Providers.
+ ShardImplementation shardImplementation =
+ useStaticInjectionMethod
+ ? componentImplementation.getComponentShard()
+ : componentImplementation.shardImplementation(binding);
TypeMirror keyType = binding.key().type().java();
TypeMirror membersInjectedType =
isTypeAccessibleFrom(keyType, shardImplementation.name().packageName())
@@ -113,10 +141,16 @@
String methodName = shardImplementation.getUniqueMethodName("inject" + bindingTypeName);
ParameterSpec parameter = ParameterSpec.builder(membersInjectedTypeName, "instance").build();
MethodSpec.Builder methodBuilder =
- methodBuilder(methodName)
- .addModifiers(PRIVATE)
- .returns(membersInjectedTypeName)
- .addParameter(parameter);
+ useStaticInjectionMethod
+ ? methodBuilder(methodName)
+ .addModifiers(PRIVATE, STATIC)
+ .returns(membersInjectedTypeName)
+ .addParameter(parameter)
+ .addParameter(Object[].class, "dependencies")
+ : methodBuilder(methodName)
+ .addModifiers(PRIVATE)
+ .returns(membersInjectedTypeName)
+ .addParameter(parameter);
TypeElement canIgnoreReturnValue =
elements.getTypeElement("com.google.errorprone.annotations.CanIgnoreReturnValue");
if (canIgnoreReturnValue != null) {
@@ -130,8 +164,13 @@
instance,
membersInjectedType,
request ->
- bindingExpressions
- .getDependencyArgumentExpression(request, shardImplementation.name())
+ (useStaticInjectionMethod
+ ? bindingExpressions
+ .getExperimentalSwitchingProviderDependencyRepresentation(
+ bindingRequest(request))
+ .getDependencyExpression(request.kind(), (ProvisionBinding) binding)
+ : bindingExpressions.getDependencyArgumentExpression(
+ request, shardImplementation.name()))
.codeBlock(),
types,
metadataUtil));
diff --git a/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java b/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java
index 6b989e8..caef3a6 100644
--- a/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java
@@ -39,10 +39,12 @@
private final ComponentRequestRepresentations componentRequestRepresentations;
private final DaggerTypes types;
private final SourceVersion sourceVersion;
+ private final boolean isExperimentalMergedMode;
@AssistedInject
OptionalRequestRepresentation(
@Assisted ProvisionBinding binding,
+ ComponentImplementation componentImplementation,
ComponentRequestRepresentations componentRequestRepresentations,
DaggerTypes types,
SourceVersion sourceVersion) {
@@ -50,6 +52,8 @@
this.componentRequestRepresentations = componentRequestRepresentations;
this.types = types;
this.sourceVersion = sourceVersion;
+ this.isExperimentalMergedMode =
+ componentImplementation.compilerMode().isExperimentalMergedMode();
}
@Override
@@ -74,9 +78,15 @@
DependencyRequest dependency = getOnlyElement(binding.dependencies());
CodeBlock dependencyExpression =
- componentRequestRepresentations
- .getDependencyExpression(bindingRequest(dependency), requestingClass)
- .codeBlock();
+ isExperimentalMergedMode
+ ? componentRequestRepresentations
+ .getExperimentalSwitchingProviderDependencyRepresentation(
+ bindingRequest(dependency))
+ .getDependencyExpression(dependency.kind(), binding)
+ .codeBlock()
+ : componentRequestRepresentations
+ .getDependencyExpression(bindingRequest(dependency), requestingClass)
+ .codeBlock();
// If the dependency type is inaccessible, then we have to use Optional.<Object>of(...), or else
// we will get "incompatible types: inference variable has incompatible bounds.
@@ -87,7 +97,7 @@
types.erasure(binding.key().type().java()),
optionalKind.presentObjectExpression(dependencyExpression));
}
-
+
@AssistedFactory
static interface Factory {
OptionalRequestRepresentation create(ProvisionBinding binding);
diff --git a/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java b/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java
index 5cf34e1..0085d32 100644
--- a/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java
+++ b/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java
@@ -61,6 +61,7 @@
FrameworkInstanceSupplier frameworkInstanceSupplier = null;
switch (FrameworkInstanceKind.from(binding, compilerMode)) {
case SWITCHING_PROVIDER:
+ case EXPERIMENTAL_SWITCHING_PROVIDER:
frameworkInstanceSupplier = switchingProviderInstanceSupplierFactory.create(binding);
break;
case STATIC_FACTORY:
@@ -82,6 +83,9 @@
}
private boolean usesDirectInstanceExpression(RequestKind requestKind) {
+ if (compilerMode.isExperimentalMergedMode()) {
+ return false;
+ }
if (requestKind != RequestKind.INSTANCE && requestKind != RequestKind.FUTURE) {
return false;
}
diff --git a/java/dagger/internal/codegen/writing/SetRequestRepresentation.java b/java/dagger/internal/codegen/writing/SetRequestRepresentation.java
index 15491d9..7fec86a 100644
--- a/java/dagger/internal/codegen/writing/SetRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/SetRequestRepresentation.java
@@ -51,11 +51,13 @@
private final ComponentRequestRepresentations componentRequestRepresentations;
private final DaggerTypes types;
private final DaggerElements elements;
+ private final boolean isExperimentalMergedMode;
@AssistedInject
SetRequestRepresentation(
@Assisted ProvisionBinding binding,
BindingGraph graph,
+ ComponentImplementation componentImplementation,
ComponentRequestRepresentations componentRequestRepresentations,
DaggerTypes types,
DaggerElements elements) {
@@ -64,6 +66,8 @@
this.componentRequestRepresentations = componentRequestRepresentations;
this.types = types;
this.elements = elements;
+ this.isExperimentalMergedMode =
+ componentImplementation.compilerMode().isExperimentalMergedMode();
}
@Override
@@ -141,7 +145,15 @@
DependencyRequest dependency, ClassName requestingClass) {
RequestRepresentation bindingExpression =
componentRequestRepresentations.getRequestRepresentation(bindingRequest(dependency));
- CodeBlock expression = bindingExpression.getDependencyExpression(requestingClass).codeBlock();
+ CodeBlock expression =
+ isExperimentalMergedMode
+ ? componentRequestRepresentations
+ .getExperimentalSwitchingProviderDependencyRepresentation(
+ bindingRequest(dependency))
+ .getDependencyExpression(dependency.kind(), binding)
+ .codeBlock()
+ : bindingExpression.getDependencyExpression(requestingClass).codeBlock();
+
// TODO(b/211774331): Type casting should be Set after contributions to Set multibinding are
// limited to be Set.
// Add a cast to "(Collection)" when the contribution is a raw "Provider" type because the
diff --git a/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java b/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java
index c89c6b7..20c6ac6 100644
--- a/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java
@@ -20,6 +20,7 @@
import static com.google.auto.common.MoreElements.asExecutable;
import static com.google.auto.common.MoreElements.asType;
import static com.google.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
@@ -60,6 +61,7 @@
private final SourceVersion sourceVersion;
private final KotlinMetadataUtil metadataUtil;
private final ShardImplementation shardImplementation;
+ private final boolean isExperimentalMergedMode;
@AssistedInject
SimpleMethodRequestRepresentation(
@@ -70,7 +72,8 @@
ComponentRequirementExpressions componentRequirementExpressions,
SourceVersion sourceVersion,
KotlinMetadataUtil metadataUtil,
- ComponentImplementation componentImplementation) {
+ ComponentImplementation componentImplementation,
+ ExperimentalSwitchingProviders switchingProviders) {
this.compilerOptions = compilerOptions;
this.provisionBinding = binding;
this.metadataUtil = metadataUtil;
@@ -83,6 +86,8 @@
this.componentRequirementExpressions = componentRequirementExpressions;
this.sourceVersion = sourceVersion;
this.shardImplementation = componentImplementation.shardImplementation(binding);
+ this.isExperimentalMergedMode =
+ componentImplementation.compilerMode().isExperimentalMergedMode();
}
@Override
@@ -153,8 +158,12 @@
}
private Expression dependencyArgument(DependencyRequest dependency, ClassName requestingClass) {
- return componentRequestRepresentations.getDependencyArgumentExpression(
- dependency, requestingClass);
+ return isExperimentalMergedMode
+ ? componentRequestRepresentations
+ .getExperimentalSwitchingProviderDependencyRepresentation(bindingRequest(dependency))
+ .getDependencyExpression(dependency.kind(), provisionBinding)
+ : componentRequestRepresentations.getDependencyArgumentExpression(
+ dependency, requestingClass);
}
private Expression injectMembers(CodeBlock instance, ClassName requestingClass) {
@@ -172,8 +181,11 @@
instance = CodeBlock.of("($T) ($T) $L", keyType, rawTypeName(keyType), instance);
}
}
- return membersInjectionMethods.getInjectExpression(
- provisionBinding.key(), instance, requestingClass);
+ return isExperimentalMergedMode
+ ? membersInjectionMethods.getInjectExpressionExperimental(
+ provisionBinding, instance, requestingClass)
+ : membersInjectionMethods.getInjectExpression(
+ provisionBinding.key(), instance, requestingClass);
}
private Optional<CodeBlock> moduleReference(ClassName requestingClass) {
@@ -182,7 +194,11 @@
.contributingModule()
.map(XTypeElement::getType)
.map(ComponentRequirement::forModule)
- .map(module -> componentRequirementExpressions.getExpression(module, requestingClass))
+ .map(
+ module ->
+ isExperimentalMergedMode
+ ? CodeBlock.of("(($T) dependencies[0])", module.type().getTypeName())
+ : componentRequirementExpressions.getExpression(module, requestingClass))
: Optional.empty();
}
diff --git a/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java b/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java
index f441532..74ebbad 100644
--- a/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java
@@ -16,26 +16,33 @@
package dagger.internal.codegen.writing;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
import dagger.assisted.Assisted;
import dagger.assisted.AssistedFactory;
import dagger.assisted.AssistedInject;
import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.CodeBlocks;
import dagger.internal.codegen.javapoet.Expression;
import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
+import java.util.ArrayList;
+import java.util.List;
/** A binding expression for a subcomponent creator that just invokes the constructor. */
final class SubcomponentCreatorRequestRepresentation extends RequestRepresentation {
private final ShardImplementation shardImplementation;
private final ContributionBinding binding;
+ private final boolean isExperimentalMergedMode;
@AssistedInject
SubcomponentCreatorRequestRepresentation(
@Assisted ContributionBinding binding, ComponentImplementation componentImplementation) {
this.binding = binding;
this.shardImplementation = componentImplementation.shardImplementation(binding);
+ this.isExperimentalMergedMode =
+ componentImplementation.compilerMode().isExperimentalMergedMode();
}
@Override
@@ -44,9 +51,26 @@
binding.key().type().java(),
"new $T($L)",
shardImplementation.getSubcomponentCreatorSimpleName(binding.key()),
- shardImplementation.componentFieldsByImplementation().values().stream()
- .map(field -> CodeBlock.of("$N", field))
- .collect(CodeBlocks.toParametersCodeBlock()));
+ isExperimentalMergedMode
+ ? getDependenciesExperimental()
+ : shardImplementation.componentFieldsByImplementation().values().stream()
+ .map(field -> CodeBlock.of("$N", field))
+ .collect(toParametersCodeBlock()));
+ }
+
+ private CodeBlock getDependenciesExperimental() {
+ List<CodeBlock> expressions = new ArrayList<>();
+ int index = 0;
+ for (FieldSpec field : shardImplementation.componentFieldsByImplementation().values()) {
+ expressions.add(CodeBlock.of("($T) dependencies[$L]", field.type, index++));
+ }
+ return expressions.stream().collect(toParametersCodeBlock());
+ }
+
+ CodeBlock getDependencyExpressionArguments() {
+ return shardImplementation.componentFieldsByImplementation().values().stream()
+ .map(field -> CodeBlock.of("$N", field))
+ .collect(toParametersCodeBlock());
}
@AssistedFactory
diff --git a/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java b/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java
index 0d81c4a..ef6bd49 100644
--- a/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java
+++ b/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java
@@ -40,13 +40,17 @@
SwitchingProviderInstanceSupplier(
@Assisted ProvisionBinding binding,
SwitchingProviders switchingProviders,
+ ExperimentalSwitchingProviders experimentalSwitchingProviders,
BindingGraph graph,
ComponentImplementation componentImplementation,
UnscopedDirectInstanceRequestRepresentationFactory
unscopedDirectInstanceRequestRepresentationFactory) {
FrameworkInstanceCreationExpression frameworkInstanceCreationExpression =
- switchingProviders.newFrameworkInstanceCreationExpression(
- binding, unscopedDirectInstanceRequestRepresentationFactory.create(binding));
+ componentImplementation.compilerMode().isExperimentalMergedMode()
+ ? experimentalSwitchingProviders.newFrameworkInstanceCreationExpression(
+ binding, unscopedDirectInstanceRequestRepresentationFactory.create(binding))
+ : switchingProviders.newFrameworkInstanceCreationExpression(
+ binding, unscopedDirectInstanceRequestRepresentationFactory.create(binding));
this.frameworkInstanceSupplier =
new FrameworkFieldInitializer(
componentImplementation, binding, scope(binding, frameworkInstanceCreationExpression));