[FIR] Add ability to specify members in FirScopeDumpHandler

This commit is contained in:
Dmitriy Novozhilov
2021-12-09 12:13:12 +03:00
parent d588b2e654
commit 09a7a1c09f
5 changed files with 49 additions and 19 deletions
@@ -30,6 +30,10 @@ class HandlersStepBuilder<I : ResultingArtifact<I>>(val artifactKind: TestArtifa
handlers += constructor handlers += constructor
} }
fun useHandlersAtFirst(vararg constructor: Constructor<AnalysisHandler<I>>) {
handlers.addAll(0, constructor.toList())
}
fun useHandlers(constructors: List<Constructor<AnalysisHandler<I>>>) { fun useHandlers(constructors: List<Constructor<AnalysisHandler<I>>>) {
handlers += constructors handlers += constructors
} }
@@ -54,6 +54,10 @@ object FirDiagnosticsDirectives : SimpleDirectivesContainer() {
val SCOPE_DUMP by stringDirective( val SCOPE_DUMP by stringDirective(
description = """ description = """
Dump hierarchies of overrides of classes listed in arguments Dump hierarchies of overrides of classes listed in arguments
Syntax: SCOPE_DUMP: some.package.ClassName:foo;bar, some.package.OtherClass
^^^ ^^^
members foo and bar from ClassName |
all members from OtherClass
Enables ${FirScopeDumpHandler::class} Enables ${FirScopeDumpHandler::class}
""".trimIndent() """.trimIndent()
) )
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.render import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -40,16 +40,39 @@ class FirScopeDumpHandler(testServices: TestServices) : FirAnalysisHandler(testS
get() = listOf(FirDiagnosticsDirectives) get() = listOf(FirDiagnosticsDirectives)
override fun processModule(module: TestModule, info: FirOutputArtifact) { override fun processModule(module: TestModule, info: FirOutputArtifact) {
val fqNames = module.directives[FirDiagnosticsDirectives.SCOPE_DUMP] val fqNamesWithNames = module.directives[FirDiagnosticsDirectives.SCOPE_DUMP]
if (fqNames.isEmpty()) return if (fqNamesWithNames.isEmpty()) return
val printer = SmartPrinter(dumper.builderForModule(module), indent = " ") val printer = SmartPrinter(dumper.builderForModule(module), indent = " ")
for (fqName in fqNames) { for (fqNameWithNames in fqNamesWithNames) {
printer.processClass(fqName, info.session, info.firAnalyzerFacade.scopeSession, module) val (fqName, names) = extractFqNameAndMemberNames(fqNameWithNames)
printer.processClass(fqName, names, info.session, info.firAnalyzerFacade.scopeSession, module)
} }
} }
private fun SmartPrinter.processClass(fqName: String, session: FirSession, scopeSession: ScopeSession, module: TestModule) { private fun extractFqNameAndMemberNames(fqNameWithNames: String): Pair<String, List<String>> {
val classId = ClassId.topLevel(FqName.fromSegments(fqName.split("."))) val (fqName, namesString) = fqNameWithNames.split(":").takeIf { it.size > 1 } ?: return fqNameWithNames to emptyList()
return fqName to namesString.split(";")
}
private fun SmartPrinter.processClass(
fqName: String,
namesFromDirective: List<String>,
session: FirSession,
scopeSession: ScopeSession,
module: TestModule
) {
val (packageFqName, className) = fqName.split(".").let {
val packageName = FqName.fromSegments(it.dropLast(1))
packageName to it.last()
}
val classId = className.let {
val names = it.split("$")
var classId = ClassId(packageFqName, Name.identifier(names.first()))
for (name in names.drop(1)) {
classId = classId.createNestedClassId(Name.identifier(name))
}
classId
}
val symbol = session.symbolProvider.getClassLikeSymbolByClassId(classId) ?: assertions.fail { val symbol = session.symbolProvider.getClassLikeSymbolByClassId(classId) ?: assertions.fail {
"Class $fqName not found in module ${module.name}" "Class $fqName not found in module ${module.name}"
} }
@@ -57,7 +80,7 @@ class FirScopeDumpHandler(testServices: TestServices) : FirAnalysisHandler(testS
println("$fqName: ") println("$fqName: ")
val scope = firClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) val scope = firClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
val names = scope.getCallableNames() val names = namesFromDirective.takeIf { it.isNotEmpty() }?.map { Name.identifier(it) } ?: scope.getCallableNames()
withIndent { withIndent {
for (name in names) { for (name in names) {
processFunctions(name, scope) processFunctions(name, scope)
@@ -80,15 +103,14 @@ class FirScopeDumpHandler(testServices: TestServices) : FirAnalysisHandler(testS
val functions = scope.getFunctions(name) val functions = scope.getFunctions(name)
for (function in functions) { for (function in functions) {
processFunction(function, scope, SymbolCounter()) processFunction(function, scope, SymbolCounter())
println()
} }
} }
private fun SmartPrinter.processFunction(symbol: FirNamedFunctionSymbol, scope: FirTypeScope, counter: SymbolCounter) { private fun SmartPrinter.processFunction(symbol: FirNamedFunctionSymbol, scope: FirTypeScope, counter: SymbolCounter) {
printInfo(symbol.fir, counter) printInfo(symbol.fir, scope, counter)
scope.processDirectOverriddenFunctionsWithBaseScope(symbol) { overriden, baseScope -> scope.processDirectOverriddenFunctionsWithBaseScope(symbol) { overridden, baseScope ->
withIndent { withIndent {
processFunction(overriden, baseScope, counter) processFunction(overridden, baseScope, counter)
} }
ProcessorAction.NEXT ProcessorAction.NEXT
} }
@@ -97,14 +119,13 @@ class FirScopeDumpHandler(testServices: TestServices) : FirAnalysisHandler(testS
private fun SmartPrinter.processProperties(name: Name, scope: FirTypeScope) { private fun SmartPrinter.processProperties(name: Name, scope: FirTypeScope) {
val properties = scope.getProperties(name) val properties = scope.getProperties(name)
for (property in properties) { for (property in properties) {
if (property !is FirPropertySymbol) continue
processProperty(property, scope, SymbolCounter()) processProperty(property, scope, SymbolCounter())
println()
} }
} }
private fun SmartPrinter.processProperty(symbol: FirPropertySymbol, scope: FirTypeScope, counter: SymbolCounter) { private fun SmartPrinter.processProperty(symbol: FirVariableSymbol<*>, scope: FirTypeScope, counter: SymbolCounter) {
printInfo(symbol.fir, counter) printInfo(symbol.fir, scope, counter)
if (symbol !is FirPropertySymbol) return
withIndent { withIndent {
scope.processDirectOverriddenPropertiesWithBaseScope(symbol) { overriden, baseScope -> scope.processDirectOverriddenPropertiesWithBaseScope(symbol) { overriden, baseScope ->
processProperty(overriden, baseScope, counter) processProperty(overriden, baseScope, counter)
@@ -113,10 +134,10 @@ class FirScopeDumpHandler(testServices: TestServices) : FirAnalysisHandler(testS
} }
} }
private fun SmartPrinter.printInfo(declaration: FirCallableDeclaration, counter: SymbolCounter) { private fun SmartPrinter.printInfo(declaration: FirCallableDeclaration, scope: FirTypeScope, counter: SymbolCounter) {
print("[${declaration.origin}]: ") print("[${declaration.origin}]: ")
print(declaration.render(FirRenderer.RenderMode.NoBodies).trim()) print(declaration.render(FirRenderer.RenderMode.NoBodies).trim())
print(" from ${declaration.dispatchReceiverType?.render()}") print(" from $scope")
println(" [id: ${counter.getIndex(declaration.symbol)}]") println(" [id: ${counter.getIndex(declaration.symbol)}]")
} }
@@ -82,6 +82,7 @@ fun TestConfigurationBuilder.baseFirDiagnosticTestConfiguration(
::FirCfgDumpHandler, ::FirCfgDumpHandler,
::FirCfgConsistencyHandler, ::FirCfgConsistencyHandler,
::FirNoImplicitTypesHandler, ::FirNoImplicitTypesHandler,
::FirScopeDumpHandler,
) )
} }
@@ -52,7 +52,7 @@ open class AbstractFirBlackBoxCodegenTest : AbstractJvmBlackBoxCodegenTestBase<F
} }
configureFirHandlersStep { configureFirHandlersStep {
useHandlers( useHandlersAtFirst(
::FirDumpHandler, ::FirDumpHandler,
::FirScopeDumpHandler, ::FirScopeDumpHandler,
::FirCfgDumpHandler, ::FirCfgDumpHandler,