codegen-java: Support not annotating constructor parameters (#792)

Motivation:
Spring Boot configuration classes neither require nor benefit from annotating constructor parameters with their name.
The same is true for pkl-config-java configuration classes compiled with `-parameter`.

Changes:
- Change CLI parameter `--params-annotation` to accept a `none` value.
  This is recommended in https://clig.dev/#arguments-and-flags and is how the `-F` parameter of the `ssh` command works.
- Change `paramsAnnotation` property in Gradle plugin, CliJavaCodeGeneratorOptions, and JavaCodegenOptions as follows:
  - Change meaning of `null` from "generate org.pkl.java.config.mapper.Named annotations" to "do not generate annotations".
    This is a breaking change (only) affecting users who explicitly set the property to `null` instead of omitting it.
  - Change property default from `null` to:
    `null` if `generateSpringBootConfig` is `true` and `org.pkl.java.config.mapper.Named` otherwise
- add tests
- update docs of this and other codegen options

Result:
Generated code does not contain unnecessary annotations.
This commit is contained in:
odenix
2024-12-13 14:29:18 -08:00
committed by GitHub
parent 70aaa6322e
commit 01bf844a96
13 changed files with 185 additions and 114 deletions

View File

@@ -145,23 +145,27 @@ Flag that indicates to generate private final fields and public getter methods i
[%collapsible] [%collapsible]
==== ====
Default: (flag not set) + Default: (flag not set) +
Flag that indicates to generate Javadoc based on doc comments for Pkl modules, classes, and properties. Flag that indicates to preserve Pkl doc comments by generating corresponding Javadoc comments.
==== ====
.--params-annotation .--params-annotation
[%collapsible] [%collapsible]
==== ====
Default: `org.pkl.config.java.mapper.Named` + Default: `none` if `--generate-spring-boot` is set, `org.pkl.config.java.mapper.Named` otherwise +
Fully qualified name of the annotation to use on constructor parameters. Fully qualified name of the annotation type to use for annotating constructor parameters with their name. +
The specified annotation type must have a `value` parameter of type `String` or the generated code may not compile.
If set to `none`, constructor parameters are not annotated.
Whether and how constructor parameters should be annotated depends on the library that instantiates the generated classes.
For Spring Boot applications, and for users of `pkl-config-java` compiling the generated classes with `-parameters`, no annotation is required.
==== ====
.--non-null-annotation .--non-null-annotation
[%collapsible] [%collapsible]
==== ====
Default: `org.pkl.config.java.mapper.NonNull` + Default: `org.pkl.config.java.mapper.NonNull` +
Fully qualified named of the annotation class to use for non-null types. + Fully qualified name of the annotation type to use for annotating non-null types. +
This annotation is required to have `java.lang.annotation.ElementType.TYPE_USE` as a `@Target` The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or it may generate code that does not compile. or the generated code may not compile.
==== ====
Common code generator options: Common code generator options:

View File

@@ -26,7 +26,7 @@ Flag that indicates to generate config classes for use with Spring Boot.
[%collapsible] [%collapsible]
==== ====
Default: (not set) + Default: (not set) +
Whether to make generated classes implement `java.io.Serializable`. Flag that indicates to generate classes that implement `java.io.Serializable`.
==== ====
.--rename .--rename

View File

@@ -118,7 +118,7 @@ Relative URIs are resolved against the working directory.
[%collapsible] [%collapsible]
==== ====
Default: (flag not set) + Default: (flag not set) +
Flag that indicates to generate Kdoc based on doc comments for Pkl modules, classes, and properties. Flag that indicates to preserve Pkl doc comments by generating corresponding KDoc comments.
==== ====
Common code generator options: Common code generator options:

View File

@@ -373,14 +373,26 @@ Example: `generateGetters = true` +
Whether to generate private final fields and public getter methods rather than public final fields. Whether to generate private final fields and public getter methods rather than public final fields.
==== ====
// TODO: fixme (paramsAnnotation, nonNullAnnotation) .paramsAnnotation: Property<String>
.preferJavaxInjectAnnotation: Boolean
[%collapsible] [%collapsible]
==== ====
Default: `false` + Default: `null` if `generateSpringBootConfig` is `true`, `"org.pkl.config.java.mapper.Named"` otherwise+
Example: `preferJavaxInjectAnnotation = true` + Example: `paramsAnnotation = "org.project.MyAnnotation"` +
Whether to annotate constructor parameters with `@javax.inject.Named` instead of `@org.pkl.config.java.mapper.Named`. Fully qualified name of the annotation type to use for annotating constructor parameters with their name. +
If `true`, the generated code will have a compile dependency on `javax.inject:javax.inject:1`. The specified annotation type must have a `value` parameter of type `String` or the generated code may not compile.
If set to `null`, constructor parameters are not annotated.
Whether and how constructor parameters should be annotated depends on the library that instantiates the generated classes.
For Spring Boot applications, and for users of `pkl-config-java` compiling the generated classes with `-parameters`, no annotation is required.
====
.nonNullAnnotation: Property<String>
[%collapsible]
====
Default: `"org.pkl.config.java.mapper.NonNull"` +
Example: `nonNullAnnotation = "org.project.MyAnnotation"` +
Fully qualified name of the annotation type to use for annotating non-null types. +
The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or the generated code may not compile.
==== ====
Common code generation properties: Common code generation properties:
@@ -443,8 +455,15 @@ see link:{uri-codegen-kotlin-example}[codegen-kotlin] in the _pkl/pkl-examples_
=== Configuration Options === Configuration Options
// TODO: fixme (generateKdoc) === Configuration Options
(None)
.generateKdoc: Property<Boolean>
[%collapsible]
====
Default: `false` +
Example: `generateKdoc = true` +
Whether to preserve Pkl doc comments by generating corresponding KDoc comments.
====
Common code generation properties: Common code generation properties:

View File

@@ -36,6 +36,14 @@ Example: `generateSpringBootConfig = true` +
Whether to generate config classes for use with Spring Boot. Whether to generate config classes for use with Spring Boot.
==== ====
.implementSerializable: Property<Boolean>
[%collapsible]
====
Default: `false` +
Example: `implementSerializable = true` +
Whether to generate classes that implement `java.io.Serializable`.
====
.renames: MapProperty<String, String> .renames: MapProperty<String, String>
[%collapsible] [%collapsible]
==== ====
@@ -86,4 +94,3 @@ Keys in this mapping can be arbitrary strings, including an empty string.
Values must be valid dot-separated fully qualifed class name prefixes, possibly terminated by a dot. Values must be valid dot-separated fully qualifed class name prefixes, possibly terminated by a dot.
==== ====
// TODO: fixme (implementSerializable)

View File

@@ -35,25 +35,35 @@ data class CliJavaCodeGeneratorOptions(
*/ */
val generateGetters: Boolean = false, val generateGetters: Boolean = false,
/** Whether to generate Javadoc based on doc comments for Pkl modules, classes, and properties. */ /** Whether to preserve Pkl doc comments by generating corresponding Javadoc comments. */
val generateJavadoc: Boolean = false, val generateJavadoc: Boolean = false,
/** Whether to generate config classes for use with Spring Boot. */ /** Whether to generate config classes for use with Spring Boot. */
val generateSpringBootConfig: Boolean = false, val generateSpringBootConfig: Boolean = false,
/** /**
* Fully qualified name of the annotation to use on constructor parameters. If this options is not * Fully qualified name of the annotation type to use for annotating constructor parameters with
* set, [org.pkl.config.java.mapper.Named] will be used. * their name.
*
* The specified annotation type must have a `value` parameter of type [java.lang.String] or the
* generated code may not compile.
*
* If set to `null`, constructor parameters are not annotated. The default value is `null` if
* [generateSpringBootConfig] is `true` and `"org.pkl.config.java.mapper.Named"` otherwise.
*/ */
val paramsAnnotation: String? = null, val paramsAnnotation: String? =
if (generateSpringBootConfig) null else "org.pkl.config.java.mapper.Named",
/** /**
* Fully qualified name of the annotation to use on non-null properties. If this option is not * Fully qualified name of the annotation type to use for annotating non-null types.
* set, [org.pkl.config.java.mapper.NonNull] will be used. *
* The specified annotation type must have a [java.lang.annotation.Target] of
* [java.lang.annotation.ElementType.TYPE_USE] or the generated code may not compile. If set to
* `null`, [org.pkl.config.java.mapper.NonNull] will be used.
*/ */
val nonNullAnnotation: String? = null, val nonNullAnnotation: String? = null,
/** Whether to make generated classes implement [java.io.Serializable] */ /** Whether to generate classes that implement [java.io.Serializable]. */
val implementSerializable: Boolean = false, val implementSerializable: Boolean = false,
/** /**

View File

@@ -54,25 +54,35 @@ data class JavaCodeGeneratorOptions(
*/ */
val generateGetters: Boolean = false, val generateGetters: Boolean = false,
/** Whether to generate Javadoc based on doc comments for Pkl modules, classes, and properties. */ /** Whether to preserve Pkl doc comments by generating corresponding Javadoc comments. */
val generateJavadoc: Boolean = false, val generateJavadoc: Boolean = false,
/** Whether to generate config classes for use with Spring Boot. */ /** Whether to generate config classes for use with Spring Boot. */
val generateSpringBootConfig: Boolean = false, val generateSpringBootConfig: Boolean = false,
/** /**
* Fully qualified name of the annotation to use on constructor parameters. If this options is not * Fully qualified name of the annotation type to use for annotating constructor parameters with
* set, [org.pkl.config.java.mapper.Named] will be used. * their name.
*
* The specified annotation type must have a `value` parameter of type [java.lang.String] or the
* generated code may not compile.
*
* If set to `null`, constructor parameters are not annotated. The default value is `null` if
* [generateSpringBootConfig] is `true` and `"org.pkl.config.java.mapper.Named"` otherwise.
*/ */
val paramsAnnotation: String? = null, val paramsAnnotation: String? =
if (generateSpringBootConfig) null else "org.pkl.config.java.mapper.Named",
/** /**
* Fully qualified name of the annotation to use on non-null properties. If this option is not * Fully qualified name of the annotation type to use for annotating non-null types.
* set, [org.pkl.config.java.mapper.NonNull] will be used. *
* The specified annotation type must have a [java.lang.annotation.Target] of
* [java.lang.annotation.ElementType.TYPE_USE] or the generated code may not compile. If set to
* `null`, [org.pkl.config.java.mapper.NonNull] will be used.
*/ */
val nonNullAnnotation: String? = null, val nonNullAnnotation: String? = null,
/** Whether to make generated classes implement [java.io.Serializable] */ /** Whether to generate classes that implement [java.io.Serializable]. */
val implementSerializable: Boolean = false, val implementSerializable: Boolean = false,
/** /**
@@ -233,15 +243,15 @@ class JavaCodeGenerator(
propJavaName: String, propJavaName: String,
property: PClass.Property property: PClass.Property
) { ) {
builder.addParameter( val paramBuilder = ParameterSpec.builder(property.type.toJavaPoetName(), propJavaName)
ParameterSpec.builder(property.type.toJavaPoetName(), propJavaName) if (paramsAnnotationName != null) {
.addAnnotation( paramBuilder.addAnnotation(
AnnotationSpec.builder(namedAnnotationName) AnnotationSpec.builder(paramsAnnotationName)
.addMember("value", "\$S", property.simpleName) .addMember("value", "\$S", property.simpleName)
.build() .build()
) )
.build() }
) builder.addParameter(paramBuilder.build())
} }
fun generateConstructor(isInstantiable: Boolean): MethodSpec { fun generateConstructor(isInstantiable: Boolean): MethodSpec {
@@ -671,12 +681,8 @@ class JavaCodeGenerator(
return builder return builder
} }
private val namedAnnotationName = private val paramsAnnotationName: ClassName? =
if (codegenOptions.paramsAnnotation != null) { codegenOptions.paramsAnnotation?.let { toClassName(it) }
toClassName(codegenOptions.paramsAnnotation)
} else {
ClassName.get("org.pkl.config.java.mapper", "Named")
}
private fun appendPropertyMethod() = private fun appendPropertyMethod() =
MethodSpec.methodBuilder("appendProperty") MethodSpec.methodBuilder("appendProperty")

View File

@@ -17,10 +17,7 @@
package org.pkl.codegen.java package org.pkl.codegen.java
import com.github.ajalt.clikt.parameters.options.associate import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.path import com.github.ajalt.clikt.parameters.types.path
import java.nio.file.Path import java.nio.file.Path
import org.pkl.commons.cli.CliBaseOptions import org.pkl.commons.cli.CliBaseOptions
@@ -71,33 +68,37 @@ class PklJavaCodegenCommand :
private val generateJavadoc: Boolean by private val generateJavadoc: Boolean by
option( option(
names = arrayOf("--generate-javadoc"), names = arrayOf("--generate-javadoc"),
help = help = "Whether to preserve Pkl doc comments by generating corresponding Javadoc comments."
"Whether to generate Javadoc based on doc comments " +
"for Pkl modules, classes, and properties."
) )
.flag() .flag()
private val generateSpringboot: Boolean by private val generateSpringBoot: Boolean by
option( option(
names = arrayOf("--generate-spring-boot"), names = arrayOf("--generate-spring-boot"),
help = "Whether to generate config classes for use with Spring boot." help = "Whether to generate config classes for use with Spring Boot."
) )
.flag() .flag()
private val paramsAnnotation: String? by private val paramsAnnotation: String by
option( option(
names = arrayOf("--params-annotation"), names = arrayOf("--params-annotation"),
help = "Fully qualified name of the annotation to use on constructor parameters." help =
) "Fully qualified name of the annotation type to use for annotating constructor parameters with their name."
)
.defaultLazy(
"`none` if `--generate-spring-boot` is set, `org.pkl.config.java.mapper.Named` otherwise"
) {
if (generateSpringBoot) "none" else "org.pkl.config.java.mapper.Named"
}
private val nonNullAnnotation: String? by private val nonNullAnnotation: String? by
option( option(
names = arrayOf("--non-null-annotation"), names = arrayOf("--non-null-annotation"),
help = help =
""" """
Fully qualified named of the annotation class to use for non-null types. Fully qualified name of the annotation type to use for annotating non-null types.
This annotation is required to have `java.lang.annotation.ElementType.TYPE_USE` as a `@Target` The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or it may generate code that does not compile. or the generated code may not compile.
""" """
.trimIndent() .trimIndent()
) )
@@ -105,7 +106,7 @@ class PklJavaCodegenCommand :
private val implementSerializable: Boolean by private val implementSerializable: Boolean by
option( option(
names = arrayOf("--implement-serializable"), names = arrayOf("--implement-serializable"),
help = "Whether to make generated classes implement java.io.Serializable." help = "Whether to generate classes that implement java.io.Serializable."
) )
.flag() .flag()
@@ -117,7 +118,7 @@ class PklJavaCodegenCommand :
""" """
Replace a prefix in the names of the generated Java classes (repeatable). Replace a prefix in the names of the generated Java classes (repeatable).
By default, the names of generated classes are derived from the Pkl module names. By default, the names of generated classes are derived from the Pkl module names.
With this option, you can override the modify the default names, renaming entire With this option, you can override or modify the default names, renaming entire
classes or just their packages. classes or just their packages.
""" """
.trimIndent() .trimIndent()
@@ -132,8 +133,8 @@ class PklJavaCodegenCommand :
indent = indent, indent = indent,
generateGetters = generateGetters, generateGetters = generateGetters,
generateJavadoc = generateJavadoc, generateJavadoc = generateJavadoc,
generateSpringBootConfig = generateSpringboot, generateSpringBootConfig = generateSpringBoot,
paramsAnnotation = paramsAnnotation, paramsAnnotation = if (paramsAnnotation == "none") null else paramsAnnotation,
nonNullAnnotation = nonNullAnnotation, nonNullAnnotation = nonNullAnnotation,
implementSerializable = implementSerializable, implementSerializable = implementSerializable,
renames = renames renames = renames

View File

@@ -104,26 +104,10 @@ class JavaCodeGeneratorTest {
private fun generateJavaCode( private fun generateJavaCode(
pklCode: String, pklCode: String,
generateGetters: Boolean = false, options: JavaCodeGeneratorOptions = JavaCodeGeneratorOptions()
generateJavadoc: Boolean = false,
generateSpringBootConfig: Boolean = false,
nonNullAnnotation: String? = null,
implementSerializable: Boolean = false,
renames: Map<String, String> = emptyMap()
): JavaSourceCode { ): JavaSourceCode {
val module = Evaluator.preconfigured().evaluateSchema(text(pklCode)) val module = Evaluator.preconfigured().evaluateSchema(text(pklCode))
val generator = val generator = JavaCodeGenerator(module, options)
JavaCodeGenerator(
module,
JavaCodeGeneratorOptions(
generateGetters = generateGetters,
generateJavadoc = generateJavadoc,
generateSpringBootConfig = generateSpringBootConfig,
nonNullAnnotation = nonNullAnnotation,
implementSerializable = implementSerializable,
renames = renames
)
)
return JavaSourceCode(generator.javaFile) return JavaSourceCode(generator.javaFile)
} }
} }
@@ -235,7 +219,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateJavadoc = true JavaCodeGeneratorOptions(generateJavadoc = true)
) )
assertThat(javaCode) assertThat(javaCode)
.contains( .contains(
@@ -274,8 +258,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateGetters = true, JavaCodeGeneratorOptions(generateGetters = true, generateJavadoc = true)
generateJavadoc = true
) )
assertThat(javaCode) assertThat(javaCode)
.contains( .contains(
@@ -322,7 +305,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateJavadoc = true JavaCodeGeneratorOptions(generateJavadoc = true)
) )
assertThat(javaCode) assertThat(javaCode)
.contains( .contains(
@@ -349,7 +332,7 @@ class JavaCodeGeneratorTest {
propertyInDeprecatedModuleClass : Int = 42 propertyInDeprecatedModuleClass : Int = 42
""" """
.trimIndent(), .trimIndent(),
generateJavadoc = generateJavadoc JavaCodeGeneratorOptions(generateJavadoc = generateJavadoc)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -389,7 +372,7 @@ class JavaCodeGeneratorTest {
""" """
.trimIndent(), .trimIndent(),
// no message, so no Javadoc, regardless of flag // no message, so no Javadoc, regardless of flag
generateJavadoc = generateJavadoc JavaCodeGeneratorOptions(generateJavadoc = generateJavadoc)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -424,7 +407,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateGetters = true JavaCodeGeneratorOptions(generateGetters = true)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -513,7 +496,7 @@ class JavaCodeGeneratorTest {
@Deprecated { message = "property is deprecated" } @Deprecated { message = "property is deprecated" }
deprecatedProperty: Int deprecatedProperty: Int
""", """,
generateJavadoc = true JavaCodeGeneratorOptions(generateJavadoc = true)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -735,7 +718,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateGetters = true JavaCodeGeneratorOptions(generateGetters = true)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -889,7 +872,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateGetters = true JavaCodeGeneratorOptions(generateGetters = true)
) )
assertThat(javaCode).compilesSuccessfully().isEqualToResourceFile("GenerateGetters.jva") assertThat(javaCode).compilesSuccessfully().isEqualToResourceFile("GenerateGetters.jva")
@@ -1002,7 +985,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateJavadoc = true JavaCodeGeneratorOptions(generateJavadoc = true)
) )
assertThat(javaCode).compilesSuccessfully().isEqualToResourceFile("Javadoc.jva") assertThat(javaCode).compilesSuccessfully().isEqualToResourceFile("Javadoc.jva")
@@ -1026,8 +1009,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateGetters = true, JavaCodeGeneratorOptions(generateGetters = true, generateJavadoc = true)
generateJavadoc = true
) )
assertThat(javaCode) assertThat(javaCode)
@@ -1169,7 +1151,7 @@ class JavaCodeGeneratorTest {
foo: String foo: String
""" """
.trimIndent(), .trimIndent(),
nonNullAnnotation = "com.example.Annotations\$NonNull" JavaCodeGeneratorOptions(nonNullAnnotation = "com.example.Annotations\$NonNull")
) )
assertThat(javaCode) assertThat(javaCode)
@@ -1463,6 +1445,40 @@ class JavaCodeGeneratorTest {
.contains("public final @NonNull String v6;") .contains("public final @NonNull String v6;")
} }
@Test
fun `custom constructor parameter annotation`() {
val javaCode =
generateJavaCode(
"""
module my.mod
name: String
"""
.trimIndent(),
JavaCodeGeneratorOptions(paramsAnnotation = "org.project.MyAnnotation")
)
assertThat(javaCode)
.contains("import org.project.MyAnnotation;")
.contains("public Mod(@MyAnnotation(\"name\") @NonNull String name)")
}
@Test
fun `no constructor parameter annotation`() {
val javaCode =
generateJavaCode(
"""
module my.mod
name: String
"""
.trimIndent(),
JavaCodeGeneratorOptions(paramsAnnotation = null)
)
assertThat(javaCode).contains("public Mod(@NonNull String name)")
}
@Test @Test
fun `spring boot config`() { fun `spring boot config`() {
val javaCode = val javaCode =
@@ -1478,7 +1494,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateSpringBootConfig = true JavaCodeGeneratorOptions(generateSpringBootConfig = true)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -1511,6 +1527,7 @@ class JavaCodeGeneratorTest {
.trimMargin() .trimMargin()
) )
.doesNotContain("@ConstructorBinding") .doesNotContain("@ConstructorBinding")
.doesNotContain("@Named")
// not worthwhile to add spring & spring boot dependency just so that this test can compile // not worthwhile to add spring & spring boot dependency just so that this test can compile
// their annotations // their annotations
@@ -1765,7 +1782,7 @@ class JavaCodeGeneratorTest {
typealias Direction = "north"|"east"|"south"|"west" typealias Direction = "north"|"east"|"south"|"west"
""" """
.trimIndent(), .trimIndent(),
implementSerializable = true JavaCodeGeneratorOptions(implementSerializable = true)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -1846,7 +1863,7 @@ class JavaCodeGeneratorTest {
abstract class Foo { str: String } abstract class Foo { str: String }
""" """
.trimIndent(), .trimIndent(),
implementSerializable = true JavaCodeGeneratorOptions(implementSerializable = true)
) )
assertThat(javaCode).doesNotContain("Serializable") assertThat(javaCode).doesNotContain("Serializable")
@@ -1857,7 +1874,7 @@ class JavaCodeGeneratorTest {
module my.mod module my.mod
""" """
.trimIndent(), .trimIndent(),
implementSerializable = true JavaCodeGeneratorOptions(implementSerializable = true)
) )
assertThat(javaCode).doesNotContain("Serializable") assertThat(javaCode).doesNotContain("Serializable")
@@ -1874,7 +1891,7 @@ class JavaCodeGeneratorTest {
class Address { city: String } class Address { city: String }
""" """
.trimIndent(), .trimIndent(),
implementSerializable = true JavaCodeGeneratorOptions(implementSerializable = true)
) )
assertThat(javaCode) assertThat(javaCode)
@@ -1960,7 +1977,7 @@ class JavaCodeGeneratorTest {
} }
""" """
.trimIndent(), .trimIndent(),
generateGetters = true JavaCodeGeneratorOptions(generateGetters = true)
) )
assertThat(javaCode) assertThat(javaCode)

View File

@@ -29,13 +29,13 @@ data class CliKotlinCodeGeneratorOptions(
/** The characters to use for indenting generated source code. */ /** The characters to use for indenting generated source code. */
val indent: String = " ", val indent: String = " ",
/** Whether to generate Kdoc based on doc comments for Pkl modules, classes, and properties. */ /** Whether to preserve Pkl doc comments by generating corresponding KDoc comments. */
val generateKdoc: Boolean = false, val generateKdoc: Boolean = false,
/** Whether to generate config classes for use with Spring Boot. */ /** Whether to generate config classes for use with Spring Boot. */
val generateSpringBootConfig: Boolean = false, val generateSpringBootConfig: Boolean = false,
/** Whether to make generated classes implement [java.io.Serializable] */ /** Whether generated classes should implement [java.io.Serializable]. */
val implementSerializable: Boolean = false, val implementSerializable: Boolean = false,
/** /**

View File

@@ -32,13 +32,13 @@ data class KotlinCodeGeneratorOptions(
/** The characters to use for indenting generated Kotlin code. */ /** The characters to use for indenting generated Kotlin code. */
val indent: String = " ", val indent: String = " ",
/** Whether to generate KDoc based on doc comments for Pkl modules, classes, and properties. */ /** Whether to preserve Pkl doc comments by generating corresponding KDoc comments. */
val generateKdoc: Boolean = false, val generateKdoc: Boolean = false,
/** Whether to generate config classes for use with Spring Boot. */ /** Whether to generate config classes for use with Spring Boot. */
val generateSpringBootConfig: Boolean = false, val generateSpringBootConfig: Boolean = false,
/** Whether to make generated classes implement [java.io.Serializable] */ /** Whether to generate classes that implement [java.io.Serializable]. */
val implementSerializable: Boolean = false, val implementSerializable: Boolean = false,
/** /**

View File

@@ -62,23 +62,21 @@ class PklKotlinCodegenCommand :
private val generateKdoc: Boolean by private val generateKdoc: Boolean by
option( option(
names = arrayOf("--generate-kdoc"), names = arrayOf("--generate-kdoc"),
help = help = "Whether to preserve Pkl doc comments by generating corresponding KDoc comments."
"Whether to generate Kdoc based on doc comments " +
"for Pkl modules, classes, and properties."
) )
.flag() .flag()
private val generateSpringboot: Boolean by private val generateSpringboot: Boolean by
option( option(
names = arrayOf("--generate-spring-boot"), names = arrayOf("--generate-spring-boot"),
help = "Whether to generate config classes for use with Spring boot." help = "Whether to generate config classes for use with Spring Boot."
) )
.flag() .flag()
private val implementSerializable: Boolean by private val implementSerializable: Boolean by
option( option(
names = arrayOf("--implement-serializable"), names = arrayOf("--implement-serializable"),
help = "Whether to make generated classes implement java.io.Serializable" help = "Whether to generate classes that implement java.io.Serializable."
) )
.flag() .flag()
@@ -90,7 +88,7 @@ class PklKotlinCodegenCommand :
""" """
Replace a prefix in the names of the generated Kotlin classes (repeatable). Replace a prefix in the names of the generated Kotlin classes (repeatable).
By default, the names of generated classes are derived from the Pkl module names. By default, the names of generated classes are derived from the Pkl module names.
With this option, you can override the modify the default names, renaming entire With this option, you can override or modify the default names, renaming entire
classes or just their packages. classes or just their packages.
""" """
.trimIndent() .trimIndent()

View File

@@ -192,6 +192,15 @@ public class PklPlugin implements Plugin<Project> {
spec.getGenerateGetters().convention(false); spec.getGenerateGetters().convention(false);
spec.getGenerateJavadoc().convention(false); spec.getGenerateJavadoc().convention(false);
// Not using `convention()` so that users can disable generation of
// constructor parameters annotations by setting this property to `null`.
spec.getParamsAnnotation()
.set(
project.provider(
() ->
spec.getGenerateSpringBootConfig().get()
? null
: "org.pkl.config.java.mapper.Named"));
createModulesTask(JavaCodeGenTask.class, spec) createModulesTask(JavaCodeGenTask.class, spec)
.configure( .configure(