All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.backend.common.phaser.DumperVerifier.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2019 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.backend.common.phaser

import org.jetbrains.kotlin.backend.common.CheckDeclarationParentsVisitor
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.IrValidator
import org.jetbrains.kotlin.backend.common.IrValidatorConfig
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
import java.io.File

private val IrElement.elementName: String
    get() = when (this) {
        is IrModuleFragment ->
            this.name.asString()

        is IrFile ->
            this.name

        else ->
            this.toString()
    }

private fun ActionState.isDumpNeeded() =
    phase in when (beforeOrAfter) {
        BeforeOrAfter.BEFORE -> config.toDumpStateBefore
        BeforeOrAfter.AFTER -> config.toDumpStateAfter
    }

private fun ActionState.isValidationNeeded() =
    phase in when (beforeOrAfter) {
        BeforeOrAfter.BEFORE -> config.toValidateStateBefore
        BeforeOrAfter.AFTER -> config.toValidateStateAfter
    }

fun  makeDumpAction(dumper: Action): Action =
    { phaseState, data, context ->
        if (phaseState.isDumpNeeded())
            dumper(phaseState, data, context)
    }

fun  makeVerifyAction(verifier: (Context, Data) -> Unit): Action =
    { phaseState, data, context ->
        if (phaseState.isValidationNeeded())
            verifier(context, data)
    }

fun dumpIrElement(actionState: ActionState, data: IrElement, @Suppress("UNUSED_PARAMETER") context: Any?): String {
    val beforeOrAfterStr = actionState.beforeOrAfter.name.toLowerCaseAsciiOnly()

    var dumpText: String = ""
    val elementName: String

    val dumpOnlyFqName = actionState.config.dumpOnlyFqName
    if (dumpOnlyFqName != null) {
        elementName = dumpOnlyFqName
        data.acceptVoid(object : IrElementVisitorVoid {
            override fun visitElement(element: IrElement) {
                element.acceptChildrenVoid(this)
            }

            override fun visitDeclaration(declaration: IrDeclarationBase) {
                if (declaration is IrDeclarationWithName && FqName(dumpOnlyFqName) == declaration.fqNameWhenAvailable) {
                    dumpText += declaration.dump()
                } else {
                    super.visitDeclaration(declaration)
                }
            }
        })
    } else {
        elementName = data.elementName
        dumpText = data.dump()
    }

    val title = "-- IR for $elementName $beforeOrAfterStr ${actionState.phase.description}\n"
    return title + dumpText
}

typealias Dumper = (ActionState, Data, Context) -> String?

fun  dumpToFile(
    fileExtension: String,
    dumper: Dumper
): Action =
    fun(actionState: ActionState, data: Data, context: Context) {
        val directoryPath = actionState.config.dumpToDirectory ?: return
        val dumpContent = dumper(actionState, data, context) ?: return

        val directoryFile = File(directoryPath)
        if (!directoryFile.isDirectory)
            if (!directoryFile.mkdirs())
                error("Can't create directory for IR dumps at $directoryPath")

        // Make dump files in a directory sorted by ID
        val phaseIdFormatted = "%02d".format(actionState.phaseCount)

        val fileName = "${phaseIdFormatted}_${actionState.phase.name}.$fileExtension"

        File(directoryFile, fileName).writeText(dumpContent)
    }

fun  dumpToStdout(
    dumper: Dumper
): Action =
    fun(actionState: ActionState, data: Data, context: Context) {
        if (actionState.config.dumpToDirectory != null) return
        val dumpContent = dumper(actionState, data, context) ?: return
        println("\n\n----------------------------------------------")
        println(dumpContent)
        println()
    }

val defaultDumper = makeDumpAction(dumpToStdout(::dumpIrElement) + dumpToFile("ir", ::dumpIrElement))

fun  validationCallback(context: CommonBackendContext, fragment: Fragment, checkProperties: Boolean = false) {
    val validatorConfig = IrValidatorConfig(
        abortOnError = true,
        ensureAllNodesAreDifferent = true,
        checkTypes = false,
        checkDescriptors = false,
        checkProperties = checkProperties,
    )
    fragment.accept(IrValidator(context, validatorConfig), null)
    fragment.accept(CheckDeclarationParentsVisitor, null)
}

val validationAction = makeVerifyAction(::validationCallback)




© 2015 - 2025 Weber Informatics LLC | Privacy Policy