[AA] KtSymbolPointer: introduce pointsToTheSameSymbolAs method

^KT-55191
This commit is contained in:
Dmitrii Gridin
2022-12-19 14:04:55 +01:00
committed by Space Team
parent 19a0a1fcd8
commit 13917887e0
34 changed files with 337 additions and 58 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertyAccessorSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
@KtAnalysisApiInternals
@@ -24,4 +25,9 @@ class KtPropertyAccessorSymbolPointer(
return if (isGetter) propertySymbol.getter else propertySymbol.setter
}
override fun pointsToTheSameSymbolAs(other: KtSymbolPointer<KtSymbol>): Boolean = this === other ||
other is KtPropertyAccessorSymbolPointer &&
other.isGetter == isGetter &&
other.propertySymbolPointer.pointsToTheSameSymbolAs(propertySymbolPointer)
}
@@ -22,4 +22,8 @@ class KtValueParameterFromDefaultSetterSymbolPointer(
return ownerSymbol?.setter?.parameter
}
override fun pointsToTheSameSymbolAs(other: KtSymbolPointer<KtSymbol>): Boolean = this === other ||
other is KtValueParameterFromDefaultSetterSymbolPointer &&
other.ownerPointer.pointsToTheSameSymbolAs(ownerPointer)
}
@@ -62,24 +62,27 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
fun KtAnalysisSession.safePointer(ktSymbol: KtSymbol): PointerWrapper? {
val regularPointer = ktSymbol.runCatching {
KtPsiBasedSymbolPointer.withDisabledPsiBasedPointers(disable = false) { ktSymbol.createPointer() }
createPointerForTest(disablePsiBasedSymbols = false)
}.let {
if (directiveToIgnoreSymbolRestore == null) it.getOrThrow() else it.getOrNull()
} ?: return null
val nonPsiPointer = kotlin.runCatching {
if (ktSymbol is KtFileSymbol) return@runCatching null
KtPsiBasedSymbolPointer.withDisabledPsiBasedPointers(disable = true) { ktSymbol.createPointer() }
assertSymbolPointer(regularPointer, testServices)
val nonPsiPointer = ktSymbol.runCatching {
if (this is KtFileSymbol) return@runCatching null
createPointerForTest(disablePsiBasedSymbols = true)
}
return PointerWrapper(
regularPointer = regularPointer,
pointerWithoutPsiAnchor = if (directiveToIgnoreSymbolRestore == null && directiveToIgnoreNonPsiSymbolRestore == null)
nonPsiPointer.getOrThrow()
else
nonPsiPointer.getOrNull(),
)
val pointerWithoutPsiAnchor = if (directiveToIgnoreSymbolRestore == null && directiveToIgnoreNonPsiSymbolRestore == null)
nonPsiPointer.getOrThrow()
else
nonPsiPointer.getOrNull()
if (pointerWithoutPsiAnchor != null) {
assertSymbolPointer(pointerWithoutPsiAnchor, testServices)
}
return PointerWrapper(regularPointer = regularPointer, pointerWithoutPsiAnchor = pointerWithoutPsiAnchor)
}
val pointersWithRendered = executeOnPooledThreadInReadAction {
@@ -130,7 +133,7 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
restoreSymbolsInOtherReadActionAndCompareResults(
directiveToIgnore = directiveToIgnoreSymbolRestore,
pointerAccessor = PointerWrapper::regularPointer,
isRegularPointers = true,
ktFile = ktFile,
pointersWithRendered = pointersWithRendered.pointers,
testServices = testServices,
@@ -139,7 +142,7 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
if (directiveToIgnoreSymbolRestore == null) {
restoreSymbolsInOtherReadActionAndCompareResults(
directiveToIgnore = directiveToIgnoreNonPsiSymbolRestore,
pointerAccessor = PointerWrapper::pointerWithoutPsiAnchor,
isRegularPointers = false,
ktFile = ktFile,
pointersWithRendered = pointersWithRendered.pointers,
testServices = testServices,
@@ -147,6 +150,16 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
}
}
context(KtAnalysisSession)
private fun KtSymbol.createPointerForTest(disablePsiBasedSymbols: Boolean): KtSymbolPointer<*> =
KtPsiBasedSymbolPointer.withDisabledPsiBasedPointers(disable = disablePsiBasedSymbols) { createPointer() }
private fun assertSymbolPointer(pointer: KtSymbolPointer<*>, testServices: TestServices) {
testServices.assertions.assertTrue(value = pointer.pointsToTheSameSymbolAs(pointer)) {
"The symbol is not equal to itself: ${pointer::class}"
}
}
private fun RegisteredDirectives.doNotCheckSymbolRestoreDirective(): Directive? = findSpecificDirective(
commonDirective = DO_NOT_CHECK_SYMBOL_RESTORE,
k1Directive = DO_NOT_CHECK_SYMBOL_RESTORE_K1,
@@ -187,17 +200,25 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
private fun restoreSymbolsInOtherReadActionAndCompareResults(
directiveToIgnore: Directive?,
pointerAccessor: (PointerWrapper) -> KtSymbolPointer<KtSymbol>?,
isRegularPointers: Boolean,
ktFile: KtFile,
pointersWithRendered: List<PointerWithRenderedSymbol>,
testServices: TestServices,
) {
var failed = false
val restoredPointers = mutableListOf<KtSymbolPointer<*>>()
try {
val restored = analyseForTest(ktFile) {
pointersWithRendered.mapNotNull { (pointerWrapper, expectedRender, shouldBeRendered) ->
val pointer = pointerWrapper?.let(pointerAccessor) ?: error("Symbol pointer for $expectedRender was not created")
val pointer = if (isRegularPointers) {
pointerWrapper?.regularPointer
} else {
pointerWrapper?.pointerWithoutPsiAnchor
} ?: error("Symbol pointer for $expectedRender was not created")
val restored = pointer.restoreSymbol() ?: error("Symbol $expectedRender was not restored")
restoredPointers += pointer
val actualRender = renderSymbolForComparison(restored)
if (shouldBeRendered) {
actualRender
@@ -215,6 +236,10 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
failed = true
}
if (!failed) {
compareRestoredSymbols(restoredPointers, testServices, ktFile, isRegularPointers)
}
if (failed || directiveToIgnore == null) return
testServices.assertions.assertEqualsToTestDataFileSibling(
@@ -225,6 +250,41 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
fail("Redundant // ${directiveToIgnore.name} directive")
}
private fun compareRestoredSymbols(
restoredPointers: List<KtSymbolPointer<*>>,
testServices: TestServices,
ktFile: KtFile,
isRegularPointers: Boolean,
) {
if (restoredPointers.isEmpty()) return
analyseForTest(ktFile) {
val symbolsToPointersMap = restoredPointers.groupByTo(mutableMapOf()) {
it.restoreSymbol() ?: error("Unexpectedly non-restored symbol pointer: ${it::class}")
}
val pointersToCheck = symbolsToPointersMap.map { (key, value) ->
value += if (isRegularPointers) {
key.createPointerForTest(disablePsiBasedSymbols = false)
} else {
key.createPointerForTest(disablePsiBasedSymbols = true)
}
value
}
for (pointers in pointersToCheck) {
for (firstPointer in pointers) {
for (secondPointer in pointers) {
testServices.assertions.assertTrue(firstPointer.pointsToTheSameSymbolAs(secondPointer)) {
"${firstPointer::class} is not the same as ${secondPointer::class}"
}
}
}
}
}
}
protected open fun KtAnalysisSession.renderSymbolForComparison(symbol: KtSymbol): String {
return with(DebugSymbolRenderer(renderExtra = true)) { render(symbol) }
}