From 30b1487afc403ce0b2b94c364205aee8edefb6eb Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 28 Sep 2021 19:19:51 +0200 Subject: [PATCH] LL API: add checks to the compiler based tests to ensure ConeTypeVariableType are not leaked --- .../based/AbstractCompilerBasedTest.kt | 6 +- .../based/LLDiagnosticParameterChecker.kt | 60 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTest.kt index 29d6e25a03f..9335d742846 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTest.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTest.kt @@ -11,11 +11,11 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilt import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile import org.jetbrains.kotlin.analysis.low.level.api.fir.createResolveStateForNoCaching import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.FirLazyTransformerForIDE -import org.jetbrains.kotlin.analysis.project.structure.* import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.test.TestConfiguration import org.jetbrains.kotlin.test.bind import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.builders.firHandlersStep import org.jetbrains.kotlin.test.builders.testConfiguration import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives import org.jetbrains.kotlin.test.directives.model.DirectivesContainer @@ -54,6 +54,10 @@ abstract class AbstractCompilerBasedTest : AbstractKotlinCompilerTest() { useAdditionalService(::TestKtModuleProvider) usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable)) + + firHandlersStep { + useHandlers(::LLDiagnosticParameterChecker) + } } open fun TestConfigurationBuilder.configureTest() {} diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt new file mode 100644 index 00000000000..2f0a3ca457e --- /dev/null +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based + +import org.jetbrains.kotlin.fir.analysis.diagnostics.* +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.ConeTypeVariableType +import org.jetbrains.kotlin.fir.types.contains +import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact +import org.jetbrains.kotlin.test.frontend.fir.handlers.FirAnalysisHandler +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions + +internal class LLDiagnosticParameterChecker(testServices: TestServices) : FirAnalysisHandler(testServices) { + override fun processModule(module: TestModule, info: FirOutputArtifact) { + val diagnostics = info.firAnalyzerFacade.runCheckers().values.flatten() + + for (diagnostic in diagnostics) { + checkDiagnosticIsSuitableForFirIde(diagnostic) + } + } + + private fun checkDiagnosticIsSuitableForFirIde(diagnostic: FirDiagnostic) { + val parameters = diagnostic.allParameters() + for (parameter in parameters) { + checkDiagnosticParameter(diagnostic, parameter) + } + } + + private fun checkDiagnosticParameter(diagnostic: FirDiagnostic, parameter: Any?) { + when (parameter) { + is ConeKotlinType -> checkType(parameter, diagnostic) + } + } + + private fun checkType(parameter: ConeKotlinType, diagnostic: FirDiagnostic) { + val containsTypeVariableType = parameter.contains { it is ConeTypeVariableType } + if (containsTypeVariableType) { + val rendered = FirDefaultErrorMessages.getRendererForDiagnostic(diagnostic).render(diagnostic) + testServices.assertions.fail { + "ConeTypeVariableType should not be exposed from diagnostic. But it was for ${diagnostic.factoryName} $rendered" + } + } + } + + private fun FirDiagnostic.allParameters(): List = when (this) { + is FirPsiDiagnosticWithParameters1<*> -> listOf(a) + is FirPsiDiagnosticWithParameters2<*, *> -> listOf(a, b) + is FirPsiDiagnosticWithParameters3<*, *, *> -> listOf(a, b, c) + is FirPsiDiagnosticWithParameters4<*, *, *, *> -> listOf(a, b, c, d) + is FirPsiSimpleDiagnostic -> emptyList() + else -> error("Unexpected diagnostic $this") + } + + override fun processAfterAllModules(someAssertionWasFailed: Boolean) {} +}