mirror of
https://github.com/apple/pkl.git
synced 2026-01-19 09:57:15 +01:00
codegen-java: Make stateless classes instantiable (#734)
Motivation: Currently, the condition for making a generated Java class instantiable is "class is neither abstract nor stateless". (An instantiable class receives a public constructor and equals/hashCode/toString/with methods.) This is inconsistent with Pkl and codegen-kotlin, both of which support instantiation of stateless classes. Changes: Widen condition for making a class instantiable to "class is neither abstract nor a stateless final module class". This is consistent with codegen-kotlin, which generates object declarations (only) for stateless final module classes. Result: Stateless classes are instantiable in Pkl, codegen-java, and codegen-kotlin.
This commit is contained in:
@@ -541,8 +541,9 @@ class JavaCodeGenerator(
|
||||
val builder =
|
||||
TypeSpec.classBuilder(javaPoetClassName.simpleName()).addModifiers(Modifier.PUBLIC)
|
||||
|
||||
// stateless classes aren't instantiable by choice, i.e., no public ctor is generated
|
||||
val isInstantiable = !pClass.isAbstract && allProperties.isNotEmpty()
|
||||
// stateless final module classes are non-instantiable by choice
|
||||
val isInstantiable =
|
||||
!(pClass.isAbstract || (isModuleClass && !pClass.isOpen && allProperties.isEmpty()))
|
||||
|
||||
if (codegenOptions.implementSerializable && isInstantiable) {
|
||||
builder.addSuperinterface(java.io.Serializable::class.java)
|
||||
|
||||
@@ -775,6 +775,83 @@ class JavaCodeGeneratorTest {
|
||||
.isEqualToResourceFile("Inheritance.jva")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `stateless classes`() {
|
||||
val javaCode =
|
||||
generateJavaCode(
|
||||
"""
|
||||
module my.mod
|
||||
|
||||
class Foo
|
||||
abstract class Bar
|
||||
class Baz extends Bar
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
assertThat(javaCode)
|
||||
.contains(
|
||||
"""
|
||||
| public static final class Foo {
|
||||
| public Foo() {
|
||||
| }
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
.contains(
|
||||
"""
|
||||
| public abstract static class Bar {
|
||||
| protected Bar() {
|
||||
| }
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
.contains(
|
||||
"""
|
||||
| public static final class Baz extends Bar {
|
||||
| public Baz() {
|
||||
| }
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `stateless module classes`() {
|
||||
var javaCode = generateJavaCode("module my.mod")
|
||||
assertThat(javaCode)
|
||||
.contains(
|
||||
"""
|
||||
|public final class Mod {
|
||||
| private Mod() {
|
||||
| }
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
|
||||
javaCode = generateJavaCode("abstract module my.mod")
|
||||
assertThat(javaCode)
|
||||
.contains(
|
||||
"""
|
||||
|public abstract class Mod {
|
||||
| protected Mod() {
|
||||
| }
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
|
||||
javaCode = generateJavaCode("open module my.mod")
|
||||
assertThat(javaCode)
|
||||
.contains(
|
||||
"""
|
||||
|public class Mod {
|
||||
| public Mod() {
|
||||
| }
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `reserved words`() {
|
||||
val props = javaReservedWords.joinToString("\n") { "`$it`: Int" }
|
||||
@@ -1765,12 +1842,22 @@ class JavaCodeGeneratorTest {
|
||||
|
||||
@Test
|
||||
fun `non-instantiable classes aren't made serializable`() {
|
||||
val javaCode =
|
||||
var javaCode =
|
||||
generateJavaCode(
|
||||
"""
|
||||
module my.mod
|
||||
abstract class Foo { str: String }
|
||||
class Bar // non-instantiable because no constructor is generated for stateless class
|
||||
"""
|
||||
.trimIndent(),
|
||||
implementSerializable = true
|
||||
)
|
||||
|
||||
assertThat(javaCode).doesNotContain("Serializable")
|
||||
|
||||
javaCode =
|
||||
generateJavaCode(
|
||||
"""
|
||||
module my.mod
|
||||
"""
|
||||
.trimIndent(),
|
||||
implementSerializable = true
|
||||
|
||||
Reference in New Issue
Block a user