예제 #1
0
  public FieldSpec buildRowIdColumnFieldSpec() {
    String name = "_rowid_";
    TypeName columnDefType = ParameterizedTypeName.get(Types.ColumnDef, TypeName.LONG.box());

    CodeBlock initializer;
    initializer =
        CodeBlock.builder()
            .add(
                "new $T($S, $T.class, $L, $L, $L, $L, $L, $L)",
                columnDefType,
                name,
                TypeName.LONG,
                false /* nullable */,
                true /* primary key */,
                false /* autoincrement */,
                true /* autoId */,
                false,
                false)
            .build();

    return FieldSpec.builder(columnDefType, name)
        .addModifiers(publicStaticFinal)
        .initializer(initializer)
        .build();
  }
예제 #2
0
 public FieldSpec createFieldMissing() {
   return FieldSpec.builder(
           terminalTypeName, "MISSING", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
       .addJavadoc("Represents a missing {@code $L}.\n", terminalName)
       .initializer("new $T()", terminalTypeName)
       .build();
 }
예제 #3
0
  public List<FieldSpec> buildFieldSpecs() {
    List<FieldSpec> fieldSpecs = new ArrayList<>();

    List<FieldSpec> columns = new ArrayList<>();

    schema
        .getColumns()
        .forEach(
            columnDef -> {
              FieldSpec fieldSpec = buildColumnFieldSpec(columnDef);
              columns.add(fieldSpec);

              if (columnDef.primaryKey) {
                primaryKey = fieldSpec;
              }
            });

    if (primaryKey == null) {
      // Even if primary key is omitted, "_rowid_" is always available.
      // (WITHOUT ROWID is not supported by Orma)
      primaryKey = buildRowIdColumnFieldSpec();
      fieldSpecs.add(primaryKey);
    }

    fieldSpecs.addAll(columns);

    fieldSpecs.add(
        FieldSpec.builder(Types.String, TABLE_NAME)
            .addModifiers(publicStaticFinal)
            .initializer("$S", schema.tableName)
            .build());

    fieldSpecs.add(
        FieldSpec.builder(Types.ColumnList, COLUMNS)
            .addModifiers(publicStaticFinal)
            .initializer(buildColumnsInitializer(columns))
            .build());

    fieldSpecs.add(
        FieldSpec.builder(Types.StringArray, ESCAPED_COLUMN_NAMES)
            .addModifiers(publicStaticFinal)
            .initializer(buildEscapedColumnNamesInitializer())
            .build());

    return fieldSpecs;
  }
예제 #4
0
 private void addConstructorParameterAndTypeField(
     TypeName typeName,
     String variableName,
     TypeSpec.Builder factoryBuilder,
     MethodSpec.Builder constructorBuilder) {
   FieldSpec field = FieldSpec.builder(typeName, variableName, PRIVATE, FINAL).build();
   factoryBuilder.addField(field);
   ParameterSpec parameter = ParameterSpec.builder(typeName, variableName).build();
   constructorBuilder.addParameter(parameter);
   constructorBuilder.addCode("assert $1N != null; this.$2N = $1N;", parameter, field);
 }
예제 #5
0
 @Override
 public Optional<FieldSpec> parserFieldSpec() {
   TypeName type = property.returnTypeInfo().typeName();
   String name = property.name();
   FieldSpec field =
       FieldSpec.builder(type, name)
           .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
           .initializer("$S", text())
           .build();
   return Optional.of(field);
 }
예제 #6
0
  public FieldSpec buildColumnFieldSpec(ColumnDefinition c) {
    TypeName type = c.getType();

    CodeBlock initializer;
    if (type instanceof ParameterizedTypeName) {
      initializer =
          CodeBlock.builder()
              .add(
                  "new $T($S, $T.getType(new $T<$T>(){}), $L, $L, $L, $L, $L, $L)",
                  c.getColumnDefType(),
                  c.columnName,
                  Types.ParameterizedTypes,
                  Types.TypeHolder,
                  type,
                  c.nullable,
                  c.primaryKey,
                  c.autoincrement,
                  c.autoId,
                  c.indexed,
                  c.unique)
              .build();

    } else {
      initializer =
          CodeBlock.builder()
              .add(
                  "new $T($S, $T.class, $L, $L, $L, $L, $L, $L)",
                  c.getColumnDefType(),
                  c.columnName,
                  type,
                  c.nullable,
                  c.primaryKey,
                  c.autoincrement,
                  c.autoId,
                  c.indexed,
                  c.unique)
              .build();
    }

    return FieldSpec.builder(c.getColumnDefType(), c.name)
        .addModifiers(publicStaticFinal)
        .initializer(initializer)
        .build();
  }
예제 #7
0
  private void addCreatorField(HelperClassBuilder builder) {
    FieldSpec.Builder field =
        FieldSpec.builder(
            ParameterizedTypeName.get(
                ClassName.get(Parcelable.Creator.class), builder.getArgClassName()),
            FIELD_NAME_CREATOR,
            Modifier.PUBLIC,
            Modifier.STATIC,
            Modifier.FINAL);

    field.addAnnotation(
        WeaveBuilder.weave()
            .field()
            .withStatement("%s.%s", fullName(builder.getClassName()), FIELD_NAME_CREATOR)
            .build());
    field.initializer(
        "new $T<$T>() {\n"
            + "\t@$T\n"
            + "\tpublic $T createFromParcel($T in) {\n"
            + "\t\treturn new $T(in);\n"
            + "\t}\n"
            + "\t@$T\n"
            + "\tpublic $T[] newArray(int size) {\n"
            + "\t\treturn new $T[size];\n"
            + "\t}\n"
            + "}",
        Parcelable.Creator.class,
        builder.getArgClassName(),
        Override.class,
        builder.getArgClassName(),
        Parcel.class,
        builder.getArgClassName(),
        Override.class,
        builder.getArgClassName(),
        builder.getArgClassName());

    builder.getBuilder().addField(field.build());
  }
예제 #8
0
 private FieldSpec versionSetField() {
   return FieldSpec.builder(VersionSet.class, "versionSet")
       .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
       .build();
 }
예제 #9
0
 private FieldSpec instanceField() {
   return FieldSpec.builder(exportClassName, "INSTANCE")
       .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
       .initializer("new $T()", exportClassName)
       .build();
 }
  @Override
  public void onWriteDefinition(TypeSpec.Builder typeBuilder) {

    typeBuilder.addField(
        FieldSpec.builder(
                ClassName.get(String.class),
                AUTHORITY,
                Modifier.PRIVATE,
                Modifier.STATIC,
                Modifier.FINAL)
            .initializer("$S", authority)
            .build());

    int code = 0;
    for (TableEndpointDefinition endpointDefinition : endpointDefinitions) {
      for (ContentUriDefinition contentUriDefinition : endpointDefinition.contentUriDefinitions) {
        typeBuilder.addField(
            FieldSpec.builder(
                    TypeName.INT,
                    contentUriDefinition.name,
                    Modifier.PRIVATE,
                    Modifier.STATIC,
                    Modifier.FINAL)
                .initializer(String.valueOf(code))
                .build());
        code++;
      }
    }

    FieldSpec.Builder uriField =
        FieldSpec.builder(
            ClassNames.URI_MATCHER, URI_MATCHER, Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL);

    CodeBlock.Builder initializer =
        CodeBlock.builder()
            .addStatement("new $T($T.NO_MATCH)", ClassNames.URI_MATCHER, ClassNames.URI_MATCHER)
            .add("static {\n");

    for (TableEndpointDefinition endpointDefinition : endpointDefinitions) {
      for (ContentUriDefinition contentUriDefinition : endpointDefinition.contentUriDefinitions) {
        String path;
        if (contentUriDefinition.path != null) {
          path = "\"" + contentUriDefinition.path + "\"";
        } else {
          path =
              CodeBlock.builder()
                  .add(
                      "$L.$L.getPath()",
                      contentUriDefinition.elementClassName,
                      contentUriDefinition.name)
                  .build()
                  .toString();
        }
        initializer.addStatement(
            "$L.addURI($L, $L, $L)", URI_MATCHER, AUTHORITY, path, contentUriDefinition.name);
      }
    }
    initializer.add("}\n");
    typeBuilder.addField(uriField.initializer(initializer.build()).build());

    typeBuilder.addMethod(
        MethodSpec.methodBuilder("getDatabaseName")
            .addAnnotation(Override.class)
            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
            .addStatement("return $S", databaseNameString)
            .returns(ClassName.get(String.class))
            .build());

    MethodSpec.Builder getTypeBuilder =
        MethodSpec.methodBuilder("getType")
            .addAnnotation(Override.class)
            .addParameter(ClassNames.URI, "uri")
            .returns(ClassName.get(String.class))
            .addModifiers(Modifier.PUBLIC, Modifier.FINAL);

    CodeBlock.Builder getTypeCode =
        CodeBlock.builder()
            .addStatement("$T type = null", ClassName.get(String.class))
            .beginControlFlow("switch($L.match(uri))", URI_MATCHER);

    for (TableEndpointDefinition tableEndpointDefinition : endpointDefinitions) {
      for (ContentUriDefinition uriDefinition : tableEndpointDefinition.contentUriDefinitions) {
        getTypeCode
            .beginControlFlow("case $L:", uriDefinition.name)
            .addStatement("type = $S", uriDefinition.type)
            .addStatement("break")
            .endControlFlow();
      }
    }
    getTypeCode
        .beginControlFlow("default:")
        .addStatement(
            "throw new $T($S + $L)",
            ClassName.get(IllegalArgumentException.class),
            "Unknown URI",
            "uri")
        .endControlFlow();
    getTypeCode.endControlFlow();
    getTypeCode.addStatement("return type");

    getTypeBuilder.addCode(getTypeCode.build());
    typeBuilder.addMethod(getTypeBuilder.build());

    for (MethodDefinition method : methods) {
      MethodSpec methodSpec = method.getMethodSpec();
      if (methodSpec != null) {
        typeBuilder.addMethod(methodSpec);
      }
    }
  }
예제 #11
0
 private static FieldSpec createField(String fieldName) {
   return FieldSpec.builder(CLASS_BUNDLE, fieldName, Modifier.FINAL).build();
 }
예제 #12
0
  private DeriveResult<DerivedCodeSpec> functionDispatchImpl(List<DataConstructor> constructors) {

    NameAllocator nameAllocator = nameAllocator(constructors);

    TypeElement f = FlavourImpl.findF(context.flavour(), utils.elements());
    TypeName returnType =
        TypeName.get(
            utils
                .types()
                .getDeclaredType(
                    f,
                    adt.typeConstructor().declaredType(),
                    adt.matchMethod().returnTypeVariable()));

    TypeSpec wrapper =
        TypeSpec.anonymousClassBuilder("")
            .addField(
                FieldSpec.builder(returnType, nameAllocator.get("cata"))
                    .initializer(
                        CodeBlock.builder()
                            .addStatement(
                                "$L -> $L.$L($L)",
                                nameAllocator.get("adt var"),
                                nameAllocator.get("adt var"),
                                adt.matchMethod().element().getSimpleName(),
                                Utils.joinStringsAsArguments(
                                    constructors
                                        .stream()
                                        .map(
                                            constructor ->
                                                constructor
                                                        .arguments()
                                                        .stream()
                                                        .map(DataArguments::getType)
                                                        .noneMatch(
                                                            tm ->
                                                                utils
                                                                    .types()
                                                                    .isSameType(
                                                                        tm,
                                                                        adt.typeConstructor()
                                                                            .declaredType()))
                                                    ? constructor.name()
                                                    : CodeBlock.builder()
                                                        .add(
                                                            "($L) -> $L.$L($L)",
                                                            Utils.asLambdaParametersString(
                                                                constructor.arguments(),
                                                                constructor.typeRestrictions()),
                                                            constructor.name(),
                                                            MapperDerivator.mapperApplyMethod(
                                                                utils, context, constructor),
                                                            Utils.joinStringsAsArguments(
                                                                Stream.concat(
                                                                    constructor
                                                                        .arguments()
                                                                        .stream()
                                                                        .map(
                                                                            argument ->
                                                                                utils
                                                                                        .types()
                                                                                        .isSameType(
                                                                                            argument
                                                                                                .type(),
                                                                                            adt.typeConstructor()
                                                                                                .declaredType())
                                                                                    ? "() -> this."
                                                                                        + nameAllocator
                                                                                            .get(
                                                                                                "cata")
                                                                                        + "."
                                                                                        + FlavourImpl
                                                                                            .functionApplyMethod(
                                                                                                utils,
                                                                                                context)
                                                                                        + "("
                                                                                        + argument
                                                                                            .fieldName()
                                                                                        + ")"
                                                                                    : argument
                                                                                        .fieldName()),
                                                                    constructor
                                                                        .typeRestrictions()
                                                                        .stream()
                                                                        .map(
                                                                            TypeRestriction
                                                                                ::idFunction)
                                                                        .map(
                                                                            DataArgument
                                                                                ::fieldName))))
                                                        .build()
                                                        .toString())))
                            .build())
                    .build())
            .build();

    MethodSpec cataMethod =
        MethodSpec.methodBuilder("cata")
            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
            .addTypeVariables(
                Stream.concat(
                        adt.typeConstructor().typeVariables().stream(),
                        Stream.of(adt.matchMethod().returnTypeVariable()))
                    .map(TypeVariableName::get)
                    .collect(Collectors.toList()))
            .returns(returnType)
            .addParameters(
                constructors
                    .stream()
                    .map(
                        dc ->
                            ParameterSpec.builder(
                                    cataMapperTypeName(dc), MapperDerivator.mapperFieldName(dc))
                                .build())
                    .collect(toList()))
            .addStatement("return $L.$L", wrapper, nameAllocator.get("cata"))
            .build();

    return result(methodSpec(cataMethod));
  }
예제 #13
0
 public FieldSpec createFieldValue() {
   return FieldSpec.builder(String.class, "value", Modifier.PRIVATE, Modifier.FINAL)
       .addAnnotation(AnnotationSpec.builder(Text.class).addMember("required", "false").build())
       .build();
 }
  public static DeriveResult<DerivedCodeSpec> derive(
      AlgebraicDataType adt, DeriveContext deriveContext, DeriveUtils deriveUtils) {

    // skip constructors for enums
    if (adt.typeConstructor().declaredType().asElement().getKind() == ElementKind.ENUM) {
      return result(none());
    }

    TypeConstructor typeConstructor = adt.typeConstructor();
    TypeElement lazyTypeElement =
        FlavourImpl.findF0(deriveContext.flavour(), deriveUtils.elements());
    TypeName lazyArgTypeName =
        TypeName.get(
            deriveUtils.types().getDeclaredType(lazyTypeElement, typeConstructor.declaredType()));
    String lazyArgName = Utils.uncapitalize(typeConstructor.typeElement().getSimpleName());
    TypeName typeName = TypeName.get(typeConstructor.declaredType());

    List<TypeVariableName> typeVariableNames =
        adt.typeConstructor()
            .typeVariables()
            .stream()
            .map(TypeVariableName::get)
            .collect(Collectors.toList());

    String className = "Lazy";
    TypeSpec.Builder typeSpecBuilder =
        TypeSpec.classBuilder(className)
            .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
            .addTypeVariables(typeVariableNames)
            .addField(
                FieldSpec.builder(
                        TypeName.get(Object.class), "lock", Modifier.PRIVATE, Modifier.FINAL)
                    .initializer("new Object()")
                    .build())
            .addField(FieldSpec.builder(lazyArgTypeName, "expression", Modifier.PRIVATE).build())
            .addField(
                FieldSpec.builder(typeName, "evaluation", Modifier.PRIVATE, Modifier.VOLATILE)
                    .build())
            .addMethod(
                MethodSpec.constructorBuilder()
                    .addParameter(ParameterSpec.builder(lazyArgTypeName, lazyArgName).build())
                    .addStatement("this.expression = $N", lazyArgName)
                    .build())
            .addMethod(
                MethodSpec.methodBuilder("eval")
                    .addModifiers(Modifier.PRIVATE)
                    .returns(typeName)
                    .addCode(
                        CodeBlock.builder()
                            .addStatement("$T _evaluation = this.evaluation", typeName)
                            .beginControlFlow("if (_evaluation == null)")
                            .beginControlFlow("synchronized (this.lock)")
                            .addStatement("_evaluation = this.evaluation")
                            .beginControlFlow("if (_evaluation == null)")
                            .addStatement(
                                "this.evaluation = _evaluation = expression.$L()",
                                Utils.getAbstractMethods(lazyTypeElement.getEnclosedElements())
                                    .get(0)
                                    .getSimpleName())
                            .addStatement("this.expression = null")
                            .endControlFlow()
                            .endControlFlow()
                            .endControlFlow()
                            .addStatement("return _evaluation")
                            .build())
                    .build())
            .addMethod(
                Utils.overrideMethodBuilder(adt.matchMethod().element())
                    .addStatement(
                        "return this.eval().$L($L)",
                        adt.matchMethod().element().getSimpleName(),
                        Utils.asArgumentsStringOld(adt.matchMethod().element().getParameters()))
                    .build());

    if (adt.typeConstructor().declaredType().asElement().getKind() == ElementKind.INTERFACE) {
      typeSpecBuilder.addSuperinterface(typeName);
    } else {
      typeSpecBuilder.superclass(typeName);
    }

    typeSpecBuilder.addMethods(
        optionalAsStream(
                findAbstractEquals(typeConstructor.typeElement(), deriveUtils.elements())
                    .map(
                        equals ->
                            deriveUtils
                                .overrideMethodBuilder(equals)
                                .addStatement(
                                    "return this.eval().equals($L)",
                                    equals.getParameters().get(0).getSimpleName())
                                .build()))
            .collect(Collectors.toList()));

    typeSpecBuilder.addMethods(
        optionalAsStream(
                findAbstractHashCode(typeConstructor.typeElement(), deriveUtils.elements())
                    .map(
                        hashCode ->
                            deriveUtils
                                .overrideMethodBuilder(hashCode)
                                .addStatement("return this.eval().hashCode()")
                                .build()))
            .collect(Collectors.toList()));

    typeSpecBuilder.addMethods(
        optionalAsStream(
                findAbstractToString(typeConstructor.typeElement(), deriveUtils.elements())
                    .map(
                        toString ->
                            deriveUtils
                                .overrideMethodBuilder(toString)
                                .addStatement("return this.eval().toString()")
                                .build()))
            .collect(Collectors.toList()));

    return result(
        codeSpec(
            typeSpecBuilder.build(),
            MethodSpec.methodBuilder("lazy")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                .addTypeVariables(
                    typeConstructor
                        .typeVariables()
                        .stream()
                        .map(TypeVariableName::get)
                        .collect(Collectors.toList()))
                .addParameter(lazyArgTypeName, lazyArgName)
                .returns(typeName)
                .addStatement(
                    "return new $L$L($L)",
                    className,
                    typeVariableNames.isEmpty() ? "" : "<>",
                    lazyArgName)
                .build()));
  }
예제 #15
0
  private TypeSpec build(ScopeSpec spec) {
    MethodSpec configureScopeSpec =
        MethodSpec.methodBuilder("configureScope")
            .addModifiers(Modifier.PUBLIC)
            .addAnnotation(Override.class)
            .addParameter(ClassName.get(MortarScope.Builder.class), "builder")
            .addParameter(ClassName.get(MortarScope.class), "parentScope")
            .addCode(
                CodeBlock.builder()
                    .add(
                        "builder.withService($T.SERVICE_NAME, $T.builder()\n",
                        DAGGERSERVICE_CLS,
                        spec.getDaggerComponentTypeName())
                    .indent()
                    .add(
                        ".$L(parentScope.<$T>getService($T.SERVICE_NAME))\n",
                        spec.getDaggerComponentBuilderDependencyMethodName(),
                        spec.getDaggerComponentBuilderDependencyTypeName(),
                        DAGGERSERVICE_CLS)
                    .add(".module(new Module())\n")
                    .add(".build());\n")
                    .unindent()
                    .build())
            .build();

    List<FieldSpec> fieldSpecs = new ArrayList<>();
    for (ParameterSpec parameterSpec : spec.getModuleSpec().getInternalParameters()) {
      fieldSpecs.add(FieldSpec.builder(parameterSpec.type, parameterSpec.name).build());
    }

    MethodSpec.Builder constructorBuilder =
        MethodSpec.constructorBuilder()
            .addModifiers(Modifier.PUBLIC)
            .addAnnotation(AnnotationSpec.builder(ParcelConstructor.class).build())
            .addParameters(spec.getModuleSpec().getInternalParameters());
    for (ParameterSpec parameterSpec : spec.getModuleSpec().getInternalParameters()) {
      constructorBuilder.addStatement("this.$L = $L", parameterSpec.name, parameterSpec.name);
    }

    TypeSpec.Builder builder =
        TypeSpec.classBuilder(spec.getClassName().simpleName())
            .addModifiers(Modifier.PUBLIC)
            .addAnnotation(
                AnnotationSpec.builder(Generated.class)
                    .addMember(
                        "value",
                        "$S",
                        architect.autostack.compiler.AnnotationProcessor.class.getName())
                    .build())
            .addAnnotation(spec.getComponentAnnotationSpec())
            .addAnnotation(
                AnnotationSpec.builder(Parcel.class).addMember("parcelsIndex", "false").build())
            .addType(buildModule(spec.getModuleSpec()))
            .addMethod(constructorBuilder.build())
            .addMethod(configureScopeSpec)
            .addFields(fieldSpecs);

    if (spec.getScopeAnnotationSpec() != null) {
      builder.addAnnotation(spec.getScopeAnnotationSpec());
    }

    if (spec.getPathViewTypeName() != null) {
      builder.addSuperinterface(PATH_CLS);
      MethodSpec createViewSpec =
          MethodSpec.methodBuilder("createView")
              .addModifiers(Modifier.PUBLIC)
              .returns(spec.getPathViewTypeName())
              .addAnnotation(Override.class)
              .addParameter(CONTEXT_CLS, "context")
              .addStatement("return new $T(context)", spec.getPathViewTypeName())
              .build();

      builder.addMethod(createViewSpec);
    } else {
      builder.addSuperinterface(STACKABLE_CLS);
    }

    return builder.build();
  }
예제 #16
0
  @Override
  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, MembersInjectionBinding binding) {
    // Empty members injection bindings are special and don't need source files.
    if (binding.injectionSites().isEmpty()) {
      return Optional.absent();
    }
    // We don't want to write out resolved bindings -- we want to write out the generic version.
    checkState(!binding.unresolved().isPresent());

    ImmutableList<TypeVariableName> typeParameters = bindingTypeElementTypeVariableNames(binding);
    TypeSpec.Builder injectorTypeBuilder =
        TypeSpec.classBuilder(generatedTypeName.simpleName())
            .addModifiers(PUBLIC, FINAL)
            .addTypeVariables(typeParameters);

    TypeName injectedTypeName = TypeName.get(binding.key().type());
    TypeName implementedType = membersInjectorOf(injectedTypeName);
    injectorTypeBuilder.addSuperinterface(implementedType);

    MethodSpec.Builder injectMembersBuilder =
        MethodSpec.methodBuilder("injectMembers")
            .returns(TypeName.VOID)
            .addModifiers(PUBLIC)
            .addAnnotation(Override.class)
            .addParameter(injectedTypeName, "instance")
            .addCode("if (instance == null) {")
            .addStatement(
                "throw new $T($S)",
                NullPointerException.class,
                "Cannot inject members into a null reference")
            .addCode("}");

    ImmutableMap<BindingKey, FrameworkField> fields =
        SourceFiles.generateBindingFieldsForDependencies(dependencyRequestMapper, binding);

    ImmutableMap.Builder<BindingKey, FieldSpec> dependencyFieldsBuilder = ImmutableMap.builder();

    MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder().addModifiers(PUBLIC);

    // We use a static create method so that generated components can avoid having
    // to refer to the generic types of the factory.
    // (Otherwise they may have visibility problems referring to the types.)
    MethodSpec.Builder createMethodBuilder =
        MethodSpec.methodBuilder("create")
            .returns(implementedType)
            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
            .addTypeVariables(typeParameters);

    createMethodBuilder.addCode(
        "return new $T(", javapoetParameterizedGeneratedTypeNameForBinding(binding));
    ImmutableList.Builder<CodeBlock> constructorInvocationParameters = ImmutableList.builder();

    boolean usesRawFrameworkTypes = false;
    UniqueNames fieldNames = new UniqueNames();
    for (Entry<BindingKey, FrameworkField> fieldEntry : fields.entrySet()) {
      BindingKey bindingKey = fieldEntry.getKey();
      FrameworkField bindingField = fieldEntry.getValue();

      // If the dependency type is not visible to this members injector, then use the raw framework
      // type for the field.
      boolean useRawFrameworkType =
          !VISIBLE_TO_MEMBERS_INJECTOR.visit(bindingKey.key().type(), binding);

      String fieldName = fieldNames.getUniqueName(bindingField.name());
      TypeName fieldType =
          useRawFrameworkType
              ? bindingField.javapoetFrameworkType().rawType
              : bindingField.javapoetFrameworkType();
      FieldSpec.Builder fieldBuilder = FieldSpec.builder(fieldType, fieldName, PRIVATE, FINAL);
      ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(fieldType, fieldName);

      // If we're using the raw type for the field, then suppress the injectMembers method's
      // unchecked-type warning and the field's and the constructor and create-method's
      // parameters' raw-type warnings.
      if (useRawFrameworkType) {
        usesRawFrameworkTypes = true;
        fieldBuilder.addAnnotation(SUPPRESS_WARNINGS_RAWTYPES);
        parameterBuilder.addAnnotation(SUPPRESS_WARNINGS_RAWTYPES);
      }
      constructorBuilder.addParameter(parameterBuilder.build());
      createMethodBuilder.addParameter(parameterBuilder.build());

      FieldSpec field = fieldBuilder.build();
      injectorTypeBuilder.addField(field);
      constructorBuilder.addStatement("assert $N != null", field);
      constructorBuilder.addStatement("this.$N = $N", field, field);
      dependencyFieldsBuilder.put(bindingKey, field);
      constructorInvocationParameters.add(CodeBlocks.format("$N", field));
    }
    createMethodBuilder.addCode(CodeBlocks.join(constructorInvocationParameters.build(), ", "));
    createMethodBuilder.addCode(");");

    injectorTypeBuilder.addMethod(constructorBuilder.build());
    injectorTypeBuilder.addMethod(createMethodBuilder.build());

    Set<String> delegateMethods = new HashSet<>();
    ImmutableMap<BindingKey, FieldSpec> dependencyFields = dependencyFieldsBuilder.build();
    List<MethodSpec> injectMethodsForSubclasses = new ArrayList<>();
    for (InjectionSite injectionSite : binding.injectionSites()) {
      injectMembersBuilder.addCode(
          visibleToMembersInjector(binding, injectionSite.element())
              ? directInjectMemberCodeBlock(binding, dependencyFields, injectionSite)
              : delegateInjectMemberCodeBlock(dependencyFields, injectionSite));
      if (!injectionSite.element().getModifiers().contains(PUBLIC)
          && injectionSite.element().getEnclosingElement().equals(binding.bindingElement())
          && delegateMethods.add(injectionSiteDelegateMethodName(injectionSite.element()))) {
        injectMethodsForSubclasses.add(
            injectorMethodForSubclasses(
                dependencyFields,
                typeParameters,
                injectedTypeName,
                injectionSite.element(),
                injectionSite.dependencies()));
      }
    }

    if (usesRawFrameworkTypes) {
      injectMembersBuilder.addAnnotation(SUPPRESS_WARNINGS_UNCHECKED);
    }

    injectorTypeBuilder.addMethod(injectMembersBuilder.build());
    for (MethodSpec methodSpec : injectMethodsForSubclasses) {
      injectorTypeBuilder.addMethod(methodSpec);
    }

    return Optional.of(injectorTypeBuilder);
  }