1 /* 2 * Copyright (C) 2021 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.internal.codegen.writing; 18 19 import static dagger.internal.codegen.javapoet.TypeNames.DOUBLE_CHECK; 20 import static dagger.internal.codegen.javapoet.TypeNames.SINGLE_CHECK; 21 22 import com.squareup.javapoet.CodeBlock; 23 import dagger.assisted.Assisted; 24 import dagger.assisted.AssistedFactory; 25 import dagger.assisted.AssistedInject; 26 import dagger.internal.codegen.binding.Binding; 27 import dagger.internal.codegen.binding.BindingGraph; 28 import dagger.internal.codegen.binding.ContributionBinding; 29 import dagger.internal.codegen.model.BindingKind; 30 import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation; 31 import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression; 32 33 /** 34 * An object that initializes a framework-type component field for a binding using instances created 35 * by switching providers. 36 */ 37 final class SwitchingProviderInstanceSupplier implements FrameworkInstanceSupplier { 38 private final FrameworkInstanceSupplier frameworkInstanceSupplier; 39 40 @AssistedInject SwitchingProviderInstanceSupplier( @ssisted ContributionBinding binding, BindingGraph graph, ComponentImplementation componentImplementation, UnscopedDirectInstanceRequestRepresentationFactory unscopedDirectInstanceRequestRepresentationFactory)41 SwitchingProviderInstanceSupplier( 42 @Assisted ContributionBinding binding, 43 BindingGraph graph, 44 ComponentImplementation componentImplementation, 45 UnscopedDirectInstanceRequestRepresentationFactory 46 unscopedDirectInstanceRequestRepresentationFactory) { 47 ShardImplementation shardImplementation = componentImplementation.shardImplementation(binding); 48 FrameworkInstanceCreationExpression frameworkInstanceCreationExpression = 49 shardImplementation 50 .getSwitchingProviders() 51 .newFrameworkInstanceCreationExpression( 52 binding, unscopedDirectInstanceRequestRepresentationFactory.create(binding)); 53 this.frameworkInstanceSupplier = 54 new FrameworkFieldInitializer( 55 componentImplementation, binding, scope(binding, frameworkInstanceCreationExpression)); 56 } 57 58 @Override memberSelect()59 public MemberSelect memberSelect() { 60 return frameworkInstanceSupplier.memberSelect(); 61 } 62 scope( Binding binding, FrameworkInstanceCreationExpression unscoped)63 private FrameworkInstanceCreationExpression scope( 64 Binding binding, FrameworkInstanceCreationExpression unscoped) { 65 // Caching assisted factory provider, so that there won't be new factory created for each 66 // provider.get() call. 67 if (!binding.scope().isPresent() && !binding.kind().equals(BindingKind.ASSISTED_FACTORY)) { 68 return unscoped; 69 } 70 return () -> 71 CodeBlock.of( 72 "$T.provider($L)", 73 binding.scope().isPresent() 74 ? (binding.scope().get().isReusable() 75 ? SINGLE_CHECK 76 : DOUBLE_CHECK) 77 : SINGLE_CHECK, 78 unscoped.creationExpression()); 79 } 80 81 @AssistedFactory 82 static interface Factory { create(ContributionBinding binding)83 SwitchingProviderInstanceSupplier create(ContributionBinding binding); 84 } 85 } 86