Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate Builder Code #850

Open
38leinaD opened this issue Aug 11, 2021 · 2 comments
Open

Generate Builder Code #850

38leinaD opened this issue Aug 11, 2021 · 2 comments

Comments

@38leinaD
Copy link

38leinaD commented Aug 11, 2021

Hi,
This is more a question than an issue. I am trying to understand JavaPoet. I am able to understand how to generate simple code fragements, but what i would like to do is generated nested code structures based on builder objects. So, i would like to generate code like this:

new MyTransactionBuilder()
  .amount(MyAmountBuilder()
    .value(100)
    .currency("EUR")
    .build())
  .build()

I am having a hard time to understand how i can generate code that includes methods-calls which again need to have a code fragment as the methods parameter. I.e. amount method call needs a code fragment again.
If someone could give me a push in the right direction, that would be great. Feels, like I am missing some basic understanding somewhere.

Thanks,
Daniel

@snturk
Copy link

snturk commented Jan 28, 2023

In Javapoet, these type of codes called "CodeBlock" also a class named CodeBlock is used to generate this type of calls.

First, you need to define your custom classes like MyTransactionBuilder and MyAmountBuilder by their package name.

Then, other calls can be added by a simple addStatement method. In this method, you can reference custom types that you defined before. For example, $T is a placeholder for typename.

For more detailed information, you should look at CodeBlock docs

The short answer to your question, the below code does the job 👍

        ClassName myTransactionBuilderClazz = ClassName.get("com.yourpackage", "MyTransactionBuilder");
        ClassName myAmountBuilderClazz = ClassName.get("com.yourpackage", "MyAmountBuilder");
        
        CodeBlock block = CodeBlock.builder()
            .addStatement("return new $T()", myTransactionBuilderClazz)
            .indent()
            .addStatement(".amount(new $T().value(100).currency(\"EUR\").build())", myAmountBuilderClazz)
            .addStatement(".build()")
            .unindent()
            .build();

@Slava96
Copy link

Slava96 commented Nov 1, 2023

Sorry, it's not working because addStatement appends ; on each line. For builder pattern-based code it's a problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants