• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 com.google.common.base.Preconditions.checkNotNull;
20 import static dagger.internal.codegen.writing.DelegateRequestRepresentation.instanceRequiresCast;
21 
22 import androidx.room.compiler.processing.XProcessingEnv;
23 import com.squareup.javapoet.ClassName;
24 import dagger.assisted.Assisted;
25 import dagger.assisted.AssistedFactory;
26 import dagger.assisted.AssistedInject;
27 import dagger.internal.codegen.base.MapType;
28 import dagger.internal.codegen.binding.BindsTypeChecker;
29 import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
30 import dagger.internal.codegen.binding.ContributionBinding;
31 import dagger.internal.codegen.binding.DelegateBinding;
32 import dagger.internal.codegen.binding.FrameworkType;
33 import dagger.internal.codegen.javapoet.Expression;
34 import dagger.internal.codegen.javapoet.TypeNames;
35 import dagger.internal.codegen.model.BindingKind;
36 import dagger.internal.codegen.model.RequestKind;
37 
38 /** A binding expression that depends on a framework instance. */
39 final class DerivedFromFrameworkInstanceRequestRepresentation extends RequestRepresentation {
40   private final ContributionBinding binding;
41   private final RequestRepresentation frameworkRequestRepresentation;
42   private final RequestKind requestKind;
43   private final FrameworkType frameworkType;
44   private final XProcessingEnv processingEnv;
45   private final BindsTypeChecker bindsTypeChecker;
46 
47   @AssistedInject
DerivedFromFrameworkInstanceRequestRepresentation( @ssisted ContributionBinding binding, @Assisted RequestRepresentation frameworkRequestRepresentation, @Assisted RequestKind requestKind, @Assisted FrameworkType frameworkType, XProcessingEnv processingEnv, BindsTypeChecker bindsTypeChecker)48   DerivedFromFrameworkInstanceRequestRepresentation(
49       @Assisted ContributionBinding binding,
50       @Assisted RequestRepresentation frameworkRequestRepresentation,
51       @Assisted RequestKind requestKind,
52       @Assisted FrameworkType frameworkType,
53       XProcessingEnv processingEnv,
54       BindsTypeChecker bindsTypeChecker) {
55     this.binding = binding;
56     this.frameworkRequestRepresentation = checkNotNull(frameworkRequestRepresentation);
57     this.requestKind = requestKind;
58     this.frameworkType = checkNotNull(frameworkType);
59     this.processingEnv = processingEnv;
60     this.bindsTypeChecker = bindsTypeChecker;
61   }
62 
63   @Override
getDependencyExpression(ClassName requestingClass)64   Expression getDependencyExpression(ClassName requestingClass) {
65     return getDependencyExpressionFromFrameworkExpression(
66         frameworkRequestRepresentation.getDependencyExpression(requestingClass),
67         requestingClass);
68   }
69 
70   @Override
getDependencyExpressionForComponentMethod( ComponentMethodDescriptor componentMethod, ComponentImplementation component)71   Expression getDependencyExpressionForComponentMethod(
72       ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
73     return getDependencyExpressionFromFrameworkExpression(
74         frameworkRequestRepresentation
75             .getDependencyExpressionForComponentMethod(componentMethod, component),
76         component.name());
77   }
78 
getDependencyExpressionFromFrameworkExpression( Expression frameworkExpression, ClassName requestingClass)79   private Expression getDependencyExpressionFromFrameworkExpression(
80       Expression frameworkExpression, ClassName requestingClass) {
81     Expression expression =
82         frameworkType.to(
83             requestKind,
84             frameworkExpression,
85             processingEnv);
86 
87     // If it is a map type we need to do a raw type cast. This is because a user requested field
88     // type like dagger.internal.Provider<Map<K, javax.inject.Provider<V>>> isn't always assignable
89     // from something like dagger.internal.Provider<Map<K, dagger.internal.Provider<V>>> just due
90     // to variance issues.
91     if (MapType.isMapOfProvider(binding.contributedType())) {
92       return castMapOfProvider(expression, binding);
93     }
94 
95     return requiresTypeCast(expression, requestingClass)
96         ? expression.castTo(binding.contributedType())
97         : expression;
98   }
99 
castMapOfProvider(Expression expression, ContributionBinding binding)100   private Expression castMapOfProvider(Expression expression, ContributionBinding binding) {
101     switch (requestKind) {
102       case INSTANCE:
103         return expression.castTo(binding.contributedType());
104       case PROVIDER:
105       case PROVIDER_OF_LAZY:
106         return expression.castTo(processingEnv.requireType(TypeNames.DAGGER_PROVIDER).getRawType());
107       case LAZY:
108         return expression.castTo(processingEnv.requireType(TypeNames.LAZY).getRawType());
109       case PRODUCER:
110       case FUTURE:
111         return expression.castTo(processingEnv.requireType(TypeNames.PRODUCER).getRawType());
112       case PRODUCED:
113         return expression.castTo(processingEnv.requireType(TypeNames.PRODUCED).getRawType());
114 
115       case MEMBERS_INJECTION: // fall through
116     }
117     throw new IllegalStateException("Unexpected request kind: " + requestKind);
118   }
119 
requiresTypeCast(Expression expression, ClassName requestingClass)120   private boolean requiresTypeCast(Expression expression, ClassName requestingClass) {
121     return binding.kind().equals(BindingKind.DELEGATE)
122         && requestKind.equals(RequestKind.INSTANCE)
123         && instanceRequiresCast(
124             (DelegateBinding) binding, expression, requestingClass, bindsTypeChecker);
125   }
126 
127   @AssistedFactory
128   static interface Factory {
create( ContributionBinding binding, RequestRepresentation frameworkRequestRepresentation, RequestKind requestKind, FrameworkType frameworkType)129     DerivedFromFrameworkInstanceRequestRepresentation create(
130         ContributionBinding binding,
131         RequestRepresentation frameworkRequestRepresentation,
132         RequestKind requestKind,
133         FrameworkType frameworkType);
134   }
135 }
136