record-builder icon indicating copy to clipboard operation
record-builder copied to clipboard

support naked main / empty packages

Open maxandersen opened this issue 1 year ago • 1 comments

in Java 23 preview you can have naked main that cannot be in a package; when I try use record-builder it seem to use classname as package:

demo.java:

import io.soabase.recordbuilder.core.RecordBuilder;

@RecordBuilder
record Person(String name, int age) {};

void main() {
    System.out.println("Hello, World");
}

result in a generated class named: demoPersonBuilder.java and inside it generates:

 @Generated("io.soabase.recordbuilder.core.RecordBuilder")
    public static demo.Person Person(String name, int age) {
        return new demo.Person(name, age);
    }

which does not work/compile.

maxandersen avatar Oct 24 '24 14:10 maxandersen

btw. this works:

package mypackage;

import io.soabase.recordbuilder.core.RecordBuilder;

@RecordBuilder
record Person(String name, int age) {};

class demo {
void main() {

    var fb = PersonBuilder.builder().name("John").age(20).build();
    System.out.println("Hello, World: " + fb);
}

}

but would love to remove all the unnecessary parts :)

maxandersen avatar Oct 24 '24 15:10 maxandersen

might actually be a limitation of naked mains.

Funny enough I can put the records in a separate file and it works.

maxandersen avatar Oct 24 '24 22:10 maxandersen

after investigating this again in https://github.com/orgs/jbangdev/discussions/2242 i'm back to saying this is a limit in soabase.

soabase always generates with a package name using the source file name which is not correct/proper.

https://gist.github.com/maxandersen/1e1cc817125ce3abd09525133398d59b has sample using soabase and avaje - soabase fails with out package, avaje works.

maxandersen avatar Oct 24 '25 22:10 maxandersen

correction - avaje also have issues. but does not make it different that would be nice the generated code is not assuming it has a package.

maxandersen avatar Oct 24 '25 23:10 maxandersen

I don't know jbang at all. I did some quick tests and I'm probably not using it correctly. However, I created this record in the RecordBuilder source and it generates correctly. I believe whatever you're seeing is a jbang bug.

import io.soabase.recordbuilder.core.RecordBuilder;

import java.time.Instant;

@RecordBuilder
public record NoPackage(Instant dateTime) implements NoPackageBuilder.With {
}

Randgalt avatar Oct 25 '25 09:10 Randgalt

You know that in recent versions of the JDK annotation processing has to be manually enabled right? It's not automatic anymore.

Randgalt avatar Oct 25 '25 09:10 Randgalt

Update: I'm reproducing something now. Stay tuned...

Randgalt avatar Oct 25 '25 09:10 Randgalt

You know that in recent versions of the JDK annotation processing has to be manually enabled right? It's not automatic anymore.

yes, hence why I put //RUNTIME_OPTIONS -proc:full

note, I don't think this is specific to jbang - it just calls javac - so if you can get it working with maven/gradle or pure javac all good with me ;)

maxandersen avatar Oct 25 '25 12:10 maxandersen

I now believe this is a JDK/Java limitation. Look at this quote from: https://docs.oracle.com/en/java/javase/25/language/compact-source-files-and-instance-main-methods.html#GUID-E49690F1-727E-45F6-A582-9821C9597112

The code of a compact source file can't refer to its implicitly declared class by name, so instances of an implicitly declared class can't be constructed directly. Such a class is useful only as a standalone program or as an entry point to a program. Therefore, an implicitly declared class must have a main method that can be launched as described in Running Compact Source Files with the java Launcher and Instance Main Methods. This requirement is enforced by the Java compiler.

Also:

An implicitly declared class can't be referenced by name, so there can be no method references to its static methods.

RecordBuilder should probably disallow adding @RecordBuilder to records defined in a compact source file as it can never be be referenced properly.

Randgalt avatar Oct 25 '25 12:10 Randgalt

@Randgalt you are correct - I realize now my other comparison just had empty packages not naked main.

That is a shame - makes naked mains way less useful when can't use annotation processors with them.

maxandersen avatar Oct 27 '25 12:10 maxandersen

Annoyingly, there's no reliable way to tell that you're in a compact source file during annotation processing so there's no way for RecordBuilder to log an error.

Randgalt avatar Oct 27 '25 12:10 Randgalt