[Analysis API] add tests for KtTypeScope

This commit is contained in:
Ilya Kirillov
2022-06-13 14:39:46 +02:00
parent b9907963fe
commit 36f370f501
25 changed files with 2072 additions and 4 deletions
@@ -12,9 +12,14 @@ import org.jetbrains.kotlin.analysis.api.calls.KtCall
import org.jetbrains.kotlin.analysis.api.calls.KtCallableMemberCall
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.analysis.api.impl.base.KtMapBackedSubstitutor
import org.jetbrains.kotlin.analysis.api.signatures.KtCallableSignature
import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature
import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
import kotlin.reflect.KProperty1
@@ -105,6 +110,35 @@ internal fun KtAnalysisSession.stringRepresentation(any: Any): String = with(any
}
}
internal fun KtAnalysisSession.prettyPrintSignature(signature: KtCallableSignature<*>): String = prettyPrint {
when (signature) {
is KtFunctionLikeSignature -> {
append("fun ")
signature.receiverType?.let { append('.'); append(it.render()) }
append((signature.symbol as KtNamedSymbol).name.asString())
printCollection(signature.valueParameters, prefix = "(", postfix = ")") { parameter ->
append(parameter.name.asString())
append(": ")
append(parameter.returnType.render())
}
append(": ")
append(signature.returnType.render())
}
is KtVariableLikeSignature -> {
val symbol = signature.symbol
if (symbol is KtVariableSymbol) {
append(if (symbol.isVal) "val" else "var")
append(" ")
}
signature.receiverType?.let { append('.'); append(it.render()) }
append((symbol as KtNamedSymbol).name.asString())
append(": ")
append(signature.returnType.render())
}
}
}
internal fun KtAnalysisSession.compareCalls(call1: KtCall, call2: KtCall): Int {
// The order of candidate calls is non-deterministic. Sort by symbol string value.
if (call1 !is KtCallableMemberCall<*, *> || call2 !is KtCallableMemberCall<*, *>) return 0
@@ -0,0 +1,103 @@
/*
* Copyright 2010-2022 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.
*/
/*
* Copyright 2010-2022 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.api.impl.base.test.cases.scopes
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
import org.jetbrains.kotlin.analysis.api.components.RendererModifier
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.prettyPrintSignature
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.stringRepresentation
import org.jetbrains.kotlin.analysis.api.scopes.KtScope
import org.jetbrains.kotlin.analysis.api.scopes.KtTypeScope
import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
abstract class AbstractTypeScopeTest : AbstractAnalysisApiSingleFileTest() {
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
val expression = testServices.expressionMarkerProvider.getSelectedElementOfType<KtExpression>(ktFile)
analyseForTest(expression) {
val type = expression.getKtType()
?: error("expression $expression is not typable")
val typeScope = type.getTypeScope()
val declaredScopeByTypeScope = typeScope?.getDeclarationScope()
val scopeStringRepresentation = prettyPrint {
appendLine("expression: ${expression.text}")
appendLine("KtType: ${type.render()}")
appendLine()
appendLine("KtTypeScope:")
appendLine(typeScope?.let { renderForTests(it) } ?: "NO_SCOPE")
appendLine()
appendLine("Declaration Scope:")
appendLine(declaredScopeByTypeScope?.let { renderForTests(it) } ?: "NO_SCOPE")
}
val signaturePretty = prettyPrint {
appendLine("KtTypeScope:")
appendLine(typeScope?.let { prettyPrintForTests(it) } ?: "NO_SCOPE")
appendLine()
appendLine("Declaration Scope:")
appendLine(declaredScopeByTypeScope?.let { prettyPrintForTests(it) } ?: "NO_SCOPE")
}
testServices.assertions.assertEqualsToTestDataFileSibling(scopeStringRepresentation)
testServices.assertions.assertEqualsToTestDataFileSibling(signaturePretty, extension = ".pretty.txt")
}
}
private fun KtAnalysisSession.renderForTests(typeScope: KtTypeScope): String {
val callables = typeScope.getCallableSignatures().toList()
return prettyPrint {
callables.forEach {
appendLine(stringRepresentation(it))
}
}
}
private fun KtAnalysisSession.prettyPrintForTests(typeScope: KtTypeScope): String {
val callables = typeScope.getCallableSignatures().toList()
return prettyPrint {
callables.forEach {
appendLine(prettyPrintSignature(it))
}
}
}
@Suppress("unused")
private fun KtAnalysisSession.renderForTests(scope: KtScope): String {
val callables = scope.getCallableSymbols().toList()
return prettyPrint {
callables.forEach {
appendLine(DebugSymbolRenderer.render(it))
}
}
}
private fun KtAnalysisSession.prettyPrintForTests(scope: KtScope): String {
val callables = scope.getCallableSymbols().toList()
return prettyPrint {
callables.forEach {
appendLine(it.render(options = KtDeclarationRendererOptions.DEFAULT.copy(modifiers = RendererModifier.NONE)))
}
}
}
}