• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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;
18 
19 import static com.google.common.base.CaseFormat.LOWER_CAMEL;
20 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
21 import static com.google.common.base.Preconditions.checkArgument;
22 import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
23 import static dagger.internal.codegen.DaggerStreams.toImmutableList;
24 import static dagger.internal.codegen.FactoryGenerator.checkNotNullProvidesMethod;
25 import static dagger.internal.codegen.RequestKinds.requestTypeName;
26 import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
27 import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
28 import static dagger.internal.codegen.javapoet.CodeBlocks.toConcatenatedCodeBlock;
29 import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
30 import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
31 import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
32 import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
33 import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
34 import static java.util.stream.Collectors.toList;
35 import static javax.lang.model.element.Modifier.STATIC;
36 import static javax.lang.model.type.TypeKind.VOID;
37 
38 import com.google.auto.common.MoreElements;
39 import com.google.common.collect.ImmutableList;
40 import com.google.common.collect.ImmutableSet;
41 import com.squareup.javapoet.ClassName;
42 import com.squareup.javapoet.CodeBlock;
43 import com.squareup.javapoet.ParameterSpec;
44 import com.squareup.javapoet.TypeName;
45 import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
46 import dagger.internal.codegen.javapoet.Expression;
47 import dagger.internal.codegen.langmodel.DaggerElements;
48 import dagger.internal.codegen.langmodel.DaggerTypes;
49 import dagger.model.DependencyRequest;
50 import dagger.model.RequestKind;
51 import java.util.ArrayList;
52 import java.util.List;
53 import java.util.Optional;
54 import java.util.function.Function;
55 import javax.lang.model.element.ExecutableElement;
56 import javax.lang.model.element.TypeElement;
57 import javax.lang.model.element.VariableElement;
58 import javax.lang.model.type.TypeKind;
59 import javax.lang.model.type.TypeMirror;
60 
61 /** Convenience methods for creating and invoking {@link InjectionMethod}s. */
62 final class InjectionMethods {
63 
64   /**
65    * A method that returns an object from a {@code @Provides} method or an {@code @Inject}ed
66    * constructor. Its parameters match the dependency requests for constructor and members
67    * injection.
68    *
69    * <p>For {@code @Provides} methods named "foo", the method name is "proxyFoo". If the
70    * {@code @Provides} method and its raw parameter types are publicly accessible, no method is
71    * necessary and this method returns {@link Optional#empty()}.
72    *
73    * <p>Example:
74    *
75    * <pre><code>
76    * abstract class FooModule {
77    *   {@literal @Provides} static Foo provideFoo(Bar bar, Baz baz) { … }
78    * }
79    *
80    * public static proxyProvideFoo(Bar bar, Baz baz) { … }
81    * </code></pre>
82    *
83    * <p>For {@code @Inject}ed constructors, the method name is "newFoo". If the constructor and its
84    * raw parameter types are publicly accessible, no method is necessary and this method returns
85    * {@code Optional#empty()}.
86    *
87    * <p>Example:
88    *
89    * <pre><code>
90    * class Foo {
91    *   {@literal @Inject} Foo(Bar bar) {}
92    * }
93    *
94    * public static Foo newFoo(Bar bar) { … }
95    * </code></pre>
96    */
97   static final class ProvisionMethod {
98     /**
99      * Names of methods that are already defined in factories and shouldn't be used for the proxy
100      * method name.
101      */
102     private static final ImmutableSet<String> BANNED_PROXY_NAMES = ImmutableSet.of("get", "create");
103 
104     /**
105      * Returns a method that invokes the binding's {@linkplain ProvisionBinding#bindingElement()
106      * constructor} and injects the instance's members.
107      */
create( ProvisionBinding binding, CompilerOptions compilerOptions, DaggerElements elements)108     static InjectionMethod create(
109         ProvisionBinding binding, CompilerOptions compilerOptions, DaggerElements elements) {
110       ClassName proxyEnclosingClass = generatedClassNameForBinding(binding);
111       ExecutableElement element = MoreElements.asExecutable(binding.bindingElement().get());
112       switch (element.getKind()) {
113         case CONSTRUCTOR:
114           return constructorProxy(proxyEnclosingClass, element, elements);
115         case METHOD:
116           return methodProxy(
117               proxyEnclosingClass,
118               element,
119               methodName(element),
120               ReceiverAccessibility.IGNORE,
121               CheckNotNullPolicy.get(binding, compilerOptions),
122               elements);
123         default:
124           throw new AssertionError(element);
125       }
126     }
127 
128     /**
129      * Invokes the injection method for {@code binding}, with the dependencies transformed with the
130      * {@code dependencyUsage} function.
131      */
132     // TODO(ronshapiro): Further extract a ProvisionMethod type that composes an InjectionMethod, so
133     // users can write ProvisionMethod.create().invoke()
invoke( ProvisionBinding binding, Function<DependencyRequest, CodeBlock> dependencyUsage, ClassName requestingClass, Optional<CodeBlock> moduleReference, CompilerOptions compilerOptions, DaggerElements elements)134     static CodeBlock invoke(
135         ProvisionBinding binding,
136         Function<DependencyRequest, CodeBlock> dependencyUsage,
137         ClassName requestingClass,
138         Optional<CodeBlock> moduleReference,
139         CompilerOptions compilerOptions,
140         DaggerElements elements) {
141       ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
142       moduleReference.ifPresent(arguments::add);
143       arguments.addAll(
144           injectionMethodArguments(
145               binding.provisionDependencies(), dependencyUsage, requestingClass));
146       // TODO(ronshapiro): make InjectionMethods @Injectable
147       return create(binding, compilerOptions, elements).invoke(arguments.build(), requestingClass);
148     }
149 
constructorProxy( ClassName proxyEnclosingClass, ExecutableElement constructor, DaggerElements elements)150     private static InjectionMethod constructorProxy(
151         ClassName proxyEnclosingClass, ExecutableElement constructor, DaggerElements elements) {
152       TypeElement enclosingType = MoreElements.asType(constructor.getEnclosingElement());
153       InjectionMethod.Builder injectionMethod =
154           InjectionMethod.builder(elements)
155               .name(methodName(constructor))
156               .returnType(enclosingType.asType())
157               .enclosingClass(proxyEnclosingClass);
158 
159       injectionMethod
160           .copyTypeParameters(enclosingType)
161           .copyThrows(constructor);
162 
163       CodeBlock arguments = injectionMethod.copyParameters(constructor);
164       injectionMethod
165           .methodBodyBuilder()
166           .addStatement("return new $T($L)", enclosingType, arguments);
167       return injectionMethod.build();
168     }
169 
170     /**
171      * Returns {@code true} if injecting an instance of {@code binding} from {@code callingPackage}
172      * requires the use of an injection method.
173      */
requiresInjectionMethod( ProvisionBinding binding, ImmutableList<Expression> arguments, CompilerOptions compilerOptions, String callingPackage, DaggerTypes types)174     static boolean requiresInjectionMethod(
175         ProvisionBinding binding,
176         ImmutableList<Expression> arguments,
177         CompilerOptions compilerOptions,
178         String callingPackage,
179         DaggerTypes types) {
180       ExecutableElement method = MoreElements.asExecutable(binding.bindingElement().get());
181       return !binding.injectionSites().isEmpty()
182           || binding.shouldCheckForNull(compilerOptions)
183           || !isElementAccessibleFrom(method, callingPackage)
184           || !areParametersAssignable(method, arguments, types)
185           // This check should be removable once we drop support for -source 7
186           || method.getParameters().stream()
187               .map(VariableElement::asType)
188               .anyMatch(type -> !isRawTypeAccessible(type, callingPackage));
189     }
190 
areParametersAssignable( ExecutableElement element, ImmutableList<Expression> arguments, DaggerTypes types)191     private static boolean areParametersAssignable(
192         ExecutableElement element, ImmutableList<Expression> arguments, DaggerTypes types) {
193       List<? extends VariableElement> parameters = element.getParameters();
194       checkArgument(parameters.size() == arguments.size());
195       for (int i = 0; i < parameters.size(); i++) {
196         if (!types.isAssignable(arguments.get(i).type(), parameters.get(i).asType())) {
197           return false;
198         }
199       }
200       return true;
201     }
202 
203     /**
204      * Returns the name of the {@code static} method that wraps {@code method}. For methods that are
205      * associated with {@code @Inject} constructors, the method will also inject all {@link
206      * InjectionSite}s.
207      */
methodName(ExecutableElement method)208     private static String methodName(ExecutableElement method) {
209       switch (method.getKind()) {
210         case CONSTRUCTOR:
211           return "newInstance";
212         case METHOD:
213           String methodName = method.getSimpleName().toString();
214           return BANNED_PROXY_NAMES.contains(methodName)
215               ? "proxy" + LOWER_CAMEL.to(UPPER_CAMEL, methodName)
216               : methodName;
217         default:
218           throw new AssertionError(method);
219       }
220     }
221   }
222 
223   /**
224    * A static method that injects one member of an instance of a type. Its first parameter is an
225    * instance of the type to be injected. The remaining parameters match the dependency requests for
226    * the injection site.
227    *
228    * <p>Example:
229    *
230    * <pre><code>
231    * class Foo {
232    *   {@literal @Inject} Bar bar;
233    *   {@literal @Inject} void setThings(Baz baz, Qux qux) {}
234    * }
235    *
236    * public static injectBar(Foo instance, Bar bar) { … }
237    * public static injectSetThings(Foo instance, Baz baz, Qux qux) { … }
238    * </code></pre>
239    */
240   static final class InjectionSiteMethod {
241     /**
242      * When a type has an inaccessible member from a supertype (e.g. an @Inject field in a parent
243      * that's in a different package), a method in the supertype's package must be generated to give
244      * the subclass's members injector a way to inject it. Each potentially inaccessible member
245      * receives its own method, as the subclass may need to inject them in a different order from
246      * the parent class.
247      */
create(InjectionSite injectionSite, DaggerElements elements)248     static InjectionMethod create(InjectionSite injectionSite, DaggerElements elements) {
249       String methodName = methodName(injectionSite);
250       ClassName proxyEnclosingClass = membersInjectorNameForType(
251           MoreElements.asType(injectionSite.element().getEnclosingElement()));
252       switch (injectionSite.kind()) {
253         case METHOD:
254           return methodProxy(
255               proxyEnclosingClass,
256               MoreElements.asExecutable(injectionSite.element()),
257               methodName,
258               ReceiverAccessibility.CAST_IF_NOT_PUBLIC,
259               CheckNotNullPolicy.IGNORE,
260               elements);
261         case FIELD:
262           return fieldProxy(
263               proxyEnclosingClass,
264               MoreElements.asVariable(injectionSite.element()),
265               methodName,
266               elements);
267       }
268       throw new AssertionError(injectionSite);
269     }
270 
271     /**
272      * Invokes each of the injection methods for {@code injectionSites}, with the dependencies
273      * transformed using the {@code dependencyUsage} function.
274      *
275      * @param instanceType the type of the {@code instance} parameter
276      */
invokeAll( ImmutableSet<InjectionSite> injectionSites, ClassName generatedTypeName, CodeBlock instanceCodeBlock, TypeMirror instanceType, DaggerTypes types, Function<DependencyRequest, CodeBlock> dependencyUsage, DaggerElements elements)277     static CodeBlock invokeAll(
278         ImmutableSet<InjectionSite> injectionSites,
279         ClassName generatedTypeName,
280         CodeBlock instanceCodeBlock,
281         TypeMirror instanceType,
282         DaggerTypes types,
283         Function<DependencyRequest, CodeBlock> dependencyUsage,
284         DaggerElements elements) {
285       return injectionSites
286           .stream()
287           .map(
288               injectionSite -> {
289                 TypeMirror injectSiteType =
290                     types.erasure(injectionSite.element().getEnclosingElement().asType());
291 
292                 // If instance has been declared as Object because it is not accessible from the
293                 // component, but the injectionSite is in a supertype of instanceType that is
294                 // publicly accessible, the InjectionSiteMethod will request the actual type and not
295                 // Object as the first parameter. If so, cast to the supertype which is accessible
296                 // from within generatedTypeName
297                 CodeBlock maybeCastedInstance =
298                     !types.isSubtype(instanceType, injectSiteType)
299                             && isTypeAccessibleFrom(injectSiteType, generatedTypeName.packageName())
300                         ? CodeBlock.of("($T) $L", injectSiteType, instanceCodeBlock)
301                         : instanceCodeBlock;
302                 return CodeBlock.of(
303                     "$L;",
304                     invoke(
305                         injectionSite,
306                         generatedTypeName,
307                         maybeCastedInstance,
308                         dependencyUsage,
309                         elements));
310               })
311           .collect(toConcatenatedCodeBlock());
312     }
313 
314     /**
315      * Invokes the injection method for {@code injectionSite}, with the dependencies transformed
316      * using the {@code dependencyUsage} function.
317      */
invoke( InjectionSite injectionSite, ClassName generatedTypeName, CodeBlock instanceCodeBlock, Function<DependencyRequest, CodeBlock> dependencyUsage, DaggerElements elements)318     private static CodeBlock invoke(
319         InjectionSite injectionSite,
320         ClassName generatedTypeName,
321         CodeBlock instanceCodeBlock,
322         Function<DependencyRequest, CodeBlock> dependencyUsage,
323         DaggerElements elements) {
324       List<CodeBlock> arguments = new ArrayList<>();
325       arguments.add(instanceCodeBlock);
326       if (!injectionSite.dependencies().isEmpty()) {
327         arguments.addAll(
328             injectionSite
329                 .dependencies()
330                 .stream()
331                 .map(dependencyUsage)
332                 .collect(toList()));
333       }
334       return create(injectionSite, elements).invoke(arguments, generatedTypeName);
335     }
336 
337     /*
338      * TODO(ronshapiro): this isn't perfect, as collisions could still exist. Some examples:
339      *
340      *  - @Inject void members() {} will generate a method that conflicts with the instance
341      *    method `injectMembers(T)`
342      *  - Adding the index could conflict with another member:
343      *      @Inject void a(Object o) {}
344      *      @Inject void a(String s) {}
345      *      @Inject void a1(String s) {}
346      *
347      *    Here, Method a(String) will add the suffix "1", which will conflict with the method
348      *    generated for a1(String)
349      *  - Members named "members" or "methods" could also conflict with the {@code static} injection
350      *    method.
351      */
methodName(InjectionSite injectionSite)352     private static String methodName(InjectionSite injectionSite) {
353       int index = injectionSite.indexAmongAtInjectMembersWithSameSimpleName();
354       String indexString = index == 0 ? "" : String.valueOf(index + 1);
355       return "inject"
356           + LOWER_CAMEL.to(UPPER_CAMEL, injectionSite.element().getSimpleName().toString())
357           + indexString;
358     }
359   }
360 
361   /**
362    * Returns an argument list suitable for calling an injection method. Down-casts any arguments
363    * that are {@code Object} (or {@code Provider<Object>}) at the caller but not the method.
364    *
365    * @param dependencies the dependencies used by the method
366    * @param dependencyUsage function to apply on each of {@code dependencies} before casting
367    * @param requestingClass the class calling the injection method
368    */
injectionMethodArguments( ImmutableSet<DependencyRequest> dependencies, Function<DependencyRequest, CodeBlock> dependencyUsage, ClassName requestingClass)369   private static ImmutableList<CodeBlock> injectionMethodArguments(
370       ImmutableSet<DependencyRequest> dependencies,
371       Function<DependencyRequest, CodeBlock> dependencyUsage,
372       ClassName requestingClass) {
373     return dependencies.stream()
374         .map(dep -> injectionMethodArgument(dep, dependencyUsage.apply(dep), requestingClass))
375         .collect(toImmutableList());
376   }
377 
injectionMethodArgument( DependencyRequest dependency, CodeBlock argument, ClassName generatedTypeName)378   private static CodeBlock injectionMethodArgument(
379       DependencyRequest dependency, CodeBlock argument, ClassName generatedTypeName) {
380     TypeMirror keyType = dependency.key().type();
381     CodeBlock.Builder codeBlock = CodeBlock.builder();
382     if (!isRawTypeAccessible(keyType, generatedTypeName.packageName())
383         && isTypeAccessibleFrom(keyType, generatedTypeName.packageName())) {
384       if (!dependency.kind().equals(RequestKind.INSTANCE)) {
385         TypeName usageTypeName = accessibleType(dependency);
386         codeBlock.add("($T) ($T)", usageTypeName, rawTypeName(usageTypeName));
387       } else if (dependency.requestElement().get().asType().getKind().equals(TypeKind.TYPEVAR)) {
388         codeBlock.add("($T)", keyType);
389       }
390     }
391     return codeBlock.add(argument).build();
392   }
393 
394   /**
395    * Returns the parameter type for {@code dependency}. If the raw type is not accessible, returns
396    * {@link Object}.
397    */
accessibleType(DependencyRequest dependency)398   private static TypeName accessibleType(DependencyRequest dependency) {
399     TypeName typeName = requestTypeName(dependency.kind(), accessibleType(dependency.key().type()));
400     return dependency
401             .requestElement()
402             .map(element -> element.asType().getKind().isPrimitive())
403             .orElse(false)
404         ? typeName.unbox()
405         : typeName;
406   }
407 
408   /**
409    * Returns the accessible type for {@code type}. If the raw type is not accessible, returns {@link
410    * Object}.
411    */
accessibleType(TypeMirror type)412   private static TypeName accessibleType(TypeMirror type) {
413     return isRawTypePubliclyAccessible(type) ? TypeName.get(type) : TypeName.OBJECT;
414   }
415 
416   /**
417    * Returns the accessible type for {@code type}. If the raw type is not accessible, returns {@link
418    * Object}.
419    */
420   // TODO(ronshapiro): Can we use DaggerTypes.publiclyAccessibleType in place of this method?
accessibleType(TypeMirror type, DaggerElements elements)421   private static TypeMirror accessibleType(TypeMirror type, DaggerElements elements) {
422     return isRawTypePubliclyAccessible(type)
423         ? type
424         : elements.getTypeElement(Object.class).asType();
425   }
426 
427   private enum ReceiverAccessibility {
428     CAST_IF_NOT_PUBLIC {
429       @Override
parameterType(TypeMirror type, DaggerElements elements)430       TypeMirror parameterType(TypeMirror type, DaggerElements elements) {
431         return accessibleType(type, elements);
432       }
433 
434       @Override
potentiallyCast(CodeBlock instance, TypeMirror instanceType)435       CodeBlock potentiallyCast(CodeBlock instance, TypeMirror instanceType) {
436         return instanceWithPotentialCast(instance, instanceType);
437       }
438     },
439     IGNORE {
440       @Override
parameterType(TypeMirror type, DaggerElements elements)441       TypeMirror parameterType(TypeMirror type, DaggerElements elements) {
442         return type;
443       }
444 
445       @Override
potentiallyCast(CodeBlock instance, TypeMirror instanceType)446       CodeBlock potentiallyCast(CodeBlock instance, TypeMirror instanceType) {
447         return instance;
448       }
449     },
450     ;
451 
parameterType(TypeMirror type, DaggerElements elements)452     abstract TypeMirror parameterType(TypeMirror type, DaggerElements elements);
potentiallyCast(CodeBlock instance, TypeMirror instanceType)453     abstract CodeBlock potentiallyCast(CodeBlock instance, TypeMirror instanceType);
454   }
455 
instanceWithPotentialCast(CodeBlock instance, TypeMirror instanceType)456   private static CodeBlock instanceWithPotentialCast(CodeBlock instance, TypeMirror instanceType) {
457     return isRawTypePubliclyAccessible(instanceType)
458         ? instance
459         : CodeBlock.of("(($T) $L)", instanceType, instance);
460   }
461 
462   private enum CheckNotNullPolicy {
463     IGNORE, CHECK_FOR_NULL;
checkForNull(CodeBlock maybeNull)464     CodeBlock checkForNull(CodeBlock maybeNull) {
465       if (this.equals(IGNORE)) {
466         return maybeNull;
467       }
468       return checkNotNullProvidesMethod(maybeNull);
469     }
470 
get(ProvisionBinding binding, CompilerOptions compilerOptions)471     static CheckNotNullPolicy get(ProvisionBinding binding, CompilerOptions compilerOptions) {
472       return binding.shouldCheckForNull(compilerOptions) ? CHECK_FOR_NULL : IGNORE;
473     }
474   }
475 
methodProxy( ClassName proxyEnclosingClass, ExecutableElement method, String methodName, ReceiverAccessibility receiverAccessibility, CheckNotNullPolicy checkNotNullPolicy, DaggerElements elements)476   private static InjectionMethod methodProxy(
477       ClassName proxyEnclosingClass,
478       ExecutableElement method,
479       String methodName,
480       ReceiverAccessibility receiverAccessibility,
481       CheckNotNullPolicy checkNotNullPolicy,
482       DaggerElements elements) {
483     TypeElement enclosingType = MoreElements.asType(method.getEnclosingElement());
484     InjectionMethod.Builder injectionMethod =
485         InjectionMethod.builder(elements).name(methodName).enclosingClass(proxyEnclosingClass);
486     ParameterSpec instance = null;
487     if (!method.getModifiers().contains(STATIC)) {
488       instance =
489           injectionMethod.addParameter(
490               "instance", receiverAccessibility.parameterType(enclosingType.asType(), elements));
491     }
492 
493     CodeBlock arguments = injectionMethod.copyParameters(method);
494     if (!method.getReturnType().getKind().equals(VOID)) {
495       injectionMethod
496           .returnType(method.getReturnType())
497           .nullableAnnotation(getNullableType(method));
498       injectionMethod.methodBodyBuilder().add("return ");
499     }
500     CodeBlock.Builder proxyInvocation = CodeBlock.builder();
501     if (method.getModifiers().contains(STATIC)) {
502       proxyInvocation.add("$T", rawTypeName(TypeName.get(enclosingType.asType())));
503     } else {
504       injectionMethod.copyTypeParameters(enclosingType);
505       proxyInvocation.add(
506           receiverAccessibility.potentiallyCast(
507               CodeBlock.of("$N", instance), enclosingType.asType()));
508     }
509 
510     injectionMethod
511         .copyTypeParameters(method)
512         .copyThrows(method);
513 
514     proxyInvocation.add(".$N($L)", method.getSimpleName(), arguments);
515     injectionMethod
516         .methodBodyBuilder()
517         .add(checkNotNullPolicy.checkForNull(proxyInvocation.build()))
518         .add(";\n");
519     return injectionMethod.build();
520   }
521 
fieldProxy( ClassName proxyEnclosingClass, VariableElement field, String methodName, DaggerElements elements)522   private static InjectionMethod fieldProxy(
523       ClassName proxyEnclosingClass,
524       VariableElement field,
525       String methodName,
526       DaggerElements elements) {
527     TypeElement enclosingType = MoreElements.asType(field.getEnclosingElement());
528     InjectionMethod.Builder injectionMethod =
529         InjectionMethod.builder(elements).name(methodName).enclosingClass(proxyEnclosingClass);
530     injectionMethod.copyTypeParameters(enclosingType);
531 
532     ParameterSpec instance =
533         injectionMethod.addParameter("instance", accessibleType(enclosingType.asType(), elements));
534     CodeBlock parameter = injectionMethod.copyParameter(field);
535     injectionMethod
536         .methodBodyBuilder()
537         .addStatement(
538             "$L.$L = $L",
539             instanceWithPotentialCast(CodeBlock.of("$N", instance), enclosingType.asType()),
540             field.getSimpleName(),
541             parameter);
542     return injectionMethod.build();
543   }
544 }
545