Skip to content

Commit

Permalink
Merge pull request #788 from Kotlin/compiler-plugin-exception-fixes
Browse files Browse the repository at this point in the history
[Compiler plugin] Avoid throwing debugging exceptions in user projects because of false positives
  • Loading branch information
koperagen authored Jul 18, 2024
2 parents 4e3ba85 + 3590f91 commit 0daccc8
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,20 @@ class DataFrameCommandLineProcessor : CommandLineProcessor {

class FirDataFrameExtensionRegistrar(
private val path: String?,
val schemasDirectory: String?
val schemasDirectory: String?,
val isTest: Boolean,
) : FirExtensionRegistrar() {
@OptIn(FirExtensionApiInternals::class)
override fun ExtensionRegistrarContext.configurePlugin() {
+::ExtensionsGenerator
+::ReturnTypeBasedReceiverInjector
+{ it: FirSession ->
FunctionCallTransformer(path, it, jsonCache(it), schemasDirectory)
FunctionCallTransformer(path, it, jsonCache(it), schemasDirectory, isTest)
}
+::TokenGenerator
+::DataRowSchemaSupertype
+{ it: FirSession ->
ExpressionAnalysisAdditionalChecker(it, jsonCache(it), schemasDirectory)
ExpressionAnalysisAdditionalChecker(it, jsonCache(it), schemasDirectory, isTest)
}
}

Expand All @@ -92,7 +93,7 @@ class FirDataFrameComponentRegistrar : CompilerPluginRegistrar() {
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
val schemasDirectory = configuration.get(SCHEMAS)
val path = configuration.get(PATH)
FirExtensionRegistrarAdapter.registerExtension(FirDataFrameExtensionRegistrar(path, schemasDirectory))
FirExtensionRegistrarAdapter.registerExtension(FirDataFrameExtensionRegistrar(path, schemasDirectory, isTest = false))
IrGenerationExtension.registerExtension(IrBodyFiller(path, schemasDirectory))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,19 @@ import org.jetbrains.kotlinx.dataframe.plugin.impl.type
class ExpressionAnalysisAdditionalChecker(
session: FirSession,
cache: FirCache<String, PluginDataFrameSchema, KotlinTypeFacade>,
schemasDirectory: String?
schemasDirectory: String?,
isTest: Boolean,
) : FirAdditionalCheckersExtension(session) {
override val expressionCheckers: ExpressionCheckers = object : ExpressionCheckers() {
override val functionCallCheckers: Set<FirFunctionCallChecker> = setOf(Checker(cache, schemasDirectory))
override val functionCallCheckers: Set<FirFunctionCallChecker> = setOf(Checker(cache, schemasDirectory, isTest))
}
}

private class Checker(val cache: FirCache<String, PluginDataFrameSchema, KotlinTypeFacade>, val schemasDirectory: String?) : FirFunctionCallChecker(mppKind = MppCheckerKind.Common) {
private class Checker(
val cache: FirCache<String, PluginDataFrameSchema, KotlinTypeFacade>,
val schemasDirectory: String?,
val isTest: Boolean,
) : FirFunctionCallChecker(mppKind = MppCheckerKind.Common) {
companion object {
val ERROR by error1<KtElement, String>(SourceElementPositioningStrategies.DEFAULT)
val CAST_ERROR by error1<KtElement, String>(SourceElementPositioningStrategies.CALL_ELEMENT_WITH_DOT)
Expand All @@ -58,7 +63,7 @@ private class Checker(val cache: FirCache<String, PluginDataFrameSchema, KotlinT
}

override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
with(KotlinTypeFacadeImpl(context.session, cache, schemasDirectory)) {
with(KotlinTypeFacadeImpl(context.session, cache, schemasDirectory, isTest)) {
analyzeCast(expression, reporter, context)
// analyzeRefinedCallShape(expression, reporter = object : InterpretationErrorReporter {
// override var errorReported: Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class FunctionCallTransformer(
session: FirSession,
override val cache: FirCache<String, PluginDataFrameSchema, KotlinTypeFacade>,
override val schemasDirectory: String?,
override val isTest: Boolean,
) : FirFunctionCallRefinementExtension(session), KotlinTypeFacade {
companion object {
const val DEFAULT_NAME = "DataFrameType"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface KotlinTypeFacade {
val resolutionPath: String? get() = null
val cache: FirCache<String, PluginDataFrameSchema, KotlinTypeFacade>
val schemasDirectory: String?
val isTest: Boolean

fun Marker.type() = type

Expand Down Expand Up @@ -110,8 +111,8 @@ private fun String.collectionsId() = ClassId(StandardClassIds.BASE_COLLECTIONS_P
class KotlinTypeFacadeImpl(
override val session: FirSession,
override val cache: FirCache<String, PluginDataFrameSchema, KotlinTypeFacade>,
override val schemasDirectory: String?

override val schemasDirectory: String?,
override val isTest: Boolean
) : KotlinTypeFacade

class Marker private constructor(internal val type: ConeKotlinType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ fun <T> KotlinTypeFacade.interpret(
val defaultArguments = processor.expectedArguments.filter { it.defaultValue is Present }.map { it.name }.toSet()
val actualArgsMap = refinedArguments.associateBy { it.name.identifier }.toSortedMap()
val conflictingKeys = additionalArguments.keys intersect actualArgsMap.keys
if (conflictingKeys.isNotEmpty()) {
if (conflictingKeys.isNotEmpty() && isTest) {
interpretationFrameworkError("Conflicting keys: $conflictingKeys")
}
val expectedArgsMap = processor.expectedArguments
.filterNot { it.name.startsWith("typeArg") }
.associateBy { it.name }.toSortedMap().minus(additionalArguments.keys)

val unexpectedArguments = expectedArgsMap.keys - defaultArguments != actualArgsMap.keys - defaultArguments
if (unexpectedArguments) {
if (unexpectedArguments && isTest) {
val message = buildString {
appendLine("ERROR: Different set of arguments")
appendLine("Implementation class: $processor")
Expand Down Expand Up @@ -305,7 +305,7 @@ fun KotlinTypeFacade.pluginDataFrameSchema(schemaTypeArg: ConeTypeProjection): P
}

fun KotlinTypeFacade.pluginDataFrameSchema(coneClassLikeType: ConeClassLikeType): PluginDataFrameSchema {
val symbol = coneClassLikeType.toSymbol(session) as FirRegularClassSymbol
val symbol = coneClassLikeType.toSymbol(session) as? FirRegularClassSymbol ?: return PluginDataFrameSchema(emptyList())
val declarationSymbols = if (symbol.isLocal && symbol.resolvedSuperTypes.firstOrNull() != session.builtinTypes.anyType.type) {
val rootSchemaSymbol = symbol.resolvedSuperTypes.first().toSymbol(session) as FirRegularClassSymbol
rootSchemaSymbol.declaredMemberScope(session, FirResolvePhase.DECLARATIONS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ class ExperimentalExtensionRegistrarConfigurator(testServices: TestServices) : E
) {
FirExtensionRegistrarAdapter.registerExtension(
FirDataFrameExtensionRegistrar(
configuration.get(PATH)!!,
null
)
configuration.get(PATH)!!,
null,
isTest = true
)
)
IrGenerationExtension.registerExtension(IrBodyFiller(configuration.get(PATH), null))
}
Expand Down

0 comments on commit 0daccc8

Please sign in to comment.