1

I am writing an annotation processor in android which generates a java file. I am using JavaPoet library for that.

The purpose of generated file: It should have a list of names of the classes with a particular annotation that my processor supports and provide a public method to get that list.

Now, I've generated the file:

 private final List<String> names;

 GeneratedFile(ArrayList<String> names) {
    this.names = names;
 }

 public List<String> getNames() {
   return names;
}

Now, the problem is: How do I initialize the names field from the processor? The Javapoet api provides an initializer for the field but that only takes a string. In my processor, I've the list of classes that have my supported annotation. I want to populate this field with that list.

WonderCsabo
  • 11,947
  • 13
  • 63
  • 105
Yash
  • 5,225
  • 4
  • 32
  • 65
  • Are you looking for a list of classes that implement your annotation und use this list to initialize the array of the generated class? Is that what you want to do? – El Hoss Apr 09 '17 at 16:23
  • @ElHoss: yes ! exactly ! – Yash Apr 10 '17 at 08:07

1 Answers1

0

As you already know, JavaPoet offers only a string to specify field initialization. To accomplish your task you have to (I will show you some code that is not specific to your problem, but it can be a good example to show you how to do it):

  • Get from your annotation processor the list of classes with your annotation (the code is copied from a my library):

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        model = new PrefsModel();
    
        parseBindType(roundEnv);
    
        // Put all @BindSharedPreferences elements in beanElements
        for (Element item : roundEnv.getElementsAnnotatedWith(BindSharedPreferences.class)) {
            AssertKripton.assertTrueOrInvalidKindForAnnotationException(item.getKind() == ElementKind.CLASS, item, BindSharedPreferences.class);
    
          // store type name somewhere
        }
    
        return true;
    }
    
  • Use this set of TypeName to generate the initial value for you field:

    ...
    Builder sp = FieldSpec.builder(ArrayTypeName.of(String.class), "COLUMNS", Modifier.STATIC, Modifier.PRIVATE,
        Modifier.FINAL);
    String s = "";
    StringBuilder buffer = new StringBuilder();
    for (SQLProperty property : entity.getCollection()) {
      buffer.append(s + "COLUMN_" + 
         columnNameToUpperCaseConverter.convert(property.getName()));
     s = ", ";
    }
    classBuilder.addField(sp.addJavadoc("Columns array\n").initializer("{" + 
      buffer.toString() + "}").build());    
    ...
    

You will find my library on github. In particular, you have to read the class com.abubusoft.kripton.processor.sqlite.BindTableGenerator.

Hope this information can be still useful.

xcesco
  • 4,690
  • 4
  • 34
  • 65