Skip to content
Original file line number Diff line number Diff line change
@@ -1,14 +1,89 @@
package org.jetbrains.kotlinx.dataframe.api

import org.jetbrains.kotlinx.dataframe.DataFrame
import org.jetbrains.kotlinx.dataframe.annotations.ColumnName
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
import org.jetbrains.kotlinx.dataframe.codeGen.CodeGenerator
import org.jetbrains.kotlinx.dataframe.codeGen.MarkerVisibility
import org.jetbrains.kotlinx.dataframe.codeGen.NameNormalizer
import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup
import org.jetbrains.kotlinx.dataframe.columns.FrameColumn
import org.jetbrains.kotlinx.dataframe.documentation.DocumentationUrls
import org.jetbrains.kotlinx.dataframe.documentation.ExcludeFromSources
import org.jetbrains.kotlinx.dataframe.impl.codeGen.from
import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema

// region Docs

/**
* Generates a [CodeString] containing generated [@DataSchema][DataSchema] $[TYPES]
* for the given $[RECEIVER]
* (including all nested [frame columns][FrameColumn] and [column groups][ColumnGroup]).
*
* These generated declarations can also be called "markers".
*
* This is useful when working with the compiler plugin in cases where the schema
* cannot be inferred automatically from the source.
*
* This function is a simplified wrapper for the more advanced and customizable
* [CodeGenerator] API.
* For more customizability, have a look at [CodeGenerator.create()][CodeGenerator.create].
*
* For more information: {@include [DocumentationUrls.DataSchemaGeneration]}
*
* @return [CodeString] – A value class wrapper for [String], containing
* the generated Kotlin code of data schema declarations (markers).
*/
@ExcludeFromSources
private interface CommonGenerateCodeDocs {

// "interfaces" or "data classes"
interface TYPES

// "DataFrameSchema" or "DataFrame"
interface RECEIVER
}

@ExcludeFromSources
private interface Params {

/** @param markerName The base name to use for generated data schema declarations (markers). */
interface MarkerName

/** @include [MarkerName] If not specified, generates a name from type [T]. */
interface MarkerNameOptional

/** @param fields Whether to generate fields (`val ...:`) inside the generated data schema declarations (markers). */
interface Fields

/** @param extensionProperties Whether to generate extension properties in addition to data schema declarations (markers). */
interface ExtensionProperties

/** @param visibility Visibility modifier for the generated declarations (markers). */
interface Visibility

/** @param useFqNames If `true`, fully qualified type names will be used in generated code. */
interface UseFqNames

/**
* @param nameNormalizer Strategy for converting column names (with spaces, underscores, etc.) to valid Kotlin identifiers.
* Columns will keep their original name inside the dataframe via [@ColumnName][ColumnName].
*/
interface NameNormalizer
}

// endregion

// region DataFrame

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrame's][this] [schema][DataFrameSchema]}
* {@set [CommonGenerateCodeDocs.TYPES] interfaces and extension properties}
*
* @include [Params.Fields] Default is `true`.
* @include [Params.ExtensionProperties] Default is `true`.
*/
public inline fun <reified T> DataFrame<T>.generateCode(
fields: Boolean = true,
extensionProperties: Boolean = true,
Expand All @@ -19,6 +94,16 @@ public inline fun <reified T> DataFrame<T>.generateCode(
extensionProperties = extensionProperties,
)

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrame's][this] [schema][DataFrameSchema]}
* {@set [CommonGenerateCodeDocs.TYPES] interfaces and extension properties}
*
* @include [Params.MarkerName]
* @include [Params.Fields] Default is `true`.
* @include [Params.ExtensionProperties] Default is `true`.
* @include [Params.Visibility] Default is [MarkerVisibility.IMPLICIT_PUBLIC].
*/
public fun <T> DataFrame<T>.generateCode(
markerName: String,
fields: Boolean = true,
Expand All @@ -32,11 +117,39 @@ public fun <T> DataFrame<T>.generateCode(
visibility = visibility,
)

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrame's][this] [schema][DataFrameSchema]}
* {@set [CommonGenerateCodeDocs.TYPES] interfaces}
*
* @include [Params.MarkerNameOptional]
*/
public inline fun <reified T> DataFrame<T>.generateInterfaces(): CodeString =
schema().generateInterfaces(
markerName = markerName<T>(),
)

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrame's][this] [schema][DataFrameSchema]}
* {@set [CommonGenerateCodeDocs.TYPES] interfaces}
*
* @include [Params.MarkerNameOptional]
*/
public fun <T> DataFrame<T>.generateInterfaces(markerName: String): CodeString =
schema().generateInterfaces(markerName = markerName)

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrame's][this] [schema][DataFrameSchema]}
* {@set [CommonGenerateCodeDocs.TYPES] data classes}
*
* @include [Params.MarkerNameOptional]
* @include [Params.ExtensionProperties] Default is `false`.
* @include [Params.Visibility] Default is [MarkerVisibility.IMPLICIT_PUBLIC].
* @include [Params.UseFqNames] Default is `false`.
* @include [Params.NameNormalizer] Default is [NameNormalizer.default][NameNormalizer.Companion.default].
*/
public inline fun <reified T> DataFrame<T>.generateDataClasses(
markerName: String? = null,
extensionProperties: Boolean = false,
Expand All @@ -45,20 +158,27 @@ public inline fun <reified T> DataFrame<T>.generateDataClasses(
nameNormalizer: NameNormalizer = NameNormalizer.default,
): CodeString =
schema().generateDataClasses(
name = markerName ?: markerName<T>(),
markerName = markerName ?: markerName<T>(),
extensionProperties = extensionProperties,
visibility = visibility,
useFqNames = useFqNames,
nameNormalizer = nameNormalizer,
)

public fun <T> DataFrame<T>.generateInterfaces(markerName: String): CodeString =
schema().generateInterfaces(markerName = markerName)

// endregion

// region DataFrameSchema

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrameSchema][this]}
* {@set [CommonGenerateCodeDocs.TYPES] interfaces and extension properties}
*
* @include [Params.MarkerName]
* @include [Params.Fields] Default is `true`.
* @include [Params.ExtensionProperties] Default is `true`.
* @include [Params.Visibility] Default is [MarkerVisibility.IMPLICIT_PUBLIC].
*/
@JvmName("generateCodeForSchema")
public fun DataFrameSchema.generateCode(
markerName: String,
Expand All @@ -77,6 +197,13 @@ public fun DataFrameSchema.generateCode(
).code.declarations.toCodeString()
}

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrameSchema][this]}
* {@set [CommonGenerateCodeDocs.TYPES] interfaces}
*
* @include [Params.MarkerName]
*/
@JvmName("generateInterfacesForSchema")
public fun DataFrameSchema.generateInterfaces(markerName: String): CodeString =
generateCode(
Expand All @@ -85,9 +212,20 @@ public fun DataFrameSchema.generateInterfaces(markerName: String): CodeString =
extensionProperties = false,
)

/**
* @include [CommonGenerateCodeDocs]
* {@set [CommonGenerateCodeDocs.RECEIVER] [DataFrameSchema][this]}
* {@set [CommonGenerateCodeDocs.TYPES] data classes}
*
* @include [Params.MarkerName]
* @include [Params.ExtensionProperties] Default is `false`.
* @include [Params.Visibility] Default is [MarkerVisibility.IMPLICIT_PUBLIC].
* @include [Params.UseFqNames] Default is `false`.
* @include [Params.NameNormalizer] Default is [NameNormalizer.default][NameNormalizer.Companion.default].
*/
@JvmName("generateDataClassesForSchema")
public fun DataFrameSchema.generateDataClasses(
name: String,
markerName: String,
extensionProperties: Boolean = false,
visibility: MarkerVisibility = MarkerVisibility.IMPLICIT_PUBLIC,
useFqNames: Boolean = false,
Expand All @@ -96,7 +234,7 @@ public fun DataFrameSchema.generateDataClasses(
val codeGen = CodeGenerator.create(useFqNames)
return codeGen.generate(
schema = this,
name = name,
name = markerName,
fields = true,
extensionProperties = extensionProperties,
isOpen = false,
Expand All @@ -121,6 +259,10 @@ internal inline fun <reified T> markerName(): String =
*/
public val NameNormalizer.Companion.default: NameNormalizer get() = NameNormalizer.from(setOf('\t', ' ', '_'))

/**
* A value class wrapper for [String], containing
* generated Kotlin code of data schema declarations (markers) and optionally extension properties.
*/
@JvmInline
public value class CodeString(public val value: String) {
override fun toString(): String = value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import org.jetbrains.kotlinx.dataframe.impl.schema.DataFrameSchemaImpl
import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema
import kotlin.reflect.KClass

/**
* Which type of visibility the marker (generated class-like code declaration)
* will have:
* - [INTERNAL][INTERNAL]: "internal"
* - [IMPLICIT_PUBLIC][IMPLICIT_PUBLIC]: ""
* - [EXPLICIT_PUBLIC][EXPLICIT_PUBLIC]: "public"
*/
public enum class MarkerVisibility {
INTERNAL,
IMPLICIT_PUBLIC,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,7 @@ internal interface DocumentationUrls {

/** [See `explode` on the documentation website.]({@include [Url]}/explode.html) */
interface Explode

/** [See `Data Schemas/Data Classes Generation` on the documentation website.]({@include [Url]}/dataschema-data-classes-generation.html) */
interface DataSchemaGeneration
}
Loading
Loading