[AA] AbstractSymbolTest: add assertion on redundant directive

^KT-54311
This commit is contained in:
Dmitrii Gridin
2022-10-05 18:17:42 +02:00
committed by Space Team
parent 3c2e0cb3b9
commit 119f6858cd
6 changed files with 48 additions and 22 deletions
@@ -7,21 +7,26 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.SymbolTestDirectives.DO_NOT_CHECK_SYMBOL_RESTORE
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.SymbolTestDirectives.DO_NOT_CHECK_SYMBOL_RESTORE_K1
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.SymbolTestDirectives.DO_NOT_CHECK_SYMBOL_RESTORE_K2
import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
import org.jetbrains.kotlin.analysis.test.framework.utils.executeOnPooledThreadInReadAction
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability
import org.jetbrains.kotlin.test.directives.model.Directive
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
import kotlin.test.fail
abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
private val renderingOptions = KtDeclarationRendererOptions.DEFAULT
@@ -38,27 +43,35 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
abstract fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): SymbolsData
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
val createPointers = SymbolTestDirectives.DO_NOT_CHECK_SYMBOL_RESTORE !in module.directives
val directives = module.directives
val directiveToIgnore = DO_NOT_CHECK_SYMBOL_RESTORE.takeIf { it in directives }
?: DO_NOT_CHECK_SYMBOL_RESTORE_K1.takeIf { configurator.frontendKind == FrontendKind.Fe10 && it in directives }
?: DO_NOT_CHECK_SYMBOL_RESTORE_K2.takeIf { configurator.frontendKind == FrontendKind.Fir && it in directives }
val prettyRenderOptions = when (prettyRenderMode) {
PrettyRenderingMode.RENDER_SYMBOLS_LINE_BY_LINE -> renderingOptions
PrettyRenderingMode.RENDER_SYMBOLS_NESTED -> renderingOptions.copy(renderClassMembers = true)
}
fun KtSymbol.safePointer(): KtSymbolPointer<KtSymbol>? {
val result = kotlin.runCatching { createPointer() }
return if (directiveToIgnore == null) result.getOrThrow() else result.getOrNull()
}
val pointersWithRendered = executeOnPooledThreadInReadAction {
analyseForTest(ktFile) {
val (symbols, symbolForPrettyRendering) = collectSymbols(ktFile, testServices)
val pointerWithRenderedSymbol = symbols.map { symbol ->
PointerWithRenderedSymbol(
if (createPointers) symbol.createPointer() else null,
symbol.safePointer(),
renderSymbolForComparison(symbol),
)
}
val pointerWithPrettyRenderedSymbol = symbolForPrettyRendering.map { symbol ->
PointerWithRenderedSymbol(
if (createPointers) symbol.createPointer() else null,
symbol.safePointer(),
when (symbol) {
is KtDeclarationSymbol -> symbol.render(prettyRenderOptions)
is KtFileSymbol -> prettyPrint {
@@ -80,9 +93,7 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
configurator.doOutOfBlockModification(ktFile)
if (createPointers) {
restoreSymbolsInOtherReadActionAndCompareResults(ktFile, pointersWithRendered.pointers, testServices)
}
restoreSymbolsInOtherReadActionAndCompareResults(directiveToIgnore, ktFile, pointersWithRendered.pointers, testServices)
}
private fun compareResults(
@@ -104,20 +115,35 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
else joinToString(separator = "\n\n")
private fun restoreSymbolsInOtherReadActionAndCompareResults(
directiveToIgnore: Directive?,
ktFile: KtFile,
pointersWithRendered: List<PointerWithRenderedSymbol>,
testServices: TestServices,
) {
val restored = analyseForTest(ktFile) {
pointersWithRendered.map { (pointer, expectedRender) ->
val restored = pointer!!.restoreSymbol()
?: error("Symbol $expectedRender was not restored")
var failed = false
try {
val restored = analyseForTest(ktFile) {
pointersWithRendered.map { (pointer, expectedRender) ->
val restored = pointer!!.restoreSymbol() ?: error("Symbol $expectedRender was not restored")
renderSymbolForComparison(restored)
renderSymbolForComparison(restored)
}
}
val actual = restored.renderAsDeclarations()
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
} catch (e: Throwable) {
if (directiveToIgnore == null) throw e
failed = true
}
val actual = restored.renderAsDeclarations()
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
if (failed || directiveToIgnore == null) return
testServices.assertions.assertEqualsToTestDataFileSibling(
actual = ktFile.text.lines().filterNot { it == "// ${directiveToIgnore.name}" }.joinToString(separator = "\n"),
extension = "kt",
)
fail("Redundant // ${directiveToIgnore.name} directive")
}
protected open fun KtAnalysisSession.renderSymbolForComparison(symbol: KtSymbol): String {
@@ -128,7 +154,14 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
object SymbolTestDirectives : SimpleDirectivesContainer() {
val DO_NOT_CHECK_SYMBOL_RESTORE by directive(
description = "Symbol restoring for some symbols in current test is not supported yet",
applicability = DirectiveApplicability.Global
)
val DO_NOT_CHECK_SYMBOL_RESTORE_K1 by directive(
description = "Symbol restoring for some symbols in current test is not supported yet in K1",
)
val DO_NOT_CHECK_SYMBOL_RESTORE_K2 by directive(
description = "Symbol restoring for some symbols in current test is not supported yet in K2",
)
}