Skip to content

Commit cdbb23f

Browse files
authored
Merge pull request #979 from Kotlin/cast-target-warning
[Compiler plugin] Add warning to avoid confusion with missing extension properties
2 parents 9ae0331 + e6130ba commit cdbb23f

File tree

4 files changed

+41
-2
lines changed

4 files changed

+41
-2
lines changed

plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/ExpressionAnalysisAdditionalChecker.kt

+11-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
99
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
1010
import org.jetbrains.kotlin.diagnostics.error1
1111
import org.jetbrains.kotlin.diagnostics.reportOn
12+
import org.jetbrains.kotlin.diagnostics.warning1
1213
import org.jetbrains.kotlin.fir.FirSession
1314
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
1415
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.fir.types.coneType
2930
import org.jetbrains.kotlin.fir.types.isSubtypeOf
3031
import org.jetbrains.kotlin.fir.types.renderReadable
3132
import org.jetbrains.kotlin.fir.types.resolvedType
33+
import org.jetbrains.kotlin.fir.types.toSymbol
3234
import org.jetbrains.kotlin.fir.types.type
3335
import org.jetbrains.kotlin.name.CallableId
3436
import org.jetbrains.kotlin.name.ClassId
@@ -38,6 +40,7 @@ import org.jetbrains.kotlin.psi.KtElement
3840
import org.jetbrains.kotlinx.dataframe.plugin.impl.PluginDataFrameSchema
3941
import org.jetbrains.kotlinx.dataframe.plugin.impl.SimpleDataColumn
4042
import org.jetbrains.kotlinx.dataframe.plugin.impl.type
43+
import org.jetbrains.kotlinx.dataframe.plugin.utils.Names
4144

4245
class 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)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FILE: targetOfCastIsNotDataSchema.kt
2+
public abstract interface MySchema : R|kotlin/Any| {
3+
public abstract val a: R|kotlin/String|
4+
public get(): R|kotlin/String|
5+
6+
}
7+
public final fun box(): R|kotlin/String| {
8+
lval df: R|{org/jetbrains/kotlinx/dataframe/AnyFrame=} org/jetbrains/kotlinx/dataframe/DataFrame<*>| = Q|org/jetbrains/kotlinx/dataframe/DataFrame|.R|org/jetbrains/kotlinx/dataframe/DataFrame.Companion.Empty|
9+
R|<local>/df|.R|org/jetbrains/kotlinx/dataframe/api/cast|<R|MySchema|>()
10+
^box String(OK)
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import org.jetbrains.kotlinx.dataframe.*
2+
import org.jetbrains.kotlinx.dataframe.annotations.*
3+
import org.jetbrains.kotlinx.dataframe.api.*
4+
import org.jetbrains.kotlinx.dataframe.io.*
5+
6+
interface MySchema {
7+
val a: String
8+
}
9+
fun box(): String {
10+
val df = DataFrame.Empty
11+
<!CAST_TARGET_WARNING!>df.cast<MySchema>()<!>
12+
return "OK"
13+
}

plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameDiagnosticTestGenerated.java

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ public void testStructuralCast() {
4444
runTest("testData/diagnostics/structuralCast.kt");
4545
}
4646

47+
@Test
48+
@TestMetadata("targetOfCastIsNotDataSchema.kt")
49+
public void testTargetOfCastIsNotDataSchema() {
50+
runTest("testData/diagnostics/targetOfCastIsNotDataSchema.kt");
51+
}
52+
4753
@Test
4854
@TestMetadata("toDataFrame_java.kt")
4955
public void testToDataFrame_java() {

0 commit comments

Comments
 (0)