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 a9b0e94b73..8309cf5237 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 @@ -274,6 +274,39 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR private fun String.removeQuotes() = this.removeSurrounding("`") + private val troubleshootingLink = "" + + /** + * Generate a try-catch block for column accessor with custom error messages. + * + * Catch any exception. Throws an [IllegalStateException] with a special message and original exception. + * Can be improved with custom exception (#1872). + * + * 1) IllegalArgumentException -> most probably column not found. Should be replaced with a custom exception (#1871) + * 2) ClassCastException -> most probably incorrect column type. Should be replaced with a custom exception (#1871) + * 3) else -> unexpected exception. + */ + private fun generateTryCatchColumnAccess(columnAccessCode: String, columnName: String): String { + val renderedColumnName = renderStringLiteral(columnName) + return $$""" + try { + $$columnAccessCode + } catch (e: kotlin.Exception) { + val msg = when (e) { + is kotlin.IllegalArgumentException -> + "Column not found exception in the generated DataFrame extension property '$$renderedColumnName': ${e.localizedMessage}. See $$troubleshootingLink for more information." + + is kotlin.ClassCastException -> + "Incorrect column type exception in generated DataFrame extension property '$$renderedColumnName': ${e.localizedMessage}. See $$troubleshootingLink for more information." + + else -> + "Unexpected exception in generated DataFrame extension property '$$renderedColumnName'. Please report it to https://github.com/Kotlin/dataframe/issues. Exception message: $e." + } + throw IllegalStateException(msg, e) + } + """.trimIndent() + } + private fun generatePropertyCode( marker: IsolatedMarker, shortMarkerName: String, @@ -282,6 +315,7 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR propertyType: String, getter: String, visibility: String, + columnName: String, ): String { // jvm name is required to prevent signature clash like this: // val DataRow.name: String @@ -296,7 +330,7 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR } return "${visibility}val$typeParameters $typeName.$name: $propertyType @JvmName(\"${ renderStringLiteral(jvmName) - }\") get() = $getter as $propertyType" + }\") get() = ${generateTryCatchColumnAccess("$getter as $propertyType", columnName)} " } /** @@ -355,6 +389,7 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR propertyType = columnType, getter = getter, visibility = visibility, + columnName = it.columnName, ), generatePropertyCode( marker = marker, @@ -364,6 +399,7 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR propertyType = fieldType, getter = getter, visibility = visibility, + columnName = it.columnName, ), ), ) @@ -378,6 +414,7 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR propertyType = nullableColumnType, getter = getter, visibility = visibility, + columnName = it.columnName, ), generatePropertyCode( marker = marker, @@ -387,6 +424,7 @@ internal open class ExtensionsCodeGeneratorImpl(private val typeRendering: TypeR propertyType = nullableFieldType, getter = getter, visibility = visibility, + columnName = it.columnName, ), ), ) 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 cdf62667f6..e9a850c602 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 @@ -225,60 +225,125 @@ class CodeGenerationTests : BaseTest() { 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>""", + expectedExtensionProperty( + "$dfName<$fullTypeName>", + "age", + "$dataCol<$intName>", + "${shortTypeName}_age", + ), ) appendLine( - """val $dfRowName<$fullTypeName>.age: $intName @JvmName("${shortTypeName}_age") get() = this["age"] as $intName""", + expectedExtensionProperty("$dfRowName<$fullTypeName>", "age", intName, "${shortTypeName}_age"), ) if (addNullable) { appendLine( - """val $dfName<$fullTypeName?>.age: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $dataCol<$intName?>""", + expectedExtensionProperty( + "$dfName<$fullTypeName?>", + "age", + "$dataCol<$intName?>", + "Nullable${shortTypeName}_age", + ), ) appendLine( - """val $dfRowName<$fullTypeName?>.age: $intName? @JvmName("Nullable${shortTypeName}_age") get() = this["age"] as $intName?""", + expectedExtensionProperty( + "$dfRowName<$fullTypeName?>", + "age", + "$intName?", + "Nullable${shortTypeName}_age", + ), ) } appendLine( - """val $dfName<$fullTypeName>.city: $dataCol<$stringName?> @JvmName("${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?>""", + expectedExtensionProperty( + "$dfName<$fullTypeName>", + "city", + "$dataCol<$stringName?>", + "${shortTypeName}_city", + ), ) appendLine( - """val $dfRowName<$fullTypeName>.city: $stringName? @JvmName("${shortTypeName}_city") get() = this["city"] as $stringName?""", + expectedExtensionProperty("$dfRowName<$fullTypeName>", "city", "$stringName?", "${shortTypeName}_city"), ) if (addNullable) { appendLine( - """val $dfName<$fullTypeName?>.city: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $dataCol<$stringName?>""", + expectedExtensionProperty( + "$dfName<$fullTypeName?>", + "city", + "$dataCol<$stringName?>", + "Nullable${shortTypeName}_city", + ), ) appendLine( - """val $dfRowName<$fullTypeName?>.city: $stringName? @JvmName("Nullable${shortTypeName}_city") get() = this["city"] as $stringName?""", + expectedExtensionProperty( + "$dfRowName<$fullTypeName?>", + "city", + "$stringName?", + "Nullable${shortTypeName}_city", + ), ) } appendLine( - """val $dfName<$fullTypeName>.name: $dataCol<$stringName> @JvmName("${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName>""", + expectedExtensionProperty( + "$dfName<$fullTypeName>", + "name", + "$dataCol<$stringName>", + "${shortTypeName}_name", + ), ) appendLine( - """val $dfRowName<$fullTypeName>.name: $stringName @JvmName("${shortTypeName}_name") get() = this["name"] as $stringName""", + expectedExtensionProperty("$dfRowName<$fullTypeName>", "name", stringName, "${shortTypeName}_name"), ) if (addNullable) { appendLine( - """val $dfName<$fullTypeName?>.name: $dataCol<$stringName?> @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $dataCol<$stringName?>""", + expectedExtensionProperty( + "$dfName<$fullTypeName?>", + "name", + "$dataCol<$stringName?>", + "Nullable${shortTypeName}_name", + ), ) appendLine( - """val $dfRowName<$fullTypeName?>.name: $stringName? @JvmName("Nullable${shortTypeName}_name") get() = this["name"] as $stringName?""", + expectedExtensionProperty( + "$dfRowName<$fullTypeName?>", + "name", + "$stringName?", + "Nullable${shortTypeName}_name", + ), ) } appendLine( - """val $dfName<$fullTypeName>.weight: $dataCol<$intName?> @JvmName("${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?>""", + expectedExtensionProperty( + "$dfName<$fullTypeName>", + "weight", + "$dataCol<$intName?>", + "${shortTypeName}_weight", + ), ) append( - """val $dfRowName<$fullTypeName>.weight: $intName? @JvmName("${shortTypeName}_weight") get() = this["weight"] as $intName?""", + expectedExtensionProperty( + "$dfRowName<$fullTypeName>", + "weight", + "$intName?", + "${shortTypeName}_weight", + ), ) if (addNullable) { appendLine("") appendLine( - """val $dfName<$fullTypeName?>.weight: $dataCol<$intName?> @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $dataCol<$intName?>""", + expectedExtensionProperty( + "$dfName<$fullTypeName?>", + "weight", + "$dataCol<$intName?>", + "Nullable${shortTypeName}_weight", + ), ) append( - """val $dfRowName<$fullTypeName?>.weight: $intName? @JvmName("Nullable${shortTypeName}_weight") get() = this["weight"] as $intName?""", + expectedExtensionProperty( + "$dfRowName<$fullTypeName?>", + "weight", + "$intName?", + "Nullable${shortTypeName}_weight", + ), ) } } @@ -352,12 +417,22 @@ class CodeGenerationTests : BaseTest() { val name: String } - val $dfName<$nestedType>.city: $dataCol<$stringName?> @JvmName("${nestedType}_city") get() = this["city"] as $dataCol<$stringName?> - val $dfRowName<$nestedType>.city: $stringName? @JvmName("${nestedType}_city") get() = this["city"] as $stringName? - val $dfName<$nestedType>.name: $dataCol<$stringName> @JvmName("${nestedType}_name") get() = this["name"] as $dataCol<$stringName> - val $dfRowName<$nestedType>.name: $stringName @JvmName("${nestedType}_name") get() = this["name"] as $stringName - - """.trimIndent() + """.trimIndent() + listOf( + expectedExtensionProperty( + "$dfName<$nestedType>", + "city", + "$dataCol<$stringName?>", + "${nestedType}_city", + ), + expectedExtensionProperty("$dfRowName<$nestedType>", "city", "$stringName?", "${nestedType}_city"), + expectedExtensionProperty( + "$dfName<$nestedType>", + "name", + "$dataCol<$stringName>", + "${nestedType}_name", + ), + expectedExtensionProperty("$dfRowName<$nestedType>", "name", stringName, "${nestedType}_name"), + ).joinToString("\n", prefix = "\n", postfix = "\n") val declaration2 = """ @@ -368,13 +443,24 @@ class CodeGenerationTests : BaseTest() { val weight: Int? } - 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>.nameAndCity: $colGroup<$nestedType> @JvmName("${type2}_nameAndCity") get() = this["nameAndCity"] as $colGroup<$nestedType> - val $dfRowName<$type2>.nameAndCity: $dataRow<$nestedType> @JvmName("${type2}_nameAndCity") get() = this["nameAndCity"] as $dataRow<$nestedType> - 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? - """.trimIndent() + """.trimIndent() + listOf( + expectedExtensionProperty("$dfName<$type2>", "age", "$dataCol<$intName>", "${type2}_age"), + expectedExtensionProperty("$dfRowName<$type2>", "age", intName, "${type2}_age"), + expectedExtensionProperty( + "$dfName<$type2>", + "nameAndCity", + "$colGroup<$nestedType>", + "${type2}_nameAndCity", + ), + expectedExtensionProperty( + "$dfRowName<$type2>", + "nameAndCity", + "$dataRow<$nestedType>", + "${type2}_nameAndCity", + ), + expectedExtensionProperty("$dfName<$type2>", "weight", "$dataCol<$intName?>", "${type2}_weight"), + expectedExtensionProperty("$dfRowName<$type2>", "weight", "$intName?", "${type2}_weight"), + ).joinToString("\n", prefix = "\n") val expectedConverter = "it.cast<$type2>()" @@ -428,11 +514,32 @@ class CodeGenerationTests : BaseTest() { override val weight: kotlin.Int } - 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.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 - """.trimIndent() + """.trimIndent() + listOf( + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "city", + "$packageName.DataColumn", + "ValidPerson_city", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "city", + "kotlin.String", + "ValidPerson_city", + ), + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "weight", + "$packageName.DataColumn", + "ValidPerson_weight", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "weight", + "kotlin.Int", + "ValidPerson_weight", + ), + ).joinToString("\n", prefix = "\n") assertEquals(expected, code) } @@ -480,16 +587,65 @@ class CodeGenerationTests : BaseTest() { val name: kotlin.String val weight: kotlin.Int? } - - 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.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.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.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? - """.trimIndent() + + """.trimIndent() + listOf( + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "age", + "$packageName.DataColumn", + "DataType_age", + visibility = "internal ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "age", + "kotlin.Int", + "DataType_age", + visibility = "internal ", + ), + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "city", + "$packageName.DataColumn", + "DataType_city", + visibility = "internal ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "city", + "kotlin.String?", + "DataType_city", + visibility = "internal ", + ), + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "name", + "$packageName.DataColumn", + "DataType_name", + visibility = "internal ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "name", + "kotlin.String", + "DataType_name", + visibility = "internal ", + ), + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "weight", + "$packageName.DataColumn", + "DataType_weight", + visibility = "internal ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "weight", + "kotlin.Int?", + "DataType_weight", + visibility = "internal ", + ), + ).joinToString("\n", prefix = "\n") assertEquals(expected, code) } @@ -505,7 +661,8 @@ class CodeGenerationTests : BaseTest() { MarkerVisibility.EXPLICIT_PUBLIC, ).code.declarations val packageName = "org.jetbrains.kotlinx.dataframe" - val expected = """ + val expected = + """ @DataSchema(isOpen = false) public interface DataType { public val age: kotlin.Int @@ -514,17 +671,66 @@ class CodeGenerationTests : BaseTest() { public val weight: kotlin.Int? } - 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.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.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.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? - """ + """.trimIndent() + listOf( + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "age", + "$packageName.DataColumn", + "DataType_age", + visibility = "public ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "age", + "kotlin.Int", + "DataType_age", + visibility = "public ", + ), + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "city", + "$packageName.DataColumn", + "DataType_city", + visibility = "public ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "city", + "kotlin.String?", + "DataType_city", + visibility = "public ", + ), + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "name", + "$packageName.DataColumn", + "DataType_name", + visibility = "public ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "name", + "kotlin.String", + "DataType_name", + visibility = "public ", + ), + expectedExtensionProperty( + "$packageName.ColumnsContainer", + "weight", + "$packageName.DataColumn", + "DataType_weight", + visibility = "public ", + ), + expectedExtensionProperty( + "$packageName.DataRow", + "weight", + "kotlin.Int?", + "DataType_weight", + visibility = "public ", + ), + ).joinToString("\n", prefix = "\n") - assertEquals(expected.trimIndent(), code) + assertEquals(expected, code) } @Test diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExpectedExtensionProperty.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExpectedExtensionProperty.kt new file mode 100644 index 0000000000..1b38a44a8c --- /dev/null +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/ExpectedExtensionProperty.kt @@ -0,0 +1,44 @@ +package org.jetbrains.kotlinx.dataframe.codeGen + +internal fun expectedExtensionProperty( + receiverType: String, + name: String, + propertyType: String, + jvmName: String, + visibility: String = "", + columnName: String = name.removeSurrounding("`"), +): String = + buildString { + val renderedColumnName = columnName + .replace("\\", "\\\\") + .replace("$", "\\\$") + .replace("\"", "\\\"") + .replace("\n", "\\n") + .replace("\r", "\\r") + + appendLine("""${visibility}val $receiverType.$name: $propertyType @JvmName("$jvmName") get() = try {""") + appendLine(""" this["$renderedColumnName"] as $propertyType""") + appendLine("} catch (e: kotlin.Exception) {") + appendLine(" val msg = when (e) {") + appendLine(" is kotlin.IllegalArgumentException ->") + appendLine( + " \"Column not found exception in the generated DataFrame extension property " + + "'$renderedColumnName': \${e.localizedMessage}. See for more information.\"", + ) + appendLine("") + appendLine(" is kotlin.ClassCastException ->") + appendLine( + " \"Incorrect column type exception in generated DataFrame extension property " + + $$"'$$renderedColumnName': ${e.localizedMessage}. See for more information.\"", + ) + appendLine("") + appendLine(" else ->") + appendLine( + " \"Unexpected exception in generated DataFrame extension property " + + "'$renderedColumnName'. Please report it to https://github.com/Kotlin/dataframe/issues. " + + $$"Exception message: $e.\"", + ) + appendLine(" }") + appendLine(" throw IllegalStateException(msg, e)") + append("} ") + } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/NameGenerationTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/NameGenerationTests.kt index 8f43fa2a23..512405a014 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/NameGenerationTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/NameGenerationTests.kt @@ -54,9 +54,12 @@ class NameGenerationTests { @Test fun `properties generation`() { val codeGen = ReplCodeGenerator.create() - val code = codeGen.process().split("\n") - code.size shouldBe 8 - code.forEach { + val propertyDeclarations = codeGen.process() + .lineSequence() + .filter { it.startsWith("val ") } + .toList() + propertyDeclarations.size shouldBe 8 + propertyDeclarations.forEach { it.count { it == '`' } 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 9f0bd18ad0..b172857a04 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 @@ -34,6 +34,18 @@ class ReplCodeGenTests : BaseTest() { val intName = Int::class.simpleName!! val stringName = String::class.simpleName!! + private fun personProperties(marker: String) = + listOf( + expectedExtensionProperty("$dfName<$marker>", "age", "$dataCol<$intName>", "${marker}_age"), + expectedExtensionProperty("$dfRowName<$marker>", "age", intName, "${marker}_age"), + expectedExtensionProperty("$dfName<$marker>", "city", "$dataCol<$stringName?>", "${marker}_city"), + expectedExtensionProperty("$dfRowName<$marker>", "city", "$stringName?", "${marker}_city"), + expectedExtensionProperty("$dfName<$marker>", "name", "$dataCol<$stringName>", "${marker}_name"), + expectedExtensionProperty("$dfRowName<$marker>", "name", stringName, "${marker}_name"), + expectedExtensionProperty("$dfName<$marker>", "weight", "$dataCol<$intName?>", "${marker}_weight"), + expectedExtensionProperty("$dfRowName<$marker>", "weight", "$intName?", "${marker}_weight"), + ).joinToString("\n", prefix = "\n") + class Test1 { @DataSchema interface _DataFrameType @@ -95,16 +107,8 @@ class ReplCodeGenTests : BaseTest() { val name: String val weight: Int? } - - 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>.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>.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>.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? - """.trimIndent() + + """.trimIndent() + personProperties(marker) code shouldBe expected val code2 = repl.process() @@ -119,10 +123,11 @@ class ReplCodeGenTests : BaseTest() { interface $marker3 : $markerFull { override val city: String } - - 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 - """.trimIndent() + + """.trimIndent() + listOf( + expectedExtensionProperty("$dfName<$marker3>", "city", "$dataCol<$stringName>", "${marker3}_city"), + expectedExtensionProperty("$dfRowName<$marker3>", "city", stringName, "${marker3}_city"), + ).joinToString("\n", prefix = "\n") code3 shouldBe expected3 @@ -138,10 +143,11 @@ class ReplCodeGenTests : BaseTest() { interface $marker5 : $markerFull { override val weight: Int } - - 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 - """.trimIndent() + + """.trimIndent() + listOf( + expectedExtensionProperty("$dfName<$marker5>", "weight", "$dataCol<$intName>", "${marker5}_weight"), + expectedExtensionProperty("$dfRowName<$marker5>", "weight", intName, "${marker5}_weight"), + ).joinToString("\n", prefix = "\n") code5 shouldBe expected5 val code6 = repl.process() @@ -184,12 +190,13 @@ class ReplCodeGenTests : BaseTest() { val city: String? val weight: Int? } - - 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>.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? - """.trimIndent() + + """.trimIndent() + listOf( + expectedExtensionProperty("$dfName<$marker>", "city", "$dataCol<$stringName?>", "${marker}_city"), + expectedExtensionProperty("$dfRowName<$marker>", "city", "$stringName?", "${marker}_city"), + expectedExtensionProperty("$dfName<$marker>", "weight", "$dataCol<$intName?>", "${marker}_weight"), + expectedExtensionProperty("$dfRowName<$marker>", "weight", "$intName?", "${marker}_weight"), + ).joinToString("\n", prefix = "\n") val code = repl.process(typed).declarations.trimIndent() code shouldBe expected @@ -286,22 +293,35 @@ class ReplCodeGenTests : BaseTest() { val c: Int } - val $dfName.a: $dataCol @JvmName("Leaf_a") get() = this["a"] as $dataCol - val $dfRowName.a: Int @JvmName("Leaf_a") get() = this["a"] as Int - val $dfName.c: $dataCol @JvmName("Leaf_c") get() = this["c"] as $dataCol - val $dfRowName.c: Int @JvmName("Leaf_c") get() = this["c"] as Int - + """.trimIndent() + listOf( + expectedExtensionProperty("$dfName", "a", "$dataCol", "Leaf_a"), + expectedExtensionProperty("$dfRowName", "a", "Int", "Leaf_a"), + expectedExtensionProperty("$dfName", "c", "$dataCol", "Leaf_c"), + expectedExtensionProperty("$dfRowName", "c", "Int", "Leaf_c"), + ).joinToString("\n", prefix = "\n", postfix = "\n\n") + + """ @DataSchema interface _DataFrameType2 { val col: String val leaf: Leaf } - val $dfName<_DataFrameType2>.col: $dataCol @JvmName("_DataFrameType2_col") get() = this["col"] as $dataCol - val $dfRowName<_DataFrameType2>.col: String @JvmName("_DataFrameType2_col") get() = this["col"] as String - val $dfName<_DataFrameType2>.leaf: ColumnGroup @JvmName("_DataFrameType2_leaf") get() = this["leaf"] as ColumnGroup - val $dfRowName<_DataFrameType2>.leaf: $dfRowName @JvmName("_DataFrameType2_leaf") get() = this["leaf"] as $dfRowName - """.trimIndent() + """.trimIndent() + listOf( + expectedExtensionProperty("$dfName<_DataFrameType2>", "col", "$dataCol", "_DataFrameType2_col"), + expectedExtensionProperty("$dfRowName<_DataFrameType2>", "col", "String", "_DataFrameType2_col"), + expectedExtensionProperty( + "$dfName<_DataFrameType2>", + "leaf", + "ColumnGroup", + "_DataFrameType2_leaf", + ), + expectedExtensionProperty( + "$dfRowName<_DataFrameType2>", + "leaf", + "$dfRowName", + "_DataFrameType2_leaf", + ), + ).joinToString("\n", prefix = "\n") } object TestColumnOrderInGroup { diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTreeTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTreeTests.kt index 6d46279c3a..d0f7e23280 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTreeTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTreeTests.kt @@ -99,6 +99,7 @@ import org.jetbrains.kotlinx.dataframe.api.withNull import org.jetbrains.kotlinx.dataframe.api.xs import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenerator import org.jetbrains.kotlinx.dataframe.codeGen.InterfaceGenerationMode +import org.jetbrains.kotlinx.dataframe.codeGen.expectedExtensionProperty import org.jetbrains.kotlinx.dataframe.codeGen.generate import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.ColumnKind @@ -517,21 +518,70 @@ class DataFrameTreeTests : BaseTest() { val nameAndCity = NameAndCity::class.qualifiedName val groupedColumn = ColumnGroup::class.qualifiedName val columnData = DataColumn::class.qualifiedName - val expected = - """ - val $columnsContainer<$className>.age: $columnData @JvmName("${shortName}_age") get() = this["age"] as $columnData - val $dataFrameRowBase<$className>.age: kotlin.Int @JvmName("${shortName}_age") get() = this["age"] as kotlin.Int - val $columnsContainer<$className?>.age: $columnData @JvmName("Nullable${shortName}_age") get() = this["age"] as $columnData - val $dataFrameRowBase<$className?>.age: kotlin.Int? @JvmName("Nullable${shortName}_age") get() = this["age"] as kotlin.Int? - val $columnsContainer<$className>.nameAndCity: $groupedColumn<$nameAndCity> @JvmName("${shortName}_nameAndCity") get() = this["nameAndCity"] as $groupedColumn<$nameAndCity> - val $dataFrameRowBase<$className>.nameAndCity: $dataFrameRow<$nameAndCity> @JvmName("${shortName}_nameAndCity") get() = this["nameAndCity"] as $dataFrameRow<$nameAndCity> - val $columnsContainer<$className?>.nameAndCity: $groupedColumn<$nameAndCity?> @JvmName("Nullable${shortName}_nameAndCity") get() = this["nameAndCity"] as $groupedColumn<$nameAndCity?> - val $dataFrameRowBase<$className?>.nameAndCity: $dataFrameRow<$nameAndCity?> @JvmName("Nullable${shortName}_nameAndCity") get() = this["nameAndCity"] as $dataFrameRow<$nameAndCity?> - val $columnsContainer<$className>.weight: $columnData @JvmName("${shortName}_weight") get() = this["weight"] as $columnData - val $dataFrameRowBase<$className>.weight: kotlin.Int? @JvmName("${shortName}_weight") get() = this["weight"] as kotlin.Int? - val $columnsContainer<$className?>.weight: $columnData @JvmName("Nullable${shortName}_weight") get() = this["weight"] as $columnData - val $dataFrameRowBase<$className?>.weight: kotlin.Int? @JvmName("Nullable${shortName}_weight") get() = this["weight"] as kotlin.Int? - """.trimIndent() + val expected = listOf( + expectedExtensionProperty( + "$columnsContainer<$className>", + "age", + "$columnData", + "${shortName}_age", + ), + expectedExtensionProperty("$dataFrameRowBase<$className>", "age", "kotlin.Int", "${shortName}_age"), + expectedExtensionProperty( + "$columnsContainer<$className?>", + "age", + "$columnData", + "Nullable${shortName}_age", + ), + expectedExtensionProperty( + "$dataFrameRowBase<$className?>", + "age", + "kotlin.Int?", + "Nullable${shortName}_age", + ), + expectedExtensionProperty( + "$columnsContainer<$className>", + "nameAndCity", + "$groupedColumn<$nameAndCity>", + "${shortName}_nameAndCity", + ), + expectedExtensionProperty( + "$dataFrameRowBase<$className>", + "nameAndCity", + "$dataFrameRow<$nameAndCity>", + "${shortName}_nameAndCity", + ), + expectedExtensionProperty( + "$columnsContainer<$className?>", + "nameAndCity", + "$groupedColumn<$nameAndCity?>", + "Nullable${shortName}_nameAndCity", + ), + expectedExtensionProperty( + "$dataFrameRowBase<$className?>", + "nameAndCity", + "$dataFrameRow<$nameAndCity?>", + "Nullable${shortName}_nameAndCity", + ), + expectedExtensionProperty( + "$columnsContainer<$className>", + "weight", + "$columnData", + "${shortName}_weight", + ), + expectedExtensionProperty("$dataFrameRowBase<$className>", "weight", "kotlin.Int?", "${shortName}_weight"), + expectedExtensionProperty( + "$columnsContainer<$className?>", + "weight", + "$columnData", + "Nullable${shortName}_weight", + ), + expectedExtensionProperty( + "$dataFrameRowBase<$className?>", + "weight", + "kotlin.Int?", + "Nullable${shortName}_weight", + ), + ).joinToString("\n") code shouldBe expected } diff --git a/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt b/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt index afdebb58e3..e3947503d7 100644 --- a/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt +++ b/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt @@ -19,6 +19,8 @@ class OpenApiTests : JupyterReplTestCase() { private val openApi = OpenApi() private val additionalImports = openApi.createDefaultReadMethod().additionalImports.joinToString("\n") + private val extensionPropertyRegex = + """val (.+)\.([^.:]+): (.+) @JvmName\("([^"]+)"\) get\(\) = this\["((?:\\.|[^"])*)"] as (.+)""".toRegex() private fun execGeneratedCode(code: Code): Code { @Language("kts") @@ -41,6 +43,67 @@ class OpenApiTests : JupyterReplTestCase() { return execGeneratedCode(code) } + private fun String.expectedExtensionProperties(): String = + trimLines().lines().joinToString("\n") { line -> + extensionPropertyRegex.matchEntire(line) + ?.destructured + ?.let { (receiverType, name, propertyType, jvmName, columnName, castType) -> + expectedExtensionProperty( + receiverType = receiverType, + name = name, + propertyType = propertyType, + jvmName = jvmName, + columnName = columnName, + castType = castType, + ) + } + ?: error("Unexpected extension property format: $line") + } + + private fun expectedExtensionProperty( + receiverType: String, + name: String, + propertyType: String, + jvmName: String, + columnName: String, + castType: String, + ): String = + buildString { + val renderedColumnName = columnName + .replace("\\", "\\\\") + .replace("$", "\\\$") + .replace("\"", "\\\"") + .replace("\n", "\\n") + .replace("\r", "\\r") + + appendLine("""val $receiverType.$name: $propertyType @JvmName("$jvmName") get() = try {""") + appendLine(""" this["$renderedColumnName"] as $castType""") + appendLine("} catch (e: kotlin.Exception) {") + appendLine(" val msg = when (e) {") + appendLine(" is kotlin.IllegalArgumentException ->") + appendLine( + " \"Column not found exception in the generated DataFrame extension property " + + "'$renderedColumnName': \${e.localizedMessage}. See for more information.\"", + ) + appendLine("") + appendLine(" is kotlin.ClassCastException ->") + appendLine( + " \"Incorrect column type exception in generated DataFrame extension property " + + "'$renderedColumnName': \${e.localizedMessage}. See for more information.\"", + ) + + appendLine("") + appendLine(" else ->") + appendLine( + " \"Unexpected exception in generated DataFrame extension property " + + "'$renderedColumnName'. Please report it to https://github.com/Kotlin/dataframe/issues. " + + "Exception message: \$e.\"", + ) + appendLine(" }") + appendLine(" throw IllegalStateException(msg, e)") + append("} ") + }.trimLines() + private val petstoreJson = File("src/test/resources/petstore.json") private val petstoreAdvancedJson = File("src/test/resources/petstore_advanced.json") private val petstoreYaml = File("src/test/resources/petstore.yaml") @@ -111,7 +174,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Pet>.tag: kotlin.String? @JvmName("Pet_tag") get() = this["tag"] as kotlin.String? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Pet?>.tag: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullablePet_tag") get() = this["tag"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Pet?>.tag: kotlin.String? @JvmName("NullablePet_tag") get() = this["tag"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(petExtensions) @@ -144,7 +207,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Error>.message: kotlin.String @JvmName("Error_message") get() = this["message"] as kotlin.String val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Error?>.message: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableError_message") get() = this["message"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Error?>.message: kotlin.String? @JvmName("NullableError_message") get() = this["message"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(errorExtensions) @@ -226,7 +289,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Customer>.username: kotlin.String? @JvmName("Customer_username") get() = this["username"] as kotlin.String? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Customer?>.username: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableCustomer_username") get() = this["username"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Customer?>.username: kotlin.String? @JvmName("NullableCustomer_username") get() = this["username"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(customerExtensions) @@ -256,7 +319,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Order>.status: $functionName.Status? @JvmName("Order_status") get() = this["status"] as $functionName.Status? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Order?>.status: org.jetbrains.kotlinx.dataframe.DataColumn<$functionName.Status?> @JvmName("NullableOrder_status") get() = this["status"] as org.jetbrains.kotlinx.dataframe.DataColumn<$functionName.Status?> val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Order?>.status: $functionName.Status? @JvmName("NullableOrder_status") get() = this["status"] as $functionName.Status? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(orderExtensions) @@ -292,7 +355,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Address>.zip: kotlin.String? @JvmName("Address_zip") get() = this["zip"] as kotlin.String? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Address?>.zip: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableAddress_zip") get() = this["zip"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Address?>.zip: kotlin.String? @JvmName("NullableAddress_zip") get() = this["zip"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(addressExtensions) @@ -318,7 +381,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Category>.name: kotlin.String? @JvmName("Category_name") get() = this["name"] as kotlin.String? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Category?>.name: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableCategory_name") get() = this["name"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Category?>.name: kotlin.String? @JvmName("NullableCategory_name") get() = this["name"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(categoryExtensions) @@ -374,7 +437,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.User>.username: kotlin.String? @JvmName("User_username") get() = this["username"] as kotlin.String? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.User?>.username: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableUser_username") get() = this["username"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.User?>.username: kotlin.String? @JvmName("NullableUser_username") get() = this["username"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(userExtensions) @@ -444,7 +507,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Pet>.tags: org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Tag?> @JvmName("Pet_tags") get() = this["tags"] as org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Tag?> val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Pet?>.tags: org.jetbrains.kotlinx.dataframe.DataColumn> @JvmName("NullablePet_tags") get() = this["tags"] as org.jetbrains.kotlinx.dataframe.DataColumn> val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Pet?>.tags: org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Tag?> @JvmName("NullablePet_tags") get() = this["tags"] as org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Tag?> - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(petExtensions) @@ -475,7 +538,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ApiResponse>.type: kotlin.String? @JvmName("ApiResponse_type") get() = this["type"] as kotlin.String? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.ApiResponse?>.type: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableApiResponse_type") get() = this["type"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ApiResponse?>.type: kotlin.String? @JvmName("NullableApiResponse_type") get() = this["type"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(apiResponseExtensions) @@ -548,7 +611,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Dog>.tag: kotlin.String @JvmName("Dog_tag") get() = this["tag"] as kotlin.String val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Dog?>.tag: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableDog_tag") get() = this["tag"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Dog?>.tag: kotlin.String? @JvmName("NullableDog_tag") get() = this["tag"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(dogExtensions) @@ -602,7 +665,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Cat>.hunts: kotlin.Boolean? @JvmName("Cat_hunts") get() = this["hunts"] as kotlin.Boolean? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Cat?>.hunts: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableCat_hunts") get() = this["hunts"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Cat?>.hunts: kotlin.Boolean? @JvmName("NullableCat_hunts") get() = this["hunts"] as kotlin.Boolean? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(catExtensions) @@ -670,7 +733,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Pet>.value: kotlin.Any? @JvmName("Pet_value") get() = this["value"] as kotlin.Any? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Pet?>.value: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullablePet_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Pet?>.value: kotlin.Any? @JvmName("NullablePet_value") get() = this["value"] as kotlin.Any? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(petExtensions) @@ -719,7 +782,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.IntList>.list: kotlin.collections.List @JvmName("IntList_list") get() = this["list"] as kotlin.collections.List val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.IntList?>.list: org.jetbrains.kotlinx.dataframe.DataColumn?> @JvmName("NullableIntList_list") get() = this["list"] as org.jetbrains.kotlinx.dataframe.DataColumn?> val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.IntList?>.list: kotlin.collections.List? @JvmName("NullableIntList_list") get() = this["list"] as kotlin.collections.List? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(intListExtensions) @@ -752,7 +815,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditionalProperties>.value: kotlin.String @JvmName("ObjectWithAdditionalProperties_value") get() = this["value"] as kotlin.String val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.ObjectWithAdditionalProperties?>.value: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableObjectWithAdditionalProperties_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditionalProperties?>.value: kotlin.String? @JvmName("NullableObjectWithAdditionalProperties_value") get() = this["value"] as kotlin.String? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(objectWithAdditionalPropertiesExtensions) @@ -785,7 +848,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditional2>.value: kotlin.Any @JvmName("ObjectWithAdditional2_value") get() = this["value"] as kotlin.Any val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.ObjectWithAdditional2?>.value: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableObjectWithAdditional2_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditional2?>.value: kotlin.Any? @JvmName("NullableObjectWithAdditional2_value") get() = this["value"] as kotlin.Any? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(objectWithAdditional2Extensions) @@ -818,7 +881,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditional3>.value: kotlin.Any? @JvmName("ObjectWithAdditional3_value") get() = this["value"] as kotlin.Any? val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.ObjectWithAdditional3?>.value: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableObjectWithAdditional3_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditional3?>.value: kotlin.Any? @JvmName("NullableObjectWithAdditional3_value") get() = this["value"] as kotlin.Any? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(objectWithAdditional3Extensions) @@ -892,7 +955,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Error>.pets: org.jetbrains.kotlinx.dataframe.DataFrame @JvmName("Error_pets") get() = this["pets"] as org.jetbrains.kotlinx.dataframe.DataFrame val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.Error?>.pets: org.jetbrains.kotlinx.dataframe.DataColumn> @JvmName("NullableError_pets") get() = this["pets"] as org.jetbrains.kotlinx.dataframe.DataColumn> val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Error?>.pets: org.jetbrains.kotlinx.dataframe.DataFrame @JvmName("NullableError_pets") get() = this["pets"] as org.jetbrains.kotlinx.dataframe.DataFrame - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(errorExtensions) @@ -933,7 +996,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditional>.value: kotlin.Int @JvmName("ObjectWithAdditional_value") get() = this["value"] as kotlin.Int val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.ObjectWithAdditional?>.value: org.jetbrains.kotlinx.dataframe.DataColumn @JvmName("NullableObjectWithAdditional_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.DataColumn val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ObjectWithAdditional?>.value: kotlin.Int? @JvmName("NullableObjectWithAdditional_value") get() = this["value"] as kotlin.Int? - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(objectWithAdditionalExtensions) @@ -980,7 +1043,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.SomeArrayContent>.value: org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Value?> @JvmName("SomeArrayContent_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Value?> val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.SomeArrayContent?>.value: org.jetbrains.kotlinx.dataframe.columns.ColumnGroup<$functionName.Value?> @JvmName("NullableSomeArrayContent_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.columns.ColumnGroup<$functionName.Value?> val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.SomeArrayContent?>.value: org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Value?> @JvmName("NullableSomeArrayContent_value") get() = this["value"] as org.jetbrains.kotlinx.dataframe.DataRow<$functionName.Value?> - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(someArrayContentExtensions) @@ -1019,7 +1082,7 @@ class OpenApiTests : JupyterReplTestCase() { val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ErrorHolder>.errors: org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Error> @JvmName("ErrorHolder_errors") get() = this["errors"] as org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Error> val org.jetbrains.kotlinx.dataframe.ColumnsContainer<$functionName.ErrorHolder?>.errors: org.jetbrains.kotlinx.dataframe.DataColumn> @JvmName("NullableErrorHolder_errors") get() = this["errors"] as org.jetbrains.kotlinx.dataframe.DataColumn> val org.jetbrains.kotlinx.dataframe.DataRow<$functionName.ErrorHolder?>.errors: org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Error?> @JvmName("NullableErrorHolder_errors") get() = this["errors"] as org.jetbrains.kotlinx.dataframe.DataFrame<$functionName.Error?> - """.trimLines() + """.expectedExtensionProperties() code should haveSubstring(errorHolderExtensions)