From 68fecefac577c5514e8086604f45aad64e1a29b2 Mon Sep 17 00:00:00 2001 From: Nikita Klimenko Date: Mon, 25 Nov 2024 16:05:11 +0200 Subject: [PATCH] [Compiler plugin] Add checkers that report compile time schema as info warnings to observe implicit schema generation --- .../plugin/FirDataFrameComponentRegistrar.kt | 7 +- .../ExpressionAnalysisAdditionalChecker.kt | 114 +++++++++++++++++- .../plugin/extensions/KotlinTypeFacade.kt | 11 +- .../dataframe/plugin/impl/SimpleCol.kt | 8 +- .../kotlinx/dataframe/plugin/interpret.kt | 11 +- .../kotlinx/dataframe/plugin/utils/Names.kt | 6 + .../testData/diagnostics/schemaInfo.fir.txt | 103 ++++++++++++++++ .../testData/diagnostics/schemaInfo.kt | 18 +++ .../DataFrameDiagnosticTestGenerated.java | 12 ++ .../AbstractDataFrameDiagnosticTest.kt | 2 + .../ExtensionRegistrarConfigurators.kt | 12 +- 11 files changed, 287 insertions(+), 17 deletions(-) create mode 100644 plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.fir.txt create mode 100644 plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.kt diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/FirDataFrameComponentRegistrar.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/FirDataFrameComponentRegistrar.kt index 68f4accc73..778ce06892 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/FirDataFrameComponentRegistrar.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/FirDataFrameComponentRegistrar.kt @@ -65,6 +65,7 @@ class FirDataFrameExtensionRegistrar( private val path: String?, val schemasDirectory: String?, val isTest: Boolean, + val dumpSchemas: Boolean, ) : FirExtensionRegistrar() { @OptIn(FirExtensionApiInternals::class) override fun ExtensionRegistrarContext.configurePlugin() { @@ -76,7 +77,7 @@ class FirDataFrameExtensionRegistrar( +::TokenGenerator +::DataRowSchemaSupertype +{ it: FirSession -> - ExpressionAnalysisAdditionalChecker(it, jsonCache(it), schemasDirectory, isTest) + ExpressionAnalysisAdditionalChecker(it, jsonCache(it), schemasDirectory, isTest, dumpSchemas) } } @@ -93,7 +94,9 @@ class FirDataFrameComponentRegistrar : CompilerPluginRegistrar() { override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) { val schemasDirectory = configuration.get(SCHEMAS) val path = configuration.get(PATH) - FirExtensionRegistrarAdapter.registerExtension(FirDataFrameExtensionRegistrar(path, schemasDirectory, isTest = false)) + FirExtensionRegistrarAdapter.registerExtension( + FirDataFrameExtensionRegistrar(path, schemasDirectory, isTest = false, dumpSchemas = true) + ) IrGenerationExtension.registerExtension(IrBodyFiller(path, schemasDirectory)) } diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/ExpressionAnalysisAdditionalChecker.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/ExpressionAnalysisAdditionalChecker.kt index 59533e4aee..0d0083d06f 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/ExpressionAnalysisAdditionalChecker.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/ExpressionAnalysisAdditionalChecker.kt @@ -5,7 +5,13 @@ package org.jetbrains.kotlinx.dataframe.plugin.extensions +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.diagnostics.AbstractSourceElementPositioningStrategy +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1DelegateProvider import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory1 +import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies import org.jetbrains.kotlin.diagnostics.error1 import org.jetbrains.kotlin.diagnostics.reportOn @@ -13,18 +19,24 @@ import org.jetbrains.kotlin.diagnostics.warning1 import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSimpleFunctionChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker +import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirPropertyAccessExpressionChecker import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension import org.jetbrains.kotlin.fir.caches.FirCache -import org.jetbrains.kotlinx.dataframe.plugin.impl.api.flatten -import org.jetbrains.kotlinx.dataframe.plugin.pluginDataFrameSchema +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.hasAnnotation import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.isSubtypeOf @@ -39,17 +51,30 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlinx.dataframe.plugin.impl.PluginDataFrameSchema import org.jetbrains.kotlinx.dataframe.plugin.impl.SimpleDataColumn -import org.jetbrains.kotlinx.dataframe.plugin.impl.type +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.flatten +import org.jetbrains.kotlinx.dataframe.plugin.pluginDataFrameSchema import org.jetbrains.kotlinx.dataframe.plugin.utils.Names +import org.jetbrains.kotlinx.dataframe.plugin.utils.isDataFrame +import org.jetbrains.kotlinx.dataframe.plugin.utils.isGroupBy class ExpressionAnalysisAdditionalChecker( session: FirSession, cache: FirCache, schemasDirectory: String?, isTest: Boolean, + dumpSchemas: Boolean ) : FirAdditionalCheckersExtension(session) { override val expressionCheckers: ExpressionCheckers = object : ExpressionCheckers() { - override val functionCallCheckers: Set = setOf(Checker(cache, schemasDirectory, isTest)) + override val functionCallCheckers: Set = setOfNotNull( + Checker(cache, schemasDirectory, isTest), FunctionCallSchemaReporter.takeIf { dumpSchemas } + ) + override val propertyAccessExpressionCheckers: Set = setOfNotNull( + PropertyAccessSchemaReporter.takeIf { dumpSchemas } + ) + } + override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() { + override val propertyCheckers: Set = setOfNotNull(PropertySchemaReporter.takeIf { dumpSchemas }) + override val simpleFunctionCheckers: Set = setOfNotNull(FunctionDeclarationSchemaReporter.takeIf { dumpSchemas }) } } @@ -132,3 +157,84 @@ private class Checker( } } } + +private data object PropertySchemaReporter : FirPropertyChecker(mppKind = MppCheckerKind.Common) { + val SCHEMA by info1(SourceElementPositioningStrategies.DECLARATION_NAME) + + override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { + context.sessionContext { + declaration.returnTypeRef.coneType.let { type -> + reportSchema(reporter, declaration.source, SCHEMA, type, context) + } + } + } +} + +private data object FunctionCallSchemaReporter : FirFunctionCallChecker(mppKind = MppCheckerKind.Common) { + val SCHEMA by info1(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) + + override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { + if (expression.calleeReference.name in setOf(Name.identifier("let"), Name.identifier("run"))) return + val initializer = expression.resolvedType + context.sessionContext { + reportSchema(reporter, expression.source, SCHEMA, initializer, context) + } + } +} + +private data object PropertyAccessSchemaReporter : FirPropertyAccessExpressionChecker(mppKind = MppCheckerKind.Common) { + val SCHEMA by info1(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) + + override fun check( + expression: FirPropertyAccessExpression, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val initializer = expression.resolvedType + context.sessionContext { + reportSchema(reporter, expression.source, SCHEMA, initializer, context) + } + } +} + +private data object FunctionDeclarationSchemaReporter : FirSimpleFunctionChecker(mppKind = MppCheckerKind.Common) { + val SCHEMA by info1(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) + + override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) { + val type = declaration.returnTypeRef.coneType + context.sessionContext { + reportSchema(reporter, declaration.source, SCHEMA, type, context) + } + } +} + +private fun SessionContext.reportSchema( + reporter: DiagnosticReporter, + source: KtSourceElement?, + factory: KtDiagnosticFactory1, + type: ConeKotlinType, + context: CheckerContext, +) { + val schema: PluginDataFrameSchema? = if (type.isDataFrame(session)) { + type.typeArguments.getOrNull(0)?.let { + pluginDataFrameSchema(it) + } + } else if (type.isGroupBy(session)) { + null + } else { + null + } + if (schema != null && source != null) { + reporter.reportOn(source, factory, "\n" + schema.toString(), context) + } +} + +fun CheckerContext.sessionContext(f: SessionContext.() -> Unit) { + SessionContext(session).f() +} + +inline fun info1( + positioningStrategy: AbstractSourceElementPositioningStrategy = SourceElementPositioningStrategies.DEFAULT +): DiagnosticFactory1DelegateProvider { + return DiagnosticFactory1DelegateProvider(Severity.INFO, positioningStrategy, P::class) +} diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/KotlinTypeFacade.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/KotlinTypeFacade.kt index 75d1d37800..307575490e 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/KotlinTypeFacade.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/KotlinTypeFacade.kt @@ -27,8 +27,7 @@ import kotlin.reflect.KType import kotlin.reflect.KTypeProjection import kotlin.reflect.KVariance -interface KotlinTypeFacade { - val session: FirSession +interface KotlinTypeFacade : SessionContext { val resolutionPath: String? get() = null val cache: FirCache val schemasDirectory: String? @@ -99,6 +98,14 @@ interface KotlinTypeFacade { } } +interface SessionContext { + val session: FirSession +} + +fun SessionContext(session: FirSession) = object : SessionContext { + override val session: FirSession = session +} + private val List = "List".collectionsId() private fun ConeKotlinType.isBuiltinType(classId: ClassId, isNullable: Boolean?): Boolean { diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/SimpleCol.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/SimpleCol.kt index 06551c1cf1..2fd873f506 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/SimpleCol.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/SimpleCol.kt @@ -6,6 +6,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClassId import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeNullability import org.jetbrains.kotlin.fir.types.isNullable +import org.jetbrains.kotlin.fir.types.renderReadable import org.jetbrains.kotlinx.dataframe.plugin.extensions.KotlinTypeFacade import org.jetbrains.kotlinx.dataframe.plugin.extensions.wrap import org.jetbrains.kotlinx.dataframe.plugin.impl.api.TypeApproximation @@ -28,16 +29,17 @@ data class PluginDataFrameSchema( } private fun List.asString(indent: String = ""): String { + if (isEmpty()) return "$indent" return joinToString("\n") { val col = when (it) { is SimpleFrameColumn -> { - "${it.name}*\n" + it.columns().asString("$indent ") + "${it.name}: *\n" + it.columns().asString("$indent ") } is SimpleColumnGroup -> { - "${it.name}\n" + it.columns().asString("$indent ") + "${it.name}:\n" + it.columns().asString("$indent ") } is SimpleDataColumn -> { - "${it.name}: ${it.type}" + "${it.name}: ${it.type.type.renderReadable()}" } } "$indent$col" diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt index fe135e62a5..17fa8b996a 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt @@ -68,6 +68,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlinx.dataframe.annotations.* +import org.jetbrains.kotlinx.dataframe.plugin.extensions.SessionContext import org.jetbrains.kotlinx.dataframe.plugin.impl.data.ColumnPathApproximation import org.jetbrains.kotlinx.dataframe.plugin.impl.data.ColumnWithPathApproximation import org.jetbrains.kotlinx.dataframe.plugin.impl.data.DataFrameCallableId @@ -320,7 +321,7 @@ interface InterpretationErrorReporter { } } -fun KotlinTypeFacade.pluginDataFrameSchema(schemaTypeArg: ConeTypeProjection): PluginDataFrameSchema { +fun SessionContext.pluginDataFrameSchema(schemaTypeArg: ConeTypeProjection): PluginDataFrameSchema { val schema = if (schemaTypeArg.isStarProjection) { PluginDataFrameSchema.EMPTY } else { @@ -330,7 +331,7 @@ fun KotlinTypeFacade.pluginDataFrameSchema(schemaTypeArg: ConeTypeProjection): P return schema } -fun KotlinTypeFacade.pluginDataFrameSchema(coneClassLikeType: ConeClassLikeType): PluginDataFrameSchema { +fun SessionContext.pluginDataFrameSchema(coneClassLikeType: ConeClassLikeType): PluginDataFrameSchema { val symbol = coneClassLikeType.toSymbol(session) as? FirRegularClassSymbol ?: return PluginDataFrameSchema.EMPTY val declarationSymbols = if (symbol.isLocal && symbol.resolvedSuperTypes.firstOrNull() != session.builtinTypes.anyType.type) { val rootSchemaSymbol = symbol.resolvedSuperTypes.first().toSymbol(session) as? FirRegularClassSymbol @@ -394,7 +395,7 @@ private fun KotlinTypeFacade.columnWithPathApproximations(result: FirPropertyAcc } } -private fun KotlinTypeFacade.columnOf(it: FirPropertySymbol, mapping: Map): SimpleCol? { +private fun SessionContext.columnOf(it: FirPropertySymbol, mapping: Map): SimpleCol? { val annotation = it.getAnnotationByClassId(Names.COLUMN_NAME_ANNOTATION, session) val columnName = (annotation?.argumentMapping?.mapping?.get(Names.COLUMN_NAME_ARGUMENT) as? FirLiteralExpression)?.value as? String val name = columnName ?: it.name.identifier @@ -443,14 +444,14 @@ private fun KotlinTypeFacade.columnOf(it: FirPropertySymbol, mapping: Map.classId(): ClassId { val className = fqName.substringAfterLast(".") return ClassId(FqName(packageFqName), Name.identifier(className)) } + +fun ConeKotlinType.isDataFrame(session: FirSession) = fullyExpandedClassId(session) == Names.DF_CLASS_ID +fun ConeKotlinType.isGroupBy(session: FirSession) = fullyExpandedClassId(session) == Names.GROUP_BY_CLASS_ID diff --git a/plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.fir.txt b/plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.fir.txt new file mode 100644 index 0000000000..c17bb74075 --- /dev/null +++ b/plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.fir.txt @@ -0,0 +1,103 @@ +FILE: schemaInfo.kt + public abstract interface MySchema : R|kotlin/Any| { + public abstract val a: R|kotlin/String| + public get(): R|kotlin/String| + + } + private final fun a(): R|org/jetbrains/kotlinx/dataframe/DataFrame</Int_87>| { + ^a R|kotlin/collections/listOf|(Int(1)).R|kotlin/let||, R|org/jetbrains/kotlinx/dataframe/DataFrame</Int_87>|>( = fun (it: R|kotlin/collections/List|): R|org/jetbrains/kotlinx/dataframe/DataFrame</Int_87>| { + local abstract class Int_87I : R|kotlin/Any| { + @R|org/jetbrains/kotlinx/dataframe/annotations/Order|(order = Int(0)) public abstract val a: R|kotlin/Int| + public get(): R|kotlin/Int| + + public constructor(): R|/Int_87I| + + } + + local final class Scope0 : R|kotlin/Any| { + public final val R|org/jetbrains/kotlinx/dataframe/DataRow</Int_87I>|.a: R|kotlin/Int| + public get(): R|kotlin/Int| + + public final val R|org/jetbrains/kotlinx/dataframe/ColumnsScope</Int_87I>|.a: R|org/jetbrains/kotlinx/dataframe/DataColumn| + public get(): R|org/jetbrains/kotlinx/dataframe/DataColumn| + + public constructor(): R|/Scope0| + + } + + local abstract class Int_87 : R|/Int_87I| { + @R|org/jetbrains/kotlinx/dataframe/annotations/ScopeProperty|() public abstract val scope0: R|/Scope0| + public get(): R|/Scope0| + + public constructor(): R|/Int_87| + + } + + ^ R|/it|.R|org/jetbrains/kotlinx/dataframe/api/toDataFrame|( = toDataFrame@fun R|org/jetbrains/kotlinx/dataframe/api/CreateDataFrameDsl|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, String(a)).R|SubstitutionOverride|(from@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it| + } + ) + } + ) + } + ) + } + public final fun test(): R|kotlin/Unit| { + lval df: R|org/jetbrains/kotlinx/dataframe/DataFrame</Invoke_36>| = R|org/jetbrains/kotlinx/dataframe/api/dataFrameOf|(vararg(String(a))).R|kotlin/let|/Invoke_36>|>( = fun (it: R|org/jetbrains/kotlinx/dataframe/api/DataFrameBuilder|): R|org/jetbrains/kotlinx/dataframe/DataFrame</Invoke_36>| { + local abstract class Invoke_36I : R|kotlin/Any| { + @R|org/jetbrains/kotlinx/dataframe/annotations/Order|(order = Int(0)) public abstract val a: R|kotlin/Int| + public get(): R|kotlin/Int| + + public constructor(): R|/Invoke_36I| + + } + + local final class Scope0 : R|kotlin/Any| { + public final val R|org/jetbrains/kotlinx/dataframe/DataRow</Invoke_36I>|.a: R|kotlin/Int| + public get(): R|kotlin/Int| + + public final val R|org/jetbrains/kotlinx/dataframe/ColumnsScope</Invoke_36I>|.a: R|org/jetbrains/kotlinx/dataframe/DataColumn| + public get(): R|org/jetbrains/kotlinx/dataframe/DataColumn| + + public constructor(): R|/Scope0| + + } + + local abstract class Invoke_36 : R|/Invoke_36I| { + @R|org/jetbrains/kotlinx/dataframe/annotations/ScopeProperty|() public abstract val scope0: R|/Scope0| + public get(): R|/Scope0| + + public constructor(): R|/Invoke_36| + + } + + ^ R|/it|.R|org/jetbrains/kotlinx/dataframe/api/DataFrameBuilder.invoke|(vararg(Int(123))) + } + ) + R|/df|.R|kotlin/let|/Invoke_36>|, R|org/jetbrains/kotlinx/dataframe/DataFrame</Invoke_92>|>( = fun (it: R|org/jetbrains/kotlinx/dataframe/DataFrame</Invoke_36>|): R|org/jetbrains/kotlinx/dataframe/DataFrame</Invoke_92>| { + local abstract class Invoke_92I : R|kotlin/Any| { + public constructor(): R|/Invoke_92I| + + } + + local final class Scope0 : R|kotlin/Any| { + public constructor(): R|/Scope0| + + } + + local abstract class Invoke_92 : R|/Invoke_92I| { + @R|org/jetbrains/kotlinx/dataframe/annotations/ScopeProperty|() public abstract val scope0: R|/Scope0| + public get(): R|/Scope0| + + public constructor(): R|/Invoke_92| + + } + + ^ R|/it|.R|org/jetbrains/kotlinx/dataframe/api/remove|/Invoke_36|>( = remove@fun R|org/jetbrains/kotlinx/dataframe/api/ColumnsSelectionDsl</Invoke_36>|.(it: R|org/jetbrains/kotlinx/dataframe/api/ColumnsSelectionDsl</Invoke_36>|): R|org/jetbrains/kotlinx/dataframe/columns/ColumnsResolver<*>| { + ^ (this@R|/test|, this@R|special/anonymous|).R|/Scope0.a| + } + ) + } + ) + } diff --git a/plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.kt b/plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.kt new file mode 100644 index 0000000000..7d20edcfc2 --- /dev/null +++ b/plugins/kotlin-dataframe/testData/diagnostics/schemaInfo.kt @@ -0,0 +1,18 @@ +// DUMP_SCHEMAS +import org.jetbrains.kotlinx.dataframe.* +import org.jetbrains.kotlinx.dataframe.annotations.* +import org.jetbrains.kotlinx.dataframe.api.* +import org.jetbrains.kotlinx.dataframe.io.* + +interface MySchema { + val a: String +} + +private fun a() = listOf(1).toDataFrame { + "a" from { it } +} + +fun test() { + val df = dataFrameOf("a")(123) + df.remove { a } +} diff --git a/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameDiagnosticTestGenerated.java b/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameDiagnosticTestGenerated.java index dfc30eb01d..6a600d5f1b 100644 --- a/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameDiagnosticTestGenerated.java +++ b/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameDiagnosticTestGenerated.java @@ -26,12 +26,24 @@ public void testDisableInterpretation() { runTest("testData/diagnostics/disableInterpretation.kt"); } + @Test + @TestMetadata("ff.kt") + public void testFf() { + runTest("testData/diagnostics/ff.kt"); + } + @Test @TestMetadata("HistoryItem.kt") public void testHistoryItem() { runTest("testData/diagnostics/HistoryItem.kt"); } + @Test + @TestMetadata("schemaInfo.kt") + public void testSchemaInfo() { + runTest("testData/diagnostics/schemaInfo.kt"); + } + @Test @TestMetadata("selectDuringTyping.kt") public void testSelectDuringTyping() { diff --git a/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/AbstractDataFrameDiagnosticTest.kt b/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/AbstractDataFrameDiagnosticTest.kt index 814fa4f2c5..6675815469 100644 --- a/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/AbstractDataFrameDiagnosticTest.kt +++ b/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/AbstractDataFrameDiagnosticTest.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.dataframe +import org.jetbrains.kotlin.fir.dataframe.services.Directives import org.jetbrains.kotlin.fir.dataframe.services.DataFramePluginAnnotationsProvider import org.jetbrains.kotlin.fir.dataframe.services.ExperimentalExtensionRegistrarConfigurator import org.jetbrains.kotlin.fir.dataframe.services.TemporaryDirectoryManagerImplFixed @@ -54,6 +55,7 @@ abstract class AbstractDataFrameDiagnosticTest : AbstractKotlinCompilerTest() { JvmEnvironmentConfigurationDirectives.JDK_KIND with TestJdkKind.FULL_JDK } + useDirectives(Directives) useConfigurators( ::DataFramePluginAnnotationsProvider, ::ExperimentalExtensionRegistrarConfigurator diff --git a/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/services/ExtensionRegistrarConfigurators.kt b/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/services/ExtensionRegistrarConfigurators.kt index 78b7893ae8..8cbc58cfcd 100644 --- a/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/services/ExtensionRegistrarConfigurators.kt +++ b/plugins/kotlin-dataframe/tests/org/jetbrains/kotlin/fir/dataframe/services/ExtensionRegistrarConfigurators.kt @@ -12,9 +12,11 @@ import org.jetbrains.kotlinx.dataframe.plugin.FirDataFrameExtensionRegistrar import org.jetbrains.kotlinx.dataframe.plugin.PATH import org.jetbrains.kotlinx.dataframe.plugin.extensions.IrBodyFiller import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter +import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.EnvironmentConfigurator import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.moduleStructure class ExperimentalExtensionRegistrarConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) { @@ -26,13 +28,21 @@ class ExperimentalExtensionRegistrarConfigurator(testServices: TestServices) : E module: TestModule, configuration: CompilerConfiguration ) { + val dumpSchemas = testServices.moduleStructure.allDirectives.contains(Directives.DUMP_SCHEMAS) FirExtensionRegistrarAdapter.registerExtension( FirDataFrameExtensionRegistrar( configuration.get(PATH)!!, null, - isTest = true + isTest = true, + dumpSchemas ) ) IrGenerationExtension.registerExtension(IrBodyFiller(configuration.get(PATH), null)) } } + +internal object Directives : SimpleDirectivesContainer() { + val DUMP_SCHEMAS by directive( + description = "Whether checkers should report schemas as info warnings" + ) +}