1
1
package org.jetbrains.kotlinx.dataframe.plugin.impl.api
2
2
3
3
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
4
+ import org.jetbrains.kotlin.fir.FirSession
4
5
import org.jetbrains.kotlinx.dataframe.plugin.classId
5
6
import org.jetbrains.kotlinx.dataframe.plugin.utils.Names
6
7
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
8
+ import org.jetbrains.kotlin.fir.declarations.hasAnnotation
7
9
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
8
10
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
9
11
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
@@ -37,13 +39,16 @@ import org.jetbrains.kotlin.fir.types.isStarProjection
37
39
import org.jetbrains.kotlin.fir.types.isSubtypeOf
38
40
import org.jetbrains.kotlin.fir.types.resolvedType
39
41
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
42
+ import org.jetbrains.kotlin.fir.types.toSymbol
40
43
import org.jetbrains.kotlin.fir.types.type
41
44
import org.jetbrains.kotlin.fir.types.upperBoundIfFlexible
42
45
import org.jetbrains.kotlin.fir.types.withArguments
43
46
import org.jetbrains.kotlin.name.ClassId
44
47
import org.jetbrains.kotlin.name.FqName
45
48
import org.jetbrains.kotlin.name.Name
46
49
import org.jetbrains.kotlin.name.StandardClassIds
50
+ import org.jetbrains.kotlin.name.StandardClassIds.List
51
+ import org.jetbrains.kotlinx.dataframe.codeGen.*
47
52
import org.jetbrains.kotlinx.dataframe.plugin.extensions.KotlinTypeFacade
48
53
import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractInterpreter
49
54
import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractSchemaModificationInterpreter
@@ -58,6 +63,9 @@ import org.jetbrains.kotlinx.dataframe.plugin.impl.SimpleFrameColumn
58
63
import org.jetbrains.kotlinx.dataframe.plugin.impl.dsl
59
64
import org.jetbrains.kotlinx.dataframe.plugin.impl.simpleColumnOf
60
65
import org.jetbrains.kotlinx.dataframe.plugin.impl.type
66
+ import org.jetbrains.kotlinx.dataframe.plugin.utils.Names.DATA_ROW_CLASS_ID
67
+ import org.jetbrains.kotlinx.dataframe.plugin.utils.Names.DATA_SCHEMA_CLASS_ID
68
+ import org.jetbrains.kotlinx.dataframe.plugin.utils.Names.DF_CLASS_ID
61
69
import java.util.*
62
70
63
71
class ToDataFrameDsl : AbstractSchemaModificationInterpreter () {
@@ -160,7 +168,7 @@ class Exclude1 : AbstractInterpreter<Unit>() {
160
168
dsl.excludeProperties.addAll(properties.arguments.filterIsInstance<FirCallableReferenceAccess >())
161
169
}
162
170
}
163
-
171
+ @Suppress( " INVISIBLE_MEMBER " )
164
172
@OptIn(SymbolInternals ::class )
165
173
internal fun KotlinTypeFacade.toDataFrame (
166
174
maxDepth : Int ,
@@ -228,17 +236,17 @@ internal fun KotlinTypeFacade.toDataFrame(
228
236
.filterNot { excludedClasses.contains(it.first.resolvedReturnType) }
229
237
.filter { it.first.effectiveVisibility == EffectiveVisibility .Public }
230
238
.map { (it, name) ->
231
- var resolvedReturnType = it.fir.returnTypeRef.resolveIfJavaType(session, JavaTypeParameterStack .EMPTY , null )
239
+ var returnType = it.fir.returnTypeRef.resolveIfJavaType(session, JavaTypeParameterStack .EMPTY , null )
232
240
.coneType.upperBoundIfFlexible()
233
241
234
- resolvedReturnType = if (resolvedReturnType is ConeTypeParameterType ) {
235
- if (resolvedReturnType .canBeNull(session)) {
242
+ returnType = if (returnType is ConeTypeParameterType ) {
243
+ if (returnType .canBeNull(session)) {
236
244
session.builtinTypes.nullableAnyType.type
237
245
} else {
238
246
session.builtinTypes.anyType.type
239
247
}
240
248
} else {
241
- resolvedReturnType .withArguments {
249
+ returnType .withArguments {
242
250
val type = it.type
243
251
if (type is ConeTypeParameterType ) {
244
252
session.builtinTypes.nullableAnyType.type
@@ -248,33 +256,34 @@ internal fun KotlinTypeFacade.toDataFrame(
248
256
}
249
257
}
250
258
251
- if (depth >= maxDepth || resolvedReturnType.isValueType() || resolvedReturnType.classId in preserveClasses || it in preserveProperties ) {
252
- SimpleDataColumn (name,
253
- TypeApproximation (resolvedReturnType)
254
- )
259
+ val fieldKind = returnType.getFieldKind(session)
260
+
261
+ val keepSubtree = depth >= maxDepth && ! fieldKind.shouldBeConvertedToColumnGroup && ! fieldKind.shouldBeConvertedToFrameColumn
262
+ if (keepSubtree || returnType.isValueType() || returnType.classId in preserveClasses || it in preserveProperties) {
263
+ SimpleDataColumn (name, TypeApproximation (returnType))
255
264
} else if (
256
- resolvedReturnType .isSubtypeOf(StandardClassIds .Iterable .constructClassLikeType(arrayOf(ConeStarProjection )), session) ||
257
- resolvedReturnType .isSubtypeOf(StandardClassIds .Iterable .constructClassLikeType(arrayOf(ConeStarProjection ), isNullable = true ), session)
265
+ returnType .isSubtypeOf(StandardClassIds .Iterable .constructClassLikeType(arrayOf(ConeStarProjection )), session) ||
266
+ returnType .isSubtypeOf(StandardClassIds .Iterable .constructClassLikeType(arrayOf(ConeStarProjection ), isNullable = true ), session)
258
267
) {
259
- val type: ConeKotlinType = when (val typeArgument = resolvedReturnType .typeArguments[0 ]) {
268
+ val type: ConeKotlinType = when (val typeArgument = returnType .typeArguments[0 ]) {
260
269
is ConeKotlinType -> typeArgument
261
270
ConeStarProjection -> session.builtinTypes.nullableAnyType.type
262
271
else -> session.builtinTypes.nullableAnyType.type
263
272
}
264
273
if (type.isValueType()) {
265
274
SimpleDataColumn (name,
266
275
TypeApproximation (
267
- StandardClassIds . List .constructClassLikeType(
276
+ List .constructClassLikeType(
268
277
arrayOf(type),
269
- resolvedReturnType .isNullable
278
+ returnType .isNullable
270
279
)
271
280
)
272
281
)
273
282
} else {
274
283
SimpleFrameColumn (name, convert(type, depth + 1 ))
275
284
}
276
285
} else {
277
- SimpleColumnGroup (name, convert(resolvedReturnType , depth + 1 ))
286
+ SimpleColumnGroup (name, convert(returnType , depth + 1 ))
278
287
}
279
288
}
280
289
}
@@ -291,6 +300,21 @@ internal fun KotlinTypeFacade.toDataFrame(
291
300
}
292
301
}
293
302
303
+ // org.jetbrains.kotlinx.dataframe.codeGen.getFieldKind
304
+ @Suppress(" INVISIBLE_MEMBER" )
305
+ private fun ConeKotlinType.getFieldKind (session : FirSession ) = when {
306
+ classId == DF_CLASS_ID -> Frame
307
+ classId == List && typeArguments[0 ].type.hasAnnotation(DATA_SCHEMA_CLASS_ID , session) -> ListToFrame
308
+ classId == DATA_ROW_CLASS_ID -> Group
309
+ hasAnnotation(DATA_SCHEMA_CLASS_ID , session) -> ObjectToGroup
310
+ else -> Default
311
+ }
312
+
313
+
314
+ private fun ConeKotlinType?.hasAnnotation (id : ClassId , session : FirSession ) =
315
+ this ?.toSymbol(session)?.hasAnnotation(id, session) == true
316
+
317
+
294
318
class CreateDataFrameDslImplApproximation {
295
319
val configuration: CreateDataFrameConfiguration = CreateDataFrameConfiguration ()
296
320
val columns: MutableList <SimpleCol > = mutableListOf ()
0 commit comments