mirror of
https://github.com/apple/pkl.git
synced 2026-04-23 08:48:36 +02:00
codegen-kotlin: Generate toString() methods consistent with data classes (#793)
Motivation: codegen-kotlin generates a mix of data classes and regular classes. For regular classes, toString() methods are also generated. However, the output of generated toString() methods differs from the output of default toString() methods of data classes. Changes: Generate toString() methods that produce the same output as default toString() methods of data classes. Also: rename KotlinCodegenOptions to KotlinCodeGeneratorOptions The new name is consistent with existing names KotlinCodeGenerator and CliKotlinCodeGeneratorOptions. Backward compatibility is ensured by turning KotlinCodegenOptions into a (deprecated) type alias.
This commit is contained in:
@@ -147,7 +147,7 @@ class KotlinCodeGeneratorTest {
|
||||
val generator =
|
||||
KotlinCodeGenerator(
|
||||
module,
|
||||
KotlinCodegenOptions(
|
||||
KotlinCodeGeneratorOptions(
|
||||
generateKdoc = generateKdoc,
|
||||
generateSpringBootConfig = generateSpringBootConfig,
|
||||
implementSerializable = implementSerializable
|
||||
@@ -195,65 +195,52 @@ class KotlinCodeGeneratorTest {
|
||||
|
||||
assertThat(propertyTypes.toString())
|
||||
.isEqualTo(
|
||||
"""PropertyTypes(boolean=true, int=42, float=42.3, string=string, duration=5.min, """ +
|
||||
"""durationUnit=min, dataSize=3.gb, dataSizeUnit=gb, nullable=idea, nullable2=null, """ +
|
||||
"""pair=(1, 2), pair2=(pigeon, Other(name=pigeon)), coll=[1, 2], """ +
|
||||
"""coll2=[Other(name=pigeon), Other(name=pigeon)], list=[1, 2], """ +
|
||||
"""list2=[Other(name=pigeon), Other(name=pigeon)], set=[1, 2], """ +
|
||||
"""set2=[Other(name=pigeon)], map={1=one, 2=two}, map2={one=Other(name=pigeon), """ +
|
||||
"""two=Other(name=pigeon)}, container={1=one, 2=two}, container2={one=Other(name=pigeon), """ +
|
||||
"""two=Other(name=pigeon)}, other=Other(name=pigeon), regex=(i?)\w*, any=Other(name=pigeon), """ +
|
||||
"""nonNull=Other(name=pigeon), enum=north)"""
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `quoted identifiers`() {
|
||||
val kotlinCode =
|
||||
generateKotlinCode(
|
||||
"""
|
||||
PropertyTypes {
|
||||
boolean = true
|
||||
int = 42
|
||||
float = 42.3
|
||||
string = string
|
||||
duration = 5.min
|
||||
durationUnit = min
|
||||
dataSize = 3.gb
|
||||
dataSizeUnit = gb
|
||||
nullable = idea
|
||||
nullable2 = null
|
||||
pair = (1, 2)
|
||||
pair2 = (pigeon, Other {
|
||||
name = pigeon
|
||||
})
|
||||
coll = [1, 2]
|
||||
coll2 = [Other {
|
||||
name = pigeon
|
||||
}, Other {
|
||||
name = pigeon
|
||||
}]
|
||||
list = [1, 2]
|
||||
list2 = [Other {
|
||||
name = pigeon
|
||||
}, Other {
|
||||
name = pigeon
|
||||
}]
|
||||
set = [1, 2]
|
||||
set2 = [Other {
|
||||
name = pigeon
|
||||
}]
|
||||
map = {1=one, 2=two}
|
||||
map2 = {one=Other {
|
||||
name = pigeon
|
||||
}, two=Other {
|
||||
name = pigeon
|
||||
}}
|
||||
container = {1=one, 2=two}
|
||||
container2 = {one=Other {
|
||||
name = pigeon
|
||||
}, two=Other {
|
||||
name = pigeon
|
||||
}}
|
||||
other = Other {
|
||||
name = pigeon
|
||||
}
|
||||
regex = (i?)\w*
|
||||
any = Other {
|
||||
name = pigeon
|
||||
}
|
||||
nonNull = Other {
|
||||
name = pigeon
|
||||
}
|
||||
enum = north
|
||||
}
|
||||
"""
|
||||
open class `A Person` {
|
||||
`first name`: String
|
||||
}
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
|
||||
assertThat(kotlinCode)
|
||||
.compilesSuccessfully()
|
||||
.contains(
|
||||
"""
|
||||
| open class `A Person`(
|
||||
| open val `first name`: String
|
||||
| )
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
.contains(
|
||||
"""
|
||||
| override fun toString(): String = ""${'"'}A Person(first name=${'$'}`first name`)""${'"'}
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
.contains(
|
||||
"""
|
||||
| open fun copy(`first name`: String = this.`first name`): `A Person` = `A Person`(`first name`)
|
||||
"""
|
||||
.trimMargin()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1816,7 +1803,7 @@ class KotlinCodeGeneratorTest {
|
||||
@Test
|
||||
fun `override names in a standalone module`() {
|
||||
val files =
|
||||
KotlinCodegenOptions(
|
||||
KotlinCodeGeneratorOptions(
|
||||
renames = mapOf("a.b.c" to "x.y.z", "d.e.f.AnotherModule" to "u.v.w.RenamedModule")
|
||||
)
|
||||
.generateFiles(
|
||||
@@ -1851,7 +1838,7 @@ class KotlinCodeGeneratorTest {
|
||||
@Test
|
||||
fun `override names based on the longest prefix`() {
|
||||
val files =
|
||||
KotlinCodegenOptions(
|
||||
KotlinCodeGeneratorOptions(
|
||||
renames = mapOf("com.foo.bar." to "x.", "com.foo." to "y.", "com." to "z.", "" to "w.")
|
||||
)
|
||||
.generateFiles(
|
||||
@@ -1897,7 +1884,7 @@ class KotlinCodeGeneratorTest {
|
||||
@Test
|
||||
fun `override names in multiple modules using each other`() {
|
||||
val files =
|
||||
KotlinCodegenOptions(
|
||||
KotlinCodeGeneratorOptions(
|
||||
renames =
|
||||
mapOf(
|
||||
"org.foo" to "com.foo.x",
|
||||
@@ -1980,7 +1967,7 @@ class KotlinCodeGeneratorTest {
|
||||
@Test
|
||||
fun `do not capitalize names of renamed classes`() {
|
||||
val files =
|
||||
KotlinCodegenOptions(
|
||||
KotlinCodeGeneratorOptions(
|
||||
renames = mapOf("a.b.c.MyModule" to "x.y.z.renamed_module", "d.e.f." to "u.v.w.")
|
||||
)
|
||||
.generateFiles(
|
||||
@@ -2024,7 +2011,7 @@ class KotlinCodeGeneratorTest {
|
||||
assertThat(files).isEmpty()
|
||||
}
|
||||
|
||||
private fun KotlinCodegenOptions.generateFiles(
|
||||
private fun KotlinCodeGeneratorOptions.generateFiles(
|
||||
vararg pklModules: PklModule
|
||||
): Map<String, String> {
|
||||
val pklFiles = pklModules.map { it.writeToDisk(tempDir.resolve("pkl/${it.name}.pkl")) }
|
||||
@@ -2036,13 +2023,13 @@ class KotlinCodeGeneratorTest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinCodegenOptions.generateFiles(
|
||||
private fun KotlinCodeGeneratorOptions.generateFiles(
|
||||
vararg pklModules: kotlin.Pair<String, String>
|
||||
): Map<String, String> =
|
||||
generateFiles(*pklModules.map { (name, text) -> PklModule(name, text) }.toTypedArray())
|
||||
|
||||
private fun generateFiles(vararg pklModules: PklModule): Map<String, KotlinSourceCode> =
|
||||
KotlinCodegenOptions().generateFiles(*pklModules).mapValues { KotlinSourceCode(it.value) }
|
||||
KotlinCodeGeneratorOptions().generateFiles(*pklModules).mapValues { KotlinSourceCode(it.value) }
|
||||
|
||||
private fun instantiateOtherAndPropertyTypes(): kotlin.Pair<Any, Any> {
|
||||
val otherCtor = propertyTypesClasses.getValue("Other").constructors.first()
|
||||
|
||||
@@ -6,23 +6,9 @@ import kotlin.Boolean
|
||||
import kotlin.Int
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.text.StringBuilder
|
||||
import org.pkl.core.Duration
|
||||
|
||||
object Mod {
|
||||
private fun appendProperty(
|
||||
builder: StringBuilder,
|
||||
name: String,
|
||||
value: Any?
|
||||
) {
|
||||
builder.append("\n ").append(name).append(" = ")
|
||||
val lines = value.toString().split("\n")
|
||||
builder.append(lines[0])
|
||||
for (i in 1..lines.lastIndex) {
|
||||
builder.append("\n ").append(lines[i])
|
||||
}
|
||||
}
|
||||
|
||||
open class Foo(
|
||||
open val one: Long
|
||||
) {
|
||||
@@ -42,13 +28,7 @@ object Mod {
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder(100)
|
||||
builder.append(Foo::class.java.simpleName).append(" {")
|
||||
appendProperty(builder, "one", this.one)
|
||||
builder.append("\n}")
|
||||
return builder.toString()
|
||||
}
|
||||
override fun toString(): String = """Foo(one=$one)"""
|
||||
}
|
||||
|
||||
open class None(
|
||||
@@ -70,13 +50,7 @@ object Mod {
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder(100)
|
||||
builder.append(None::class.java.simpleName).append(" {")
|
||||
appendProperty(builder, "one", this.one)
|
||||
builder.append("\n}")
|
||||
return builder.toString()
|
||||
}
|
||||
override fun toString(): String = """None(one=$one)"""
|
||||
}
|
||||
|
||||
open class Bar(
|
||||
@@ -103,14 +77,7 @@ object Mod {
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder(150)
|
||||
builder.append(Bar::class.java.simpleName).append(" {")
|
||||
appendProperty(builder, "one", this.one)
|
||||
appendProperty(builder, "two", this.two)
|
||||
builder.append("\n}")
|
||||
return builder.toString()
|
||||
}
|
||||
override fun toString(): String = """Bar(one=$one, two=$two)"""
|
||||
}
|
||||
|
||||
class Baz(
|
||||
@@ -146,14 +113,6 @@ object Mod {
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder(200)
|
||||
builder.append(Baz::class.java.simpleName).append(" {")
|
||||
appendProperty(builder, "one", this.one)
|
||||
appendProperty(builder, "two", this.two)
|
||||
appendProperty(builder, "three", this.three)
|
||||
builder.append("\n}")
|
||||
return builder.toString()
|
||||
}
|
||||
override fun toString(): String = """Baz(one=$one, two=$two, three=$three)"""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import kotlin.Any
|
||||
import kotlin.Boolean
|
||||
import kotlin.Int
|
||||
import kotlin.String
|
||||
import kotlin.text.StringBuilder
|
||||
|
||||
/**
|
||||
* type alias comment.
|
||||
@@ -51,13 +50,7 @@ data class Mod(
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder(100)
|
||||
builder.append(Product::class.java.simpleName).append(" {")
|
||||
appendProperty(builder, "price", this.price)
|
||||
builder.append("\n}")
|
||||
return builder.toString()
|
||||
}
|
||||
override fun toString(): String = """Product(price=$price)"""
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,19 +64,4 @@ data class Mod(
|
||||
*/
|
||||
val name: String
|
||||
)
|
||||
|
||||
companion object {
|
||||
private fun appendProperty(
|
||||
builder: StringBuilder,
|
||||
name: String,
|
||||
value: Any?
|
||||
) {
|
||||
builder.append("\n ").append(name).append(" = ")
|
||||
val lines = value.toString().split("\n")
|
||||
builder.append(lines[0])
|
||||
for (i in 1..lines.lastIndex) {
|
||||
builder.append("\n ").append(lines[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,26 +13,12 @@ import kotlin.collections.List
|
||||
import kotlin.collections.Map
|
||||
import kotlin.collections.Set
|
||||
import kotlin.text.Regex
|
||||
import kotlin.text.StringBuilder
|
||||
import org.pkl.core.DataSize
|
||||
import org.pkl.core.DataSizeUnit
|
||||
import org.pkl.core.Duration
|
||||
import org.pkl.core.DurationUnit
|
||||
|
||||
object Mod {
|
||||
private fun appendProperty(
|
||||
builder: StringBuilder,
|
||||
name: String,
|
||||
value: Any?
|
||||
) {
|
||||
builder.append("\n ").append(name).append(" = ")
|
||||
val lines = value.toString().split("\n")
|
||||
builder.append(lines[0])
|
||||
for (i in 1..lines.lastIndex) {
|
||||
builder.append("\n ").append(lines[i])
|
||||
}
|
||||
}
|
||||
|
||||
open class PropertyTypes(
|
||||
open val boolean: Boolean,
|
||||
open val int: Long,
|
||||
@@ -160,39 +146,8 @@ object Mod {
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder(1400)
|
||||
builder.append(PropertyTypes::class.java.simpleName).append(" {")
|
||||
appendProperty(builder, "boolean", this.boolean)
|
||||
appendProperty(builder, "int", this.int)
|
||||
appendProperty(builder, "float", this.float)
|
||||
appendProperty(builder, "string", this.string)
|
||||
appendProperty(builder, "duration", this.duration)
|
||||
appendProperty(builder, "durationUnit", this.durationUnit)
|
||||
appendProperty(builder, "dataSize", this.dataSize)
|
||||
appendProperty(builder, "dataSizeUnit", this.dataSizeUnit)
|
||||
appendProperty(builder, "nullable", this.nullable)
|
||||
appendProperty(builder, "nullable2", this.nullable2)
|
||||
appendProperty(builder, "pair", this.pair)
|
||||
appendProperty(builder, "pair2", this.pair2)
|
||||
appendProperty(builder, "coll", this.coll)
|
||||
appendProperty(builder, "coll2", this.coll2)
|
||||
appendProperty(builder, "list", this.list)
|
||||
appendProperty(builder, "list2", this.list2)
|
||||
appendProperty(builder, "set", this.set)
|
||||
appendProperty(builder, "set2", this.set2)
|
||||
appendProperty(builder, "map", this.map)
|
||||
appendProperty(builder, "map2", this.map2)
|
||||
appendProperty(builder, "container", this.container)
|
||||
appendProperty(builder, "container2", this.container2)
|
||||
appendProperty(builder, "other", this.other)
|
||||
appendProperty(builder, "regex", this.regex)
|
||||
appendProperty(builder, "any", this.any)
|
||||
appendProperty(builder, "nonNull", this.nonNull)
|
||||
appendProperty(builder, "enum", this.enum)
|
||||
builder.append("\n}")
|
||||
return builder.toString()
|
||||
}
|
||||
override fun toString(): String =
|
||||
"""PropertyTypes(boolean=$boolean, int=$int, float=$float, string=$string, duration=$duration, durationUnit=$durationUnit, dataSize=$dataSize, dataSizeUnit=$dataSizeUnit, nullable=$nullable, nullable2=$nullable2, pair=$pair, pair2=$pair2, coll=$coll, coll2=$coll2, list=$list, list2=$list2, set=$set, set2=$set2, map=$map, map2=$map2, container=$container, container2=$container2, other=$other, regex=$regex, any=$any, nonNull=$nonNull, enum=$enum)"""
|
||||
}
|
||||
|
||||
open class Other(
|
||||
@@ -214,13 +169,7 @@ object Mod {
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder(100)
|
||||
builder.append(Other::class.java.simpleName).append(" {")
|
||||
appendProperty(builder, "name", this.name)
|
||||
builder.append("\n}")
|
||||
return builder.toString()
|
||||
}
|
||||
override fun toString(): String = """Other(name=$name)"""
|
||||
}
|
||||
|
||||
enum class Direction(
|
||||
|
||||
Reference in New Issue
Block a user