@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
99import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
1010import org.jetbrains.kotlin.diagnostics.error1
1111import org.jetbrains.kotlin.diagnostics.reportOn
12+ import org.jetbrains.kotlin.diagnostics.warning1
1213import org.jetbrains.kotlin.fir.FirSession
1314import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
1415import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.fir.types.coneType
2930import org.jetbrains.kotlin.fir.types.isSubtypeOf
3031import org.jetbrains.kotlin.fir.types.renderReadable
3132import org.jetbrains.kotlin.fir.types.resolvedType
33+ import org.jetbrains.kotlin.fir.types.toSymbol
3234import org.jetbrains.kotlin.fir.types.type
3335import org.jetbrains.kotlin.name.CallableId
3436import org.jetbrains.kotlin.name.ClassId
@@ -38,6 +40,7 @@ import org.jetbrains.kotlin.psi.KtElement
3840import org.jetbrains.kotlinx.dataframe.plugin.impl.PluginDataFrameSchema
3941import org.jetbrains.kotlinx.dataframe.plugin.impl.SimpleDataColumn
4042import org.jetbrains.kotlinx.dataframe.plugin.impl.type
43+ import org.jetbrains.kotlinx.dataframe.plugin.utils.Names
4144
4245class ExpressionAnalysisAdditionalChecker (
4346 session : FirSession ,
@@ -58,6 +61,7 @@ private class Checker(
5861 companion object {
5962 val ERROR by error1<KtElement , String >(SourceElementPositioningStrategies .DEFAULT )
6063 val CAST_ERROR by error1<KtElement , String >(SourceElementPositioningStrategies .CALL_ELEMENT_WITH_DOT )
64+ val CAST_TARGET_WARNING by warning1<KtElement , String >(SourceElementPositioningStrategies .CALL_ELEMENT_WITH_DOT )
6165 val CAST_ID = CallableId (FqName .fromSegments(listOf (" org" , " jetbrains" , " kotlinx" , " dataframe" , " api" )), Name .identifier(" cast" ))
6266 val CHECK = ClassId (FqName (" org.jetbrains.kotlinx.dataframe.annotations" ), Name .identifier(" Check" ))
6367 }
@@ -87,13 +91,18 @@ private class Checker(
8791 || ! calleeReference.resolvedSymbol.hasAnnotation(CHECK , session)) {
8892 return
8993 }
94+ val targetProjection = expression.typeArguments.getOrNull(0 ) as ? FirTypeProjectionWithVariance ? : return
95+ val targetType = targetProjection.typeRef.coneType as ? ConeClassLikeType ? : return
96+ val targetSymbol = targetType.toSymbol(session)
97+ if (targetSymbol != null && ! targetSymbol.hasAnnotation(Names .DATA_SCHEMA_CLASS_ID , session)) {
98+ val text = " Annotate ${targetType.renderReadable()} with @DataSchema to use generated properties"
99+ reporter.reportOn(expression.source, CAST_TARGET_WARNING , text, context)
100+ }
90101 val coneType = expression.explicitReceiver?.resolvedType
91102 if (coneType != null ) {
92103 val sourceType = coneType.fullyExpandedType(session).typeArguments.getOrNull(0 )?.type as ? ConeClassLikeType
93104 ? : return
94105 val source = pluginDataFrameSchema(sourceType)
95- val targetProjection = expression.typeArguments.getOrNull(0 ) as ? FirTypeProjectionWithVariance ? : return
96- val targetType = targetProjection.typeRef.coneType as ? ConeClassLikeType ? : return
97106 val target = pluginDataFrameSchema(targetType)
98107 val sourceColumns = source.flatten(includeFrames = true )
99108 val targetColumns = target.flatten(includeFrames = true )
0 commit comments