support naked main / empty packages
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.
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 :)
might actually be a limitation of naked mains.
Funny enough I can put the records in a separate file and it works.
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.
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.
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 {
}
You know that in recent versions of the JDK annotation processing has to be manually enabled right? It's not automatic anymore.
Update: I'm reproducing something now. Stay tuned...
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 ;)
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 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.
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.