Skip to content

Commit 962bb33

Browse files
Chang-EricDagger Team
authored and
Dagger Team
committed
Disallow providing or injecting dagger.internal.Provider. This will help with IDEs accidentally suggesting importing dagger.internal.Provider.
Also disallow injections of raw Provider in Maps, for both javax and dagger Providers. This matches the policy of disallowing raw Provider injections in general. RELNOTES=Disallow providing or injecting `dagger.internal.Provider`. Also disallow injections of raw Provider in Maps, for both javax and dagger Providers. PiperOrigin-RevId: 713755026
1 parent 7ca9977 commit 962bb33

File tree

6 files changed

+408
-23
lines changed

6 files changed

+408
-23
lines changed

java/dagger/internal/codegen/base/FrameworkTypes.java

+10
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ public final class FrameworkTypes {
5555
TypeNames.PROVIDER,
5656
TypeNames.JAKARTA_PROVIDER);
5757

58+
// This is a set of types that are disallowed from use, but also aren't framework types in the
59+
// sense that they aren't supported. Like we shouldn't try to unwrap these if we see them, though
60+
// we shouldn't see them at all if they are correctly caught in validation.
61+
private static final ImmutableSet<ClassName> DISALLOWED_TYPES =
62+
ImmutableSet.of(TypeNames.DAGGER_PROVIDER);
63+
5864
/** Returns true if the type represents a producer-related framework type. */
5965
public static boolean isProducerType(XType type) {
6066
return typeIsOneOf(PRODUCTION_TYPES, type);
@@ -73,6 +79,10 @@ public static boolean isMapValueFrameworkType(XType type) {
7379
return typeIsOneOf(MAP_VALUE_FRAMEWORK_TYPES, type);
7480
}
7581

82+
public static boolean isDisallowedType(XType type) {
83+
return typeIsOneOf(DISALLOWED_TYPES, type);
84+
}
85+
7686
private static boolean typeIsOneOf(Set<ClassName> classNames, XType type) {
7787
return classNames.stream().anyMatch(className -> isTypeOf(type, className));
7888
}

java/dagger/internal/codegen/validation/BindingElementValidator.java

+27-5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import dagger.internal.codegen.model.Key;
4343
import dagger.internal.codegen.model.Scope;
4444
import dagger.internal.codegen.xprocessing.XElements;
45+
import dagger.internal.codegen.xprocessing.XTypes;
4546
import java.util.Formatter;
4647
import java.util.HashMap;
4748
import java.util.Map;
@@ -176,6 +177,9 @@ protected void checkAdditionalProperties() {}
176177
protected void checkType() {
177178
switch (ContributionType.fromBindingElement(element)) {
178179
case UNIQUE:
180+
// Basic checks on the types
181+
bindingElementType().ifPresent(this::checkKeyType);
182+
179183
// Validate that a unique binding is not attempting to bind a framework type. This
180184
// validation is only appropriate for unique bindings because multibindings may collect
181185
// framework types. E.g. Set<Provider<Foo>> is perfectly reasonable.
@@ -185,17 +189,22 @@ protected void checkType() {
185189
// This validation is only appropriate for unique bindings because multibindings may
186190
// collect assisted types.
187191
checkAssistedType();
188-
// fall through
192+
193+
// Check for any specifically disallowed types
194+
bindingElementType().ifPresent(this::checkDisallowedType);
195+
break;
189196

190197
case SET:
191198
bindingElementType().ifPresent(this::checkSetValueFrameworkType);
192199
break;
200+
193201
case MAP:
194202
bindingElementType().ifPresent(this::checkMapValueFrameworkType);
195203
break;
196204

197205
case SET_VALUES:
198206
checkSetValuesType();
207+
break;
199208
}
200209
}
201210

@@ -360,24 +369,37 @@ private void checkScopes() {
360369
*/
361370
private void checkFrameworkType() {
362371
if (bindingElementType().filter(FrameworkTypes::isFrameworkType).isPresent()) {
363-
report.addError(bindingElements("must not %s framework types", bindingElementTypeVerb()));
372+
report.addError(bindingElements("must not %s framework types: %s",
373+
bindingElementTypeVerb(), XTypes.toStableString(bindingElementType().get())));
364374
}
365375
}
366376

367377
private void checkSetValueFrameworkType(XType bindingType) {
368378
checkKeyType(bindingType);
369379
if (FrameworkTypes.isSetValueFrameworkType(bindingType)) {
370380
report.addError(bindingElements(
371-
"with @IntoSet/@ElementsIntoSet must not %s framework types",
372-
bindingElementTypeVerb()));
381+
"with @IntoSet/@ElementsIntoSet must not %s framework types: %s",
382+
bindingElementTypeVerb(), XTypes.toStableString(bindingType)));
373383
}
384+
checkDisallowedType(bindingType);
374385
}
375386

376387
private void checkMapValueFrameworkType(XType bindingType) {
377388
checkKeyType(bindingType);
378389
if (FrameworkTypes.isMapValueFrameworkType(bindingType)) {
379390
report.addError(
380-
bindingElements("with @IntoMap must not %s framework types", bindingElementTypeVerb()));
391+
bindingElements("with @IntoMap must not %s framework types: %s",
392+
bindingElementTypeVerb(), XTypes.toStableString(bindingType)));
393+
}
394+
checkDisallowedType(bindingType);
395+
}
396+
397+
private void checkDisallowedType(XType bindingType) {
398+
// TODO(erichang): Consider if we want to go inside complex types to ban
399+
// dagger.internal.Provider as well? E.g. List<dagger.internal.Provider<Foo>>
400+
if (FrameworkTypes.isDisallowedType(bindingType)) {
401+
report.addError(bindingElements("must not %s disallowed types: %s",
402+
bindingElementTypeVerb(), XTypes.toStableString(bindingElementType().get())));
381403
}
382404
}
383405
}

java/dagger/internal/codegen/validation/DependencyRequestValidator.java

+29
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
import static androidx.room.compiler.processing.XElementKt.isField;
2020
import static androidx.room.compiler.processing.XElementKt.isTypeElement;
21+
import static dagger.internal.codegen.base.FrameworkTypes.isDisallowedType;
2122
import static dagger.internal.codegen.base.FrameworkTypes.isFrameworkType;
23+
import static dagger.internal.codegen.base.FrameworkTypes.isMapValueFrameworkType;
2224
import static dagger.internal.codegen.base.RequestKinds.extractKeyType;
2325
import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedFactoryType;
2426
import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedInjectionType;
@@ -40,6 +42,7 @@
4042
import androidx.room.compiler.processing.XVariableElement;
4143
import com.google.common.collect.ImmutableSet;
4244
import dagger.internal.codegen.base.FrameworkTypes;
45+
import dagger.internal.codegen.base.MapType;
4346
import dagger.internal.codegen.base.RequestKinds;
4447
import dagger.internal.codegen.binding.InjectionAnnotations;
4548
import dagger.internal.codegen.javapoet.TypeNames;
@@ -154,6 +157,14 @@ private void checkType() {
154157
// will just be noise.
155158
return;
156159
}
160+
if (isDisallowedType(requestType)) {
161+
report.addError(
162+
"Dagger disallows injecting the type: " + XTypes.toStableString(requestType),
163+
requestElement);
164+
// If the requested type is a disallowed type then skip the remaining checks as they
165+
// will just be noise.
166+
return;
167+
}
157168
XType keyType = extractKeyType(requestType);
158169
if (qualifiers.isEmpty() && isDeclared(keyType)) {
159170
XTypeElement typeElement = keyType.getTypeElement();
@@ -191,6 +202,24 @@ && isAssistedFactoryType(typeElement)) {
191202
requestElement, keyType.getTypeArguments().get(0)));
192203
}
193204
}
205+
if (MapType.isMap(keyType)) {
206+
MapType mapType = MapType.from(keyType);
207+
if (!mapType.isRawType()) {
208+
XType valueType = mapType.valueType();
209+
if (isMapValueFrameworkType(valueType) && isRawParameterizedType(valueType)) {
210+
report.addError(
211+
"Dagger does not support injecting maps of raw framework types: "
212+
+ XTypes.toStableString(requestType),
213+
requestElement);
214+
}
215+
if (isDisallowedType(valueType)) {
216+
report.addError(
217+
"Dagger does not support injecting maps of disallowed types: "
218+
+ XTypes.toStableString(requestType),
219+
requestElement);
220+
}
221+
}
222+
}
194223
}
195224
}
196225

javatests/dagger/internal/codegen/BindsInstanceValidationTest.java

+24
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,28 @@ public void bindsInstanceFrameworkType() {
187187
});
188188
}
189189

190+
@Test
191+
public void bindsInstanceDaggerProvider() {
192+
Source bindsDaggerProvider =
193+
CompilerTests.javaSource(
194+
"test.BindsInstanceFrameworkType",
195+
"package test;",
196+
"",
197+
"import dagger.BindsInstance;",
198+
"import dagger.internal.Provider;",
199+
"import dagger.producers.Producer;",
200+
"",
201+
"interface BindsInstanceFrameworkType {",
202+
" @BindsInstance void bindsProvider(Provider<Object> objectProvider);",
203+
"}");
204+
CompilerTests.daggerCompiler(bindsDaggerProvider)
205+
.withProcessingOptions(compilerMode.processorOptions())
206+
.compile(
207+
subject -> {
208+
subject.hasErrorCount(1);
209+
subject.hasErrorContaining("@BindsInstance parameters must not be disallowed types")
210+
.onSource(bindsDaggerProvider)
211+
.onLine(8);
212+
});
213+
}
190214
}

0 commit comments

Comments
 (0)