diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt index 7c63be3d4a..73baaf8f01 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt @@ -249,7 +249,26 @@ internal open class ExtensionsCodeGeneratorImpl( return "${visibility}val$typeParameters $typeName.$name: $propertyType @JvmName(\"${renderStringLiteral(jvmName)}\") get() = $getter as $propertyType" } - protected fun generateExtensionProperties(marker: IsolatedMarker): Code { + /** + * nullable properties can be needed when *DECLARED* schema is referenced with nullability: + * ``` + * @DataSchema + * data class Schema(val i: Int) + * + * @DataSchema + * data class A( + * val prop: Schema? + * ) + * ``` + * When converted `listOf().toDataFrame(maxDepth=2)` actual schema is + * ``` + * prop: + * i: Int? + * ``` + * So this sudden `i: Int?` must be somehow handled. + * However, REPL code generator will not create such a situation. Nullable properties are not needed then + */ + protected fun generateExtensionProperties(marker: IsolatedMarker, withNullable: Boolean = true): Code { val markerName = marker.name val markerType = "$markerName${marker.typeArguments}" val visibility = renderTopLevelDeclarationVisibility(marker) @@ -278,7 +297,6 @@ internal open class ExtensionsCodeGeneratorImpl( declarations.addAll( listOf( - // non nullable generatePropertyCode( marker = marker, shortMarkerName = shortMarkerName, @@ -296,29 +314,33 @@ internal open class ExtensionsCodeGeneratorImpl( propertyType = fieldType, getter = getter, visibility = visibility, - ), - - // nullable - generatePropertyCode( - marker = marker, - shortMarkerName = nullableShortMarkerName, - typeName = nullableDfTypename, - name = name.quotedIfNeeded, - propertyType = nullableColumnType, - getter = getter, - visibility = visibility, - ), - generatePropertyCode( - marker = marker, - shortMarkerName = nullableShortMarkerName, - typeName = nullableRowTypename, - name = name.quotedIfNeeded, - propertyType = nullableFieldType, - getter = getter, - visibility = visibility, - ), + ) ) ) + if (withNullable) { + declarations.addAll( + listOf( + generatePropertyCode( + marker = marker, + shortMarkerName = nullableShortMarkerName, + typeName = nullableDfTypename, + name = name.quotedIfNeeded, + propertyType = nullableColumnType, + getter = getter, + visibility = visibility, + ), + generatePropertyCode( + marker = marker, + shortMarkerName = nullableShortMarkerName, + typeName = nullableRowTypename, + name = name.quotedIfNeeded, + propertyType = nullableFieldType, + getter = getter, + visibility = visibility, + ) + ) + ) + } } return declarations.joinToString("\n") } @@ -421,7 +443,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua context.generatedMarkers.forEach { itMarker -> declarations.add(generateInterface(itMarker, fields, readDfMethod.takeIf { marker == itMarker })) if (extensionProperties) { - declarations.add(generateExtensionProperties(itMarker)) + declarations.add(generateExtensionProperties(itMarker, withNullable = false)) } } val code = createCodeWithConverter(declarations.joinToString("\n\n"), marker.name) diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt index ed33a20f74..affb54991c 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt @@ -34,24 +34,33 @@ class CodeGenerationTests : BaseTest() { val stringName = String::class.simpleName!! val intName = Int::class.simpleName!! - fun expectedProperties(fullTypeName: String, shortTypeName: String) = """ - val $dfName<$fullTypeName>.age: $dataCol<$intName> @JvmName("${shortTypeName}_age") get() = this["age"] as $dataCol<$intName> - val $dfRowName<$fullTypeName>.age: $intName @JvmName("${shortTypeName}_age") get() = this["age"] as $intName - val $dfName<$fullTypeName?>.age: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $dataCol<$intName?> - val $dfRowName<$fullTypeName?>.age: $intName? @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $intName? - val $dfName<$fullTypeName>.city: $dataCol<$stringName?> @JvmName("${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$fullTypeName>.city: $stringName? @JvmName("${shortTypeName}_city") get() = this["city"] as $stringName? - val $dfName<$fullTypeName?>.city: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$fullTypeName?>.city: $stringName? @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $stringName? - val $dfName<$fullTypeName>.name: $dataCol<$stringName> @JvmName("${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName> - val $dfRowName<$fullTypeName>.name: $stringName @JvmName("${shortTypeName}_name") get() = this["name"] as $stringName - val $dfName<$fullTypeName?>.name: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName?> - val $dfRowName<$fullTypeName?>.name: $stringName? @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $stringName? - val $dfName<$fullTypeName>.weight: $dataCol<$intName?> @JvmName("${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$fullTypeName>.weight: $intName? @JvmName("${shortTypeName}_weight") get() = this["weight"] as $intName? - val $dfName<$fullTypeName?>.weight: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$fullTypeName?>.weight: $intName? @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $intName? - """.trimIndent() + fun expectedProperties(fullTypeName: String, shortTypeName: String, addNullable: Boolean = false) = buildString { + appendLine("""val $dfName<$fullTypeName>.age: $dataCol<$intName> @JvmName("${shortTypeName}_age") get() = this["age"] as $dataCol<$intName>""") + appendLine("""val $dfRowName<$fullTypeName>.age: $intName @JvmName("${shortTypeName}_age") get() = this["age"] as $intName""") + if (addNullable) { + appendLine("""val $dfName<$fullTypeName?>.age: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $dataCol<$intName?>""") + appendLine("""val $dfRowName<$fullTypeName?>.age: $intName? @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $intName?""") + } + appendLine("""val $dfName<$fullTypeName>.city: $dataCol<$stringName?> @JvmName("${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?>""") + appendLine("""val $dfRowName<$fullTypeName>.city: $stringName? @JvmName("${shortTypeName}_city") get() = this["city"] as $stringName?""") + if (addNullable) { + appendLine("""val $dfName<$fullTypeName?>.city: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?>""") + appendLine("""val $dfRowName<$fullTypeName?>.city: $stringName? @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $stringName?""") + } + appendLine("""val $dfName<$fullTypeName>.name: $dataCol<$stringName> @JvmName("${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName>""") + appendLine("""val $dfRowName<$fullTypeName>.name: $stringName @JvmName("${shortTypeName}_name") get() = this["name"] as $stringName""") + if (addNullable) { + appendLine("""val $dfName<$fullTypeName?>.name: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName?>""") + appendLine("""val $dfRowName<$fullTypeName?>.name: $stringName? @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $stringName?""") + } + appendLine("""val $dfName<$fullTypeName>.weight: $dataCol<$intName?> @JvmName("${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?>""") + append("""val $dfRowName<$fullTypeName>.weight: $intName? @JvmName("${shortTypeName}_weight") get() = this["weight"] as $intName?""") + if (addNullable) { + appendLine("") + appendLine("""val $dfName<$fullTypeName?>.weight: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?>""") + append("""val $dfRowName<$fullTypeName?>.weight: $intName? @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $intName?""") + } + } @Test fun `generate marker interface`() { @@ -108,12 +117,8 @@ class CodeGenerationTests : BaseTest() { val $dfName<$type1>.city: $dataCol<$stringName?> @JvmName("${type1}_city") get() = this["city"] as $dataCol<$stringName?> val $dfRowName<$type1>.city: $stringName? @JvmName("${type1}_city") get() = this["city"] as $stringName? - val $dfName<$type1?>.city: $dataCol<$stringName?> @JvmName("Nullable${type1}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$type1?>.city: $stringName? @JvmName("Nullable${type1}_city") get() = this["city"] as $stringName? val $dfName<$type1>.name: $dataCol<$stringName> @JvmName("${type1}_name") get() = this["name"] as $dataCol<$stringName> val $dfRowName<$type1>.name: $stringName @JvmName("${type1}_name") get() = this["name"] as $stringName - val $dfName<$type1?>.name: $dataCol<$stringName?> @JvmName("Nullable${type1}_name") get() = this["name"] as $dataCol<$stringName?> - val $dfRowName<$type1?>.name: $stringName? @JvmName("Nullable${type1}_name") get() = this["name"] as $stringName? """.trimIndent() @@ -123,16 +128,10 @@ class CodeGenerationTests : BaseTest() { val $dfName<$type2>.age: $dataCol<$intName> @JvmName("${type2}_age") get() = this["age"] as $dataCol<$intName> val $dfRowName<$type2>.age: $intName @JvmName("${type2}_age") get() = this["age"] as $intName - val $dfName<$type2?>.age: $dataCol<$intName?> @JvmName("Nullable${type2}_age") get() = this["age"] as $dataCol<$intName?> - val $dfRowName<$type2?>.age: $intName? @JvmName("Nullable${type2}_age") get() = this["age"] as $intName? val $dfName<$type2>.nameAndCity: $colGroup<$type1> @JvmName("${type2}_nameAndCity") get() = this["nameAndCity"] as $colGroup<$type1> val $dfRowName<$type2>.nameAndCity: $dataRow<$type1> @JvmName("${type2}_nameAndCity") get() = this["nameAndCity"] as $dataRow<$type1> - val $dfName<$type2?>.nameAndCity: $colGroup<$type1?> @JvmName("Nullable${type2}_nameAndCity") get() = this["nameAndCity"] as $colGroup<$type1?> - val $dfRowName<$type2?>.nameAndCity: $dataRow<$type1?> @JvmName("Nullable${type2}_nameAndCity") get() = this["nameAndCity"] as $dataRow<$type1?> val $dfName<$type2>.weight: $dataCol<$intName?> @JvmName("${type2}_weight") get() = this["weight"] as $dataCol<$intName?> val $dfRowName<$type2>.weight: $intName? @JvmName("${type2}_weight") get() = this["weight"] as $intName? - val $dfName<$type2?>.weight: $dataCol<$intName?> @JvmName("Nullable${type2}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$type2?>.weight: $intName? @JvmName("Nullable${type2}_weight") get() = this["weight"] as $intName? """.trimIndent() val expectedConverter = "it.cast<$type2>()" @@ -147,7 +146,7 @@ class CodeGenerationTests : BaseTest() { val expected = """ @DataSchema interface $personClass { } - """.trimIndent() + "\n" + expectedProperties(personClassName, personShortName) + """.trimIndent() + "\n" + expectedProperties(personClassName, personShortName, addNullable = true) val code = CodeGenerator.create(useFqNames = false) .generate(InterfaceGenerationMode.NoFields, extensionProperties = true).declarations @@ -187,12 +186,8 @@ class CodeGenerationTests : BaseTest() { val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("ValidPerson_city") get() = this["city"] as $packageName.DataColumn val $packageName.DataRow.city: kotlin.String @JvmName("ValidPerson_city") get() = this["city"] as kotlin.String - val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("NullableValidPerson_city") get() = this["city"] as $packageName.DataColumn - val $packageName.DataRow.city: kotlin.String? @JvmName("NullableValidPerson_city") get() = this["city"] as kotlin.String? val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("ValidPerson_weight") get() = this["weight"] as $packageName.DataColumn val $packageName.DataRow.weight: kotlin.Int @JvmName("ValidPerson_weight") get() = this["weight"] as kotlin.Int - val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("NullableValidPerson_weight") get() = this["weight"] as $packageName.DataColumn - val $packageName.DataRow.weight: kotlin.Int? @JvmName("NullableValidPerson_weight") get() = this["weight"] as kotlin.Int? """.trimIndent() code shouldBe expected } @@ -241,20 +236,12 @@ class CodeGenerationTests : BaseTest() { internal val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("DataType_age") get() = this["age"] as $packageName.DataColumn internal val $packageName.DataRow.age: kotlin.Int @JvmName("DataType_age") get() = this["age"] as kotlin.Int - internal val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("NullableDataType_age") get() = this["age"] as $packageName.DataColumn - internal val $packageName.DataRow.age: kotlin.Int? @JvmName("NullableDataType_age") get() = this["age"] as kotlin.Int? internal val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("DataType_city") get() = this["city"] as $packageName.DataColumn internal val $packageName.DataRow.city: kotlin.String? @JvmName("DataType_city") get() = this["city"] as kotlin.String? - internal val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("NullableDataType_city") get() = this["city"] as $packageName.DataColumn - internal val $packageName.DataRow.city: kotlin.String? @JvmName("NullableDataType_city") get() = this["city"] as kotlin.String? internal val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("DataType_name") get() = this["name"] as $packageName.DataColumn internal val $packageName.DataRow.name: kotlin.String @JvmName("DataType_name") get() = this["name"] as kotlin.String - internal val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("NullableDataType_name") get() = this["name"] as $packageName.DataColumn - internal val $packageName.DataRow.name: kotlin.String? @JvmName("NullableDataType_name") get() = this["name"] as kotlin.String? internal val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("DataType_weight") get() = this["weight"] as $packageName.DataColumn internal val $packageName.DataRow.weight: kotlin.Int? @JvmName("DataType_weight") get() = this["weight"] as kotlin.Int? - internal val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("NullableDataType_weight") get() = this["weight"] as $packageName.DataColumn - internal val $packageName.DataRow.weight: kotlin.Int? @JvmName("NullableDataType_weight") get() = this["weight"] as kotlin.Int? """.trimIndent() } @@ -281,20 +268,12 @@ class CodeGenerationTests : BaseTest() { public val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("DataType_age") get() = this["age"] as $packageName.DataColumn public val $packageName.DataRow.age: kotlin.Int @JvmName("DataType_age") get() = this["age"] as kotlin.Int - public val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("NullableDataType_age") get() = this["age"] as $packageName.DataColumn - public val $packageName.DataRow.age: kotlin.Int? @JvmName("NullableDataType_age") get() = this["age"] as kotlin.Int? public val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("DataType_city") get() = this["city"] as $packageName.DataColumn public val $packageName.DataRow.city: kotlin.String? @JvmName("DataType_city") get() = this["city"] as kotlin.String? - public val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("NullableDataType_city") get() = this["city"] as $packageName.DataColumn - public val $packageName.DataRow.city: kotlin.String? @JvmName("NullableDataType_city") get() = this["city"] as kotlin.String? public val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("DataType_name") get() = this["name"] as $packageName.DataColumn public val $packageName.DataRow.name: kotlin.String @JvmName("DataType_name") get() = this["name"] as kotlin.String - public val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("NullableDataType_name") get() = this["name"] as $packageName.DataColumn - public val $packageName.DataRow.name: kotlin.String? @JvmName("NullableDataType_name") get() = this["name"] as kotlin.String? public val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("DataType_weight") get() = this["weight"] as $packageName.DataColumn public val $packageName.DataRow.weight: kotlin.Int? @JvmName("DataType_weight") get() = this["weight"] as kotlin.Int? - public val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("NullableDataType_weight") get() = this["weight"] as $packageName.DataColumn - public val $packageName.DataRow.weight: kotlin.Int? @JvmName("NullableDataType_weight") get() = this["weight"] as kotlin.Int? """.trimIndent() } @@ -305,7 +284,7 @@ class CodeGenerationTests : BaseTest() { val declarations = repl.generate(df.schema(), "DataType", false, true, false).code.declarations df.columnNames().forEach { val matches = "`$it`".toRegex().findAll(declarations).toList() - matches.size shouldBe 4 + matches.size shouldBe 2 } } diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt index 9c8983835b..a63363935e 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt @@ -79,20 +79,12 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker>.age: $dataCol<$intName> @JvmName("${marker}_age") get() = this["age"] as $dataCol<$intName> val $dfRowName<$marker>.age: $intName @JvmName("${marker}_age") get() = this["age"] as $intName - val $dfName<$marker?>.age: $dataCol<$intName?> @JvmName("Nullable${marker}_age") get() = this["age"] as $dataCol<$intName?> - val $dfRowName<$marker?>.age: $intName? @JvmName("Nullable${marker}_age") get() = this["age"] as $intName? val $dfName<$marker>.city: $dataCol<$stringName?> @JvmName("${marker}_city") get() = this["city"] as $dataCol<$stringName?> val $dfRowName<$marker>.city: $stringName? @JvmName("${marker}_city") get() = this["city"] as $stringName? - val $dfName<$marker?>.city: $dataCol<$stringName?> @JvmName("Nullable${marker}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$marker?>.city: $stringName? @JvmName("Nullable${marker}_city") get() = this["city"] as $stringName? val $dfName<$marker>.name: $dataCol<$stringName> @JvmName("${marker}_name") get() = this["name"] as $dataCol<$stringName> val $dfRowName<$marker>.name: $stringName @JvmName("${marker}_name") get() = this["name"] as $stringName - val $dfName<$marker?>.name: $dataCol<$stringName?> @JvmName("Nullable${marker}_name") get() = this["name"] as $dataCol<$stringName?> - val $dfRowName<$marker?>.name: $stringName? @JvmName("Nullable${marker}_name") get() = this["name"] as $stringName? val $dfName<$marker>.weight: $dataCol<$intName?> @JvmName("${marker}_weight") get() = this["weight"] as $dataCol<$intName?> val $dfRowName<$marker>.weight: $intName? @JvmName("${marker}_weight") get() = this["weight"] as $intName? - val $dfName<$marker?>.weight: $dataCol<$intName?> @JvmName("Nullable${marker}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$marker?>.weight: $intName? @JvmName("Nullable${marker}_weight") get() = this["weight"] as $intName? """.trimIndent() code shouldBe expected @@ -108,8 +100,6 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker3>.city: $dataCol<$stringName> @JvmName("${marker3}_city") get() = this["city"] as $dataCol<$stringName> val $dfRowName<$marker3>.city: $stringName @JvmName("${marker3}_city") get() = this["city"] as $stringName - val $dfName<$marker3?>.city: $dataCol<$stringName?> @JvmName("Nullable${marker3}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$marker3?>.city: $stringName? @JvmName("Nullable${marker3}_city") get() = this["city"] as $stringName? """.trimIndent() code3 shouldBe expected3 @@ -126,8 +116,6 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker5>.weight: $dataCol<$intName> @JvmName("${marker5}_weight") get() = this["weight"] as $dataCol<$intName> val $dfRowName<$marker5>.weight: $intName @JvmName("${marker5}_weight") get() = this["weight"] as $intName - val $dfName<$marker5?>.weight: $dataCol<$intName?> @JvmName("Nullable${marker5}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$marker5?>.weight: $intName? @JvmName("Nullable${marker5}_weight") get() = this["weight"] as $intName? """.trimIndent() code5 shouldBe expected5 @@ -168,12 +156,8 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker>.city: $dataCol<$stringName?> @JvmName("${marker}_city") get() = this["city"] as $dataCol<$stringName?> val $dfRowName<$marker>.city: $stringName? @JvmName("${marker}_city") get() = this["city"] as $stringName? - val $dfName<$marker?>.city: $dataCol<$stringName?> @JvmName("Nullable${marker}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$marker?>.city: $stringName? @JvmName("Nullable${marker}_city") get() = this["city"] as $stringName? val $dfName<$marker>.weight: $dataCol<$intName?> @JvmName("${marker}_weight") get() = this["weight"] as $dataCol<$intName?> val $dfRowName<$marker>.weight: $intName? @JvmName("${marker}_weight") get() = this["weight"] as $intName? - val $dfName<$marker?>.weight: $dataCol<$intName?> @JvmName("Nullable${marker}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$marker?>.weight: $intName? @JvmName("Nullable${marker}_weight") get() = this["weight"] as $intName? """.trimIndent() val code = repl.process(typed).declarations.trimIndent() diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt index 7c63be3d4a..73baaf8f01 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt @@ -249,7 +249,26 @@ internal open class ExtensionsCodeGeneratorImpl( return "${visibility}val$typeParameters $typeName.$name: $propertyType @JvmName(\"${renderStringLiteral(jvmName)}\") get() = $getter as $propertyType" } - protected fun generateExtensionProperties(marker: IsolatedMarker): Code { + /** + * nullable properties can be needed when *DECLARED* schema is referenced with nullability: + * ``` + * @DataSchema + * data class Schema(val i: Int) + * + * @DataSchema + * data class A( + * val prop: Schema? + * ) + * ``` + * When converted `listOf().toDataFrame(maxDepth=2)` actual schema is + * ``` + * prop: + * i: Int? + * ``` + * So this sudden `i: Int?` must be somehow handled. + * However, REPL code generator will not create such a situation. Nullable properties are not needed then + */ + protected fun generateExtensionProperties(marker: IsolatedMarker, withNullable: Boolean = true): Code { val markerName = marker.name val markerType = "$markerName${marker.typeArguments}" val visibility = renderTopLevelDeclarationVisibility(marker) @@ -278,7 +297,6 @@ internal open class ExtensionsCodeGeneratorImpl( declarations.addAll( listOf( - // non nullable generatePropertyCode( marker = marker, shortMarkerName = shortMarkerName, @@ -296,29 +314,33 @@ internal open class ExtensionsCodeGeneratorImpl( propertyType = fieldType, getter = getter, visibility = visibility, - ), - - // nullable - generatePropertyCode( - marker = marker, - shortMarkerName = nullableShortMarkerName, - typeName = nullableDfTypename, - name = name.quotedIfNeeded, - propertyType = nullableColumnType, - getter = getter, - visibility = visibility, - ), - generatePropertyCode( - marker = marker, - shortMarkerName = nullableShortMarkerName, - typeName = nullableRowTypename, - name = name.quotedIfNeeded, - propertyType = nullableFieldType, - getter = getter, - visibility = visibility, - ), + ) ) ) + if (withNullable) { + declarations.addAll( + listOf( + generatePropertyCode( + marker = marker, + shortMarkerName = nullableShortMarkerName, + typeName = nullableDfTypename, + name = name.quotedIfNeeded, + propertyType = nullableColumnType, + getter = getter, + visibility = visibility, + ), + generatePropertyCode( + marker = marker, + shortMarkerName = nullableShortMarkerName, + typeName = nullableRowTypename, + name = name.quotedIfNeeded, + propertyType = nullableFieldType, + getter = getter, + visibility = visibility, + ) + ) + ) + } } return declarations.joinToString("\n") } @@ -421,7 +443,7 @@ internal class CodeGeneratorImpl(typeRendering: TypeRenderingStrategy = FullyQua context.generatedMarkers.forEach { itMarker -> declarations.add(generateInterface(itMarker, fields, readDfMethod.takeIf { marker == itMarker })) if (extensionProperties) { - declarations.add(generateExtensionProperties(itMarker)) + declarations.add(generateExtensionProperties(itMarker, withNullable = false)) } } val code = createCodeWithConverter(declarations.joinToString("\n\n"), marker.name) diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt index ed33a20f74..affb54991c 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/CodeGenerationTests.kt @@ -34,24 +34,33 @@ class CodeGenerationTests : BaseTest() { val stringName = String::class.simpleName!! val intName = Int::class.simpleName!! - fun expectedProperties(fullTypeName: String, shortTypeName: String) = """ - val $dfName<$fullTypeName>.age: $dataCol<$intName> @JvmName("${shortTypeName}_age") get() = this["age"] as $dataCol<$intName> - val $dfRowName<$fullTypeName>.age: $intName @JvmName("${shortTypeName}_age") get() = this["age"] as $intName - val $dfName<$fullTypeName?>.age: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $dataCol<$intName?> - val $dfRowName<$fullTypeName?>.age: $intName? @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $intName? - val $dfName<$fullTypeName>.city: $dataCol<$stringName?> @JvmName("${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$fullTypeName>.city: $stringName? @JvmName("${shortTypeName}_city") get() = this["city"] as $stringName? - val $dfName<$fullTypeName?>.city: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$fullTypeName?>.city: $stringName? @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $stringName? - val $dfName<$fullTypeName>.name: $dataCol<$stringName> @JvmName("${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName> - val $dfRowName<$fullTypeName>.name: $stringName @JvmName("${shortTypeName}_name") get() = this["name"] as $stringName - val $dfName<$fullTypeName?>.name: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName?> - val $dfRowName<$fullTypeName?>.name: $stringName? @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $stringName? - val $dfName<$fullTypeName>.weight: $dataCol<$intName?> @JvmName("${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$fullTypeName>.weight: $intName? @JvmName("${shortTypeName}_weight") get() = this["weight"] as $intName? - val $dfName<$fullTypeName?>.weight: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$fullTypeName?>.weight: $intName? @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $intName? - """.trimIndent() + fun expectedProperties(fullTypeName: String, shortTypeName: String, addNullable: Boolean = false) = buildString { + appendLine("""val $dfName<$fullTypeName>.age: $dataCol<$intName> @JvmName("${shortTypeName}_age") get() = this["age"] as $dataCol<$intName>""") + appendLine("""val $dfRowName<$fullTypeName>.age: $intName @JvmName("${shortTypeName}_age") get() = this["age"] as $intName""") + if (addNullable) { + appendLine("""val $dfName<$fullTypeName?>.age: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $dataCol<$intName?>""") + appendLine("""val $dfRowName<$fullTypeName?>.age: $intName? @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $intName?""") + } + appendLine("""val $dfName<$fullTypeName>.city: $dataCol<$stringName?> @JvmName("${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?>""") + appendLine("""val $dfRowName<$fullTypeName>.city: $stringName? @JvmName("${shortTypeName}_city") get() = this["city"] as $stringName?""") + if (addNullable) { + appendLine("""val $dfName<$fullTypeName?>.city: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?>""") + appendLine("""val $dfRowName<$fullTypeName?>.city: $stringName? @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $stringName?""") + } + appendLine("""val $dfName<$fullTypeName>.name: $dataCol<$stringName> @JvmName("${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName>""") + appendLine("""val $dfRowName<$fullTypeName>.name: $stringName @JvmName("${shortTypeName}_name") get() = this["name"] as $stringName""") + if (addNullable) { + appendLine("""val $dfName<$fullTypeName?>.name: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName?>""") + appendLine("""val $dfRowName<$fullTypeName?>.name: $stringName? @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $stringName?""") + } + appendLine("""val $dfName<$fullTypeName>.weight: $dataCol<$intName?> @JvmName("${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?>""") + append("""val $dfRowName<$fullTypeName>.weight: $intName? @JvmName("${shortTypeName}_weight") get() = this["weight"] as $intName?""") + if (addNullable) { + appendLine("") + appendLine("""val $dfName<$fullTypeName?>.weight: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?>""") + append("""val $dfRowName<$fullTypeName?>.weight: $intName? @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $intName?""") + } + } @Test fun `generate marker interface`() { @@ -108,12 +117,8 @@ class CodeGenerationTests : BaseTest() { val $dfName<$type1>.city: $dataCol<$stringName?> @JvmName("${type1}_city") get() = this["city"] as $dataCol<$stringName?> val $dfRowName<$type1>.city: $stringName? @JvmName("${type1}_city") get() = this["city"] as $stringName? - val $dfName<$type1?>.city: $dataCol<$stringName?> @JvmName("Nullable${type1}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$type1?>.city: $stringName? @JvmName("Nullable${type1}_city") get() = this["city"] as $stringName? val $dfName<$type1>.name: $dataCol<$stringName> @JvmName("${type1}_name") get() = this["name"] as $dataCol<$stringName> val $dfRowName<$type1>.name: $stringName @JvmName("${type1}_name") get() = this["name"] as $stringName - val $dfName<$type1?>.name: $dataCol<$stringName?> @JvmName("Nullable${type1}_name") get() = this["name"] as $dataCol<$stringName?> - val $dfRowName<$type1?>.name: $stringName? @JvmName("Nullable${type1}_name") get() = this["name"] as $stringName? """.trimIndent() @@ -123,16 +128,10 @@ class CodeGenerationTests : BaseTest() { val $dfName<$type2>.age: $dataCol<$intName> @JvmName("${type2}_age") get() = this["age"] as $dataCol<$intName> val $dfRowName<$type2>.age: $intName @JvmName("${type2}_age") get() = this["age"] as $intName - val $dfName<$type2?>.age: $dataCol<$intName?> @JvmName("Nullable${type2}_age") get() = this["age"] as $dataCol<$intName?> - val $dfRowName<$type2?>.age: $intName? @JvmName("Nullable${type2}_age") get() = this["age"] as $intName? val $dfName<$type2>.nameAndCity: $colGroup<$type1> @JvmName("${type2}_nameAndCity") get() = this["nameAndCity"] as $colGroup<$type1> val $dfRowName<$type2>.nameAndCity: $dataRow<$type1> @JvmName("${type2}_nameAndCity") get() = this["nameAndCity"] as $dataRow<$type1> - val $dfName<$type2?>.nameAndCity: $colGroup<$type1?> @JvmName("Nullable${type2}_nameAndCity") get() = this["nameAndCity"] as $colGroup<$type1?> - val $dfRowName<$type2?>.nameAndCity: $dataRow<$type1?> @JvmName("Nullable${type2}_nameAndCity") get() = this["nameAndCity"] as $dataRow<$type1?> val $dfName<$type2>.weight: $dataCol<$intName?> @JvmName("${type2}_weight") get() = this["weight"] as $dataCol<$intName?> val $dfRowName<$type2>.weight: $intName? @JvmName("${type2}_weight") get() = this["weight"] as $intName? - val $dfName<$type2?>.weight: $dataCol<$intName?> @JvmName("Nullable${type2}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$type2?>.weight: $intName? @JvmName("Nullable${type2}_weight") get() = this["weight"] as $intName? """.trimIndent() val expectedConverter = "it.cast<$type2>()" @@ -147,7 +146,7 @@ class CodeGenerationTests : BaseTest() { val expected = """ @DataSchema interface $personClass { } - """.trimIndent() + "\n" + expectedProperties(personClassName, personShortName) + """.trimIndent() + "\n" + expectedProperties(personClassName, personShortName, addNullable = true) val code = CodeGenerator.create(useFqNames = false) .generate(InterfaceGenerationMode.NoFields, extensionProperties = true).declarations @@ -187,12 +186,8 @@ class CodeGenerationTests : BaseTest() { val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("ValidPerson_city") get() = this["city"] as $packageName.DataColumn val $packageName.DataRow.city: kotlin.String @JvmName("ValidPerson_city") get() = this["city"] as kotlin.String - val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("NullableValidPerson_city") get() = this["city"] as $packageName.DataColumn - val $packageName.DataRow.city: kotlin.String? @JvmName("NullableValidPerson_city") get() = this["city"] as kotlin.String? val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("ValidPerson_weight") get() = this["weight"] as $packageName.DataColumn val $packageName.DataRow.weight: kotlin.Int @JvmName("ValidPerson_weight") get() = this["weight"] as kotlin.Int - val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("NullableValidPerson_weight") get() = this["weight"] as $packageName.DataColumn - val $packageName.DataRow.weight: kotlin.Int? @JvmName("NullableValidPerson_weight") get() = this["weight"] as kotlin.Int? """.trimIndent() code shouldBe expected } @@ -241,20 +236,12 @@ class CodeGenerationTests : BaseTest() { internal val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("DataType_age") get() = this["age"] as $packageName.DataColumn internal val $packageName.DataRow.age: kotlin.Int @JvmName("DataType_age") get() = this["age"] as kotlin.Int - internal val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("NullableDataType_age") get() = this["age"] as $packageName.DataColumn - internal val $packageName.DataRow.age: kotlin.Int? @JvmName("NullableDataType_age") get() = this["age"] as kotlin.Int? internal val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("DataType_city") get() = this["city"] as $packageName.DataColumn internal val $packageName.DataRow.city: kotlin.String? @JvmName("DataType_city") get() = this["city"] as kotlin.String? - internal val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("NullableDataType_city") get() = this["city"] as $packageName.DataColumn - internal val $packageName.DataRow.city: kotlin.String? @JvmName("NullableDataType_city") get() = this["city"] as kotlin.String? internal val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("DataType_name") get() = this["name"] as $packageName.DataColumn internal val $packageName.DataRow.name: kotlin.String @JvmName("DataType_name") get() = this["name"] as kotlin.String - internal val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("NullableDataType_name") get() = this["name"] as $packageName.DataColumn - internal val $packageName.DataRow.name: kotlin.String? @JvmName("NullableDataType_name") get() = this["name"] as kotlin.String? internal val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("DataType_weight") get() = this["weight"] as $packageName.DataColumn internal val $packageName.DataRow.weight: kotlin.Int? @JvmName("DataType_weight") get() = this["weight"] as kotlin.Int? - internal val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("NullableDataType_weight") get() = this["weight"] as $packageName.DataColumn - internal val $packageName.DataRow.weight: kotlin.Int? @JvmName("NullableDataType_weight") get() = this["weight"] as kotlin.Int? """.trimIndent() } @@ -281,20 +268,12 @@ class CodeGenerationTests : BaseTest() { public val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("DataType_age") get() = this["age"] as $packageName.DataColumn public val $packageName.DataRow.age: kotlin.Int @JvmName("DataType_age") get() = this["age"] as kotlin.Int - public val $packageName.ColumnsContainer.age: $packageName.DataColumn @JvmName("NullableDataType_age") get() = this["age"] as $packageName.DataColumn - public val $packageName.DataRow.age: kotlin.Int? @JvmName("NullableDataType_age") get() = this["age"] as kotlin.Int? public val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("DataType_city") get() = this["city"] as $packageName.DataColumn public val $packageName.DataRow.city: kotlin.String? @JvmName("DataType_city") get() = this["city"] as kotlin.String? - public val $packageName.ColumnsContainer.city: $packageName.DataColumn @JvmName("NullableDataType_city") get() = this["city"] as $packageName.DataColumn - public val $packageName.DataRow.city: kotlin.String? @JvmName("NullableDataType_city") get() = this["city"] as kotlin.String? public val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("DataType_name") get() = this["name"] as $packageName.DataColumn public val $packageName.DataRow.name: kotlin.String @JvmName("DataType_name") get() = this["name"] as kotlin.String - public val $packageName.ColumnsContainer.name: $packageName.DataColumn @JvmName("NullableDataType_name") get() = this["name"] as $packageName.DataColumn - public val $packageName.DataRow.name: kotlin.String? @JvmName("NullableDataType_name") get() = this["name"] as kotlin.String? public val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("DataType_weight") get() = this["weight"] as $packageName.DataColumn public val $packageName.DataRow.weight: kotlin.Int? @JvmName("DataType_weight") get() = this["weight"] as kotlin.Int? - public val $packageName.ColumnsContainer.weight: $packageName.DataColumn @JvmName("NullableDataType_weight") get() = this["weight"] as $packageName.DataColumn - public val $packageName.DataRow.weight: kotlin.Int? @JvmName("NullableDataType_weight") get() = this["weight"] as kotlin.Int? """.trimIndent() } @@ -305,7 +284,7 @@ class CodeGenerationTests : BaseTest() { val declarations = repl.generate(df.schema(), "DataType", false, true, false).code.declarations df.columnNames().forEach { val matches = "`$it`".toRegex().findAll(declarations).toList() - matches.size shouldBe 4 + matches.size shouldBe 2 } } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt index 9c8983835b..a63363935e 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ReplCodeGenTests.kt @@ -79,20 +79,12 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker>.age: $dataCol<$intName> @JvmName("${marker}_age") get() = this["age"] as $dataCol<$intName> val $dfRowName<$marker>.age: $intName @JvmName("${marker}_age") get() = this["age"] as $intName - val $dfName<$marker?>.age: $dataCol<$intName?> @JvmName("Nullable${marker}_age") get() = this["age"] as $dataCol<$intName?> - val $dfRowName<$marker?>.age: $intName? @JvmName("Nullable${marker}_age") get() = this["age"] as $intName? val $dfName<$marker>.city: $dataCol<$stringName?> @JvmName("${marker}_city") get() = this["city"] as $dataCol<$stringName?> val $dfRowName<$marker>.city: $stringName? @JvmName("${marker}_city") get() = this["city"] as $stringName? - val $dfName<$marker?>.city: $dataCol<$stringName?> @JvmName("Nullable${marker}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$marker?>.city: $stringName? @JvmName("Nullable${marker}_city") get() = this["city"] as $stringName? val $dfName<$marker>.name: $dataCol<$stringName> @JvmName("${marker}_name") get() = this["name"] as $dataCol<$stringName> val $dfRowName<$marker>.name: $stringName @JvmName("${marker}_name") get() = this["name"] as $stringName - val $dfName<$marker?>.name: $dataCol<$stringName?> @JvmName("Nullable${marker}_name") get() = this["name"] as $dataCol<$stringName?> - val $dfRowName<$marker?>.name: $stringName? @JvmName("Nullable${marker}_name") get() = this["name"] as $stringName? val $dfName<$marker>.weight: $dataCol<$intName?> @JvmName("${marker}_weight") get() = this["weight"] as $dataCol<$intName?> val $dfRowName<$marker>.weight: $intName? @JvmName("${marker}_weight") get() = this["weight"] as $intName? - val $dfName<$marker?>.weight: $dataCol<$intName?> @JvmName("Nullable${marker}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$marker?>.weight: $intName? @JvmName("Nullable${marker}_weight") get() = this["weight"] as $intName? """.trimIndent() code shouldBe expected @@ -108,8 +100,6 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker3>.city: $dataCol<$stringName> @JvmName("${marker3}_city") get() = this["city"] as $dataCol<$stringName> val $dfRowName<$marker3>.city: $stringName @JvmName("${marker3}_city") get() = this["city"] as $stringName - val $dfName<$marker3?>.city: $dataCol<$stringName?> @JvmName("Nullable${marker3}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$marker3?>.city: $stringName? @JvmName("Nullable${marker3}_city") get() = this["city"] as $stringName? """.trimIndent() code3 shouldBe expected3 @@ -126,8 +116,6 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker5>.weight: $dataCol<$intName> @JvmName("${marker5}_weight") get() = this["weight"] as $dataCol<$intName> val $dfRowName<$marker5>.weight: $intName @JvmName("${marker5}_weight") get() = this["weight"] as $intName - val $dfName<$marker5?>.weight: $dataCol<$intName?> @JvmName("Nullable${marker5}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$marker5?>.weight: $intName? @JvmName("Nullable${marker5}_weight") get() = this["weight"] as $intName? """.trimIndent() code5 shouldBe expected5 @@ -168,12 +156,8 @@ class ReplCodeGenTests : BaseTest() { val $dfName<$marker>.city: $dataCol<$stringName?> @JvmName("${marker}_city") get() = this["city"] as $dataCol<$stringName?> val $dfRowName<$marker>.city: $stringName? @JvmName("${marker}_city") get() = this["city"] as $stringName? - val $dfName<$marker?>.city: $dataCol<$stringName?> @JvmName("Nullable${marker}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$marker?>.city: $stringName? @JvmName("Nullable${marker}_city") get() = this["city"] as $stringName? val $dfName<$marker>.weight: $dataCol<$intName?> @JvmName("${marker}_weight") get() = this["weight"] as $dataCol<$intName?> val $dfRowName<$marker>.weight: $intName? @JvmName("${marker}_weight") get() = this["weight"] as $intName? - val $dfName<$marker?>.weight: $dataCol<$intName?> @JvmName("Nullable${marker}_weight") get() = this["weight"] as $dataCol<$intName?> - val $dfRowName<$marker?>.weight: $intName? @JvmName("Nullable${marker}_weight") get() = this["weight"] as $intName? """.trimIndent() val code = repl.process(typed).declarations.trimIndent()