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