EzDevInfo.com

javapoet

A Java API for generating .java source files.

JavaPoet Add Generic Parameter

How would I generate a method with the following signature?

public <T extends MyClass> void doSomething(T t)

So far I have:

MethodSpec.methodBuilder("doSomething")
        .addModifiers(Modifier.PUBLIC)
        .addTypeVariable(TypeVariableName.get("T", MyClass.class))
        .build()

EDIT This is what the above code is generating (I don't know how to add the parameter):

public <T extends Myclass> void doSomething()

Source: (StackOverflow)

How to add the 'Any Type' questionmark in JavaPoet?

I'm generating code with JavaPoet.

Somewhere in the generated code I want to add a method which has the following argument.

...
    public B someMethod(final AbstractObjectBuilder<Persoon,?> builder) {
       ...
    }
...

So my JavaPoet code should look something like this

    //This does not compile, since I don't know what to put as last argument (questionmark)
ParameterizedTypeName parameterizedTypeName = ParameterizedTypeName.get(AbstractObjectBuilder.class, propertyType,?);

ParameterSpec parameterSpec = ParameterSpec.builder(parameterizedTypeName, name+"Builder", Modifier.FINAL).build();

MethodSpec modMethod = MethodSpec.methodBuilder(name)
                        .addModifiers(Modifier.PUBLIC)
                        .addParameter(parameterSpec)
                        .returns(TypeVariableName.get("B"));
...

Source: (StackOverflow)

Advertisements

Javapoet/JavaWriter append to existing class

I have been experimenting with code generation in an annotation processor.

Consider the following piece of code that adds a constructor that has a statement in it.

private void addRegister(ExecutableElement el) {
    MethodSpec builder = MethodSpec.constructorBuilder().addStatement("$T.register(this)", EventExecutor.class).build();
    TypeSpec spec = TypeSpec.classBuilder(el.getEnclosingElement().getSimpleName().toString()).addOriginatingElement(el).addMethod(builder).build();
    JavaFile file = JavaFile.builder(pEnv.getElementUtils().getPackageOf(el.getEnclosingElement()).getQualifiedName().toString(), spec).build();
    pEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, file.toString());
}

Now, when given an executable element named "bla" in class "Test" the result is this:

class Test {
   Test() {
     EventExecutor.register(this);
   }
}

However this class already exists and I want to append the constructor to the existing code rather than create this fresh class here.

Existing code:

public class Test {

    @Event
    public void bla(TestEvent event) {

    }
}

Can I do this?


Source: (StackOverflow)

Generating annotations using JavaPoet

I am writing a code generator using JavaPoet and need to put an annotation on the class

For example :

package some.package

import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.Entity;
import javax.persistence.Cache

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class SomeClass {
}

My code looks like this:

TypeSpec spec = TypeSpec
  .classBuilder("SomeClass")
  .addAnnotation(Entity.class)
  .addAnnotation(AnnotationSpec.builder(Cache.class)
     .addMember("usage", "$L", CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
     .build())
  .build()

This code generates the class but the resulting code is missing the import statement for the CacheConcurrencyStrategy. How can I generate the code so that all the required code is outputted?


Source: (StackOverflow)

Generating static class initializer using javapoet

Is it possible to generate static initializer using javapoet? See an example of what I'm trying to generate below:

class Foo {
    static int one = 1;
    static int two = 2;
    static int sum;

    static {
        sum = one + two;
    }
}

I tried adding static initializer as a constructor with static modifier:

TypeSpec.classBuilder("Foo")
    .addField(FieldSpec.builder(int.class, "one", Modifier.STATIC).initializer("1").build())
    .addField(FieldSpec.builder(int.class, "two", Modifier.STATIC).initializer("2").build())
    .addField(int.class, "sum", Modifier.STATIC)
    .addMethod(MethodSpec.constructorBuilder()
        .addModifier(Modifier.STATIC)
        .addCode("sum = one + two;")
        .build())
    .build();

But this produces static Foo() { ... } instead of static {...}, which is incorrect syntax.

Is there a way to do it?


Source: (StackOverflow)

Generate self-referencing generic type with JavaPoet

How could I generate the following:

class A extends B<A> {}

I'm stuck at constructing the ParameterizedTypeName to add the super class, I cannot seem to find a way to reference the type of A before it is constructed...

Any pointers? Is this at all possible?


Source: (StackOverflow)

javapoet how to specify current generated instance as return result

I am writing an annotation Processor that generates Agenerated class from an annotated A class. I would like to be able to do something like

AgeneratedInst.getFoo().getBar()...

In order to do so I have to specify the return type wich is the current class I am writing...Is there a way to do so?


Source: (StackOverflow)

Compare JavaPoet ParameterSpec type with Java 8 AnnotatedType

I need to compare the annotated type of a field (or method parameter) with a ParameterSpec instance. The name of the parameter does not matter in this context. The context is somewhat related to the unresolved issue 136.

The following tests are green - but the comparing code uses not so type-safe string conversions. Who can think of a more type-safe approach?

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedType;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.junit.Assert;
import org.junit.Test;

import com.squareup.javapoet.ParameterSpec;

@SuppressWarnings("javadoc")
public class JavaPoetTest {

  @Retention(RetentionPolicy.RUNTIME)
  @Target({ ElementType.PARAMETER, ElementType.TYPE_USE })
  @interface Tag {}

  public static int n;
  public static @Tag int t;

  public static boolean isParameterSpecSameAsAnnotatedType(ParameterSpec parameter, AnnotatedType type) {
    if (!parameter.type.toString().equals(type.getType().getTypeName()))
      return false;

    List<String> specAnnotations = parameter.annotations.stream()
        .map(a -> a.type.toString())
        .collect(Collectors.toList());
    List<String> typeAnnotations = Arrays.asList(type.getAnnotations()).stream()
        .map(a -> a.toString().replace('$', '.').replace("()", "").replace("@", ""))
        .collect(Collectors.toList());

    return specAnnotations.equals(typeAnnotations);
  }

  @Test
  public void testN() throws Exception {
    AnnotatedType annotatedType = JavaPoetTest.class.getField("n").getAnnotatedType();
    ParameterSpec parameterSpec = ParameterSpec.builder(int.class, "name").build();
    Assert.assertTrue(isParameterSpecSameAsAnnotatedType(parameterSpec, annotatedType));
  }

  @Test
  public void testT() throws Exception {
    AnnotatedType annotatedType = JavaPoetTest.class.getField("t").getAnnotatedType();
    ParameterSpec parameterSpec = ParameterSpec.builder(int.class, "name").addAnnotation(Tag.class).build();
    Assert.assertTrue(isParameterSpecSameAsAnnotatedType(parameterSpec, annotatedType));
  }

}

Source: (StackOverflow)

JavaPoet + Android Studio "addModifiers(Modifier) cannot be applied to Modifier"

I've built an annotation processor for my Android project that builds a source file using JavaPoet. However, every time I need to call addModifiers on any JavaPoet object, Android Studio flags it as an error. It will say either

Cannot resolve method addModifiers(javax.lang.model.element.Modifier)

or

addModifiers(javax.lang.model.element.Modifier) cannot be applied to javax.lang.model.element.Modifier

depending on which object I'm calling the method on. I've checked many times that the two fully qualified class names match perfectly. These methods in JavaPoet use VarArgs arguments, but that shouldn't make a difference since I'm compiling to Java 7.

Now here's the kicker: The package compiles just fine, and creates my source file. It only gives me the error in the IDE, not when javac runs. The modifiers are correct in the generated file.

So I guess what I want answered is: How do I get rid of the IDE error, and who do I report this to? Is this a JavaPoet issue, an Android Studio issue, or an IntelliJ issue, or something I haven't considered yet?


Source: (StackOverflow)

Assign an Array to a MethodSpec Statement in JavaPoet?

I use JavaPoet to create Java code. I defined the following array:

String[] testArr = new String[] {"1","2"};

and a constructor:

ArrayTypeName stringArray = ArrayTypeName.of(String.class);

MethodSpec constroctMethod = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
                    .addStatement("$T names", stringArray)
                    .addStatement("names = $N", testArr)
                    .build();

The former does not work. I want to create the statement:

String[] names = new String[] {"1","2"};

How can I assign an Array to a Statement like in the previous line?


Source: (StackOverflow)

Annotation Code Gen with JavaPoet

I am writing a code generator using JavaPoet and need to put an annotation on a class

For example :

@RequestMapping("/api")
public class SomeResource {
   // rest of the code elided
}

I am able to get this far:

TypeSpec spec = TypeSpec
   .classBuilder("SomeResource")
     .addAnnotation(AnnotationSpec.builder(RequestMapping.class)
     // what should go here?
     .build())
   .build();

There is an addMember method in the AnnotationSpec.Builder but that does not appear to do what I want.


Source: (StackOverflow)