Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/StardustDocs/d.tree
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<toc-element topic="staticInterpretation.md"/>
<toc-element topic="dataSchema.md"/>
<toc-element topic="compilerPluginExamples.md"/>
<toc-element topic="compilerPluginLimitationsAndWorkarounds.md"/>
</toc-element>
<toc-element topic="operations.md">
<toc-element topic="create.md">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Known limitations and workarounds

### Compiler plugin in lambdas with receiver marked as DslMarker

Problem: Property calls on a dataframe type created inside @Composable `Column { }` lambda cannot be resolved.
[Issue 1604](https://github.com/Kotlin/dataframe/issues/1604)

The lambda of `Column` has a receiver parameter `content: @Composable ColumnScope.() -> Unit`.

Here's the declaration from Compose. Receiver parameter types with annotations similar to this one will conflict with the plugin.
```kotlin
@LayoutScopeMarker
interface ColumnScope

@DslMarker
annotation class LayoutScopeMarker
```

Repro: The snippet below shows a dataframe variable initialized with a local DataFrame type inside a `Column` lambda. `ageComposableLambdaScope` cannot be resolved.

```kotlin
@DataSchema
data class Person(val age: Int, val name: String)

@Composable
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be clearer if you split this example because it now contains the bug and the solution interwoven with each other.

I'd first write the reproducer containing the bug, then separately write the workaround, so it's easy to see the difference.

fun DataFrameScreen(df: DataFrame<Person>) {
Column {
val filteredDf = remember(df) {
df
.add("ageComposableLambdaScope") { age }
.filter { ageComposableLambdaScope >= 20 }
}
filteredDf.ageComposableLambdaScope // error
}
}
```

Error message:
```
val ColumnsScope<Person_59I>.ageComposableLambdaScope: Int'
cannot be called in this context with an implicit receiver.
Use an explicit receiver if necessary
```

Workaround:
Initialize your dataframe properties outside lambdas with DslMarker receiver parameters.

```kotlin
@DataSchema
data class Person(val age: Int, val name: String)

@Composable
fun DataFrameScreen(df: DataFrame<Person>) {
val filteredDf = remember(df) {
df
.add("ageValidScope") { age }
.filter { ageValidScope >= 20 }
}
filteredDf.ageValidScope // OK

Column {
Text(filteredDf.ageValidScope.toString())
}
}
```
2 changes: 1 addition & 1 deletion examples/android-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A minimal Android project showcasing integration with **Kotlin DataFrame**.
It also includes the [Kotlin DataFrame Compiler Plugin](https://kotlin.github.io/dataframe/compiler-plugin.html).

We recommend using an up-to-date Android Studio for the best experience.
For proper functionality in Android Studio requires version Otter | 2025.2.2 or newer.
For proper functionality in Android Studio requires version Otter | 2025.2.3 or newer.

[Download Android Example](https://github.com/Kotlin/dataframe/raw/example-projects-archives/android-example.zip)

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -66,6 +67,7 @@ fun DefaultDataFrameScreenPreview() {

@Composable
fun DataFrameScreen(df: DataFrame<Person>) {
val filtered = remember(df) { df.filter { age >= 20 } }
Column(
modifier = Modifier
.fillMaxSize()
Expand Down Expand Up @@ -93,7 +95,7 @@ fun DataFrameScreen(df: DataFrame<Person>) {
.padding(2.dp)
)

DataFrameTable(df.filter { age >= 20 })
DataFrameTable(filtered)
}
}

Expand All @@ -109,26 +111,28 @@ fun DefaultDataFrameTablePreview() {

@Composable
fun DataFrameTable(df: DataFrame<*>) {
val columnNames = df.columnNames()
val columnNames = remember(df) { df.columnNames() }
val rows = remember(df) { df.rows().toList() }

// Header
Row {
for (name in columnNames) {
Text(
text = name,
modifier = Modifier
.weight(1f)
.padding(4.dp),
style = MaterialTheme.typography.labelLarge
)
}
}

Spacer(Modifier.height(4.dp))

// Rows
LazyColumn {
items(df.rows().toList()) { row ->
item {
// Header
Row {
for (name in columnNames) {
Text(
text = name,
modifier = Modifier
.weight(1f)
.padding(4.dp),
style = MaterialTheme.typography.labelLarge
)
}
}

Spacer(Modifier.height(4.dp))
}
// Rows
items(rows) { row ->
Row {
for (cell in row.values()) {
Text(
Expand Down
2 changes: 1 addition & 1 deletion examples/android-example/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
agp = "9.0.0-beta04"
agp = "9.0.0"
kotlin = "2.3.0-RC2"
coreKtx = "1.10.1"
junit = "4.13.2"
Expand Down